Nginx 反向代理配置的拆分设计:文件名不重要,边界设计更重要

随着服务器数量和自建服务逐渐增加,Nginx 反向代理配置往往会从最初的几个 server 块,发展成一个包含大量域名、端口、证书和代理规则的超长配置文件。 这种集中式配置在规模较小时没有明显问题,但当后端主机越来越多后,维护成本会迅速上升。此时,可以采用一种更清晰的设计: 按后端主机拆分 Nginx 反向代理配置,一台主机对应一个配置文件。 这不仅是文件整理方式的变化,更是一种配置管理思想的变化。 一、Nginx 是否关心配置文件的名字 Nginx 通常不关心配置文件叫什么名字,它真正关心的是主配置中的 include 指令。 例如: 这条规则表示: 加载指定目录中所有以 .conf 结尾的文件。 因此,下面这些文件名都可以被加载: Nginx 不会因为文件名中出现了 host、proxy、storage 或其他词语,就赋予文件特殊功能。 文件名主要是给管理员阅读和管理使用的。 真正决定配置是否生效的是: 例如,当加载规则是: 以下文件通常不会被加载: 因为它们并不是以 .conf 结尾。 这也是一种很实用的配置停用方式:保留文件,但通过修改后缀让它退出加载范围。 二、为什么要按后端主机拆分 一个反向代理节点可能同时代理多台后端服务器。 例如: 如果所有配置都写在同一个文件中,随着服务数量增加,文件会逐渐变成: 不同主机、不同服务和不同证书混在一起,查找和修改都容易出错。 按后端主机拆分后,目录结构可以变成: 每个文件只负责一台后端主机。 例如: 只包含所有转发到主站服务器的域名和服务。 只包含备份管理系统的入口。 只包含转发到另一台独立服务器的域名和端口。 这种设计符合一个重要原则: 将具有相同变化原因的配置放在一起,将变化原因不同的配置分开。 某台后端服务器迁移、关机、更换地址或调整服务端口时,只需要检查对应的一个文件,而不必在数百行配置中寻找所有相关规则。 三、这种设计的核心思想 1. 高内聚 …

让公网 URL 与服务器目录解耦:一套低风险的 Apache 多应用路由重构方法

前言 一台 Web 服务器长期运行后,常会逐渐积累多个独立应用。最初部署时,为了省事,很多应用直接依赖站点根目录发布:磁盘目录叫 tool-alpha,公网地址也自然变成 /tool-alpha/。 这种方式能够工作,但公网 URL 与磁盘目录形成了不必要的一一绑定。项目目录一旦带有内部命名、历史命名或技术实现含义,公网地址也会跟着暴露;以后想调整 URL,又容易误以为必须移动项目目录。 更稳妥的做法是: 保持应用目录和程序结构不动,只在 Web 服务器配置层重新定义公网入口。 本文记录一次经过审计、分层验证和安全切换的实践。示例中的域名、主机名、应用名、目录、端口和配置文件名均为虚构内容。 一、改造前的典型结构 示例环境有两层 Web 服务: 公网客户端   ↓ HTTPSedge-gateway(Nginx)   ↓ HTTP 反向代理web-node(Apache)   ↓多个静态、PHP 和本地后端应用 网关层使用通用代理规则,将普通路径原样转发给后端 Apache: location / {    proxy_pass http://10.0.0.20;} 后端 Apache 的站点根目录是: /srv/web/ 多个应用原先直接按目录名对外发布: /srv/web/app-alpha/   → /app-alpha//srv/web/app-beta/   → /app-beta//srv/web/app-gamma/ …

从二维码登录到安全收尾:一个轻量文件柜系统的设计、审计与加固实践

本文中的项目名称、域名、主机名、账号、目录、Cookie 名称、时间参数、容量限制和命令均为虚构示例,仅用于说明技术方案,不对应任何真实部署环境。 一、项目目标 在家庭服务器或小型内部网络中,经常需要一种比网盘更轻量的文件交换工具: 基于这些需求,设计了一个名为 LanternBox 的示例系统。 它采用 PHP、SQLite 和现有 Web 服务器运行,不新增独立公网端口,不依赖常驻应用服务,也不把用户文件映射成静态下载地址。 整体结构如下: 二维码只负责临时授权。真正的用户身份由已经登记的手机浏览器持有,电脑获得的则是短期会话。 二、示例部署结构 示例环境使用以下虚构信息: 项目目录大致划分为: 这里最重要的设计不是“禁止访问几个敏感目录”,而是: 默认拒绝整个项目,只显式开放 public/。 示例 Apache 配置如下: 这种配置的安全意义是: 安全审计中,公开入口可以正常访问,而核心代码、配置、数据库和工具路径均未发现可用的公网绕过方式;普通用户访问管理入口也会被拒绝。 三、认证设计:手机浏览器作为可信设备 3.1 为什么不使用密码 对于少量家庭成员或内部使用者,账号密码会引入额外负担: 因此,系统采用手机设备登记与二维码批准模式。 3.2 首次登记流程 管理员创建用户后,为该用户生成一次性登记链接,例如: 手机浏览器打开链接后,服务器执行以下操作: 示例 Cookie: 登记令牌必须具备一次性和短时效特征。审计验证表明,一次性登记、令牌到期、使用后清除以及安全 Cookie 属性都能够正常工作。 3.3 电脑端扫码登录 电脑打开登录页后,服务器生成一条短期登录请求。 页面显示二维码,二维码中不直接包含永久设备凭据,而是一个短时、一次性的批准入口。 流程如下: 为了防止登录劫持,系统必须保证: 四、同一浏览器只能绑定一个账号的问题 在实际测试中发现,一个浏览器配置文件先登记管理员,再登记普通用户后,管理员身份会被普通用户覆盖。 原因并不是浏览器只能保存一个 Cookie,而是相同的: 只能对应一个当前值。 …

使用 Mailcow API 批量创建邮箱账号:从手工操作到自动化

在 Mailcow 管理后台中逐个创建邮箱账号并不困难,但当一次需要创建十几个甚至更多账号时,重复填写用户名、密码、配额和启用状态会变得繁琐,也容易出现输入错误。 Mailcow 提供了管理 API,可以通过脚本批量创建邮箱。即使 Mailcow 使用 Docker 部署,调用方也不需要进入容器,只需通过 Mailcow 对外提供的 HTTPS 地址访问 API。 本文介绍一种相对安全、简单且容易检查的批量创建方法。 一、Mailcow API 是什么 Mailcow 的网页管理后台适合人工操作,而 API 适合程序化管理。 例如,创建邮箱通常使用类似下面的接口: 请求中包含: 调用成功后,Mailcow 会像在网页后台手动创建一样,在系统中生成邮箱账号。 API 客户端与 Docker 容器之间没有直接关系,实际通信过程如下: 因此,脚本可以运行在: 不需要进入 Docker 容器,也不需要直接操作数据库。 二、在 Mailcow 后台启用 API 登录 Mailcow 管理后台,进入系统配置中的 API 页面。 通常可以看到两类权限: 创建邮箱属于写操作,因此需要临时启用 Read-Write API。 建议遵循以下原则: API …

在 Android 手机上将剪贴板内容广播到多台 KDE 设备

KDE Connect 可以在手机与电脑之间同步通知、文件、输入设备和剪贴板。不过在实际使用中,剪贴板同步往往会出现一个明显差异: 这并不一定是 KDE Connect 配置错误,而是与 Android 系统对后台读取剪贴板的限制有关。 问题表现 多台电脑与一部 Android 手机已经通过 KDE Connect 完成配对,并且各设备上的剪贴板插件均已启用。 测试时发现: 实际需求是:在手机上复制一段文字后,将它一次发送给所有当前在线并已配对的设备。 为什么手机端不能自动同步 较新的 Android 系统限制后台应用持续读取系统剪贴板。 当用户在其他应用中复制文字时,KDE Connect 通常无法像桌面程序一样,在后台立即获取刚刚复制的内容。因此,手机端很难实现完全自动的“复制即广播”。 这就导致了两种不同的工作方式: 这种差异主要来自操作系统权限模型,而不是 KDE Connect 本身失效。 解决方法:添加“发送剪贴板”快捷开关 KDE Connect 在 Android 的快捷设置面板中提供了一个“发送剪贴板”按钮。 设置步骤如下: 之后的使用流程为: 能否一次发送到多台设备 可以。 当多台设备同时满足以下条件时,点击一次“发送剪贴板”按钮,就可以将内容发送到这些设备: 因此,这个功能不仅适用于手机与单台电脑之间同步,也适用于手机向多台电脑广播当前剪贴板内容。 电脑端需要检查的设置 如果部分电脑收不到内容,可以检查: 如果设备处于离线状态,发送操作不会在设备重新上线后自动补发。需要在设备恢复连接后再次点击“发送剪贴板”。 实际使用体验 最终形成的操作流程非常简单: 手机复制文字 → 下拉快捷设置 …

从 X11 切换到 Wayland 后,远程代理无法打开可见浏览器的排查与修复

在一套多主机自动化环境中,AI 代理需要远程控制一台 Linux 桌面设备上的专用浏览器。这个浏览器使用独立用户数据目录启动,同时开启本机回环地址上的远程调试接口,再通过 SSH 隧道供另一台控制主机访问。 这套流程过去一直可以正常工作,但桌面环境从 X11 切换到 Wayland 后,代理突然无法打开可见的浏览器窗口,并判断当前系统“没有图形显示环境”。 经过手动测试和流程修正,最终确认问题并不在浏览器,也不在 Wayland,而在于代理获取图形会话环境的方法仍然停留在旧的 X11 逻辑。 一、原有工作方式 整个浏览器控制流程大致分为四部分: 正常情况下,代理不仅可以读取网页内容,还可以操作可见浏览器窗口,例如: 这种方式与普通无头浏览不同。操作过程会真实显示在桌面上,坐在屏幕前的人可以同步观看。 二、出现的问题 桌面环境切换到 Wayland 后,代理尝试启动浏览器时发现: 随后代理直接得出结论: 表面上看,这个判断似乎合理,但实际上检查的是代理当前所在的 SSH shell,而不是桌面主机中正在运行的真实图形会话。 SSH 登录产生的非图形 shell 没有继承桌面会话变量,是完全正常的现象。即使桌面上正在运行完整的 KDE Wayland 会话,SSH 终端中的相关变量仍然可能为空。 因此,不能根据 SSH shell 中的环境变量判断远程设备是否存在图形会话。 三、手动测试 为了区分浏览器故障和代理逻辑故障,首先在桌面主机本地终端中进行了测试。 本地图形终端可以正常读取到以下类型的环境信息: 随后使用以下参数启动专用浏览器: 测试进行了两次,两次都顺利打开了可见浏览器窗口,并正常进入目标网页。 这说明: 四、真正的原因 旧流程主要针对 X11 环境设计,通常从 X11 …

多个域名共用同一台 Nginx 反向代理服务器的 443 端口

本文中的域名、主机名、IP 地址、端口、文件路径、脚本名称和服务名称均为虚构示例,已与实际环境完全分离。 一、需求背景 在家庭服务器、小型实验室或自托管环境中,常见需求包括: 例如,存在两套独立域名: 这些域名可以全部使用同一个公网 IP,并共同通过标准 HTTPS 端口 443 访问。 核心技术包括: 二、整体架构 示例网络结构如下: 路由器只需保留一条主要的 HTTPS 转发: 外部访问地址保持为标准形式: 无需在 URL 后附加内部应用端口。 三、为什么多个域名能够共用 443 HTTPS 客户端在 TLS 握手阶段通常会携带目标域名,这项机制称为: Nginx 接收到连接后,可以根据客户端请求的域名选择对应的: 因此,以下请求虽然全部进入同一个地址: 仍可被 Nginx 分别处理: 从公网看,所有服务都使用标准 HTTPS;从局域网看,每个域名可以对应不同的主机、端口和应用。 四、Nginx 配置示例 假设域名和后端关系如下: 可以配置四个独立的 server 块。 主域名和 www 子域名 管理子域名 API 子域名 其他应用子域名 五、不同域名可以使用不同证书 多个域名共用同一个 …

systemd 服务因 /tmp 目录消失而启动失败:一次证书工具的修复记录

问题背景 某台 Linux 服务器上运行着一个内部证书申请工具。该工具通过 Web 页面发起 ACME 证书申请,并使用 DNS TXT 记录完成域名验证。 应用采用 Python 编写,通过 Gunicorn 运行,仅监听本机回环地址,再由 Web 服务器进行反向代理。 其目录结构大致如下: 临时目录中可能出现: 证书签发完成后,还可能短暂保存: 这些文件包含证书和私钥,因此不适合长期保存在服务器上。证书下载完成后,应尽快清除服务器副本。 故障现象 服务器重启后,证书工具无法启动。查看 systemd 状态时发现服务不断退出并自动重启: 由于服务配置了自动重启,短时间内重复失败,最终形成了持续的重启循环,累计重启次数达到数万次。 需要注意的是,此时 Gunicorn 和 Python 应用实际上还没有开始执行。 故障发生在 systemd 为服务建立挂载命名空间的阶段。 根本原因 服务的 unit 文件中包含类似配置: 这项配置用于限制服务可写入的位置,是一种合理的 systemd 安全加固措施。 问题在于: 在服务启动前必须已经存在。 /tmp 本身是临时文件系统。系统重启后,其中的自定义目录可能被正常清除。当 systemd 尝试根据 ReadWritePaths= 建立服务的挂载命名空间时,发现目录不存在,于是直接返回: …

使用自动化代理完成安卓手机全面审计与定向优化

一、审计目标 在安卓手机通过无线 ADB 连接家庭服务器后,可以让自动化代理执行一次较为深入的非 Root 审计。 此次审计目标不是获取个人内容,也不是制作取证镜像,而是检查: 整个过程遵循: 二、非 Root ADB 能做到什么 通过 ADB,可以获取: 但它不能: 因此,这类任务应称为: 三、审计过程设计 审计分成两阶段。 第一阶段:只读采集 所有操作只读取,不修改: 所有证据保存到服务器独立目录,并生成结构化报告。 第二阶段:定向整改 审计结束后,仅处理用户明确选择的项目。 每项整改必须包含: 四、系统安全基线 审计确认了以下基础安全状态: 这些结果说明系统完整性基础正常。 未发现以下常见高风险迹象: 但“未发现”只能代表当前可见证据中没有,不能等同于绝对排除。 五、应用和权限审计 自动化代理逐个扫描了大量用户应用,并生成: 重点检查的能力包括: 审计发现的高权限应用,大部分都能与实际用途对应。 例如: 因此,高权限并不等于恶意。 风险判断必须结合: 六、一次重要的误判纠正 报告最初将某个远程桌面应用写成“无障碍已启用”。 但原始系统状态显示,它只是安装了无障碍组件,实际没有启用。 真正处于启用状态的无障碍服务只有两个用户明确使用的工具。 这说明自动化审计不能只依赖应用 Manifest 或已安装服务列表。 必须区分: 这四种状态完全不同。 七、共享存储中的残留 APK 共享存储检查发现一个文件名看起来像常见社交应用的 APK。 静态分析后发现: …

Fcitx5 for Android 中实现 Rime 动态日期时间:一次从静态配置到真实验收的排查

一、需求目标 安卓设备使用 Fcitx5 for Android,并安装了 Rime 插件。希望在现有拼音方案中加入动态日期和时间候选。 目标触发词包括: 要求保持原有输入习惯,不更换输入法框架,不影响用户词库和同步数据。 桌面版 Fcitx5-Rime 中,可以通过 Lua translator 实现类似功能。但安卓版本的目录结构、插件构建和部署方式与桌面 Linux 不完全相同,不能直接照搬。 二、最初的实现思路 最初方案采用三个核心文件: 目录结构类似: 基本逻辑是: 理论上,这一结构是合理的。 三、为什么第一次没有生效 配置文件写入后,实际输入没有出现动态候选。 最初并不能确定问题位于哪一层: 静态查看文件只能证明“配置存在”,不能证明运行时已经加载。 四、通过无线 ADB 获取运行时证据 无线 ADB 建立后,可以直接查看 Fcitx5 Android 的外部数据目录。 审计重点包括: 还可以检查: 这使排查从“根据备份猜测”变成“根据实时系统判断”。 五、关键时间线线索 实时目录中发现: 这说明新增配置写入后,部署产物没有同步更新。 这一现象通常对应几种可能: 其中,“配置文件存在,但 build 仍旧”是非常重要的诊断信号。 六、确认安卓 Rime 插件的 Lua 能力 …