Skip to main content
A server is the machine a workspace’s coworkers run on: one engine, in one Docker container. Each workspace has exactly one server, and a server belongs to one workspace. Your first workspace already has one: the engine docker compose starts next to the app. Every other workspace gets its server by pairing, from the app, in about a minute.

Add a server

You need a machine with Docker. It can be the same machine as the app, another computer on your network, or a VPS.
1

Open Servers

Open the workspace menu, the pill in the top left corner of the app, and click Servers. The dialog shows the workspace’s server, or an Add server button when it has none.
2

Get the command

Click Add server. Fill Address the app reaches it at if you know it, for example http://100.101.102.103:3000 or https://engine.example.com. Then copy the command.
The command works once, for 15 minutes, and only for this workspace.
3

Run it on the server

Paste it in a terminal on the machine. The dialog waits, and shows the server as Connected as soon as it is attached.
Add --shm-size 2g to the command, before the image name. The engine started by docker compose has it: it keeps Chromium from crashing on heavy pages.

What happens behind the command

  1. The engine starts and makes up its own key. It keeps it in its data-dir, at /data/engine.key. The key never appears in the command nor in a URL.
  2. It sends the key and the token to your app, at RERUN_HUB_URL/api/engines/pair.
  3. The app checks it can reach the server: first GET /health, then a call that needs the key.
  4. Only then does the app attach the server to the workspace, and spend the token.
The address the app uses is RERUN_PUBLIC_URL when you set it. Without it, the app takes the address the request came from, on port 3000. Set it whenever the server sits behind a proxy, a NAT or a tunnel.

When it does not connect

The server logs say why, in one line:
The usual messages, and the fix for each: A refused pairing is final: the engine stops trying. A pairing that failed before the app attached the server did not spend the token, so within the 15 minutes you can fix the cause and run the command again, after docker rm -f rerun-engine. The server also needs to reach the app. RERUN_HUB_URL is your NEXT_PUBLIC_APP_URL: when it is http://localhost:3000, only a server on the same machine can pair, and even then localhost inside the container is the container itself. Give the app an address the server can reach first.

Enter a server by hand

For an engine you started yourself with your own RERUN_API_KEY, click Enter address and key instead of Add server. Fill the address and the key, and click Connect. The app runs the same two checks before attaching it.

Networking

The app must reach the server on its port, and the server must reach the app. Two setups work well.
Put the app’s machine and the server on the same tailnet. Nothing to open to the internet, and the traffic is encrypted.Use the server’s Tailscale IP as the address, for example RERUN_PUBLIC_URL=http://100.101.102.103:3000. An IP is safer than a MagicDNS name, which the app container may not resolve.The people watching a coworker’s screen need to be on the tailnet too, since their browser opens it on the same address.
The app itself goes behind HTTPS the same way: a Caddyfile block for rerun.example.com with reverse_proxy localhost:3000, then NEXT_PUBLIC_APP_URL=https://rerun.example.com and a rebuild with docker compose up -d --build.

The desktop screen

Each coworker has a screen you can watch and take over. The browser opens it directly on the server’s address: ws:// when the server is on http://, wss:// when it is on https://. So:
  • The person watching must be able to reach the server, not just the app.
  • When the app is on HTTPS, the server must be on HTTPS too. A browser refuses a ws:// connection from an https:// page.
A browser reaches the engine docker compose starts at RERUN_ENGINE_BROWSER_URL: http://localhost:3001 by default, its own https domain on a server. See On a server.

Remove or replace a server

In Servers, click Remove. The workspace’s coworkers stop answering until a server is attached again. Removing only detaches the server. Its data-dir stays on the machine, with every coworker, file and memory. Attach the same server again and they come back. To move a workspace to another machine:
1

Stop the old server

docker stop rerun-engine, so nothing changes while you copy.
2

Copy its data-dir

Back up the volume as in Backups, copy the archive to the new machine, and restore it there into a volume named rerun-engine.
3

Start the engine on the new machine

Without a pairing token: the key and the app’s address are already in the data-dir.
4

Point the workspace at it

In Servers, click Remove, then Enter address and key. The address is the new machine’s, and the key is the one in the data-dir:

Updating

The app and the engine of your first workspace update together:
A paired server updates by pulling the image and starting it again on the same volume, without a pairing token:
Keep the same -p you started it with. On start, the engine migrates its data-dir to the new version. An archive taken weeks ago boots on a newer engine the same way. To check a server’s data-dir without changing it:

Backups

Two things hold your data, and you back up both. The Supabase database: accounts, workspaces, members, the catalog. On supabase.com, the project’s own backups cover it. With open source Supabase, run docker exec supabase-db pg_dump -U postgres postgres | gzip > rerun-db.sql.gz. Otherwise, dump it with pg_dump and the connection string from Connect in the Supabase dashboard. For the local stack:
Files people upload to the app live in Supabase Storage, which a database dump does not include. The engine data-dir: everything the coworkers know and do. It holds their credentials too, so store the archive like a password.
Stop the engine first for a perfectly consistent copy, or take it while it runs and accept the last seconds may be missing.

Restore the data-dir

Stop the engine, empty the volume, unpack the archive, and start again. For the engine started by compose:
For a paired server, use docker stop rerun-engine, the volume rerun-engine, and docker start rerun-engine. The engine migrates an older archive on start.