Initial commit: restic backup configuration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
4
.envrc
Executable file
4
.envrc
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then
|
||||||
|
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM="
|
||||||
|
fi
|
||||||
|
use flake
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.password
|
||||||
|
.direnv
|
||||||
67
backup.sh
Executable file
67
backup.sh
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
#export RESTIC_REPOSITORY="sftp:glen@thalassa.local:/Users/glen/backups/restic-starbak"
|
||||||
|
export RESTIC_REPOSITORY="sftp:glen@192.168.0.247:/Users/glen/backups/restic-starbak"
|
||||||
|
export RESTIC_PASSWORD_FILE="${SCRIPT_DIR}/.password"
|
||||||
|
|
||||||
|
EXCLUDE_FILE="${SCRIPT_DIR}/excludes.txt"
|
||||||
|
|
||||||
|
# Force macOS system ssh — the nix restic wrapper prepends nix openssh to PATH,
|
||||||
|
# which lacks macOS network entitlements and fails inside tmux
|
||||||
|
SFTP_OPTS=(-o "sftp.command=/usr/bin/ssh glen@192.168.0.247 -s sftp")
|
||||||
|
|
||||||
|
if [ ! -f "$RESTIC_PASSWORD_FILE" ]; then
|
||||||
|
echo "Error: Password file not found at $RESTIC_PASSWORD_FILE"
|
||||||
|
echo "Create it with: head -c 32 /dev/urandom | base64 > ${RESTIC_PASSWORD_FILE}"
|
||||||
|
echo "Then: chmod 600 ${RESTIC_PASSWORD_FILE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${1:-backup}" in
|
||||||
|
init)
|
||||||
|
restic "${SFTP_OPTS[@]}" init
|
||||||
|
;;
|
||||||
|
backup)
|
||||||
|
restic "${SFTP_OPTS[@]}" backup \
|
||||||
|
/Users/glen \
|
||||||
|
--exclude-file="$EXCLUDE_FILE" \
|
||||||
|
--exclude-caches \
|
||||||
|
--one-file-system \
|
||||||
|
--verbose
|
||||||
|
;;
|
||||||
|
snapshots)
|
||||||
|
restic "${SFTP_OPTS[@]}" snapshots
|
||||||
|
;;
|
||||||
|
prune)
|
||||||
|
restic "${SFTP_OPTS[@]}" forget \
|
||||||
|
--keep-hourly 24 \
|
||||||
|
--keep-daily 7 \
|
||||||
|
--keep-weekly 4 \
|
||||||
|
--keep-monthly 12 \
|
||||||
|
--keep-yearly 3 \
|
||||||
|
--prune
|
||||||
|
;;
|
||||||
|
check)
|
||||||
|
restic "${SFTP_OPTS[@]}" check
|
||||||
|
;;
|
||||||
|
stats)
|
||||||
|
# per-snapshot sizes; pass snapshot ID for a specific one
|
||||||
|
restic "${SFTP_OPTS[@]}" stats "${2:-latest}"
|
||||||
|
;;
|
||||||
|
diff)
|
||||||
|
# diff two snapshots: ./backup.sh diff <id1> <id2>
|
||||||
|
restic "${SFTP_OPTS[@]}" diff "${2:?snapshot1 ID required}" "${3:?snapshot2 ID required}"
|
||||||
|
;;
|
||||||
|
mount)
|
||||||
|
MOUNT_POINT="${2:-/tmp/restic-mount}"
|
||||||
|
mkdir -p "$MOUNT_POINT"
|
||||||
|
restic "${SFTP_OPTS[@]}" mount "$MOUNT_POINT"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {init|backup|snapshots|prune|check|stats [id]|diff <id1> <id2>|mount [path]}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
104
excludes.txt
Normal file
104
excludes.txt
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# ============================================
|
||||||
|
# Restic exclude list for macOS user data backup
|
||||||
|
# Mirrors Time Machine standard exclusions + extras
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
# --- macOS system/app caches ---
|
||||||
|
Library/Caches
|
||||||
|
Library/Logs
|
||||||
|
Library/Cookies
|
||||||
|
Library/HTTPStorages
|
||||||
|
Library/Saved Application State
|
||||||
|
Library/WebKit/MediaKeys
|
||||||
|
Library/Containers/*/Data/Library/Caches
|
||||||
|
Library/Containers/*/Data/Library/Logs
|
||||||
|
Library/Group Containers/*/Library/Caches
|
||||||
|
Library/Application Support
|
||||||
|
Library/Containers
|
||||||
|
|
||||||
|
# --- Spotlight & indexing ---
|
||||||
|
.Spotlight-V100
|
||||||
|
.fseventsd
|
||||||
|
|
||||||
|
# --- Trash ---
|
||||||
|
.Trash
|
||||||
|
|
||||||
|
# --- macOS metadata ---
|
||||||
|
.DS_Store
|
||||||
|
.TemporaryItems
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
|
||||||
|
# --- Nix store symlinks (reconstructable) ---
|
||||||
|
.nix-defexpr
|
||||||
|
.nix-profile
|
||||||
|
# Skip files that are nix store symlinks
|
||||||
|
.zshrc
|
||||||
|
.zshenv
|
||||||
|
.manpath
|
||||||
|
|
||||||
|
# --- Build artifacts & dependency caches ---
|
||||||
|
node_modules
|
||||||
|
.gradle
|
||||||
|
.ivy2
|
||||||
|
.m2
|
||||||
|
.sbt
|
||||||
|
.npm
|
||||||
|
.cache
|
||||||
|
target
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
.tox
|
||||||
|
.venv
|
||||||
|
venv
|
||||||
|
.data
|
||||||
|
|
||||||
|
# --- Go ---
|
||||||
|
go/pkg
|
||||||
|
|
||||||
|
# --- IDE/editor state ---
|
||||||
|
.vscode/extensions
|
||||||
|
.vscode-server
|
||||||
|
|
||||||
|
# --- Git large objects (restic deduplicates, but no point backing up pack files) ---
|
||||||
|
.git/objects/pack
|
||||||
|
|
||||||
|
# --- Large/reconstructable/synced ---
|
||||||
|
big-files
|
||||||
|
Seafile
|
||||||
|
cloud
|
||||||
|
Downloads
|
||||||
|
|
||||||
|
# --- Application-specific transient data ---
|
||||||
|
Library/Application Support/Google/Chrome/Default/Service Worker
|
||||||
|
Library/Application Support/Google/Chrome/Default/Code Cache
|
||||||
|
Library/Application Support/Google/Chrome/Default/GPUCache
|
||||||
|
Library/Application Support/Google/Chrome/Default/IndexedDB
|
||||||
|
Library/Application Support/Google/Chrome/ShaderCache
|
||||||
|
Library/Application Support/Slack/Service Worker
|
||||||
|
Library/Application Support/Slack/Code Cache
|
||||||
|
Library/Application Support/Slack/GPUCache
|
||||||
|
Library/Application Support/Discord/Code Cache
|
||||||
|
Library/Application Support/Discord/GPUCache
|
||||||
|
|
||||||
|
# --- Photos library (synced from iCloud, very large) ---
|
||||||
|
Library/Photos
|
||||||
|
|
||||||
|
# --- Mail downloads (re-downloadable) ---
|
||||||
|
Library/Mail/V*/MailData/Envelope Index*
|
||||||
|
|
||||||
|
# --- Swap/sleep/VM ---
|
||||||
|
.SleepImage
|
||||||
|
.swap*
|
||||||
|
|
||||||
|
# --- Claude Code ---
|
||||||
|
#.claude.json.backup
|
||||||
|
|
||||||
|
# --- SSH sockets ---
|
||||||
|
.ssh/sockets
|
||||||
|
|
||||||
|
# --- atuin (shell history sync, reconstructable) ---
|
||||||
|
#.atuin
|
||||||
|
|
||||||
|
# --- zsh compiled/session state ---
|
||||||
|
.zcompdump*
|
||||||
|
.zsh_sessions
|
||||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1778794387,
|
||||||
|
"narHash": "sha256-BL04pOS9453Awkeb9f90XBJXBSkWxN+vB7HIgnL0iMM=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "8a1b0127302ea51e05bf4ea5a291743fac442406",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
20
flake.nix
Normal file
20
flake.nix
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
description = "Restic backup for starbak -> thalassa.local";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs }:
|
||||||
|
let
|
||||||
|
system = "aarch64-darwin";
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.${system}.default = pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
pkgs.restic
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user