Compare commits
5
Commits
32b1f095fe
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3e328f969 | ||
|
|
c287fb0145 | ||
|
|
f7888a8f8d | ||
|
|
c1c5c08cbb | ||
|
|
30869a16b0 |
@@ -15,6 +15,7 @@ Recovery steps are in `RUNBOOK.md`. Repo overview and workflows are in `README.m
|
|||||||
- **Cockpit (argento.timothykim.net)**: Runs directly on the host (not Docker) on port 9090 with self-signed TLS. The nginx conf inlines security headers instead of including security-headers.inc because Cockpit's internal iframes break with X-Frame-Options: DENY. Cockpit has a known bug where font files return 404 — this is not a proxy issue.
|
- **Cockpit (argento.timothykim.net)**: Runs directly on the host (not Docker) on port 9090 with self-signed TLS. The nginx conf inlines security headers instead of including security-headers.inc because Cockpit's internal iframes break with X-Frame-Options: DENY. Cockpit has a known bug where font files return 404 — this is not a proxy issue.
|
||||||
- **Minecraft HTTP-only**: HTTPS causes WebSocket/CORS errors with the MCSManager daemon. No cert issued for this domain.
|
- **Minecraft HTTP-only**: HTTPS causes WebSocket/CORS errors with the MCSManager daemon. No cert issued for this domain.
|
||||||
- **SSL cert issuance chicken-and-egg**: On fresh recovery, certs don't exist so SSL confs can't load. The `.hold` pattern moves SSL confs aside, starts nginx with HTTP-only confs, issues certs, then restores SSL confs.
|
- **SSL cert issuance chicken-and-egg**: On fresh recovery, certs don't exist so SSL confs can't load. The `.hold` pattern moves SSL confs aside, starts nginx with HTTP-only confs, issues certs, then restores SSL confs.
|
||||||
|
- **ZFS NFSv4 ACLs on threeteras/media**: `acltype=nfsv4`, `aclmode=restricted`, `aclinherit=passthrough`. `chmod` on anything under `/opt/argento/smb/media` fails with `Operation not permitted` (EPERM) even as root — that is the ACL refusing to be overwritten, not a bug. New dirs inherit the parent's ACL automatically, so setgid bits and `chmod` are unnecessary; don't put `force create mode` / `force directory mode` in smb.conf shares over this dataset either, since those make Samba call chmod.
|
||||||
- **SELinux is enforcing**: Caused issues with samba (symlinks blocked, parent directory traversal blocked). Don't use symlinks for config files — use the sync-system.sh copy approach instead.
|
- **SELinux is enforcing**: Caused issues with samba (symlinks blocked, parent directory traversal blocked). Don't use symlinks for config files — use the sync-system.sh copy approach instead.
|
||||||
- **Secrets in .env files**: All secrets (DB passwords, API keys, tokens) live in `.env` files under each app's `docker/<app>/` directory on the server. These are gitignored (`**/.env` in root `.gitignore`). The `.env` files are included in the USB backup. If the backup is lost, all secrets can be recreated from Bitwarden. The `system/msmtprc` in the repo has its password REDACTED -- the real one is only on the server.
|
- **Secrets in .env files**: All secrets (DB passwords, API keys, tokens) live in `.env` files under each app's `docker/<app>/` directory on the server. These are gitignored (`**/.env` in root `.gitignore`). The `.env` files are included in the USB backup. If the backup is lost, all secrets can be recreated from Bitwarden. The `system/msmtprc` in the repo has its password REDACTED -- the real one is only on the server.
|
||||||
- **ZFS parent dataset mountpoints**: Pools have parent datasets (e.g., `nextcloud`, `threeteras`) that create mountpoints like `/mnt/nextcloud`. These are empty and expected — do not delete them.
|
- **ZFS parent dataset mountpoints**: Pools have parent datasets (e.g., `nextcloud`, `threeteras`) that create mountpoints like `/mnt/nextcloud`. These are empty and expected — do not delete them.
|
||||||
|
|||||||
+19
-14
@@ -120,19 +120,10 @@ zfs create -o mountpoint=/opt/argento/docker/immich/library threeteras/immich
|
|||||||
|
|
||||||
zpool status # verify pools are ONLINE
|
zpool status # verify pools are ONLINE
|
||||||
|
|
||||||
# Per-user SMB share dirs need ownership + setgid (rsync in step 7c will
|
|
||||||
# preserve these if a USB backup exists, but freshly-created datasets are
|
|
||||||
# root-owned and need this fixup).
|
|
||||||
for u in yireh isaac; do
|
|
||||||
chown "$u":sambagroup "/opt/argento/smb/$u"
|
|
||||||
chmod 2770 "/opt/argento/smb/$u"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Shared music dir. Lives inside the media dataset (so it rides the media
|
# Shared music dir. Lives inside the media dataset (so it rides the media
|
||||||
# snapshot policy) but is exported as its own writable [music] share.
|
# snapshot policy) but is exported as its own writable [music] share.
|
||||||
# setgid so files dropped in over SMB inherit sambagroup and stay readable
|
# Ownership is set in step 7b — sambagroup doesn't exist yet.
|
||||||
# by the Navidrome container.
|
mkdir -p /opt/argento/smb/media/Music
|
||||||
install -d -o timothykim -g sambagroup -m 2775 /opt/argento/smb/media/Music
|
|
||||||
|
|
||||||
# SELinux contexts for samba — fresh ZFS datasets get unlabeled_t and samba
|
# SELinux contexts for samba — fresh ZFS datasets get unlabeled_t and samba
|
||||||
# refuses to serve them. Persistent rules (semanage) survive full relabels;
|
# refuses to serve them. Persistent rules (semanage) survive full relabels;
|
||||||
@@ -151,9 +142,23 @@ so file ownership lands on the correct UIDs.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
/opt/argento/scripts/restore-users.sh
|
/opt/argento/scripts/restore-users.sh
|
||||||
|
|
||||||
|
# Share dirs are root-owned on freshly created datasets. These must run AFTER
|
||||||
|
# restore-users.sh — the users and sambagroup don't exist before it. Skip if
|
||||||
|
# the datasets were imported intact; step 7c's rsync preserves ownership.
|
||||||
|
for u in yireh isaac; do
|
||||||
|
chown "$u":sambagroup "/opt/argento/smb/$u"
|
||||||
|
chmod 2770 "/opt/argento/smb/$u"
|
||||||
|
done
|
||||||
|
|
||||||
|
# No chmod on Music: threeteras/media is acltype=nfsv4 aclmode=restricted, so
|
||||||
|
# chmod fails with EPERM. aclinherit=passthrough already copied the parent's
|
||||||
|
# ACL onto the dir, which is what grants sambagroup write. The other datasets
|
||||||
|
# are acltype=posix aclmode=discard, so chmod works normally there.
|
||||||
|
chown timothykim:sambagroup /opt/argento/smb/media/Music
|
||||||
```
|
```
|
||||||
|
|
||||||
This recreates timothykim, yireh, isaac, and the sambagroup group with
|
This recreates timothykim, yireh, isaac, hannah, and the sambagroup group with
|
||||||
their original UIDs/GIDs, then restores the samba password hashes from
|
their original UIDs/GIDs, then restores the samba password hashes from
|
||||||
`/mnt/backup/argento/system/samba-private/` if present (mirrored there
|
`/mnt/backup/argento/system/samba-private/` if present (mirrored there
|
||||||
by sync-system.sh, gitignored so the hashes aren't in version control).
|
by sync-system.sh, gitignored so the hashes aren't in version control).
|
||||||
@@ -161,7 +166,7 @@ by sync-system.sh, gitignored so the hashes aren't in version control).
|
|||||||
If the samba passdb backup is missing, set passwords manually:
|
If the samba passdb backup is missing, set passwords manually:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
for u in timothykim yireh isaac; do
|
for u in timothykim yireh isaac hannah; do
|
||||||
smbpasswd -a "$u"
|
smbpasswd -a "$u"
|
||||||
smbpasswd -e "$u"
|
smbpasswd -e "$u"
|
||||||
done
|
done
|
||||||
@@ -265,7 +270,7 @@ Deploy each app (nginx is already running and will return 502 until they start):
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Add any new apps that have been added since this was written
|
# Add any new apps that have been added since this was written
|
||||||
for app in nextcloud gitea jellyfin navidrome garage minecraft immich beszel-agent; do
|
for app in nextcloud gitea jellyfin navidrome garage minecraft immich beszel-agent diun; do
|
||||||
cd /opt/argento/docker/$app
|
cd /opt/argento/docker/$app
|
||||||
docker compose pull
|
docker compose pull
|
||||||
docker compose build
|
docker compose build
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
services:
|
||||||
|
navidrome:
|
||||||
|
image: deluan/navidrome:latest
|
||||||
|
container_name: navidrome
|
||||||
|
restart: unless-stopped
|
||||||
|
# timothykim:sambagroup — needs group-read on the music files. Without an
|
||||||
|
# explicit user the image runs as root.
|
||||||
|
user: "1000:1001"
|
||||||
|
networks:
|
||||||
|
- shared
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
- /opt/argento/smb/media/Music:/music:ro
|
||||||
|
environment:
|
||||||
|
TZ: America/New_York
|
||||||
|
# Navidrome watches the filesystem, but a periodic sweep catches anything
|
||||||
|
# inotify missed. Default is 0 (watcher only).
|
||||||
|
ND_SCANNER_SCHEDULE: "@every 24h"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
shared:
|
||||||
|
external: true
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ USERS=(
|
|||||||
"timothykim:1000:1000:/bin/bash:home:wheel,video,docker,sambagroup"
|
"timothykim:1000:1000:/bin/bash:home:wheel,video,docker,sambagroup"
|
||||||
"yireh:1100:1100:/sbin/nologin:nohome:sambagroup"
|
"yireh:1100:1100:/sbin/nologin:nohome:sambagroup"
|
||||||
"isaac:1101:1101:/sbin/nologin:nohome:sambagroup"
|
"isaac:1101:1101:/sbin/nologin:nohome:sambagroup"
|
||||||
|
"hannah:1102:1102:/sbin/nologin:nohome:sambagroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Abort if an existing entity's numeric ID doesn't match what we expect
|
# Abort if an existing entity's numeric ID doesn't match what we expect
|
||||||
@@ -122,7 +123,7 @@ if ! mountpoint -q /mnt/backup; then
|
|||||||
echo "[!] /mnt/backup is not mounted — skipping samba passdb restore"
|
echo "[!] /mnt/backup is not mounted — skipping samba passdb restore"
|
||||||
echo " mount the USB backup drive (RUNBOOK step 5) and re-run if you want"
|
echo " mount the USB backup drive (RUNBOOK step 5) and re-run if you want"
|
||||||
echo " to restore preserved SMB passwords; otherwise set them manually:"
|
echo " to restore preserved SMB passwords; otherwise set them manually:"
|
||||||
echo " for u in timothykim yireh isaac; do smbpasswd -a \"\$u\"; done"
|
echo " for u in timothykim yireh isaac hannah; do smbpasswd -a \"\$u\"; done"
|
||||||
elif [ -f "$PASSDB_SRC/passdb.tdb" ]; then
|
elif [ -f "$PASSDB_SRC/passdb.tdb" ]; then
|
||||||
install -d -m 700 /var/lib/samba/private
|
install -d -m 700 /var/lib/samba/private
|
||||||
cp "$PASSDB_SRC"/*.tdb /var/lib/samba/private/
|
cp "$PASSDB_SRC"/*.tdb /var/lib/samba/private/
|
||||||
@@ -130,7 +131,7 @@ elif [ -f "$PASSDB_SRC/passdb.tdb" ]; then
|
|||||||
echo "[+] restored samba passdb from $PASSDB_SRC/"
|
echo "[+] restored samba passdb from $PASSDB_SRC/"
|
||||||
else
|
else
|
||||||
echo "[!] no samba passdb backup found at $PASSDB_SRC/"
|
echo "[!] no samba passdb backup found at $PASSDB_SRC/"
|
||||||
echo " run: for u in timothykim yireh isaac; do smbpasswd -a \"\$u\"; done"
|
echo " run: for u in timothykim yireh isaac hannah; do smbpasswd -a \"\$u\"; done"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<service name="samba"/>
|
<service name="samba"/>
|
||||||
<service name="https"/>
|
<service name="https"/>
|
||||||
<service name="smtp"/>
|
<service name="smtp"/>
|
||||||
|
<service name="mdns"/>
|
||||||
<port port="465" protocol="tcp"/>
|
<port port="465" protocol="tcp"/>
|
||||||
<port port="19999" protocol="tcp"/>
|
<port port="19999" protocol="tcp"/>
|
||||||
<port port="3901" protocol="tcp"/>
|
<port port="3901" protocol="tcp"/>
|
||||||
|
|||||||
@@ -45,6 +45,15 @@
|
|||||||
browseable = yes
|
browseable = yes
|
||||||
guest ok = no
|
guest ok = no
|
||||||
|
|
||||||
|
[music]
|
||||||
|
path = /opt/argento/smb/media/Music
|
||||||
|
valid users = @sambagroup
|
||||||
|
write list = @sambagroup
|
||||||
|
force group = sambagroup
|
||||||
|
read only = no
|
||||||
|
browseable = yes
|
||||||
|
guest ok = no
|
||||||
|
|
||||||
|
|
||||||
#[homes]
|
#[homes]
|
||||||
# comment = Home Directories
|
# comment = Home Directories
|
||||||
|
|||||||
Reference in New Issue
Block a user