apps/backup/backup.sh 1.6 K raw
1
#!/bin/sh
2
set -eu
3
4
TIMESTAMP=$(date -u +%Y-%m-%dT%H%M%SZ)
5
BUCKET="${R2_BUCKET:-andromeda-backups}"
6
RETENTION_DAYS="${RETENTION_DAYS:-30}"
7
8
DBS="jotts:/data/jotts/jotts.sqlite sipp:/data/sipp/sipp.sqlite cellar:/data/cellar/cellar.sqlite posts:/data/posts/posts.sqlite feeds:/data/feeds/feeds.sqlite library:/data/library/library.sqlite bookmarks:/data/bookmarks/bookmarks.sqlite parcels:/data/parcels/parcels.db easel:/data/easel/easel.sqlite"
9
10
for entry in $DBS; do
11
  name="${entry%%:*}"
12
  path="${entry#*:}"
13
14
  if [ ! -f "$path" ]; then
15
    echo "WARN: $path not found, skipping $name"
16
    continue
17
  fi
18
19
  backup_file="/tmp/${name}-${TIMESTAMP}.sqlite"
20
  echo "$(date -u) Backing up $name..."
21
  sqlite3 "$path" ".backup '$backup_file'"
22
  gzip "$backup_file"
23
  aws s3 cp "${backup_file}.gz" "s3://${BUCKET}/${name}/${TIMESTAMP}.sqlite.gz" \
24
    --endpoint-url "${R2_ENDPOINT}"
25
  rm -f "${backup_file}.gz"
26
  echo "$(date -u) OK: $name uploaded"
27
done
28
29
# Prune old backups
30
cutoff=$(date -u -d "-${RETENTION_DAYS} days" +%Y-%m-%d 2>/dev/null || date -u -v-${RETENTION_DAYS}d +%Y-%m-%d)
31
for name in jotts sipp cellar posts feeds library bookmarks parcels easel; do
32
  aws s3 ls "s3://${BUCKET}/${name}/" --endpoint-url "${R2_ENDPOINT}" 2>/dev/null | while read -r line; do
33
    filedate=$(echo "$line" | awk '{print $1}')
34
    filename=$(echo "$line" | awk '{print $4}')
35
    if [ -n "$filename" ] && [ "$filedate" \< "$cutoff" ]; then
36
      aws s3 rm "s3://${BUCKET}/${name}/${filename}" --endpoint-url "${R2_ENDPOINT}"
37
      echo "$(date -u) Pruned: ${name}/${filename}"
38
    fi
39
  done
40
done
41
42
echo "$(date -u) Backup complete"