systemd
管理进程以 root 运行、只用来换版本,站点降到专用用户 nextskin 运行:站点被攻破也改不了程序目录,一键升级照样能用。前面的反向代理见反向代理与 HTTPS。
用系统级安装的 Node 26(发行版的包、NodeSource 或官方二进制)。装在某个用户家目录下的 Node(nvm 等),服务用户读不到。
sudo unzip nextskin-<版本>.zip -d /opt # 得到 /opt/nextskin,程序属于 rootsudo useradd --system --home-dir /opt/nextskin --shell /usr/sbin/nologin nextskinsudo install -d -o nextskin -g nextskin /opt/nextskin/datasudo sh -c 'umask 077; printf "NEXTSKIN_SECRET=%s\nNEXTSKIN_HOST=127.0.0.1\n" "$(openssl rand -hex 32)" > /opt/nextskin/.env'sudo chown nextskin:nextskin /opt/nextskin/.env # 备份这个文件程序目录(nextskin.mjs、manager/、releases/)属于 root,服务用户只读;只有 data/ 和 .env 属于它。.env 存在时必须带 NEXTSKIN_SECRET,否则启动以退出码 78 失败。
/etc/systemd/system/nextskin.service:
[Unit]Description=NextSkinAfter=network-online.targetWants=network-online.target# 数据库在同一台机器上时加上它,例如 After=mysql.service
[Service]# 管理进程以 root 运行(降权要 CAP_SETUID),拉起站点时降到 nextskin:# 站点被攻破也改不了程序目录,一键升级时管理进程照样能写 releases/Environment=NEXTSKIN_RUN_AS=nextskinWorkingDirectory=/opt/nextskin# node 的绝对路径:command -v nodeExecStart=/usr/bin/node /opt/nextskin/nextskin.mjs start# 只给管理进程发 SIGTERM,由它经 IPC 让启动器按顺序停核心和 plugin host;到时再强杀其余进程KillMode=mixed# 启动器最多等核心 30 秒TimeoutStopSec=40Restart=on-failure# 78 是配置错误,重启没用RestartPreventExitStatus=78
[Install]WantedBy=multi-user.targetsudo systemctl daemon-reloadsudo systemctl enable --now nextskinjournalctl -u nextskin -fsudo cat /opt/nextskin/data/setup-code然后经反向代理打开 https://<域名>/setup 建站。
不想让 root 常驻:去掉 Environment=NEXTSKIN_RUN_AS=…,加上 User=nextskin、Group=nextskin。这时管理进程写不了 releases/,后台只检测新版本、不能一键升级,升级照下面的“手动升级”。
日常命令用服务用户运行,否则数据目录里会出现服务读写不了的文件:
sudo -u nextskin node /opt/nextskin/nextskin.mjs doctor一键升级之后、重启服务之前,这样运行的命令会先打一行“没有换上新管理进程,继续使用旧版:EACCES”。新的管理进程放在 manager.next/,要等服务下次以 root 启动时换上,服务用户换不了。命令照常执行,sudo systemctl restart nextskin 一次之后就不再出现。
update、rollback 要读 root 的令牌、写 releases/,用 root 运行。服务停着时它们自己跑迁移,单元文件里的环境变量带不过来,要自己给上:
sudo node /opt/nextskin/nextskin.mjs update statussudo NEXTSKIN_RUN_AS=nextskin node /opt/nextskin/nextskin.mjs update --yes # 服务停着时以 root 运行而没给 NEXTSKIN_RUN_AS 时,服务停着的 update、rollback 发现数据目录属于别的用户就拒绝(退出码 78):root 跑的迁移会在 data/ 里留下服务读写不了的文件。
一键升级:后台“更新”页,或者 sudo node /opt/nextskin/nextskin.mjs update,见升级与回退。
手动升级:
sudo systemctl stop nextskin# 备份 /opt/nextskin/data 和 /opt/nextskin/.envsudo unzip -o nextskin-<新版本>.zip -d /opt # 不会覆盖 .env 和 data/sudo systemctl start nextskin从 0.4 及更早的版本升级时,旧单元文件里的 User=nextskin 要换成上面的 Environment=NEXTSKIN_RUN_AS=nextskin(sudo systemctl edit --full nextskin,再 daemon-reload);不换也能运行,只是不能一键升级。