|
| 1 | +# CCSync Production Deployment |
| 2 | + |
| 3 | +This directory contains the production deployment configuration for CCSync. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The deployment system uses: |
| 8 | +- **GitHub Actions** to build and push Docker images to GHCR |
| 9 | +- **SSH-based deployment** triggered manually via GitHub Actions |
| 10 | +- **Automatic rollback** if health checks fail |
| 11 | + |
| 12 | +## VPS Directory Structure |
| 13 | + |
| 14 | +``` |
| 15 | +/opt/ccsync/ |
| 16 | +├── docker-compose.yml # Copy from this directory |
| 17 | +├── .env # Contains IMAGE_TAG=<sha> |
| 18 | +├── secrets/ |
| 19 | +│ └── backend.env # OAuth secrets, session key (chmod 600) |
| 20 | +├── data/ |
| 21 | +│ ├── backend/ # Backend persistent data |
| 22 | +│ └── syncserver/ # Taskchampion sync server data |
| 23 | +├── scripts/ |
| 24 | +│ └── deploy.sh # Copy from this directory |
| 25 | +└── deployments/ # Deployment history |
| 26 | + └── current -> ... # Symlink to current deployment |
| 27 | +``` |
| 28 | + |
| 29 | +## Initial VPS Setup |
| 30 | + |
| 31 | +### 1. Create deploy user |
| 32 | + |
| 33 | +```bash |
| 34 | +sudo useradd -m -s /bin/bash deploy |
| 35 | +sudo usermod -aG docker deploy |
| 36 | +``` |
| 37 | + |
| 38 | +### 2. Create directory structure |
| 39 | + |
| 40 | +```bash |
| 41 | +sudo mkdir -p /opt/ccsync/{scripts,secrets,data/backend,data/syncserver,deployments} |
| 42 | +sudo chown -R deploy:deploy /opt/ccsync |
| 43 | +sudo chmod 750 /opt/ccsync |
| 44 | +sudo chmod 700 /opt/ccsync/secrets |
| 45 | +``` |
| 46 | + |
| 47 | +### 3. Copy deployment files |
| 48 | + |
| 49 | +```bash |
| 50 | +# Copy docker-compose.yml |
| 51 | +sudo -u deploy cp deployment/docker-compose.yml /opt/ccsync/ |
| 52 | + |
| 53 | +# Copy and make deploy script executable |
| 54 | +sudo -u deploy cp deployment/deploy.sh /opt/ccsync/scripts/ |
| 55 | +sudo chmod +x /opt/ccsync/scripts/deploy.sh |
| 56 | +``` |
| 57 | + |
| 58 | +### 4. Create secrets file |
| 59 | + |
| 60 | +```bash |
| 61 | +sudo -u deploy nano /opt/ccsync/secrets/backend.env |
| 62 | +sudo chmod 600 /opt/ccsync/secrets/backend.env |
| 63 | +``` |
| 64 | + |
| 65 | +Required variables in `backend.env`: |
| 66 | +```bash |
| 67 | +# Google OAuth (from Google Cloud Console) |
| 68 | +CLIENT_ID=your-client-id.apps.googleusercontent.com |
| 69 | +CLIENT_SEC=your-client-secret |
| 70 | + |
| 71 | +# Session security (generate with: openssl rand -hex 32) |
| 72 | +SESSION_KEY=your-64-character-hex-string |
| 73 | + |
| 74 | +# Environment |
| 75 | +ENV=production |
| 76 | +PORT=8000 |
| 77 | + |
| 78 | +# URLs |
| 79 | +ALLOWED_ORIGIN=https://taskwarrior-server.ccextractor.org |
| 80 | +FRONTEND_ORIGIN_DEV=https://taskwarrior-server.ccextractor.org |
| 81 | +REDIRECT_URL_DEV=https://taskwarrior-server.ccextractor.org/auth/callback |
| 82 | +CONTAINER_ORIGIN=https://taskwarrior-server.ccextractor.org:8080 |
| 83 | +``` |
| 84 | + |
| 85 | +### 5. Generate SSH key for GitHub Actions |
| 86 | + |
| 87 | +```bash |
| 88 | +# As deploy user |
| 89 | +sudo -u deploy ssh-keygen -t ed25519 -C "github-deploy@ccsync" -f /home/deploy/.ssh/github_deploy -N "" |
| 90 | + |
| 91 | +# Add to authorized_keys |
| 92 | +sudo -u deploy bash -c 'cat /home/deploy/.ssh/github_deploy.pub >> /home/deploy/.ssh/authorized_keys' |
| 93 | +sudo -u deploy chmod 600 /home/deploy/.ssh/authorized_keys |
| 94 | + |
| 95 | +# Display private key (add to GitHub Secrets as DEPLOY_SSH_KEY) |
| 96 | +sudo cat /home/deploy/.ssh/github_deploy |
| 97 | +``` |
| 98 | + |
| 99 | +## GitHub Repository Setup |
| 100 | + |
| 101 | +### 1. Create "production" environment |
| 102 | + |
| 103 | +In GitHub repo settings → Environments → Create "production": |
| 104 | +- Add required reviewers (optional, for manual approval) |
| 105 | +- Add deployment branch rule: `main` |
| 106 | + |
| 107 | +### 2. Add environment variables |
| 108 | + |
| 109 | +| Name | Value | |
| 110 | +|------|-------| |
| 111 | +| `SSH_HOST` | `<your-server-ip>` | |
| 112 | +| `SSH_USER` | `deploy` | |
| 113 | +| `SSH_PORT` | `22` | |
| 114 | + |
| 115 | +### 3. Add environment secrets |
| 116 | + |
| 117 | +| Name | Description | |
| 118 | +|------|-------------| |
| 119 | +| `DEPLOY_SSH_KEY` | Private key from step 5 above | |
| 120 | + |
| 121 | +## Deployment |
| 122 | + |
| 123 | +### Automatic (after merge to main) |
| 124 | + |
| 125 | +1. Push/merge to `main` branch |
| 126 | +2. GitHub Actions builds and pushes images to GHCR |
| 127 | +3. Go to Actions → "Deploy to Production" → Run workflow |
| 128 | +4. Enter the image tag (commit SHA) or "latest" |
| 129 | +5. If environment protection is enabled, approve the deployment |
| 130 | + |
| 131 | +### Manual deployment on VPS |
| 132 | + |
| 133 | +```bash |
| 134 | +# SSH to VPS |
| 135 | +ssh deploy@<your-server-ip> |
| 136 | + |
| 137 | +# Deploy specific tag |
| 138 | +/opt/ccsync/scripts/deploy.sh abc1234 |
| 139 | + |
| 140 | +# Deploy latest |
| 141 | +/opt/ccsync/scripts/deploy.sh latest |
| 142 | +``` |
| 143 | + |
| 144 | +## Rollback |
| 145 | + |
| 146 | +### Automatic |
| 147 | + |
| 148 | +The deploy script automatically rolls back if: |
| 149 | +- Docker image pull fails |
| 150 | +- Container startup fails |
| 151 | +- Health check fails within 120 seconds |
| 152 | + |
| 153 | +### Manual |
| 154 | + |
| 155 | +```bash |
| 156 | +# Check deployment history |
| 157 | +ls -la /opt/ccsync/deployments/ |
| 158 | + |
| 159 | +# Get previous tag from a deployment record |
| 160 | +cat /opt/ccsync/deployments/<deployment-dir>/info.txt |
| 161 | + |
| 162 | +# Roll back to previous tag |
| 163 | +/opt/ccsync/scripts/deploy.sh <previous-tag> |
| 164 | +``` |
| 165 | + |
| 166 | +## Monitoring |
| 167 | + |
| 168 | +The existing health check script at `/opt/ccsync-monitor/health-check.sh` monitors: |
| 169 | +- Docker container health status |
| 170 | +- Backend `/health` endpoint |
| 171 | +- Alerts to Zulip on failures |
| 172 | + |
| 173 | +After migration, update the script to use `/opt/ccsync` instead of `~/ccsync`. |
0 commit comments