Files
LocalNav/部署与使用说明.md
T
2026-05-12 15:38:27 +08:00

451 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 本地导航站 · 部署与使用说明
本文档为 **中文说明****部署操作** 合一版本,适用于在局域网(Ubuntu / Windows 等)上自建使用,不涉及公网穿透、云服务器 Nginx 或 frp。
---
## 一、项目概述
**本地导航站**是一个基于 **Flask** 的轻量 Web 应用,用于把多台内网机器、多个带端口的本地服务(宝塔、AI 面板、路由管理页、各类后端控制台等)**收纳到同一个入口地址**。
- 浏览器打开一个网址即可进入。
- 左侧为 **自定义分组 + 服务链接列表**
- 右侧为 **大尺寸 iframe**:点击左侧链接时,在页面内嵌打开对应 `http://内网IP:端口/路径`,**不整页跳转、不新开标签**(体验类似统一后台)。
数据全部落在本机 **SQLite** 文件中,无需安装 MySQL,适合个人或小范围内网使用。
---
## 二、功能特性
| 模块 | 说明 |
|------|------|
| 账号登录 | 用户名 + 密码,会话由 Flask-Login 管理;表单带 CSRF 防护。 |
| 导航首页 | 左右分栏;左侧分组与服务;右侧 iframe 内嵌打开目标页。 |
| 分组管理 | 新增 / 编辑 / 删除分组;支持排序字段(数字越小越靠前)。 |
| 服务管理 | 新增 / 编辑 / 删除服务;字段:名称、内网主机、端口、路径、所属分组、排序。 |
| 数据库 | SQLite,默认文件名为 `nav_local.db`(与运行当前工作目录有关)。 |
| 网络监听 | 默认绑定 `0.0.0.0`,便于同局域网手机、电脑访问。 |
**说明**:服务访问地址由程序拼接为 `http://{host}:{port}{path}`,当前版本固定为 **HTTP**(内网场景)。若目标服务为 HTTPS,需在后续版本中扩展字段;嵌入 iframe 时浏览器仍按 HTTPS 规则校验混合内容等。
---
## 三、技术栈与运行要求
- **Python**:建议 **3.10+**(3.9 一般也可,未在全部小版本上逐一验证)。
- **主要依赖**Flask、Flask-SQLAlchemy、Flask-Login、Flask-WTF、WTForms、Werkzeug。
- **浏览器**:现代浏览器(Chrome / Edge / Firefox / Safari 等)。
---
## 四、目录结构(参考)
```
本地导航/
├── app.py # 应用入口、路由、启动参数
├── models.py # 数据模型(用户、分组、服务)
├── forms.py # 表单定义
├── requirements.txt # Python 依赖列表
├── .env.example # 环境变量模板(复制为 .env 后修改)
├── .env # 本地配置(自建,勿提交 Git)
├── ecosystem.config.cjs # PM2 守护进程配置
├── nav_local.db # SQLite 数据库(首次成功运行后生成,勿手误提交到公开仓库)
├── static/
│ └── style.css # 样式
└── templates/ # Jinja2 模板(登录、首页、后台页)
├── base.html
├── login.html
├── index.html
├── admin_groups.html
├── admin_group_form.html
├── admin_services.html
└── admin_service_form.html
```
---
## 五、环境变量与 `.env` 文件
程序启动时会从 **与 `app.py` 同目录**`.env` 文件加载变量(依赖 `python-dotenv`)。**若 `.env` 不存在则跳过,不影响启动。**
**优先级**:操作系统或进程里 **已经设置** 的环境变量 **优先**`.env` 中的键 **不会覆盖** 已有变量(与 `python-dotenv` 默认行为一致)。便于在 systemd 里写死 `NAV_SECRET_KEY`,本地开发仍用 `.env` 填其他项。
**初次使用:**
```bash
cp .env.example .env
# 编辑 .env,至少设置 NAV_SECRET_KEY(长期运行强烈建议)
```
`.env` 含敏感信息,已列入 `.gitignore`,请勿提交到公开仓库;仓库内仅保留 **`.env.example`** 作模板。
### 5.1 变量一览
| 变量名 | 含义 | 默认值 |
|--------|------|--------|
| `NAV_SECRET_KEY` | Flask 会话、CSRF 等加密签名密钥。**生产或长期运行务必设置固定值**,否则重启后会话失效且安全性下降。 | 未设置时每次进程启动随机生成 |
| `NAV_DATABASE_URL` | SQLAlchemy 数据库连接串 | `sqlite:///nav_local.db` |
| `NAV_HOST` | `python app.py` 时监听地址 | `0.0.0.0` |
| `NAV_PORT` | `python app.py` 时监听端口 | `5000` |
| `NAV_DEBUG` | 是否开启调试模式(**勿**在内网多人共用服务器上长期开启) | 未设置或不为 `1` 则为关闭;设为 `1` 开启 |
**生成密钥示例(Linux / macOS):**
```bash
export NAV_SECRET_KEY="$(openssl rand -hex 32)"
```
**Windows PowerShell 示例:**
```powershell
$env:NAV_SECRET_KEY = -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 48 | ForEach-Object {[char]$_})
```
---
## 六、安装与运行(通用)
### 6.1 获取代码
将项目目录放到目标机器上(拷贝、压缩包解压、或 Git 克隆均可)。下文以项目根目录为当前工作目录。
### 6.2 创建虚拟环境并安装依赖
**Linux / macOS**
```bash
cd /path/to/本地导航
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -r requirements.txt
```
**WindowsPowerShell):**
```powershell
cd C:\path\to\本地导航
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -U pip
pip install -r requirements.txt
```
**若 `pip install` 报错 “No matching distribution” 或版本列表为空**:多为镜像源未同步或网络策略问题,可显式指定官方索引:
```bash
pip install -r requirements.txt -i https://pypi.org/simple
```
### 6.3 直接启动(开发 / 小范围内网)
若已用 `.env` 配置 `NAV_SECRET_KEY` 等,可直接:
```bash
python app.py
```
否则可临时用环境变量(与 `.env` 二选一或混用,见上文优先级):
```bash
export NAV_SECRET_KEY="$(openssl rand -hex 32)" # Linux;长期部署也可写进 systemd 的 EnvironmentFile
python app.py
```
默认监听 **`http://0.0.0.0:5000`**。在同一局域网内的其他设备浏览器访问:
```text
http://<本机局域网IP>:5000
```
例如:`http://192.168.1.100:5000`
**注意**:内置的 `app.run()` 为 Flask 开发用服务器,**并发能力与健壮性有限**,适合个人使用或低并发内网场景。需要长期开机、略高并发时,建议使用下文 **Gunicorn** 方式。
---
## 七、首次登录与默认账号
1. 第一次成功启动且数据库中 **没有任何用户** 时,程序会自动创建:
- 用户:**`admin`**
- 密码:**`admin123`**
- 一个名为 **「默认分组」** 的空分组。
2. 控制台会打印一行提示(内容大意:默认账号仅内网使用,请尽快修改)。
**安全建议(强烈)**
- 首次登录后,尽快通过可靠方式修改密码。当前版本未内置「改密页」,可自行选用其一:
- 使用 [DB Browser for SQLite](https://sqlitebrowser.org/) 等工具打开 `nav_local.db`,删除 `users` 表中对应用户后,临时改代码跑一次初始化(不推荐反复操作);
- 或自行增加「修改密码」路由(二次开发)。
- **不要将**带默认口令的数据库文件提交到公开 Git 仓库。
- 本应用设计为 **纯内网**,请勿直接暴露到公网。
---
## 八、使用说明(操作层面)
### 8.1 登录
访问站点根路径,未登录会跳转至 **`/login`**,输入用户名与密码即可。
### 8.2 导航首页(`/`
- **左侧**:按分组展示服务名称;点击后在 **右侧 iframe** 打开对应地址。
- **顶部**:可进入「分组管理」「服务管理」或退出登录。
### 8.3 分组管理(`/admin/groups`
- **新建 / 编辑**:填写分组名称、排序。
- **删除**:会 **同时删除** 该分组下的 **所有服务**(级联删除),请谨慎操作。
- 列表中可从某分组快捷 **「在此分组添加服务」**。
### 8.4 服务管理(`/admin/services`
- 字段含义简要说明:
- **服务名称**:左侧显示名称。
- **内网 IP 或主机名**:如 `192.168.1.10` 或可解析的主机名。
- **端口**165535。
- **路径**:可选,须以 `/` 开头;留空则按 `/` 处理。
- **分组**:必选。
- **排序**:同分组内数字越小越靠前。
### 8.5 关于 iframe 打不开的说明
部分网站(尤其银行、部分管理面板)通过 **`X-Frame-Options`** 或 **`Content-Security-Policy`** 禁止被嵌入 iframe,此时右侧区域可能为空白或浏览器控制台报错。这属于 **目标站点安全策略**,与本导航站实现无关。若必须统一入口,只能由目标服务侧放开嵌入策略,或改为新窗口打开(需改代码,非当前默认行为)。
---
## 九、部署指南(以 Ubuntu 为例)
以下假设:系统为 **Ubuntu 20.04/22.04/24.04** 等,项目路径为 `/opt/nav-site`,监听端口 **5000**;可根据实际路径与端口修改。
### 9.1 系统准备
```bash
sudo apt update
sudo apt install -y python3 python3-venv python3-pip
```
(若已安装 Python 3 与 venv,可跳过。)
### 9.2 放置项目并安装依赖
```bash
sudo mkdir -p /opt/nav-site
# 将项目文件同步到 /opt/nav-site,保证 app.py、requirements.txt 等在根目录
cd /opt/nav-site
sudo python3 -m venv .venv
sudo chown -R $USER:$USER /opt/nav-site
source .venv/bin/activate
pip install -U pip
pip install -r requirements.txt -i https://pypi.org/simple
```
### 9.3 配置密钥(必做)
```bash
sudo mkdir -p /etc/nav-site
sudo bash -c 'openssl rand -hex 32 > /etc/nav-site/secret_key'
sudo chmod 600 /etc/nav-site/secret_key
```
后续由 systemd 读取该文件并注入 `NAV_SECRET_KEY`(见下节)。
**替代做法**:也可在项目根目录放置 `.env`(建议 `chmod 600 .env`),`WorkingDirectory` 指向项目根时程序会自动加载。若 systemd 的 `Environment` / `EnvironmentFile` 里已设置同名变量,**以 systemd 为准**`.env` 不会覆盖已有环境变量)。
### 9.4 使用 systemd 常驻运行(推荐)
创建服务文件(仍使用内置 `python app.py` 时示例;若改用 Gunicorn,将 `ExecStart` 改为 gunicorn 命令即可):
```bash
sudo nano /etc/systemd/system/nav-site.service
```
示例内容:
```ini
[Unit]
Description=Local Nav Flask Site
After=network.target
[Service]
Type=simple
User=你的Linux用户名
Group=你的Linux用户组
WorkingDirectory=/opt/nav-site
EnvironmentFile=-/etc/nav-site/env
ExecStart=/opt/nav-site/.venv/bin/python /opt/nav-site/app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
```
创建环境文件 `/etc/nav-site/env`**不要**把密钥写进 Git):
```bash
sudo nano /etc/nav-site/env
```
示例:
```ini
NAV_SECRET_KEY=粘贴openssl_rand_hex32的输出
NAV_HOST=0.0.0.0
NAV_PORT=5000
```
启用并启动:
```bash
sudo systemctl daemon-reload
sudo systemctl enable nav-site
sudo systemctl start nav-site
sudo systemctl status nav-site
```
查看日志:
```bash
journalctl -u nav-site -f
```
### 9.5 防火墙(若启用了 ufw
```bash
sudo ufw allow 5000/tcp
sudo ufw reload
```
仅内网使用时,也可限制来源网段(示例,请按实际修改):
```bash
sudo ufw allow from 192.168.0.0/16 to any port 5000 proto tcp
```
### 9.6 可选:使用 Gunicorn 提高稳定性
安装:
```bash
source /opt/nav-site/.venv/bin/activate
pip install gunicorn
```
`WorkingDirectory` 仍为项目根目录,**保证 `nav_local.db` 路径与工作目录一致**。示例 `ExecStart`
```ini
ExecStart=/opt/nav-site/.venv/bin/gunicorn -w 2 -b 0.0.0.0:5000 app:app
```
说明:`-w 2` 为 worker 数量,可按机器 CPU 调整;`app:app` 表示 `app.py` 中的全局变量 `app`
### 9.7 使用 PM2 守护进程(可选)
适合已安装 [PM2](https://pm2.keymetrics.io/) 的环境(常见于用 Node 的服务器上顺带托管 Python 进程)。项目根目录提供 **`ecosystem.config.cjs`**,用虚拟环境里的 Python 直接运行 **`app.py`**(与手动 `python app.py` 一致),**实例数固定为 1**(Flask 内置开发服务器不宜多进程监听同一端口)。
**1. 安装 PM2(若尚未安装,需本机已有 Node.js / npm**
```bash
sudo npm install -g pm2
```
**2. 准备虚拟环境与依赖(项目根目录)**
```bash
cd /opt/nav-site # 或你的项目路径
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -i https://pypi.org/simple
cp -n .env.example .env && nano .env # 至少配置 NAV_SECRET_KEY
```
**3. 启动 / 查看 / 维护**
```bash
cd /opt/nav-site
pm2 start ecosystem.config.cjs
pm2 status
pm2 logs nav-site
```
日志文件默认写入项目下 **`logs/`** 目录(PM2 会自动创建;该目录已加入 `.gitignore`)。
**4. 开机自启(在目标机器上执行一次)**
```bash
pm2 save
pm2 startup
# 按终端里打印的 sudo 命令整行复制执行,再执行一次 pm2 save
```
**5. 常用命令**
| 命令 | 作用 |
|------|------|
| `pm2 restart nav-site` | 热重启(改代码或 .env 后) |
| `pm2 stop nav-site` | 停止 |
| `pm2 delete nav-site` | 从 PM2 列表移除 |
| `pm2 monit` | 简易监控 |
**说明**:若 `interpreter` 指向的 `.venv/bin/python` 不存在,PM2 会启动失败;请确认虚拟环境路径与 `ecosystem.config.cjs` 中一致。Windows 下脚本会自动使用 `.venv\Scripts\python.exe`
---
## 十、数据与备份
- 默认数据库文件:**`nav_local.db`**,位于 **启动进程时的当前工作目录**(与 `WorkingDirectory` 一致)。
- 备份:定期复制该文件即可(建议在服务停止或负载极低时复制,避免损坏)。
- 恢复:替换同名文件后重启服务。
---
## 十一、路由一览(便于排障与二次开发)
| 路径 | 说明 |
|------|------|
| `/` | 导航首页(需登录) |
| `/login` | 登录页 |
| `/logout` | 退出登录 |
| `/admin/groups` | 分组列表 |
| `/admin/groups/new` | 新建分组 |
| `/admin/groups/<id>/edit` | 编辑分组 |
| `/admin/groups/<id>/delete` | 删除分组(POST |
| `/admin/services` | 服务列表(支持 `?group_id=` 筛选) |
| `/admin/services/new` | 新建服务 |
| `/admin/services/<id>/edit` | 编辑服务 |
| `/admin/services/<id>/delete` | 删除服务(POST |
---
## 十二、常见问题(FAQ
**Q:手机能打开吗?**
能。只要手机与服务器在同一局域网,且防火墙放行端口,浏览器访问 `http://服务器IP:端口` 即可。
**Q:为什么右侧 iframe 是白的?**
常见原因:目标站禁止被嵌入;目标服务宕机或地址/端口填错;浏览器混合内容策略(本应用为 HTTP 打开链接,若目标强制 HTTPS 且策略严格,可能异常)。可在新标签直接打开同一 URL 对比排查。
**Q:端口想改成 8080**
设置环境变量 `NAV_PORT=8080` 后重启进程;防火墙放行对应端口。
**Q:忘记密码怎么办?**
若有服务器文件权限,可用 SQLite 工具修改 `users` 表,或删除用户行后通过代码逻辑重新种子用户(需具备运维或开发能力)。
**Q:能否放到公网?**
本应用为内网场景设计,未内置 HTTPS、限流、审计等生产级能力。**不建议**直接暴露公网;若必须上公网,请自行叠加反向代理、TLS、访问控制与监控。
---
## 十三、版本与维护
- 依赖版本见 `requirements.txt`;升级依赖前建议在测试环境验证。
- 修改模板或静态文件后,重启进程即可生效;修改 Python 代码同样需要重启(`NAV_DEBUG=1` 时开发服务器可自动重载,但不建议在生产长期开启)。
---
**文档结束。** 若你后续增加「HTTPS 链接」「新窗口打开」「修改密码」等功能,建议在本文档对应章节补充说明并保持与代码一致。