Skip to main content
This guide covers common issues you might encounter when self-hosting Cap and how to resolve them.

General Debugging

Check Service Status

Verify all services are running:
docker compose ps
Expected output:
NAME                 STATUS
cap-web              Up (healthy)
cap-media-server     Up (healthy)
cap-mysql            Up (healthy)
cap-minio            Up (healthy)
cap-minio-setup      Exited (0)

View Logs

# All services
docker compose logs -f

# Specific service
docker compose logs cap-web -f

# Last 100 lines
docker compose logs --tail=100 cap-web

# Since specific time
docker compose logs --since 10m cap-web

Restart Services

# Restart all
docker compose restart

# Restart specific service
docker compose restart cap-web

# Full restart (recreate containers)
docker compose down
docker compose up -d

Installation Issues

Port Already in Use

Error:
Error starting userland proxy: listen tcp 0.0.0.0:3000: bind: address already in use
Solution: Find and stop the process using the port
# Find process
sudo lsof -i :3000

# Or
sudo netstat -tulpn | grep :3000

# Kill process
sudo kill -9 <PID>

# Or change Cap port
echo "CAP_PORT=8080" >> .env
docker compose down
docker compose up -d

Docker Not Running

Error:
Cannot connect to the Docker daemon
Solution:
# Start Docker
sudo systemctl start docker

# Enable on boot
sudo systemctl enable docker

# Check status
sudo systemctl status docker

Permission Denied

Error:
permission denied while trying to connect to the Docker daemon socket
Solution:
# Add user to docker group
sudo usermod -aG docker $USER

# Log out and back in
# Or run:
newgrp docker

# Test
docker ps

Image Pull Fails

Error:
Error response from daemon: manifest for ghcr.io/capsoftware/cap-web:latest not found
Solution:
# Check internet connection
ping -c 3 github.com

# Try pulling manually
docker pull ghcr.io/capsoftware/cap-web:latest

# If behind proxy, configure Docker proxy
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf
# Add:
# [Service]
# Environment="HTTP_PROXY=http://proxy.example.com:80"
# Environment="HTTPS_PROXY=https://proxy.example.com:443"

Application Issues

Can’t Access Cap Web

Symptom: Browser shows “Connection refused” at http://localhost:3000
1

Check if container is running

docker compose ps cap-web
If not running:
docker compose up -d cap-web
2

Check health status

docker inspect cap-web | grep -A 10 Health
If unhealthy, check logs:
docker compose logs cap-web
3

Test from inside container

docker compose exec cap-web wget -O- http://localhost:3000
If this works but external access doesn’t, it’s a networking issue.
4

Check firewall

sudo ufw status
sudo ufw allow 3000/tcp

Database Connection Errors

Error in logs:
Error: connect ECONNREFUSED mysql:3306
Wait for MySQL to finish initializing:
docker compose logs mysql | grep "ready for connections"
If not ready, wait 30-60 seconds and check again.
Verify connection string:
docker compose exec cap-web env | grep DATABASE_URL
Should be:
mysql://cap:password@mysql:3306/cap
Fix in .env and restart:
docker compose restart cap-web
Test connection from cap-web to mysql:
docker compose exec cap-web ping mysql
docker compose exec cap-web nc -zv mysql 3306
If fails, recreate network:
docker compose down
docker network prune
docker compose up -d

S3/MinIO Errors

Error: Videos won’t upload or display
1

Check MinIO is running

docker compose ps minio
Access console:
http://localhost:9001
Login with MINIO_ROOT_USER and MINIO_ROOT_PASSWORD
2

Verify bucket exists

docker compose exec minio mc ls local/
Should show cap bucket. If not:
docker compose exec minio mc mb local/cap
docker compose exec minio mc anonymous set download local/cap
3

Check S3 credentials

docker compose exec cap-web env | grep CAP_AWS
Verify:
  • CAP_AWS_ACCESS_KEY matches MINIO_ROOT_USER
  • CAP_AWS_SECRET_KEY matches MINIO_ROOT_PASSWORD
4

Test S3 upload

docker compose exec cap-web sh -c '
  echo "test" > /tmp/test.txt
  aws s3 cp /tmp/test.txt s3://cap/test.txt \
    --endpoint-url $S3_INTERNAL_ENDPOINT
'

Authentication Issues

Symptom: Can’t log in or session expires immediately
docker compose exec cap-web env | grep NEXTAUTH_SECRET
If empty, generate and add to .env:
openssl rand -hex 32
Then:
.env
NEXTAUTH_SECRET=your-generated-secret
Must match actual access URL:
.env
# Local
NEXTAUTH_URL=http://localhost:3000

# Production
NEXTAUTH_URL=https://cap.yourdomain.com
Check if sessions table exists:
docker compose exec mysql mysql -u cap -p cap -e "SHOW TABLES LIKE 'session';"
If empty, run migrations:
docker compose exec cap-web pnpm db:push

Email Issues

No Login Email Received

1

Check if Resend is configured

docker compose exec cap-web env | grep RESEND
If empty, emails go to logs instead:
docker compose logs cap-web | grep "Login link"
2

Verify Resend API key

Test with curl:
curl -X POST 'https://api.resend.com/emails' \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "[email protected]",
    "to": "[email protected]",
    "subject": "Test",
    "html": "<p>Test</p>"
  }'
3

Check spam folder

Login emails might be marked as spam initially.
4

Verify domain

In Resend dashboard, check domain is verified.

Email Sends but Errors in Logs

docker compose logs cap-web | grep -i "error\|fail"
Common errors:
  • Invalid API key - Wrong RESEND_API_KEY
  • Domain not verified - Verify domain in Resend
  • Rate limit exceeded - Wait or upgrade Resend plan

Video Processing Issues

Videos Stuck in Processing

1

Check media server logs

docker compose logs media-server
Look for FFmpeg errors.
2

Verify media server is running

docker compose ps media-server
Test health:
curl http://localhost:3456/health
3

Check MEDIA_SERVER_WEBHOOK_SECRET

Must match between cap-web and media-server:
docker compose exec cap-web env | grep MEDIA_SERVER_WEBHOOK_SECRET
docker compose exec media-server env | grep MEDIA_SERVER_WEBHOOK_SECRET
4

Manually retry processing

Find video in database and trigger reprocessing:
docker compose exec mysql mysql -u cap -p cap

UPDATE videos SET status = 'pending' WHERE id = 'video-id';

Video Playback Errors

Symptom: Video uploaded but won’t play
F12 → Console shows:
Access to video from origin 'https://cap.yourdomain.com' has been blocked by CORS
Fix: Configure S3 CORSMinIO:
docker compose exec minio mc anonymous set public local/cap
AWS S3: Add CORS configuration (see S3 Storage)
Verify file exists in S3:
docker compose exec minio mc ls local/cap/videos/
If missing, reprocess video.
Video URL should be accessible from browser:
curl -I http://localhost:9000/cap/videos/test.mp4
Update .env:
S3_PUBLIC_ENDPOINT=http://localhost:9000

SSL/HTTPS Issues

Certificate Not Obtained

Let’s Encrypt errors in Caddy/Nginx logs
1

Verify DNS

dig cap.yourdomain.com
nslookup cap.yourdomain.com
Should point to your server IP.
2

Check port 80 is open

sudo ufw status | grep 80
telnet yourdomain.com 80
Let’s Encrypt requires port 80 for HTTP challenge.
3

Check rate limits

Let’s Encrypt limits:
  • 50 certs per domain per week
  • 5 failures per hour
Wait 1 hour or use staging:
sudo certbot --nginx --staging

Mixed Content Warnings

Browser: “This page includes insecure resources”
1

Update all URLs to HTTPS

.env
WEB_URL=https://cap.yourdomain.com
NEXTAUTH_URL=https://cap.yourdomain.com
S3_PUBLIC_ENDPOINT=https://s3.yourdomain.com
2

Check video URLs in database

If videos were uploaded before HTTPS, URLs might be HTTP.Update:
UPDATE videos 
SET thumbnail_url = REPLACE(thumbnail_url, 'http://', 'https://');

Performance Issues

Slow Page Loads

1

Check resource usage

docker stats
Look for high CPU or memory usage.
2

Check database performance

docker compose exec mysql mysql -u cap -p cap -e "SHOW PROCESSLIST;"
Look for slow queries.
3

Enable database query logging

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
View slow queries:
docker compose exec mysql cat /var/lib/mysql/slow-query.log
4

Check network latency

docker compose exec cap-web ping mysql
docker compose exec cap-web ping minio

High CPU Usage

Media server at 100% CPU This is normal during video processing. FFmpeg is CPU-intensive. To reduce:
  • Process videos at lower quality
  • Add more media server workers
  • Use external transcoding service

Out of Memory

Error: Killed or OOMKilled
1

Check memory usage

docker stats
free -h
2

Increase Docker memory limits

docker-compose.yml
services:
  cap-web:
    deploy:
      resources:
        limits:
          memory: 2G
3

Add swap

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Make permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Docker Issues

Disk Space Full

# Check Docker disk usage
docker system df

# Remove unused images
docker image prune -a

# Remove unused volumes
docker volume prune

# Full cleanup
docker system prune -a --volumes
docker system prune -a --volumes removes ALL unused data. Be careful with volumes.

Network Issues

Services can’t communicate
# Inspect network
docker network inspect cap_cap-network

# Recreate network
docker compose down
docker network prune
docker compose up -d

Container Won’t Start

# Check exit code
docker compose ps -a

# View full logs
docker compose logs --tail=500 <service-name>

# Try starting in foreground
docker compose up <service-name>

# Remove and recreate
docker compose rm -f <service-name>
docker compose up -d <service-name>

Complete Reset

This deletes ALL data including videos, users, and database.
When all else fails:
# Stop and remove everything
docker compose down -v

# Remove images
docker rmi ghcr.io/capsoftware/cap-web:latest
docker rmi ghcr.io/capsoftware/cap-media-server:latest

# Clean Docker
docker system prune -a

# Start fresh
docker compose up -d

Getting Help

Collect Debug Info

Before asking for help, collect:
# System info
uname -a
docker --version
docker compose version

# Service status
docker compose ps

# Recent logs
docker compose logs --tail=100 > cap-logs.txt

# Environment (remove secrets!)
docker compose exec cap-web env | grep -v "SECRET\|KEY\|PASSWORD"

Where to Get Help

Reporting Bugs

Include:
  1. Environment: OS, Docker version, deployment method
  2. Steps to reproduce: Exact steps to trigger the issue
  3. Expected behavior: What should happen
  4. Actual behavior: What actually happens
  5. Logs: Relevant error messages and stack traces
  6. Configuration: Sanitized environment variables

Next Steps

Architecture

Understand how Cap works

Scaling

Optimize for performance

Environment Variables

Review configuration options

Docker Compose

Deployment guide

Build docs developers (and LLMs) love