用 systemd 托管小服务:自动重启、限制内存和基础沙箱加固

举报
yd_286747025 发表于 2026/11/05 12:13:33 2026/11/05
【摘要】 在 2核2G 的云服务器上跑自己的小应用,一开始我是 nohup node app.js & 挂着,结果 SSH 一断、进程一崩就得手动拉起。后来全部改成 systemd 托管,顺手加了内存上限和一些沙箱选项。这篇记录我的 unit 文件写法和踩过的坑。 一、新建专用用户不要用 root 跑应用。先建一个没有登录 shell 的用户:sudo useradd --system --creat...

在 2核2G 的云服务器上跑自己的小应用,一开始我是 nohup node app.js & 挂着,结果 SSH 一断、进程一崩就得手动拉起。后来全部改成 systemd 托管,顺手加了内存上限和一些沙箱选项。这篇记录我的 unit 文件写法和踩过的坑。

一、新建专用用户

不要用 root 跑应用。先建一个没有登录 shell 的用户:

sudo useradd --system --create-home --shell /usr/sbin/nologin appuser
sudo mkdir -p /opt/myapp && sudo chown -R appuser:appuser /opt/myapp

二、写 unit 文件

/etc/systemd/system/myapp.service:

[Unit]
Description=My App
After=network-online.target
Wants=network-online.target

[Service]
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/app.js
Environment=NODE_ENV=production
Restart=on-failure
RestartSec=3
MemoryHigh=700M
MemoryMax=900M
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/myapp/data

[Install]
WantedBy=multi-user.target

几个关键点:

  1. Restart=on-failure 只在异常退出时重启;如果用 always,你手动 stop 以外的正常退出也会被拉起,调试时容易困惑。
  2. MemoryHigh 是软限制,超过后内核会限速回收;MemoryMax 是硬限制,超过会被 OOM 杀掉。2G 机器上给应用设上限,可以避免它把 sshd 之类的挤死。
  3. ProtectSystem=strict 会把整个文件系统变成只读,只有 ReadWritePaths 列出的目录可写。应用要写日志或数据库,必须把目录加进去。

三、启用并查看

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f

四、踩坑

坑 1:改了 unit 文件没生效。每次修改后必须 daemon-reload,否则 systemctl 还在用旧配置,systemctl status 会提示 unit 文件已变更。

坑 2:开了 ProtectSystem=strict 后服务起不来,日志里是 EROFS(只读文件系统)或 EACCES。原因是应用要往目录里写文件,而该目录不在 ReadWritePaths 里。另外 ReadWritePaths 里的目录必须事先存在,否则会报 namespace 相关的错误(状态码 226/NAMESPACE)。先 mkdir 再启动即可。

坑 3:服务一直在重启。默认 5 次/10 秒内连续失败,systemd 会放弃并进入 failed 状态。用 systemctl reset-failed myapp 清除后再看 journalctl 找真正原因,别只盯着重启本身。

坑 4:想绑 80/443 这类低端口,但用了普通用户。可以加:

AmbientCapabilities=CAP_NET_BIND_SERVICE

或者更常见的做法,让应用监听高位端口,前面用 nginx 反代。

五、检查安全评分

systemd 自带一个评估工具:

systemd-analyze security myapp

它会按各项选项给出一个"暴露程度"评分。不用追求满分,很多选项会影响应用正常运行,我的做法是逐项加、加一项重启验证一项。

六、小结

用 systemd 托管小服务的收益很实在:开机自启、崩溃自动重启、日志统一进 journald、还能顺便限制资源。我的经验是先让服务正常跑起来,再逐步加 MemoryMax 和 ProtectSystem 这类限制,出问题时看 journalctl 通常一眼就能定位。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。