Backups don’t need AI. They’re plain scripts the computer runs by itself, and AI only comes in when something goes wrong. I have three jobs, each covering something different.
Notes: every ten minutes, encrypted
All my notes are Markdown files in one folder, and that folder is a git repository. Every ten minutes a small script checks it: if anything changed, it commits and pushes to a private repository on GitHub. If an earlier push failed, it retries. Only one copy runs at a time.
The repository is encrypted with git-crypt: every file’s contents are pushed encrypted, except two settings files. Someone who saw the repository could see file names and commit messages, but couldn’t read the notes without the key.
While pushes keep working, the copy on GitHub is never more than a few minutes behind. If they stop, the machine check each morning notices the copy is old, and it shows up in my morning brief.
Code: every night
At 11:30 pm a second script goes through my projects: it commits what changed and pushes each project to its private repository on GitHub. Two rules never bend:
- Nothing is pushed until a secrets scan passes. Before any push it runs gitleaks to look for keys or passwords in the code. If it finds one, nothing goes up.
- It never force-pushes, so it can’t wipe existing work.
In some projects the agent working there commits its own work, so the script only pushes those and doesn’t commit on its behalf.
The family app’s files: every week
An app I built for the family has its own files, and every Sunday they’re copied to the server at home. The result shows on my start page. The app itself will get its own post.
How I know they ran
- Code: the nightly script writes a status file: whether it worked and when it finished. My morning brief shows a card if it failed or the last success is more than two days old.
- Notes: the morning machine check looks at when the last backup happened, and if it’s old, it shows up in the brief.
- The app’s files: on the start page.
A backup that never ran is a failure too; it just doesn’t announce itself.
How to set one up
This assumes Linux with systemd and a computer that stays on.
Encrypt your notes
Start with a new repository, and set up encryption before any note goes in. Install git-crypt, then:
mkdir ~/notes && cd ~/notes
git init
git-crypt init
git-crypt export-key ~/notes-backup.keyKeep the key somewhere safe outside the repository, like a password manager. Without it, the backup can’t be read. Then, still before adding any note, put this in a .gitattributes file so every file is encrypted except the settings files:
* filter=git-crypt diff=git-crypt
.gitattributes !filter !diff
.gitignore !filter !diffAdd your notes, run git-crypt status, and check every note shows as encrypted before the first push. File names and commit messages aren’t encrypted. An existing repository’s old history stays readable, so moving notes that are already in git needs a careful migration.
Back up your notes
My notes folder ~/notes is a git repository encrypted with git-crypt and linked to a private GitHub repository, and pushing works without a password. Write me a script called notes-backup that commits and pushes if anything changed, retries any earlier failed push, and never runs twice at once. Then create a systemd user service and timer that run it every ten minutes.
Then switch the timer on, and let your jobs run even when you’re not logged in:
systemctl --user daemon-reload
systemctl --user enable --now notes-backup.timer
loginctl enable-linger $USER
systemctl --user list-timersTest a restore once: clone the repository into another folder, go into it, run git-crypt unlock ~/notes-backup.key (or wherever you keep the key), and check your notes read correctly.
Back up your code
Write me a nightly script that goes through my projects in ~/Projects: commit what changed and push each project to its repository. Before any push, run gitleaks, and if it finds a secret, don't push. Never force-push. At the end, write a JSON status file with allOk, finishedAt, and which project failed and why.
Make it tell you
Add a line to your morning brief’s rules: read the status file, and show a card if allOk is false, finishedAt is more than two days old, or the file is missing.
What I learned
- Not everything needs AI. A plain script is cheaper and steadier; AI earns its place when something has to be read and judged.
- A backup that didn’t run is a failure. Check when the last success was, not only whether something failed.
- Scan for secrets before pushing, not after. Once it’s pushed, it’s out.
- An encrypted backup is useless without its key. Test a restore once, before you need it.
Tools
Next in the series: machine health and the exposure guard.