Deploy Webstudio
Advanced Open Source Website Builder
postgres
Just deployed
publisher
Just deployed
webstudio
Just deployed
postgrest
Just deployed
Just deployed
Deploy and Host Webstudio on Railway
Webstudio is an open-source visual development platform and Webflow alternative. Designers and developers build sites in a full CSS canvas, connect any headless CMS, and publish static or SSR projects they actually own. This template self-hosts the full builder stack on Railway — Remix builder, PostgREST, Postgres, MinIO asset storage, and the community publisher.
About Hosting Webstudio
Hosting Webstudio means running five containers on Railway’s private network: a public builder (Remix visual editor), a public publisher (one-click Publish output), Postgres for projects and users, PostgREST as the REST API over that database, and MinIO as S3-compatible asset storage. Railway terminates TLS, so every container speaks HTTP internally and binds 0.0.0.0:${PORT}. You attach volumes for Postgres, MinIO, and the publisher’s publish/work directories, generate secrets once on the webstudio service, and let each entrypoint wait over IPv6 private DNS, run Prisma migrations, then exec the main process. First boot can take a few minutes while images pull and migrations apply. After that, sign in with DEV_LOGIN (password = AUTH_SECRET) and start a project.
The official ghcr.io/webstudio-is/webstudio registry only has two-year-old sha tags and no current latest builder. This kit wraps the production self-host images from webstudio-community/webstudio-self-host: ghcr.io/webstudio-community/builder:latest and ghcr.io/webstudio-community/webstudio-publisher:latest.
Common Use Cases
- Run a private Webstudio builder for an agency or product team instead of Webstudio Cloud
- Keep project data, assets, and published HTML on infrastructure you control (AGPL-3.0 core)
- Publish marketing sites and landing pages from the visual canvas to a Railway domain or your own wildcard
- Give developers a self-hosted target for
webstudio link/ the Webstudio CLI - Pair the builder with GitHub or Google OAuth when you outgrow the single shared
DEV_LOGINpassword
Dependencies for Webstudio Hosting
- Builder image:
ghcr.io/webstudio-community/builder:latest(Remix visual editor, Prisma,/health) - Publisher image:
ghcr.io/webstudio-community/webstudio-publisher:latest(build API:4000+ site proxy:4001) - PostgreSQL 15 (
postgres:15-alpine) — projects, users, sessions.PGDATA=/var/lib/postgresql/data - PostgREST 12.2 (
postgrest/postgrest:v12.2.0) — REST API over Postgres, IPv6 listen (PGRST_SERVER_HOST=*) - MinIO (
minio/minio) — S3-compatible object storage for canvas assets - Railway private networking —
postgres.railway.internal:5432,postgrest.railway.internal:3000,minio.railway.internal:${{minio.PORT}},webstudio.railway.internal:${{webstudio.PORT}},publisher.railway.internal:4000 - Three persistent volumes (drives) — see Implementation Details
Name the services exactly postgres, postgrest, minio, webstudio, and publisher. Set each service Root Directory to its folder. Keep postgres and postgrest private. Give webstudio, publisher, and minio public domains (MinIO must be public so browser asset URLs resolve).
Upstream: Webstudio · Docs · Self-host compose · Source · License AGPL-3.0-or-later
Implementation Details
Clone the template to see how it works:
webstudio/ # public builder
Dockerfile # FROM ghcr.io/webstudio-community/builder:latest
entrypoint.sh # IPv6 wait, prisma migrate deploy, exec node /app/server.js
wait-for.cjs # dual-stack TCP/HTTP probe
railway.toml # healthcheck /health, 300s timeout
publisher/ # public published sites
Dockerfile # FROM ghcr.io/webstudio-community/webstudio-publisher:latest
gateway.mjs # $PORT → API :4000 + site proxy :4001
entrypoint.sh # wait for builder /health, exec gateway
railway.toml # healthcheck /health, 300s timeout
postgres/
Dockerfile # postgres:15-alpine, listen_addresses=*
init.sql # uuid-ossp, anon role, default privileges
minio/
Dockerfile # minio + mc on debian-slim (scratch upstream has no shell)
entrypoint.sh # create public-read bucket, exec minio on $PORT
postgrest/
Dockerfile # postgrest v12.2 + psql + python wait
entrypoint.sh # wait for Prisma migrations, GRANT anon, exec postgrest
Topology
Name the services exactly as written. Private DNS is .railway.internal. If you rename them, the builder cannot find Postgres, PostgREST, MinIO, or the publisher.
| Service | Role | Root Directory | Volume | Memory | Public |
|---|---|---|---|---|---|
| postgres | Project database | postgres | /var/lib/postgresql | 1 GB | No |
| postgrest | REST API over Postgres | postgrest | None | 512 MB | No |
| minio | S3 asset storage | minio | /data | 512 MB | Yes |
| webstudio | Visual builder | webstudio | None | 1 GB floor, 2 GB better | Yes |
| publisher | Publish API + site proxy | publisher | /var/publish and /var/work | 1 GB floor, 2 GB better | Yes |
Volumes (drives) — what to mount
Attach before the first successful start. Skip this and init lands on ephemeral disk; the next deploy wipes projects, assets, and published sites.
| Service | Mount path | What is stored | Start size |
|---|---|---|---|
| postgres | /var/lib/postgresql | Users, projects, builds, sessions. PGDATA is already /var/lib/postgresql/data. | 1 GB |
| minio | /data | Uploaded canvas assets (images, fonts, files) and the bucket-init marker. | 1 GB |
| publisher | /var/publish | Generated static sites, one directory per publish domain. | 1 GB |
| publisher | /var/work | Publisher working copies and state.json per domain. | 1 GB |
| webstudio | do not mount anything | Stateless. Assets live in MinIO. Railway terminates TLS. | — |
| postgrest | do not mount anything | Stateless API. | — |
Do not mount /etc/letsencrypt, Traefik dynamic config, or SSL certificates. Those are VPS/Coolify paths. Railway already terminates TLS in front of every public service.
Railway: each service → Settings → Volumes → Add Volume → paste the mount path exactly. The publisher needs two volumes.
Traps
Ways this still fails:
- Do not use Railway’s Postgres plugin. The builder expects user
postgres, databasewebstudio, theanonrole, anduuid-osspin schemaextensions. The kit’spostgresservice is the matching pair. PointingDATABASE_URLat a plugin instance skipsinit.sqland PostgREST cannot read tables. - Attach volumes before the first successful start. Postgres init SQL, the MinIO bucket, and published sites all live on those mounts. A first boot without volumes writes to ephemeral disk; the next deploy looks like an empty install.
- Private DNS is IPv6.
localhost,127.0.0.1, and::1are wrong for cross-service traffic. Usepostgres.railway.internal,postgrest.railway.internal,minio.railway.internal,webstudio.railway.internal,publisher.railway.internal. PostgREST is forced toPGRST_SERVER_HOST=*so it actually listens on IPv6. If the builder waits forever, redeploy the app — do not restart Postgres to “fix” DNS. - Do not put TLS inside the container. Railway terminates HTTPS. The builder already sets Express
trust proxy, soreq.protocolishttpsand__Host-cookies work. SettingALLOW_INSECURE_COOKIES=truein production crashes the process. DEPLOYMENT_URLmust match the live domain. Generate thewebstudiopublic domain first, setDEPLOYMENT_URL=https://${{RAILWAY_PUBLIC_DOMAIN}}with no trailing slash, then deploy. If you add a custom domain later, updateDEPLOYMENT_URLand redeploy or login/OAuth callbacks miss.- MinIO must be public.
S3_ENDPOINTis the publichttps://MinIO domain so canvas<img>tags load in the browser. A private MinIO makes uploads succeed and previews break. Do not pointS3_ENDPOINTathttp://minio.railway.internal. - Published sites need a wildcard custom domain.
PUBLISHER_HOSTdefaults to the publisher’s*.up.railway.apphostname. Nested hosts likemyproject..up.railway.appwill not resolve. Add a custom domain (for examplesites.example.com) plus a DNS wildcard*.sites.example.comon the publisher service, then setPUBLISHER_HOST=sites.example.comon bothwebstudioandpublisher. - Canvas preview iframes need a wildcard on the builder. Self-hosted Webstudio serves the canvas at
*.your-builder-domain. Add*.builder.example.comas a wildcard custom domain onwebstudioif project iframes stay blank. - Do not generate a second
POSTGRES_PASSWORDon the postgres service. Use${{webstudio.POSTGRES_PASSWORD}}. A newsecret(32)on postgres desyncs the URI and every connection fails authentication.
Why Deploy Webstudio 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 Webstudio 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
postgres
OpenSource-Templates/Webstudiopublisher
OpenSource-Templates/Webstudiowebstudio
OpenSource-Templates/Webstudiopostgrest
OpenSource-Templates/Webstudio