Capistrano部署时启动Puma服务报错:puma_app_production.service存在单元文件配置问题
Let’s figure out why you’re hitting this systemd unit file error when launching Puma through Capistrano, even though manual starts work perfectly. Systemd is strict about syntax and environment setup, so small inconsistencies here are almost always the culprit. Here’s how to diagnose and fix this:
1. First, pinpoint the exact unit file error
Systemd’s error message is vague, but we can get specifics with this command (run it as root on your server):
systemd-analyze verify puma_app_production.service
This will flag exactly where the unit file is failing—whether it’s a syntax issue, invalid path, or environment variable misconfiguration. This should be your first step; it’ll save you guessing.
2. Fix the ExecStart environment variable syntax
Your current ExecStart line includes environment variable assignments upfront (RBENV_ROOT=... RBENV_VERSION=...), which works in a shell but doesn’t follow systemd’s syntax rules. Systemd expects environment variables to be defined with the Environment= directive instead of inline in ExecStart.
Update your puma_app_production.service file’s [Service] block like this:
[Service] Type=simple User=rails_api WorkingDirectory=/home/rails_api/apps/app/current # Define rbenv environment variables properly for systemd Environment=RBENV_ROOT=/home/rails_api/.rbenv Environment=RBENV_VERSION=3.0.2 # Support older bundler versions where file descriptors weren't kept ExecStart=/home/rails_api/.rbenv/bin/rbenv exec bundle exec --keep-file-descriptors puma -C /home/rails_api/apps/app/shared/puma.rb ExecReload=/bin/kill -USR1 $MAINPID StandardOutput=append:/home/rails_api/apps/app/current/log/puma.access.log StandardError=append:/home/rails_api/apps/app/current/log/puma.error.log Restart=always RestartSec=1 SyslogIdentifier=puma
This aligns with systemd’s requirements and ensures the environment variables are properly loaded when the service starts.
3. Ensure Capistrano isn’t conflicting with your custom unit file
If you’re using the capistrano-puma gem, it might be auto-generating a systemd unit file that overrides your custom one. To prevent this:
- In your
deploy.rb, explicitly set the service unit name to match your custom file:set :puma_service_unit_name, 'puma_app_production.service' - Double-check that Capistrano isn’t overwriting your unit file during deployments. If you’ve defined a custom template for the service file, make sure it includes the corrected environment variable setup from step 2.
4. Validate paths and permissions
Even if syntax is correct, systemd might fail if it can’t access files or execute commands:
- Verify the
WorkingDirectorypath exists and is owned byrails_api:ls -ld /home/rails_api/apps/app/current - Ensure the unit file itself has correct permissions (should be owned by root, mode 644):
sudo chmod 644 /etc/systemd/system/puma_app_production.service sudo chown root:root /etc/systemd/system/puma_app_production.service - Test the
ExecStartcommand directly as therails_apiuser to confirm it works outside systemd:su - rails_api -c "RBENV_ROOT=/home/rails_api/.rbenv RBENV_VERSION=3.0.2 /home/rails_api/.rbenv/bin/rbenv exec bundle exec puma -C /home/rails_api/apps/app/shared/puma.rb -V"
If this command fails, it means there’s an issue with rbenv, bundler, or Puma configuration—fix that first before troubleshooting systemd.
5. Double-check your Capistrano rbenv setup
You already added append :rbenv_map_bins, 'puma', 'pumactl' which is correct, but make sure:
- The
capistrano-rbenvgem is in yourGemfileand loaded indeploy.rb(viarequire 'capistrano/rbenv'). - Your Capistrano deploy runs as the
rails_apiuser, so it inherits the correct rbenv environment during setup.
After making changes to the unit file, reload systemd to pick up the updates:
sudo systemctl daemon-reload
Then try restarting the service via Capistrano or directly with sudo systemctl restart puma_app_production.service.
内容的提问来源于stack exchange,提问作者John McMuffin

