feat(devicebackup): UrBackup for the Windows laptops, Time Machine staging for the Macs
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m42s
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m42s
New devicebackup stack: UrBackup 2.5.x (pinned, watchtower off) in internet mode on :55415 so laptops back up on the LAN and over the tailnet; web UI only via Caddy + Authentik forward_auth (provider homelab-urbackup, pk 41). MacBooks (tm-hub, tm-wif) use Time Machine on the host smbd, which already owns :445. Shares are staged in /etc/samba/smb.conf.timemachine-pending and not yet applied; README has the apply command and client setup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1028bc3a74
commit
a55cfd2b35
5 files changed
+169
-5
No files matched your search
@@ -473,6 +473,18 @@ backup.ginnoir.com {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# UrBackup web UI. Clients talk to :55415 directly, not through Caddy.
|
||||||
|
urbackup.ginnoir.com {
|
||||||
|
import internal_only
|
||||||
|
route {
|
||||||
|
import authentik_outpost
|
||||||
|
handle {
|
||||||
|
import authentik_forward_auth
|
||||||
|
reverse_proxy urbackup:55414
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
router.ginnoir.com {
|
router.ginnoir.com {
|
||||||
import internal_only
|
import internal_only
|
||||||
reverse_proxy 192.168.1.1
|
reverse_proxy 192.168.1.1
|
||||||
|
|||||||
@@ -12,11 +12,6 @@
|
|||||||
<DT><A HREF="https://foundry2.ginnoir.com">foundry2</A>
|
<DT><A HREF="https://foundry2.ginnoir.com">foundry2</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
<DT><H3>TABLETOP TOOLS (public)</H3>
|
|
||||||
<DL><p>
|
|
||||||
<DT><A HREF="https://5etools.ginnoir.com">5etools</A>
|
|
||||||
</DL><p>
|
|
||||||
|
|
||||||
<DT><H3>FILE STORAGE — internal only (Nextcloud) (internal)</H3>
|
<DT><H3>FILE STORAGE — internal only (Nextcloud) (internal)</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
<DT><A HREF="https://files.ginnoir.com">files</A>
|
<DT><A HREF="https://files.ginnoir.com">files</A>
|
||||||
@@ -24,6 +19,7 @@
|
|||||||
|
|
||||||
<DT><H3>STATIC SITES (public)</H3>
|
<DT><H3>STATIC SITES (public)</H3>
|
||||||
<DL><p>
|
<DL><p>
|
||||||
|
<DT><A HREF="https://5etools.ginnoir.com">5etools</A>
|
||||||
<DT><A HREF="https://wa4.ginnoir.com">wa4</A>
|
<DT><A HREF="https://wa4.ginnoir.com">wa4</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
@@ -95,6 +91,7 @@
|
|||||||
<DT><A HREF="https://webui.ginnoir.com">webui [internal]</A>
|
<DT><A HREF="https://webui.ginnoir.com">webui [internal]</A>
|
||||||
<DT><A HREF="https://imgstudio.ginnoir.com">imgstudio [internal]</A>
|
<DT><A HREF="https://imgstudio.ginnoir.com">imgstudio [internal]</A>
|
||||||
<DT><A HREF="https://backup.ginnoir.com">backup</A>
|
<DT><A HREF="https://backup.ginnoir.com">backup</A>
|
||||||
|
<DT><A HREF="https://urbackup.ginnoir.com">urbackup [internal]</A>
|
||||||
<DT><A HREF="https://router.ginnoir.com">router [internal]</A>
|
<DT><A HREF="https://router.ginnoir.com">router [internal]</A>
|
||||||
</DL><p>
|
</DL><p>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
# devicebackup stack
|
||||||
|
|
||||||
|
Full backups of the household laptops onto valhalla.
|
||||||
|
|
||||||
|
| Device | Disk | Tool | Cap |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Windows laptop A | 1 TB | UrBackup image backups | shared 3.5 TB soft quota |
|
||||||
|
| Windows laptop B | 512 GB | UrBackup image backups | (same) |
|
||||||
|
| MacBook (hub) | 1 TB | Time Machine → `tm-hub` share | 1.5 TB |
|
||||||
|
| MacBook (wif) | 1 TB | Time Machine → `tm-wif` share | 1.5 TB |
|
||||||
|
|
||||||
|
Worst case (every disk full) that's ~6.5 TB on `storage1`. It had 16 TB free on 2026-10-01
|
||||||
|
(84% used); keep an eye on pool fill, since ZFS slows down past ~90%.
|
||||||
|
|
||||||
|
**storage1 has no redundancy.** Treat this as the *second* copy of each laptop, not the only one,
|
||||||
|
until the mirror rebuild is done.
|
||||||
|
|
||||||
|
## Windows: UrBackup
|
||||||
|
|
||||||
|
### Before first deploy (host)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo install -d -o ginnoir -g ginnoir /config/urbackup /storage1/labdata/urbackup
|
||||||
|
```
|
||||||
|
|
||||||
|
Register a new Portainer git stack → `stacks/devicebackup` (one-time), then push.
|
||||||
|
|
||||||
|
### Server settings (web UI → Settings)
|
||||||
|
|
||||||
|
- **General → Server:** backup storage path `/backups`.
|
||||||
|
- **General → Internet:** enable internet mode, server name `urbackup.ginnoir.com`, port `55415`;
|
||||||
|
tick **"Do image backups over internet"** and **"Do full file backups over internet"**.
|
||||||
|
- **General → Soft filesystem quota:** `3500G`.
|
||||||
|
- **Client defaults → Image backups:** incremental every 1 day, full every 30 days;
|
||||||
|
keep min 2 / max 4 full images, min 7 / max 30 incrementals. Volumes `ALL_NONUSB` (with ESP).
|
||||||
|
- **Client defaults → File backups:** off (images are browsable and mountable for single-file restores).
|
||||||
|
- Leave UrBackup with **no admin user**: auth is Authentik forward_auth at Caddy, and 55414 is not
|
||||||
|
published. Adding a UrBackup user just means logging in twice.
|
||||||
|
|
||||||
|
### Each Windows laptop
|
||||||
|
|
||||||
|
1. Web UI → **Add client → Internet/active client**, name it, and download the per-client installer
|
||||||
|
(it embeds the server address + auth key).
|
||||||
|
2. Run it on the laptop. The first full image takes a long time on Wi-Fi, so do it at home, plugged in.
|
||||||
|
3. **Make the restore USB:** download the UrBackup restore ISO and keep a stick around. A bare-metal
|
||||||
|
restore boots it, connects to the server on the LAN, and writes the image back.
|
||||||
|
4. BitLocker: images contain the *decrypted* volume. The data is protected only by valhalla's own security.
|
||||||
|
|
||||||
|
## macOS: Time Machine (host smbd)
|
||||||
|
|
||||||
|
Host `smbd` already serves `[storage1]` on :445, so Time Machine goes on the host Samba rather than
|
||||||
|
a container (Macs handle SMB on a non-standard port poorly). This config is **host-managed**, not
|
||||||
|
deployed from this repo. Keep this section in sync with `/etc/samba/smb.conf`.
|
||||||
|
|
||||||
|
Add to `[global]` (fruit has to be global, because macOS negotiates the AAPL extensions on the
|
||||||
|
first tree connect):
|
||||||
|
|
||||||
|
```ini
|
||||||
|
vfs objects = catia fruit streams_xattr
|
||||||
|
fruit:metadata = stream
|
||||||
|
fruit:model = MacSamba
|
||||||
|
fruit:posix_rename = yes
|
||||||
|
fruit:veto_appledouble = no
|
||||||
|
fruit:nfs_aces = no
|
||||||
|
fruit:wipe_intentionally_left_blank_rfork = yes
|
||||||
|
fruit:delete_empty_adfiles = yes
|
||||||
|
```
|
||||||
|
|
||||||
|
One share per Mac, so each Mac gets its own 1.5 TB cap:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[tm-hub]
|
||||||
|
path = /storage1/labdata/timemachine/hub
|
||||||
|
valid users = timemachine
|
||||||
|
read only = No
|
||||||
|
fruit:time machine = yes
|
||||||
|
fruit:time machine max size = 1500G
|
||||||
|
|
||||||
|
[tm-wif]
|
||||||
|
path = /storage1/labdata/timemachine/wif
|
||||||
|
valid users = timemachine
|
||||||
|
read only = No
|
||||||
|
fruit:time machine = yes
|
||||||
|
fruit:time machine max size = 1500G
|
||||||
|
```
|
||||||
|
|
||||||
|
Done on 2026-10-01: `timemachine` user + Samba password (password is in `stack.env`), and
|
||||||
|
`/storage1/labdata/timemachine/{hub,wif}` (owned by `timemachine`, mode 0700).
|
||||||
|
|
||||||
|
The full target config is **staged** at `/etc/samba/smb.conf.timemachine-pending`, already
|
||||||
|
`testparm`-validated. It is *not* live yet, because smbd re-reads `smb.conf` automatically
|
||||||
|
whenever the file changes. Apply it when nothing is mid-copy on `[storage1]`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak-$(date +%F) && sudo mv /etc/samba/smb.conf.timemachine-pending /etc/samba/smb.conf && sudo systemctl reload smb
|
||||||
|
```
|
||||||
|
|
||||||
|
Samba registers the shares with avahi (already running), so on the LAN they show up directly in
|
||||||
|
**System Settings → General → Time Machine → Add Backup Disk**. Pick the share, enter the
|
||||||
|
`timemachine` credentials, and **turn on "Encrypt backup"**. Away from home, Bonjour doesn't cross
|
||||||
|
Tailscale, and valhalla has no MagicDNS name (the tailnet reaches it via the subnet route), so
|
||||||
|
when re-adding remotely use the LAN IP:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tmutil setdestination -a "smb://timemachine@192.168.1.69/tm-hub"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verify
|
||||||
|
|
||||||
|
- [ ] Each Windows laptop: one full image completes, then **mount it in the UrBackup UI and open a file**.
|
||||||
|
- [ ] Each Mac: first backup completes, then **Enter Time Machine and restore one file**.
|
||||||
|
- [ ] Uptime Kuma: HTTP monitor on `https://urbackup.ginnoir.com`, TCP monitor on `valhalla:55415`.
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# devicebackup stack — full backups of the household laptops onto valhalla.
|
||||||
|
#
|
||||||
|
# Windows laptops → UrBackup (this stack): incremental disk images, bare-metal restore.
|
||||||
|
# MacBooks → Time Machine over the HOST smbd (not in compose — host already owns
|
||||||
|
# :445, see README.md for the smb.conf shares).
|
||||||
|
#
|
||||||
|
# Clients run in UrBackup "internet mode" against urbackup.ginnoir.com:55415, which resolves
|
||||||
|
# to valhalla on the LAN and over the tailnet, so laptops keep backing up away from home.
|
||||||
|
# The web UI (55414) is only reachable through Caddy + Authentik forward_auth.
|
||||||
|
#
|
||||||
|
# Not part of the Kopia → B2 offsite set (stacks/backup) — this is copy #2 of each laptop.
|
||||||
|
|
||||||
|
services:
|
||||||
|
urbackup:
|
||||||
|
container_name: urbackup
|
||||||
|
image: uroni/urbackup-server:2.5.x
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.centurylabs.watchtower.enable=false"
|
||||||
|
networks: [edge]
|
||||||
|
env_file:
|
||||||
|
- stack.env
|
||||||
|
volumes:
|
||||||
|
- /config/urbackup:/var/urbackup
|
||||||
|
- /storage1/labdata/urbackup:/backups
|
||||||
|
ports:
|
||||||
|
- "55415:55415" # internet-mode clients (LAN + tailnet)
|
||||||
|
|
||||||
|
networks:
|
||||||
|
edge:
|
||||||
|
name: edge
|
||||||
|
external: true
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# devicebackup stack — UrBackup server.
|
||||||
|
TZ=America/Chicago
|
||||||
|
|
||||||
|
# Run as ginnoir so /config/urbackup and /storage1/labdata/urbackup stay ginnoir-owned.
|
||||||
|
PUID=1000
|
||||||
|
PGID=1000
|
||||||
|
|
||||||
|
# Samba password for the host-managed Time Machine shares (tm-hub, tm-wif).
|
||||||
|
# Not read by the container; lives here so it is versioned with the stack (see README).
|
||||||
|
TIMEMACHINE_SMB_USER=timemachine
|
||||||
|
TIMEMACHINE_SMB_PASSWORD=Ey6gC0IL3rtm6nNL7oV3e08M
|
||||||
Reference in new issue
Block a user