Solved - Puma server on dreamhost systemd service problems

dreamhost is ending passenger support so I setup a proxy server on the target subdomain and installed rvm, 3.2.2 and rails per their instructions in the ssh user home. uploaded the rails app and the puma server runs and serves (although its not finding the css) when called from inside the subdomain. But launching the systemd puma.service (also setup per the dreamhost docs) fails. I don’t understand the error message. here is a screenshot - first the call puma server and then call the systemd puma.service - where do I start to look or can someone here already see what the issue might be? thank you.

I’ve been stumbling through this, and I feel I’m 90% there. When I started the service I would check the status and would get
(code=exited, status=203/EXEC)
I have submitted a help ticket. If you get it to work I would like to compare notes,

1 Like
[vpsXXXX]$ puma -e production
Puma starting in single mode...
* Version 3.12.4 (ruby 2.7.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: production

[!] There was an error parsing `Gemfile`: `windows` is not a valid platform. The available options are: [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :ruby_26, :mri, :mri_18, :mri_19, :mri_20, :mri_21, :mri_22, :mri_23, :mri_24, :mri_25, :mri_26, :rbx, :truffleruby, :jruby, :jruby_18, :jruby_19, :mswin, :mswin_18, :mswin_19, :mswin_20, :mswin_21, :mswin_22, :mswin_23, :mswin_24, :mswin_25, :mswin_26, :mswin64, :mswin64_19, :mswin64_20, :mswin64_21, :mswin64_22, :mswin64_23, :mswin64_24, :mswin64_25, :mswin64_26, :mingw, :mingw_18, :mingw_19, :mingw_20, :mingw_21, :mingw_22, :mingw_23, :mingw_24, :mingw_25, :mingw_26, :x64_mingw, :x64_mingw_20, :x64_mingw_21, :x64_mingw_22, :x64_mingw_23, :x64_mingw_24, :x64_mingw_25, :x64_mingw_26]. Bundler cannot continue.

 #  from /home/<username>/<app_name>/releases/20240508195934/Gemfile:39
 #  -------------------------------------------
 #  # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
 >  gem "tzinfo-data", platforms: %i[ windows jruby ]
 #  
 #  -------------------------------------------

! Unable to load application: SystemExit: exit
[vpsXXXX]$ bin/rails server
=> Booting Puma
=> Rails 7.1.3.2 application starting in development 
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.2 (ruby 3.3.1-p55) ("The Eagle of Durango")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 205862
* Listening on http://127.0.0.1:8003
* Listening on http://[::1]:8003
Use Ctrl-C to stop
^C- Gracefully stopping, waiting for requests to finish
=== puma shutdown: 2024-05-09 12:58:03 -0700 ===
- Goodbye!
Exiting

For the parsing error, I found this worked. https://stackoverflow.com/questions/77895836/there-was-an-error-parsing-gemfile-windows-is-not-a-valid-platform

Switch that line in the Gemfile to: gem “tzinfo-data”, platforms: %i[mswin mswin64 mingw x64_mingw jruby ] (Note: you will have to update the line for gem “debug” as well if your dokku deployment is running in development or test environment)

But I still had an issue.

[vpsXXXX]$ puma -e production
Puma starting in single mode...
* Version 3.12.4 (ruby 2.7.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: production
Your Ruby version is 2.7.0, but your Gemfile specified 3.3.1
! Unable to load application: SystemExit: exit
[vpsXXXX]$ ruby -v
ruby 3.3.1 (2024-04-23 revision c56cd86388) [x86_64-linux]
[vpsXXXX]$ bundle exec puma -e production
Puma starting in single mode...

Running this would start the site:

[vpsXXXX]$ bundle exec puma -e production
Puma starting in single mode...
* Puma version: 6.4.2 (ruby 3.3.1-p55) ("The Eagle of Durango")
*  Min threads: 5
*  Max threads: 5
*  Environment: production
*          PID: 206405
/home/<username>/<app_name>/shared/bundle/ruby/3.3.0/gems/bootsnap-1.18.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30: warning: /home/<username>/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/csv.rb was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add csv to your Gemfile or gemspec.
* Listening on http://0.0.0.0:8003
Use Ctrl-C to stop
I, [2024-05-09T13:07:51.595448 #206405]  INFO -- : [b9d096a0-d809-49fb-94ca-685dc09d44b2] Started GET "/login" for xxx.xxx.xxx.xxx at 2024-05-09 13:07:51 -0700
I, [2024-05-09T13:07:51.598996 #206405]  INFO -- : [b9d096a0-d809-49fb-94ca-685dc09d44b2] Processing by SessionController#new as HTML
D, [2024-05-09T13:07:51.600092 #206405] DEBUG -- : [b9d096a0-d809-49fb-94ca-685dc09d44b2] 
D, [2024-05-09T13:07:51.600232 #206405] DEBUG -- : [b9d096a0-d809-49fb-94ca-685dc09d44b2] ==> where am I? session | new
D, [2024-05-09T13:07:51.600272 #206405] DEBUG -- : [b9d096a0-d809-49fb-94ca-685dc09d44b2] 
D, [2024-05-09T13:07:51.605071 #206405] DEBUG -- : [b9d096a0-d809-49fb-94ca-685dc09d44b2]   Rendering layout layouts/application.html.erb

That’s where I’m at with this, and I’ve passed it on to Dreamhost. :crossed_fingers:

so you installed 3.3.1 ruby with rvm on the server? and why is it running in development - RAILS_ENV=production bin/rails server

oh, it works - let me know what they say

I have 3.3.1 on the server, and it is set to the default vis RVM. No idea why

puma -e production

pulls Ruby 2.7.

I filed a ticket too, its been moved to a specific tech support team member and I am waiting for news. Have your heard from them yet?

I wasn’t pointing to a Puma file. :person_shrugging: I went into the app’s current folder and installed the gem. Now I have

[vpsXXXXX]$ cd /home/<user-name>/<site-name>/current
[vpsXXXXX]$ which puma
/home/<user-name>/.rvm/gems/ruby-3.3.1@<gemset-name>/bin/puma
[vpsXXXXX]$ cd ~
[vpsXXXXX]$ which puma
/home/<user-name>/.rvm/gems/ruby-3.2.2/bin/puma

I updated the puma.service to point to it.

...
WorkingDirectory=/home/<user-name>/<site-name>/current
ExecStart=/home/<user-name>/.rvm/gems/ruby-3.3.1@<gemset-name>/bin/puma -C
...

I tried to start it, and it still fails Then I ran

journalctl --user -u puma.service -b
...
May 14 07:36:19 vps34323 systemd[118381]: puma.service: Start request repeated too quickly.
May 14 07:36:19 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:36:19 vps34323 systemd[118381]: Failed to start Puma instance to serve application.
May 14 07:40:08 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:40:08 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:40:08 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:40:08 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:40:09 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:40:09 vps34323 systemd[118381]: puma.service: Start request repeated too quickly.
May 14 07:40:09 vps34323 systemd[118381]: puma.service: Failed with result 'exit-code'.
May 14 07:40:09 vps34323 systemd[118381]: Failed to start Puma instance to serve application.

I’m lost

1 Like

me too - same journal - but I have

WorkingDirectory=/home/<user-name>/<site-name>
ExecStart=/home/<user-name>/.rvm/gems/ruby-3.2.2@<gemset-name>/bin/puma -C config/puma.rb -e production

I don’t have a current folder … and fwiw in the journal my systemd numbers keep changing

dreamhost support came back saying they can’t really help with the issue. then I went and talked to chatgpt. It took a while but it told me to put a wrapperscript.sh somewhere and make that the target of ExecStart= and it works it seems - server is running and I am logged out.

#!/bin/bash
source $HOME/.rvm/scripts/rvm  # Load RVM
rvm use ruby-3.2.2@<gemsetname> > /dev/null 2>&1  # Use the correct RVM and silence output
export PATH=$(rvm env --path -- ruby-3.2.2@<gemsetname>)/bin:$PATH  # Set PATH directly from RVM

cd /home/username/sitename  # Change to the app directory
exec bundle exec puma -C config/puma.rb -e production  # Start Puma

well its not solved. it will not find the assets and now after trying to fix that I broke the whole thing again - Service unavailable 503 - and the apache error log says:

proxy_http error (111) connection refused …

I am lost too

@john_ivanoff did you manage to solve it? I went and built this little DHH blog comments app and went through the setup process again and documented it. It failed again with the default ExecStart line from the dreamhost guide (puma.service) but it works if I use the wrapper_script.sh chatgpt made me from above (^). I used rvm local and ruby 3.0.6 with rails 7.1.3.3 and I am going to rebuild the rails app I want to deploy and use the same sequence to upload it to dreamhost.

Since this is a side project, I haven’t returned to it. I’ll try what you did. It’s frustrating when the How-Tos don’t work, and the replies are mostly regurgitated from the How-Tos. I’ve provided copious notes for them to be able to reproduce. This is the first time I have had an issue with support. I’ll let you know how it turns out.

Good luck sailor. Here is what I did for the record:

I setup a subdomain blog.example.com

I added lets encrypt cert

In the dreamhost panel I setup the proxy for:

http://blog.example.com to 9006 leaving the path empty (whole subdomain)

locally I made the rails app with rvm setting ruby 3.0.6 and rails 7.1.3.3

on the server I installed rvm in the user dir and also installed ruby 3.0.6 and 7.1.3.3 (with rvm autolibs disable)

I also setup ssh keys for passwordless access

in the User dir I created .config/systemd/user/puma.service

I entered exactly what was in the dreamhost guide into puma.service

[Unit]
Description=Puma instance to serve application
After=network.target

[Service]
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/app/bin/puma -C config/puma.rb -e production
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
Restart=on-failure

[Install]
WantedBy=default.target

and then I changed

ExecStart=/path/to/your/app/bin/puma -C config/puma.rb -e production

to

ExecStart=/home/dreamhostuser/.config/wrapper_script.sh

here is the wrapper_script.sh in .config/

#!/bin/bash
source $HOME/.rvm/scripts/rvm  # Load RVM
rvm use ruby-3.0.6@rails7133 > /dev/null 2>&1  # Use the correct RVM and silence output
export PATH=$(rvm env --path -- ruby-3.0.6@rails7133)/bin:$PATH  # Set PATH directly from RVM

cd /home/dreamhostuser/blog.example.com  # Change to the app directory
exec bundle exec puma -C config/puma.rb -e production  # Start Puma

in the puma.rb file I added or adapted:

port ENV.fetch("PORT") { 9006 }

I followed the DHH demo blog tutorial until the mailer thing after the comments thing and ran the precompile and build for production locally.

then I uploaded it with:

rsync -avz --delete --exclude='/.git/' --exclude='/log/*' --exclude='/tmp/*' /Users/localuser/blog.example.local/ dreamhostuser@example.com:blog.example.com

On the server in the blog.example.com dir I ran

bundle install --deployment --without development test

RAILS_ENV=production bin/rails assets:precompile

In the dreamhostuser dir I ran

systemctl --user enable puma.service

loginctl enable-linger

to check:

rvm autolibs status

loginctl show-user $USER --property=Linger

and then finally:

systemctl --user daemon-reload

systemctl --user start puma.service

systemctl --user status puma.service

which should show something like:

● puma.service - Puma instance to serve application
     Loaded: loaded (/home/dreamhostuser/.config/systemd/user/puma.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2024-05-23 07:05:43 PDT; 1 day 15h ago
   Main PID: 0101 (ruby)
      Tasks: 12 (limit: 115199)
     Memory: 141.1M
        CPU: 22.225s
     CGroup: /user.slice/user-1234567.slice/user@1234567.service/puma.service
             └─0101 puma 6.4.2 (tcp://0.0.0.0:9006) [blog.example.com]

After adding the log output to see what was happening, I was getting an error about ruby_executable_hooks, which led me to use wrappers in the path instead of bin.

[Unit]
Description=Puma instance to serve application
After=network.target

[Service]
WorkingDirectory=/home/<user>/path/to/app
ExecStart=/home/<user>/.rvm/gems/ruby-2.7.8/wrappers/puma exec puma -C config/puma.rb -e production
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
Restart=on-failure
StandardOutput=append:/home/<user>/<app>/current/log/puma_access.log
StandardError=append:/home/<user>/<app>/current/log/puma_error.log
SyslogIdentifier=<app>-puma-production

[Install]
WantedBy=default.target
2 Likes

@coneybeare Is that Capistrano? because I don’t have the current folder. Dreamhost answered yesterday and they are still looking into it but they said they had reports of customers having to install puma in the app and not in the userdir .config folder. But I don’t have puma installed in the app or the .config folder - I have one puma 6.4.2 installed in .rvm 3.2.2 ruby from before but the app now running uses 3.0.6 ruby … and reports puma 3.12.4 which is the dreamhost default. And the Gemfile says gem “puma”, “>=5.0” …

Sorry for the late reply. I did hear back from Dreamhost, and they got it working.

short answer in the ~/.config/systemd/user/puma.service file

ExecStart=/home/<username>/.rvm/gems/ruby-3.3.1@<app_name>/bin/puma -C config/puma.rb -e production

was changed to

ExecStart=/bin/bash -lc '/home/<username>/.rvm/gems/ruby-3.3.1@<app_name>/bin/puma -C config/puma.rb -e production'

then ran the following commands

systemctl --user enable puma
systemctl --user start puma
systemctl --user status puma

It’s up and running, and I have redeployed, and it’s still running. :tada:

1 Like

Did anyone work out how to get assets working? After setting up the Proxy, disabling Passenger and using wrappers as the path to the puma binary, I have a site back up and running. However assets aren’t working.

The Proxy instructions indicate you may need to set up a sub domain, but there is not really any further information. I set up a subdomain that mirrors the main domain (I don’t want a new VPS) and pointed asset_host to it in production.rb… but that doesn’t seem to help.

Anyone know how to solve this?

It’s super simple: