diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5daad89 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +DOMAIN=t-gstone.de +DATA_ROOT=/opt/docker-data diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..473c8ca --- /dev/null +++ b/backup.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/.env" +DATA_ROOT="${DATA_ROOT:-/opt/docker-data}" + +BACKUP_DIR="/opt/backups" +DATE=$(date +%Y-%m-%d) +KEEP_DAYS=7 + +mkdir -p "$BACKUP_DIR" + +echo "==> Starting backup ($DATE)..." + +# ------------------------------------------------------------------ +# Nextcloud Postgres dump +# ------------------------------------------------------------------ +echo " -> Dumping Nextcloud Postgres..." +docker exec nextcloud-postgres pg_dumpall -U nextcloud > "$BACKUP_DIR/nextcloud-db-$DATE.sql" + +# ------------------------------------------------------------------ +# Nextcloud data +# ------------------------------------------------------------------ +echo " -> Archiving Nextcloud data..." +tar -czf "$BACKUP_DIR/nextcloud-data-$DATE.tar.gz" \ + -C "$DATA_ROOT" nextcloud/data nextcloud/html/config + +# ------------------------------------------------------------------ +# Gitea data +# ------------------------------------------------------------------ +echo " -> Archiving Gitea data..." +tar -czf "$BACKUP_DIR/gitea-$DATE.tar.gz" \ + -C "$DATA_ROOT" gitea/data gitea/config + +# ------------------------------------------------------------------ +# Rotate old backups +# ------------------------------------------------------------------ +echo " -> Removing backups older than $KEEP_DAYS days..." +find "$BACKUP_DIR" -type f -name "*.sql" -mtime +$KEEP_DAYS -delete +find "$BACKUP_DIR" -type f -name "*.tar.gz" -mtime +$KEEP_DAYS -delete + +echo "==> Backup complete. Files in $BACKUP_DIR:" +ls -lh "$BACKUP_DIR"/*"$DATE"* 2>/dev/null || echo " (no files found)" + +echo "" +echo "To schedule daily backups, add to crontab (crontab -e):" +echo " 0 3 * * * $SCRIPT_DIR/backup.sh >> /var/log/backup.log 2>&1" diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..b6950d0 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# ------------------------------------------------------------------ +# Load config +# ------------------------------------------------------------------ +if [ ! -f "$SCRIPT_DIR/.env" ]; then + echo "ERROR: $SCRIPT_DIR/.env not found. Copy .env.example and fill in values." + exit 1 +fi +source "$SCRIPT_DIR/.env" +DATA_ROOT="${DATA_ROOT:-/opt/docker-data}" + +echo "==> VPS info:" +cat /etc/os-release +echo "" + +# ------------------------------------------------------------------ +# Install Docker if not present +# ------------------------------------------------------------------ +if ! command -v docker &>/dev/null; then + echo "==> Installing Docker..." + curl -fsSL https://get.docker.com | sh + systemctl enable --now docker + echo "==> Docker installed." +else + echo "==> Docker already installed: $(docker --version)" +fi + +# Ensure docker compose plugin is available +if ! docker compose version &>/dev/null; then + echo "ERROR: docker compose plugin not found. Install it manually." + exit 1 +fi + +# ------------------------------------------------------------------ +# Create shared Docker network +# ------------------------------------------------------------------ +if ! docker network inspect proxy &>/dev/null 2>&1; then + echo "==> Creating 'proxy' Docker network..." + docker network create proxy +else + echo "==> 'proxy' network already exists." +fi + +# ------------------------------------------------------------------ +# Create data directories +# ------------------------------------------------------------------ +echo "==> Creating data directories under $DATA_ROOT..." +mkdir -p "$DATA_ROOT"/{caddy/data,caddy/config} +mkdir -p "$DATA_ROOT"/{nextcloud/html,nextcloud/data,nextcloud/db} +mkdir -p "$DATA_ROOT"/{gitea/data,gitea/config} +mkdir -p /opt/backups + +# ------------------------------------------------------------------ +# Check .env files exist for each service +# ------------------------------------------------------------------ +for svc in nextcloud gitea monitoring; do + if [ ! -f "$SCRIPT_DIR/$svc/.env" ]; then + echo "WARNING: $svc/.env not found. Copy $svc/.env.example and fill in values." + fi +done + +# ------------------------------------------------------------------ +# Start stacks in order +# ------------------------------------------------------------------ +echo "==> Starting Caddy..." +docker compose -f "$SCRIPT_DIR/caddy/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d + +echo "==> Starting Nextcloud..." +docker compose -f "$SCRIPT_DIR/nextcloud/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d + +echo "==> Starting Gitea..." +docker compose -f "$SCRIPT_DIR/gitea/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d + +echo "==> Starting Monitoring..." +docker compose -f "$SCRIPT_DIR/monitoring/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d + +echo "" +echo "==> All services started. Verify with: docker ps" +echo "==> DNS A records required:" +echo " nextcloud.t-gstone.de -> " +echo " git.t-gstone.de -> " diff --git a/restore.sh b/restore.sh new file mode 100755 index 0000000..fbae3ec --- /dev/null +++ b/restore.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/.env" +DATA_ROOT="${DATA_ROOT:-/opt/docker-data}" + +BACKUP_DIR="/opt/backups" + +# ------------------------------------------------------------------ +# Usage +# ------------------------------------------------------------------ +if [ $# -lt 1 ]; then + echo "Usage: $0 " + echo " e.g.: $0 2026-03-22" + echo "" + echo "Expects these files in $BACKUP_DIR:" + echo " nextcloud-db-.sql" + echo " nextcloud-data-.tar.gz" + echo " gitea-.tar.gz" + exit 1 +fi + +DATE="$1" +DB_DUMP="$BACKUP_DIR/nextcloud-db-$DATE.sql" +NC_ARCHIVE="$BACKUP_DIR/nextcloud-data-$DATE.tar.gz" +GITEA_ARCHIVE="$BACKUP_DIR/gitea-$DATE.tar.gz" + +for f in "$DB_DUMP" "$NC_ARCHIVE" "$GITEA_ARCHIVE"; do + if [ ! -f "$f" ]; then + echo "ERROR: $f not found." + exit 1 + fi +done + +echo "==> Restoring from backup date: $DATE" +echo " This will overwrite current data. Press Ctrl+C within 5s to abort." +sleep 5 + +# ------------------------------------------------------------------ +# Stop services +# ------------------------------------------------------------------ +echo "==> Stopping services..." +docker compose -f "$SCRIPT_DIR/nextcloud/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" down +docker compose -f "$SCRIPT_DIR/gitea/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" down + +# ------------------------------------------------------------------ +# Restore Nextcloud data +# ------------------------------------------------------------------ +echo "==> Restoring Nextcloud data..." +tar -xzf "$NC_ARCHIVE" -C "$DATA_ROOT" + +# ------------------------------------------------------------------ +# Restore Gitea data +# ------------------------------------------------------------------ +echo "==> Restoring Gitea data..." +tar -xzf "$GITEA_ARCHIVE" -C "$DATA_ROOT" + +# ------------------------------------------------------------------ +# Start Postgres and restore DB +# ------------------------------------------------------------------ +echo "==> Starting Postgres for DB restore..." +docker compose -f "$SCRIPT_DIR/nextcloud/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d postgres +echo " -> Waiting for Postgres to be ready..." +sleep 5 + +echo "==> Restoring Nextcloud database..." +docker exec -i nextcloud-postgres psql -U nextcloud < "$DB_DUMP" + +# ------------------------------------------------------------------ +# Start all services +# ------------------------------------------------------------------ +echo "==> Starting all services..." +docker compose -f "$SCRIPT_DIR/nextcloud/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d +docker compose -f "$SCRIPT_DIR/gitea/docker-compose.yml" --env-file "$SCRIPT_DIR/.env" up -d + +echo "==> Restore complete."