From 9fc824e3ac618545ffd4cbdec6aeb49e7dd8acba Mon Sep 17 00:00:00 2001 From: Per Magnus Petersen Date: Thu, 19 Feb 2026 20:19:00 +0100 Subject: [PATCH 1/4] Initial commit --- docker-compose.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..15860db --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +services: + gitea: + image: gitea/gitea:latest + container_name: gitea + environment: + - USER_UID=1000 + - USER_GID=1000 + - GITEA__database__DB_TYPE=postgres + - GITEA__database__HOST=192.168.50.42:5432 + - GITEA__database__NAME=gitea + - GITEA__database__USER=postgres + - GITEA__database__PASSWD=ratata,123 + restart: unless-stopped + volumes: + - gitea_data:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "3008:3000" + - "2222:22" + +volumes: + gitea_data: From cce5c54177d16af9349182adc2c71e843cdae830 Mon Sep 17 00:00:00 2001 From: Per Magnus Petersen Date: Thu, 19 Feb 2026 21:33:18 +0100 Subject: [PATCH 2/4] Add automated daily Gitea backup Alpine sidecar container runs gitea dump via docker exec at 2 AM daily, writing backups to /data/backup/gitea/ with 7-day retention. Co-Authored-By: Claude Opus 4.6 --- backup.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 24 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 backup.sh diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..4e93a98 --- /dev/null +++ b/backup.sh @@ -0,0 +1,57 @@ +#!/bin/sh +set -e + +BACKUP_DIR="/backup" +RETAIN_DAYS="${BACKUP_RETAIN_DAYS:-7}" +TIMESTAMP="$(date +%Y-%m-%d_%H%M)" +BACKUP_FILE="gitea-dump-${TIMESTAMP}.zip" + +echo "========================================" +echo "Gitea backup started at $(date)" +echo "========================================" + +# Pre-flight check +if ! docker inspect gitea >/dev/null 2>&1; then + echo "ERROR: gitea container not found or not running." + exit 1 +fi + +# Ensure backup directory exists inside gitea container +docker exec -u git gitea sh -c "mkdir -p /tmp/backup" + +# Run gitea dump +echo "Running gitea dump..." +docker exec -u git -w /tmp gitea \ + /app/gitea/gitea dump \ + -c /data/gitea/conf/app.ini \ + --file "/tmp/backup/${BACKUP_FILE}" \ + --skip-log \ + --type zip + +# Verify backup was created +if [ ! -f "${BACKUP_DIR}/${BACKUP_FILE}" ]; then + echo "ERROR: Backup file not found at ${BACKUP_DIR}/${BACKUP_FILE}" + exit 1 +fi + +FILESIZE=$(stat -c%s "${BACKUP_DIR}/${BACKUP_FILE}" 2>/dev/null || stat -f%z "${BACKUP_DIR}/${BACKUP_FILE}" 2>/dev/null) +echo "Backup created: ${BACKUP_FILE} (${FILESIZE} bytes)" + +# Retention: delete backups older than N days +echo "Cleaning up backups older than ${RETAIN_DAYS} days..." +DELETED=$(find "${BACKUP_DIR}" -name "gitea-dump-*.zip" -mtime "+${RETAIN_DAYS}" -print -delete) +if [ -n "${DELETED}" ]; then + echo "Deleted old backups:" + echo "${DELETED}" +else + echo "No old backups to delete." +fi + +echo "" +echo "Current backups:" +ls -lh "${BACKUP_DIR}"/gitea-dump-*.zip 2>/dev/null || echo "(none)" + +echo "" +echo "========================================" +echo "Gitea backup completed at $(date)" +echo "========================================" diff --git a/docker-compose.yml b/docker-compose.yml index 15860db..bf0ed60 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,9 +15,33 @@ services: - gitea_data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro + - /data/backup/gitea:/tmp/backup ports: - "3008:3000" - "2222:22" + gitea-backup: + image: alpine:3.21 + container_name: gitea-backup + depends_on: + - gitea + restart: unless-stopped + environment: + - BACKUP_RETAIN_DAYS=7 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /data/backup/gitea:/backup + - ./backup.sh:/usr/local/bin/backup.sh:ro + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + entrypoint: /bin/sh + command: + - -c + - | + apk add --no-cache docker-cli + echo "0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1" > /etc/crontabs/root + touch /var/log/backup.log + crond -f -l 2 + volumes: gitea_data: From 06c9efe1a0a0a7b31c5af5498036140d50b4ea96 Mon Sep 17 00:00:00 2001 From: Per Magnus Petersen Date: Fri, 20 Feb 2026 13:16:57 +0100 Subject: [PATCH 3/4] Backup in /mnt/nasen/backup --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index bf0ed60..39ddf18 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: - gitea_data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro - - /data/backup/gitea:/tmp/backup + - /mnt/nasen/backup/gitea:/tmp/backup ports: - "3008:3000" - "2222:22" @@ -30,7 +30,7 @@ services: - BACKUP_RETAIN_DAYS=7 volumes: - /var/run/docker.sock:/var/run/docker.sock - - /data/backup/gitea:/backup + - /mnt/nasen/backup/gitea:/backup - ./backup.sh:/usr/local/bin/backup.sh:ro - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro From e3ba7fd62e6624676f909331b324a14ecbc077d4 Mon Sep 17 00:00:00 2001 From: Per Magnus Petersen Date: Sat, 21 Feb 2026 10:10:19 +0100 Subject: [PATCH 4/4] Add CLAUDE.md with project guidance for Claude Code Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..8bf02b3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,42 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Self-hosted Gitea deployment using Docker Compose with a remote PostgreSQL database and automated daily backups to NAS storage. + +## Architecture + +Two-container setup via `docker-compose.yml`: + +- **gitea** — Main Gitea application (`gitea/gitea:latest`). Web UI on port 3008, SSH on port 2222. Connects to a remote PostgreSQL instance at `192.168.50.42:5432`. +- **gitea-backup** — Alpine sidecar that installs `docker-cli`, sets up a cron job (2 AM daily), and runs `backup.sh` via `docker exec` into the gitea container. + +Backup files (`gitea-dump-YYYY-MM-DD_HHMM.zip`) are written to `/mnt/nasen/backup/gitea` (NAS mount) with 7-day retention. + +## Common Commands + +```bash +# Start/stop services +docker-compose up -d +docker-compose down + +# View logs +docker-compose logs -f gitea +docker-compose logs -f gitea-backup + +# Run a manual backup +docker exec gitea-backup /usr/local/bin/backup.sh + +# Check backup logs inside sidecar +docker exec gitea-backup cat /var/log/backup.log + +# Access Gitea admin CLI +docker exec -u git gitea /app/gitea/gitea admin [subcommand] +``` + +## Key Files + +- `docker-compose.yml` — Service definitions, environment config, volume mounts +- `backup.sh` — Backup script: runs `gitea dump`, verifies output, enforces retention policy