feat(sync-server): add GHCR-based deployment workflow

Switch from server-side builds to pre-built images:
- Add build-and-push.sh for local builds to GHCR
- Update deploy.sh to pull from registry (30s vs 20min)
- Add docker-compose.build.yml for local build fallback
- Update docker-compose.yml to use registry image
- Add GHCR_USER/GHCR_TOKEN to env.example
- Add npm scripts: docker:build, docker:deploy, docker:backup
This commit is contained in:
Johannes Millan 2025-12-19 15:24:20 +01:00
parent 57766f29dd
commit f056e1224c
6 changed files with 128 additions and 29 deletions

View file

@ -0,0 +1,11 @@
# Local build override for development
#
# Usage:
# docker-compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
services:
supersync:
build:
context: ../..
dockerfile: packages/super-sync-server/Dockerfile
image: supersync:local

View file

@ -5,8 +5,8 @@
# 2. Run: docker-compose up -d
# 3. View logs: docker-compose logs -f
#
# Build from repo root:
# docker-compose -f packages/super-sync-server/docker-compose.yml up -d --build
# For local builds (development):
# docker-compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
x-logging: &default-logging
driver: 'json-file'
@ -16,10 +16,7 @@ x-logging: &default-logging
services:
supersync:
build:
context: ../..
dockerfile: packages/super-sync-server/Dockerfile
image: supersync:v4
image: ${SUPERSYNC_IMAGE:-ghcr.io/johannesjo/supersync:latest}
container_name: supersync-server
restart: always
environment:

View file

@ -56,6 +56,17 @@ SMTP_PASS=your-smtp-password
# From address for emails
SMTP_FROM="Super Productivity Sync" <noreply@your-domain.com>
# =============================================================================
# CONTAINER REGISTRY (for build-and-push.sh)
# =============================================================================
# GitHub username for GHCR
GHCR_USER=your-github-username
# GitHub token with "Packages: Read and write" permission
# Create at: https://github.com/settings/tokens?type=beta
GHCR_TOKEN=your-github-token
# =============================================================================
# ADVANCED SETTINGS (usually no changes needed)
# =============================================================================

View file

@ -4,16 +4,18 @@
"description": "SuperSync server for Super Productivity",
"main": "dist/index.js",
"scripts": {
"deploy": "git pull && docker compose down && docker compose up -d --build && docker logs supersync-server",
"build": "tsc",
"start": "docker compose down && docker compose up -d --build",
"start2": "node dist/index.js",
"start": "node dist/index.js",
"dev": "nodemon --watch src --ext ts --exec ts-node src/index.ts",
"test": "vitest run",
"docker:build": "./scripts/build-and-push.sh",
"docker:deploy": "./scripts/deploy.sh",
"docker:deploy:build": "./scripts/deploy.sh --build",
"docker:backup": "./scripts/backup.sh",
"docker:logs": "docker logs supersync-server -f",
"delete-user": "ts-node scripts/delete-user.ts",
"clear-data": "ts-node scripts/clear-data.ts",
"monitor": "ts-node scripts/monitor.ts",
"logs": "docker logs supersync-server -f"
"monitor": "ts-node scripts/monitor.ts"
},
"dependencies": {
"@fastify/cors": "^11.1.0",

View file

@ -0,0 +1,74 @@
#!/bin/bash
# SuperSync Server - Build and Push to GitHub Container Registry
#
# Usage:
# ./scripts/build-and-push.sh [TAG]
#
# Examples:
# ./scripts/build-and-push.sh # Pushes as :latest
# ./scripts/build-and-push.sh v1.0.0 # Pushes as :v1.0.0 and :latest
#
# Prerequisites:
# Add to .env file:
# GHCR_USER=your-github-username
# GHCR_TOKEN=your-github-token
set -e
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVER_DIR="$(dirname "$SCRIPT_DIR")"
REPO_ROOT="$(dirname "$(dirname "$SERVER_DIR")")"
DOCKERFILE="$SERVER_DIR/Dockerfile"
# Load .env file
if [ -f "$SERVER_DIR/.env" ]; then
export $(grep -E '^(GHCR_USER|GHCR_TOKEN)=' "$SERVER_DIR/.env" | xargs)
fi
# Configuration
GITHUB_USER="${GHCR_USER:-johannesjo}"
GHCR_TOKEN="${GHCR_TOKEN:-}"
IMAGE_NAME="ghcr.io/$GITHUB_USER/supersync"
# Parse tag argument
TAG="${1:-latest}"
echo "==> SuperSync Build & Push"
echo " Image: $IMAGE_NAME:$TAG"
echo " Repo: $REPO_ROOT"
echo ""
# Step 1: Build image
echo "==> Building image..."
docker build \
-t "$IMAGE_NAME:$TAG" \
-t "$IMAGE_NAME:latest" \
-f "$DOCKERFILE" \
"$REPO_ROOT"
echo ""
echo "==> Build complete!"
echo ""
# Step 2: Login to GHCR (if token provided)
if [ -n "$GHCR_TOKEN" ]; then
echo "==> Logging in to GHCR..."
echo "$GHCR_TOKEN" | docker login ghcr.io -u "$GITHUB_USER" --password-stdin
echo ""
fi
# Step 3: Push to registry
echo "==> Pushing to GHCR..."
docker push "$IMAGE_NAME:$TAG"
if [ "$TAG" != "latest" ]; then
docker push "$IMAGE_NAME:latest"
fi
echo ""
echo "==> Done!"
echo " Pushed: $IMAGE_NAME:$TAG"
echo ""
echo " To deploy on server, run:"
echo " ./scripts/deploy.sh"

View file

@ -2,22 +2,21 @@
# SuperSync Server Deployment Script
#
# Usage:
# ./scripts/deploy.sh [--force]
# ./scripts/deploy.sh [--build]
#
# This script:
# 1. Pulls latest changes from git
# 2. Rebuilds and restarts containers
# 1. Pulls latest image from GHCR (or builds locally with --build)
# 2. Restarts containers
# 3. Verifies health check passes
#
# Options:
# --force Force rebuild without cache
# --build Build locally instead of pulling from registry
set -e
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVER_DIR="$(dirname "$SCRIPT_DIR")"
REPO_DIR="$(dirname "$(dirname "$SERVER_DIR")")"
# Get domain from .env file
if [ -f "$SERVER_DIR/.env" ]; then
@ -32,9 +31,9 @@ else
fi
# Parse arguments
FORCE_BUILD=""
if [ "$1" = "--force" ]; then
FORCE_BUILD="--no-cache"
BUILD_LOCAL=false
if [ "$1" = "--build" ]; then
BUILD_LOCAL=true
fi
echo "==> SuperSync Deployment"
@ -42,14 +41,6 @@ echo " Server dir: $SERVER_DIR"
echo " Health URL: $HEALTH_URL"
echo ""
# Step 1: Pull latest changes
echo "==> Pulling latest changes..."
cd "$REPO_DIR"
git pull origin "$(git rev-parse --abbrev-ref HEAD)"
# Step 2: Build and restart
echo ""
echo "==> Building and restarting containers..."
cd "$SERVER_DIR"
# Check if monitoring compose exists and include it
@ -58,9 +49,22 @@ if [ -f "docker-compose.monitoring.yml" ]; then
COMPOSE_FILES="$COMPOSE_FILES -f docker-compose.monitoring.yml"
fi
docker compose $COMPOSE_FILES up -d --build $FORCE_BUILD
if [ "$BUILD_LOCAL" = true ]; then
# Local build mode
echo "==> Building locally..."
COMPOSE_FILES="$COMPOSE_FILES -f docker-compose.build.yml"
docker compose $COMPOSE_FILES up -d --build
else
# Pull from registry (default)
echo "==> Pulling latest image..."
docker compose $COMPOSE_FILES pull supersync
# Step 3: Wait for health check
echo ""
echo "==> Restarting containers..."
docker compose $COMPOSE_FILES up -d
fi
# Wait for health check
echo ""
echo "==> Waiting for service to be healthy..."
sleep 5