Skip to content

Commit 644f16a

Browse files
ams0claude
andcommitted
feat: Add Velero backup with local-volume-provider and SSHFS mount to Mac Mini
Velero backs up PVCs via Kopia to a hostPath that is SSHFS-mounted to feynman.rhino-butterfly.ts.net:/Volumes/Store/Borg/Velero. Daily (14d) and weekly (90d) schedules cover all app namespaces. - New sshfs Ansible role with systemd automount for resilient mounts - Velero HelmRelease with replicated/local-volume-provider plugin - Remove unused Velero HTTPRoute (no web UI) - Add velero to root Flux kustomization Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 931d050 commit 644f16a

File tree

10 files changed

+178
-28
lines changed

10 files changed

+178
-28
lines changed

gitops/kustomization.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,4 @@ resources:
1414
- gateways/gateway.yaml
1515
- local-path-provisioner/local-path-provisioner.yaml
1616
- argocd
17-
18-
# Add more resources here as you create them
19-
# - deployment.yaml
20-
# - service.yaml
21-
# - ingress.yaml
17+
- velero

gitops/velero/kustomization.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@ resources:
55
- namespace.yaml
66
- velero-helmrepo.yaml
77
- velero-helmrelease.yaml
8-
- velero-httproute.yaml

gitops/velero/velero-helmrelease.yaml

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,100 @@ spec:
2626
remediation:
2727
retries: 3
2828
values:
29-
29+
initContainers:
30+
- name: local-volume-provider
31+
image: replicated/local-volume-provider:v0.6.7
32+
imagePullPolicy: IfNotPresent
33+
volumeMounts:
34+
- mountPath: /target
35+
name: plugins
36+
37+
credentials:
38+
useSecret: false
39+
40+
configuration:
41+
backupStorageLocation:
42+
- name: feynman
43+
provider: replicated.com/hostpath
44+
bucket: velero-backups
45+
default: true
46+
accessMode: ReadWrite
47+
config:
48+
path: /mnt/feynman-velero
49+
resticRepoPrefix: /var/velero-local-volume-provider/velero-backups/restic
50+
51+
volumeSnapshotLocation: []
52+
defaultVolumesToFsBackup: true
53+
uploaderType: kopia
54+
55+
snapshotsEnabled: false
56+
deployNodeAgent: true
57+
58+
nodeAgent:
59+
resources:
60+
requests:
61+
cpu: 100m
62+
memory: 256Mi
63+
limits:
64+
memory: 1Gi
65+
66+
resources:
67+
requests:
68+
cpu: 100m
69+
memory: 128Mi
70+
limits:
71+
memory: 512Mi
72+
73+
# Mount the SSHFS hostPath into the Velero pod
74+
extraVolumes:
75+
- name: feynman-velero
76+
hostPath:
77+
path: /mnt/feynman-velero
78+
type: Directory
79+
80+
extraVolumeMounts:
81+
- name: feynman-velero
82+
mountPath: /mnt/feynman-velero
83+
84+
schedules:
85+
daily-all-apps:
86+
disabled: false
87+
schedule: "0 2 * * *"
88+
useOwnerReferencesInBackup: false
89+
template:
90+
ttl: "336h"
91+
storageLocation: feynman
92+
includedNamespaces:
93+
- n8n
94+
- forgejo
95+
- minecraft
96+
- keycloak
97+
- actual
98+
- alarik
99+
- uptime-kuma
100+
- outline
101+
- waha
102+
- rustfs
103+
defaultVolumesToFsBackup: true
104+
snapshotVolumes: false
105+
106+
weekly-disaster-recovery:
107+
disabled: false
108+
schedule: "0 3 * * 0"
109+
useOwnerReferencesInBackup: false
110+
template:
111+
ttl: "2160h"
112+
storageLocation: feynman
113+
includedNamespaces:
114+
- n8n
115+
- forgejo
116+
- minecraft
117+
- keycloak
118+
- actual
119+
- alarik
120+
- uptime-kuma
121+
- outline
122+
- waha
123+
- rustfs
124+
defaultVolumesToFsBackup: true
125+
snapshotVolumes: false

gitops/velero/velero-httproute.yaml

Lines changed: 0 additions & 21 deletions
This file was deleted.

roles/sshfs/defaults/main.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
sshfs_mounts:
3+
- name: feynman-velero
4+
remote_path: "/Volumes/Store/Borg/Velero"
5+
remote_user: feynam
6+
remote_host: feynman.rhino-butterfly.ts.net
7+
local_path: /mnt/feynman-velero
8+
ssh_key: /home/ubuntu/.ssh/nas
9+
uid: "1001"
10+
gid: "1001"

roles/sshfs/handlers/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
- name: reload systemd
3+
systemd:
4+
daemon_reload: yes

roles/sshfs/tasks/main.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
- name: Install sshfs
3+
apt:
4+
name: sshfs
5+
state: present
6+
update_cache: yes
7+
8+
- name: Create mount points
9+
file:
10+
path: "{{ item.local_path }}"
11+
state: directory
12+
mode: "0755"
13+
loop: "{{ sshfs_mounts }}"
14+
15+
- name: Deploy systemd mount units
16+
template:
17+
src: sshfs.mount.j2
18+
dest: "/etc/systemd/system/{{ item.local_path | regex_replace('^/', '') | regex_replace('/', '-') }}.mount"
19+
mode: "0644"
20+
loop: "{{ sshfs_mounts }}"
21+
notify: reload systemd
22+
23+
- name: Deploy systemd automount units
24+
template:
25+
src: sshfs.automount.j2
26+
dest: "/etc/systemd/system/{{ item.local_path | regex_replace('^/', '') | regex_replace('/', '-') }}.automount"
27+
mode: "0644"
28+
loop: "{{ sshfs_mounts }}"
29+
notify: reload systemd
30+
31+
- name: Flush handlers
32+
meta: flush_handlers
33+
34+
- name: Enable and start automount units
35+
systemd:
36+
name: "{{ item.local_path | regex_replace('^/', '') | regex_replace('/', '-') }}.automount"
37+
enabled: yes
38+
state: started
39+
loop: "{{ sshfs_mounts }}"
40+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[Unit]
2+
Description=Automount SSHFS {{ item.local_path }}
3+
After=network-online.target tailscaled.service
4+
Wants=network-online.target
5+
6+
[Automount]
7+
Where={{ item.local_path }}
8+
TimeoutIdleSec=0
9+
10+
[Install]
11+
WantedBy=multi-user.target
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[Unit]
2+
Description=SSHFS mount {{ item.remote_user }}@{{ item.remote_host }}:{{ item.remote_path }}
3+
After=network-online.target tailscaled.service
4+
Wants=network-online.target
5+
6+
[Mount]
7+
What={{ item.remote_user }}@{{ item.remote_host }}:{{ item.remote_path }}
8+
Where={{ item.local_path }}
9+
Type=fuse.sshfs
10+
Options=reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,allow_other,IdentityFile={{ item.ssh_key }},uid={{ item.uid }},gid={{ item.gid }},StrictHostKeyChecking=accept-new,_netdev
11+
12+
[Install]
13+
WantedBy=multi-user.target

site.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
tags: [traefik, ingress]
2020
- role: tailscale
2121
tags: [tailscale]
22+
- role: sshfs
23+
tags: [sshfs, backup]
2224
- role: borg
2325
tags: [borg, backup]
2426
- role: datadog

0 commit comments

Comments
 (0)