This guide covers deploying the app to Coolify as 4 resources: main (web), worker (Solid Queue), PostgreSQL, and Redis.
- A Coolify instance (self-hosted or cloud)
- Your repository connected to Coolify via GitHub
- Go to your Coolify project and click New Resource > Database > PostgreSQL
- Note the internal connection URL (e.g.
postgresql://postgres:password@project-db:5432/app)
- Click New Resource > Database > Redis
- Note the internal connection URL (e.g.
redis://default:password@project-redis:6379)
- Click New Resource > Application
- Select your GitHub repository and branch
- Set Build Pack to Dockerfile
- Set Dockerfile Location to
Dockerfile - Set the Exposed Port to
80 - Configure the health check to hit
/upon port80
This builds with Dockerfile and runs Thruster + Rails server.
- Click New Resource > Application
- Select the same GitHub repository and branch
- Set Build Pack to Dockerfile
- Set Dockerfile Location to
Dockerfile.worker - Do not expose a port — the worker doesn't serve HTTP
- Disable the health check (the worker is a background process, not a web server)
The worker builds with Dockerfile.worker and runs Solid Queue (bin/jobs) to process background jobs.
If you haven't already, delete the template's placeholder credentials and generate fresh ones:
rm config/credentials.yml.enc
bin/rails credentials:editGenerate Active Record encryption keys and paste them into the credentials file:
bin/rails db:encryption:initCopy the output into your credentials file so it looks like:
active_record_encryption:
primary_key: <generated>
deterministic_key: <generated>
key_derivation_salt: <generated>The encrypted credentials file (config/credentials.yml.enc) is committed to the repo; the master key (config/master.key) is not — you'll set it as an environment variable in the next step.
Add the following environment variables to both the main and worker applications. Refer to .env.production.example for the full list.
Do not set SOLID_QUEUE_IN_PUMA — the worker container handles job processing separately.
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection URL from step 1 |
REDIS_URL |
Redis connection URL from step 1 |
RAILS_MASTER_KEY |
Contents of config/master.key |
SECRET_KEY_BASE |
Run bin/rails secret locally to generate |
APP_HOST |
Your app's domain (e.g. app.example.com) |
| Variable | Description |
|---|---|
HCA_CLIENT_ID |
HCA OAuth client ID |
HCA_CLIENT_SECRET |
HCA OAuth client secret |
SLACK_BOT_TOKEN |
Slack bot token for profile sync |
| Variable | Description |
|---|---|
R2_ACCESS_KEY_ID |
Cloudflare R2 access key |
R2_SECRET_ACCESS_KEY |
Cloudflare R2 secret key |
R2_BUCKET |
R2 bucket name |
R2_ENDPOINT |
R2 endpoint URL |
| Variable | Description |
|---|---|
GEOCODER_API_KEY |
Geocoding API key |
SKYLIGHT_AUTHENTICATION |
Skylight performance monitoring |
SENTRY_DSN |
Sentry error monitoring DSN |
LOOPS_API_KEY |
Loops.so API key for mailer |
MAILER_FROM |
Default from email address |
EXTERNAL_API_KEY |
API key for /api/v1 endpoints |
UPTIME_WORKER_PING_URL |
Uptime monitoring ping URL |
If your PostgreSQL and Redis resources are in the same Coolify project, use internal hostnames in DATABASE_URL and REDIS_URL so traffic stays on the internal Docker network.
- In the main application's settings, add your custom domain
- Coolify handles SSL certificates automatically via Let's Encrypt
- The worker does not need a domain
Deploy the main app first (its entrypoint runs rails db:prepare to apply migrations), then deploy the worker.
Push to your configured branch or click Deploy in the Coolify dashboard.
- Assets not loading: Ensure
RAILS_MASTER_KEYis set correctly — asset precompilation happens at build time with a dummy key, but the app needs the real key at runtime for encrypted credentials. - Database connection errors: Verify
DATABASE_URLuses the correct internal hostname and that the database resource is running. - WebSocket / Action Cable issues: Confirm
REDIS_URLis set and the Redis resource is healthy. - Jobs not processing: Check the worker container's logs. Ensure it has the same
DATABASE_URLandREDIS_URLas the main app.