From d8aadb93c8ba87ce35285063e5827c1edba0f2af Mon Sep 17 00:00:00 2001 From: Leander Furumo Date: Mon, 2 Nov 2026 22:47:28 +0100 Subject: [PATCH] Add deploy script, backup script and crontab for the server - deploy/uiogaming-deploy: forced command for github_deploy's SSH key. Pulls the repo and rebuilds one service from /srv/uiogaming/docker-compose.yml, fixing deploys that failed on container-name conflicts. - backup/backup_db.sh: nightly pg_dumpall of all databases, gzipped, 14-day retention. - cron/uiogaming.crontab: the uiogaming user's crontab. - Document the new deploy setup and the move to /srv/uiogaming. Co-Authored-By: Claude Opus 5.5 --- backup/backup_db.sh | 24 ++++++++++++++++++++++ cron/uiogaming.crontab | 7 +++++++ deploy/uiogaming-deploy | 44 +++++++++++++++++++++++++++++++++++++++++ driftsdokumentasjon.md | 31 +++++++++++++++-------------- 4 files changed, 91 insertions(+), 15 deletions(-) create mode 100755 backup/backup_db.sh create mode 100644 cron/uiogaming.crontab create mode 100755 deploy/uiogaming-deploy diff --git a/backup/backup_db.sh b/backup/backup_db.sh new file mode 100755 index 0000000..89db8c9 --- /dev/null +++ b/backup/backup_db.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Nightly dump of all Postgres databases + roles, compressed. +# Installed on the server as /srv/uiogaming/.backups/backup_db.sh, run by cron (see ../cron/uiogaming.crontab). +# The rsync user pulls the backup folder to off-site storage every night at 03:00. +# +# Restore: gunzip -c backup_YYYY-MM-DD.sql.gz | docker exec -i postgres psql -U postgres +set -euo pipefail + +BACKUP_DIR=/srv/uiogaming/.backups/postgres +KEEP_DAYS=14 + +log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*"; } +fail() { log "Backup FAILED: $*" >&2; rm -f "$BACKUP_FILE"; exit 1; } + +mkdir -p "$BACKUP_DIR" +BACKUP_FILE="$BACKUP_DIR/backup_$(date +%F).sql.gz" +trap 'fail "error on line $LINENO"' ERR + +log "Backing up all databases" +docker exec postgres pg_dumpall -U postgres | gzip > "$BACKUP_FILE" +[[ $(gunzip -c "$BACKUP_FILE" | tail -n 5) == *"cluster dump complete"* ]] || fail "dump incomplete" +log "Backup completed: $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))" + +find "$BACKUP_DIR" -name 'backup_*.sql*' -mtime +"$KEEP_DAYS" -delete diff --git a/cron/uiogaming.crontab b/cron/uiogaming.crontab new file mode 100644 index 0000000..f1dbc4f --- /dev/null +++ b/cron/uiogaming.crontab @@ -0,0 +1,7 @@ +# Crontab for the uiogaming user on the server. +# Install (replaces the whole crontab!): crontab cron/uiogaming.crontab +# Show what's installed: crontab -l + +# Nightly backup of all Postgres databases (see ../backup/backup_db.sh). +# The rsync user pulls /srv/uiogaming/.backups off-site at 03:00, so this must finish before then. +0 2 * * * /srv/uiogaming/.backups/backup_db.sh >> /srv/uiogaming/.backups/logs/backup.log 2>&1 diff --git a/deploy/uiogaming-deploy b/deploy/uiogaming-deploy new file mode 100755 index 0000000..f48f29d --- /dev/null +++ b/deploy/uiogaming-deploy @@ -0,0 +1,44 @@ +#!/bin/bash +# Deploy script for automatic deployment from GitHub Actions. +# +# Installed on the server as /usr/local/bin/uiogaming-deploy (owned by root, mode 755) and set as +# the only command github_deploy's SSH key may run, in ~github_deploy/.ssh/authorized_keys: +# restrict,command="/usr/local/bin/uiogaming-deploy" ssh-ed25519 AAAA... +# +# The workflow runs `ssh github_deploy@uiogaming.no `. SSH puts in +# SSH_ORIGINAL_COMMAND. The script updates that repo to origin/main and rebuilds the service +# from the top-level docker-compose.yml, which owns all the containers. +set -euo pipefail + +ROOT=/srv/uiogaming +BRANCH=main + +# compose service name -> repo folder under $ROOT +declare -A REPO=( + [bebbes]=bebbes + [mustaboard]=mustaboard + [mustafa]=mustafa + [name100]=name-100-uio-gamers + [uiogaming.no]=uiogaming.no +) + +svc=${SSH_ORIGINAL_COMMAND:-} +if [[ ! $svc =~ ^[a-z0-9.-]+$ || -z ${REPO[$svc]:-} ]]; then + echo "Usage: ssh github_deploy@uiogaming.no " >&2 + echo "Known services: ${!REPO[*]}" >&2 + exit 1 +fi + +repo="$ROOT/${REPO[$svc]}" +echo "==> Deploying $svc from $repo" + +git -C "$repo" fetch --quiet origin "$BRANCH" +git -C "$repo" reset --hard "origin/$BRANCH" +echo "==> Now at $(git -C "$repo" log -1 --format='%h %s')" + +cd "$ROOT" +docker compose up -d --build "$svc" + +# Every build leaves the previous image behind; clean those up +docker image prune -f >/dev/null +echo "==> Done" diff --git a/driftsdokumentasjon.md b/driftsdokumentasjon.md index 65f3fa2..5b6675f 100644 --- a/driftsdokumentasjon.md +++ b/driftsdokumentasjon.md @@ -94,7 +94,7 @@ Mange applikasjoner har behov for en database, og til det kjører vi en sentral Når en ny tjeneste skal gis tilgang til databasen anbefaler jeg å lage en ny bruker som bare har tilgang til databasen den skal ha, samt minimale tilganger til denne. -Backup av denne kjøres hver natt i cron job til mappa `/home/uiogaming/Documents/backups/postgres`. Denne mappa tas så backup av med _rsync_ til Leander Furumo sin personlige server off site. Dette gjøres gjennom brukeren `rsync`. +Backup av alle databasene kjøres hver natt kl. 02:00 som en cron job. Scriptet som kjører er ([`backup/backup_db.sh`](backup/backup_db.sh) som ligger i `/srv/uiogaming/.backups/backup_db.sh` på maskinen. Backups havner i `/srv/uiogaming/.backups/postgres`. Backupene komprimeres og slettes fra servermaskinen etter 14 dager. Denne mappa tas så backup av med _rsync_ til Leander Furumo sin personlige server off site kl. 03:00. Dette gjøres gjennom brukeren `rsync`, som bare har lesetilgang til backupmappa. ## uiogaming.no - Nettsiden @@ -270,7 +270,9 @@ I tillegg ligger det ymse andre ting som sakspapirer fra generalforsamlinger og # Automatisk deployment -Det er satt opp automatisk deployment for enkelte applikasjoner. Hver gang det pushes til _main_ branch på GitHub vil det kjøres en GitHub Action som logger seg på gjennom SSH og utfører kommandoene den trenger for å oppdatere tjenesten. Dette gjøres gjennom brukeren `github_deploy`. +Det er satt opp automatisk deployment for enkelte applikasjoner. Hver gang det pushes til _main_ branch på GitHub vil det kjøres en GitHub Action som logger seg på gjennom SSH som brukeren `github_deploy` og kjører `ssh github_deploy@uiogaming.no `. + +SSH-nøkkelen til `github_deploy` har bare lov til å kjøre scriptet [`deploy/uiogaming-deploy`](deploy/uiogaming-deploy), som ligger på servermaskinen som `/usr/local/bin/uiogaming-deploy`. Scriptet oppdaterer repoet til `origin/main` og bygger tjenesten på nytt med `docker compose up -d --build ` fra `/srv/uiogaming/docker-compose.yml`. Det er denne felles compose-fila som eier alle containerne, så `docker-compose.yml` i hvert enkelt repo brukes ikke av deploy. Deploy kan også kjøres manuelt fra _Actions_-fanen i repoet (_Run workflow_). I skrivende stund fungerer dette for følgende tjenester: @@ -282,24 +284,23 @@ I skrivende stund fungerer dette for følgende tjenester: ## Secrets og variabler -Workflowen (`.github/workflows/deploy.yml`) er lik i alle repoene og henter innloggingsinfo fra GitHub sine _secrets_ og _variables_. De fleste av disse er satt på organisasjonsnivå, under _Settings → Secrets and variables → Actions_ for [UiO-Gaming](https://github.com/UiO-Gaming), og deles av alle repoene: +Workflowen (`.github/workflows/deploy.yml`) er lik i alle repoene bortsett fra tjenestenavnet på slutten av `ssh`-kommandoen. Innloggingsinfo hentes fra GitHub sine _secrets_ og _variables_ på organisasjonsnivå, under _Settings → Secrets and variables → Actions_ for [UiO-Gaming](https://github.com/UiO-Gaming), og deles av alle repoene: -| Navn | Type | Nivå | Innhold | -| ----------------- | -------- | ------------ | ----------------------------------------------- | -| `SSH_PRIVATE_KEY` | Secret | Organisasjon | Privat SSH-nøkkel for `github_deploy` | -| `SSH_USER` | Secret | Organisasjon | Brukernavnet, altså `github_deploy` | -| `SSH_HOST` | Variable | Organisasjon | `uiogaming.no` | -| `MAIN_BRANCH` | Variable | Organisasjon | `main` | -| `WORK_DIR` | Secret | Repo | Mappen applikasjonen ligger i på servermaskinen | +| Navn | Type | Nivå | Innhold | +| ----------------- | -------- | ------------ | ------------------------------------- | +| `SSH_PRIVATE_KEY` | Secret | Organisasjon | Privat SSH-nøkkel for `github_deploy` | +| `SSH_USER` | Secret | Organisasjon | Brukernavnet, altså `github_deploy` | +| `SSH_HOST` | Variable | Organisasjon | `uiogaming.no` | -Den offentlige delen av SSH-nøkkelen ligger i `~/.ssh/authorized_keys` til `github_deploy` på servermaskinen. Byttes nøkkelen må begge stedene oppdateres, men bare én gang siden den deles av alle repoene. +Den offentlige delen av SSH-nøkkelen ligger i `~/.ssh/authorized_keys` til `github_deploy` på servermaskinen, med `restrict,command="/usr/local/bin/uiogaming-deploy"` foran. Byttes nøkkelen må begge stedene oppdateres, men bare én gang siden den deles av alle repoene. Vil du sette opp automatisk deployment for et nytt repo: -1. Kopier `deploy.yml` fra et av repoene over -2. Legg til `WORK_DIR` som secret i det nye repoet -3. Sjekk at organisasjonens secrets og variables er tilgjengelige for det nye repoet. De kan være begrenset til utvalgte repoer -4. Sørg for at `github_deploy` har tilgang til mappen applikasjonen ligger i på servermaskinen, samt kan kjøre `git` og `docker` der +1. Legg til tjenesten i `/srv/uiogaming/docker-compose.yml` og klon repoet til `/srv/uiogaming/` +2. Legg til tjenesten i `REPO`-lista i [`deploy/uiogaming-deploy`](deploy/uiogaming-deploy), og kopier scriptet til `/usr/local/bin/uiogaming-deploy` på servermaskinen +3. Kopier `deploy.yml` fra et av repoene over og bytt ut tjenestenavnet +4. Sjekk at organisasjonens secrets og variables er tilgjengelige for det nye repoet. De kan være begrenset til utvalgte repoer +5. Kjør `git config --global --add safe.directory /srv/uiogaming/` som `github_deploy` # Nyttige guider