Marketing website on Railway#
Deploy the public marketing site as a separate marketing service alongside the
docs service. Both are static sites; neither runs the
private Roost app or needs databases, volumes, or credentials.
Service settings#
Create an empty service and configure it before deploying:
| Setting | Value |
|---|---|
| Source root | Repository root, not sites/marketing |
Service variable RAILWAY_DOCKERFILE_PATH | sites/marketing/Dockerfile |
| Dockerfile path | sites/marketing/Dockerfile |
| Health check | /healthz, timeout 60 seconds |
| Watch paths | /sites/marketing/**, /package.json, /pnpm-lock.yaml, /.dockerignore |
| Public domain target port | 8080 |
Leave build and start overrides empty. The Dockerfile builds only the marketing
site using the root package manifest and lockfile, then copies its dist output
into Caddy. The root .dockerignore excludes app sources and local environment
files. Caddy listens on Railway's PORT; Railway handles HTTPS and compression.
Missing files return HTTP 404, not a fallback to the home page.
Set ROOST_DOCS_URL to the docs service's HTTPS origin. Set
ROOST_WEBSITE_URL to the marketing site's origin; if omitted, its Docker build
uses https://$RAILWAY_PUBLIC_DOMAIN. Set these same two public URL variables on
the docs service too and rebuild both so their navigation connects correctly.
Use origins without subdirectories. No app secrets are required.
With the correct project linked, deploy from the repository root:
railway up --service marketing --environment production --ci
For GitHub autodeploys, first commit and push the deployment files, then connect the intended repository and branch in Railway. Keep the Dockerfile and watch paths above. A CLI deployment does not automatically enable GitHub autodeploys.
CDN caching#
After applying the public domain, enable the CDN for this service separately:
railway cdn enable --service marketing --environment production
railway cdn update --service marketing --environment production \
--html-caching auto --purge-on-deploy all
railway cdn status --service marketing --environment production --json
The cache policy matches the docs service: HTML, SVGs, Markdown, and llms.txt
revalidate in browsers and cache for five minutes at Railway's edge. Existing
fingerprinted CSS and JavaScript cache for one year with immutable. Health
checks and errors use no-store. Purge-all on successful deploy refreshes stable
URLs too; purges may take around ten seconds to propagate. CDN access has no
additional CDN charge, but the separate origin service incurs Railway usage.
Verify#
Wait for SUCCESS, then run:
node scripts/check-marketing-deployment.mjs https://MARKETING-DOMAIN https://DOCS-DOMAIN --cdn
This checks public links and canonical URLs, local assets, agent-readable text,
real 404s, the docs backlink, and actual CDN hits. Use the same command without
--cdn for a local Caddy deployment. For browser verification, switch between
Moss, Wisp, and Peach, toggle Take control, download the example launch plan,
and check the layout on mobile.
Custom domains require adding Railway's DNS records and rebuilding both sites with their new public origins. See Public websites and Railway's CDN documentation.