☰
Deepseek Harness公网部署与安全鉴权实战:从Caddy反代到Authelia
2026/10/26 14:11:33 网站建设 项目流程

最近我把本地跑了好一阵的 Deepseek Harness 服务迁到了云服务器上,并且认真折腾了一遍公网访问下的身份鉴权。整个过程比我想象中有意思,也踩了几个确实容易让人卡住的坑。折腾完回头一总结,这套流程其实非常值得整理成一篇实操笔记。

先说这个项目是干什么的。Deepseek Harness 是一个面向 Deepseek 系列模型的本地优先的 AI 任务编排工具,你可以把它理解成模型与各种工具之间的调度层:后面接 Deepseek API,前面出 Web 界面和插件能力。本地跑的时候一切都好,但想让同事用、在外面也能连,就必须放到云服务器上并解决公网安全访问的问题。这篇内容适合已经基本跑通过 Deepseek Harness、现在想把它搬到云服务器并安全开放给外部访问的朋友,也适合想了解常见公网鉴权方案怎么组合落地的同学。

我采用的技术路线是:云服务器 + Docker Compose 跑 Harness,Caddy 做反向代理和自动 HTTPS,使用基础认证起步、再叠加 Authelia 做更严谨的验证流程。下面直接讲核心流程和每个环节背后的考虑,所有配置我都实际验证过。

1. 为什么公网部署第一件事是解决鉴权,而不是解决访问速度

很多人在本地把服务跑通之后,第一反应是直接买个服务器把服务跑起来,然后域名一解析就完事。这个思路在纯内网工具上没问题,但 Deepseek Harness 这类服务一旦暴露到公网,情况完全不同。

它本质上是一个带计算资源的 Web 服务,而且有对话接口、插件系统、模型调用配置。如果裸奔到公网,意味着任何一个知道地址的人都可以:消耗你的模型 API 额度、读取和修改你的配置、往你的持久化存储里写数据,甚至通过插件打开更深的执行入口。这不是危言耸听,公网扫描器会在几分钟内发现你开放的端口和路径。我自己的服务器上就亲眼看到过,只挂了一个默认页面的 IP,日志里都有大量自动化探测请求。

所以公网部署的第一个决定不是选哪家服务器,而是先确定鉴权方案。我把自己这段时间比较过的方案整理成了一张表,方便你对照自己的情况选:

方案难度适合场景我把话说透一点
Caddy/Nginx 基础认证极低单人或小团队,能接受一个共享账号最简单,密码写在配置文件里,适合起步
Authelia 或 Authentik中等需要独立账号、双因素、多服务统一登录相当于给服务加了登录系统和 TOTP,体验接近正规产品
OAuth2 Proxy + 企业账号较高公司内部对接 SSO、LDAP、GitHub 组织适合团队已经有统一身份源的情况
内网穿透(加密隧道)低临时演示,不想买服务器严格说不算公网部署,但确实能用,只是延迟和服务稳定性看第三方脸色

我自己最终用了 Caddy 基础认证 + Authelia 的组合。为什么不是直接用基础认证完事?因为基础认证的账密是一份共享凭证,时间一长容易外泄;而且没有双因子,万一密码泄露就完全裸奔了。Authelia 的好处是支持每人一个账号、还能强制 TOTP 验证码,成本只是多跑一个容器,值。

如果你只是自己用,或者团队就两三个人,我建议第一步用纯基础认证就够了,后面有需要再叠加 Authelia。别一开始就把架构搞复杂,云服务器上每多一个服务,就多一份要维护的心智负担。

2. 服务器选型、系统初始化与域名解析的细节

2.1 配置选型:别只看价格,磁盘是最容易忽略的地方

Deepseek Harness 本身不重,但对内存和磁盘有一定要求。我的经验值供你参考:

  • 日常小规模使用:2 核 4G 内存,40G SSD 起步。
  • 要跑大量插件任务、长时间会话语境重、或者还打算接本地向量库:4 核 8G 内存,80G SSD 更稳妥。

特别提醒一句,磁盘别买太小。Docker 镜像、Harness 的日志、模型调用的缓存、插件下载的文件,都会悄咪咪吃掉大量空间。我一开始买了 50G 的盘,装完依赖和插件后只剩下不到 10G,后来每次查日志都觉得难受。如果服务器已经很小了,也别慌——后面第 6 章我会单独讲清理和扩容。

2.2 系统选择:Ubuntu 22.04 目前最省心

我推荐 Ubuntu 22.04 LTS。原因不是它性能更好,而是社区资料最多,Docker 和 Caddy 的兼容性验证最充分,遇到问题搜一下基本都有答案。云厂商的通用镜像选好后,建议第一时间把系统更新跑完:

sudo apt update && sudo apt upgrade -y sudo timedatectl set-timezone Asia/Shanghai

顺手把时区改了,后面看日志会舒服很多,尤其是排查问题的时候,时间对不上会绕很多弯路。

2.3 在云控制台放行端口,再在系统层改防火墙

这一步是新手翻车重灾区。云厂商控制台的“安全组”或“防火墙”和服务器内部的 iptables/ufw 是两层概念,两层都要放行才行。有些厂商默认只放行 22 端口,你辛辛苦苦部署完了,域名一打开发现连不上,十有八九是这里的问题。

我用的规则很简单:

sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable

22 留着自己 SSH 用,80 用来处理 HTTP 跳转和证书签发,443 是最终对外提供服务的通道。其他端口一概不放行,内部服务比如 Harness 的默认端口只让它们通过 Docker 网络或本机访问。

2.4 域名解析:子域名单独建一条 A 记录

如果你只拿 IP 访问,也不是不行,但后面配 HTTPS 证书会非常痛苦。我强烈建议用一个子域名,比如 harness.example.com,在 DNS 服务商那边建一条 A 记录指向服务器 IP。为什么建议子域名而不是主域名?因为将来你可能还有别的服务,每个服务独立子域名便于管理和配证书。解析生效一般几分钟就够,别在刚添加完还没生效时就开始怀疑配置出错。

这里有一个小经验:如果你的 DNS 服务商支持“仅 DNS”模式,切换解析时优先级会高一些。不过大部分家用场景直接用默认就行,TTL 不用管它。

3. Docker Compose 部署 Deepseek Harness 与数据持久化

3.1 为什么不建议直接二进制跑,而是优先用容器

Deepseek Harness 有 Linux 下的直接安装方式,但放在云服务器上我更推荐 Docker Compose。理由很实际:二进制方式在系统升级、Python 依赖冲突、版本回退时都很痛,容器把运行环境整个打包了,升级就是拉新镜像,回退就是换个版本号,干净利落。

安装 Docker 就不啰嗦了,官方脚本一行搞定:

curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER

重登 SSH 后检查一下:docker ps能看到输出就说明 Docker 就绪了。

3.2 编写 docker-compose.yml 与 .env

我实际的目录结构是这样:

~/harness/ ├── docker-compose.yml ├── .env └── data/

.env文件内容要刻意精简,把密钥类的东西单独放:

HARNESS_PORT=8080 HARNESS_DATA_DIR=./data API_KEY=你的deepseek或者兼容接口的key

如果 Harness 支持通过环境变量注入外部模型 API Key,那就用它来传,不要写进代码或者 Web 面板的明文配置里。密钥通过环境变量传的好处是:换 key 的时候不用重新构建镜像,直接改.env后docker compose up -d就生效。

docker-compose.yml的核心部分可以参照这个思路:

services: harness: image: harness镜像:版本 container_name: harness restart: unless-stopped env_file: .env ports: - "127.0.0.1:8080:8080" volumes: - ./data:/app/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 5s retries: 3

这里有个很重要的知识:端口不要绑到 0.0.0.0,而是绑到 127.0.0.1。也就是说 Harness 本身只监听本机回环地址,外面的流量只能通过反向代理进入。这么做等于多了一层保险——就算 Caddy 或者防火墙配置出了纰漏,服务也不会直接暴露在公网端口上。这是我在实际生产环境里学到的最值钱的一条经验。

3.3 Railway 免费部署是备选,但不适合长期主力

最近网上聊 Railway 部署 Harness 的比较多。如果你想零成本快速体验,确实可以把服务用 Railway 的模板一键拉起,免费额度对个人体验基本够用。但我试过之后感受很明显:免费实例会休眠,冷启动要等十几秒到几十秒;而且 Railway 自带的域名鉴权比较弱,还是得自己套认证层。作为初体验和验证可行性的方案没问题,长期给团队用还是老老实实放云服务器上。

3.4 启动验证:先看日志,再本地请求一次

docker compose up -d docker compose logs -f

日志里出现类似“服务启动成功”的字样后,在服务器本地试一次:

curl -I http://127.0.0.1:8080

只要返回 HTTP 200,说明服务本身没问题。记住这时还不要用公网 IP 去测,等反向代理配好再测,否则你分不清问题出在服务还是代理。

4. 使用 Caddy 做反向代理:把公网流量安全地导给本地服务

4.1 为什么挑 Caddy 而不是传统 Nginx

反向代理工具有很多,Nginx 当然是经典,但让我选的话,Caddy 明显更省心。核心原因是它会自动申请和续期 HTTPS 证书,不用自己跑 certbot、写续期定时任务,配置写起来也比 Nginx 直观得多。对于一个需要快速上线的个人或小团队项目,Caddy 在维护成本上的优势一眼可见。

Caddy 的安装很简单,用官方 apt 源:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.list' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update && sudo apt install caddy

装好后配置文件的路径是/etc/caddy/Caddyfile。我的第一版配置是这样的:

harness.example.com { reverse_proxy 127.0.0.1:8080 }

就这么简单。启动 Caddy 后它会自动申请 HTTPS 证书并对外提供加密访问。但注意,如果你试了之后发现浏览器提示证书错误或无法访问,优先检查两件事:一是 DNS 解析是否真的生效,二是云控制台安全组是否放行了 80 和 443。

4.2 完整反代配置里一定要保留真实客户端 IP

上面的极简配置能跑,但缺点是你拿不到真实访问者 IP。Harness 的日志和审计功能会需要来源 IP 信息。所以我最终用的配置加了几行:

harness.example.com { encode zstd gzip reverse_proxy 127.0.0.1:8080 { header_up Host {host} header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} X-Forwarded-Proto {scheme} } }

X-Forwarded-*这几个头是 Web 服务获取客户端真实信息的标准方式。只要加了这些头,Harness 在处理请求时就能拿到正确的来源 IP,而不是反代机器的 IP。

4.3 到这里先别急着宣布“部署完成”

到这一步,你确实已经可以用https://harness.example.com访问到了服务。但如果此时就分享链接,等于把一个没上锁的房间挂在了大街上。所以正确的顺序是:反代通了一定要先感受一下登录前后的差异,然后立刻进入下一步加鉴权。我自己犯过的错就是先分享给了朋友,结果半小时后人家告诉我“你这个页面不用密码就能进”,当时的尴尬场面至今记忆犹新。

5. 公网鉴权落地:从基础认证到 Authelia 的完整配置

5.1 第一步:Caddy 自带基础认证,一分钟挡住 99% 的陌生人流量

如果你只需要最基础的保护,Caddy 自带的basic_auth就够了。先在本地生成密码哈希:

caddy hash-password

按提示输入你的密码,得到一串带$2a$开头的 bcrypt 哈希。然后修改 Caddyfile:

harness.example.com { basicauth { admin 这里粘贴生成的哈希 } reverse_proxy 127.0.0.1:8080 }

重载配置后再次访问,浏览器会弹出一个账号密码输入框。这层保护看着简单,但已经能挡住绝大多数自动扫描和普通路人流量。验证方式也很简单:访问时带账号密码是 200,不带是 401。

5.2 第二步:引入 Authelia,把人手一份的账密升级为独立账号加 TOTP

基础认证的痛点前面说了,就是共享账密。当团队超过三个人,或者你想让某个人单独撤回权限的时候,共享账密会变得非常痛苦。所以我在基础认证通过后,引入了 Authelia 作为统一认证层。

Authelia 也是一个 Docker 容器,搭配一个 SQLite 或者 Redis 存储用户的配置。核心结构和 Caddy 的联动逻辑是:所有请求先交给 Authelia 验证门户,验证通过后再转发给 Harness。用户看到的体验是“打开网址先看到一个登录界面”,输入账号密码再加 TOTP 验证码,然后才进入真正的工具。

docker-compose.yml里我加了:

services: authelia: image: authelia/authelia:latest container_name: authelia restart: unless-stopped volumes: - ./authelia:/config environment: - TZ=Asia/Shanghai networks: - harness_net

Authelia 的完整配置文件比较长,关键点包括jwt_secret、storage和access_control。第一次配置时最容易犯的错是jwt_secret和storage的encryption_key需要足够随机且固定,否则重启后会话和用户数据会出问题。生成随机值可以用:

openssl rand -hex 32

5.3 第三步:把 Caddy 与 Authelia 联动起来

这是整个流程里技术含量最高的一步。Caddy 需要先定义两个 location 级别的处理:一个是 Authelia 自己的端点(/api/auth、/api/verify等),一个是所有其他请求的验证入口。真实配置我整理成了下面这个样子:

harness.example.com { forward_auth 127.0.0.1:9091 { uri /api/verify?rd=https://harness.example.com copy_headers Remote-User Remote-Groups Remote-Email } reverse_proxy 127.0.0.1:8080 } auth.example.com { reverse_proxy 127.0.0.1:9091 }

注意这里我把 Authelia 的服务地址指向了 127.0.0.1:9091,前面的 Docker 网络里要在容器端口映射中把 9091 露出来。forward_auth的含义是:Caddy 收到任何请求,都先发给 Authelia 验证;验证通过就继续转发,验证失败就踢回登录界面。

配置完成后,在服务器本地做一次请求测试:

curl -I https://harness.example.com

应该看到 302 跳转,这是正常的。浏览器打开则应该看到登录页。输入账号密码加上 TOTP 验证码后,才能进入 Deepseek Harness 的主界面。

5.4 关于安全的额外提醒:HTTPS、Cookie 和行进中的未加密链路

有朋友会问,我已经加了鉴权,是不是就安全了?还差一步,就是确认整条链路都走 HTTPS。从浏览器到 Caddy,这是 HTTPS;从 Caddy 到 Harness,虽然走的是本机回环,但 Caddy 默认会用 HTTP 转发。如果两个服务都在同一台机器上,这个风险很小,因为回环地址不经过外部网络。但如果你把 Harness 和 Caddy 拆到两台机器上,那中间这段 HTTP 就很容易被嗅探,必须额外配置转发走自签名证书或内部私有网络协议。

还有一个细节是 Cookie 的Secure属性。你需要在 Harness 或者 Authelia 的配置里确认 Cookie 是只允许通过 HTTPS 发送的。一般反代层已经终结了 HTTPS,服务本身收到的是 HTTP 请求,所以有些框架生成的 Cookie 不会自动加Secure。如果你登录后一切正常,只是总觉得“哪里没对”,翻一下浏览器开发者工具的 Cookie 面板,看看值是不是Secure标注的。实测很多怪问题都源于此。

6. 云服务器上的长期运营:插件、模型接入、回退与磁盘维护

6.1 基础镜像跑通了,说下我日常在用的几个实用插件

部署完成只是开始,真正让 Deepseek Harness 好用的是插件。我这边长期开着的插件有三个,都跟网上大家常讨论的对得上:

  • AnySearch 类联网搜索插件:让模型在回答时可以实时查网页,用来查最新的文档、新闻、产品动态。安装思路一般是进 Harness 的插件市场勾选,或者把插件项目 clone 到data/plugins目录后重启容器。安装后记得在对话里明确告诉模型“我需要实时信息,请启用搜索”,否则有些场景下搜索插件不会自动触发。
  • 提示词优化类插件:如果你经常写提示词,这个插件可以自动把自然语言需求改写成结构化、带上下文约束的提示词。我实验过,生成的效果比手写确实稳定一些,尤其是面对长任务时。
  • LLM Wiki 类插件:给模型挂一个本地知识库,长期业务资料、产品手册整理进去后,回答会明显“懂行”很多。使用前先看一遍它的向量索引构建说明,不要一上来就把全公司文档丢进去,容易把索引质量搞低。

安装插件最频繁遇到的问题是权限。数据目录是容器内某用户所有,你在宿主机上 clone 的文件往往权限不对,导致容器启动时读不了。我一般用:

chown -R 1000:1000 data/plugins

如果镜像里指定了别的 UID,以镜像文档为准。

6.2 接入免费模型:别把所有请求都压在一个付费 key 上

现在 Deepseek Harness 也可以接入一些免费模型额度,比如部分兼容 OpenAI 协议的聚合平台上用免费 key 跑日常测试。我的建议是:免费模型用来做实验、调提示词、跑测试用例,生产环境里重要的对话和任务还是要走正式 key。用免费模型铺底还有个好处是可以把正式 key 的额度大头留给高价值任务。

接法一般是在配置文件里配置多个 provider,按路由规则分发。如果你测试时发现某个 provider 总是超时,大概率是对方的限流策略,不是你配置错了。换个思路,用低并发、多轮重试写进去,效果会好很多。

6.3 代码回退:改坏了怎么快速回到上一个能用的状态

这个话题很多人看不上,真出了问题会很着急。我的习惯是给目录打标签:

cd ~/harness docker compose down git add -A && git commit -m "backup before plugin update"

如果容器镜像更新后出了问题,最快的回退方式是:

git checkout . && docker compose up -d --no-build

只是配置文件变坏的话,这个流程够用了。如果问题出在新镜像本身,你需要切回旧镜像版本号,而不是用latest。所以平时我部署时指定的版本号永远用具体 tag,比如v0.9.5,而不是latest。用latest一时方便,但回退的时候你很难凭记忆确定“刚才那个能用的到底是哪个版本”。

6.4 磁盘空间:从 10G 剩余到清理脚本的日常保鲜

前面说了我磁盘差点爆掉,所以现在养成了隔段时间看一眼空间的习惯:

df -h docker system df

最占空间的三样东西:旧的 Harness 镜像、无主数据卷、日志文件。清理指令:

docker system prune -af docker volume prune

日志的话,可以在docker-compose.yml里给服务设置日志轮转:

logging: driver: json-file options: max-size: "10m" max-file: "3"

这个配置加了以后,单容器单日志上限 30M 左右,再也不用担心日志把小盘吃光了。如果实在扩容的话,云控制台上直接扩数据盘,然后sudo growpart加sudo resize2fs,一套操作下来不用重装系统,很方便。

6.5 离线局域网部署也是同一套路:内网 DNS 加内网证书

网上确实很多人问 Deepseek Harness 能不能离线内网使用。答案是能,而且并不需要和公网部署完全不同的方案。你搭好服务后,在内网机器上把/etc/hosts写一条内网映射,或者自己在内网 DNS 上加一条记录,然后把 Caddy 配置文件里的域名改成内网专属域名、证书改成内网 CA 签发的,流程和公网部署几乎一致。唯一要注意的是离线环境下 Caddy 无法用 ACME 自动签发证书,你需要手动生成并信任自签 CA。内网用户每台机器都要安装一次 CA 证书,否则浏览器会持续报警。

7. 部署期高频问题排查:我实测中遇到的现象和解决路径

说实话,把这套流程走完,我对 Deepseek Harness 公网化部署的整体理解上了一个台阶。最后一章把我在实际过程中遇到的高频问题列一下,按问题现象、可能原因、解决动作的顺序写。这些都是真实跑过的路线,很多人可能早晚会遇到。

现象可能原因解决动作
浏览器访问域名提示无法连接DNS 未生效或安全组未放行 443先在另一台机器上ping域名,再确认云控制台安全组和 ufw 都放行 80/443
能访问页面但一直显示“登录失败”基础认证密码哈希格式不对或账号名拼错重新用caddy hash-password生成,检查账号名是否大小写敏感
登录后无限跳回登录页Cookie 未启用Secure或 Authelia 的jwt_secret不稳确认 HTTPS 在整个链路生效,重启 Authelia 并沿用同一jwt_secret
Harness 内部一切正常,但代理访问特慢未开启压缩在 Caddyfile 中加encode gzip或encode zstd gzip
插件安装后无效果权限不对或插件未启用chown -R 1000:1000 data/plugins,然后在 Harness 界面插件管理里重新启用
磁盘空间突然被占满旧镜像 + 日志定期执行docker system prune -af,配置日志轮转
想恢复旧版但不知道镜像 tag一直用latest以后固定版本 tag,回退前先docker compose logs确认版本号特征

这里插一条经验:排查这类组合架构问题时,尽量从最外层往里层推进。浏览器 → DNS → 防火墙 → 反向代理 → 认证服务 → 应用服务,按这个顺序逐层验证,比同时瞎猜几个可能原因高效得多。

最后想说的一点实际体会

在真正把 Deepseek Harness 放到云服务器上之前,我一直觉得加鉴权是件很琐碎的事。经历了公网扫描、共享账密的别扭、插件权限的麻烦之后,我现在的观点是:公网部署的每一个安全步骤都在为后续省事。尤其是 Authelia 这套,初期花一晚上配好,之后团队加入退出都变得非常轻松,不用再到处改密码。

如果你打算自己动手做一遍,我最后的建议是:第一次调试时不要追求一步到位。先把 Docker Compose 跑起来,内网curl验证 200,再用 Caddy 反代,看看页面能出来,之后再加基础认证,跑通以后再看要不要上 Authelia。每加一层都验证一层,会比一次性堆完所有东西更容易定位问题。

我现在的服务器上,同一个域名入口同时挂着 Harness 和认证门户,晚上看日志的时候会见到各种扫描器的试探请求,但基本都被挡在第一层。作为运维者,这种感觉称得上踏实。这套流程你照着走一遍之后,很多“部署完了又不敢开放访问”的尴尬,就不会再有了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询