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_KEY | JWT 加密密钥 | ops-portal-dev-secret-change-me-32b! |
| OPS_DATABASE_URL | 数据库连接字符串 | sqlite:///instance/ops_portal.db |
| OPS_JWT_EXPIRE_HOURS | JWT 过期时间(小时) | 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 个链接录进去,团队很快就能感受到差别。




