Varmuuskopiointi ja automaatio – tekninen kuvaus

Tavoite ja periaatteet

Lähtökohta oli käytännöllinen:

  • säännölliset varmuuskopiot kotihakemistosta ja www-sisällöstä
  • selkeästi päivämäärän mukaan nimetyt varmuuskopiot
  • vanhimpien varmuuskopioiden automaattinen siivous (säilytä viimeiset N kappaletta)
  • lokitiedosto, josta näkee mitä ajettiin, mitä poistettiin ja milloin

Ratkaisu perustuu helposti ymmärrettäviin työkaluihin (shell-skriptit, cron, tar/rsync/rclone), ei suljettuun “mustaan laatikkoon”.

Hakemistorakenne

/home/jarno/
  scripts/
    backup-www.sh
    backup-home.sh
    prune-backups.sh

  backups/
    www/
    home/
    logs/
      backup.log
      prune.log

scripts/-hakemistossa sijaitsevat ajettavat skriptit ja backups/-hakemistossa itse varmuuskopiot sekä lokit.

Varmuuskopiointiskriptit

www-sisällön varmuuskopiointi

#!/bin/bash
set -euo pipefail

BACKUP_ROOT="/home/jarno/backups/www"
SOURCE_DIR="/var/www"
TIMESTAMP="$(date +%F_%H-%M-%S)"
ARCHIVE_NAME="www-${TIMESTAMP}.tar.gz"
LOG_FILE="/home/jarno/backups/logs/backup.log"

mkdir -p "${BACKUP_ROOT}"

tar -czf "${BACKUP_ROOT}/${ARCHIVE_NAME}" "${SOURCE_DIR}" 2>>"${LOG_FILE}"

echo "$(date +%F_%T) [INFO] Created ${BACKUP_ROOT}/${ARCHIVE_NAME}" >>"${LOG_FILE}"

Kotihakemiston varmuuskopiointi

#!/bin/bash
set -euo pipefail

BACKUP_ROOT="/home/jarno/backups/home"
SOURCE_DIR="/home/jarno"
TIMESTAMP="$(date +%F_%H-%M-%S)"
ARCHIVE_NAME="home-${TIMESTAMP}.tar.gz"
LOG_FILE="/home/jarno/backups/logs/backup.log"

mkdir -p "${BACKUP_ROOT}"

tar --exclude="${BACKUP_ROOT}" \
    --exclude="${SOURCE_DIR}/.cache" \
    -czf "${BACKUP_ROOT}/${ARCHIVE_NAME}" "${SOURCE_DIR}" 2>>"${LOG_FILE}"

echo "$(date +%F_%T) [INFO] Created ${BACKUP_ROOT}/${ARCHIVE_NAME}" >>"${LOG_FILE}"

Poissulut (esim. .cache) pitävät arkistot järkevän kokoisina, eikä varmuuskopio-hakemistoa arkistoida itseensä.

Vanhojen varmuuskopioiden automaattinen siivous

#!/bin/bash
set -euo pipefail

KEEP=14  # säilytettävien varmuuskopioiden määrä
TARGET_DIR="$1"
LOG_FILE="/home/jarno/backups/logs/prune.log"

if [[ ! -d "${TARGET_DIR}" ]]; then
  echo "$(date +%F_%T) [WARN] Target dir ${TARGET_DIR} not found" >>"${LOG_FILE}"
  exit 0
fi

MAPFILE -t FILES < <(ls -1t "${TARGET_DIR}"/*.tar.gz 2>/dev/null || true)

COUNT="${#FILES[@]}"

if (( COUNT <= KEEP )); then
  echo "$(date +%F_%T) [INFO] Nothing to prune in ${TARGET_DIR} (count=${COUNT}, keep=${KEEP})" >>"${LOG_FILE}"
  exit 0
fi

TO_DELETE=("${FILES[@]:KEEP}")

for f in "${TO_DELETE[@]}"; do
  rm -f -- "$f"
  echo "$(date +%F_%T) [INFO] Deleted $f" >>"${LOG_FILE}"
done

Skripti säilyttää uusimmat varmuuskopiot ja poistaa vanhimmat. Kaikki poistot kirjataan lokiin, jotta historia näkyy selkeästi.

Ajastus cronilla

Varmuuskopioinnit ja siivous ajetaan yöllä, kun koneella ei yleensä tehdä aktiivista työtä:

# www-varmuuskopio klo 03:15
15 3 * * * /home/jarno/scripts/backup-www.sh

# kotihakemiston varmuuskopio klo 03:30
30 3 * * * /home/jarno/scripts/backup-home.sh

# vanhojen varmuuskopioiden siivous klo 03:45
45 3 * * * /home/jarno/scripts/prune-backups.sh /home/jarno/backups/www
50 3 * * * /home/jarno/scripts/prune-backups.sh /home/jarno/backups/home

Lokiohjaus voidaan tehdä suoraan skripteissä, jolloin crontab-rivit pysyvät lyhyinä.

Lokitus ja läpinäkyvyys

Lokien tarkoitus on, että ongelmatilanteessa ei tarvitse arvailla:

  • onnistuneet ajot: “Created …”
  • siivousajot: “Deleted …”
  • varoitukset: puuttuva hakemisto tai tyhjä hakemisto

Lokin voi lukea suoraan komentoriviltä, tai sen voi halutessaan syöttää myöhemmin keskitettyyn lokijärjestelmään.

Jatkokehitys ja integraatiot

Tätä kokonaisuutta voi laajentaa esimerkiksi:

  • synkronoinnilla offsite-sijaintiin (esim. rclone → pilvipalvelu)
  • mail- tai Telegram-ilmoituksilla epäonnistuneista ajoista
  • pienellä HTML-/CLI-raportilla, joka kokoaa yhteen viimeisimmät ajot ja varmuuskopioiden määrän

Perusajatus säilyy: yksinkertainen skripti on helppo lukea ja korjata, kun jokin menee joskus väistämättä poikki.