How to run Thruster and Kamal in Rails app
You may have heard of Thruster, the new no-config proxy from 37signals. Many Rails application developers already using Kamal are wondering if they need Thruster and how to integrate it into their existing Rails projects. This article addresses these questions and provides a detailed guide to using Thruster and Kamal in your Rails application.
Understanding Thruster and its benefits
Thruster, as a proxy for Puma, offers four key solutions: HTTP/2 support, HTTPS using Let's Encrypt, HTTP caching for public assets, and X-Sendfile support with compression. It was initially built for managing self-hosted products without needing Kamal. If you're using Rails with Kamal, managing TLS through Traefik or Cloudflare, and using CDNs for storage, you might not think you need Thruster. However, its X-Sendfile
support makes it still useful in this case.
How Thruster improves the delivery of application assets
When you use send_file
to send a file from Rails to a controller, an X-Sendfile
header is created. This header is handled by Rack::Sendfile
and is served by the proxy or Rack middleware, depending on the proxy. Here, Thruster steps in. It can take over the job of sending these files without any specific setup.
Integrating Thruster into your Rails project
Start by adding Thruster
as a gem to your Gemfile
as shown below:
# Gemfile
gem 'thruster', group: [:development, :production]
Then run the bundle install
command. Make sure that Thruster isn't scoped for development only, as the gem needs to be available in production.
Then edit your Rails Dockerfile
. We need to wrap Puma with the thrust command:
# Dockerfile - above rails 7
.....
# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
# Change Puma port to 3001 to keep Traefik default 3000 for Thruster
ENV HTTP_PORT="3000" \
TARGET_PORT="3001"
EXPOSE 3000
CMD ["bundle", "exec", "thrust", "./bin/rails", "server"]
With this configuration, you can set HTTP_PORT
for Thruster and keep Traefik port 3000
as default, while TARGET_PORT
is assigned to the Puma port. You now need to boot Puma on 3001
:
# config/puma.rb
...
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
port ENV.fetch('PORT') { 3001 }
Finally, update the position of arguments in bin/docker-entrypoint
:
#!/bin/bash -e
# If running the rails server then create or migrate existing database
if [ "${4}" == "./bin/rails" ] && [ "${5}" == "server" ]; then
./bin/rails db:prepare
fi
exec "${@}"
With these settings, Thruster will handle all requests for Puma.
Conclusion
Thruster, the no-config proxy from 37signals, offers several advantages as a proxy for Puma in your Rails projects. Even though we run Rails with Kamal, adding Thruster to the mix brings improvements, especially when serving application assets. This article provides a streamlined walk-through for setting up and running Thruster in your Rails projects.
Happy thrusting!