---
title: "Deploy Cap | Open Source Loom Alternative"
description: "Self-hosted Loom alternative: screen recording with shareable links"
category: "Other"
url: https://railway.com/deploy/cap-screen-recorder
---

# Deploy Cap | Open Source Loom Alternative

Self-hosted Loom alternative: screen recording with shareable links

**[Deploy Cap | Open Source Loom Alternative on Railway](https://railway.com/template/cap-screen-recorder)**

- **Creator:** katsuba.dev
- **Category:** Other

## Template content

### Web https://cdn.jsdelivr.net/gh/CapSoftware/Cap@dffb42fe0d151f08f31be0e9b535d5e4941c6760/apps/web/public/logos/logo-solo.svg

- **Image:** ghcr.io/capsoftware/cap-web@sha256:a15efd82c37442d01fa95c4d94954baa1a84b20b8289b758d293fc51b1eb5d54
- **Start command:** `sh -c 'for i in $(seq 1 90); do [ -n "$DB_WAIT_JS" ] && node -e "$DB_WAIT_JS" 2>/dev/null && break; echo "waiting for mysql ($i/90)"; sleep 2; done; exec env HOSTNAME="$BIND_HOST" node apps/web/server.js'`
- **Health check:** /login
- **Public domain:** Yes

### MediaServer https://cdn.jsdelivr.net/gh/CapSoftware/Cap@dffb42fe0d151f08f31be0e9b535d5e4941c6760/apps/web/public/logos/logo-solo.svg

- **Image:** ghcr.io/capsoftware/cap-media-server@sha256:51fe32229aa016f5e333603d4901dc897eeb0038d2fbbc504369e3676863fc5a
- **Health check:** /health

### MySQL https://cdn.jsdelivr.net/gh/CapSoftware/Cap@dffb42fe0d151f08f31be0e9b535d5e4941c6760/apps/web/public/logos/logo-solo.svg

- **Image:** mysql:8.4.11
- **Start command:** `docker-entrypoint.sh mysqld --innodb-use-native-aio=0 --skip-log-bin --performance-schema=OFF --max-connections=500 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci`

## Buckets

- **Bucket**

## Documentation

# Deploy and Host Cap on Railway

Cap is an open-source screen recorder — record your screen and camera, get a shareable link in seconds, and let people comment on the timeline. It is the self-hosted alternative to Loom. This template deploys the full stack upstream ships: the web app, the ffmpeg media server that processes every recording, MySQL, and managed object storage for the video files.

## About Hosting Cap

Three services and a bucket, all from official upstream images:

- **Web** — the Cap application: dashboard, share pages, the API the desktop and mobile apps talk to, and the database migration that runs on boot. The only service with a domain.
- **MediaServer** — ffmpeg. Transcoding, thumbnails, the preview GIF, audio extraction. Private; nothing outside the project can reach it.
- **MySQL** — accounts, workspaces, recordings, comments, on a volume. Cap requires MySQL specifically.
- **Bucket** — Railway object storage for the recordings themselves, uploaded straight from the browser.

All 37 variables are filled in and described on the deploy screen. **There is nothing you have to supply** — open the URL, enter your email, and you are in.

Four things this template does that are worth knowing about:

**Recordings go to managed object storage, not a MinIO container.** The obvious way to self-host Cap is the one upstream's compose file uses: MinIO on a volume, holding every recording anyone ever made, with nobody backing it up. Here they go to a Railway bucket. Getting that right took one measurement worth repeating — Railway storage answers both S3 URL shapes, but only the `host/bucket/key` form sends CORS headers, and Cap's recorder uploads straight from the browser. With the other shape every upload is refused in the browser while `curl` cheerfully reports 200. Verified here by requesting a presigned URL through Cap's own API, uploading to it, and reading the preflight response back.

**Video processing actually finishes.** Cap's media server reports transcoding progress by calling back into the web app over the private network, and that callback carries a shared secret. Two things have to be true for it to land, and neither is the default: the web container has to listen on the project's IPv6 private network — its image hard-codes an IPv4-only bind that no environment variable can override — and both services need the same secret, because the webhook route answers 401 when either side is missing it. Measured from inside the deployment: the callback returns 200 with the right secret, 401 with a wrong one, and 401 with none.

**The images are pinned.** Cap publishes only `latest` and `beta` — there are no version tags to pin — so this template pins the **digest** of both images instead. That is the difference between a redeploy that gives you what you already had and one that quietly swaps the application under a running instance.

**MySQL is a supported version.** Upstream's compose file ships MySQL 8.0, which reached end of life in April 2026. This template runs 8.4 LTS, supported into 2032, with binary logging and the performance schema switched off — neither is useful on a single-instance deployment and together they cost several hundred megabytes of RAM and a steadily growing volume. All 40 of Cap's database migrations were run against 8.4 before this template was published.

## Common Use Cases

- **Async standups and updates**: record two minutes instead of writing four paragraphs, and drop the link in the channel.
- **Bug reports that show the bug**: a recording with the screen, the console and the reporter's voice, linked from the ticket.
- **Onboarding and support answers**: a small library of walkthroughs on a URL you control, rather than in a vendor's cloud on a per-seat plan.
- **Recordings that cannot leave your infrastructure**: customer screens, internal tooling, anything under a policy that rules out a hosted service.

## Dependencies for Cap Hosting

### Deployment Dependencies

- [Cap](https://github.com/CapSoftware/Cap) — the upstream project and its official images
- MySQL 8.4 for accounts, workspaces and recording metadata
- An S3-compatible bucket for the video files
- ffmpeg, in the media server container

### Implementation Details

- **Your login code appears in the deploy log.** Cap signs you in with a six-digit code sent by email, and it sends email through Resend — there is no generic SMTP option. Until you set `RESEND_API_KEY`, the code is printed to the **Web** service's log instead, which is how you sign in for the first time: enter your email, open the log, read the code. It works, and it means anyone who can read your Railway logs can sign in as anyone. Add a Resend key before you invite people.
- **Anyone who reaches the login page can create an account** — but they still need a code, which they cannot get. Set `CAP_ALLOWED_SIGNUP_DOMAINS` to your own domain once mail is configured, and that stops being theoretical.
- **New recordings are shareable by link** by default, matching upstream. `CAP_VIDEOS_DEFAULT_PUBLIC=false` makes them private until you share them.
- **Migrations run in the web container** on boot, and the start command waits for MySQL first. Railway starts services in parallel, so on a cold deploy the race is the default rather than the exception — and Cap gives up after three attempts.
- **The database is private.** No public TCP proxy on MySQL; it is reachable only from this project's private network.
- **AI features are opt-in.** Transcription needs an AssemblyAI key, summaries a Groq or OpenAI key, chat an Anthropic key. All four are on the deploy screen, empty, and nothing breaks without them.
- **The desktop and mobile apps** point at this instance by entering your URL on their sign-in screen — the same URL you open in the browser.

### Resource Usage and Cost

Measured on an idle deployment: **about 550 MB of RAM** across the three services — roughly 255 MB for the web app, 210 MB for MySQL and 85 MB for the media server — peaking near 1.3 GB during the first boot, while migrations run. Add the 5 GB volume MySQL is given and whatever the bucket holds.

That puts a quiet instance at roughly **$10–20/month**, but this is a product whose cost tracks use rather than uptime: transcoding is CPU-bound and happens on every upload, and video is the kind of thing that fills a bucket. Ten short recordings a week is a small bill; a team recording all day is not.

## Why Deploy Cap on Railway?

Cap needs four things that are annoying to assemble anywhere else: somewhere to run the app, a database, a machine with ffmpeg on it, and object storage the browser can upload to directly over HTTPS. Railway supplies the last one as a managed bucket rather than a container you have to back up, gives the media server a private address the app can reach without exposing it, and hands out the domain and certificate before the first deploy finishes.

The alternative is a VM with a compose file, where MinIO's data directory, the TLS certificate, the CORS configuration and the restart policy are all yours — and where the first thing you meet is a web container that exited because MySQL was not up yet.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — [Jul'26] Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/cap-screen-recorder
