The Problem
I tried managing my system with dotfiles. It was a disaster.
I use Arch BTW (well, Arch based ) which means I get my system rekt more times than I care to admit (although it's getting less frequent.). So I needed a simple solution to get back on the horse after the OS inevitably craps itself.
The problem: I spent more time configuring git repos, symlink scripts, and installation workflows than actually using my computer. Every tweak meant a commit, a push, documentation. When I needed to restore? Half the paths were wrong, dependencies were missing, and I'd spend hours debugging why my carefully crafted setup didn't work on a fresh install.
Git is brilliant for code. For backing up config files on a personal computer? Overkill.
I also care about privacy. I don't want my personal files sitting on GitHub (owned by Microsoft, no thank you). But I also don't want to need a cryptography degree just to get encrypted backup working. I needed something simple that actually worked.
Enter Mega.io: encrypted storage, automatic versioning, syncs a folder. Done. No git commands, no commit messages, no Microsoft.
The Reality Check
I failed with dotfiles because I over-engineered it.
Past me got caught in the optimization rabbit hole: perfect directory structure, perfect git workflow, perfect configuration management. I was SO excited when I switched to Linux in May 2024. I wanted the FULL experience.
You know what? That wore off after a few months. I just want stuff to work and not having a second job maintaining my operating system.
This time I made a different choice: cron jobs + bash scripts + Mega sync. That's it. No frameworks, no abstractions, no clever architectures. Just scripts that run on schedule and back up what matters.
The Solution
Here's what I built.
File Structure
/Sync/
├── scripts/backup/
│ ├── backup_typingmind_memory.sh
│ ├── backup_brave_config.sh
│ ├── backup_crontab.sh
│ ├── setup_scripts_after_reinstall.sh
│ ├── backloggd-archive/
│ │ └── backloggd-backup.sh
│ └── crontab-archive/
│ └── crontab
├── logs/
│ └── crontab_logs.log
└── README.md
The /Sync/ folder syncs to Mega.io automatically. Everything in it is encrypted and versioned. If my computer dies, I install Mega sync on a new machine, download this folder, and I'm 90% restored.
The backup_XXXX.sh files are doing the heavy lifting to backup my most important tools:
- TypingMind is a frontend for AI interaction, and it has a "memory" function that helps personalize and contextualize stuff a LOT. I love it. (It's also privacy friendly, as this is just a plain .json file living on my computer)
- Brave Config: I use Brave browser and I love it. I just simply rsync everything from the ~/.config/BraveSoftware/Brave-Browser folder off site. I find this convenient, as all my history, saved stuff, etc. are just there. BuT ThEy CaN StEaL YoUr CoOkiEs AnD HaCk YoUr BanKaCcoUnT. No Karen, they are encrypted at rest.
- Crontab: well, my Crontabs that run everything on schedule.
- Backloggd Archive: I log my gaming habits on backloggd.com and I wrote a backup solution for that, so that I can actually own my own data.s You can see the solution here
In the future I'll add more backups (just the most important, like my KeyD config to remap homerow mods).
The Backup Scripts
Each backup script follows the same pattern. Here's the template I use:
#!/bin/bash
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
SOURCE="/path/to/source"
DEST="/path/to/destination"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting backup..."
# Create destination if needed
mkdir -p "$DEST" || {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Failed to create destination"
exit 1
}
# Do the backup
cp "$SOURCE" "$DEST/" || {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Copy failed"
exit 1
}
# Verify
if [ -f "$DEST/$(basename $SOURCE)" ]; then
SIZE=$(stat -c%s "$DEST/$(basename $SOURCE)" 2>/dev/null)
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ Successfully backed up ($SIZE bytes)"
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Backup verification failed"
exit 1
fi
Simple. Logs timestamps and errors. Verifies the copy worked. No dependencies, no external tools, just bash and coreutils.
I have four backup scripts running daily:
- 20:00 - TypingMind memory backup
- 20:05 - Backloggd archive backup
- 20:10 - Brave browser config backup
- 20:15 - Crontab backup
All output goes to /Sync/logs/crontab_logs.log. Every Monday at 20:04, that log file gets cleared (simple log rotation).
The Crontab
0 20 * * * /home/user/Sync/scripts/backup/backup_typingmind_memory.sh >> /home/user/Sync/logs/crontab_logs.log 2>&1
5 20 * * * /home/user/Sync/scripts/backup/backloggd-archive/backloggd-backup.sh >> /home/user/Sync/logs/crontab_logs.log 2>&1
10 20 * * * /home/user/Sync/scripts/backup/backup_brave_config.sh >> /home/user/Sync/logs/crontab_logs.log 2>&1
15 20 * * * /home/user/Sync/scripts/backup/backup_crontab.sh >> /home/user/Sync/logs/crontab_logs.log 2>&1
# log rotate weekly, every monday 20:04
4 20 * * 1 echo "" > /home/user/Sync/logs/crontab_logs.log
The crontab backup script is crucial: it backs up the crontab itself daily to /Sync/scripts/backup/crontab-archive/crontab. One file, overwrites itself every night. When I restore on a new machine, I just run crontab /path/to/crontab and all my scheduled jobs come back.
The Setup Script
This is the key to making restoration painless. When Mega syncs my files down on a new machine, all file permissions reset to defaults. Scripts that were executable become non-executable. Directories that need specific permissions get default 755.
Here's the setup script that fixes everything after a system reinstall:
#!/bin/bash
# Master setup orchestration script for post-reinstall recovery
set -e # Exit on any error
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting post-reinstall setup..."
# Task 1: Fix file permissions
setup_permissions() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Setting up file permissions..."
chmod 700 /home/user/Sync/logs
chmod 555 /home/user/Sync/scripts/backup/*.sh
chmod 640 /home/user/Sync/logs/crontab_logs.log
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ Permissions set"
}
# Task 2: Restore crontab
setup_crontab() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Restoring crontab..."
CRONTAB_FILE="/home/user/Sync/scripts/backup/crontab-archive/crontab"
if [ ! -f "$CRONTAB_FILE" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Crontab backup not found"
return 1
fi
crontab "$CRONTAB_FILE" || {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Failed to restore crontab"
return 1
}
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ Crontab restored"
}
# Execute tasks
setup_permissions
setup_crontab
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ Post-reinstall setup complete"
Run this once after syncing from Mega, and everything's configured. The structure is expandable - if I add new setup tasks later, I just add another function and call it.
Why Permissions Matter
chmod 700 on the logs directory means only I can read/write/execute there. Cron can write to the log file because cron runs as my user.
chmod 555 on the scripts means they're executable but not writable. This prevents accidental modification. If I want to edit a script, I have to deliberately chmod +w it first, which makes me think twice.
chmod 640 on the log file means I can read/write, my group can read, others get nothing.
These permissions survive because they're set by the setup script after restore. Mega sync doesn't preserve permissions, but the setup script does.
The Protocol
Adding a new backup is straightforward:
- Write the script in
/Sync/scripts/backup/ - Make it executable:
chmod 755 script_name.sh - Test it manually: Run it, check the output, verify the backup
- Add to crontab:
crontab -e, add the line with your time slot (keep them 5 minutes apart) - Test the setup script: Run it, verify your script gets locked to
555 - Update the README: Document what your script does
That's it. The automated backup system handles the rest.
Why This Works
Simple systems survive. Complex systems get abandoned.
When my computer dies (not if, when), I can:
- Install Mega sync on a new machine
- Download my Sync folder
- Run one script:
./setup_scripts_after_reinstall.sh - Wait for 20:00 and check the logs
No git clone, no symlink scripts, no debugging broken paths, no Microsoft. Just working backups that restore themselves.
This isn't the cleverest solution. It's not the most elegant. But it's portable, it's encrypted, and I can explain the entire system in one README file.
That's all I need.
