Maintenance — Keep It Running
Cron — Linux's scheduler in 60 seconds
Cron lets you run any command on a schedule. Format:
minute hour day-of-month month day-of-week command
Examples:
0 3 * * *= 3:00 AM every day*/15 * * * *= every 15 minutes0 0 * * 0= midnight on Sundays
Build the backup script
sudo nano /usr/local/bin/backup-db.sh
Paste:
#!/usr/bin/env bash
set -euo pipefail
DEST=/home/erictey/backups/db
mkdir -p "$DEST"
DATE=$(date +%F)
FILE="$DEST/all-$DATE.sql.gz"
mysqldump --all-databases --single-transaction --routines --triggers --events \\
| gzip > "$FILE"
# Keep last 14 days only
find "$DEST" -name '*.sql.gz' -mtime +14 -delete
echo "Backed up to $FILE"
Make it executable:
sudo chmod 755 /usr/local/bin/backup-db.sh
sudo chown root:root /usr/local/bin/backup-db.sh
sudo /usr/local/bin/backup-db.sh
Should print "Backed up to /home/erictey/backups/db/all-2026-05-29.sql.gz" (today's date). Check the file exists:
ls -lh /home/erictey/backups/db/
Schedule it
sudo crontab -e
(If asked which editor, pick nano = 1.) Add at the bottom:
0 3 * * * /usr/local/bin/backup-db.sh >> /var/log/backup-db.log 2>&1
Save and exit. That runs at 3 AM every day, logs output to a file you can inspect later.
Backup project files too
Same pattern. Create /usr/local/bin/backup-files.sh:
#!/usr/bin/env bash
set -euo pipefail
DEST=/home/erictey/backups/files
mkdir -p "$DEST"
tar -czf "$DEST/server-$(date +%F).tar.gz" /home/erictey/server
find "$DEST" -name '*.tar.gz' -mtime +14 -delete
Cron it at 3:30 AM (slightly different time so the two jobs don't fight for disk):
30 3 * * * /usr/local/bin/backup-files.sh >> /var/log/backup-files.log 2>&1
Auto-install security updates
Single highest-leverage thing you can do for security:
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure unattended-upgrades
Say yes when prompted. Now security patches install every night while you sleep.
mDNS — find the server by name without hosts file edits
sudo apt install avahi-daemon -y
sudo systemctl enable --now avahi-daemon
Now Mac/iOS/Windows 10+/Linux devices on the LAN can reach the server at hostname.local with zero per-device config. Like AirDrop, but for network names.
Build: Health Check Dashboard
Goal: one page you can visit weekly to confirm everything's still happy.
- Create
/home/erictey/server/status.php - Paste:
<?php header('Content-Type: text/plain; charset=utf-8'); echo "=== SERVER STATUS ===\\n\\n"; echo "PHP version: " . PHP_VERSION . "\\n"; echo "Loaded php.ini: " . php_ini_loaded_file() . "\\n"; echo "Server software: " . $_SERVER['SERVER_SOFTWARE'] . "\\n"; echo "Timezone: " . date_default_timezone_get() . " (now: " . date('c') . ")\\n"; try { $pdo = new PDO('mysql:host=127.0.0.1', 'medtrack_user', 'YOUR_PW'); $row = $pdo->query("SELECT VERSION() v")->fetch(); echo "MariaDB version: " . $row['v'] . " ✓\\n"; } catch (Throwable $e) { echo "MariaDB: ✗ FAILED - " . $e->getMessage() . "\\n"; } $free = disk_free_space('/'); echo "Disk free (/): " . round($free / 1e9, 1) . " GB\\n"; echo "memory_limit: " . ini_get('memory_limit') . "\\n"; echo "Uptime: " . trim(file_get_contents('/proc/uptime')) . " s\\n"; // Backup freshness $last = glob('/home/erictey/backups/db/*.sql.gz'); if ($last) { $newest = max(array_map('filemtime', $last)); $age_h = round((time() - $newest) / 3600, 1); echo "Last DB backup: {$age_h}h ago\\n"; } else { echo "Last DB backup: NO BACKUPS FOUND ✗\\n"; } ?> - Sub in your real DB password
- Visit
http://192.168.0.19/status.php - You should see a clean status report. All systems good?
Stretch: protect this page with basic auth so only you can see it. Create /etc/apache2/.htpasswd with sudo htpasswd -c /etc/apache2/.htpasswd erictey, then add an .htaccess file in the same folder.
Stop and look at what you've built
- ✓ Lubuntu running on real hardware
- ✓ LAMP stack (Apache + MariaDB + PHP)
- ✓ Project served from your home folder
- ✓ SSH from Windows, VS Code editing files remotely
- ✓ Reachable from any device on the LAN
- ✓ Vhosts for clean hostnames
- ✓ HTTPS with green padlock
- ✓ Backups running on a schedule
- ✓ Security updates installing themselves
- ✓ A status page to monitor it all
That's a real server. Not a tutorial sandbox — the same kind of stack that powers a meaningful slice of the working internet.
Now stop installing things and start building. Move on to Part 2 and learn the PHP language itself — by the end, MedTrack will be a real app, not just a folder.