A minimal Rails application for verifying preview deployments on Railway and Fly.io.
| Layer | Technology | Version |
|---|---|---|
| Language | Ruby | 3.4.8 |
| Framework | Rails | 8.1.2 |
| Database | PostgreSQL | 17 |
| Web Server | Puma | 7.2.0 |
| Assets | Propshaft + Importmap | 1.3.1 / 2.2.3 |
- Post CRUD — scaffold with title (string), body (text), and published (boolean)
- Health Check —
GET /upreturns 200 if the app boots successfully - Dockerfile — multi-stage production build generated by Rails 8.1
| Method | Path | Description |
|---|---|---|
| GET | / |
Root (redirects to posts#index) |
| GET | /up |
Health check |
| GET | /posts |
List all posts |
| GET | /posts/new |
New post form |
| GET | /posts/:id |
Show a post |
| GET | /posts/:id/edit |
Edit post form |
| POST | /posts |
Create a post |
| PATCH/PUT | /posts/:id |
Update a post |
| DELETE | /posts/:id |
Delete a post |
- Ruby 3.4.8 (managed via asdf)
- PostgreSQL 17
- Bundler
bundle install
bin/rails db:create db:migrate
bin/rails serverDeployment is configured via railway.json.
| Setting | Value | Description |
|---|---|---|
| Builder | Dockerfile | Uses the multi-stage Dockerfile generated by Rails |
| Health check | GET /up |
Rails built-in health endpoint (timeout: 300s) |
| Restart policy | On failure (max 5 retries) | Prevents infinite crash loops |
The Dockerfile's entrypoint automatically runs db:prepare before starting the server. No custom start command is needed.
- Create a new project and connect this repository
- Add a PostgreSQL service
- On the app service, add a variable:
DATABASE_URL=${{Postgres.DATABASE_URL}} - On the app service, add a variable:
RAILS_MASTER_KEY(value fromconfig/master.key) - Enable PR environments: Project Settings > Environments > Enable PR Environments
- Enable bot PR environments: Project Settings > Environments > Enable Bot PR Environments
Note: If you use AI coding tools like Claude Code to create commits and pull requests, you must enable Bot PR Environments. Railway classifies PRs with commits from supported bots (including Claude Code) as bot PRs, and will not create preview environments for them unless this setting is turned on.
When PR environments are enabled, Railway automatically:
- Creates an isolated environment (including a fresh PostgreSQL instance) for each pull request
- Provisions a unique URL (e.g.,
*.up.railway.app) for the PR environment - Runs
db:prepareon the empty database via the Dockerfile entrypoint - Deletes the environment when the PR is merged or closed
Deployment is configured via fly.toml. PR preview environments are handled by GitHub Actions using superfly/fly-pr-review-apps.
| Setting | Value | Description |
|---|---|---|
| Builder | Dockerfile | Uses the multi-stage Dockerfile generated by Rails |
| Region | nrt (Tokyo) | Primary deployment region |
| Release command | bin/rails db:prepare |
Runs migrations before starting the app |
| Health check | GET /up |
Rails built-in health endpoint |
| VM | shared-cpu-1x, 512 MB | Minimal resources for demo purposes |
| Auto-stop | Enabled | Machines stop when idle to reduce costs |
The Dockerfile's entrypoint also runs db:prepare before starting the server. The release command ensures migrations complete before any instances start.
- Install the Fly CLI:
curl -L https://fly.io/install.sh | sh - Sign in:
fly auth login - Create the app:
fly apps create rails-preview-demo
- Create a PostgreSQL cluster:
fly postgres create --name rails-preview-demo-db --region nrt
- Attach PostgreSQL to the app:
fly postgres attach rails-preview-demo-db --app rails-preview-demo
- Set secrets:
fly secrets set RAILS_MASTER_KEY=<value from config/master.key> --app rails-preview-demo
- Deploy:
fly deploy
Two workflows are included:
fly-deploy.yml— Deploys to production on push tomainfly-preview.yml— Creates/updates/destroys preview apps for pull requests
Add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions):
| Secret | Description |
|---|---|
FLY_API_TOKEN |
Fly.io org-level token (get via fly tokens create org) |
RAILS_MASTER_KEY |
Value from config/master.key |
Unlike Railway, Fly.io does not have built-in PR preview environments. Instead, the fly-preview.yml workflow uses the superfly/fly-pr-review-apps GitHub Action to:
- Create an isolated Fly app for each pull request
- Attach a new database to the shared PostgreSQL cluster
- Set required secrets (
RAILS_MASTER_KEY) - Run
db:preparevia the release command - Destroy the app when the PR is merged or closed
The preview URL is posted as a comment on the pull request by the action.
"app not found" or random app name on first deploy
Fly.io's built-in GitHub integration requires fly.toml to be present on the main branch. Without it, Fly.io's scanner auto-detects the app type and generates a random app name (e.g., app-black-rain-41) that doesn't match any existing app. Ensure fly.toml with the correct app name is merged to main before connecting the repository in the Fly.io dashboard.
"No access token available. Please login with 'flyctl auth login'"
The FLY_API_TOKEN GitHub Secret is missing or empty. Add it in Settings > Secrets and variables > Actions in your GitHub repository.
"Not authorized to deploy this app"
The PR preview workflow creates new Fly apps for each pull request (e.g., pr-7-codenote-net-rails-preview-demo). A deploy token created with fly tokens create deploy is scoped to a single app and cannot create new apps. Use an org-level token instead:
fly tokens create orgUpdate the FLY_API_TOKEN GitHub Secret with this org-level token.
This project is licensed under the MIT License.