# Disaster Recovery Plan

**Version:** 1.0
**Effective:** February 2026
**Owner:** Johan Jongsma
**Review:** Annually
**Last DR Test:** Not yet performed

---

## 1. Purpose

Define procedures to recover Dealspace services and data following a disaster affecting production systems.

---

## 2. Scope

| System | Location | Criticality |
|--------|----------|-------------|
| Production server | 82.24.174.112 (Zürich) | Critical |
| Database | /opt/dealspace/data/dealspace.db | Critical |
| Master encryption key | Secure storage | Critical |

---

## 3. Recovery Objectives

| Metric | Target |
|--------|--------|
| **RTO** (Recovery Time Objective) | 4 hours |
| **RPO** (Recovery Point Objective) | 24 hours |

---

## 4. Backup Strategy

### Backup Inventory

| Data | Method | Frequency | Retention | Location |
|------|--------|-----------|-----------|----------|
| Database | SQLite backup | Daily | 30 days | Encrypted off-site |
| Master key | Manual copy | On change | Permanent | Separate secure storage |
| Configuration | Git repository | Per change | Permanent | Remote repository |

### Encryption

All data is encrypted before leaving the server:
- Database fields: AES-256-GCM encryption with per-project keys
- Off-site backups: Already encrypted
- Master key: Stored separately from data backups

---

## 5. Disaster Scenarios

### Scenario A: Hardware Failure (Single Component)

**Symptoms:** Server unresponsive, network failure

**Recovery:**
1. Contact Hostkey support
2. Restore from backup to new VPS if needed
3. Verify services: health check endpoint
4. Update DNS if IP changed

**Estimated time:** 2-4 hours

### Scenario B: Database Corruption

**Symptoms:** Application errors, SQLite integrity failures

**Recovery:**

```bash
# 1. Stop services
ssh root@82.24.174.112 "systemctl stop dealspace"

# 2. Backup corrupted DB for analysis
ssh root@82.24.174.112 "cp /opt/dealspace/data/dealspace.db /opt/dealspace/data/dealspace.db.corrupted"

# 3. Restore from backup
# Download latest backup and restore
scp backup-server:/backups/dealspace-latest.db.enc /tmp/
# Decrypt and place in position

# 4. Restart services
ssh root@82.24.174.112 "systemctl start dealspace"

# 5. Verify
curl -s https://muskepo.com/health
```

**Estimated time:** 1-2 hours

### Scenario C: Complete Server Loss

**Symptoms:** Server destroyed, stolen, or unrecoverable

**Recovery:**

```bash
# 1. Provision new VPS at Hostkey
# 2. Apply OS hardening (see security-policy.md)

# 3. Create directory structure
mkdir -p /opt/dealspace/{bin,data}

# 4. Restore master key from secure storage
# Copy 32-byte key to secure location
chmod 600 /opt/dealspace/master.key

# 5. Restore database from backup
# Download encrypted backup
# Decrypt and place at /opt/dealspace/data/dealspace.db

# 6. Deploy application binary
scp dealspace-linux root@NEW_IP:/opt/dealspace/bin/dealspace
chmod +x /opt/dealspace/bin/dealspace

# 7. Configure systemd service
# 8. Start service
# 9. Update DNS to new IP

# 10. Verify
curl -s https://muskepo.com/health
```

**Estimated time:** 4-8 hours

### Scenario D: Ransomware/Compromise

**Symptoms:** Encrypted files, unauthorized access, system tampering

**Recovery:**
1. **Do not use compromised system** - assume attacker persistence
2. Provision fresh VPS from scratch
3. Restore from known-good backup (before compromise date)
4. Rotate master key and re-encrypt all data
5. Rotate all credentials
6. Apply additional hardening
7. Monitor closely for re-compromise

**Estimated time:** 8-24 hours

### Scenario E: Provider/Region Loss

**Symptoms:** Hostkey Zürich unavailable

**Recovery:**
1. Provision new VPS at alternate provider
2. Restore from off-site backup
3. Restore master key from secure storage
4. Deploy application
5. Update DNS

**Estimated time:** 24-48 hours

---

## 6. Key Management

### Master Key Recovery

The master key is **critical**. Without it, all encrypted data is permanently unrecoverable.

**Storage locations:**
1. Production server: Secure location
2. Secure backup: Separate secure storage (not with data backups)

**Recovery procedure:**
1. Retrieve the 32-byte master key from secure storage
2. Create file with proper permissions
3. Verify length (must be exactly 32 bytes)

### Key Rotation (If Compromised)

If the master key may be compromised:

1. Generate new master key
2. Run re-encryption migration (decrypt with old key, re-encrypt with new)
3. Replace key file
4. Update secure storage with new key
5. Verify application functionality

---

## 7. Recovery Procedures

### Pre-Recovery Checklist

- [ ] Incident documented and severity assessed
- [ ] Stakeholders notified
- [ ] Backup integrity verified
- [ ] Recovery environment prepared
- [ ] Master key accessible

### Database Restore from Backup

```bash
# Stop services
ssh root@82.24.174.112 "systemctl stop dealspace"

# Download and decrypt backup
# Place at /opt/dealspace/data/dealspace.db

# Start services
ssh root@82.24.174.112 "systemctl start dealspace"

# Verify
curl -s https://muskepo.com/health
```

---

## 8. Communication During Disaster

| Audience | Method | Message |
|----------|--------|---------|
| Clients | Email + status page | "Dealspace is experiencing technical difficulties. We expect to restore service by [time]." |
| Affected clients | Direct email | Per incident response plan if data affected |

---

## 9. Testing Schedule

| Test Type | Frequency | Last Performed | Next Due |
|-----------|-----------|----------------|----------|
| Backup verification | Monthly | Not yet | March 2026 |
| Database restore | Quarterly | Not yet | Q1 2026 |
| Full DR drill | Annually | Not yet | Q4 2026 |

### Backup Verification Procedure

```bash
# Monthly: Verify backups exist and are readable
# List available backups
# Verify database integrity of latest backup
```

### Restore Test Procedure

```bash
# Quarterly: Restore to test environment and verify

# 1. Download backup to test environment
# 2. Verify database integrity: sqlite3 test.db "PRAGMA integrity_check"
# 3. Verify data is readable (requires master key)
# 4. Document results
# 5. Clean up test files
```

---

## 10. Post-Recovery Checklist

After any recovery:

- [ ] All services operational (health check passes)
- [ ] Data integrity verified (spot-check records)
- [ ] Logs reviewed for errors
- [ ] Clients notified if there was visible outage
- [ ] Incident documented
- [ ] Post-mortem scheduled if significant event
- [ ] This plan updated if gaps discovered

---

## 11. Quick Reference

### Critical Paths

| Item | Path |
|------|------|
| Database | /opt/dealspace/data/dealspace.db |
| Binary | /opt/dealspace/bin/dealspace |
| Master key | Secure location |

### Service Commands

```bash
# Status
ssh root@82.24.174.112 "systemctl status dealspace"

# Stop
ssh root@82.24.174.112 "systemctl stop dealspace"

# Start
ssh root@82.24.174.112 "systemctl start dealspace"

# Logs
ssh root@82.24.174.112 "journalctl -u dealspace -f"

# Health check
curl -s https://muskepo.com/health
```

---

*Document end*
