373 lines
13 KiB
Markdown
373 lines
13 KiB
Markdown
# 本地导航站 · 部署与使用说明
|
||
|
||
本文档为 **中文说明** 与 **部署操作** 合一版本,适用于在局域网(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 依赖列表
|
||
├── 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
|
||
```
|
||
|
||
---
|
||
|
||
## 五、环境变量说明
|
||
|
||
| 变量名 | 含义 | 默认值 |
|
||
|--------|------|--------|
|
||
| `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
|
||
```
|
||
|
||
**Windows(PowerShell):**
|
||
|
||
```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 直接启动(开发 / 小范围内网)
|
||
|
||
```bash
|
||
export NAV_SECRET_KEY="$(openssl rand -hex 32)" # Linux,建议每次部署写进 systemd 环境文件
|
||
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` 或可解析的主机名。
|
||
- **端口**:1–65535。
|
||
- **路径**:可选,须以 `/` 开头;留空则按 `/` 处理。
|
||
- **分组**:必选。
|
||
- **排序**:同分组内数字越小越靠前。
|
||
|
||
### 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`(见下节)。
|
||
|
||
### 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`。
|
||
|
||
---
|
||
|
||
## 十、数据与备份
|
||
|
||
- 默认数据库文件:**`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 链接」「新窗口打开」「修改密码」等功能,建议在本文档对应章节补充说明并保持与代码一致。
|