惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
L
LangChain Blog
IT之家
IT之家
S
SegmentFault 最新的问题
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
The Blog of Author Tim Ferriss
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
U
Unit 42
B
Blog RSS Feed
GbyAI
GbyAI
Microsoft Security Blog
Microsoft Security Blog
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
T
Threatpost
C
CERT Recently Published Vulnerability Notes
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
Vercel News
Vercel News
S
Schneier on Security
Spread Privacy
Spread Privacy
C
Cyber Attacks, Cyber Crime and Cyber Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 叶小钗
雷峰网
雷峰网
博客园_首页
人人都是产品经理
人人都是产品经理
P
Palo Alto Networks Blog
The Hacker News
The Hacker News
T
Tor Project blog
L
Lohrmann on Cybersecurity
Know Your Adversary
Know Your Adversary
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy International News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
V
Vulnerabilities – Threatpost
大猫的无限游戏
大猫的无限游戏
博客园 - 【当耐特】
V
V2EX
Security Latest
Security Latest
A
About on SuperTechFans
Cloudbric
Cloudbric
S
Security Affairs
MongoDB | Blog
MongoDB | Blog
Y
Y Combinator Blog
Martin Fowler
Martin Fowler
TaoSecurity Blog
TaoSecurity Blog

BlogFinder

日常漫步 Vol.24 之漫步前山河 - 雅余 周报 #1-聊聊本周的收获 - Edwin's Blog 我的OpenCode必装插件与Skill Write Something 掌中之物未必在掌握之中 · CRIVU PiliNara,一个更顺手的 PiliPlus 分支 「NekoEcho」:做一个必有回响的猫娘主题博客 2026-05 书影音总结 简化博客主题 - 安迪 你要加油呐 我第一次发布 npm 包 拾花小记#45:中考前的二三事 – 小改学习志 黛西花园5月游 #18 枇杷又熟了的五月月报 一些奇奇怪怪的需求?word仿方正书版的几个小操作 - Xiobb's Blog 0419 御温泉之旅 修复了一些bug,网站基本上趋于稳定了 - 新锐博客 又回到四十年前 如何定义成功 迷鹿屋2026已重新上线 科技冰火两重天+一周回顾 ${title} 热度退了,我反而用得更深了-咕咚同学 我到底该不该换个域名? 随身WIFI折腾记 - 安迪 博客撰写体验提升——hexo pro插件 为什么不用相机把屏幕上的接关密码拍下来? 国清寺与天台山 – Ouroboros ★★★★☆《挽救计划》——久违的经济上行感 - Davidの3号基地 删除右键“打开方式”里多余选项 第三周刊_No.53|一切都会被支付两次 安卓APP通话记录与录音上传踩坑记录 - 子舒的博客 天量下跌 inBox 笔记 2.3.8,把工具栏交给了你-咕咚同学 我把小龙虾搬到了微信-咕咚同学 安好 - 响石潭 Compound Engineering Plugin:让每个工程单元都比上一个更容易 MOSS-TTS Family:开源高质量语音与声音生成模型家族深度解析 Crawl4AI:专为 LLM 设计的开源 Web 爬虫与数据抓取工具 Build Your Own X:从零实现你最喜欢的技术——程序员进阶的终极资源清单 Anthropic Skills:用文件夹教 Claude 专业技能的开源框架 1年的去月球(下) - 梅之夏 欢迎回来。 简单讲讲 ASN.1 与 OID DTV - 直播聚合客户端 5.22-5.27 – 不兴江 还没去过鸭川 – 不兴江 张晶晶同学三刷林志颖 关于我 – 不兴江 爱与嫉妒 – 不兴江 港股被持续做空 备案码花了四百块-咕咚同学 一句话生成封面:我给公众号做了4种风格的AI封面生成技能 「官」方認證 再谈费曼学习法 2026-05-28T00:34:11+08:00 2026-05-28T00:28:45+08:00 离谱的英语学习指南:基于AI的英语进阶系统方法论 iii:零集成架构的后端统一运行时 Claude Code Harness:让 Claude Code 工作有迹可循的工程化框架 Heretic:全自动移除大语言模型审查机制的开源工具 MarkItDown:微软开源的万能文档转 Markdown 利器 Harness:让 Claude Code 秒变多智能体协作工厂 这段时间尽折腾AI Agent了,确实极大地提高了效率 近期动态:两个新站点正式上线啦 误判解除!zhouayuan.com 腾讯安全申诉成功 - 周阿源|玩具设计・插画日常・生活随笔 Ralph:让 AI 编码工具自主循环跑完所有 PRD 任务的量产神器 全都违法 – 个人工作记录 关于zhouayuan.com被误判 “含违规信息” 的说明与申诉记录 - 周阿源|玩具设计・插画日常・生活随笔 小米 MiMo v2.5 Pro 白嫖 最大的人间清醒,兜里有钱,但是不花。 夜晚靓歌(12):于文文现场solo - 王志勇的Blog 今日插画:风扬起的倔强 - 周阿源|玩具设计・插画日常・生活随笔 回门习俗 独立网卡 - 忘记了回忆 500亿入股人工智能企业 从命令行到桌面智能体-咕咚同学 第一性原理读书笔记 行者微评论223-加班の守株待兔-博客|政治与时事-风雨行者 ZOZO开源物理接触求解器:GPU加速的可扩展仿真引擎 OpenStock:开源股票市场交易平台技术深度解析 MoneyPrinterTurbo:基于AI的全自动短视频生成工具深度解析 Claude-Mem:为 Claude Code 构建的持久化记忆压缩系统 Twenty:可代码化定制的企业级开源 CRM 平台技术深度解析 2026-05-26T22:59:17+08:00 企业级开源大模型部署平台 GPUStack 实战教程 1年的去月球(上) - 梅之夏 Sevalla - 静态网站托管服务 不用翻墙、不用注册、不用月费,普通人也能用上 Claude Code 装修灯具要注意⚠️ 黄梅天先锋 - 游子微博 公安备案顺利办结,站点备案全部完成 - 周阿源|玩具设计・插画日常・生活随笔 第三次兑换天猫超市卡了宗宗酱-三维狐少儿编程 Don't think, feel. - Rolen's Blog 人这一辈子,到底图个什么 博客迁移 - Edwin's Blog 情感赛道写作模板 再现本轮行情的典型特征 裁员与平常心-咕咚同学 别让“偷懒”,成为隐私泄露的破绽
Grafana 单点登录对接 Gitea 配置教程
Lcry · 2026-06-01 · via BlogFinder

Grafana 是一个用于监控展示的面板,由于项目越来越多,部署的开发测试预发布环境比较多,为了统一收集日志打算给研发和测试上一个统一查看查看日志,现目前是看日志都是统一找运维实时查看,为了满足开发在部分环境必须要看日志更加方便的排查问题,在现司也搞了基于 Loki 的日志采集日志实现。感兴趣的同学可以看我这篇文章《轻量级日志管理平台Grafana Loki搭建及应用》。

今天不介绍 loki,只说遇到的问题就是单点登录集成的问题,现司代码托管用的 Gitea 而不是 gitlab,Grafana 后台是支持基于 OAuth 协议的单点认证,支持 github、gitlab、google、通用 oauth 协议,LDAP等等如下图:

Grafana 单点登录对接 Gitea 配置教程

而 Gitea 是提供了类似于 github 的 oauth 协议的,理论上简单配置就行了,官方文档见:https://docs.gitea.com/development/oauth2-provider?_highlight=oauth#endpoints

EndpointURL
OpenID Connect Discovery/.well-known/openid-configuration
Authorization Endpoint/login/oauth/authorize
Access Token Endpoint/login/oauth/access_token
Token Introspection Endpoint/login/oauth/introspect
OpenID Connect UserInfo/login/oauth/userinfo
JSON Web Key Set/login/oauth/keys

我们首先到 Gitea 创建一个应用。

依次点击右上角设置-应用-创建新的Oauth2应用程序:应用名称随便取,回调地址写你的Grafana访问地址+/login/generic_oauth

例如:http://192.168.xxx.xxx/login/generic_oauth

Grafana 单点登录对接 Gitea 配置教程

然后管理员身份账号登录Grafana依次点击配置:左侧边栏-管理-身份验证-Generic OAuth

  • 显示名称:随便输,比如我是 Gitea公司代码私服
  • Client ID:Gitea创建应用后自动生成的
  • Client secret:Gitea创建应用后自动生成的
  • 身份验证样式:默认AutoDetect 即可
  • Scopes:user:email read:org
  • Auth URL:http://你的gitea访问地址/login/oauth/authorize
  • Token URL:http://你的gitea访问地址/login/oauth/access_token
  • API URL:http://你的gitea访问地址/login/oauth/userinfo
  • 允许注册:打勾,意思是如果单点过来账号不存在则默认进行创建,就只用维护 Gitea 那边账号即可

用户映射:以为 Gitea 比较特殊用户信息的字段有不一样的,为了做到对应上按照如下配置,未说明的保持为空即可。

  • 名称属性路径:默认为空,填写name
  • 登录属性路径:默认为空,填写preferred_username
  • 电子邮箱属性路径:默认为空,填写email

然后点击保存并启用,退出到登录页后下面就有一个Sign in with Gitea公司代码私服按钮,直接点击跳转到 Gitea 授权,首次授权点击信任。

避坑

我按照这样配置了之后以为就能正常登录,结果失败,会提示Login failed,User sync failed,多次尝试之后无果,然后开了Grafana 的 debug 日志模式排查问题。

grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.631683615Z level=debug msg="Extracting user info from OAuth access token"
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.631909726Z level=debug msg="Parsed user info from JSON" raw_json="{\"gnt\":16,\"tt\":0,\"exp\":1780309537,\"iat\":1780305937}" data="Name: , Displayname: , Login: , Username: , Email: , Upn: , Attributes: map[]" source=access_token
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.631928855Z level=debug msg="Processing external user info" source=API data="Name: lcry, Displayname: , Login: , Username: , Email: i@51it.wang, Upn: , Attributes: map[]"
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.6320387Z level=debug msg="Setting user info name from nameAttributePath" nameAttributePath=name
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.632052173Z level=debug msg="Searching for login among JSON" loginAttributePath=preferred_username
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.632122502Z level=debug msg="Set user info email from extracted email" email=i@51it.wang
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.632134798Z level=debug msg="Processing external user info" source=access_token data="Name: , Displayname: , Login: , Username: , Email: , Upn: , Attributes: map[]"
grafana-1  | logger=oauth.generic_oauth t=2026-06-01T09:29:50.632152172Z level=debug msg="User info result" result="Id: 33, Name: lcry, Email: i@51it.wang, Login: xxxx, Role: , Groups: [], OrgRoles: map[]"
grafana-1  | logger=user.sync t=2026-06-01T09:29:50.635047023Z level=error msg="Failed to create user" error="user not found" auth_module=oauth_generic_oauth auth_id=33
grafana-1  | logger=authn.service t=2026-06-01T09:29:50.635122956Z level=error msg="Failed to run post auth hook" client=auth.client.generic_oauth id= error="[user.sync.internal] unable to create user: user not found"
grafana-1  | logger=context userId=0 orgId=0 uname= t=2026-06-01T09:29:50.644763065Z level=info msg="Request Completed" method=GET path=/login/generic_oauth status=302

从日志上看用户信息获取正确,最终解析出用户数据进行创建账号的时候失败了,然后 AI 给了思路说再直接强制从环境变量中重写允许注册的信息。不知道是什么原因,按照下面设置相关环境变量,你可以直接改 /etc/grafana/grafana.ini 配置文件,我是使用的 docker-compose 部署所以直接在环境变量里添加更快,两种方式均可。

    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=false
      - GF_SECURITY_ADMIN_USER=lcry
      - GF_SECURITY_ADMIN_PASSWORD=www.51it.wang博客出品
      - GF_SERVER_ROOT_URL=http://xx.xx.xxx.xx:3000
      # 下面这2行重要
      - GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=true
      - GF_AUTH_OAUTH_ALLOW_INSECURE_EMAIL_LOOKUP=true
      - GF_LOG_LEVEL=debug

然后重启grafana容器再次尝试直接单点登录成功。

即便用户不存在再首次授权登录后会进行自动创建,后面Gitea信息变更会做更新操作,这样就只用维护开发者在Gitea的账号即可完成多平台认证。

Grafana 单点登录对接 Gitea 配置教程

最后分享一个配置简单的用于标签分组查询日志的仪表盘,可以通过项目打标的项目标签以及关键字进行筛选日志,效果如下:

Grafana 单点登录对接 Gitea 配置教程

面板配置 json:

{
  "apiVersion": "dashboard.grafana.app/v2",
  "kind": "Dashboard",
  "metadata": {
    "name": "ae3ec2c4-1c19-4450-9403-226270fe0c4f",
    "namespace": "default",
    "uid": "459530de-6d8f-436c-af98-2a965efdd55b",
    "resourceVersion": "1780299277848985",
    "generation": 15,
    "creationTimestamp": "2026-06-01T07:12:50Z",
    "labels": {
      "grafana.app/deprecatedInternalID": "3200181491736576"
    },
    "annotations": {
      "grafana.app/createdBy": "anonymous:0",
      "grafana.app/folder": "",
      "grafana.app/message": "123123",
      "grafana.app/saved-from-ui": "Grafana v13.0.1+security-01 (9bbe672d)",
      "grafana.app/updatedBy": "anonymous:0",
      "grafana.app/updatedTimestamp": "2026-06-01T07:34:37Z"
    }
  },
  "spec": {
    "annotations": [
      {
        "kind": "AnnotationQuery",
        "spec": {
          "query": {
            "kind": "DataQuery",
            "group": "grafana",
            "version": "v0",
            "datasource": {
              "name": "-- Grafana --"
            },
            "spec": {}
          },
          "enable": true,
          "hide": true,
          "iconColor": "rgba(0, 211, 255, 1)",
          "name": "Annotations & Alerts",
          "builtIn": true
        }
      }
    ],
    "cursorSync": "Off",
    "editable": true,
    "elements": {
      "panel-2": {
        "kind": "Panel",
        "spec": {
          "id": 2,
          "title": "",
          "description": "",
          "links": [],
          "data": {
            "kind": "QueryGroup",
            "spec": {
              "queries": [
                {
                  "kind": "PanelQuery",
                  "spec": {
                    "query": {
                      "kind": "DataQuery",
                      "group": "loki",
                      "version": "v0",
                      "datasource": {
                        "name": "P8E80F9AEF21F6940"
                      },
                      "spec": {
                        "direction": "backward",
                        "editorMode": "code",
                        "expr": "sum(count_over_time({project=~\"$project\"} |~ \"$search\"[$__interval]))",
                        "queryType": "range"
                      }
                    },
                    "refId": "A",
                    "hidden": false
                  }
                }
              ],
              "transformations": [],
              "queryOptions": {}
            }
          },
          "vizConfig": {
            "kind": "VizConfig",
            "group": "timeseries",
            "version": "13.0.1+security-01",
            "spec": {
              "options": {
                "annotations": {
                  "clustering": -1,
                  "multiLane": false
                },
                "legend": {
                  "calcs": [],
                  "displayMode": "list",
                  "placement": "bottom",
                  "showLegend": true
                },
                "tooltip": {
                  "hideZeros": false,
                  "mode": "single",
                  "sort": "none"
                }
              },
              "fieldConfig": {
                "defaults": {
                  "thresholds": {
                    "mode": "absolute",
                    "steps": [
                      {
                        "value": 0,
                        "color": "green"
                      }
                    ]
                  },
                  "color": {
                    "mode": "palette-classic"
                  },
                  "custom": {
                    "axisBorderShow": false,
                    "axisCenteredZero": false,
                    "axisColorMode": "text",
                    "axisLabel": "",
                    "axisPlacement": "auto",
                    "barAlignment": 0,
                    "barWidthFactor": 0.6,
                    "drawStyle": "line",
                    "fillOpacity": 0,
                    "gradientMode": "none",
                    "hideFrom": {
                      "legend": false,
                      "tooltip": false,
                      "viz": false
                    },
                    "insertNulls": false,
                    "lineInterpolation": "linear",
                    "lineWidth": 1,
                    "pointSize": 5,
                    "scaleDistribution": {
                      "type": "linear"
                    },
                    "showPoints": "auto",
                    "showValues": false,
                    "spanNulls": false,
                    "stacking": {
                      "group": "A",
                      "mode": "none"
                    },
                    "thresholdsStyle": {
                      "mode": "off"
                    }
                  }
                },
                "overrides": []
              }
            }
          }
        }
      },
      "panel-3": {
        "kind": "Panel",
        "spec": {
          "id": 3,
          "title": "日志列表",
          "description": "",
          "links": [],
          "data": {
            "kind": "QueryGroup",
            "spec": {
              "queries": [
                {
                  "kind": "PanelQuery",
                  "spec": {
                    "query": {
                      "kind": "DataQuery",
                      "group": "loki",
                      "version": "v0",
                      "datasource": {
                        "name": "P8E80F9AEF21F6940"
                      },
                      "spec": {
                        "direction": "forward",
                        "editorMode": "code",
                        "expr": "{project=~\"$project\"} |= \"$search\"",
                        "queryType": "range"
                      }
                    },
                    "refId": "A",
                    "hidden": false
                  }
                }
              ],
              "transformations": [],
              "queryOptions": {}
            }
          },
          "vizConfig": {
            "kind": "VizConfig",
            "group": "logs",
            "version": "13.0.1+security-01",
            "spec": {
              "options": {
                "dedupStrategy": "exact",
                "detailsMode": "sidebar",
                "displayedFields": [],
                "enableInfiniteScrolling": true,
                "enableLogDetails": true,
                "fontSize": "small",
                "prettifyLogMessage": false,
                "showCommonLabels": false,
                "showControls": true,
                "showFieldSelector": false,
                "showLabels": true,
                "showLevel": true,
                "showTime": false,
                "sortOrder": "Ascending",
                "timestampResolution": "ms",
                "unwrappedColumns": false,
                "wrapLogMessage": false
              },
              "fieldConfig": {
                "defaults": {},
                "overrides": []
              }
            }
          },
          "transparent": true
        }
      }
    },
    "layout": {
      "kind": "GridLayout",
      "spec": {
        "items": [
          {
            "kind": "GridLayoutItem",
            "spec": {
              "x": 0,
              "y": 0,
              "width": 24,
              "height": 5,
              "element": {
                "kind": "ElementReference",
                "name": "panel-2"
              }
            }
          },
          {
            "kind": "GridLayoutItem",
            "spec": {
              "x": 0,
              "y": 5,
              "width": 24,
              "height": 16,
              "element": {
                "kind": "ElementReference",
                "name": "panel-3"
              }
            }
          }
        ]
      }
    },
    "links": [],
    "liveNow": true,
    "preload": false,
    "tags": [],
    "timeSettings": {
      "timezone": "browser",
      "from": "now-5m",
      "to": "now",
      "autoRefresh": "10s",
      "autoRefreshIntervals": [
        "5s",
        "10s",
        "30s",
        "1m",
        "5m",
        "15m",
        "30m",
        "1h",
        "2h",
        "1d"
      ],
      "hideTimepicker": false,
      "fiscalYearStartMonth": 0
    },
    "title": "研发日志查询面板",
    "variables": [
      {
        "kind": "QueryVariable",
        "spec": {
          "name": "project",
          "current": {
            "text": "xxxxx-dev",
            "value": "xxxxx-dev"
          },
          "label": "项目",
          "hide": "dontHide",
          "refresh": "onDashboardLoad",
          "skipUrlSync": false,
          "query": {
            "kind": "DataQuery",
            "group": "loki",
            "version": "v0",
            "datasource": {
              "name": "P8E80F9AEF21F6940"
            },
            "spec": {
              "label": "project",
              "refId": "LokiVariableQueryEditor-VariableQuery",
              "stream": "",
              "type": 1
            }
          },
          "regex": "",
          "regexApplyTo": "value",
          "sort": "alphabeticalAsc",
          "definition": "",
          "options": [],
          "multi": false,
          "includeAll": false,
          "allValue": ".+",
          "allowCustomValue": true
        }
      },
      {
        "kind": "QueryVariable",
        "spec": {
          "name": "search",
          "current": {
            "text": "",
            "value": ""
          },
          "label": "关键字",
          "hide": "dontHide",
          "refresh": "onDashboardLoad",
          "skipUrlSync": false,
          "description": "这里可以通过关键字搜索",
          "query": {
            "kind": "DataQuery",
            "group": "loki",
            "version": "v0",
            "datasource": {
              "name": "P8E80F9AEF21F6940"
            },
            "spec": {}
          },
          "regex": "",
          "regexApplyTo": "text",
          "sort": "disabled",
          "definition": "",
          "options": [],
          "multi": false,
          "includeAll": false,
          "allowCustomValue": true
        }
      }
    ]
  }
}

对了,最后补充一点,针对于 loki 最新版官方改了架构,和早期文章采集docker 容器日志有更加方便的方式,直接部署一个 Alloy 采集组件,然后自动监听 docker 进程实时抓取即可。官方参考链接:https://grafana.com/docs/loki/latest/get-started/quick-start/quick-start/