Overview
This guide covers two installation scenarios:
Development setup — For contributing to OpenCut or running it locally
Self-hosting with Docker — For running your own production instance
Development setup Set up a local development environment
Self-hosting Deploy your own production instance
Development setup
Prerequisites
Before you begin, ensure you have:
Docker is optional but recommended. If you only want to work on frontend features, you can skip the Docker setup.
Step 1: Clone the repository
Fork and clone the OpenCut repository:
# Clone your fork (replace YOUR-USERNAME with your GitHub username)
git clone https://github.com/YOUR-USERNAME/OpenCut.git
cd OpenCut
Contributing? Make sure to fork the repository first so you can submit pull requests later.
Step 2: Environment configuration
Copy the example environment file and configure it:
Unix/Linux/Mac
Windows Command Prompt
Windows PowerShell
cp apps/web/.env.example apps/web/.env.local
Edit apps/web/.env.local with your configuration:
# Node environment
NODE_ENV = development
# Public URLs
NEXT_PUBLIC_SITE_URL = http://localhost:3000
NEXT_PUBLIC_MARBLE_API_URL = https://api.marblecms.com
# Database (matches docker-compose.yml)
DATABASE_URL = "postgresql://opencut:opencut@localhost:5432/opencut"
# Authentication
BETTER_AUTH_SECRET = your_better_auth_secret
# Redis (matches docker-compose.yml)
UPSTASH_REDIS_REST_URL = http://localhost:8079
UPSTASH_REDIS_REST_TOKEN = example_token
# Optional: Marble CMS for blog
MARBLE_WORKSPACE_KEY = your_workspace_key_here
# Optional: Freesound audio library
FREESOUND_CLIENT_ID = your_client_id_here
FREESOUND_API_KEY = your_api_key_here
# Optional: Auto-captions (Cloudflare R2 + Modal)
CLOUDFLARE_ACCOUNT_ID = your_account_id_here
R2_ACCESS_KEY_ID = your_access_key_here
R2_SECRET_ACCESS_KEY = your_secret_key_here
R2_BUCKET_NAME = opencut-transcription
MODAL_TRANSCRIPTION_URL = your_modal_url_here
Generate BETTER_AUTH_SECRET
You need a secure secret for authentication. Generate one using any of these methods: Unix/Linux/Mac
Node.js (cross-platform)
Windows PowerShell
Or use an online generator: generate-secret.vercel.app/32
The default values in .env.example match the Docker Compose configuration and should work out of the box for local development.
Step 3: Start services
If using Docker, start the database and Redis services:
# Start only the required services for development
docker compose up -d db redis serverless-redis-http
This starts:
PostgreSQL on localhost:5432
Redis on localhost:6379
Serverless Redis HTTP on localhost:8079
Check if services are running: View logs: # All services
docker compose logs -f
# Specific service
docker compose logs -f db
Stop services:
Step 4: Install dependencies
Install project dependencies:
If you see Unsupported URL Type "workspace:*" with npm, upgrade to npm v9+ or use Bun/pnpm instead.
Step 5: Database setup
Run database migrations (only if using Docker):
cd apps/web
bun run db:migrate
cd ../..
Available database commands: # Generate migration files
bun run db:generate
# Run migrations
bun run db:migrate
# Push schema to local database
bun run db:push:local
# Push schema to production database
bun run db:push:prod
Step 6: Start development server
Start the Next.js development server:
The application will be available at http://localhost:3000 .
Success! Your development environment is ready. Changes to the code will automatically reload thanks to hot module replacement.
Self-hosting with Docker
Run your own production instance of OpenCut using Docker Compose.
Prerequisites
Docker and Docker Compose
A server or VPS with at least 2GB RAM
(Optional) A domain name for public access
Quick deployment
The simplest way to run OpenCut in production:
Clone the repository
git clone https://github.com/OpenCut-app/OpenCut.git
cd OpenCut
Configure environment
Create a .env file in the project root for production configuration: # Generate a secure secret
BETTER_AUTH_SECRET = your-production-secret-here
# Optional: Freesound integration
FREESOUND_CLIENT_ID = your_client_id
FREESOUND_API_KEY = your_api_key
# Optional: Marble CMS blog
MARBLE_WORKSPACE_KEY = your_workspace_key
# Optional: Auto-captions
CLOUDFLARE_ACCOUNT_ID = your_account_id
R2_ACCESS_KEY_ID = your_r2_access_key
R2_SECRET_ACCESS_KEY = your_r2_secret
R2_BUCKET_NAME = opencut-transcription
MODAL_TRANSCRIPTION_URL = your_modal_url
Never commit your .env file! It contains sensitive credentials. The file is already in .gitignore.
Start all services
This builds and starts:
OpenCut web application
PostgreSQL database
Redis cache
Serverless Redis HTTP adapter
The app will be available at http://localhost:3100 .
Docker Compose configuration
The docker-compose.yml includes all necessary services:
services :
# PostgreSQL database
db :
image : postgres:17
ports :
- "5432:5432"
environment :
POSTGRES_USER : opencut
POSTGRES_PASSWORD : opencut
POSTGRES_DB : opencut
volumes :
- postgres_data:/var/lib/postgresql/data
# Redis cache
redis :
image : redis:7-alpine
ports :
- "6379:6379"
# Serverless Redis HTTP adapter
serverless-redis-http :
image : hiett/serverless-redis-http:latest
ports :
- "8079:80"
environment :
SRH_TOKEN : example_token
SRH_CONNECTION_STRING : "redis://redis:6379"
# OpenCut web application
web :
build :
context : .
dockerfile : ./apps/web/Dockerfile
ports :
- "3100:3000"
environment :
NODE_ENV : production
DATABASE_URL : postgresql://opencut:opencut@db:5432/opencut
# ... other environment variables
To change the external port, edit the ports mapping in docker-compose.yml: ports :
- "8080:3000" # Change 8080 to your desired port
Production considerations
For production, use a reverse proxy like Nginx or Caddy: Nginx example: server {
listen 80 ;
server_name opencut.yourdomain.com;
location / {
proxy_pass http://localhost:3100;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection 'upgrade' ;
proxy_set_header Host $ host ;
proxy_cache_bypass $ http_upgrade ;
}
}
Caddy example: opencut.yourdomain.com {
reverse_proxy localhost:3100
}
Use Let’s Encrypt for free SSL certificates: # With Caddy (automatic)
caddy run
# With Certbot + Nginx
sudo certbot --nginx -d opencut.yourdomain.com
Update NEXT_PUBLIC_SITE_URL in your environment: NEXT_PUBLIC_SITE_URL = https://opencut.yourdomain.com
Set up automated PostgreSQL backups: # Manual backup
docker compose exec db pg_dump -U opencut opencut > backup.sql
# Restore from backup
docker compose exec -T db psql -U opencut opencut < backup.sql
Consider using automated backup solutions like:
View logs: # All services
docker compose logs -f
# Specific service
docker compose logs -f web
# Last 100 lines
docker compose logs --tail=100
Consider adding monitoring:
Set resource limits in docker-compose.yml: services :
web :
deploy :
resources :
limits :
cpus : '2'
memory : 2G
reservations :
cpus : '1'
memory : 1G
Project structure
Understanding the codebase structure:
OpenCut/
├── apps/
│ └── web/ # Main Next.js application
│ ├── src/
│ │ ├── app/ # Next.js app router pages
│ │ ├── components/ # React components
│ │ ├── core/ # Editor core system
│ │ ├── hooks/ # Custom React hooks
│ │ ├── lib/ # Business logic and utilities
│ │ ├── services/ # External services (renderer, etc.)
│ │ ├── stores/ # Zustand state management
│ │ └── types/ # TypeScript type definitions
│ ├── public/ # Static assets
│ ├── Dockerfile # Production Docker image
│ └── package.json # Web app dependencies
├── packages/ # Shared packages
│ ├── env/ # Environment configuration
│ └── ui/ # Shared UI components
├── docker-compose.yml # Docker services configuration
├── turbo.json # Turborepo configuration
└── package.json # Root workspace configuration
See AGENTS.md in the repository for detailed architecture documentation.
Troubleshooting
If ports are already in use: # Check what's using a port (macOS/Linux)
lsof -i :3000
# Check what's using a port (Windows)
netstat -ano | findstr :3000
# Kill process by PID
kill -9 < PI D > # macOS/Linux
taskkill /PID < PI D > /F # Windows
Common Docker problems: # Restart Docker Desktop
# macOS: Restart from menu bar icon
# Windows: Restart from system tray
# Clear Docker cache
docker system prune -a
# Rebuild containers
docker compose down -v
docker compose build --no-cache
docker compose up -d
If the build fails: # Clear bun cache
rm -rf node_modules
rm -rf apps/web/node_modules
bun install
# Clear Next.js cache
rm -rf apps/web/.next
bun build:web
Database connection errors
Verify database connectivity: # Check if database is running
docker compose ps db
# Test connection
docker compose exec db psql -U opencut -d opencut -c "SELECT 1;"
# Check logs
docker compose logs db
Next steps
Contributing Learn how to contribute to OpenCut
Architecture Understand the editor architecture
Core concepts Learn about the editor core system
API reference Explore the API documentation