Deploy to Railway
Deploy self-hosted Quackback to Railway with the one-click template (app, PostgreSQL with pgvector, and a storage bucket) or set it up manually. No Redis needed.
Deploy self-hosted Quackback to Railway with one click: no server to manage, automatic SSL, and PostgreSQL plus file storage included. Railway is a third-party hosting platform you pay for directly; this is separate from Quackback Cloud.
Prerequisites
- A Railway account
- A domain or subdomain for your instance (for example
feedback.yourcompany.com), or a Railway-generated domain
One-click deploy
Open the Quackback template on Railway and click Deploy.
The template provisions three services:
Service | Purpose |
|---|---|
Quackback | The application server, including background jobs |
PostgreSQL | Database with the |
Bucket | Railway's S3-compatible storage for file uploads |
There is no Redis service: PostgreSQL holds the background job queue too.
The template sets TRUSTED_PROXY_HOPS=1, because Railway's edge proxies every request. If you turn on Railway's CDN in front of the service, change it to 2.
After deploying:
- Find your sign-in code. If email isn't configured yet, sign-in codes appear in the Quackback service's deploy logs.
- Configure email (recommended): add one email provider, as shown below.
- Add a custom domain (optional), then update
BASE_URLto match.
Manual setup
If you prefer to configure each service yourself:
- Create a new project. Go to railway.com/new and click Empty Project.
- Add PostgreSQL. Click + New > Docker Image and enter
pgvector/pgvector:pg17. Add a volume mounted at/var/lib/postgresql/data, and setPOSTGRES_DB,POSTGRES_USER, andPOSTGRES_PASSWORD. - Add a bucket. Click + New > Bucket. Railway provisions S3-compatible storage for uploads.
- Deploy Quackback. Click + New > Docker Image and enter
ghcr.io/quackbackio/quackback:latest(or pin a release tag). - Configure environment variables (see below).
- Set the health check. In the Quackback service, go to Settings > Deploy and set the health check path to
/api/health/ready. The first start after an upgrade runs migrations, so allow a generous timeout (the template uses 300 seconds). - Add a domain. Go to Settings > Networking, click Generate Domain for a Railway subdomain or Custom Domain for your own (add a CNAME record pointing to Railway), then update
BASE_URLto match. Railway provides SSL automatically.
Note: Quackback requires PostgreSQL 14+ with pgvector 0.5.0+ and
pg_trgm. Thepgvector/pgvectorimage includes both. Connect over Railway's private network directly, not through a transaction-mode pooler: realtime updates useLISTEN/NOTIFY.
Environment variables
In the Quackback service settings, add:
DATABASE_URL=postgresql://quackback:${{postgres.POSTGRES_PASSWORD}}@${{postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/quackback
# Authentication, 32+ characters (generate with: openssl rand -base64 32)
SECRET_KEY=your-32-character-minimum-secret-key
# Public URL (set after assigning a domain)
BASE_URL=https://feedback.yourcompany.com
# Railway's edge is one proxy hop (use 2 if Railway's CDN is enabled)
TRUSTED_PROXY_HOPS=1
# Storage bucket
S3_ENDPOINT=${{Bucket.ENDPOINT}}
S3_BUCKET=${{Bucket.BUCKET}}
S3_REGION=${{Bucket.REGION}}
S3_ACCESS_KEY_ID=${{Bucket.ACCESS_KEY_ID}}
S3_SECRET_ACCESS_KEY=${{Bucket.SECRET_ACCESS_KEY}}
S3_FORCE_PATH_STYLE=trueDo not set REDIS_URL. It is no longer used.
Email configuration
Without email, sign-in codes are printed to the Railway logs. For production, configure exactly one sending provider: SMTP, Amazon SES, or Resend. If more than one is set, the app refuses to start and names the conflicting variables.
# SMTP
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USER=your-username
EMAIL_SMTP_PASS=your-password
EMAIL_FROM=Quackback <[email protected]>
# Or Amazon SES (all three keys required)
# EMAIL_SES_ACCESS_KEY_ID=AKIA...
# EMAIL_SES_SECRET_ACCESS_KEY=...
# EMAIL_SES_REGION=us-east-1
# Or Resend
# EMAIL_RESEND_API_KEY=re_xxxxxxxxxxxxSee Configure email delivery for details.
File storage
The template's Railway bucket stores uploads. Files are served through the app at /api/storage, so the bucket can stay private. To use another provider instead (AWS S3, Cloudflare R2, Backblaze B2), point the S3_* variables at it. See Environment variables.
Upgrades
Migrations run on every startup, so schema changes apply when the new image starts. To upgrade:
- Back up the PostgreSQL volume and the bucket.
- Change the Quackback service's image tag to the new release (or redeploy to pull
latest). - Watch the deploy logs until migrations finish and the health check passes.
Warning: Upgrading from 0.13? Follow Upgrade from 0.13 to 0.14. Remove the old Redis service and the
REDIS_URLvariable, and addTRUSTED_PROXY_HOPS=1.
Monitoring
- Logs: open the Quackback service, click Deployments, select the active deployment, and click View Logs.
- Health check: in Settings > Deploy, set the path to
/api/health/ready(checks the database, migrations, and background workers). Use/api/health/liveif you only want to confirm the process is up. See Health endpoints.
Cost
Railway bills based on usage. A typical Quackback instance costs about $5 to $20 a month depending on traffic:
Resource | Estimate |
|---|---|
Quackback (512 MB RAM) | about $5/mo |
PostgreSQL | about $5/mo |
Bucket | Depends on stored files |
Check Railway's pricing page for current plans and trial credit.
Troubleshooting
Deploy fails
Check the deploy logs. Common causes:
- Missing environment variables: make sure
DATABASE_URL,SECRET_KEY, andBASE_URLare set. - More than one email provider configured: the log names the conflicting variables.
Database connection failed
- Verify the PostgreSQL service is running.
- Check that
DATABASE_URLreferences the correct service. - Restart the Quackback service.
Port already in use
Railway assigns a port through the PORT environment variable, and Quackback reads it automatically. Do not hardcode a port.
Related articles
Was this helpful?
Your feedback shapes what we write next.
