Compare commits
15
Commits
e2dbd9620a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33bd2dfeed | ||
|
|
d3833df125 | ||
|
|
97b1fa7dd1 | ||
|
|
25c58446e9 | ||
|
|
d99e4b1e52 | ||
|
|
9ef4b9ea8b | ||
|
|
76d2d806a9 | ||
|
|
d4a4139a0c | ||
|
|
6149daa549 | ||
|
|
ee6bd1a243 | ||
|
|
8e3d295e8f | ||
|
|
d07497e061 | ||
|
|
1efbee942d | ||
|
|
9915b7a062 | ||
|
|
fbc4ee8ab9 |
@@ -1,5 +1,5 @@
|
||||
$TTL 3600
|
||||
@ IN SOA dns106.ovh.net. tech.ovh.net. (2080297022 86400 3600 3600000 300)
|
||||
@ IN SOA dns106.ovh.net. tech.ovh.net. (2089201818 86400 3600 3600000 300)
|
||||
IN NS dns106.ovh.net.
|
||||
IN NS ns106.ovh.net.
|
||||
IN MX 100 mx3.mail.ovh.net.
|
||||
@@ -36,7 +36,7 @@ ftp IN CNAME delmar.bzh.
|
||||
gen IN A 176.188.240.123
|
||||
git IN A 176.188.240.123
|
||||
gotify IN A 176.188.240.123
|
||||
hdlp IN A 176.188.240.123
|
||||
hmr IN A 176.188.240.123
|
||||
home-assistant IN A 176.188.240.123
|
||||
homepage IN A 176.188.240.123
|
||||
imgs IN A 176.188.240.123
|
||||
@@ -45,13 +45,14 @@ it IN A 176.188.240.123
|
||||
jellyfin IN A 176.188.240.123
|
||||
jellyseerr IN A 176.188.240.123
|
||||
kontadenn IN A 176.188.240.123
|
||||
lghn IN A 176.188.240.123
|
||||
lnk IN A 176.188.240.123
|
||||
lud IN A 176.188.240.123
|
||||
minio IN A 176.188.240.123
|
||||
mmgr IN A 176.188.240.123
|
||||
mmm IN A 176.188.240.123
|
||||
nds IN A 176.188.240.123
|
||||
nsns IN A 176.188.240.123
|
||||
oec IN A 176.188.240.123
|
||||
octoprint IN A 176.188.240.123
|
||||
ovhemp1116203-selector1._domainkey 60 IN CNAME ovhemp1116203-selector1._domainkey.274927.cq.dkim.mail.ovh.net.
|
||||
ovhemp1116203-selector2._domainkey 60 IN CNAME ovhemp1116203-selector2._domainkey.274928.az.dkim.mail.ovh.net.
|
||||
@@ -64,8 +65,10 @@ send IN A 176.188.240.123
|
||||
shop IN A 176.188.240.123
|
||||
smk IN A 176.188.240.123
|
||||
stream IN A 176.188.240.123
|
||||
swpt IN A 176.188.240.123
|
||||
tournoi IN A 176.188.240.123
|
||||
tpml IN A 176.188.240.123
|
||||
trfk IN A 176.188.240.123
|
||||
trek IN A 176.188.240.123
|
||||
trmx IN A 176.188.240.123
|
||||
twip IN A 176.188.240.123
|
||||
ugo IN A 176.188.240.123
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
A practical tutorial for people who moved to a ZimaBoard for the faster CPU and extra RAM, but want to keep using their existing Synology as a rock-solid backup target.
|
||||
|
||||
Disclaimer: this is a setup that works well for me. I take no responsibility for your data or hardware — test on your own gear, verify the results yourself, and be very careful with any command that writes to a disk.
|
||||
|
||||
The idea
|
||||
Your ZimaBoard is now the workhorse — apps, containers, everything runs there. Your Synology is perfect for what it’s genuinely great at: reliable, cheap, roomy storage you write to and rarely read. This tutorial wires the two together so the ZimaBoard pushes versioned, space-efficient backups to the Synology every night, automatically.
|
||||
|
||||
What you get:
|
||||
|
||||
Dated snapshots — one folder per run (e.g. 2026-08-06_000006), each a complete browsable copy of your data at that moment.
|
||||
|
||||
Almost no extra space per snapshot — unchanged files are hardlinked, so keeping 14 daily snapshots costs roughly one copy + the daily changes, not 14 full copies. (In practice: one snapshot looks like 517 GB, but 14 of them plus the live mirror total just 542 GB on disk.)
|
||||
|
||||
Only changed data crosses the network each night — quick after the first run.
|
||||
|
||||
A locked-down backup key that can’t get a shell or touch anything outside the backup folder.
|
||||
|
||||
How it works (two steps, and why)
|
||||
Rather than one big rsync, the nightly job does two things:
|
||||
|
||||
Snapshot — runs on the Synology itself: copy the previous backup into a new dated folder with cp -al (a hardlink copy). Done locally this is near-instant.
|
||||
|
||||
Mirror — runs over SSH from the ZimaBoard: a plain rsync into a single CURRENT/ folder.
|
||||
|
||||
Snapshot first, mirror second — that way, if a mirror is ever interrupted, the previous night’s snapshot is already complete and safe.
|
||||
|
||||
The Synology ends up looking like:
|
||||
|
||||
/volume2/Backups/
|
||||
├── CURRENT/ ← the live mirror (updated in place each night)
|
||||
├── 2026-08-05_000006/ ← dated hardlinked snapshot
|
||||
├── 2026-08-06_000006/ ← dated hardlinked snapshot
|
||||
└── ... ← up to however many you keep
|
||||
|
||||
Restore from a dated snapshot, never from CURRENT — CURRENT is the live mirror and could be mid-update.
|
||||
|
||||
Why the snapshot runs on the Synology, not over a mounted share: cp -al creates one hardlink per file. Run locally on the Synology, hardlinking a large tree takes a couple of minutes. Run across an SMB/network mount, each hardlink becomes a separate network round-trip — for a large file count that turns minutes into many hours. So we trigger the snapshot on the Synology. This one detail makes or breaks the whole thing.
|
||||
|
||||
Step 1 — Turn on rsync-over-SSH on the Synology
|
||||
In DSM:
|
||||
|
||||
Control Panel → File Services → rsync → enable the rsync service. Note the SSH encryption port shown (often non-standard). Your backups use this port.
|
||||
|
||||
Leave the “rsync account” option off (that’s an unencrypted mode you don’t need).
|
||||
|
||||
Make sure your DSM user is in the administrators group (Control Panel → User & Group) — DSM only allows admin users to SSH in by default.
|
||||
|
||||
Enable user home service (Control Panel → User & Group → Advanced), so your user has a home directory with a ~/.ssh folder.
|
||||
|
||||
DSM’s SSH is strict about a couple of things:
|
||||
|
||||
~/.ssh must be 700 and ~/.ssh/authorized_keys must be 600, or DSM quietly ignores your key and falls back to password auth.
|
||||
|
||||
If rapid failed attempts get your source blocked, clear it under Control Panel → Security → Account (Auto Block).
|
||||
|
||||
Step 2 — Create a key and restrict it with rrsync
|
||||
On the ZimaBoard, generate a key with no passphrase (an automated job can’t type one). Put it somewhere that survives reboots — on ZimaOS, keep it on your data pool, e.g. under /media/YOURPOOL/scripts/.ssh/:
|
||||
|
||||
ssh-keygen -t ed25519 -f /media/YOURPOOL/scripts/.ssh/synology_backup -N ""
|
||||
|
||||
rrsync is the official wrapper that confines a key to rsync-only, in one folder. Fetch it into your DSM user’s home (over SSH to the Synology):
|
||||
|
||||
mkdir -p ~/bin
|
||||
curl -o ~/bin/rrsync https://raw.githubusercontent.com/RsyncProject/rsync/master/support/rrsync
|
||||
chmod +x ~/bin/rrsync
|
||||
|
||||
(head -1 ~/bin/rrsync tells you if it wants python3 or perl — DSM has both.)
|
||||
|
||||
Install the public key on the Synology with a forced command, so this key can only run rsync into your backup folder — no shell, no other paths:
|
||||
|
||||
# on the Synology, append (>> not >) to ~/.ssh/authorized_keys:
|
||||
cat >> ~/.ssh/authorized_keys <<'EOF'
|
||||
command="/var/services/homes/YOURUSER/bin/rrsync '/volume2/Backups'",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAA...your_public_key... zimaboard
|
||||
EOF
|
||||
chmod 700 ~/.ssh
|
||||
chmod 600 ~/.ssh/authorized_keys
|
||||
|
||||
Use plain rrsync '...', not -wo — write-only mode blocks reading the destination, which the snapshot approach and any restore need.
|
||||
|
||||
Test: an rsync of a small file should work; a plain ssh with this key should not give you a shell. That refusal is the lockdown doing its job.
|
||||
|
||||
Step 3 — The snapshot script (lives on the Synology)
|
||||
Put this on the Synology as ~/bin/snapshot.sh (adjust path and retention):
|
||||
|
||||
#!/bin/sh
|
||||
BACKUP_ROOT="/volume2/Backups"
|
||||
RETENTION=14
|
||||
TS=$(date +%Y-%m-%d_%H%M%S)
|
||||
cd "$BACKUP_ROOT" || exit 1
|
||||
[ -d CURRENT ] || { echo "No CURRENT yet, skipping"; exit 0; }
|
||||
echo "Snapshotting CURRENT -> $TS"
|
||||
mkdir -p "$TS"
|
||||
cp -al CURRENT/. "$TS/" || { rm -rf "$TS"; echo "cp -al failed"; exit 1; }
|
||||
TOTAL=$(ls -1d [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_* 2>/dev/null | wc -l)
|
||||
if [ "$TOTAL" -gt "$RETENTION" ]; then
|
||||
ls -1d [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_* | sort | head -n $((TOTAL-RETENTION)) \
|
||||
| while read -r old; do echo "Pruning $old"; rm -rf "$old"; done
|
||||
fi
|
||||
echo "Done: $TS"
|
||||
|
||||
chmod +x ~/bin/snapshot.sh and test it once by hand — it should finish in a couple of minutes and leave a dated folder.
|
||||
|
||||
Trigger it remotely with a second restricted key, so the nightly job can run it without a shell. Generate a second key on the ZimaBoard (synology_snapshot), and install its public key on the Synology forced to run only this script:
|
||||
|
||||
command="/var/services/homes/YOURUSER/bin/snapshot.sh",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAA...second_public_key... zimaboard
|
||||
|
||||
Now SSHing in with that key just runs the snapshot and disconnects.
|
||||
|
||||
Step 4 — The nightly backup script (on the ZimaBoard)
|
||||
#!/bin/sh
|
||||
SSH="ssh -p PORT -o StrictHostKeyChecking=accept-new"
|
||||
SNAPKEY=/media/YOURPOOL/scripts/.ssh/synology_snapshot
|
||||
MIRRORKEY=/media/YOURPOOL/scripts/.ssh/synology_backup
|
||||
USER_HOST="youruser@your.synology.ip"
|
||||
|
||||
# 1. Snapshot CURRENT server-side (fast, local cp -al)
|
||||
$SSH -i "$SNAPKEY" "$USER_HOST" || { echo "snapshot failed"; exit 1; }
|
||||
|
||||
# 2. Mirror your data -> CURRENT
|
||||
rsync -aH --delete --stats \
|
||||
-e "$SSH -i $MIRRORKEY" \
|
||||
/media/YOURPOOL/ "$USER_HOST":/CURRENT/
|
||||
|
||||
Adjust the pool path, port, and add any excludes you need (see the traps below).
|
||||
|
||||
Scheduling on ZimaOS: ZimaOS clears the system crontab on reboot, so don’t rely on plain cron. Run the schedule from a small Docker container instead (e.g. the lightweight Ofelia scheduler, deployed as a Portainer stack) — Docker state lives on your pool and survives reboots, so the schedule sticks. Point one Ofelia job at your backup script on your chosen time (e.g. daily at 00:00).
|
||||
|
||||
Two traps worth knowing before your first run
|
||||
1. rsync include/exclude order is first-match-wins. If you exclude a big directory but want to keep a subfolder of it, the --include for that subfolder must come before the broad --exclude, or it never takes effect and you silently lose that data. Correct order:
|
||||
|
||||
--include='/somedir/'
|
||||
--include='/somedir/keepthis/***'
|
||||
--exclude='/somedir/**'
|
||||
|
||||
2. Some objects can’t be rsynced, and that’s normal. Live special files (block devices, sockets, certain container-runtime internals under Docker’s overlay2) make rsync return exit 23 (“some files not transferred”) — the real files still went across fine. If you back up your whole pool, exclude Docker’s runtime layers (keep docker/volumes, skip docker/overlay2 and friends), plus the SMB recycle bin (.trash) and @eaDir metadata. Treat exit codes 23 and 24 (files vanished mid-copy — normal on a live system) as OK in your script; anything else is a real failure.
|
||||
|
||||
Verify it — the important part
|
||||
Check hardlinks are real (snapshots share storage instead of duplicating). On the Synology:
|
||||
|
||||
find "/volume2/Backups/<a-dated-snapshot>/<some/known/file/path>" -type f -printf '%n %p\n' | head
|
||||
|
||||
Link count 2 or more = shared with CURRENT, working correctly. 1 = something’s full-copying.
|
||||
|
||||
Check the real total size — the decisive space test. On the Synology:
|
||||
|
||||
du -sh "/volume2/Backups"
|
||||
|
||||
du counts hardlinked files only once, so CURRENT + all snapshots together should total roughly one copy plus accumulated changes — not N copies. (Example: 14 snapshots + mirror = 542 GB, versus 517 GB for a single snapshot. The 25 GB difference is two weeks of real changed data.) Note: File Station → Properties on one snapshot shows the full ~517 GB because it counts each hardlink as a full file — that number is misleading. du -sh on the whole Backups folder is the true figure.
|
||||
|
||||
Check the data you expect is actually there:
|
||||
|
||||
ls "/volume2/Backups/CURRENT/"
|
||||
ls "/volume2/Backups/CURRENT/<a/subfolder/you/care/about>"
|
||||
|
||||
Restoring
|
||||
One file: browse the right dated snapshot on the Synology (File Station or SSH) and copy it out — plain hardlinked folders, no special tooling.
|
||||
|
||||
Full restore: rsync a dated snapshot back to the ZimaBoard using your normal Synology login (the restricted keys are for pushing):
|
||||
|
||||
rsync -aH --info=progress2 -e "ssh -p PORT" \ "youruser@synology:/volume2/Backups/2026-MM-DD_HHMMSS/" /media/YOURPOOL/
|
||||
|
||||
Fix ownership afterward if an app expects specific file owners (databases, web apps, etc.).
|
||||
|
||||
Getting the most out of the Synology as a target
|
||||
Throughput will be modest, and that’s expected. A single rsync stream over gigabit, with lots of small files, runs well under line speed because per-file overhead dominates. A link-aggregation bond doesn’t speed up a single stream. The first full run takes a while; every run after is fast because only changes move.
|
||||
|
||||
Keep the versioning on the Synology (Step 3). It’s the difference between a 2-minute snapshot and an hours-long one.
|
||||
|
||||
If a run ever fails with “another instance is already accessing this directory,” a killed transfer left a process running on the Synology holding the lock. SSH in, ps aux | grep rsync, and kill the leftover rrsync/rsync --server PIDs — but not the SynoRsync … --daemon one (that’s DSM’s own service).
|
||||
|
||||
Expect a “login at an unusual time” notice if you back up at night — that’s DSM (via Active Insight) noticing your own nightly login. Either widen the “usual” window in Active Insight or accept the notice; don’t disable login alerts entirely.
|
||||
|
||||
Keep the disks healthy (SMART checks, periodic scrubs). This is where your safety net lives.
|
||||
|
||||
One habit to keep
|
||||
Verify on disk. Exit codes and “done” messages don’t prove your data is there. Check the destination contents, the link counts, and the real du size yourself now and then. It takes a minute and it’s the difference between hoping you have a backup and knowing you do.
|
||||
Binary file not shown.
+2
-1
@@ -67,7 +67,8 @@ UUID=B23E-A140 /boot/efi vfat umask=0077
|
||||
# swap was on /dev/mmcblk0p3 during installation
|
||||
UUID=69691db2-1213-4f0b-8797-a246e6924c4a none swap sw 0 0
|
||||
# ssd
|
||||
UUID=6702c3b0-eb03-4c1f-9ddc-56f4f7736222 /mnt/ssd ext4 defaults 0 0
|
||||
# UUID=6702c3b0-eb03-4c1f-9ddc-56f4f7736222 /mnt/tmp ext4 defaults 0 0
|
||||
UUID=bac562df-e5ca-4b1c-acde-d6c541a89ddb /mnt/ssd ext4 defaults 0 0
|
||||
/mnt/ssd/var /var none bind
|
||||
/mnt/ssd/tmp /tmp none bind
|
||||
/mnt/ssd/home /home none bind
|
||||
|
||||
+12
-7
@@ -31,6 +31,9 @@ ff02::3 ip6-allhosts
|
||||
192.168.1.19 pearl
|
||||
192.168.1.20 karen
|
||||
|
||||
# turinpi
|
||||
192.168.1.21 bikinibottom bikinibottom.local
|
||||
|
||||
#
|
||||
192.168.1.53 retropie
|
||||
```
|
||||
@@ -50,18 +53,20 @@ ssh-copy-id -f -i ~/.ssh/id_ed25519.pub pleb@<hostname>
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBLk24u7FT8PhAdM8EVUFGlOi0hle4CW8L284E1foUhS julien@julien-pc
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE6wr+DUbcfVTltoWT6gbPRY3geUYNhgN7/CLcMaMu0B eliot@toile-win
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKmttayKqj6Z290hMCc97v4dMZTSUz4lYgXR0NtcRr8U delmar@thinkpad
|
||||
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFlta/YdJ0ztVpZsP/nh37Fn+H5Hxg/Mw+jR91f5Gf08 pleb@bob
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9mn7tuYWTPLbH2MViAkiKSUkXj4NauCUgzj778LoQ2 pleb@carlo
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKL7A0xvHSfmWo+LUHdWWb03a5NXN1IlbLS5iSHxs3zw pleb@sandy
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHpnC0ftrLwzhsmonDtSvh38Oi5OGe1iOaQjlsm1RlD2 pleb@gary
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII9USnPFJx/PbV+KnlTN4o3f4SwiuHCWaAlE8aKcY4Ne pleb@sheldon
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMrWtBN3yRh3PHG+7UUeRUIvhuMcwtR88FzUn4xS5FyV pleb@pearl
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMfd7PrJ50jHrG6yjIJ5u7jKTyXi9mPn8/oa+HNAVNsf pleb@krabs
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKe0iX+Al5bdMf93lMj/V/1FUpXJsYG6XNw4C4Bpj7SS pleb@sandy
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPq4T605pUQsUAntUbFousyuJADISEHAk+MnZoq7lAYB pleb@gary
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKvQwj0zeF18hl/BcX7eRFgXb3TNFUGooOE1NJeNlX0z pleb@sheldon
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEPUeE7PCnDcEW7dtyWUdxDBD57GmIzeY1a0eFn0JiRX pleb@pearl
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILPeyUpr/R9KgX+0Yr8R9VLIoxREc+XC7EJA1aWDS/08 pleb@krabs
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJtrn0Oj2IstMwzheIZcJGBA8RNWTyNtksaK2LhvjNul pleb@bernie
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHh1LTS5PzsQ45xiRbyxBbCurI7JdEpdkCsbx3mlYaaR pleb@patrick
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAaOsYNLsoYcXDV3I7zbJABeIo7CJOdMxUN86rH1/IH9 pleb@karen
|
||||
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG+Odc/LY/fPcapj6yxF6of+pygbaFvMg0P9RUA69pQV borg@3c6ee04b29c5
|
||||
## krabs
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJDsfMBjZO/uWCoyvuYEKVq4wr6Z67gZRC3wRAimxdLS root@nextcloud-aio-borgbackup
|
||||
## karen
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCiAt5dNKbcaYmmsMGitBTaYoKkfEMJ5dGBzbSIDF4WdmPQGFmNf3urAxM1MDjlW7ifzfia7I49pc+Sndo0+b/FiS9FIMWwlNmOrr5c24XXZvYhPvk2M9ghEhXgLGDO3N/xPG6M+rrEzeRFXCdlHZuan6/iUdGcDQtgS2q4ciAMCk8V0QptmvWYqgs/CMsnU3WULUA+abKdx605zzG0inF6pNFaIO50mRraPQsWq34SxXknkJnTBHFogj9NyV/Y9BhiKBm3IXn2f9cVK5/+8Af91w5uI07kpLnPXSDkEZFKK4J48dCdDLhOk2H1/PzapkwW5pF8dhBeKVW2W7oyvuWplKj7cS2dS9ODqqae5kgI83IBdOxQ3VONRCHiUVbezREON66xpOncmWq/YhegWCCHviHUzO0DtpxQXPnZTcX6LwiWhZ9vzGdostJ72i2PxtU155S5PBqaXF+u01cbD0yOuA364LIri2mJxgXHqQH6VwgUJYA7G3Ln4KTueHc9oQxZS5+zZA6LfIu0AB0o7RGcvRV2F+434svy9aXceOUQ2n/5qWo6jmqtOsx2IGkiBkCCHBK8G/83mWBWcfbzXdfPDj7a2xeMoiAU5Rr99JIJkiplDMVrR48diGtCxRYjitWUBigbz6Yy0ozowT6TUvK2PaPUgfhxVK2lhi/et37+/w== NVIDIA-SDK-Manager
|
||||
```
|
||||
|
||||
|
||||
@@ -1,375 +0,0 @@
|
||||
Kubernetes (K3Sup)
|
||||
===
|
||||
|
||||
### Installation de kubectl ?
|
||||
|
||||
```bash
|
||||
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
|
||||
sudo mkdir -p -m 755 /etc/apt/keyrings
|
||||
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
|
||||
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y kubectl
|
||||
```
|
||||
|
||||
### Installation de k3sup :
|
||||
|
||||
```bash
|
||||
# Avec curl
|
||||
curl -sLS https://get.k3sup.dev | sh
|
||||
sudo install k3sup /usr/local/bin/
|
||||
|
||||
# Ou téléchargement direct depuis GitHub
|
||||
wget https://github.com/alexellis/k3sup/releases/download/0.13.11/k3sup
|
||||
chmod +x k3sup
|
||||
sudo mv k3sup /usr/local/bin/
|
||||
```
|
||||
|
||||
#### Premier déploiement :
|
||||
|
||||
```bash
|
||||
# Installation du master node
|
||||
k3sup install --ip 192.168.1.14 --user pleb --ssh-key $HOME/.ssh/bikiniBottom
|
||||
|
||||
# Ajout des worker nodes
|
||||
k3sup join --ip 192.168.1.13 --server-ip 192.168.1.14 --user pleb --ssh-key $HOME/.ssh/bikiniBottom
|
||||
k3sup join --ip 192.168.1.16 --server-ip 192.168.1.14 --user pleb --ssh-key $HOME/.ssh/bikiniBottom
|
||||
k3sup join --ip 192.168.1.19 --server-ip 192.168.1.14 --user pleb --ssh-key $HOME/.ssh/bikiniBottom
|
||||
```
|
||||
|
||||
#### Vérification du cluster :
|
||||
|
||||
```bash
|
||||
# Export du kubeconfig
|
||||
export KUBECONFIG=~/delmar.bzh/kubernetes/kubeconfig
|
||||
|
||||
# Vérification des nœuds
|
||||
kubectl get nodes -o wide
|
||||
|
||||
# Check des pods système
|
||||
kubectl get pods -n kube-system
|
||||
```
|
||||
|
||||
#### Setting labels:
|
||||
|
||||
```bash
|
||||
# sudo k3s kubectl label nodes xxx kubernetes.io/role=worker
|
||||
kubectl label nodes gary kubernetes.io/role=worker
|
||||
kubectl label nodes sheldon kubernetes.io/role=worker
|
||||
kubectl label nodes pearl kubernetes.io/role=worker
|
||||
|
||||
# sudo k3s kubectl label nodes sandy node-type=worker
|
||||
kubectl label nodes gary node-type=worker
|
||||
kubectl label nodes sheldon node-type=worker
|
||||
kubectl label nodes pearl node-type=worker
|
||||
```
|
||||
|
||||
```bash
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
```
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
gary Ready worker 82m v1.35.5+k3s1
|
||||
pearl Ready worker 81m v1.35.5+k3s1
|
||||
sandy Ready control-plane 84m v1.35.5+k3s1
|
||||
sheldon Ready worker 82m v1.35.5+k3s1
|
||||
```
|
||||
|
||||
### Helm
|
||||
|
||||
> On sandy
|
||||
|
||||
```bash
|
||||
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
|
||||
chmod 700 get_helm.sh
|
||||
./get_helm.sh
|
||||
helm version
|
||||
```
|
||||
|
||||
#### [Headlamp](https://headlamp.dev/docs/latest/)
|
||||
|
||||
```bash
|
||||
# first add our custom repo to your local helm repositories
|
||||
helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
|
||||
|
||||
# now you should be able to install headlamp via helm
|
||||
helm install bb-headlamp headlamp/headlamp --namespace kube-system
|
||||
```
|
||||
|
||||
```
|
||||
NAME: bb-headlamp
|
||||
LAST DEPLOYED: Tue Feb 17 17:17:03 2026
|
||||
NAMESPACE: kube-system
|
||||
STATUS: deployed
|
||||
REVISION: 1
|
||||
TEST SUITE: None
|
||||
NOTES:
|
||||
```
|
||||
|
||||
1. Get the application URL by running these commands:
|
||||
```bash
|
||||
export POD_NAME=$(kubectl get pods --namespace kube-system -l "app.kubernetes.io/name=headlamp,app.kubernetes.io/instance=bb-headlamp" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace kube-system $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace kube-system port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||
```
|
||||
|
||||
2. Get the token using
|
||||
```bash
|
||||
kubectl create token bb-headlamp --namespace kube-system
|
||||
```
|
||||
|
||||
#### metallb
|
||||
|
||||
```bash
|
||||
# Add MetalLB repository to Helm
|
||||
helm repo add metallb https://metallb.github.io/metallb
|
||||
|
||||
# Check the added repository
|
||||
helm search repo metallb
|
||||
|
||||
helm upgrade --install metallb metallb/metallb --create-namespace \
|
||||
--namespace metallb-system --wait
|
||||
```
|
||||
```bash
|
||||
Release "metallb" does not exist. Installing it now.
|
||||
NAME: metallb
|
||||
LAST DEPLOYED: Wed Feb 18 11:46:03 2026
|
||||
NAMESPACE: metallb-system
|
||||
STATUS: deployed
|
||||
REVISION: 1
|
||||
TEST SUITE: None
|
||||
NOTES:
|
||||
MetalLB is now running in the cluster.
|
||||
|
||||
Now you can configure it via its CRs. Please refer to the metallb official docs
|
||||
on how to use the CRs.
|
||||
```
|
||||
```bash
|
||||
vim metallb-config.yaml
|
||||
|
||||
---
|
||||
apiVersion: metallb.io/v1beta1
|
||||
kind: IPAddressPool
|
||||
metadata:
|
||||
name: default-pool
|
||||
namespace: metallb-system
|
||||
spec:
|
||||
addresses:
|
||||
- 192.168.1.21-192.168.1.30
|
||||
|
||||
---
|
||||
apiVersion: metallb.io/v1beta1
|
||||
kind: L2Advertisement
|
||||
metadata:
|
||||
name: default
|
||||
namespace: metallb-system
|
||||
spec:
|
||||
ipAddressPools:
|
||||
- default-pool
|
||||
```
|
||||
|
||||
#### traefik
|
||||
|
||||
```bash
|
||||
vim traefik-ingress.yml
|
||||
```
|
||||
|
||||
```
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: traefik-basic-auth-secret
|
||||
namespace: kube-system
|
||||
data:
|
||||
users: |2
|
||||
YWRtaW46JGFwcjEkMmp5TzMwYmskRE5IV0VEQW1VQXFVajVGOHNvdXNVMAoK
|
||||
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: traefik-basic-auth-middleware
|
||||
spec:
|
||||
basicAuth:
|
||||
secret: traefik-basic-auth-secret
|
||||
realm: "Traefik Dashboard"
|
||||
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: traefik-ingress
|
||||
namespace: kube-system
|
||||
annotations:
|
||||
spec.ingressClassName: traefik
|
||||
traefik.ingress.kubernetes.io/router.middlewares: kube-system-traefik-basic-auth-middleware@kubernetescrd
|
||||
spec:
|
||||
serviceAccountName: traefik-ingress
|
||||
env:
|
||||
name: OVH_ENDPOINT
|
||||
value: ovh-eu
|
||||
name: OVH_APPLICATION_KEY
|
||||
value: 3f8bdfed17f848d8
|
||||
name: OVH_APPLICATION_SECRET
|
||||
value: 6946758d7515ecef108aeb286bf3c7d0
|
||||
name: OVH_CONSUMER_KEY
|
||||
value: 94b2ddf482d36421a33aa6b3aa51595
|
||||
args:
|
||||
- --configFile=/config/traefik.toml
|
||||
volumeMounts:
|
||||
- name: traefik-config
|
||||
mountPath: /config/
|
||||
- name: traefik-custom
|
||||
mountPath: /custom/
|
||||
- name: traefik-certs
|
||||
mountPath: /certs/
|
||||
ports:
|
||||
name: http
|
||||
containerPort: 80
|
||||
name: https
|
||||
containerPort: 443
|
||||
name: dashboard
|
||||
containerPort: 8080
|
||||
volumes:
|
||||
- name: traefik-config
|
||||
configMap:
|
||||
- name: traefik-config
|
||||
- name: traefik-custom
|
||||
- name: traefik-certs
|
||||
persistentVolumeClaim:
|
||||
claimName: traefik-certsrules:
|
||||
- http:
|
||||
paths:
|
||||
- pathType: Prefix
|
||||
path: "/"
|
||||
backend:
|
||||
service:
|
||||
name: traefik-dashboard
|
||||
port:
|
||||
number: 8080
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: traefik-dashboard
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: traefik-dashboard
|
||||
type: LoadBalancer
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo k3s kubectl -n kube-system apply -f traefik-ingress.yml
|
||||
```
|
||||
|
||||
#### [longhorn](https://longhorn.io)
|
||||
|
||||
```bash
|
||||
helm repo add longhorn https://charts.longhorn.io
|
||||
helm repo update
|
||||
kubectl create namespace longhorn-system
|
||||
helm install longhorn longhorn/longhorn --namespace longhorn-system
|
||||
|
||||
USER=admin; PASSWORD=v5bB4OQRDfY5tFJ1; echo "${USER}:$(openssl passwd -stdin -apr1 <<< ${PASSWORD})" >> auth
|
||||
|
||||
kubectl -n longhorn-system create secret generic basic-auth --from-file=auth
|
||||
|
||||
vim longhorn/longhorn-middelwares.yaml
|
||||
````
|
||||
|
||||
```
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: longhorn-auth
|
||||
namespace: longhorn-system
|
||||
spec:
|
||||
basicAuth:
|
||||
secret: basic-auth
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: longhorn-buffering
|
||||
namespace: longhorn-system
|
||||
spec:
|
||||
buffering:
|
||||
# Allows backing image uploads up to 10,000MB
|
||||
maxRequestBodyBytes: 10485760000
|
||||
```
|
||||
|
||||
```bash
|
||||
kubectl apply -f longhorn-middlewares.yml
|
||||
```
|
||||
|
||||
```bash
|
||||
vim longhorn/longhorn-ingress.yaml
|
||||
```
|
||||
|
||||
```
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: longhorn-ingress
|
||||
namespace: longhorn-system
|
||||
annotations:
|
||||
# Connect the middlewares defined in step 2
|
||||
traefik.ingress.kubernetes.io/router.middlewares:
|
||||
longhorn-system-longhorn-auth@kubernetescrd,
|
||||
longhorn-system-longhorn-buffering@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: longhorn-frontend
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
```bash
|
||||
kubectl -n longhorn-system get pod
|
||||
|
||||
kubectl get storageclass
|
||||
```
|
||||
|
||||
```
|
||||
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
|
||||
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 93m
|
||||
longhorn (default) driver.longhorn.io Delete Immediate true 59m
|
||||
longhorn-static driver.longhorn.io Delete Immediate true 59m
|
||||
```
|
||||
|
||||
##### Unset default for "local-path" (emmc)
|
||||
|
||||
```bash
|
||||
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
|
||||
```
|
||||
|
||||
##### Mark longhorn as "default"
|
||||
|
||||
```bash
|
||||
kubectl patch storageclass longhorn -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
|
||||
```
|
||||
|
||||
##### Apply ingress
|
||||
```bash
|
||||
kubectl -n longhorn-system apply -f longhorn/longhorn-ingress.yaml
|
||||
|
||||
kubectl -n longhorn-system get ingress
|
||||
```
|
||||
+68
-10
@@ -92,7 +92,7 @@ borg.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:8080
|
||||
reverse_proxy carlo:8081
|
||||
}
|
||||
|
||||
cap.delmar.bzh {
|
||||
@@ -187,7 +187,7 @@ dev.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:19080
|
||||
reverse_proxy patrick:5678
|
||||
}
|
||||
|
||||
dia.delmar.bzh {
|
||||
@@ -235,6 +235,15 @@ gotify.delmar.bzh {
|
||||
reverse_proxy carlo:41901
|
||||
}
|
||||
|
||||
hmr.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy bob:39084
|
||||
}
|
||||
|
||||
homepage.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
@@ -290,7 +299,7 @@ jellyfin.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:8096
|
||||
reverse_proxy carlo:8096
|
||||
}
|
||||
|
||||
jellyseerr.delmar.bzh {
|
||||
@@ -299,7 +308,7 @@ jellyseerr.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:5055
|
||||
reverse_proxy carlo:5055
|
||||
}
|
||||
|
||||
kontadenn.delmar.bzh {
|
||||
@@ -320,6 +329,15 @@ kontadenn.delmar.bzh {
|
||||
}
|
||||
}
|
||||
|
||||
lghn.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy bikinibottom:80
|
||||
}
|
||||
|
||||
lnk.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
@@ -335,7 +353,11 @@ lud.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy carlo:3002
|
||||
reverse_proxy carlo:3002 {
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
mmgr.delmar.bzh {
|
||||
@@ -344,7 +366,16 @@ mmgr.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:38274
|
||||
reverse_proxy carlo:38274
|
||||
}
|
||||
|
||||
mmm.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy bikinibottom:8001
|
||||
}
|
||||
|
||||
nds.delmar.bzh {
|
||||
@@ -383,6 +414,15 @@ nsns.delmar.bzh {
|
||||
}
|
||||
}
|
||||
|
||||
oec.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy carlo:32768
|
||||
}
|
||||
|
||||
octoprint.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
@@ -524,13 +564,22 @@ stream.delmar.bzh {
|
||||
}
|
||||
}
|
||||
|
||||
swarmpit.delmar.bzh {
|
||||
swpt.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy 192.168.1.21:888
|
||||
reverse_proxy bikinibottom:888
|
||||
}
|
||||
|
||||
tournoi.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy carlo:2020
|
||||
}
|
||||
|
||||
tpml.delmar.bzh {
|
||||
@@ -560,6 +609,15 @@ trek.delmar.bzh {
|
||||
reverse_proxy carlo:32776
|
||||
}
|
||||
|
||||
trfk.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy bikinibottom:9000
|
||||
}
|
||||
|
||||
trmx.delmar.bzh {
|
||||
encode {
|
||||
zstd
|
||||
@@ -610,7 +668,7 @@ wizarr.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:5690
|
||||
reverse_proxy carlo:5690
|
||||
}
|
||||
|
||||
www.delmar.bzh {
|
||||
@@ -652,5 +710,5 @@ zik.delmar.bzh {
|
||||
gzip
|
||||
minimum_length 1024
|
||||
}
|
||||
reverse_proxy patrick:4533
|
||||
reverse_proxy carlo:4533
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user