Buffalo 生产服务需用 buffalo build 生成前台运行二进制,配合 systemd service 文件(Type=simple、Restart=on-failure、正确 WorkingDirectory 和 Environment),并确保权限、路径、SELinux 等环境就绪。

Buffalo 二进制如何被 systemd 正确识别为长期服务
Buffalo 默认生成的是开发模式的 Web 服务(buffalo dev),它会监听文件变化、自动重启、输出彩色日志——这些行为和 systemd 的守护进程模型冲突。systemd 要求主进程是前台运行、不 daemonize、退出即代表服务终止。所以不能直接用 buffalo dev,必须用构建后的生产二进制(如 ./myapp)并确保它以阻塞方式运行 HTTP 服务。
常见错误现象:systemctl status myapp 显示 active (exited) 或反复重启;journal 日志里出现 fork: Resource temporarily unavailable 或 failed to start process: exec format error。
- 先执行
buffalo build -o ./myapp生成静态二进制(注意:不是buffalo build --static,那个是嵌入 assets 的选项,非必需) - 确认二进制可执行:
chmod +x ./myapp,并在命令行手动运行一次,看是否能稳定监听:3000并响应 HTTP 请求 - 确保
GOOS=linux GOARCH=amd64 buffalo build(若在 macOS/Windows 构建)——交叉编译时遗漏目标平台会导致exec format error - 避免在代码中调用
os.Exit(0)或 panic 后未捕获,systemd 会把非零退出码视为故障
systemd service 文件的关键配置项
创建 /etc/systemd/system/myapp.service,核心在于让 systemd 知道如何启动、何时认为服务“就绪”、以及如何管理生命周期。默认的 Type=simple 就够用,但必须配好 Restart 和 RestartSec,否则崩溃后不会自愈。
示例最小可用配置:
[Unit] Description=My Buffalo App After=network.target [Service] Type=simple User=www-data WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/myapp Restart=on-failure RestartSec=5 Environment=GO_ENV=production Environment=ADDR=:8080 [Install] WantedBy=multi-user.target
-
WorkingDirectory必须设,否则 Buffalo 可能找不到public/或templates/目录 -
Environment用于覆盖GO_ENV和监听地址;Buffalo 会读取ADDR环境变量,比硬编码端口更安全 - 不要加
PrivateTmp=yes或NoNewPrivileges=yes(除非明确需要沙箱),它们可能干扰 Buffalo 的 asset 加载或日志写入 - 如果应用依赖数据库,应在
After=中加入postgresql.service或对应服务名,并加Wants=声明强依赖
权限与路径问题最容易被忽略
Buffalo 应用常需读取静态资源、写入日志、连接数据库 socket,而 systemd 默认以最小权限运行服务。若没设对用户、目录所有权或 SELinux 上下文,systemctl start myapp 会静默失败或报 permission denied。
- 用
chown -R www-data:www-data /opt/myapp确保服务用户有全部读+执行权(二进制需x,模板和 public 需r) - 日志目录(如
/var/log/myapp)要提前创建并授权:mkdir -p /var/log/myapp && chown www-data:www-data /var/log/myapp - 若用 SQLite,数据库文件路径必须可写;若用 PostgreSQL,确认
pg_hba.conf允许127.0.0.1的md5认证 - 在 CentOS/RHEL 上启用 SELinux 时,需运行
setsebool -P httpd_can_network_connect 1,否则 outbound DB 连接被拦截
调试 systemctl 启动失败的三步法
别急着改 service 文件——先确认问题是出在 Buffalo 本身,还是 systemd 环境。最有效的排查顺序是固定变量、逐层验证。
- 用
sudo -u www-data /opt/myapp/myapp手动模拟 systemd 用户身份运行,看是否立即 panic 或报错 - 临时删掉
Restart=行,然后systemctl start myapp && journalctl -u myapp -f实时盯日志,重点搜panic:、listen tcp、no such file - 检查
systemctl show myapp | grep -E "(ExecStart|Environment|WorkingDirectory)",确认实际加载的值和你写的 .service 文件一致(比如有没有被 drop-in 覆盖)
真正麻烦的永远不是配置语法,而是 Buffalo 在 systemd 环境下读不到 .env、连不上 /run/postgresql/.s.PGSQL.5432、或因 umask 0022 导致生成的 session key 权限太松被拒绝——这些细节得一条条对着日志扣。











