Deploy for free

This puts Switchyard on the internet with free plans only, no credit card:

Piece Where Free plan
Database Neon Postgres 0.5 GB storage, sleeps when idle
Server Render web service, running the native image 512 MB RAM, 750 hours a month (enough for one service around the clock)
Server image GitHub Container Registry, built by GitHub Actions Free for this repository
Dashboard Cloudflare Pages Unlimited static requests

Allow about 30 minutes the first time. You need accounts on GitHub, Neon, Render and Cloudflare (all can sign up with GitHub).

1. Publish the server image

The Server image workflow (.github/workflows/image.yml) builds the native server and pushes it to ghcr.io/<your-github-user>/switchyard-server. It runs on every push to main; to run it now, open the repository's Actions tab, pick Server image, then Run workflow. It takes about 10 minutes.

Render needs to be able to pull the image. Either:

2. Create the database on Neon

  1. In Neon, Create project. Pick the region closest to where you'll run the server (Render's free plan offers Oregon, Ohio, Virginia, Frankfurt and Singapore).
  2. On the project dashboard, Connect, and choose Java in the connection string menu. You get something like jdbc:postgresql://ep-cool-name-123456.eu-central-1.aws.neon.tech/neondb?user=…&password=…&sslmode=require.
  3. Split it into the three settings the server reads:
    • DATABASE_URL: jdbc:postgresql://ep-cool-name-123456.eu-central-1.aws.neon.tech/neondb?sslmode=require
    • DATABASE_USER: the user value
    • DATABASE_PASSWORD: the password value

The server creates its tables itself on first start.

3. Run the server on Render

  1. In Render, New, Blueprint, and connect this repository. Render reads render.yaml and proposes one web service called switchyard.
  2. If your GitHub user isn't nikolaviews, edit the image URL in render.yaml first.
  3. Fill in the values it asks for:
    • The three DATABASE_… values from Neon.
    • SWITCHYARD_DASHBOARD_ORIGINS: leave empty for now; you'll know the dashboard's address after step 4.
    • Leave the SWITCHYARD_GITHUB_… values empty unless you're setting up GitHub sign-in (step 5).
  4. Apply. When the deploy finishes, the service shows its address, like https://switchyard-abcd.onrender.com. Opening https://switchyard-abcd.onrender.com/actuator/health should show {"status":"UP"}.
  5. Render generated SWITCHYARD_ADMIN_TOKEN. Find it under the service's Environment tab: that's your admin token for signing in.

Free plan sleep: Render's free services sleep after 15 minutes without requests and take a few seconds to wake up. Apps using a Switchyard client poll every 30 seconds, which keeps it awake; when nothing is connected, the first request after a quiet spell is slow. Clients keep using their last flags meanwhile.

4. Put the dashboard on Cloudflare Pages

  1. In Cloudflare, Workers & Pages, Create, Pages, Connect to Git, and pick this repository.
  2. Build settings:
    • Framework preset: None
    • Build command: npm ci && npx ng build
    • Build output directory: dist/dashboard/browser
    • Root directory: dashboard
    • Environment variable: NODE_VERSION = 24
  3. Save and Deploy. You get an address like https://switchyard.pages.dev.
  4. Back in Render, set SWITCHYARD_DASHBOARD_ORIGINS to that address (no trailing slash), and save. Render restarts the server.
  5. Open the dashboard, enter the Render address as the server URL, and sign in with the admin token.

The dashboard is static files: it talks to the server straight from your browser, which is why the server must list its address.

5. GitHub sign-in (optional)

With this, your team signs in with their GitHub accounts instead of sharing the admin token, and History shows who made each change.

  1. On GitHub, open Settings, Developer settings, OAuth Apps, New OAuth App:
    • Application name: Switchyard
    • Homepage URL: your dashboard address, e.g. https://switchyard.pages.dev
    • Authorization callback URL: your server address plus /auth/github/callback, e.g. https://switchyard-abcd.onrender.com/auth/github/callback
  2. Register application, then Generate a new client secret. Copy the secret now; GitHub shows it only once.
  3. In Render, set:
    • SWITCHYARD_GITHUB_CLIENT_ID: the app's Client ID
    • SWITCHYARD_GITHUB_CLIENT_SECRET: the secret
    • SWITCHYARD_GITHUB_ADMINS: who's an admin, e.g. alice (you, at least)
    • SWITCHYARD_GITHUB_ALLOWED_USERS: everyone else who may sign in, e.g. bob,carol. They start as editors (SWITCHYARD_GITHUB_DEFAULT_ROLE changes that); admins change roles on the Members page
    • SWITCHYARD_GITHUB_CALLBACK_URL: the same callback URL as in step 1
  4. Save. The dashboard's sign-in page now shows Continue with GitHub.

Removing someone from SWITCHYARD_GITHUB_ALLOWED_USERS signs them out on their next request. Sessions last 12 hours (SWITCHYARD_SESSION_TTL).

To try GitHub sign-in locally, register a second OAuth app with the callback http://localhost:8080/auth/github/callback and run the server with the same four settings.

6. Connect your apps

Create a project in the dashboard. It shows each environment's SDK key once: put the production key in your app's secrets, and point a client library at the Render address. See the Java client and the JavaScript client.

Running the image anywhere else

The image is an ordinary container. It listens on PORT (default 8080) and reads everything else from the environment variables above:

bash
docker run -p 8080:8080 \
  -e DATABASE_URL=jdbc:postgresql://db.example.com/switchyard \
  -e DATABASE_USER=switchyard -e DATABASE_PASSWORD=… \
  -e SWITCHYARD_ADMIN_TOKEN=… \
  -e SWITCHYARD_DASHBOARD_ORIGINS=https://flags-dashboard.example.com \
  ghcr.io/nikolaviews/switchyard-server:latest

To build it yourself, from the repository root: docker build -f server/Dockerfile -t switchyard-server . (needs about 6 GB of memory for Docker).

The public website (optional)

The site folder builds the project's website: a landing page, plus the user guide, this guide and the client docs as web pages. It is plain static files, so it goes on Cloudflare Pages like the dashboard, as a second Pages project:

  1. Workers & Pages, Create, Pages, Connect to Git, and pick this repository again.
  2. Build settings:
    • Framework preset: None
    • Build command: npm ci && npm run build
    • Build output directory: dist
    • Root directory: site
    • Environment variable: NODE_VERSION = 24
  3. Save and Deploy. The site rebuilds on every push to main, so editing a doc in the repository updates its page.

The website is separate from the dashboard and never talks to the server. To look at it locally: cd site && npm ci && npm run build && npm run preview, then open http://localhost:4300.