- Create a file named
.backend.envwith the following attributes:
CLIENT_ID="client_ID" # Google Auth Secret from Prerequisites
CLIENT_SEC="client_SECRET" # Google Auth Secret from Prerequisites
REDIRECT_URL_DEV="http://localhost:8000/auth/callback"
SESSION_KEY="generate a secret key using 'openssl rand -hex 32'"
FRONTEND_ORIGIN_DEV="http://localhost" # URL of the web frontend to avoid CORS errors
CONTAINER_ORIGIN="http://production-syncserver-1:8080/" # Deployed taskchampion-sync-server container- Run
docker-compose pullto pull the CCSync images. - Run
docker-compose upto start the project. - The frontend should now be available at localhost:80, the backend at localhost:8000, and the sync server at localhost:8080
For production deployments with HTTPS, use nginx as a reverse proxy with Let's Encrypt SSL certificates.
- A domain name pointing to your server
- Ubuntu/Debian server with root access
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginxsudo systemctl stop nginx
sudo certbot certonly --standalone -d your-domain.com
sudo systemctl start nginx-
Copy
example.nginx.confto nginx sites:sudo cp example.nginx.conf /etc/nginx/sites-available/ccsync
-
Edit the file and replace
your-domain.comwith your actual domain:sudo sed -i 's/your-domain.com/your-actual-domain.com/g' /etc/nginx/sites-available/ccsync -
Enable the site:
sudo ln -s /etc/nginx/sites-available/ccsync /etc/nginx/sites-enabled/ sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t sudo systemctl reload nginx
The production/docker-compose.production.yml file binds all ports to localhost only, so nginx handles external traffic. Use it as an override file (do not modify the base docker-compose.yml):
# From the project root directory:
docker compose -f docker-compose.yml -f production/docker-compose.production.yml up -dThis applies the following port changes:
| Service | Development | Production |
|---|---|---|
| frontend | 80:80 |
127.0.0.1:3000:80 |
| backend | 8000:8000 |
127.0.0.1:8000:8000 |
| syncserver | 8080:8080 |
127.0.0.1:8081:8080 |
Create .backend.env:
CLIENT_ID="your-google-client-id"
CLIENT_SEC="your-google-client-secret"
REDIRECT_URL_DEV="https://your-domain.com/auth/callback"
SESSION_KEY="$(openssl rand -hex 32)"
FRONTEND_ORIGIN_DEV="https://your-domain.com"
CONTAINER_ORIGIN="http://syncserver:8080/"
ENV="production"
# Rate limiting: Trusted proxies for correct client IP detection
# Not needed if nginx runs on the same server (loopback is trusted by default)
# Only set this if using an external load balancer:
# TRUSTED_PROXIES="10.0.0.0/8,192.168.0.0/16"Create .frontend.env (see example.frontend.env):
VITE_BACKEND_URL="https://your-domain.com/"
VITE_FRONTEND_URL="https://your-domain.com"
VITE_CONTAINER_ORIGIN="https://your-domain.com:8080/"In Google Cloud Console, add the redirect URI:
https://your-domain.com/auth/callback
# Pull latest images
docker compose pull
# Start with production override (localhost-only ports)
docker compose -f docker-compose.yml -f production/docker-compose.production.yml up -dYour CCSync instance should now be available at https://your-domain.com
Useful commands:
# View logs
docker compose -f docker-compose.yml -f production/docker-compose.production.yml logs -f
# Restart services
docker compose -f docker-compose.yml -f production/docker-compose.production.yml restart
# Rebuild and restart (after code changes)
docker compose -f docker-compose.yml -f production/docker-compose.production.yml up -d --buildFrom WSL / Linux / Git Bash (run as root to access frontend on port 80):
chmod +x ./run-ports.sh
./run-ports.shFrom PowerShell (Windows):
bash .\run-ports.shNotes:
- Ensure kubectl, tmux (for managing individual pods better) and access to your cluster are configured before running the script.
- Edit
backend-env-configmap.yamland create secrets as needed before running the script.