Self-hosting Thread
How to deploy Thread on your own infrastructure
Thread is the web application for uploading, sharing, and managing Threads. You can upload videos to it from the dashboard or from Thread Desktop.
Quick Start (One Command)
The fastest way to self-host Thread is with Docker Compose. This single command will start everything you need:
git clone https://github.com/Hxnnyy/Arkwright-Cap.git
cd Arkwright-Cap
docker compose up -dThat's it. Your local Thread instance will be available at http://localhost:3000.
The default docker-compose.yml includes placeholder secrets for quick local testing. If you're deploying to a public server or production environment, you must change these values. See the Production Checklist below.
Login links will appear in the logs since email isn't configured:
docker compose logs cap-webDeployment Options
Option 1: Docker Compose (Recommended)
Best for VPS, home servers, or any Docker-capable host.
What's included:
- Thread web application
- Media server (FFmpeg processing)
- MySQL database
- MinIO (S3-compatible storage)
Steps:
- Clone the repository
- Run
docker compose up -d - Access Thread at
http://localhost:3000
Note: The main
docker-compose.ymlbuilds the media server from source, so a full clone of the repository is required. The Coolify compose file uses a pre-built image fromghcr.ioinstead.
Custom configuration:
Create a .env file to customize your deployment:
# Public web URL (required for production)
CAP_URL=https://thread.yourdomain.com
# S3 public URL (for video playback)
S3_PUBLIC_URL=https://s3.yourdomain.com
# Optional: Custom ports
CAP_PORT=3000
MINIO_PORT=9000
# Optional: Custom passwords (auto-generated if not set)
MYSQL_PASSWORD=your-secure-password
MINIO_ROOT_PASSWORD=your-minio-passwordThe bundled docker-compose.yml still uses the CAP_URL variable name for historical reasons, but it should point at your Thread web host.
If you run separate web and share hosts in a custom deployment, set WEB_URL to your main app host and SHARE_URL to your public share host on the web container directly.
Option 2: Railway (One-Click)
Railway provides a fully managed deployment with automatic SSL and scaling. Login credentials appear in Railway's Deploy Logs after deployment.
Option 3: Coolify
For Coolify users, use docker-compose.coolify.yml which includes environment variable placeholders:
- Create a new Docker Compose project in Coolify
- Point to the Thread repository
- Set compose file to
docker-compose.coolify.yml - Configure environment variables in Coolify's UI
- Deploy
Note: The Coolify compose file uses slightly different environment variable names:
WEB_URLinstead ofCAP_URL, andS3_PUBLIC_ENDPOINTinstead ofS3_PUBLIC_URL.
Connecting Thread Desktop
- Open Thread Desktop settings
- Set the server URL to your deployment URL (for example
https://thread.yourdomain.com) - Uploads will now go to your self-hosted instance
Email Configuration
By default, login links are printed to the server logs. To send emails:
- Create an account at Resend
- Add these environment variables:
RESEND_API_KEY=re_xxxxx RESEND_FROM_DOMAIN=yourdomain.com
Workflow And AI
Thread uses workflow endpoints under /.well-known/workflow/* for background jobs. Keep that path publicly reachable and exempt from auth middleware or the transcript and summary jobs will never run.
Optional Features
AI Features
For video transcription and AI summaries:
DEEPGRAM_API_KEY=your-key # Transcription
GROQ_API_KEY=your-key # AI summaries (preferred)
OPENAI_API_KEY=your-key # AI summaries (fallback, uses gpt-5.4-nano)Google OAuth
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-secretProduction Checklist
The default docker-compose.yml contains hardcoded placeholder secrets that are visible in the public repository. Anyone who knows you're using Thread with defaults could potentially:
- Forge authentication sessions (via
NEXTAUTH_SECRET) - Decrypt sensitive database fields (via
DATABASE_ENCRYPTION_KEY) - Spoof webhook requests (via
MEDIA_SERVER_WEBHOOK_SECRET)
This is fine for local development or testing on a private network, but you must generate unique secrets before exposing Thread to the internet.
Generate secure secrets:
openssl rand -hex 32Run this command three times to generate values for:
NEXTAUTH_SECRETDATABASE_ENCRYPTION_KEYMEDIA_SERVER_WEBHOOK_SECRET
Full production checklist:
- Set secure passwords:
MYSQL_PASSWORD,MINIO_ROOT_PASSWORD - Set secure secrets:
DATABASE_ENCRYPTION_KEY,NEXTAUTH_SECRET,MEDIA_SERVER_WEBHOOK_SECRET - Set
CAP_URLto your public URL - Set
S3_PUBLIC_URLto your MinIO/S3 public URL - Configure a reverse proxy (nginx, Caddy, Traefik) with SSL
- Set up email with Resend
- Configure backups for MySQL and MinIO volumes
Architecture
┌─────────────────┐ ┌─────────────────┐
│ Thread Desktop │────▶│ Thread Web │
└─────────────────┘ │ (port 3000) │
└────────┬────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ MySQL │ │ MinIO │ │ Media │
│ (3306) │ │ (9000) │ │ Server │
└──────────┘ └──────────┘ └──────────┘
Environment Variables Reference
See packages/env/server.ts for all available options.
Troubleshooting
Can't access Thread after starting:
docker compose logs cap-webDatabase migration issues:
docker compose down -v # Warning: deletes data
docker compose up -dReset everything:
docker compose down -v
docker compose up -dSupport
If you encounter issues with self-hosting:
- Open a GitHub issue
- Check existing issues for solutions
We do not offer direct support for self-hosted deployments.