A deployment-ready Rails 7 (Ruby 3.3.4) backend with React, TailwindCSS, and other goodies.
Run bin/boil
and follow the instructions. You'll need a Hetzner Cloud account, a Cloudflare account, a Docker Hub account, and a GitHub account.
Start the application with bin/dev
. Stop it with Ctrl+C
followed by bin/stop
.
You can also run the application using
docker-compose up
to mimic production.
bin/dev
uses foreman
to start the application using the Procfile.dev
, with the following processes:
web
: the Rails server (with debugging enabled).js
: usesyarn
to build JavaScript files (such as React components). Auto-rebuilds on file changes.css
: Uses yarn to build CSS files. Auto-rebuilds on file changes.redis
: Starts a Redis server for storing background jobs.sidekiq
: Starts a Sidekiq worker for processing background jobs.
In production, the
web
process and theredis
andsidekiq
processes (for background jobs) live on aweb
server and anaccessory
server, respectively.
Run super-fast tests with bin/test (thing you want to test)
.
- End-to-end/system tests run in a headless browser with
bin/test spec/system
. - Unit tests run with
bin/test spec/<unit-you-want-to-test>_spec.rb
.
Other testing things:
- Fixtures are managed using FactoryBot, and you can find them in the
/factories
directory.
Deployment is handled automatically when you merge using git. Boiler apps have both staging
and main
branches, which correspond to the environment that is provisioned for each.
- When you create a Pull Request from any branch to
staging
, a preview environment is provisioned, deployed to, and tested. - When you merge to
staging
, a staging environment is (re-)provisioned, and deployed to. - When you merge to
main
, a production environment is (re-)provisioned, and deployed to.
To enable this delicious workflow, you need to:
- Add a
HETZNER_API_KEY
for a Hetzner Cloud project,CLOUDFLARE_API_TOKEN
with read and modify zone permissions, Docker HubREGISTRY_PASSWORD
andGITHUB_USERNAME
to .env. - If you want, update the required infrastructure in infrastructure.yml.
You're good to go!
As a fallback, run
bin/teardown
to tear down all provisioned infrastructure. This is permanent!
Here's each of the deployment stages in more detail:
The preview workflow is triggered by a Pull Request from your-branch
to staging
. It uses a Github Action to:
- Provision a new minimum setup of infrastructure as defined in
infrastructure.yml
(by default that's two servers (oneweb
for Rails and Sidekiq, anotheraccessories
for Redis and Postgres), a load balancer, a firewall, and a Cloudflare subdomain.) - Rebuild the Docker images and push them to Docker Hub with the tag
your-app:preview-<branch-number>
. - Deploy the app to this preview environment using Kamal.
- Run the tests and report the results in the Pull Request.
You can visit your preview environment at
https://preview-<branch-number>.yourdomain.com
.
The staging workflow is triggered by merging your preview Pull Request into staging
. It uses a Github Action to:
- Ensure staging environment infrastructure exists as defined in
infrastructure.yml
. - Rebuild the Docker images and push them to Docker Hub with the tag
your-app:staging-<branch-number>
. - Deploy the app to this staging environment using Kamal.
You can visit your staging environment at
https://staging.yourdomain.com
.
The production workflow is triggered by merging staging
into main
. It uses a Github Action to:
- Ensures production environment infrastructure exists as defined in
infrastructure.yml
. - Rebuilds the Docker images and pushes them to Docker Hub with the tag
your-app:latest
. - Deploys the app to this production environment using Kamal.
- Get an account on Google Cloud.
- Create a new project.
- Create new OAuth client ID and secret for your project.
i. For the authorised JavaScript origins, add
https://localhost:3000
and your production URL. ii. For the authorised redirect URIs, addhttps://localhost:3000/users/auth/google_oauth2/callback
andhttps://<your-domain>/users/auth/google_oauth2/callback
. - Set the following environment variables:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
Google login will appear automatically in the combined login/# page.
For other OAuth2 providers, set the environment variables as in the register or # view.
Use rails c
to create an admin user:
User.create!(email: "admin@example.com", password: "password", admin: true)
Boiler uses sidekiq-cron to run cron jobs. cron jobs are defined in config/schedule.yml
. sidekiq-cron is smart enough to only schedule jobs if they are not already scheduled (even across multiple instances of sidekiq).
Boiler uses pghero for database analytics. To access the pghero interface, go to /pghero
(e.g. https://techmap.app/pghero
). You need to be an admin user to access this page.
Boiler's puma webserver is designed to be run with SSL (even locally). If you need to regenerate an SSL certificate for local development, you can do it like this: openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 365 -keyout config/development-ssl/localhost.key -out config/development-ssl/localhost.crt
.
Postgres is used for the database. You can connect to the database using the psql
command-line tool. For example: psql -d boiler_development
.
Redis and Sidekiq are used for background jobs. Redis is used for job queuing, and Sidekiq is used to run jobs.
By default, Sidekiq runs on localhost:6379
and Redis runs on localhost:6379/12
.