
1. 为什么要在 Linux 上源码部署 DeepSeek Harness Web1.1 这个项目到底解决什么问题先把话说清楚DeepSeek Harness Web 本质上是一套把大模型能力接出来的 Web 服务层。它不是一个模型本身而是一个外壳——负责把 DeepSeek 的推理接口、会话管理、工具调用、流式输出这些东西包装成一个可以通过浏览器访问的 Web 应用。你可以把它理解成一个自建的 AI 工作台前端是网页后端跑在 Linux 服务器上模型能力通过 API 或者本地推理引擎接入。那为什么不用官方网页版非要自己折腾一套我踩过几次坑之后总结下来自建的核心价值有三个第一是数据可控所有会话记录、上传的文件、工具调用的中间结果都留在你自己的机器上不经过第三方第二是可定制你可以改前端界面、加自己的工具插件、接自己的知识库官方网页版给不了这种自由度第三是可集成把它部署在内网服务器上团队里其他人通过浏览器就能用还能和内部系统打通。源码部署相比 Docker 一键拉镜像好处是你能看到每一行配置、能改、能调优、出问题能定位。坏处也明显——依赖、环境、权限、进程守护每一步都可能卡住。这篇就是把我从零到远程访问的完整过程拆开讲包括那些文档里不会写的坑。适合谁看有基本 Linux 命令基础、想在自己服务器或内网机器上跑一套 AI Web 应用的人。如果你连cd、ls都不熟建议先补一下基础命令再来不然中间会很难受。1.2 源码部署 vs 镜像部署选型背后的逻辑很多人第一反应是有没有现成镜像拉下来就跑。确实有但源码部署在几个场景下更合适我把对比列出来你就明白了维度源码部署镜像部署可定制性高任意改代码和配置低只能改环境变量依赖透明度完全可见出问题好定位黑盒报错难查版本控制可锁定 commit可回滚依赖镜像 tag资源占用可裁剪按需装依赖通常偏大上手速度慢需要配环境快一条命令适合场景二次开发、内网集成、学习快速验证、临时使用我个人的判断标准很简单如果你只是想用一下看看效果镜像部署如果你打算长期跑、要改、要集成到别的系统里源码部署。这篇讲的是后者。还有一个现实原因——很多服务器是国产 Linux 发行版比如某些基于 openEuler、Anolis 的系统镜像不一定兼容源码部署反而更稳。这一点在嵌入式场景比如香橙派、全志平台的板子上尤其明显ARM 架构的镜像经常缺源码编译是唯一出路。2. 部署前的环境准备与依赖梳理2.1 系统与硬件的最低要求先说底线配置低于这个数就别折腾了跑起来也是卡CPU2 核起步4 核舒服。如果模型走本地推理核心越多越好。内存4GB 是底线8GB 推荐。Node.js 构建阶段很吃内存2GB 的机器大概率在npm install阶段就被 OOM Killer 干掉。磁盘至少 20GB 空闲。源码 依赖 日志 可能的模型缓存很容易吃掉十几个 G。系统主流发行版都行Ubuntu 20.04/22.04、Debian 11/12、CentOS Stream、国产的 openEuler 我都试过问题不大。内核建议 4.x 以上。查看系统信息用这几条命令先摸清家底# 看发行版 cat /etc/os-release # 看内核 uname -r # 看 CPU 核数 nproc # 看内存单位 MB free -m # 看磁盘 df -h提示如果free -m显示可用内存低于 2GB先加 swap否则构建阶段必挂。加 swap 的命令后面会讲。2.2 依赖清单一个都不能少DeepSeek Harness Web 这类项目典型技术栈是 Node.js 前端 后端服务可能还带 Python 脚本做工具调用。所以依赖大致分三块基础工具链git、curl、wget、build-essential编译原生模块用、python3部分 npm 包需要。运行时Node.js建议 18 LTS 或 20 LTS、npm 或 pnpm。如果后端有 Python 部分还要 Python 3.10。进程管理systemd系统自带用来做守护进程。一次性装齐以 Debian/Ubuntu 系为例sudo apt update sudo apt install -y git curl wget build-essential python3 python3-pipCentOS/openEuler 系换成sudo dnf install -y git curl wget gcc gcc-c make python3 python3-pip2.3 Node.js 版本管理别用系统自带的这是第一个大坑。系统仓库里的 Node.js 版本往往很老Ubuntu 20.04 自带的是 10.x而现代前端项目基本要求 16 以上。直接用apt install nodejs装出来的版本npm install阶段就会报一堆语法错误。正确做法是用版本管理工具。我推荐nvm理由是可以随时切版本不污染系统# 安装 nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 让当前 shell 生效 source ~/.bashrc # 装 Node 20 LTS nvm install 20 nvm use 20 nvm alias default 20 # 验证 node -v npm -v注意nvm装完后node命令只在交互式 shell 里可用。后面配 systemd 服务时必须写node的绝对路径否则服务启动会报command not found。这个坑我踩过排查了半小时。绝对路径一般是/root/.nvm/versions/node/v20.x.x/bin/node用which node确认。如果服务器访问外网受限nvm的安装脚本拉不下来那就手动下载 Node 二进制包解压一样能用wget https://nodejs.org/dist/v20.11.0/node-v20.11.0-linux-x64.tar.xz tar -xf node-v20.11.0-linux-x64.tar.xz sudo mv node-v20.11.0-linux-x64 /opt/node # 加到 PATH echo export PATH/opt/node/bin:$PATH ~/.bashrc source ~/.bashrc3. 源码获取与构建实操3.1 拉取源码与目录规划源码从项目仓库拉。这里有个习惯问题——我建议把应用统一放在/opt下而不是随手丢在/root或/home。原因是/opt是 Linux 约定的第三方应用目录权限清晰备份和迁移都方便。# 建目录 sudo mkdir -p /opt/deepseek-harness sudo chown -R $USER:$USER /opt/deepseek-harness # 拉源码 cd /opt/deepseek-harness git clone 项目仓库地址 . # 看下当前 commit记下来方便回滚 git log -1 --oneline提示如果仓库有多个分支先确认要部署哪个分支。生产环境建议用打了 tag 的 release 分支别直接上 mainmain 随时可能挂。3.2 依赖安装npm 与 pnpm 的取舍进到项目根目录先看package.json确认用哪个包管理器。有pnpm-lock.yaml就用 pnpm有yarn.lock就用 yarn只有package-lock.json就用 npm。# 如果用 pnpm npm install -g pnpm pnpm install # 如果用 npm npm installnpm install慢是常态尤其在国内网络下。换源能快不少npm config set registry https://registry.npmmirror.com如果安装过程中报node-gyp相关的编译错误八成是缺build-essential或 Python回头检查 2.2 节的依赖。实操心得npm install卡在某个包上超过 5 分钟先 CtrlC删掉node_modules和package-lock.json重来。有时候是网络抖动导致的半成品缓存重装比死等快。3.3 环境变量配置最容易出错的一步几乎所有这类项目都靠.env文件读配置。项目里一般有个.env.example复制一份改名cp .env.example .env vim .env关键配置项通常包括配置项作用典型值PORT服务监听端口3000HOST监听地址0.0.0.0API_KEY模型接口密钥你的密钥API_BASE_URL接口地址按服务商填DATABASE_URL数据库连接sqlite 或 postgres 连接串NODE_ENV运行环境production注意HOST一定要设成0.0.0.0不能是127.0.0.1。设成后者只有本机能访问远程访问会一直连不上而且报错很隐蔽——服务明明起来了就是外部访问不了。这个坑我见过太多人踩。.env文件权限也要收紧里面有密钥chmod 600 .env3.4 构建与首次启动配置好了就构建。前端项目一般有build脚本npm run build构建产物通常在dist或.next目录。构建完先手动启动一次确认能跑起来npm run start # 或者 node server.js看到类似Server listening on 0.0.0.0:3000的日志就说明起来了。这时候在服务器本机用curl测一下curl http://127.0.0.1:3000返回 HTML 就对了。如果报错看日志常见的是端口被占用、数据库连不上、密钥没配。4. 用 systemd 做进程守护与开机自启4.1 为什么必须用 systemd手动npm run start启动的服务一旦你关掉 SSH 窗口进程就跟着没了。这就是热词里说的让后台运行指令不因界面退出而退出。有人用nohup ... 能用但不够优雅——进程挂了不会自动重启开机也不会自启。systemd是 Linux 标准的服务管理器优势是开机自启、崩溃自动重启、日志统一管理、资源限制。生产环境就该用它。4.2 编写 service 文件在/etc/systemd/system/下建一个deepseek-harness.service[Unit] DescriptionDeepSeek Harness Web Service Afternetwork.target [Service] Typesimple Userroot WorkingDirectory/opt/deepseek-harness EnvironmentNODE_ENVproduction EnvironmentFile/opt/deepseek-harness/.env ExecStart/root/.nvm/versions/node/v20.11.0/bin/node /opt/deepseek-harness/server.js Restarton-failure RestartSec5 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target几个关键点解释一下ExecStart里的 node 路径必须是绝对路径原因前面说过systemd 不读你的.bashrc。EnvironmentFile把.env加载进来这样服务能读到配置。Restarton-failure表示进程异常退出时自动重启RestartSec5是重启前等 5 秒避免疯狂重启。WorkingDirectory很重要很多项目用相对路径读文件不设这个会找不到资源。4.3 启动、验证与日志查看# 重载 systemd 配置 sudo systemctl daemon-reload # 启动服务 sudo systemctl start deepseek-harness # 设置开机自启 sudo systemctl enable deepseek-harness # 看状态 sudo systemctl status deepseek-harness # 看实时日志 sudo journalctl -u deepseek-harness -f状态显示active (running)就成功了。如果显示failed用journalctl -u deepseek-harness -n 50看最近 50 行日志定位问题。实操心得改完 service 文件一定要daemon-reload否则 systemd 用的还是旧配置。这个我踩过改了ExecStart死活不生效折腾半天才发现忘了 reload。5. 远程访问的三种方案与安全加固5.1 方案对比直接暴露 vs 反向代理 vs 内网穿透服务在本机跑起来了怎么从外部访问三条路方案原理优点缺点适用场景直接暴露端口防火墙放行端口简单无加密、无认证内网测试反向代理Nginx 转发 HTTPS安全、可加认证配置稍复杂公网生产内网穿透中转服务无需公网 IP依赖第三方家庭/内网我一般推荐反向代理因为能顺便把 HTTPS、访问认证、限流都做了。下面重点讲这个。5.2 Nginx 反向代理配置先装 Nginxsudo apt install -y nginx建一个站点配置/etc/nginx/sites-available/deepseek-harnessserver { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; } }这里几个 header 是给 WebSocket 用的——AI 应用的流式输出很多走 WebSocket不配Upgrade和Connection流式响应会断。proxy_read_timeout调大是因为模型推理可能很慢默认 60 秒会超时。启用配置sudo ln -s /etc/nginx/sites-available/deepseek-harness /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx5.3 加一层访问认证公网暴露的服务不加认证等于裸奔。最简单的办法是 Nginx 的 Basic Auth# 装工具 sudo apt install -y apache2-utils # 生成密码文件 sudo htpasswd -c /etc/nginx/.htpasswd youruser然后在 Nginx 配置的location里加两行auth_basic Restricted; auth_basic_user_file /etc/nginx/.htpasswd;reload 之后访问就会弹用户名密码框。虽然简陋但挡住了绝大部分扫描。5.4 HTTPS用 Lets Encrypt 免费证书有域名的前提下用certbot一键签证书sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d your-domain.comcertbot会自动改 Nginx 配置、加证书、配自动续期。签完访问https://your-domain.com就是加密的了。注意certbot需要 80 端口能被外部访问到做验证。如果服务器前面还有一层防火墙或路由器先把 80 和 443 放行。5.5 防火墙配置不管用哪种方案防火墙都得配。ufw是最省心的sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable提示ufw enable之前一定先放行 22 端口否则 SSH 会被自己关在门外。这个错误犯一次就够记一辈子。6. 常见问题排查与避坑清单6.1 服务起不来从日志倒推服务启动失败90% 的问题能在日志里找到。排查顺序systemctl status看退出码和最后几行日志。journalctl -u 服务名 -n 100看完整日志。手动用ExecStart里的命令跑一遍看报错。常见错误对照表报错信息原因解决command not foundnode 路径不对用绝对路径EADDRINUSE端口被占用lsof -i:3000找进程杀掉Cannot find module依赖没装全重跑npm installENOENT .env工作目录不对检查WorkingDirectoryEACCES权限不足检查文件属主和权限connect ECONNREFUSED数据库/接口连不上检查地址和网络6.2 远程访问连不上分层排查外部访问不了别急着改代码按层排查服务层本机curl 127.0.0.1:3000通不通不通是服务问题。监听层ss -tlnp | grep 3000看监听地址是0.0.0.0还是127.0.0.1后者外部访问不了。防火墙层ufw status或iptables -L看端口放行没。代理层Nginx 配置对不对nginx -t过没过。网络层域名解析对不对ping和telnet测一下。一层层往下问题一定在某层暴露。6.3 内存不足与 OOM构建阶段或运行阶段被 OOM Killer 干掉日志里会有Killed字样。解决办法# 加 2GB swap sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 开机自动挂载 echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstabswap 是权宜之计长期还是加内存。另外可以在 service 文件里限制内存避免单个服务拖垮整机MemoryMax2G6.4 更新与回滚源码部署的好处就是更新方便cd /opt/deepseek-harness git pull npm install npm run build sudo systemctl restart deepseek-harness出问题要回滚用 git 切回旧 commitgit log --oneline git checkout 旧commit npm install npm run build sudo systemctl restart deepseek-harness实操心得每次更新前先git tag打个标记或者记下当前 commit。回滚的时候不用翻日志找。我一般还会把.env单独备份一份更新代码不会动它但手滑覆盖过。7. 性能调优与长期维护建议7.1 日志轮转别让日志撑爆磁盘systemd 的 journal 默认会一直涨。限制一下大小sudo vim /etc/systemd/journald.conf # 改这两行 SystemMaxUse500M MaxRetentionSec1month然后重启 journaldsudo systemctl restart systemd-journald7.2 资源监控心里有数装个htop看实时资源或者用systemd-cgtop看各服务的资源占用。长期跑的话建议配个简单的监控脚本定时记录 CPU、内存、磁盘出问题好回溯。7.3 备份策略要备份的东西就三样.env配置、数据库文件如果是 sqlite、上传的文件目录。写个 cron 定时打包# 每天凌晨 3 点备份 0 3 * * * tar -czf /backup/deepseek-$(date \%F).tar.gz /opt/deepseek-harness/.env /opt/deepseek-harness/data备份文件也要定期清理别把磁盘塞满。7.4 安全维护清单长期跑在公网的服务这几件事定期做系统补丁及时打apt update apt upgrade。密钥定期轮换别一个密钥用到底。看登录日志last和journalctl -u ssh发现异常登录及时处理。Nginx 和 Node 版本跟进安全公告。这套流程我从头跑过好几遍从裸机到能远程访问顺利的话一两个小时卡壳的话可能折腾一天。卡的地方基本都在环境依赖和 systemd 配置上把这两块吃透后面就顺了。源码部署最大的价值不是跑起来而是跑起来之后你知道每一环在哪、怎么改、坏了怎么修——这个掌控感是拉镜像给不了的。