Deploy a Ruby on Rails app

Deploy a Rails app on Hangar with the Dockerfile Rails generates, a managed PostgreSQL database, migrations on release and HTTPS on your domain.

Updated

Rails 7.1 and later ship a production-ready Dockerfile in every new app. Hangar builds that file directly, so there is nothing to translate: the image you would build locally is the image that runs.

Before you start

  • A Rails app in a Git repository, with the generated Dockerfile and bin/docker-entrypoint. For an app created before Rails 7.1, run bin/rails app:update or use the automatic builder.
  • The contents of config/master.key.
  • A Hangar account.

1. Create the database

In a new project, add a PostgreSQL service and pick a region. Open it and copy the internal connection URL.

2. Create the Rails service

Add a service from your repository in the same region. In its Settings → Source choose Dockerfile; the default path, Dockerfile, is the one Rails generates.

3. Set the variables

RAILS_MASTER_KEY=<contents of config/master.key>
DATABASE_URL=<the internal connection URL>

Rails reads DATABASE_URL on its own and merges it over config/database.yml.

4. Trust the proxy

Hangar terminates TLS and forwards requests to your app over HTTP. Tell Rails so it does not redirect in a loop:

# config/environments/production.rb
config.assume_ssl = true
config.force_ssl = true

5. Deploy and add a domain

Deploy the service. The generated entrypoint runs db:prepare, which creates the schema on the first deploy and migrates it on later ones.

In Settings → Networking, add your hostname, turn HTTPS on and set the container port to the port in your Dockerfile's EXPOSE line: 80 for the Rails 8 Dockerfile, which starts the app behind Thruster, and 3000 for Rails 7.1 and 7.2.

Background jobs

Run Sidekiq, Solid Queue or another worker as a second service from the same repository, with the same variables and a different start command:

bundle exec sidekiq

Sidekiq needs Redis: add a Redis database to the project and set REDIS_URL. Share DATABASE_URL and REDIS_URL as environment variables referenced by both services, as described in Environment variables.

Uploaded files

A container's filesystem is replaced on every deploy. Store Active Storage uploads in S3-compatible object storage, or attach a volume to the service if you keep them on disk.

Troubleshooting

  • Missing secret_key_base or ActiveSupport::MessageEncryptor::InvalidMessage: RAILS_MASTER_KEY is missing or does not match the credentials file.
  • Too many redirects: config.assume_ssl is not set.
  • 502 on the domain: the container port does not match the EXPOSE line of the Dockerfile.

Frequently asked questions

Do I need to write a Dockerfile to deploy Rails on Hangar?
No. Rails 7.1 and later generate a production Dockerfile with every new app, and Hangar builds it as it is. Older apps can use the automatic builder or the Heroku buildpacks builder instead.
How do Rails migrations run on Hangar?
The entrypoint Rails generates runs db:prepare before the server starts, so every deploy migrates the database first. If your app has no such entrypoint, put bin/rails db:prepare in the start command.
Where do I put the Rails master key?
Set RAILS_MASTER_KEY as an environment variable of the service, with the contents of config/master.key. The key file itself stays out of the repository.

Deploy your app on Hangar

Connect a repository and it is live in minutes.

Start deploying