feat: initial itpp-docs setup with MkDocs Material
Publish Docs Site / build (push) Failing after 5s
Publish Docs Site / build (push) Failing after 5s
- mkdocs.yml with dark slate theme, nav for 12 ITPP projects - build-docs.sh aggregates docs from all project repos - .gitea/workflows/docs-publish.yml for nightly rebuild+deploy - README and CHANGELOG for the itpp-docs repo itself - docs-source/ populated from all 12 repos - site/ ready for deployment to docs.itpropartner.com
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# Backup-Restore — Architecture
|
||||
|
||||
## Topology
|
||||
|
||||
```
|
||||
INTERNET
|
||||
|
|
||||
[Caddy on Core]
|
||||
my.itpropartner.com
|
||||
|
|
||||
+---------------+---------------+
|
||||
| | |
|
||||
/backups/* /api/restore /api/backup
|
||||
/api/log /api/download /api/delete
|
||||
| | |
|
||||
+-------+-------+-------+-------+
|
||||
|
|
||||
app3 (152.53.241.111)
|
||||
netcup RS 4000
|
||||
|
|
||||
[Flask :8090]
|
||||
/opt/backup-restore/
|
||||
|
|
||||
+-------------------+-------------------+
|
||||
| | |
|
||||
snapshot.sh app.py (UI+API) snapshots/
|
||||
(cron 1AM,1PM) Jinja templates /opt/backup-restore/
|
||||
| | snapshots/<domain>/
|
||||
v v |
|
||||
[tar files] [render HTML] +------+------+
|
||||
[mysqldump] [REST API] | | |
|
||||
| | .tar.gz .sql note.txt
|
||||
v v
|
||||
/opt/backup-restore/ [Browser]
|
||||
snapshots/<domain>/
|
||||
<timestamp>/
|
||||
```
|
||||
|
||||
## Data Flow — Manual Backup
|
||||
|
||||
```
|
||||
Browser (user clicks "Backup Now")
|
||||
|
|
||||
|-- POST /api/backup {"domain":"x.com","note":"pre-deploy"}
|
||||
| |
|
||||
| v
|
||||
| Caddy → app3:8090
|
||||
| |
|
||||
| v
|
||||
| Flask api_backup()
|
||||
| |
|
||||
| |-- Parse nginx config → find htdocs path
|
||||
| |-- tar -czf files.tar.gz (timeout 300s)
|
||||
| |-- Parse wp-config.php → find DB_NAME
|
||||
| |-- mysqldump → database.sql (timeout 300s)
|
||||
| |-- Save note.txt, size.txt
|
||||
| |-- Return {"ok":true, "snapshot":"<timestamp>"}
|
||||
| |
|
||||
| v
|
||||
| snapshots/x.com/2026-07-20_163208/
|
||||
| files.tar.gz (16MB)
|
||||
| database.sql (74KB)
|
||||
| note.txt ("pre-deploy")
|
||||
| size.txt
|
||||
|
|
||||
v
|
||||
Browser reloads → new snapshot in list
|
||||
```
|
||||
|
||||
## Data Flow — Restore
|
||||
|
||||
```
|
||||
Browser (user clicks Restore on a snapshot)
|
||||
|
|
||||
|-- POST /api/restore {"domain":"x.com","snapshot":"2026-07-20_130001"}
|
||||
| |
|
||||
| v
|
||||
| Caddy → app3:8090 (flush_interval -1, 300s timeouts)
|
||||
| |
|
||||
| v
|
||||
| Flask api_restore()
|
||||
| |
|
||||
| |-- Find snapshot path
|
||||
| |-- tar -xzf files.tar.gz → htdocs (timeout 300s)
|
||||
| |-- mysql < database.sql → WordPress DB (timeout 300s)
|
||||
| |-- chown -R site-user:site-user
|
||||
| |-- Log to restore.log: "TS|x.com|snap_id|OK"
|
||||
| |-- Return {"ok":true, "msg":"x.com restored to <snap>"}
|
||||
| |
|
||||
| v
|
||||
| Site is restored
|
||||
|
|
||||
v
|
||||
Browser shows success toast → Restore History updates
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### 1. Flask App (`/opt/backup-restore/app/app.py`)
|
||||
- Single-file Flask application, port 8090
|
||||
- Jinja2 templating for backup dashboard (render_template_string)
|
||||
- 6 API endpoints (backup, restore, delete, download, log, index)
|
||||
- All HTML/CSS/JS inline in a single Python triple-quoted string
|
||||
- No auth — accessible via Caddy-only routing
|
||||
- Systemd: `backup-restore.service`
|
||||
|
||||
### 2. Snapshot Engine (`/opt/backup-restore/snapshot.sh`)
|
||||
- Bash script, runs at 1 AM and 1 PM via cron
|
||||
- Iterates all WordPress sites in `/etc/nginx/sites-enabled/`
|
||||
- Creates: files.tar.gz (document root), database.sql (MySQL dump)
|
||||
- Auto-cleanup: deletes snapshots older than 30 days
|
||||
- Log: `/opt/backup-restore/logs/snapshots.log`
|
||||
|
||||
### 3. Snapshot Storage (`/opt/backup-restore/snapshots/`)
|
||||
- Structure: `/<domain>/<YYYY-MM-DD_HHMMSS>/`
|
||||
- 9 WordPress domains, 10 snapshots each (10 days retention shown)
|
||||
- Average snapshot size: 16MB files + 74KB database
|
||||
- Total: ~1.4GB for full snapshot set
|
||||
|
||||
### 4. Restore Log (`/opt/backup-restore/logs/restore.log`)
|
||||
- Pipe-delimited format: `timestamp|domain|snapshot_id|status`
|
||||
- Written by api_restore() on every restore attempt
|
||||
- Read by /api/log → displayed in Restore History table
|
||||
- Last 50 entries retained
|
||||
|
||||
### 5. Caddy Proxy (on Core)
|
||||
- `handle /api/backup` → app3:8090
|
||||
- `handle /api/restore` → app3:8090 (flush_interval -1, 300s read/write timeouts)
|
||||
- `handle /api/download/*` → app3:8090
|
||||
- `handle /api/log` → app3:8090
|
||||
- `handle_path /backups/*` → app3:8090 (300s timeouts for long restores)
|
||||
- Domain: my.itpropartner.com
|
||||
|
||||
## 9 Hosted WordPress Sites
|
||||
|
||||
All served by CloudPanel on app3, backed up by this system:
|
||||
|
||||
| Domain | htdocs Path | DB Pattern |
|
||||
|---|---|---|
|
||||
| apextrackexperience.com | /home/apx/htdocs/apextrackexperience.com | wp-config DB_NAME |
|
||||
| boxpilotlogistics.com | /home/boxpilotlogistics/htdocs/boxpilotlogistics.com | wp-config DB_NAME |
|
||||
| debtrecoveryexperts.com | /home/debtrecoveryexperts/... | wp-config DB_NAME |
|
||||
| iamgmb.com | /home/iamgmb/... | wp-config DB_NAME |
|
||||
| katiewattdesign.com | /home/katiewattdesign/htdocs/katiewattdesign.com | wp-config DB_NAME |
|
||||
| katiewattsdesign.com | /home/katiewattsdesign/... | wp-config DB_NAME |
|
||||
| mainwp.itpropartner.com | /home/mainwp/... | wp-config DB_NAME |
|
||||
| vigilanttac.com | /home/vigilanttac/... | wp-config DB_NAME |
|
||||
| voipsimplicity.com | /home/voipsimplicity/... | wp-config DB_NAME |
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
1. **Single-file Flask app:** No package structure needed — the app has 6 endpoints and one HTML template. Keeping it in one file makes deployment trivial (scp + systemctl restart).
|
||||
|
||||
2. **Caddy on Core as single entry point:** app3 isn't exposed to the internet directly. All access goes through Core's Caddy with proper timeouts. The restore operation takes 30-45s and Caddy's default proxy timeout was killing connections mid-operation.
|
||||
|
||||
3. **Tar + mysqldump over rsync:** Snapshots are point-in-time archives, not incremental backups. Each snapshot is self-contained (files.tar.gz + database.sql). Restore is a single operation with no dependency chain.
|
||||
|
||||
4. **No auth on backup API:** The endpoints have no authentication. Access is controlled by Caddy routing — only requests through my.itpropartner.com reach the app. Internal network only.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Backup-Restore Changelog
|
||||
|
||||
## 2026-07-20 — Restore logging and manual backup
|
||||
|
||||
### Added
|
||||
- **Backup Now button:** Green "+ Backup Now" button on backup page
|
||||
- **Domain dropdown:** Select element with all 9 hosted domains
|
||||
- **Note field:** Optional "why" note saved as note.txt in snapshot
|
||||
- **Restore History section:** Auto-expanded table at bottom — Domain, Snapshot, Date/Time, Status
|
||||
- **Restore logging:** Every restore writes to `/opt/backup-restore/logs/restore.log`
|
||||
- **Status formatting:** Green OK / red FAILED with centered status column
|
||||
|
||||
### Fixed
|
||||
- **Restore timing out:** Caddy flush_interval added + 300s transport timeouts
|
||||
- **Route ordering:** `/api/restore` decorator was stacked on backup function → reconnected to restore function
|
||||
- **API routing:** `/api/restore`, `/api/backup`, `/api/log` not proxied → added to Caddy config
|
||||
- **Mobile toggle:** Inline `display:none` on site tables removed → CSS class toggle now works
|
||||
- **Mobile touch:** role="button", tabindex="0", Enter key support added to card headers
|
||||
- **Auto-expand first domain:** Removed — all domains now start collapsed
|
||||
- **Restore History auto-expanded:** tbl-log has class="show", arrow is ▼
|
||||
|
||||
### Changed
|
||||
- "Backup Log History" → "Restore History"
|
||||
- Config page scripts directory now shows content when clicked
|
||||
|
||||
## 2026-07-17 — Initial deployment
|
||||
- Flask app deployed on app3 as systemd service
|
||||
- Snapshot script scheduled (1 AM, 1 PM)
|
||||
- 9 WordPress sites configured for backup
|
||||
- Caddy proxy from Core via my.itpropartner.com
|
||||
@@ -0,0 +1,50 @@
|
||||
# Backup-Restore — my.itpropartner.com/backups/
|
||||
|
||||
## Architecture
|
||||
- **Server:** app3 (152.53.241.111, netcup RS 4000)
|
||||
- **Backend:** Flask Python app at `/opt/backup-restore/app/app.py` (port 8090)
|
||||
- **Proxy:** Caddy on Core → reverse_proxy to 152.53.241.111:8090 with 300s timeouts
|
||||
- **Snapshots:** `/opt/backup-restore/snapshots/<domain>/<timestamp>/`
|
||||
- **Scheduled:** `0 1,13 * * * /opt/backup-restore/snapshot.sh` — 1 AM and 1 PM daily
|
||||
- **Systemd:** `backup-restore.service`
|
||||
- **Retention:** 30 days (auto-cleanup)
|
||||
|
||||
## Sites Backed Up (9 domains)
|
||||
apextrackexperience.com, boxpilotlogistics.com, debtrecoveryexperts.com, iamgmb.com, katiewattdesign.com, katiewattsdesign.com, mainwp.itpropartner.com, vigilanttac.com, voipsimplicity.com
|
||||
|
||||
## Snapshot Contents
|
||||
Each snapshot directory contains:
|
||||
- `files.tar.gz` — WordPress document root tarball
|
||||
- `database.sql` — MySQL dump
|
||||
- `size.txt` — Total backup size in bytes
|
||||
- `note.txt` — Optional manual backup note
|
||||
|
||||
## API Endpoints
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | /backups/ | No | Backup dashboard page |
|
||||
| POST | /api/backup | No | Trigger manual backup |
|
||||
| POST | /api/restore | No | Restore a snapshot |
|
||||
| POST | /api/delete | No | Delete a snapshot |
|
||||
| GET | /api/download/<domain>/<id> | No | Download snapshot archive |
|
||||
| GET | /api/log | No | Restore history |
|
||||
|
||||
## Caddy Routes (on Core)
|
||||
```
|
||||
handle /api/backup → app3:8090
|
||||
handle /api/restore → app3:8090 (flush_interval -1, 300s timeouts)
|
||||
handle /api/download/* → app3:8090
|
||||
handle /api/log → app3:8090
|
||||
handle_path /backups/* → app3:8090 (300s timeouts)
|
||||
```
|
||||
|
||||
## Recovery
|
||||
```
|
||||
systemctl restart backup-restore
|
||||
# Manual snapshot:
|
||||
/opt/backup-restore/snapshot.sh
|
||||
# Manual restore via curl:
|
||||
curl -X POST https://my.itpropartner.com/api/restore \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"domain":"katiewattdesign.com","snapshot":"2026-07-20_130001"}'
|
||||
```
|
||||
Reference in New Issue
Block a user