Running and Deploying Ruby on Rails apps on AlwaysData
AlwaysData is hands-down the greatest hosting provider I’ve worked with in almost two decades, while also being the cheapest, don’t ask me how they manage that feat! Here’s how to simplify Ruby version switching and Puma restarts for Ruby apps deployed with Capistrano.
Ruby version switching
AlwaysData provides almost every Ruby version precompiled, which is nice. They also provide Python, PHP, Node, Java, Elixir, and even .net and Deno! At the time of writing, the oldest Ruby version you can select is 1.8.7.
To change Ruby version globally, go to Environment then select either a major (which will automagically use the latest minor), or pin to a specific minor.
You can also choose a specific version to run for each web app, with the same major/minor mechanism.
If the version you want hasn’t been compiled, you can either compile it yourself, use rbenv, or rv. I trust that mise would work just as well.
Using .ruby-version
If you’d rather switch from the app itself, as is common, switch the app type from Ruby Rack to Custom program, then use the following command:
sh -c 'RUBY_VERSION="$(cat .ruby-version)" exec bundle exec puma --environment production'
Here’s what this command does:
- Spawn a shell to evaluate the next command
- Set
RUBY_VERSIONto the exact string found in.ruby-version - Tell our friend Bundler to use gem versions defined in
Gemfile.locklaunch Puma with Production environment
Restarting Puma after Capistrano deploy on AlwaysData
I wasn’t able to restart Puma using the capistrano-puma gem because it uses systemd, which isn’t available on AlwaysData for security reasons (on VPS plans).
There’s a simple way however: create an executable file which calls the AlwaysData API using curl, and execute it when deploying with Capistrano.
Create puma-restart
You’ll need two values from the AlwaysData admin panel:
- Account name: visible in the top-right menu
- API key: in Profile → Tokens
- SITE_ID: visible in the URL when editing your site, e.g.
https://admin.alwaysdata.com/site/123456/
Set API_KEY as an environment variable in website setup — do not hardcode it in the script.
cat << EOF > bin/puma-restart
#!/bin/bash
# Config
if [ -z "\${ALWAYSDATA_API_KEY}" ]; then
echo "Error: ALWAYSDATA_API_KEY environment variable is not set."
echo "Visit https://admin.alwaysdata.com/token/add/"
exit 1
fi
if [ -z "\${ALWAYSDATA_ACCOUNT_NAME}" ]; then
echo "Visit https://admin.alwaysdata.com/subscription/"
exit 1
fi
if [ -z "\${ALWAYSDATA_SITE_ID}" ]; then
echo "Visit https://admin.alwaysdata.com/site/"
exit 1
fi
# POST request
status=\$(curl \\
--user "\${ALWAYSDATA_API_KEY} account=\${ALWAYSDATA_ACCOUNT_NAME}:" \\
--data '' \\
--silent \\
--output /dev/null \\
--write-out '%{http_code}' \\
"https://api.alwaysdata.com/v1/site/\${ALWAYSDATA_SITE_ID}/restart/")
# Display confirmation
if [ "\$status" = 204 ];
then
echo "Application restarted"
else
echo "Application restart failed. Try using the admin panel:"
echo "https://admin.alwaysdata.com/site/\${ALWAYSDATA_SITE_ID}/"
exit 1
fi
EOF
# Make it executable
chmod +x bin/puma-restart
Now set the ALWAYSDATA_API_KEY, ALWAYSDATA_ACCOUNT_NAME and ALWAYSDATA_SITE_ID environment variables.
Add a deploy task
cat << EOF > lib/capistrano/tasks/deploy.rake
# frozen_string_literal: true
namespace :deploy do
desc "Restart the application"
task :restart do
on roles(:app) do
within current_path do
execute "bin/puma-restart"
end
end
end
# Restart Puma after deploy
after "deploy:finished", "deploy:restart"
desc "Prevent deploy if the server doesn't have the required Ruby version"
task :check_available_ruby do
on roles(:app) do
required_version = File.read(".ruby-version").strip
actual_version = capture("RUBY_VERSION=#{required_version} ruby --version 2>&1")
unless actual_version.include?(required_version)
error "Ruby #{required_version} is not available on the server."
error "Check available versions at https://admin.alwaysdata.com/environment/ruby/"
exit 1
end
end
end
before "deploy:starting", "deploy:check_available_ruby"
end
EOF
Commit everything
git add bin/puma-restart
git add tasks/capistrano/deploy.rake
git commit -m "Restart Puma after Capistrano deployments"
Conclusion
And there you have it, you can now deploy Rails apps on AlwaysData, confident that Ruby version will automatically be picked up on each deploy.