---
title: "Deploy Cap Custom Domain"
description: "Serve Cap share links from your own domain"
category: "Other"
url: https://railway.com/deploy/deploy-cap-on-a-custom-domain
---

# Deploy Cap Custom Domain

Serve Cap share links from your own domain

**[Deploy Cap Custom Domain on Railway](https://railway.com/template/deploy-cap-on-a-custom-domain)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/deploy-cap-on-a-custom-domain/manifest.json

- **Creator:** onepush
- **Category:** Other

## Template content

### MySQL

- **Image:** mysql:8.0.46@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b
- **Start command:** `docker-entrypoint.sh mysqld --max_connections=1000 --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --performance-schema=OFF`

### media-server

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

### cap-web

- **Image:** ghcr.io/capsoftware/cap-web@sha256:8ee4cbd3fd87f88f538831aed06c954c525db9c2426a62abeaf0ca307c5e1ce9
- **Start command:** `node -e 'const e=process.env,fs=require("fs"),d=e.WORKFLOW_LOCAL_DATA_DIR||"/app/apps/web/.workflow-data";if(process.getuid()===0){fs.mkdirSync(d,{recursive:true});fs.chownSync(d,1001,1001);process.setgroups([1001]);process.setgid(1001);process.setuid(1001);console.log("[railway] workflow data in "+d+", running as uid "+process.getuid())}try{const{S3Client:C,PutBucketCorsCommand:P}=require("/app/node_modules/.pnpm/node_modules/@aws-sdk/client-s3");new C({endpoint:e.S3_INTERNAL_ENDPOINT,region:e.CAP_AWS_REGION,forcePathStyle:e.S3_PATH_STYLE==="true",credentials:{accessKeyId:e.CAP_AWS_ACCESS_KEY||"",secretAccessKey:e.CAP_AWS_SECRET_KEY||""}}).send(new P({Bucket:e.CAP_AWS_BUCKET,CORSConfiguration:{CORSRules:[{AllowedOrigins:[e.WEB_URL],AllowedMethods:["GET","HEAD","PUT","POST"],AllowedHeaders:["*"],ExposeHeaders:["ETag"],MaxAgeSeconds:3600}]}})).then(()=>console.log("[railway] bucket CORS set for "+e.WEB_URL),x=>console.error("[railway] bucket CORS not set: "+x.name+" "+x.message))}catch(x){console.error("[railway] bucket CORS skipped: "+x.message)}e.HOSTNAME="::";require("/app/apps/web/server.js")'`
- **Health check:** /api/status
- **Public domain:** Yes

## Buckets

- **Bucket**

## Documentation

# Deploy and Host self hosted Cap Custom Domain (Self-Hosted Screen Recorder on Your Own Domain) on Railway

This template runs self-hosted Cap with every share link on your own domain, like video.company.com.

## About Hosting Cap Custom Domain open-source software on Railway (self hosted Cap on your own domain template)

Cap is an open-source screen recorder, and this template runs its full stack on Railway: cap-web for the dashboard and share pages, a private media-server, a MySQL 8.0 database, and a private Railway Bucket for recordings.

This version puts your own hostname, such as video.company.com, in front of cap-web.

## Why Deploy Cap Custom Domain, the Loom alternative on Railway (Railway Free Trial)

Loom charges per seat and gates custom branding behind paid plans, so every viewer and seat costs money.

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 Cap Custom Domain 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.

### Railway vs Other Hosting Providers and VPS for Cap Custom Domain self hosting

A VPS makes you wire up the app, database, bucket, and domain yourself, while Railway packages them as one template.

| Provider | What You Get with Railway | What You Get with the Other Provider |
| --- | --- | --- |
| DigitalOcean | Custom domain added on cap-web with a CNAME and edge TLS, plus WEB_URL changed in one variable. | A droplet where you set up Nginx, certificates, and keep WEB_URL and bucket CORS in sync by hand. |
| AWS | Railway Bucket attached, with CORS re-applied for the new origin on every boot. | Route 53, ACM, and an S3 bucket policy you write and maintain yourself. |
| Hetzner | Managed domain and certificate handling, with redeploys carrying the new origin into the bucket CORS rule. | Cheap servers where the domain, reverse proxy, and bucket CORS are all your responsibility. |

Railway trades some low-level control for a faster path to a branded share link.

## Common Use Cases for hosted Cap Custom Domain

- **Branded support videos:** Your support team records a quick fix and sends a link like video.company.com/s/abc123, so customers see your domain instead of a generic recording service.
- **Sales demos on your domain:** Account executives send demo recordings from demos.company.com, which keeps the buyer inside your brand from first click to follow-up.
- **Internal recordings behind sign-ups:** Engineering and ops share walkthroughs on a private instance locked to your company domain with CAP_ALLOWED_SIGNUP_DOMAINS, so only staff can view and upload.
- **Docs and changelog videos:** Product marketing hosts release videos on a docs subdomain, so embeds and links stay under the same domain as your documentation.
- **Replacing Loom links in a help center:** Support articles swap old Loom links for Cap links on your own domain, and the share pages keep working after you move the server.

## Dependencies for Cap Custom Domain Docker hosted on Railway

Cap Custom Domain runs as four parts, and the custom domain lives only on cap-web.

### Deployment Dependencies for Managed Cap Custom Domain Service (Screen Recording)

- **cap-web:** official ghcr.io/capsoftware/cap-web image pinned by digest, port 3000, volume at /app/apps/web/.workflow-data.
- **media-server:** official ghcr.io/capsoftware/cap-media-server image pinned by digest, private port 3456, no volume.
- **MySQL:** MySQL 8.0.46 pinned by digest, private port 3306, volume at /var/lib/mysql.
- **Railway Bucket:** private S3-compatible storage for recordings, reached through presigned URLs.

### Implementation Details for Cap Custom Domain (Using Cap official docker image)

The cap-web start command resets the bucket CORS rule to allow only WEB_URL on every boot, so a domain change needs a redeploy.

## How does Cap Custom Domain compare against other ways to share recordings from your own domain

### Cap vs Loom custom domains (Loom Alternative)

- **Where Loom wins:** Loom is polished and hosted, with almost no setup and no server to run.
- **Where Cap wins:** Share links live on your own domain, such as video.company.com, and recordings sit in a bucket you control.
- **Cost shape:** Loom sells per-seat plans, while Cap is free to self host and you pay only the Railway bill.
- **Trade-off:** You own uptime and backups, which Loom absorbs for you.

### Cap vs Vimeo (Vimeo Alternative)

- **Where Vimeo wins:** Vimeo has mature video delivery and a large set of integrations.
- **Where Cap wins:** Cap is built for desktop screen recordings with a share page and comments, not a general video library.
- **Branding:** Cap serves share pages from the domain in WEB_URL, while Vimeo branded players are a paid-tier feature.
- **Trade-off:** Vimeo handles far more traffic than a single Cap instance.

### Cap vs Tella (Tella Alternative)

- **Where Tella wins:** Tella offers a guided recorder with scenes and layouts, and you never think about infrastructure.
- **Where Cap wins:** Cap is open source under AGPL-3.0, so you can read the code and run it on a Railway service you control.
- **Hosting:** Recordings and share links stay on your domain and bucket, with no third-party recorder account in between.
- **Trade-off:** Tella's recording flow is more polished, and Cap asks you to set the custom domain and desktop server URL yourself.

### Cap vs Screen Studio (Screen Studio Alternative)

- **Where Screen Studio wins:** It is a focused macOS app that makes polished auto-zoomed demos with strong local editing.
- **Where Cap wins:** Cap adds a shared server, so finished videos get a link on your domain that teammates open without downloading.
- **Scope:** Screen Studio has no self-hosted share server, so publishing usually means exporting and uploading elsewhere.
- **Trade-off:** For editing clips on one Mac, Screen Studio is simpler, and Cap is worth running when you want shared links on your own domain.

## How to use Cap Custom Domain (the OSS screen recorder)?

1. Pick a subdomain for your team, such as video.company.com, and decide whether it will be the only address people use.
2. In Railway, open the cap-web service, go to Settings, Networking, and add video.company.com under Custom domain.
3. Create the CNAME record Railway shows in your DNS provider, then wait for the TLS certificate to issue at the edge.
4. Set WEB_URL on cap-web to https://video.company.com and redeploy, which also updates NEXTAUTH_URL and MEDIA_SERVER_WEB_ORIGIN by reference.
5. Sign in at the new domain, then open Cap Desktop, go to Settings, and set Cap Server URL to https://video.company.com.
6. Record a short clip and check that the share link starts with https://video.company.com/s/.

```
DNS (at your DNS provider):
video.company.com  CNAME  target-shown-by-railway

Railway, cap-web variables:
WEB_URL=https://video.company.com
```

## How to self host Cap Custom Domain on other VPS Services (Cap self hosting guide)

### Clone the Repository

Clone the upstream Cap repository so you have the compose file and the web and media server sources to build or pin from.

```bash
git clone https://github.com/CapSoftware/Cap.git
cd Cap
```

### Install Dependencies

Install Docker and the Docker Compose plugin on your VPS, then confirm both respond before going further.

```bash
docker --version
docker compose version
```

### Configure Environment Variables

Set your public URL and replace every default secret, since the upstream compose file ships publicly known values.

```bash
WEB_URL=https://your-domain
NEXTAUTH_URL=https://your-domain
NEXTAUTH_SECRET=replace-with-64-hex-characters
DATABASE_ENCRYPTION_KEY=replace-with-64-hex-characters
```

Add your S3 credentials and bucket settings as well, since recordings are stored in object storage rather than on the web container.

### Start the Cap Custom Domain Application

Bring the stack up in the background, then check that the web service answers its health endpoint.

```bash
docker compose up -d
curl -f https://your-domain/api/status
```

Railway handles TLS, the bucket CORS rule, database migrations, and the private networking between services for you, so none of these steps are needed there.

## Official Pricing of Cap Custom Domain (Cap pricing)

Cap itself is free and open source under AGPL-3.0, so there is no license fee to pay for the custom domain setup.

## Cap Custom Domain cloud vs self hosted comparison (Pricing, features, costs, and more)

Self hosting puts your share links on your own domain, with recordings in a bucket you control.

### Monthly cost of self hosting Cap Custom Domain on Railway

A small team running cap-web, media-server, MySQL, and the Railway Bucket typically lands around $10 to $20 per month at idle, plus bucket storage.

### System Requirements for Hosting Cap Custom Domain on a VPS

Plan for roughly 850 MB of RAM at idle across cap-web, MySQL, and media-server, with headroom since the media server grows during long recordings.

## Frequently Asked Questions (FAQs)

### Do old share links still work after I add my domain?

Yes, as long as you keep the original railway.app domain attached to cap-web.

### Why do uploads fail after I change the domain?

Uploads go straight to the Railway Bucket, and its CORS rule is set to allow only WEB_URL.

### Do I need to change NEXTAUTH_URL too?

No.

### Can I use a root domain instead of a subdomain?

You can, but the root domain needs an ALIAS or flattened record instead of a plain CNAME, because a CNAME cannot sit at the apex.

### Does the bucket need its own domain?

No.

### How do I set up email login codes?

Add RESEND_API_KEY and RESEND_FROM_DOMAIN to cap-web and verify your domain in Resend.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — 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/deploy-cap-on-a-custom-domain
