---
title: "Deploy Webstudio"
description: "Advanced Open Source Website Builder"
category: "CMS"
url: https://railway.com/deploy/webstudio
---

# Deploy Webstudio

Advanced Open Source Website Builder

**[Deploy Webstudio on Railway](https://railway.com/template/webstudio)**

- **Creator:** OpenSource Templates
- **Category:** CMS
- **Total deploys:** 13

## Template content

### postgres https://devicons.railway.com/i/postgresql.svg

- **Source:** OpenSource-Templates/Webstudio

### publisher

- **Source:** OpenSource-Templates/Webstudio
- **Public domain:** Yes

### webstudio https://thesvg.org/icons/webstudio/default.svg

- **Source:** OpenSource-Templates/Webstudio
- **Public domain:** Yes

### postgrest https://docs.postgrest.org/en/v16/_static/favicon.ico

- **Source:** OpenSource-Templates/Webstudio

### minio https://devicons.railway.com/i/minio.svg

- **Source:** OpenSource-Templates/Webstudio
- **Public domain:** Yes

## Documentation

# 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](https://github.com/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_LOGIN` password

## 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](https://webstudio.is/) · [Docs](https://docs.webstudio.is) · [Self-host compose](https://github.com/webstudio-community/webstudio-self-host) · [Source](https://github.com/webstudio-is/webstudio) · License AGPL-3.0-or-later

### Implementation Details

Clone the template to see how it works:

```text
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`, database `webstudio`, the `anon` role, and `uuid-ossp` in schema `extensions`. The kit’s `postgres` service is the matching pair. Pointing `DATABASE_URL` at a plugin instance skips `init.sql` and 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 `::1` are wrong for cross-service traffic. Use `postgres.railway.internal`, `postgrest.railway.internal`, `minio.railway.internal`, `webstudio.railway.internal`, `publisher.railway.internal`. PostgREST is forced to `PGRST_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`, so `req.protocol` is `https` and `__Host-` cookies work. Setting `ALLOW_INSECURE_COOKIES=true` in production crashes the process.
* **`DEPLOYMENT_URL` must match the live domain.** Generate the `webstudio` public domain first, set `DEPLOYMENT_URL=https://${{RAILWAY_PUBLIC_DOMAIN}}` with no trailing slash, then deploy. If you add a custom domain later, update `DEPLOYMENT_URL` and redeploy or login/OAuth callbacks miss.
* **MinIO must be public.** `S3_ENDPOINT` is the public `https://` MinIO domain so canvas `<img>` tags load in the browser. A private MinIO makes uploads succeed and previews break. Do not point `S3_ENDPOINT` at `http://minio.railway.internal`.
* **Published sites need a wildcard custom domain.** `PUBLISHER_HOST` defaults to the publisher’s `*.up.railway.app` hostname. Nested hosts like `myproject..up.railway.app` will not resolve. Add a custom domain (for example `sites.example.com`) plus a DNS wildcard `*.sites.example.com` on the **publisher** service, then set `PUBLISHER_HOST=sites.example.com` on both `webstudio` and `publisher`.
* **Canvas preview iframes need a wildcard on the builder.** Self-hosted Webstudio serves the canvas at `*.your-builder-domain`. Add `*.builder.example.com` as a wildcard custom domain on `webstudio` if project iframes stay blank.
* **Do not generate a second `POSTGRES_PASSWORD` on the postgres service.** Use `${{webstudio.POSTGRES_PASSWORD}}`. A new `secret(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.

## Similar templates

- [Libredesk - Complete Setup](https://railway.com/deploy/libredesk-complete-setup) — Complete self-hosted omnichannel customer support desk.
- [Paperless-ngx](https://railway.com/deploy/paperless-ngx-3) — Paperless-ngx — document management with OCR and full-text search
- [Instatic CMS - Postgres](https://railway.com/deploy/instatic-cms-postgres) — Design, build and manage powerful static sites from state-of-the-art CMS

Open this page in a browser: https://railway.com/deploy/webstudio
