The PC Takes Care of Itself — Backup, Cache, Image Compression

Written by

in

Self-hosting Build Series Part 4. Automation solves operations.

← Previous: Part 3 — AI Should Read (robots.txt·llms.txt)
→ Next: Part 5 — Star Whale Analytics Lab (Umami)


TL;DR

  • Backup: Daily mariadb-dump at 03:00 → gzip → Obsidian Vault. 30-day rotation. Content safe even if the mini-PC dies.
  • DB Cache: Memory caching of repeated queries with Redis Object Cache. Page response speeds up by 30%.
  • Page Cache: Generating static HTML with WP Super Cache. No PHP processing from the second visitor onward.
  • Images: Automatic WebP conversion with EWWW. Average size reduction of 30-70%.
  • One setup, and forget it.

1. The Real Work of Self-Hosting is Operation

Initial setup takes 30 minutes, but the real work begins afterward. Who backs up daily, clears caches, and compresses images? Humans forget. So, automate.

When each of the three automations runs, and what it does Backup runs daily at 03:00 via cron: mariadb-dump exports the database, gzip compresses it, it is saved into the Obsidian Vault, and the vault syncs to the laptop and phone. Backups older than 30 days are deleted automatically. Caching works on every visitor request: WP Super Cache serves finished HTML, Redis Object Cache absorbs repeated DB queries, and only when neither has it does the request reach MariaDB. Images are handled on upload: EWWW converts them to WebP with lossless compression, and older images are converted in bulk from the Bulk Optimize menu. When What runs Backup Daily 03:00 · cron mariadb-dump gzip Obsidian Vault Laptop, phone sync Backups older than 30 days are deleted (rotation) Cache On every request WP Super Cache Redis Object Cache MariaDB Caches finished HTML Caches repeated queries Only if both miss Images On upload Image upload EWWW WebP + lossless compression Older images: convert in bulk from the Bulk Optimize menu
Figure 1. When each automation runs and what it does. Backup is triggered by time (03:00), caching by visitor requests, image compression by uploads.

2. Backup — wp-backup.sh

/home/worker/scripts/wp-backup.sh:

#!/bin/bash
set -euo pipefail

BACKUP_DIR="/home/user/문서/Obsidian Vault/KnowledgeVault/Meta/backups/wordpress"
DATE=$(date +%Y-%m-%d)
LOG_DIR="/home/worker/logs"
WEEK=$(date +%Y-W%V)
LOG_FILE="$LOG_DIR/kimcorp-${WEEK}.log"

mkdir -p "$BACKUP_DIR" "$LOG_DIR"

START=$(date +%s)
TARGET="$BACKUP_DIR/wp-${DATE}.sql.gz"

# mariadb-dump → gzip
if sudo docker exec wordpress-db-1 
   mariadb-dump --single-transaction -u root -p"${DB_ROOT_PW}" wp 
   | gzip > "$TARGET"; then
    SIZE=$(du -h "$TARGET" | cut -f1)
    ELAPSED=$(( $(date +%s) - START ))
    echo "$(date '+%Y-%m-%d %H:%M') | [wp-backup] | OK | ${SIZE} | ${ELAPSED}s" >> "$LOG_FILE"
else
    echo "$(date '+%Y-%m-%d %H:%M') | [wp-backup] | FAIL-L2 | dump error" >> "$LOG_FILE"
    exit 1
fi

# Rotate older than 30 days
find "$BACKUP_DIR" -name "wp-*.sql.gz" -mtime +30 -delete

Permission: chmod +x. Crontab:

0 3 * * * /home/worker/scripts/wp-backup.sh

Automatically executed daily at 03:00. First backup verification:

ls -la "$BACKUP_DIR"
# wp-2026-05-27.sql.gz  20K

20KB represents an empty initial database. With 100 articles plus image metadata, the usual size ranges from 500KB to 5MB.

Why Store in Obsidian Vault?

The Obsidian Vault is already my note system = automatically synchronized to other PCs and phones (when using OneDrive or Syncthing). There’s no need for a separate backup medium. Even if the mini-PC dies, backup copies remain intact on my laptop and phone.


3. Redis Object Cache — Caching DB Queries

WordPress sends an average of 50 to 200 DB queries to display a page once. Out of these, 80% are repetitive (menus, options, settings).

The Redis Object Cache caches these repetitive queries in memory:

wp config set WP_REDIS_HOST redis --allow-root
wp config set WP_REDIS_PORT 6379 --allow-root
wp config set WP_REDIS_PREFIX byeolgorae: --allow-root
wp config set WP_CACHE true --raw --allow-root
wp plugin install redis-cache --activate --allow-root
wp redis enable --allow-root

Verification:

wp redis status --allow-root
# Status: Connected
# Client: PhpRedis (v6.x)

Experience: Page response times decrease from 300ms to 200ms (30% faster).


4. WP Super Cache — Page Caching

While Redis caches DB queries, WP Super Cache caches the finished HTML itself.

Visit Redis Only Redis + Super Cache
First visitor Execution of PHP + Redis cache miss → DB → response Execution of PHP + generation of static HTML
2nd visit onward Execution of PHP + Redis cache hit → response (~200ms) No PHP processing. Direct response with static file (~50ms)
The path of one visitor request through the two caches When a visitor request arrives, WP Super Cache first checks whether finished HTML exists. If it does, from the second visit onward the static HTML file is served directly without PHP (about 50ms). If not, this is a first visit, so PHP runs, and WordPress’s DB queries go to Redis Object Cache first. MariaDB is queried only on a cache miss. Along with the response, static HTML is generated and stored for the next visitor. Logged-in users do not receive the page cache. Visitor request WP Super Cache Finished HTML? Yes From 2nd visit on Serve the static HTML file directly No PHP · about 50ms No PHP runs WordPress · 1st visit query Redis Object Cache Repeats served from RAM cache miss MariaDB Queried only on a miss Response + static HTML generated The next visitor takes the upper path HTML stored Note: logged-in users don’t get the page cache (intended). Check fresh posts in an incognito window.
Figure 2. Where the two caches sit in the request flow. WP Super Cache handles finished HTML; Redis Object Cache absorbs repeated DB queries inside PHP.

After installation, activate via GUI:
– Settings → WP Super Cache → Easy tab
– Select “Caching On (Recommended)” radio button
– Update Status

Cannot be activated via wp-cli (command not registered). Requires a single manual click from my side.

⚠ Pitfall: Logged-in users (like myself) do not receive the page cache (this is intentional). After publishing, there might be confusion when I ask “Why can’t I see it?” Switching to incognito mode reveals the correct display.


5. EWWW Image Optimizer — Automatic Image Compression

Automatically converts uploaded images to WebP format + performs lossless compression.

Format Size of the same photo
JPEG (original) 800KB
WebP (EWWW) 250KB (-69%)
AVIF (EWWW paid) 150KB (-81%)

If left with the default settings after installation, it works fine. Automatically converts new image uploads. Bulk conversion of older images can be done via the Bulk Optimize menu.

Experience: Mobile page LCP (Largest Contentful Paint) improves from 2.5 seconds to 1.2 seconds.


6. Summary — One Setup, Zero Operations

Task Setup Time After
wp-backup.sh + cron 10 minutes Automates daily at 03:00
Redis Object Cache 3 minutes Permanent automation
WP Super Cache GUI activation 1 minute Permanent automation
EWWW Image Optimizer 1 minute Automatic with new image uploads

A total of 15 minutes once = automation of operations completed.


FAQ

Q. How to restore the backup?

gunzip -c wp-2026-05-30.sql.gz | sudo docker exec -i wordpress-db-1 mariadb -u root -p"${DB_ROOT_PW}" wp

One line. Real restoration is recommended to be rehearsed about once a quarter.

Q. Are images in wp-content/uploads also backed up?
This script only backs up the database. For images, just add one line: tar -czf uploads-$DATE.tar.gz wp-content/uploads/. If handling manually via the Obsidian Vault, no separate backup is necessary.

Q. Can I use WP backup plugins like UpdraftPlus?
It is possible. However, backing up within WP means that if WP fails, the backup also fails. A system-level cron is safer. UpdraftPlus can be installed as a backup but kept inactive.

Q. What if Redis runs out of memory?
For the Star Whale traffic scale (less than 10,000 monthly), it stays under 100MB. Even if memory fills, it automatically cleans up via LRU (Least Recently Used). No need to worry.

Q. Isn’t it redundant to use WP Super Cache with Cloudflare CDN?
Not redundant. The CDN serves static files (images, CSS), while Super Cache handles HTML. Keeping both active is the correct approach.


Next Preview

Part 5 — Star Whale Analytics: Visitor Statistics with Umami. Self-hosted instead of Google Analytics. No cookies + I own the data.


One-Line Summary

With a setup time of 15 minutes, backup, DB caching, page caching, and image compression run automatically daily. Operating time is zero, page speed increases by 30%, image sizes are reduced by 70%, and data remains secure.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *