OPS 资源中心教程:运维命令与文档统一管理门户

OPS 资源中心是一个内部资源管理门户,专门解决运维团队的一个老问题:常用命令、文档、链接和文件散落在每个人的收藏夹、聊天记录和备忘录里,新人来了找不到,老员工走了就丢了。它把这些东西集中到一个门户里,支持全局搜索、分类筛选、一键复制命令,后面再配一个管理后台做分类、资源、文件、用户和站点设置。

一、项目简介

OPS 资源中心分两部分:门户展示(给所有人用的前台)和管理后台(给管理员维护内容)。前台是响应式设计,支持按 / 快捷键唤起全局搜索,按分类多维度筛选,资源以卡片形式展示,命令类资源支持一键复制;后台提供数据仪表盘、分类管理、资源管理、文件上传、侧栏链接管理、站点设置和用户管理。

  • 后端:Flask + Flask-SQLAlchemy + SQLite + JWT 认证 + bcrypt 密码加密
  • 前端:Vue 3 + Element Plus + Vite + Axios
  • 默认端口:后端 8090
  • 默认账号:admin / admin123(首次登录后必须立即修改)
  • 开源协议:MIT License

二、功能特性

门户展示侧的能力围绕“找得到、拿得到”:全局搜索支持按 / 快捷键唤起,分类可以多维度筛选,资源卡片一键复制命令,右侧还有快捷链接栏放常用入口。管理后台侧的能力围绕“管得住”:仪表盘看数据概况,分类支持排序和分面选项,资源支持命令、链接、文档、文件四种类型,文件可以上传,侧栏链接、站点标题、副标题、公告都能在后台改,用户可以创建、重置密码和删除。

模块功能说明
门户展示全局搜索按 / 快捷键唤起,跨资源全文检索
门户展示分类筛选多维度分类筛选,快速定位资源
门户展示资源卡片命令一键复制,链接直接跳转
门户展示快捷链接栏右侧边栏放置常用入口
管理后台数据仪表盘资源数量、分类分布等概览
管理后台分类管理创建、排序、分面选项
管理后台资源管理命令 / 链接 / 文档 / 文件四种类型
管理后台文件上传上传文件类资源供下载
管理后台用户管理创建账号、重置密码、删除用户
管理后台站点设置标题、副标题、公告等

三、适用场景

  • 运维命令手册:把常用的巡检命令、排障命令、重启流程沉淀成命令类资源,新人照着复制执行,不用每次都问老员工。
  • 内部文档入口:把散落在各处的部署文档、应急手册、值班表收进文档类资源,统一入口、统一搜索。
  • 常用链接导航:监控面板、工单系统、云控制台、Git 仓库这些天天要点的链接放进快捷链接栏和链接类资源。
  • 文件分发:常用的安装包、脚本、证书、模板文件上传成文件类资源,团队内部直接下载,不用反复传网盘。
  • 新人入职引导:新人第一天打开门户,按分类就能找到入职要装的软件、要加的群、要读的文档、要跑的命令。

不适用场景:它不是 Wiki(文档类资源是富文本说明,不是完整的知识库编辑器),不是网盘(文件上传是附件能力,不是海量存储),也不是 CMDB(没有资产自动发现和状态同步)。它的定位是“团队内部的资源导航站”,解决找得到的问题。

四、技术架构与项目结构

后端是 Flask 单体应用:app.py 是入口,config.py 管配置,models.py 定义数据模型,auth.py 处理认证,routes/ 下按门户公开 API、管理后台 API、认证 API 拆了三个路由模块。数据存在 SQLite,文件存在 backend/uploads/。前端是 Vue 3 + Vite 的单页应用,Portal.vue 是门户首页,admin/ 下是管理后台的多个页面。

ops-manager/
├── backend/                 # 后端服务
│   ├── app.py              # 应用入口
│   ├── config.py           # 配置文件
│   ├── models.py           # 数据模型
│   ├── auth.py             # 认证相关
│   ├── routes/             # API 路由
│   │   ├── portal.py       # 门户公开 API
│   │   ├── admin.py        # 管理后台 API
│   │   └── auth.py         # 认证 API
│   ├── instance/           # 数据库文件(自动创建)
│   ├── uploads/            # 上传文件目录(自动创建)
│   └── requirements.txt    # Python 依赖
└── frontend/               # 前端应用
    ├── src/
    │   ├── views/          # 页面组件
    │   │   ├── Portal.vue  # 门户首页
    │   │   └── admin/      # 管理后台页面
    │   ├── api/index.js    # API 封装
    │   ├── router/         # 路由配置
    │   └── styles/         # 样式文件
    ├── dist/               # 构建产物(自动创建)
    └── package.json

认证用 JWT:登录后前端拿 token,之后每次请求在 Authorization 头里带上。密码用 bcrypt 加密存储。SQLite 对于这种内部工具足够用,数据量小、备份就是复制一个文件;如果团队规模变大、并发写变多,再考虑迁到 PostgreSQL 或 MySQL。

五、安装部署

环境要求:Python 3.8+、Node.js 16+。后端和前端分开启动,开发模式下后端跑 8090 端口,前端用 Vite 开发服务器;生产环境前端先构建再由 Nginx 托管静态文件,后端用 Gunicorn 或 uWSGI 部署。

# 后端启动
cd backend

# 安装依赖
pip install -r requirements.txt

# 启动服务(开发模式)
python app.py
# 服务将在 http://localhost:8090 启动

# 前端启动(另开一个终端)
cd frontend

# 安装依赖
npm install

# 开发模式
npm run dev
# 按终端输出的地址访问(Vite 开发服务器地址见启动日志)

# 构建生产版本
npm run build
# 生产部署:Gunicorn 托管后端
pip install gunicorn
cd backend
gunicorn -w 4 -b 127.0.0.1:8090 app:app

# systemd 托管后端(示例)
cat > /etc/systemd/system/ops-portal.service << 'EOF'
[Unit]
Description=OPS Portal Backend
After=network.target

[Service]
Type=simple
User=ops
WorkingDirectory=/opt/ops-manage/backend
Environment="OPS_SECRET_KEY=请换成强随机字符串"
ExecStart=/opt/ops-manage/backend/venv/bin/gunicorn -w 4 -b 127.0.0.1:8090 app:app
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now ops-portal
# Nginx 反向代理:前端静态文件 + API
cat > /etc/nginx/conf.d/ops-portal.conf << 'EOF'
server {
    listen 80;
    server_name ops.example.local;

    location / {
        root /opt/ops-manage/frontend/dist;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8090;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /uploads/ {
        proxy_pass http://127.0.0.1:8090;
    }
}
EOF
nginx -t && systemctl reload nginx

默认账号是 admin / admin123,首次登录后第一件事就是改密码,然后到用户管理里给团队成员建账号。README 明确建议生产环境把 OPS_SECRET_KEY 换成强随机字符串,否则 JWT 容易被伪造。

六、配置详解

后端配置全部走环境变量,默认值适合开发,生产环境至少要改 OPS_SECRET_KEY。数据库默认是 SQLite 文件,上传目录默认在 backend/uploads。

变量名说明默认值
OPS_SECRET_KEYJWT 加密密钥ops-portal-dev-secret-change-me-32b!
OPS_DATABASE_URL数据库连接字符串sqlite:///instance/ops_portal.db
OPS_JWT_EXPIRE_HOURSJWT 过期时间(小时)12
OPS_UPLOAD_DIR文件上传目录backend/uploads
OPS_UPLOAD_URL_PREFIX文件访问 URL 前缀/uploads
# 生产环境配置示例(写进 systemd 的 Environment 或 .env 文件)
export OPS_SECRET_KEY="$(openssl rand -hex 32)"
export OPS_DATABASE_URL="sqlite:///instance/ops_portal.db"
export OPS_JWT_EXPIRE_HOURS="12"
export OPS_UPLOAD_DIR="/opt/ops-manage/backend/uploads"
export OPS_UPLOAD_URL_PREFIX="/uploads"

# 验证配置是否生效
curl -s http://localhost:8090/api/health 2>/dev/null || curl -s http://localhost:8090/ | head -5

关于 OPS_SECRET_KEY 多说一句:它的默认值 ops-portal-dev-secret-change-me-32b! 是公开写在 README 里的,任何人拿到这个值都能伪造任意用户的 JWT。生产部署时必须换成随机字符串,换完之后之前签发的 token 全部失效,所有用户需要重新登录。OPS_JWT_EXPIRE_HOURS 默认 12 小时,内网工具这个值比较合理;如果希望更安全可以调小到 4 小时,代价是用户每天要多登录几次。

七、资源模型:四种资源类型

平台的资源分四种类型,每种类型对应不同的展示和交互方式。建资源之前先想清楚它属于哪一类,选错了类型展示效果会打折扣。

  • 命令(command):可一键复制的 Shell 命令。比如巡检命令、日志查看命令、服务重启命令。门户上显示为代码卡片,点一下就复制到剪贴板。
  • 链接(link):内部或外部链接跳转。比如监控面板地址、工单系统、云控制台。点卡片直接在新标签页打开。
  • 文档(text):富文本说明文档。比如应急流程、部署步骤、值班说明。适合几百字以内的说明,太长的文档还是放 Wiki,门户里放链接。
  • 文件(file):可下载的文件资源。比如安装包、脚本、证书、模板。上传后生成下载链接,团队成员直接下载。
# 示例:登录后拿到 JWT(后续管理接口都要带这个 token)
curl -s -X POST http://localhost:8090/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"admin123"}' | python3 -m json.tool

# 示例:用 token 查看资源列表(具体路径以 routes 定义为准)
# curl -s http://localhost:8090/api/portal/resources \
#   -H "Authorization: Bearer <token>" | python3 -m json.tool

资源组织建议:分类按“用途”而不是按“技术”划分,比如“日常巡检”“应急处理”“新人入职”“常用链接”这种任务导向的分类,比“Linux”“MySQL”“网络”这种技术分类更好找。分类支持排序,把最常用的分类排前面;分面选项可以进一步按环境(生产 / 测试)或团队(运维 / 开发)过滤。

八、使用流程:门户与管理后台

日常使用分两种角色。普通成员打开门户首页,用搜索或分类筛选找资源:按 / 唤起搜索框,输入关键词(比如“磁盘”),匹配的命令、文档、链接都列出来;命令类资源点一下复制,粘贴到终端执行。右侧快捷链接栏放最常用的几个入口,不用每次都搜索。

管理员进管理后台维护内容:先建分类(比如日常巡检、应急处理、部署文档),再往分类里加资源。加命令类资源时,标题写清楚用途,正文贴完整命令,备注里写清楚执行前提(比如要在哪个用户下执行、会不会重启服务)。加文件类资源时上传文件并写好版本说明。站点设置里可以改门户标题、副标题和公告,公告适合放值班安排或临时通知。

# 示例:门户里常用的巡检命令(可作为命令类资源录入)
# 磁盘使用率 TOP 10
df -h | sort -k5 -hr | head -10
# 内存占用 TOP 10 进程
ps aux --sort=-%mem | head -10
# 最近一小时的错误日志
journalctl --since "1 hour ago" -p err --no-pager | head -50
# 检查服务状态
systemctl list-units --failed --no-pager

九、用户与权限管理

用户管理在管理后台的 Users 页面:创建账号、重置密码、删除用户。权限模型比较简单——能登录后台的就是管理员,普通成员只用门户浏览和复制,不需要账号。这个设计对内网小团队够用,但如果需要细粒度权限(比如只能看某个分类、只能管理某类资源),目前的版本不支持,需要二次开发。

  • 首次上线清单:改 admin 密码、换 OPS_SECRET_KEY、给管理员建独立账号、停用或删掉不需要的默认账号。
  • 密码策略:密码用 bcrypt 加密存储,重置密码走管理后台的重置功能,不要直接改数据库。
  • 账号回收:人员离职时及时在用户管理里删除账号,JWT 最长 12 小时过期,删除后最迟半天内失效。

十、自定义主题与二次开发

主题样式变量集中在 frontend/src/styles/portal.css 的 :root 块里,改几个变量就能换整站配色,不用逐个组件改样式。

/* frontend/src/styles/portal.css(节选) */
:root {
  --ink: #0a1424;        /* 主深色 */
  --cyan: #2dd9f0;       /* 主青色 */
  --red: #e5484d;        /* 主红色 */
  --paper: #f2f5f9;      /* 背景色 */
  /* ... */
}

添加新的资源类型需要改三处:后端 backend/models.py 里的 Resource 模型(如果需要新字段),后端 backend/routes/admin.py 里的 RESOURCE_TYPES 和验证逻辑,前端 Resources.vue 的展示样式和 Portal.vue 的 badge 样式。README 里明确列出了这个扩展路径,说明作者预留了扩展点。仓库里还有 backend/seed.py(README 未说明其用法,从文件名看是数据初始化脚本,使用前请先阅读文件内容确认它会写入哪些初始数据)。

十一、常见问题

  • 后端启动报数据库错误?确认 backend/instance/ 目录可写,SQLite 文件是自动创建的,权限不对会启动失败。也可以检查 OPS_DATABASE_URL 指向的路径是否存在。
  • 前端 npm run dev 打不开?先确认 Node.js 版本是否满足 16+,再看终端输出的实际地址(Vite 默认端口可能被占用,会自动换端口,以终端输出为准)。
  • 登录后接口报 401?先确认 token 是否过期(默认 12 小时),再确认请求头是否带了 Authorization: Bearer。换过 OPS_SECRET_KEY 后旧 token 全部失效,需要重新登录。
  • 上传的文件下载不了?检查 OPS_UPLOAD_DIR 目录权限和 Nginx 的 /uploads/ 代理配置是否正确,文件访问走的是 OPS_UPLOAD_URL_PREFIX 前缀。
  • 门户搜不到刚加的资源?确认资源已保存且分类正确,搜索是按标题和内容匹配的,关键词尽量用资源标题里的词。
  • 数据丢了怎么恢复?SQLite 数据库就是 backend/instance/ops_portal.db 一个文件,从备份复制回来即可,上传的文件在 backend/uploads/ 里也要一起恢复。

十二、运维建议

  • 备份:定期备份 SQLite 数据库文件(backend/instance/ops_portal.db)和上传目录(backend/uploads/),两个都要备,只备数据库不备文件,文件类资源的下载链接会断。
  • 安全:生产环境用 Gunicorn 或 uWSGI 部署后端,不要用 Flask 开发服务器;Nginx 反向代理前端和 API;OPS_SECRET_KEY 换成强随机字符串;默认密码立即修改;只允许内网访问,公网访问务必加认证和 HTTPS。
  • 内容治理:定期清理过期资源(比如已经下线的服务的命令、失效的链接),分类保持精简,资源标题写清楚用途,避免“新建命令 1”这种无意义标题。
  • 高可用:SQLite 单文件架构不适合多副本部署,内网单机部署即可;如果要求高可用,把数据库迁到 PostgreSQL/MySQL 并做主从,再配多实例 + 负载均衡。

总结:OPS 资源中心解决的是团队知识沉淀的“最后一公里”——命令、文档、链接、文件都有地方放,而且找得到。部署成本很低(一个 Flask 后端加一个 Vue 前端),收益却很实在:新人上手快、老人不用反复回答同样的问题、关键操作都有统一的入口。先跑起来,把最常用的 20 条命令和 10 个链接录进去,团队很快就能感受到差别。

发表回复

后才能评论