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 -d

That's it. Your local Thread instance will be available at http://localhost:3000.

Security Notice for Production Deployments

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-web

Deployment Options

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:

  1. Clone the repository
  2. Run docker compose up -d
  3. Access Thread at http://localhost:3000

Note: The main docker-compose.yml builds the media server from source, so a full clone of the repository is required. The Coolify compose file uses a pre-built image from ghcr.io instead.

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-password

The 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)

Deploy on Railway

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:

  1. Create a new Docker Compose project in Coolify
  2. Point to the Thread repository
  3. Set compose file to docker-compose.coolify.yml
  4. Configure environment variables in Coolify's UI
  5. Deploy

Note: The Coolify compose file uses slightly different environment variable names: WEB_URL instead of CAP_URL, and S3_PUBLIC_ENDPOINT instead of S3_PUBLIC_URL.

Connecting Thread Desktop

  1. Open Thread Desktop settings
  2. Set the server URL to your deployment URL (for example https://thread.yourdomain.com)
  3. Uploads will now go to your self-hosted instance

Email Configuration

By default, login links are printed to the server logs. To send emails:

  1. Create an account at Resend
  2. 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-secret

Production Checklist

Critical: Change Default Secrets Before Going Public

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 32

Run this command three times to generate values for:

  • NEXTAUTH_SECRET
  • DATABASE_ENCRYPTION_KEY
  • MEDIA_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_URL to your public URL
  • Set S3_PUBLIC_URL to 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-web

Database migration issues:

docker compose down -v  # Warning: deletes data
docker compose up -d

Reset everything:

docker compose down -v
docker compose up -d

Support

If you encounter issues with self-hosting:

We do not offer direct support for self-hosted deployments.

Self-hosting Thread - Thread Docs