- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
15 KiB
NPMplus Backup and Restore Guide
Last Updated: 2026-01-31
Document Version: 1.0
Status: Active Documentation
Date: 2026-01-20
Status: Complete Backup/Restore Procedures
Purpose: Backup and restore procedures for NPMplus configuration
Overview
This guide provides backup and restore procedures for NPMplus (VMID 10233) configuration, including:
- NPMplus database export (SQLite)
- Proxy host configuration export (JSON via API)
- Certificate export (file copy)
- Docker volume backup
NPMplus Container Information
| Property | Value |
|---|---|
| VMID | 10233 |
| Host | r630-01 (192.168.11.11) |
| Internal IP (eth0) | 192.168.11.166 |
| Internal IP (eth1) | 192.168.11.167 |
| Management UI | https://192.168.11.166:81 |
| Database Location | /data/database.sqlite (inside container) |
| Certificate Location | /data/tls/certbot/live/ (inside container) |
| Docker Container | npmplus |
Backup Procedures
Automated Backup Script
Script Location: scripts/verify/backup-npmplus.sh ✅ CREATED
Manual Backup Steps:
1. NPMplus Database Export (SQLite)
Method 1: Direct SQLite Export:
NPMPLUS_VMID=10233
NPMPLUS_HOST=192.168.11.11
BACKUP_DIR="/tmp/npmplus-backup-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# Export database
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c '
cd /app
if [ -f /data/database.sqlite ]; then
sqlite3 /data/database.sqlite \".dump\" > /tmp/npm-database.sql 2>/dev/null || echo \"Database export may have issues\"
fi
'"
# Copy database export
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /tmp/npm-database.sql" > "$BACKUP_DIR/database.sql"
Method 2: Copy Database File:
# Copy entire database file
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /data/database.sqlite" > "$BACKUP_DIR/database.sqlite"
2. Proxy Host Configuration Export (JSON via API)
Using Export Script:
bash scripts/verify/export-npmplus-config.sh
Manual Export via API:
NPM_URL="https://192.168.11.166:81"
NPM_EMAIL="nsatoshi2007@hotmail.com"
# Note: Use .env file for credentials in production
# NPM_PASSWORD="your-password" # Set in .env file
BACKUP_DIR="/tmp/npmplus-backup-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# Authenticate
TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" \
-H "Content-Type: application/json" \
-d "{\"identity\":\"$NPM_EMAIL\",\"secret\":\"$NPM_PASSWORD\"}")
TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.token')
# Export proxy hosts
curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" \
-H "Authorization: Bearer $TOKEN" | jq '.' > "$BACKUP_DIR/proxy_hosts.json"
# Export certificates
curl -s -k -X GET "$NPM_URL/api/nginx/certificates" \
-H "Authorization: Bearer $TOKEN" | jq '.' > "$BACKUP_DIR/certificates.json"
3. Certificate Export (File Copy)
NPMPLUS_VMID=10233
NPMPLUS_HOST=192.168.11.11
BACKUP_DIR="/tmp/npmplus-backup-$(date +%Y%m%d_%H%M%S)/certs"
mkdir -p "$BACKUP_DIR"
# List all certificates
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- ls -1 /data/tls/certbot/live/" > "$BACKUP_DIR/cert_list.txt"
# Copy all certificate directories
while IFS= read -r cert_dir; do
if [ -n "$cert_dir" ] && [ "$cert_dir" != "lost+found" ]; then
mkdir -p "$BACKUP_DIR/$cert_dir"
# Copy fullchain.pem
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /data/tls/certbot/live/$cert_dir/fullchain.pem" > "$BACKUP_DIR/$cert_dir/fullchain.pem"
# Copy privkey.pem
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /data/tls/certbot/live/$cert_dir/privkey.pem" > "$BACKUP_DIR/$cert_dir/privkey.pem"
fi
done < "$BACKUP_DIR/cert_list.txt"
4. Docker Volume Backup
NPMPLUS_VMID=10233
NPMPLUS_HOST=192.168.11.11
BACKUP_DIR="/tmp/npmplus-backup-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# Get Docker volume name
VOLUME_NAME=$(ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- docker inspect npmplus --format '{{ range .Mounts }}{{ if eq .Destination \"/data\" }}{{ .Name }}{{ end }}{{ end }}'" 2>/dev/null || echo "")
# Create volume backup (if using Docker volumes)
if [ -n "$VOLUME_NAME" ]; then
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- docker run --rm -v $VOLUME_NAME:/data -v $(pwd)/$BACKUP_DIR:/backup alpine tar czf /backup/npmplus-data.tar.gz -C /data ."
fi
Complete Backup Script
Create: scripts/verify/backup-npmplus.sh
#!/usr/bin/env bash
# Complete NPMplus backup script
# Backs up database, proxy hosts, certificates, and Docker volumes
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Source .env
if [ -f "$PROJECT_ROOT/.env" ]; then
set +euo pipefail
source "$PROJECT_ROOT/.env" 2>/dev/null || true
set -euo pipefail
fi
NPMPLUS_VMID="${NPMPLUS_VMID:-10233}"
NPMPLUS_HOST="${NPMPLUS_HOST:-192.168.11.11}"
NPM_URL="${NPM_URL:-https://192.168.11.166:81}"
NPM_EMAIL="${NPM_EMAIL:-nsatoshi2007@hotmail.com}"
NPM_PASSWORD="${NPM_PASSWORD:-}"
BACKUP_DIR="/tmp/npmplus-backup-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📦 NPMplus Complete Backup"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Backup directory: $BACKUP_DIR"
echo ""
# 1. Database backup
echo "1. Backing up database..."
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c '
if [ -f /data/database.sqlite ]; then
sqlite3 /data/database.sqlite \".dump\" > /tmp/npm-database.sql 2>/dev/null || echo \"Database export may have issues\"
cp /data/database.sqlite /tmp/database.sqlite 2>/dev/null || true
fi
'"
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /tmp/npm-database.sql" > "$BACKUP_DIR/database.sql" 2>/dev/null || true
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /tmp/database.sqlite" > "$BACKUP_DIR/database.sqlite" 2>/dev/null || true
echo "✅ Database backup complete"
echo ""
# 2. Proxy hosts and certificates via API
if [ -n "$NPM_PASSWORD" ]; then
echo "2. Backing up proxy hosts and certificates via API..."
TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" \
-H "Content-Type: application/json" \
-d "{\"identity\":\"$NPM_EMAIL\",\"secret\":\"$NPM_PASSWORD\"}")
TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.token // empty' 2>/dev/null || echo "")
if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ]; then
curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" \
-H "Authorization: Bearer $TOKEN" | jq '.' > "$BACKUP_DIR/proxy_hosts.json"
curl -s -k -X GET "$NPM_URL/api/nginx/certificates" \
-H "Authorization: Bearer $TOKEN" | jq '.' > "$BACKUP_DIR/certificates.json"
echo "✅ API backup complete"
else
echo "⚠️ API backup failed (authentication error)"
fi
else
echo "⚠️ Skipping API backup (NPM_PASSWORD not set)"
fi
echo ""
# 3. Certificate files
echo "3. Backing up certificate files..."
CERT_DIR="$BACKUP_DIR/certs"
mkdir -p "$CERT_DIR"
CERT_LIST=$(ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- ls -1 /data/tls/certbot/live/ 2>/dev/null" | grep -v "lost+found" || echo "")
if [ -n "$CERT_LIST" ]; then
while IFS= read -r cert_dir; do
if [ -n "$cert_dir" ]; then
mkdir -p "$CERT_DIR/$cert_dir"
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /data/tls/certbot/live/$cert_dir/fullchain.pem" > "$CERT_DIR/$cert_dir/fullchain.pem" 2>/dev/null || true
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- cat /data/tls/certbot/live/$cert_dir/privkey.pem" > "$CERT_DIR/$cert_dir/privkey.pem" 2>/dev/null || true
fi
done <<< "$CERT_LIST"
echo "✅ Certificate backup complete"
else
echo "⚠️ No certificates found"
fi
echo ""
# 4. Create backup archive
echo "4. Creating backup archive..."
cd "$(dirname "$BACKUP_DIR")"
tar czf "$(basename "$BACKUP_DIR").tar.gz" "$(basename "$BACKUP_DIR")" 2>/dev/null || true
BACKUP_ARCHIVE="$(dirname "$BACKUP_DIR")/$(basename "$BACKUP_DIR").tar.gz"
if [ -f "$BACKUP_ARCHIVE" ]; then
echo "✅ Backup archive created: $BACKUP_ARCHIVE"
echo ""
echo "Backup complete!"
echo "Directory: $BACKUP_DIR"
echo "Archive: $BACKUP_ARCHIVE"
else
echo "⚠️ Archive creation failed, backup directory available: $BACKUP_DIR"
fi
Restore Procedures
1. Database Restore
Restore SQLite Database:
NPMPLUS_VMID=10233
NPMPLUS_HOST=192.168.11.11
BACKUP_DIR="/tmp/npmplus-backup-20260120_120000"
# Stop NPMplus (if running)
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- docker stop npmplus"
# Restore database from SQL dump
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c '
cd /app
if [ -f /data/database.sqlite ]; then
mv /data/database.sqlite /data/database.sqlite.bak
fi
'"
cat "$BACKUP_DIR/database.sql" | ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c 'sqlite3 /data/database.sqlite'"
# OR restore from file copy
# ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c 'cp /tmp/database.sqlite /data/database.sqlite'"
# cat "$BACKUP_DIR/database.sqlite" | ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c 'cat > /data/database.sqlite'"
# Restart NPMplus
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- docker start npmplus"
2. Configuration Restore (via API)
Restore Proxy Hosts:
NPM_URL="https://192.168.11.166:81"
NPM_EMAIL="nsatoshi2007@hotmail.com"
# Note: Use .env file for credentials in production
# NPM_PASSWORD="your-password" # Set in .env file
BACKUP_DIR="/tmp/npmplus-backup-20260120_120000"
# Authenticate
TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" \
-H "Content-Type: application/json" \
-d "{\"identity\":\"$NPM_EMAIL\",\"secret\":\"$NPM_PASSWORD\"}")
TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.token')
# Create proxy hosts from backup
cat "$BACKUP_DIR/proxy_hosts.json" | jq -c '.[]' | while read -r proxy_host; do
curl -s -k -X POST "$NPM_URL/api/nginx/proxy-hosts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$proxy_host"
done
# Request certificates (they will auto-renew)
cat "$BACKUP_DIR/certificates.json" | jq -c '.[]' | while read -r cert; do
domains=$(echo "$cert" | jq -r '.domain_names | join(",")')
# Request new certificate via API or UI
done
3. Certificate Restore
NPMPLUS_VMID=10233
NPMPLUS_HOST=192.168.11.11
BACKUP_DIR="/tmp/npmplus-backup-20260120_120000"
# Stop NPMplus
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- docker stop npmplus"
# Restore certificates
CERT_DIR="$BACKUP_DIR/certs"
if [ -d "$CERT_DIR" ]; then
for cert_dir in "$CERT_DIR"/*; do
if [ -d "$cert_dir" ]; then
cert_name=$(basename "$cert_dir")
mkdir -p /tmp/cert_restore
cp "$cert_dir/fullchain.pem" /tmp/cert_restore/fullchain.pem
cp "$cert_dir/privkey.pem" /tmp/cert_restore/privkey.pem
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- mkdir -p /data/tls/certbot/live/$cert_name"
cat /tmp/cert_restore/fullchain.pem | ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c 'cat > /data/tls/certbot/live/$cert_name/fullchain.pem'"
cat /tmp/cert_restore/privkey.pem | ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- bash -c 'cat > /data/tls/certbot/live/$cert_name/privkey.pem'"
fi
done
fi
# Restart NPMplus
ssh root@"$NPMPLUS_HOST" "pct exec $NPMPLUS_VMID -- docker start npmplus"
Disaster Recovery Scenarios
Scenario 1: NPMplus Container Lost (VMID Recreated)
Restore Steps:
-
Recreate Container:
- Install NPMplus on new container (VMID)
- Get new IP address
- Update UDM Pro port forwarding (if IP changed)
-
Restore Database:
- Copy database backup to new container
- Restore as described above
-
Restore Certificates:
- Copy certificate files to new container
- Restore as described above
-
Verify Configuration:
- Run verification scripts
- Test all domains
Scenario 2: NPMplus Database Corrupted
Restore Steps:
- Stop NPMplus:
ssh root@192.168.11.11 "pct exec 10233 -- docker stop npmplus"
- Backup Current Database:
ssh root@192.168.11.11 "pct exec 10233 -- cp /data/database.sqlite /data/database.sqlite.corrupted"
-
Restore from Backup:
- Restore database as described above
-
Verify and Test:
- Start NPMplus
- Verify all proxy hosts exist
- Test domains
Scenario 3: Certificate Files Lost
Restore Steps:
-
If Backup Available:
- Restore certificate files as described above
-
If No Backup Available:
- Re-request certificates via NPMplus UI or API
- Certificates will auto-renew from Let's Encrypt
Backup Schedule Recommendations
Recommended Backup Schedule
| Backup Type | Frequency | Retention | Location |
|---|---|---|---|
| Complete Backup | Weekly | 4 weeks | /tmp/npmplus-backup-* |
| Database Export | Daily | 7 days | Backup server or cloud storage |
| Configuration Export (API) | After each change | 30 days | Version control or config management |
| Certificate Export | Monthly | 90 days | Secure storage (encrypted) |
Automated Backup Script
Create cron job for daily backups:
# Add to crontab (crontab -e)
0 2 * * * /home/intlc/projects/proxmox/scripts/verify/backup-npmplus.sh >> /var/log/npmplus-backup.log 2>&1
Backup Retention Policy
- Daily backups: Keep 7 days
- Weekly backups: Keep 4 weeks
- Monthly backups: Keep 3 months
- Before major changes: Keep indefinitely
Verification After Restore
After restore, verify:
- NPMplus Container Status:
ssh root@192.168.11.11 "pct exec 10233 -- docker ps | grep npmplus"
- Proxy Hosts:
bash scripts/verify/export-npmplus-config.sh
- Certificates:
# Check certificate files exist
ssh root@192.168.11.11 "pct exec 10233 -- ls -la /data/tls/certbot/live/"
- End-to-End Tests:
bash scripts/verify/verify-end-to-end-routing.sh
Related Documentation
- Verification Runbook:
docs/04-configuration/INGRESS_VERIFICATION_RUNBOOK.md - NPMplus Setup:
docs/04-configuration/NPMPLUS_COMPLETE_SETUP_SUMMARY.md - Backup Scripts:
scripts/verify/backup-npmplus.sh(to be created)
Last Updated: 2026-01-20
Maintained By: Infrastructure Team
Status: Complete Backup/Restore Procedures