Monorepo for Aesthetic.Computer
aesthetic.computer
1#!/usr/bin/env bash
2# PDS Backup Script
3# Backs up SQLite databases and configuration
4
5set -euo pipefail
6
7# Configuration
8PDS_DIR="${PDS_DIR:-/pds}"
9BACKUP_DIR="${BACKUP_DIR:-/backups/pds}"
10RETENTION_DAYS="${RETENTION_DAYS:-30}"
11TIMESTAMP=$(date +%Y%m%d-%H%M%S)
12
13# Colors
14GREEN='\033[0;32m'
15BLUE='\033[0;34m'
16YELLOW='\033[1;33m'
17NC='\033[0m'
18
19echo "╔════════════════════════════════════════╗"
20echo "║ PDS Backup ║"
21echo "╚════════════════════════════════════════╝"
22echo ""
23
24# Create backup directory
25mkdir -p "$BACKUP_DIR"
26
27echo -e "${BLUE}ℹ${NC} Backup directory: $BACKUP_DIR"
28echo -e "${BLUE}ℹ${NC} Timestamp: $TIMESTAMP"
29echo ""
30
31# Backup SQLite databases
32backup_database() {
33 local DB_NAME=$1
34 local DB_PATH="$PDS_DIR/$DB_NAME"
35
36 if [ ! -f "$DB_PATH" ]; then
37 echo -e "${YELLOW}⊘${NC} $DB_NAME not found, skipping"
38 return 0
39 fi
40
41 echo -n "Backing up $DB_NAME... "
42
43 # Use SQLite backup command for consistency
44 sqlite3 "$DB_PATH" ".backup '$BACKUP_DIR/${DB_NAME%.sqlite}-$TIMESTAMP.sqlite'" 2>/dev/null
45
46 if [ $? -eq 0 ]; then
47 SIZE=$(du -h "$BACKUP_DIR/${DB_NAME%.sqlite}-$TIMESTAMP.sqlite" | cut -f1)
48 echo -e "${GREEN}✓${NC} ($SIZE)"
49 return 0
50 else
51 echo -e "${RED}✗${NC} FAILED"
52 return 1
53 fi
54}
55
56# Backup configuration
57backup_config() {
58 echo -n "Backing up configuration... "
59
60 if [ -f "$PDS_DIR/pds.env" ]; then
61 cp "$PDS_DIR/pds.env" "$BACKUP_DIR/pds.env-$TIMESTAMP"
62 echo -e "${GREEN}✓${NC}"
63 else
64 echo -e "${YELLOW}⊘${NC} pds.env not found"
65 fi
66}
67
68# Backup databases
69backup_database "accounts.sqlite"
70backup_database "blocks.sqlite"
71backup_database "pds.sqlite"
72
73# Backup config
74backup_config
75
76# Create compressed archive
77echo -n "Creating compressed archive... "
78ARCHIVE_NAME="pds-backup-$TIMESTAMP.tar.gz"
79tar czf "$BACKUP_DIR/$ARCHIVE_NAME" -C "$BACKUP_DIR" \
80 $(ls "$BACKUP_DIR" | grep "$TIMESTAMP") 2>/dev/null
81
82if [ $? -eq 0 ]; then
83 ARCHIVE_SIZE=$(du -h "$BACKUP_DIR/$ARCHIVE_NAME" | cut -f1)
84 echo -e "${GREEN}✓${NC} ($ARCHIVE_SIZE)"
85
86 # Remove individual files
87 rm -f "$BACKUP_DIR"/*-$TIMESTAMP.sqlite "$BACKUP_DIR"/*-$TIMESTAMP
88else
89 echo -e "${YELLOW}⚠${NC} Archive creation failed, keeping individual files"
90fi
91
92# Clean old backups
93echo -n "Cleaning old backups (>$RETENTION_DAYS days)... "
94DELETED=$(find "$BACKUP_DIR" -name "pds-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete -print | wc -l)
95echo -e "${GREEN}✓${NC} (deleted $DELETED)"
96
97# Summary
98echo ""
99echo "Backup Summary:"
100echo " Location: $BACKUP_DIR/$ARCHIVE_NAME"
101echo " Size: ${ARCHIVE_SIZE:-unknown}"
102echo " Retention: $RETENTION_DAYS days"
103
104# Optional: Upload to Spaces/S3
105if [ -n "${SPACES_BACKUP_BUCKET:-}" ]; then
106 echo ""
107 echo -n "Uploading to Spaces... "
108
109 if command -v s3cmd &> /dev/null; then
110 s3cmd put "$BACKUP_DIR/$ARCHIVE_NAME" "s3://$SPACES_BACKUP_BUCKET/backups/" &> /dev/null
111 echo -e "${GREEN}✓${NC}"
112 else
113 echo -e "${YELLOW}⊘${NC} s3cmd not installed"
114 fi
115fi
116
117echo ""
118echo -e "${GREEN}Backup complete!${NC}"