Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 111 additions & 11 deletions production/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,136 @@
# To run using Docker:
# Production Deployment

1. Create a file named .backend.env with the following attributes:
## Option 1: Docker (HTTP only, for local/development)

```
1. Create a file named `.backend.env` with the following attributes:

```bash
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://YOUR_CONTAINER_NAME:8080/" # Deployed taskchampion-sync-server container, default is production-syncserver-1
CONTAINER_ORIGIN="http://production-syncserver-1:8080/" # Deployed taskchampion-sync-server container
```

2. Run docker-compose pull to pull the CCSync images.
3. Run docker-compose up to start the project.
2. Run `docker-compose pull` to pull the CCSync images.
3. Run `docker-compose up` to start the project.
4. The frontend should now be available at localhost:80, the backend at localhost:8000, and the sync server at localhost:8080

# To run the project using Kubernetes:
## Option 2: Docker with nginx Reverse Proxy (HTTPS, recommended for production)

For production deployments with HTTPS, use nginx as a reverse proxy with Let's Encrypt SSL certificates.

### Prerequisites

- A domain name pointing to your server
- Ubuntu/Debian server with root access

### Step 1: Install nginx and certbot

```bash
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
```

### Step 2: Obtain SSL certificate

```bash
sudo systemctl stop nginx
sudo certbot certonly --standalone -d your-domain.com
sudo systemctl start nginx
```

### Step 3: Configure nginx

1. Copy `example.nginx.conf` to nginx sites:
```bash
sudo cp example.nginx.conf /etc/nginx/sites-available/ccsync
```

2. Edit the file and replace `your-domain.com` with your actual domain:
```bash
sudo sed -i 's/your-domain.com/your-actual-domain.com/g' /etc/nginx/sites-available/ccsync
```

3. Enable the site:
```bash
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
```

### Step 4: Update docker-compose.yml

Modify the port bindings to listen only on localhost (nginx will handle external traffic):

- From WSL / Linux / Git Bash (Please run as root in order to access frontend on port 80):
```yaml
services:
frontend:
ports:
- "127.0.0.1:3000:80" # Changed from "80:80"

backend:
ports:
- "127.0.0.1:8000:8000" # Bind to localhost only

syncserver:
ports:
- "127.0.0.1:8081:8080" # Changed from "8080:8080"
```

### Step 5: Create environment files

Create `.backend.env`:
```bash
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/"
```

Create `.frontend.env` (see `example.frontend.env`):
```bash
VITE_BACKEND_URL="https://your-domain.com/"
VITE_FRONTEND_URL="https://your-domain.com"
VITE_CONTAINER_ORIGIN="https://your-domain.com:8080/"
```

### Step 6: Configure Google OAuth

In Google Cloud Console, add the redirect URI:
- `https://your-domain.com/auth/callback`

### Step 7: Deploy

```bash
docker-compose pull
docker-compose up -d
```

Your CCSync instance should now be available at `https://your-domain.com`

---

## Option 3: Kubernetes

From WSL / Linux / Git Bash (run as root to access frontend on port 80):

```bash
chmod +x ./run-ports.sh
./run-ports.sh
```

- From PowerShell (Windows):
From PowerShell (Windows):

```
```bash
bash .\run-ports.sh
```

Notes:

- Ensure kubectl, tmux (for managing individual pods better) and access to your cluster are configured before running the script.
- Edit production/backend-env-configmap.yaml and create secrets as needed before running the script.
- Edit `backend-env-configmap.yaml` and create secrets as needed before running the script.
3 changes: 3 additions & 0 deletions production/example.frontend.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VITE_BACKEND_URL="https://your-domain.com/"
VITE_FRONTEND_URL="https://your-domain.com"
VITE_CONTAINER_ORIGIN="https://your-domain.com:8080/"
203 changes: 203 additions & 0 deletions production/example.nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# CCSync nginx reverse proxy configuration
# For production deployment with SSL (Let's Encrypt)
#
# Prerequisites:
# 1. Install nginx: apt install nginx
# 2. Install certbot: apt install certbot python3-certbot-nginx
# 3. Obtain certificate: certbot certonly --standalone -d your-domain.com
# 4. Copy this file to /etc/nginx/sites-available/ccsync
# 5. Create symlink: ln -s /etc/nginx/sites-available/ccsync /etc/nginx/sites-enabled/
# 6. Remove default: rm /etc/nginx/sites-enabled/default
# 7. Test config: nginx -t
# 8. Reload nginx: systemctl reload nginx
#
# Note: Update docker-compose.yml to bind ports to localhost only:
# frontend: "127.0.0.1:3000:80"
# backend: "127.0.0.1:8000:8000"
# syncserver: "127.0.0.1:8081:8080"

# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name your-domain.com;

location / {
return 301 https://$server_name$request_uri;
}
}

# Main HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.com;

# SSL certificates (update paths for your domain)
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;

# Backend API routes
location /auth/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /tasks {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /add-task {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /edit-task {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /modify-task {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /complete-task {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /complete-tasks {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /delete-task {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /delete-tasks {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /sync/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /health {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

location /docs {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

# WebSocket support
location /ws {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}

# Frontend (default)
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

# Taskchampion sync server (port 8080 with SSL)
server {
listen 8080 ssl http2;
listen [::]:8080 ssl http2;
server_name your-domain.com;

ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;

location / {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Loading