Deploy PG On Rails
"PG On Rails" | Self-hosted Supabase. Amazing developer experience.
Just deployed
Supabase Realtime
Just deployed
PgBouncer
Just deployed
Supabase Auth
Just deployed
imgproxy
Just deployed
RustFS Bucket Init
Just deployed
Supabase Studio
Just deployed
Just deployed
Postgres Meta
Just deployed
Postgres
Just deployed
/var/lib/postgresql/data
PostgREST
Just deployed
Supabase Storage
Just deployed
Edge Functions
Just deployed
RustFS
Just deployed
/data
Deploy and Host Complete Supabase + TanStack Start on Railway
PG On Rails is a passion project that combines two of my favourite things: Supabase and Railway! It is local-first and is a joy to build Supabase applications with. It is a monorepo with one directory per service, and is designed for the modern deployment pattern of watch paths.
My longterm vision is to make PG On Rails the best strategy for bootstrapping, building and self-hosting Supabase.
About Hosting PG On Rails
Please visit the official GitHub repo to view GIFs of the deployment process.
You can now deploy and setup PG On Rails completely hands-free! With a single shell command, accomplish every step from the manual setup in minutes without lifting a finger. Simply run the following command on a Linux, MacOS or WSL terminal:
bash <(curl -fsSL https://raw.githubusercontent.com/BenIsenstein/pgonrails-cli/main/start.sh)
For the manual tutorial, continue reading!
To deploy this template, only 3 environment variables need to be configured. Please visit the Supabase self-hosting tool to generate a JWT secret and keys, and input them when prompted into the Postgres service.
You can use your deployment as a remote backend only, or you can practice truly local-first development by running your project on your machine. To do this, you'll need to eject the project and clone your newly forked GitHub repo.
Whether remote or local, you'll be able to use the Supabase Studio dashboard right away, by copying the DASHBOARD_PASSWORD variable from the Envoy service. Visit the public url for Envoy, and log in with user pgonrails and the password.
Common Use Cases
- Postgres database with instant APIs
- Auth, Edge Functions, Websockets
- S3-compatible storage, Vector embeddings
- Startups, Scale-ups, SaaS
Dependencies for Complete Supabase + TanStack Start Frontend Hosting
Deployment Dependencies
In order to deploy this template smoothly, you must create a JWT secret and keys using the Supabase online self-hosting tool. The link to it is provided directly in the environment configuration UI.
Implementation Details
Sane and simple defaults
Get working on real application features in seconds. We go the extra mile to make default configuration minimal while still covering everything needed to run out-of-the-box. Avoid drowning in config, and opt in to more hackability as needed.
Add your app logic, deploy seamlessly
Every service gets its own directory, so watchpaths just work. Add new functions, configuration files, migrations, and anything else to a service's repo, commit your work, and Railway (or your CI/CD of choice) will trigger a new build.
Your frontend, included in the stack
Reduce context-switching and host as much of your stack as possible on the same platform. For Tanstack Start, Django, htmx or any server-rendered frontend, get fast and secure access to Supabase data APIs via the shared internal network.
Full control over your application
For the hackers. Configure every aspect of your Supabase application and version it in code:
- Email templates
- Third-party auth providers
- Environment variables
- Networking settings
- Railway config-as-code
Railway observability instead of Logflare
The entire Supabase feature set for building applications has been extensively tested and proven via the included TanStack Start app, "Trello Clone". At this time, it doesn't include a Logflare analytics service, and opts to use Railway's platform observability instead.
Frontend included with seamless dev mode
We included a frontend app in the stack and named it site. The frontend site is a TanStack app built with Tanstack Start, tailwindCSS and shadcn/ui. It includes basic auth functionality so you can begin building user experiences out of the box.
Separate Dockerfiles for development and deployment
The project is setup so that running the Docker Compose stack locally runs the site in dev mode. The local dev experience points to a dev.Dockerfile in the site repo. This dockerfile runs the vite dev server. For production, however, Railway looks for a Dockerfile by default (no dev prefix), and will deploy using the Dockerfile which builds and serves the optimized site.
The other strategy which enables smooth local development inside Docker, is mounting the entire site directory as a volume inside the dev container (volumes: - ./site:/app). This exposes the codebase from your local filesystem inside the container, where the dev server can pick up any changes and deliver that hot-reload experience we all love.
Choose your DB migrations story
By default, the Site service runs its DB migrations on startup:
ENTRYPOINT supabase db push ... && node server.js
This way, the example web app is usable from the moment you deploy. It is easy to move this process into a GitHub action however - there is one already included in the repo for you! Simply add a DB_URL secret to your forked repo and it will run when you add migration files to /site/supabase/migrations.
No mail server yet, no problem
By default, mailing is disabled. Once a user signs up with their email and password, their email is "auto-confirmed" by the auth server and they are signed in.
Setup mailing fast
The auth server requires an SMTP server to send transactional emails. In my experience, the quickest way to get up and running in both local and non-production cloud environments, is through a gmail account with an app password.
Log in to the Google account you want all transactional emails to come from. Visit the following link to create a Google app password.
Make sure the email signup and SMTP environment variables are set:
GOTRUE_MAILER_AUTOCONFIRM=false
GOTRUE_SMTP_ADMIN_EMAIL=johndoe@gmail.com
GOTRUE_SMTP_USER=myapp@gmail.com
GOTRUE_SMTP_PASS="abcd efgh ijkl mnop"
GOTRUE_SMTP_HOST=smtp.gmail.com
GOTRUE_SMTP_PORT=587
GOTRUE_SMTP_SENDER_NAME: "PG On Rails"
NOTE - SMTP traffic on Railway is only allowed for the Pro Plan and above.
Why Deploy PG On Rails on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying PG On Rails on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
Template Content
PORT
DASHBOARD_PASSWORD
DASHBOARD_USERNAME
ANON_KEY_ASYMMETRIC
SUPABASE_SECRET_KEY
SUPABASE_PUBLISHABLE_KEY
SERVICE_ROLE_KEY_ASYMMETRIC
Supabase Realtime
BenIsenstein/pgonrailsPORT
DB_USER
APP_NAME
DNS_NODES
DB_ENC_KEY
ERL_AFLAGS
RUN_JANITOR
RLIMIT_NOFILE
SEED_SELF_HOST
SECRET_KEY_BASE
SELF_HOST_TENANT_NAME
DB_AFTER_CONNECT_QUERY
PgBouncer
BenIsenstein/pgonrailsPORT
DB_USER
AUTH_TYPE
POOL_MODE
AUTH_QUERY
LISTEN_ADDR
MAX_CLIENT_CONN
DEFAULT_POOL_SIZE
Supabase Auth
BenIsenstein/pgonrailsPORT
GOTRUE_JWT_AUD
GOTRUE_API_HOST
GOTRUE_DB_DRIVER
GOTRUE_SMTP_HOST
GOTRUE_SMTP_PASS
GOTRUE_SMTP_PORT
GOTRUE_SMTP_USER
GOTRUE_JWT_ADMIN_ROLES
GOTRUE_SMTP_ADMIN_EMAIL
GOTRUE_SMTP_SENDER_NAME
GOTRUE_MAILER_AUTOCONFIRM
GOTRUE_JWT_DEFAULT_GROUP_NAME
GOTRUE_MAILER_URLPATHS_INVITE
AUTH_LOCAL_MAILER_TEMPLATES_URL
GOTRUE_MAILER_URLPATHS_RECOVERY
GOTRUE_MAILER_URLPATHS_CONFIRMATION
GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE
GOTRUE_MAILER_SUBJECTS_REAUTHENTICATION
GOTRUE_SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION
imgproxy
BenIsenstein/pgonrailsPORT
IMGPROXY_USE_S3
IMGPROXY_USE_ETAG
IMGPROXY_AUTO_WEBP
IMGPROXY_JPEG_PROGRESSIVE
IMGPROXY_IGNORE_SSL_VERIFICATION
RustFS Bucket Init
rustfs/rcSupabase Studio
BenIsenstein/pgonrailsPORT
HOSTNAME
DEFAULT_PROJECT_NAME
DEFAULT_ORGANIZATION_NAME
ENABLED_FEATURES_LOGS_ALL
SNIPPETS_MANAGEMENT_FOLDER
EDGE_FUNCTIONS_MANAGEMENT_FOLDER
HOST
PORT
Postgres Meta
BenIsenstein/pgonrailsPORT
CRYPTO_KEY
PG_META_HOST
PG_META_DB_USER
Postgres
BenIsenstein/pgonrailsPORT
PGDATA
DB_NAME
JWT_EXPIRY
JWT_SECRET
POSTGRES_HOST
DB_AUTH_PASSWORD
LISTEN_ADDRESSES
SUPABASE_ANON_KEY
DB_STORAGE_PASSWORD
DB_WEBHOOKS_PASSWORD
SUPABASE_SERVICE_KEY
DB_PGBOUNCER_PASSWORD
DB_SUPERUSER_PASSWORD
DB_AUTHENTICATOR_PASSWORD
PostgREST
BenIsenstein/pgonrailsPORT
PGRST_DB_SCHEMAS
PGRST_SERVER_HOST
PGRST_DB_ANON_ROLE
PGRST_DB_USE_LEGACY_GUCS
Supabase Storage
BenIsenstein/pgonrailsPORT
TENANT_ID
SERVER_HOST
DB_ANON_ROLE
TUS_URL_PATH
DB_SUPER_USER
TUS_PART_SIZE
DB_SERVICE_ROLE
FILE_SIZE_LIMIT
STORAGE_BACKEND
DB_INSTALL_ROLES
SERVER_ADMIN_PORT
STORAGE_S3_REGION
TUS_URL_EXPIRY_MS
AUTH_JWT_ALGORITHM
DB_AUTHENTICATED_ROLE
STORAGE_S3_MAX_SOCKETS
UPLOAD_FILE_SIZE_LIMIT
IMGPROXY_REQUEST_TIMEOUT
IMGPROXY_HTTP_MAX_SOCKETS
S3_PROTOCOL_ACCESS_KEY_ID
DB_ALLOW_MIGRATION_REFRESH
DATABASE_CONNECTION_TIMEOUT
STORAGE_S3_FORCE_PATH_STYLE
IMAGE_TRANSFORMATION_ENABLED
S3_PROTOCOL_ACCESS_KEY_SECRET
UPLOAD_FILE_SIZE_LIMIT_STANDARD
UPLOAD_SIGNED_URL_EXPIRATION_TIME
IMAGE_TRANSFORMATION_LIMIT_MAX_SIZE
IMAGE_TRANSFORMATION_LIMIT_MIN_SIZE
Edge Functions
BenIsenstein/pgonrailsPORT
VERIFY_JWT
EDGE_RUNTIME_LISTEN
RustFS
BenIsenstein/pgonrailsPORT
S3_ID
S3_SECRET
CONSOLE_PORT
STORAGE_S3_BUCKET
RUSTFS_CORS_ALLOWED_ORIGINS
RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS