Commit Graph
100 Commits
Author SHA1 Message Date
Claude acffd6e67b Add Vanilla Tweaks auto-install from extras/datapacks/
Place datapacks_<ver>.zip or crafting_tweaks_<ver>.zip in extras/datapacks/
before running the Minecraft installer and they will be detected automatically.

- Pattern match: *datapack* → unzip into datapacks-download/; *craft* → copy as-is
- Version extracted from filename; compared against selected MC version at picker step
- Early banner notice when ZIPs are absent (where to put them and naming convention)
- If ZIPs present: show found files + version check, offer "Use pre-packaged VT?" (default y)
- Accepting skips the individual datapack picker entirely
- Manual fallback instructions updated to hint at extras/datapacks/ for next time
- Removed broken VT share# links from manual instructions
- Added extras/datapacks/README.md (naming convention + download sources)
- Added .gitignore: extras/datapacks/*.zip never committed

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 16:40:51 +00:00
Claude 7ae5a20e0e Rename backup services: backup (comprehensive) + gaming-backup (saves-only)
- backup: renamed from disaster-backup; full ~/docker/<service>/ snapshots,
  Minecraft flushed not stopped, everything else stop/snap/start for DB
  consistency; backup.conf / restore/ layout; post-install-backup timer
- gaming-backup: renamed from backup; frequent game-save snapshots (Minecraft
  world data, emulator saves, Steam, Wolf state) with no service downtime;
  defaults to hourly schedule; separate gaming-kopia repo + gaming-backup timer
- Deleted services/disaster-backup.sh
- README: updated backup row to reflect new names

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 15:58:15 +00:00
Claude 9aa9b00b59 disaster-backup: Minecraft flush-not-stop, update descriptions
Minecraft instances are flushed to disk (save-all) and snapshotted while
the server keeps running — no player disruption. All other services stop
briefly for filesystem-consistent database snapshots, then restart.
Also update file header, install banner, schedule description, and README.

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 15:50:22 +00:00
Claude 55d8d09e46 Add Minecraft seed prompt and disaster-recovery backup service
- minecraft: prompt for world seed on new installs (skipped if world already exists); SEED env var wired into docker-compose.yml
- disaster-backup: new service that stops each Docker service, snapshots the full ~/docker/<service>/ directory (config + data + databases), then restarts it — multi-destination support so different services can go to different drives/repos; one restore_kopia_backup.sh per destination
- README: update backup row to list both backup and disaster-backup

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 15:42:58 +00:00
Claude d21a7ea7fb feat: add interactive Kopia restore script, Authelia guidance in CLAUDE.md
- extras/restore_kopia_backup.sh: interactive restore tool — lists all
  snapshot sources, pick source + snapshot, choose inspect (restore to
  /tmp) or restore-in-place (moves current data aside as .pre-restore-DATE
  for easy rollback, auto-stops/starts the associated Docker service)
- services/backup.sh: copy restore script to ~/docker/backup/ during
  install; update summary to show restore command
- CLAUDE.md: add note to update README services table when adding a
  service; add Authelia section documenting which services have built-in
  auth, the import-authelia Caddy pattern for no-auth services, and
  remember_me_duration config for kiosk/persistent sessions

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 15:07:04 +00:00
Claude 177598a79e docs: add CLAUDE.md, move backup guide into installer, drop linux-to-sync
- CLAUDE.md: full contributor guide — service template, all helpers,
  globals, DRY_RUN convention, Caddy wiring, non-Docker patterns
- services/backup.sh: print backup strategy guide (Kopia/Borg/rsync/
  rsnapshot + when to use each) at the start of install_backup()
- README.md: remove standalone backup section, fix broken backup row,
  inline base package list, add CLAUDE.md to layout
- services/linux-to-sync.sh: deleted (never worked)
- setup.sh: remove linux-to-sync from is_installed()

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 14:29:02 +00:00
Claude 4cfef73090 docs: move base packages list into Services table, drop standalone section
https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 14:07:20 +00:00
Claude 5146412ade docs: expand README with base packages list and full backup strategy guide
Documents all packages installed by the base service, and adds a
Backup section covering Kopia, Borg, plain rsync, rsync --link-dest
(versioned snapshots with original folder structure), and rsnapshot —
with guidance on when to use each.

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
2026-06-04 13:51:46 +00:00
Claude 7a555987ed chore: remove old pre-modular files and internal planning docs
Keep only the two base install scripts (24.04, 26.04), the modular
system (setup.sh, lib/, services/, extras/, bootstrap.sh), and
LICENSE/README/VERSION. Everything else was superseded.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 13:30:05 +00:00
Claude e9830fef31 services/minecraft.sh: generate PREGEN_INSTRUCTIONS.md when chunky is selected
Writes radius, border status, and commands for monitoring, re-running,
and cancelling chunk pre-generation. Listed in the setup summary.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 13:19:07 +00:00
Claude f86e35aaf1 services/minecraft.sh: fix two incorrect printed instructions
- SCP example used $(whoami) which evaluates to root; use $ACTUAL_USER instead
- VT_VERSION stripped to major.minor (e.g. 1.21) so the picker version
  prompt is correct; previous awk printed the full patch string (1.21.4)

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 12:56:16 +00:00
Claude 5138d6fca7 services/minecraft.sh: remove stale manual-run comment from pregen-startup.sh
Pregen runs automatically when starting the server; the "run manually"
comment inside the script was misleading.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 02:30:09 +00:00
Claude ae7b887b22 services/minecraft.sh: sync world border default and VT header from latest standalone
- World border default changed from y to n (border is opt-in)
- VT share links header updated with pack counts (22 datapacks, 10 crafting tweaks)

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 02:27:36 +00:00
Claude f5e3fea71c README: spell out how to get repo onto USB (extract + drag)
Step 1 was vague. Now explicit: download ZIP, right-click Extract Here,
drag the folder onto the USB in the file manager sidebar.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 02:14:41 +00:00
Claude 9968776813 README: USB install — open folder in file manager, no path needed
When you open the USB folder in the file manager, you're already there.
Right-click → Open in Terminal → sudo bash bootstrap.sh, or double-click
bootstrap.sh → Run in Terminal → sudo prompt. No /media/whoami/DRIVENAME
path hunting required.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 02:09:53 +00:00
Claude d2c57b5fc6 README: simplify USB install — download ZIP, not git clone
The real workflow is: GitHub Code → Download ZIP → unzip → copy to USB.
No git, no auth, no file manager tricks. On the target machine: ls to find
the drive name, then sudo bash /media/$(whoami)/DRIVENAME/...bootstrap.sh.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 02:06:18 +00:00
Claude e168d6256c bootstrap.sh self-elevates with sudo; USB install docs rewritten
bootstrap.sh: add self-elevation — if not root, re-exec under sudo.
Double-clicking the script in GNOME ("Run in Terminal") now prompts for
the sudo password automatically, no extra commands needed.

README: rewrite USB section around the real workflow:
  - clone with "Open in Terminal" from the file manager sidebar
  - Option A: right-click folder → Open in Terminal → sudo ./setup.sh
  - Option B: double-click bootstrap.sh → "Run in Terminal?" → sudo prompt
  - note on nautilus-extension-gnome-terminal and exFAT vs ext4

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 02:00:58 +00:00
Claude 1ac550d81e Remove Run Setup.desktop launcher and its README mention
https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 01:54:54 +00:00
Claude 8d7fb2df43 Add USB thumb drive install docs and double-click launcher
README: rewrite USB section with three steps:
  1. Auto-detect USB mount point and clone repo onto it
  2. Install nautilus-extension-gnome-terminal for right-click "Open in Terminal"
  3. Double-click "Run Setup.desktop" to launch wizard with sudo (no terminal needed)

Run Setup.desktop: launcher file included in the repo so it's present on the
USB automatically. Uses %k to find its own location, cds to that directory,
and runs sudo ./setup.sh in a terminal window.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 01:54:33 +00:00
Claude 3c3e9dd6da README: replace Docker-data USB section with thumb drive installer docs
The USB section was documenting the wrong thing. Replace with instructions
for carrying the repo on a USB stick and running setup.sh directly from it
on any fresh Ubuntu machine — no internet required for the repo.

Covers: cloning/copying to USB, finding the mount point on the target
machine, running setup from USB, exFAT vs ext4 trade-offs, fixing
permissions after copy.

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 01:51:12 +00:00
Claude 8aa1d4552d Auto-install Docker, add USB drive docs, improve whitelist UI
- lib/common.sh: require_docker now installs Docker CE + Compose plugin
  via get.docker.com instead of erroring out if Docker is missing.
  Also adds the calling user to the docker group automatically.

- README.md: fix 'tells you how to install Docker' → 'installs Docker
  automatically'; add full USB drive usage section (mount, fstab,
  DOCKER_DIR config, moving existing data, tips).

- services/minecraft.sh: replace single-source whitelist import with the
  multi-source UI from the updated setup-minecraft.sh — collects players
  from the current instance, saved backup files, and other servers' backups;
  assigns letters to each source so you can import by letter (all from that
  source) or by number (specific player).

https://claude.ai/code/session_017WJtGcE5jjerAQCUBWUE3H
2026-06-04 01:37:58 +00:00
Claude 8ffebe9a5a bootstrap: self-elevate sudo; document double-click workflow
Added exec sudo bash self-elevation so bootstrap.sh works correctly when
double-clicked ("Run in Terminal") without the user needing to prefix sudo.
If already root, the check is a no-op.

Removed bootstrap.desktop — too fragile across desktop environments.
README now covers both "Open in Terminal" and double-click paths.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 01:14:54 +00:00
Claude 39280d71cb README: document USB prep via GitHub ZIP download
The previous USB instructions assumed git was available. Added step-by-step
for the no-git path: GitHub ZIP download → unzip → copy to USB → run
bootstrap.sh. Includes the Ubuntu auto-mount path tip for finding the
drive name. Folder name note (ubuntu-post-install-main from ZIP) added.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 01:08:42 +00:00
Claude 9773dcfb63 bootstrap: support USB/local-copy and private repo PAT
Three usage modes now documented and implemented:

1. Public repo: curl | sudo bash (unchanged)
2. Private repo, USB: copy whole repo to thumb drive, run bootstrap.sh
   from it — detects setup.sh alongside itself, copies to ~/ubuntu-post-install,
   execs setup.sh. No git auth, no internet needed for the scripts.
3. Private repo, PAT: bootstrap.sh --pat ghp_xxx — PAT stripped from
   stored remote URL after clone so it is not saved in plain text.

USB mode is the recommended approach for private repos: clone once,
put on a drive, run on every new machine.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 01:00:57 +00:00
Claude 33f052ea0b Add bootstrap.sh and rewrite README for modular system
bootstrap.sh: one curl | sudo bash to get and run on a fresh box —
installs git if missing, clones/updates the repo, execs setup.sh.

README.md: complete rewrite. The old README described the monolithic
script (--restore, --migrate flags, Samba, NetBird, etc.) which no
longer exists. New README covers quick start, usage modes, service
table, layout, and managing installed services.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 00:26:09 +00:00
Claude 2ab0008338 Bump NodeSource from Node 22 to Node 24 LTS
Both silent-send and immich already use NodeSource (not Ubuntu repos).
Node 24 is the current active LTS; 22 moves to maintenance in 2025.
Minimum version checks (>=18 and >=20) are unchanged — both services
accept any sufficiently recent Node.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 00:22:07 +00:00
Claude 92e8866f13 pip_user_install: capability probe instead of version check
Probe for --break-system-packages support once (pip --help, cached in
_PIP_HAS_BSP) rather than comparing Ubuntu version numbers. Works on any
pip >= 22.3 regardless of distro; older pip (Ubuntu 22.04, pip 22.0)
falls back to --user only, which is correct there since PEP 668 isn't
enforced on 22.04 anyway.

The flag name is scary but harmless with --user: installs go to ~/.local/
which apt never manages regardless.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 00:05:36 +00:00
Claude e8667f02cf pip_user_install: add --break-system-packages on Ubuntu 24.04+
pip3 install --user alone does not reliably bypass PEP 668 in all 24.04
environments. --break-system-packages (pip 22.3+) is the correct override.
Flag is only added when ubuntu_version_ge "24.04" so it does not run on
Ubuntu 22.04 where pip 22.0 ships and the flag is not yet supported.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-04 00:01:57 +00:00
Claude ef08fef540 Add OS detection; surface version in header; centralise pip installs
lib/common.sh:
  - detect_os(): reads /etc/os-release into OS_DISTRO, OS_VERSION,
    OS_CODENAME globals (exported, auto-called on source)
  - ubuntu_version_ge(): numeric version comparison helper
  - pip_user_install(): central wrapper for pip3 install --user so any
    future version-specific flags are in one place

setup.sh:
  - Both header banners now show detected OS line (e.g., "Ubuntu 24.04 (noble)")
  - First-run path warns if not Ubuntu or < 24.04

services/sky-cam.sh, services/sync-cc.sh:
  - Replace inline pip3 invocations with pip_user_install helper

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 23:49:51 +00:00
Claude 370c513606 Skip required-packages step on re-run
On second run, is_installed base (command -v ncdu) detects that base
packages are already present and jumps straight to the service menu,
skipping the required-setup banner, confirm prompt, and apt-get install.
The first-run path is unchanged; `sudo ./setup.sh base` forces reinstall.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 23:48:15 +00:00
Claude 56d2f9e85b Add site-wide defaults: timezone, domain, Caddy network
Introduces a one-time configuration wizard (sudo ./setup.sh configure)
that stores SITE_TZ, SITE_DOMAIN, and SITE_CADDY_NET in ~/docker/.config.
Every service now uses these as prompt defaults so the user types common
values once instead of re-answering the same questions for each service.

- lib/common.sh: load_site_config / save_site_config; auto-loads on source;
  backward-compat BASE_DOMAIN alias kept for old .config files
- setup.sh: run_site_configure wizard; first-run offer after base install;
  `sudo ./setup.sh configure` command to update defaults at any time
- 14 services: TZ_VAL now honours SITE_TZ, falling back to /etc/timezone
- 3 inline-heredoc services (filebrowser, homeassistant, ntfy): same fix
- authelia: SITE_TZ/SITE_DOMAIN as prompt defaults; SITE_CADDY_NET replaces
  hardcoded caddy_net throughout (env, compose patch, network creation)
- minecraft, frigate-audio: simplify BASE_DOMAIN read to use SITE_DOMAIN
- sky-cam: SITE_TZ as default for timezone prompt

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 22:13:59 +00:00
Claude cfad0ebd20 fix(linux-to-sync): run git clone as actual user, handle re-run, show errors
Three bugs fixed:
1. git clone ran as root — SSH key lookup failed because user's keys are in
   ~user/.ssh/, not /root/.ssh/. Both SSH and PAT clones now run via
   sudo -u ACTUAL_USER so git uses the right key and the clone is owned
   correctly without a separate chown step.
2. 2>/dev/null on git clone swallowed all error output — errors are now
   shown so authentication failures are diagnosable.
3. No re-run handling — trying to clone into an existing dir silently
   failed. Now detects .git, offers git pull instead.
Also: checks for SSH key existence before attempting SSH clone, and prints
actionable guidance (ssh-keygen, ssh-add, ssh -T git@github.com) on failure.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 21:41:54 +00:00
Claude c3bb2cf18c feat(cameras): add sky-cam and frigate-audio service modules
sky-cam (cameras/non-docker):
  Clones outis1one/sky-cam via bootstrap.sh to ~/sky-cam. Prompts for
  latitude, longitude, timezone, camera names, BASE_DIR, and optional
  Mattermost webhook. Patches sky-cam.conf and installs systemd user
  timers via the repo's install.sh. Produces sunrise clips, Four Seasons
  timelapse, moon-track, and monthly moon-phase images.

frigate-audio (cameras/docker):
  Full stack from outis1one/frigate_w_audio: Frigate 0.17 NVR +
  Mosquitto MQTT broker + frigate-notify → ntfy push alerts. Audio-ready
  config template with face recognition and LPR pre-configured. Prompts
  for camera credentials, media storage path (supports drive detection),
  MQTT password (auto-generated), and ntfy server. Bootstraps the
  Mosquitto passwd file. Detector choice: CPU / USB Coral / PCIe Coral.
  Hardcoded media path from upstream replaced with a configurable prompt.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 21:40:49 +00:00
Claude 1d4b38674d feat(extras): add sync-cc service — Whisper/ffsubsync subtitle tool
Adds sync_cc as an extras service module:
- extras/sync_cc.py: the Python tool (3196 lines) — 8 modes: SYNC,
  GENERATE, BATCH, RENAME (TMDB), EXTRACT, REMUX, EMBED, BURNSUBS
- services/sync-cc.sh: installs system deps (python3, ffmpeg, mkvtoolnix,
  ccextractor), pip installs openai-whisper + ffsubsync, copies the script
  to ~/sync-cc/, prompts for TMDB API key → .env, creates /usr/local/bin/sync-cc
  wrapper so users run it from any directory containing video/SRT files

Heavy optional deps (easyocr, pgsreader) are installed on first use by the
script itself. GPU (CUDA/MPS) is used automatically if detected.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 21:36:22 +00:00
Claude a63f72ef17 feat(minecraft): port whitelist import + VT share links + pause from standalone
Three improvements ported from the standalone setupminecraft.sh:
- Whitelist: detect existing whitelist.json on re-run, offer to import
  players by number (0=all, comma list, Enter=skip), no UUID re-lookup
  for already-resolved entries; new gamertags still looked up via Mojang API
- Vanilla Tweaks: add vanillatweaks.net pre-configured share links at the
  top of the download instructions section (datapacks + crafting tweaks)
- Vanilla Tweaks: pause with "Press Enter when datapacks are in
  datapacks-download/" so user can SCP the ZIP before the build starts

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 21:32:39 +00:00
Claude cd59549e39 chore: add versioned snapshot setup_v0.9.5.sh, reset VERSION to 0.9.5
Introduces the versioned-snapshot naming convention: each release creates
a new setup_v<X.Y.Z>.sh file alongside the live setup.sh; old snapshots
are never removed. Resets VERSION from 1.0.0 to 0.9.5.

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 19:24:23 +00:00
Claude d5941f2b26 feat: parity milestone — add linux-to-sync, mark v1.0.0
Every service from ubuntu-post-install-24.04-crowdsec.sh is now a module.
35 services across 8 categories; setup.sh is the primary install path.

- services/linux-to-sync.sh (extras): clone private repo via SSH or PAT
- setup.sh: is_installed case for linux-to-sync (~/.git marker)
- MODULAR.md: migration table updated to show full inventory
- VERSION: 0.9.11 → 1.0.0 (parity achieved)

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 18:33:04 +00:00
Claude 2210dd4bed feat: add utilities + cameras batches (v0.9.11)
Utilities (8 modules):
- mealie: recipe manager, port 9925
- actualbudget: personal finance, port 5006
- traccar: GPS tracking, ports 8082 + 5000-5150 device protocols
- fmd: Android FindMyDevice server, random admin password, port 8084
- ddclient: dynamic DNS, config template, default start=n
- wg-easy: WireGuard VPN+UI, auto-detects public IP, random password
- meshcentral: remote device management, hostname prompt, ports 4430+4433
- magicmirror: smart mirror, 1-3 instances, MMM-* module auto-clone

Cameras (2 modules):
- frigate: AI NVR, auto-enables /dev/dri, starter config.yml, default start=n
- frigate-notify: Frigate push alerts, auto-detects local Frigate+ntfy, no web UI

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 18:30:58 +00:00
Claude a36f058a51 feat(media): add 6 media service modules (v0.9.10)
Migrate the full media batch from the monolith:

- jellyfin: auto-VAAPI on /dev/dri/renderD128 + render GID; DLNA/discovery UDP ports
- emby: UID/GID baked at install; HW transcoding block commented for manual opt-in
- audiobookshelf: separate audiobooks + podcasts paths; port 13378
- arm: optical drive detection; privileged:true; split movies/music output; port 8080
- lyrion: network_mode:host for Chromecast/Squeezebox UDP discovery; port 9000
- immich: multi-container stack (server+ML+valkey+postgres); two library strategies
  (unified with import-photos.sh helper, or external read-only); port 2283

https://claude.ai/code/session_01Y4dMKtkqkpvmgDKoRdzhTG
2026-06-03 18:24:02 +00:00
Claude 527808d610 feat(extras): add silent-send module + new extras category
Adds services/silent-send.sh — installs the Silent Send browser extension
(client-side PII redaction for AI chat). Non-docker module: installs git +
Node.js >=18 (NodeSource) + npm, clones outis1one/silent-send to ~/silent-send,
runs npm install (readies web-ext for Firefox build/sign), optionally builds a
signed Firefox .xpi, and prints per-browser load/build instructions. README
written to the checkout.

Introduces a new 'extras' category for non-docker add-ons pulled from other
repos, wired into setup.sh CATEGORY_ORDER (gaming -> extras -> backup) with an
is_installed marker. MODULAR.md groups list updated.

Bumps version to 0.9.9.
2026-06-03 18:11:07 +00:00
Claude d9b19b5f56 feat(gaming): add wolf-pair module — browser PIN form for Moonlight pairing
Adds services/wolf-pair.sh (gaming group, port 8090). Builds a tiny
python:3.12-alpine container from server.py + Dockerfile (both baked
into the script) that reads Wolf's docker logs for the current pairing
secret and serves a PIN entry form. Runs with network_mode: host so
localhost:47989 (Wolf's /pin/ API) is reachable; docker socket mounted
read-only for log access.

Replaces the ./manage.sh pin CLI workflow: visit the URL, type the PIN.
Optional Caddy subdomain, UFW port 8090, README in ~/docker/wolf-pair/.

Bumps version to 0.9.8.
2026-06-03 17:52:19 +00:00
Claude b619733a61 Add HANDOFF.md — migration status, taxonomy, wolf-pair open item
Status snapshot at v0.9.7 for continuing in a new session: module status by
category, final taxonomy, the module contract/conventions, verification steps,
and the open wolf-pair item (awaiting server.py + Dockerfile upload).

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 17:35:50 +00:00
Claude 9dc8c4063d v0.9.7: Caddy + CrowdSec modules; category menu with required-gate
- services/caddy.sh (homelab): reverse proxy + auto HTTPS, own ~/docker/caddy
  folder (compose + starter Caddyfile + README).
- services/crowdsec.sh (homelab): system-level IPS (agent + firewall bouncer +
  Caddy acquisition + optional ntfy alerts), README in ~/docker/crowdsec.
- setup.sh guided flow redesign:
  * Prints REQUIRED set (essentials + glow + docker check) with a cancel option.
  * Offers Caddy first (most services proxy through it).
  * Category menu LOOP: pick category -> checklist ([installed] marked) ->
    install -> back to menu, until Done. whiptail + text fallback.
- Categories reorganized: base/homelab/utilities/media/cameras/gaming/backup;
  moved ntfy/filebrowser/portainer/uptimekuma/watchtower to utilities;
  caddy->crowdsec->authelia ordered first in homelab.

Verified: bash -n all; --list groups by category with caddy first; cancel path
prints 'Cancelled, nothing changed'; dry-run guided flow runs required + loops
menu; run-one still works.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 17:16:32 +00:00
Claude 4a37b3622d v0.9.6: README generation + migrate authelia + 5 services
- lib/common.sh: add write_readme helper. Every module now writes a README.md
  into its ~/docker/<service>/ folder (self-documenting service folders).
- services/authelia.sh: SSO + 2FA portal, ported from the authelia-setup repo +
  the monolith's working block (secrets + Argon2 hash generation, caddy_net,
  Caddyfile forward-auth snippet + portal block, README). Guards against
  clobbering an existing install.
- services/{filebrowser,ntfy,uptimekuma,portainer,watchtower}.sh: mechanical
  migrations from the monolith, each with a README. Ports 8085/8090/3001/9443/—.

All pass bash -n; ./setup.sh --list shows them under homelab; dry-run run-one
exits 0 for each with real commands guarded.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 17:01:14 +00:00
Claude d4109839fc v0.9.5: port Minecraft to a per-service-folder module
services/minecraft.sh — full port of the standalone setupminecraft.sh into the
modular system. Each instance is its own ~/docker/<name>/ with a standalone
compose (multi-server via port auto-bump). Preserves flavour choice, the live
Modrinth version/mod picker, Vanilla Tweaks datapacks, whitelist UUID
pre-population, LuckPerms bootstrap, Chunky pre-gen, playit.gg tunnel, generated
networking/client docs, and the client-mods web page. Fixes the original's
env-block trailing-newline YAML bug. Selkies/manage.sh/setup-backup hand-offs
removed (points at 'sudo ./setup.sh backup').

Verified: bash -n; ./setup.sh --list shows minecraft under GAMING; dry-run
exits 0 with early return; generated compose validates.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 16:42:45 +00:00
Claude 840566e3f8 v0.9.4: gaming modules (wolf, js99er), backup module, versioning
- services/wolf.sh (gaming): Games-on-Whales Wolf / Moonlight, per-service
  folder ~/docker/wolf, wolf-pair dropped, manage.sh pin workflow kept.
- services/js99er.sh (gaming): TI-99/4A emulator, own folder, port 8099,
  Selkies launcher tie-in removed.
- services/backup.sh: Kopia encrypted backups, paths adapted to ~/docker.
- Start versioning: VERSION (0.9.4), CHANGELOG.md, setup.sh --version flag.

All modules pass bash -n; ./setup.sh --list groups base/homelab/gaming/backup;
dry-run run-one exits 0 for every module with real commands guarded.

Note: minecraft module deferred to 0.9.5 (port hit a session limit).

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 16:25:25 +00:00
Claude d7b9f935c2 Add modular setup framework (lib + services + dispatcher) and glow
Introduce the modular post-install structure chosen for reconciling 'one
source of truth' with 'run just the service I want':

- lib/common.sh: shared helpers (logging, prompts, ownership, Caddy wiring) and
  a service registry. Single implementation of each helper.
- setup.sh: dispatcher — interactive menu, run-one (./setup.sh <name>), --list,
  --dry-run, --unattended. Sources lib + services/*.sh (self-registering).
- services/base.sh: essential CLI packages incl. glow (Charm apt repo).
- services/homeassistant.sh: first migrated service (bridge/host networking,
  trusted_proxies, Caddy integration).
- MODULAR.md: architecture, how to add a module, migration status.
- Groups: base/homelab/gaming/backup. Gaming group makes this a base for
  homelab OR gaming boxes.

Also add glow as a default app to the live -crowdsec scripts' essential
packages so it's installed today regardless of entry point.

Verified: bash -n on all new files; ./setup.sh --list groups services;
dry-run run-one routes correctly.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 12:57:12 +00:00
Claude d528cfbea3 Home Assistant: prompt for bridge vs host networking
Let the user choose Home Assistant's networking mode at install time in the
-crowdsec variants:
- Bridge (default): publishes port 8123, works behind Caddy, isolated.
- Host: shares the host network for LAN device auto-discovery (Cast, HomeKit,
  mDNS/Zeroconf, some Zigbee/Z-Wave/Bluetooth).

The compose file is generated conditionally; both modes verified to produce
valid YAML, and both scripts pass 'bash -n' and a --dry-run --unattended pass.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 12:25:15 +00:00
Claude 8f6523a47b Add Home Assistant to CrowdSec variants
Add Home Assistant (home-automation hub, port 8123) to the -crowdsec scripts
for 24.04 and 26.04, following the existing service pattern (menu entry,
detection, defaults, parse, uninstall, install block, UFW rule, Caddy template).

- Image ghcr.io/home-assistant/home-assistant:stable, config volume, privileged
  + /run/dbus for hardware integrations; documents host-networking alternative
  for full mDNS/device discovery.
- Pre-seeds config/configuration.yaml with default_config + http.trusted_proxies
  (only on a fresh install) so HA works behind the Caddy reverse proxy without
  the usual 400 'request from reverse proxy' error.
- Integrates with configure_caddy_for_service (subdomain 'home').

Added only to the -crowdsec tier (current tip); original and -no-keycloak
scripts stay frozen as the evolution record. Both variants pass 'bash -n' and a
--dry-run --unattended pass (exit 0), including with Home Assistant forced on.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 12:20:36 +00:00
Claude b6af49f1f1 Add optional ntfy ban alerts to CrowdSec variants
When configuring CrowdSec, optionally wire up an ntfy push notification via
CrowdSec's HTTP notification plugin: writes /etc/crowdsec/notifications/ntfy.yaml
and references it from the default profile in profiles.yaml. Alerts fire on a
ban decision (after repeated failed attempts), not on every failed login.

Document the behavior in SCRIPT-VARIANTS.md, including why Authelia (email-only)
doesn't cover failed-login push. Both crowdsec variants verified with 'bash -n'
and a --dry-run --unattended pass (exit 0).

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 12:05:13 +00:00
Claude 7cf82d5d28 Add no-keycloak and CrowdSec script variants; restore originals
Provide three tiers of the install script for both 24.04 and 26.04:

- Originals (ubuntu-post-install-24.04.sh / -26.04.sh): restored to their
  true original state, with Keycloak intact, as a fallback baseline. (This
  reverts the in-place Keycloak removal from the previous commit; the cleanup
  now lives in the -no-keycloak variants instead.)
- -no-keycloak.sh: Keycloak fully removed, Authelia as the SSO/2FA option.
- -crowdsec.sh: builds on -no-keycloak and replaces fail2ban entirely with
  CrowdSec (SSH via auth.log/sshd collection, Caddy via caddy collection + log
  acquisition, firewall bouncer for enforcement, plus geo-blocking and
  community IP-reputation blocklists).

Add SCRIPT-VARIANTS.md documenting the three tiers and how the Authelia /
fail2ban / CrowdSec security layers differ.

All variants pass 'bash -n'.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 11:34:43 +00:00
Claude f564b4b6d8 Remove Keycloak; standardize on Authelia for SSO
Keycloak never reliably ran (fiddly reverse-proxy/hostname config) and the
repo has standardized on Authelia for SSO + 2FA. This rips Keycloak out
entirely:

- Delete the install block, whiptail menu entry, uninstall plumbing, and
  EXISTING_SERVICES detection from both 24.04 and 26.04 scripts
- Delete docker-compose-keycloak.yml, fix-keycloak-proxy.sh, and
  KEYCLOAK-SETUP-GUIDE.md
- Remove the Keycloak block from caddy-setup-helper.sh
- Update docs (CADDY-FAIL2BAN-SETUP.md, SECURITY-IMPROVEMENTS.md,
  NEW-SCRIPT-STRUCTURE.md, SCRIPT-FLOW-INTRO.txt) to reference Authelia

Also documents the fail2ban/Authelia overlap: Authelia handles failed-login
regulation (per-account lockout); the Caddy fail2ban jail is complementary
firewall-level IP banning. Neither does geo-blocking — noted CrowdSec / Caddy
GeoIP as the path for that.

https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
2026-06-03 03:44:26 +00:00
Claude a8dd0d78dd Install Caddy before Authelia so Caddyfile exists at Authelia setup time
Authelia's installer auto-injects the (authelia) snippet and auth portal
block into the Caddyfile. Moving Caddy first means that injection works
in a single fresh install run without manual follow-up.

https://claude.ai/code/session_01FvqXSZyk3g7rUombwLcprZ
2026-06-02 18:44:15 +00:00
Claude 49f91ac9c0 Fix Authelia authentication_backend config for 4.38+ format
The working authelia-setup repo uses the Authelia 4.38+ password
hashing config format with a nested argon2 block and variant key.
The previous version used the old flat format which is rejected by
Authelia 4.39.20 validation. Fix both 24.04 and 26.04 scripts.

  Before (broken):
    password:
      algorithm: argon2id
      iterations: 3
      ...

  After (correct for 4.38+):
    password:
      algorithm: argon2
      argon2:
        variant: argon2id
        iterations: 3
        ...

https://claude.ai/code/session_01FvqXSZyk3g7rUombwLcprZ
2026-06-02 17:56:39 +00:00
Claude 9e353eb921 Sync 24.04 and 26.04 scripts: rename, Authelia, NetBird SSH
- Rename ubuntu-post-install.sh → ubuntu-post-install-24.04.sh to match 26.04 naming convention
- Add --allow-server-ssh systemd override to 24.04 NetBird install (already in 26.04)
- Add full Authelia install block to 26.04 (matching what was added to 24.04)
  - Whiptail menu, uninstall, detection, default vars, parse flags, install block
- Both scripts now identical in Authelia and NetBird SSH behavior

https://claude.ai/code/session_01FvqXSZyk3g7rUombwLcprZ
2026-06-02 17:52:25 +00:00
Claude db8e83447a Add working Authelia SSO install based on authelia-setup repo
Ports the full working configuration from outis1one/authelia-setup:
- Authelia 4.39.20 on caddy_net with secrets via env var files
- Generates jwt/session/storage secrets with openssl at install time
- Prompts for domain, admin user, SMTP settings, timezone
- Generates argon2id password hash via Docker during install
- Writes configuration.yml, users.yml, docker-compose.yml, .env
- Auto-injects (authelia) snippet + auth portal block into Caddyfile
- Creates caddy_net Docker network if missing
- Adds Authelia to whiptail service menu, uninstall list, and detection
- Adds Authelia snippet as commented example in new Caddyfile template

https://claude.ai/code/session_01FvqXSZyk3g7rUombwLcprZ
2026-06-02 17:43:35 +00:00
Claude d790d09295 Persist --allow-server-ssh in netbird systemd override
Without --allow-server-ssh, NetBird prompts for re-authentication on
every SSH connection. This adds a systemd drop-in override at
/etc/systemd/system/netbird.service.d/ssh-server.conf so the flag
is set automatically on every boot without manual intervention.

https://claude.ai/code/session_017jFG5YuHf2CCGS5HiheoeM
2026-06-01 21:51:34 +00:00
Claude afb5d22d2e Update NetBird SSH for v0.60.0+ breaking change in 26.04 script
NetBird v0.60.0 removed the built-in SSH server ('netbird ssh <peer-name>').
SSH now routes through standard openssh-server via a drop-in config at
/etc/ssh/sshd_config.d/99-netbird.conf on port 22022.

- Ensure openssh-server is installed and enabled when NetBird is selected
- Remove all 'netbird ssh <peer-name>' references
- Update instructions: connect via 'ssh user@<netbird-ip>' using netbird status
- Note the dashboard step: Peers > [peer] > SSH to enable per-peer SSH access
- Applied across install section, SSH summary, and next-steps section

https://claude.ai/code/session_017jFG5YuHf2CCGS5HiheoeM
2026-06-01 21:49:06 +00:00
Claude 8a276337ab Add ubuntu-post-install-26.04.sh for Ubuntu 26.04 LTS (Resolute Raccoon)
Based on the 24.04 script with the following updates:
- Updated all version references from 24.04 to 26.04
- Fixed Tailscale APT repo from hardcoded 'jammy' to 'resolute' codename
  (was a latent bug even on 24.04; jammy is 22.04)
- All other repos (Docker, Kopia, NodeSource) already use dynamic
  VERSION_CODENAME detection and work as-is on 26.04

https://claude.ai/code/session_017jFG5YuHf2CCGS5HiheoeM
2026-06-01 20:43:24 +00:00
Claude 947d9597e6 Require Node.js >= 20 for Immich CLI; install Node 22 LTS from NodeSource
The Immich CLI uses the File global class which requires Node.js v20+.
The script previously fell back to apt install nodejs which gives v18 on
Ubuntu and fails with "ReferenceError: File is not defined".

Now checks the Node.js major version first. If < 20, offers to install
Node.js 22 LTS from NodeSource before proceeding.

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 07:15:51 +00:00
Claude d3d887a548 Fix Immich docker-compose: update DB image, create marker dirs, remove broken healthcheck
- Update database image from deprecated tensorchord/pgvecto-rs:pg14-v0.2.0
  to ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
- Remove database command block (vectors.so) that blocks VectorChord from
  loading — the new image handles shared_preload_libraries internally
- Remove bogus healthcheck using non-existent googlechecksum function
- Create required subdirectories (thumbs, upload, backups, library, profile,
  encoded-video) with .immich marker files before first start — fixes
  ENOENT crash on encoded-video/.immich
- Update Valkey from 8-bookworm to 9-bookworm
- Fix status output: show UPLOAD_LOCATION instead of unset PHOTOS_DIR
  for external library strategy

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 06:56:48 +00:00
Claude 791c9a3c47 Fix YAML syntax error in Immich docker-compose templates
The healthcheck test value contained "googlechecksum: $$Chksum"
which YAML interprets as a mapping separator (colon-space in an
unquoted scalar). This caused "mapping values are not allowed in
this context" on the command line below it.

Fixed by using >- block scalar for the healthcheck test and
multi-line array format for the postgres command, matching the
official Immich docker-compose format.

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 06:27:32 +00:00
Claude b591f44626 Skip already-configured services on rerun, respect whiptail selection
Three issues fixed:

1. SSH/VPN/Remote Desktop rerun detection: When services are already
   configured, ask a single "Reconfigure?" question instead of
   prompting through every individual service again.

2. Whiptail selection respected: When user selects specific services
   in the whiptail menu, skip all unrelated sections (linux-to-sync,
   Caddy Legacy, Kopia, local backup, cloud backup, UFW) instead of
   prompting for each one.

3. Import-photos.sh reminder: Clarify that import-photos.sh should
   be run AFTER the main setup script completes, not during.

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 06:16:03 +00:00
Claude 28896fd194 Add progress feedback to import-photos.sh scan step
The find command to count photos can take a long time on large
collections or slow mounts. Added visible output so it doesn't
look like the script hung.

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 05:24:32 +00:00
Claude 0058af3242 Make apt upgrade optional; simplify Immich photo library prompts
- apt upgrade at end of script now prompts (default: no) instead of
  running unconditionally. This prevents unwanted package upgrades
  when running the script just to install a new service.

- Immich setup: ask "existing photos?" first (default: no) so fresh
  installs only get one path question. Strategy choice and path prompts
  now only appear when relevant to the chosen strategy.

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 05:00:18 +00:00
Claude 99a6843010 Ask strategy before photo location in Immich setup
The user should decide *what* they want (import vs external library)
before being asked *where* their photos are. The "what" frames the
context for the "where" question.

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 04:24:12 +00:00
Claude 5c37d23788 Clean up post-setup instructions: one step for import path
The import-photos.sh script creates the admin account via API, so
"Open browser and create admin account" is no longer needed for the
import path. Post-setup is now just:

  Import path (Strategy 1 + existing photos):
    "Run ~/docker/immich/import-photos.sh" — one step, no browser

  External library path (Strategy 2):
    Still requires web UI for library creation (3 steps)

  No existing photos:
    Still requires web UI for storage template (2 steps)

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 04:14:37 +00:00
Claude 89c484e0f2 Fully automate Immich import: account creation, API key, and upload
The import-photos.sh helper script now handles the entire setup flow
without requiring any manual web UI interaction:

1. Checks if Immich is initialized via /api/server/config
2. If uninitialized: creates admin account via /api/auth/admin-sign-up
   (prompts for email, password, name)
3. If already initialized: prompts for existing credentials
4. Logs in via /api/auth/login to get bearer token
5. Creates API key via /api/api-keys automatically
6. Configures storage template via /api/system-config (PUT)
7. Installs immich-cli (checks immich → npx → npm → offers apt install)
8. Runs recursive upload with EXIF date preservation

Also accepts an API key as argument to skip account setup for re-runs.

Fixes:
- Removed -f flag from curl calls that suppressed error details
- Fixed $? check after login (now uses if ! command pattern)
- Variable naming collision (INSTALL_NODE → INSTALL_NODE_YN)
- Post-setup instructions now just say "run the import script"
  instead of listing manual steps

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 04:10:17 +00:00
Claude ee145dc736 Add automated import-photos.sh helper script for existing photos
When Strategy 1 (unified library) is chosen with existing photos, the
setup now generates an import-photos.sh script that automates the entire
import process:

- Verifies Immich is running (API health check)
- Prompts for API key with validation
- Configures the storage template via API automatically (uses python3
  for JSON manipulation, falls back to manual instructions)
- Installs immich-cli via npx if Node.js available, offers to install
  Node.js if not
- Runs the upload with --recursive from the baked-in source path
- Shows photo count and progress

Also:
- Ask where existing photos currently live (separate from library path)
- Use that path for both the external library mount (Strategy 2) and
  the import script source (Strategy 1)
- Post-setup instructions reduced to 3 steps: create account, get API
  key, run import script
- .env comments reference the import script instead of raw CLI commands

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 03:23:15 +00:00
Claude 430a30ca18 Rework Immich setup UX with strategy-based photo library flow
Replace the confusing two-prompt (upload/external) configuration with a
cohesive strategy-based flow:

- One question for photo library path instead of two separate prompts
- Ask if user has existing photos, then present two clear strategies:
  [1] Import everything into Immich (unified library, recommended)
  [2] Keep existing photos in place (external library, read-only)
- Generate strategy-specific docker-compose.yml (no unused external
  mount when not needed)
- Strategy-specific .env files with relevant instructions only
- Fix nesting issue: external library uploads now go to sibling dir
  instead of subfolder (prevents duplicate scan)
- Unified post-setup instructions that match chosen strategy

https://claude.ai/code/session_01NAtxAkC5t6YVb3gcP1VcX8
2026-02-19 02:37:02 +00:00
Claude 3620a3adf0 Improve fix-keycloak-proxy.sh to handle existing .env files
- Check for existing .env file instead of extracting from docker-compose
- Replace KC_PROXY with KC_PROXY_HEADERS in .env
- Add KC_PROXY_HEADERS if missing
- Remove KC_PROXY from docker-compose.yml if present
- Show current configuration before restart
- Handles both migration scenarios:
  1. Old config with KC_PROXY in .env
  2. Existing .env without proxy settings
2026-01-13 04:34:46 +00:00
Claude b4cb82c0d7 Make fix-keycloak-proxy.sh executable 2026-01-13 03:40:18 +00:00
Claude 736c53b1db Update Keycloak to use v2 proxy headers (KC_PROXY_HEADERS)
- Replace deprecated KC_PROXY=edge with KC_PROXY_HEADERS=xforwarded
- Fixes 'Hostname v1 options [proxy] are still in use' warning
- Convert docker-compose-keycloak.yml to use .env file
- Remove hardcoded passwords from docker-compose.yml
- Add comprehensive .env template in comments
- Update deployment instructions and production checklist
- Resolves CORS and secure context warnings
- All credentials now in .env with proper security
2026-01-13 03:39:08 +00:00
Claude 6098bbc209 Add Keycloak proxy configuration fix script
- Fixes deprecated KC_PROXY warning
- Updates to KC_PROXY_HEADERS=xforwarded (v2)
- Migrates credentials to .env file
- Preserves existing passwords
- Automatic backup and restart
- Resolves 'Hostname v1 options [proxy] are still in use' warning
2026-01-13 03:36:54 +00:00
Claude ccb145103f Fix Docker ownership, Keycloak security, and .env file management
This comprehensive update addresses multiple security and usability issues:

## Docker Directory Ownership
- Added ensure_docker_dir_ownership() helper function
- Applied to ALL 25+ services (Immich, Keycloak, ActualBudget, Jellyfin,
  Emby, ARM, FileBrowser, MagicMirror, Lyrion, Mealie, Minecraft, Frigate,
  ntfy, Uptime Kuma, wg-easy, Traccar, Portainer, MeshCentral, FindMyDevice,
  Frigate-Notify, Watchtower, Kopia, Caddy)
- Fixed disaster recovery path (line 309) to set ownership
- Docker folders now owned by sudo user, not root
- Users can run docker commands without sudo

## Keycloak Security Improvements
- Implemented password validation with retry loop
- Password requirements: 12+ chars, alphanumeric only (no special chars)
- Auto-generate secure passwords by pressing ENTER
- Moved all credentials to .env file (no passwords in docker-compose.yml)
- Added production vs development mode selection
- Production mode uses 'start' command with hostname configuration
- Development mode uses 'start-dev' for testing only
- Proper KC_HOSTNAME configuration for public deployments
- Interactive prompts with clear security warnings

## Environment Variable Management
- ActualBudget now uses .env file for configuration
- Keycloak uses .env for admin and database passwords
- Consistent .env pattern across services
- Passwords no longer visible in docker-compose files
- Easier credential management and rotation

## Helper Functions
- ensure_docker_dir_ownership(): Fix ownership recursively
- generate_password(): Generate secure alphanumeric passwords
- validate_password(): Validate Keycloak-compatible passwords

## Documentation
- Added SECURITY-IMPROVEMENTS.md with comprehensive guide
- Password requirements and best practices
- Keycloak setup guide for ActualBudget on Pikapods
- Migration guide for existing services
- Troubleshooting section
- Verification checklist

## Integration Status
- Caddy2 reverse proxy: Already integrated via configure_caddy_for_service()
- fail2ban monitoring: Already configured with labels on all services
- HTTPS and security headers: Already implemented
- JSON logging for fail2ban: Already configured

All services now follow consistent patterns for ownership, credentials,
and security configuration. Script tested with bash -n for syntax errors.
2026-01-13 00:44:23 +00:00
Claude 7cdd9345b5 Implement global drive detection - detect once, use everywhere
MAJOR IMPROVEMENT: Drive detection now happens ONCE at startup and
is reused by all services, instead of each service detecting separately.

1. **New detect_drives() Function:**
   - Runs once before service selection menu
   - Scans ~/drives directory for all mounted drives
   - Shows drive name, path, size, used space, available space
   - Sets global variables for all services to use

2. **Global Variables Set:**
   - PRIMARY_DRIVE: name of first drive (e.g., "storage1")
   - PRIMARY_DRIVE_PATH: full path to first drive
   - DRIVES_DETECTED: true/false
   - DRIVES_DIR: base drives directory
   - AVAILABLE_DRIVES_COUNT: number of drives

3. **Display Example:**
   ```
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
     DETECTED DRIVES
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

     ✓ storage1
       Path: /home/user/drives/storage1
       Size: 2.0T (Used: 800G, Available: 1.2T)

     ✓ backup
       Path: /home/user/drives/backup
       Size: 4.0T (Used: 1.5T, Available: 2.5T)

     Using 'storage1' as primary drive for default paths
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   ```

4. **Updated Services to Use Global Detection:**
   - Immich: photos/immich-uploads
   - AudioBookshelf: audiobooks
   - Emby: media
   - Jellyfin: media
   - ARM: ripped
   - FileBrowser: (root browse)
   - LMS: music

5. **Benefits:**
   - Detect drives only once (faster)
   - Consistent paths across all services
   - Shows actual drive information (size, usage)
   - Falls back to $HOME if no ~/drives exists
   - All services use PRIMARY_DRIVE_PATH variable

This fixes user complaint:
"There is no ~/drives.... it should detect which drives are already
 in ~/drives and offer to use one of those"
2026-01-12 18:05:49 +00:00
Claude de4bbf4711 Apply reconfigure fix to ActualBudget
- Added check_service_exists() to ActualBudget
- Now shows Skip/Reconfigure/Restart options
- Prevents accidental overwrite of existing configurations

Progress: 6/24 services complete (Immich, AudioBookshelf, Emby, ARM, FileBrowser, ActualBudget)
2026-01-12 17:54:08 +00:00
Claude 53f0101f9b Apply reconfigure fix to ARM and FileBrowser services
- Added check_service_exists() to ARM (Automatic Ripping Machine)
- Added check_service_exists() to FileBrowser
- Both now show Skip/Reconfigure/Restart options
- Prevents accidental overwrite of existing configurations

Progress: 5/24 services complete (Immich, AudioBookshelf, Emby, ARM, FileBrowser)
2026-01-12 17:52:47 +00:00
Claude 4a7dd2e654 Add helper function and apply reconfigure fix to key services
1. **Created check_service_exists() Helper Function:**
   - Reusable function to check if service exists
   - Shows options: Skip / Reconfigure / Restart
   - Handles backup automatically on reconfigure
   - Returns boolean flag to control installation flow
   - Reduces code duplication across services

2. **Applied Reconfigure Fix to Services:**
   - Immich (with drive detection)
   - AudioBookshelf
   - Emby

3. **How It Works:**
   ```bash
   check_service_exists "ServiceName" "$SERVICE_DIR" RECONFIGURE_FLAG
   if [ "$RECONFIGURE_FLAG" = "true" ]; then
       # Only run configuration if true
   fi
   ```

4. **Benefits:**
   - Consistent behavior across all services
   - Automatic backup before any changes
   - Safe default (Skip) protects existing configs
   - Easy to apply to remaining services

Next: Apply to remaining 20+ services (ActualBudget, Mealie, Jellyfin, etc.)
2026-01-12 17:46:43 +00:00
Claude bbaec6b86d Fix critical reconfigure bug - detect existing installations and skip reinstall
CRITICAL FIX: Script was reinstalling and reconfiguring services from scratch
when they were already installed, potentially breaking existing configurations.

1. **Detect Existing Installations:**
   - Check for existing docker-compose.yml before configuration
   - Show options: Skip / Reconfigure / Restart only
   - Default to Skip to preserve existing configs

2. **Skip/Reconfigure/Restart Options:**
   - Option 1: Skip (keep existing configuration)
   - Option 2: Reconfigure (backup existing, then reconfigure)
   - Option 3: Restart containers only (no reconfiguration)

3. **Automatic Backup on Reconfigure:**
   - Creates timestamped backup before any changes
   - Backup location: ~/docker/backups/YYYYMMDD-HHMMSS-servicename/
   - Full service directory backed up

4. **Fixed Drive Detection:**
   - Detects existing ~/drives directory
   - Lists all available drives to user
   - Uses detected drives in default paths
   - Changed from $HOME_DIR to $ACTUAL_HOME for correct paths
   - No more missing "/drives/primary/..." paths

5. **Drive Path Examples:**
   - Detects: ~/drives/storage1, ~/drives/backup, ~/drives/media
   - Shows: "Detected drives: storage1, backup, media"
   - Default becomes: ~/drives/storage1/photos/immich-uploads

Applied to: Immich (template for other services)

This fixes user issues:
- "I selected keep the items that were already installed, then it lead
  me to reinstall configure from scratch all those services"
- "It did not detect if the service was already in the Caddyfile"
- "it might have messed up what I already had"
- "There is no ~/drives...."
- "it should detect which drives are already in ~/drives and offer to
  use one of those"
2026-01-12 17:41:29 +00:00
Claude 671a59bf12 Add automatic Caddy configuration for services during installation
Implemented automatic Caddy reverse proxy configuration that runs
BEFORE each service is started, with backup, reload, and formatting.

1. **New configure_caddy_for_service() Function:**
   - Detects if Caddy is installed (skips if not)
   - Prompts user if they want to configure reverse proxy
   - Asks for domain/subdomain (e.g., photos.example.com)
   - Backs up Caddyfile with timestamp
   - Checks for existing configuration and offers to overwrite
   - Adds service block with security headers and fail2ban logging
   - Reloads Caddy configuration
   - Formats Caddyfile with `caddy fmt --overwrite`
   - Final reload after formatting
   - Shows final access URL (https://...)

2. **Configuration Sequence:**
   - Service docker-compose.yml created
   - Service .env configured
   - Caddy configuration added (if Caddy installed)
   - Caddy reloaded and formatted
   - Service containers started
   - All happens before `docker compose up -d`

3. **Integrated into Services:**
   - Immich (photos.example.com)
   - AudioBookshelf (audiobooks.example.com)
   - Emby (emby.example.com)
   - ActualBudget (budget.example.com)
   - Mealie (recipes.example.com)
   - Jellyfin (jellyfin.example.com)
   - Uptime Kuma (uptime.example.com)

4. **Caddy Configuration Includes:**
   - Automatic HTTPS via Let's Encrypt
   - Security headers (HSTS, X-Content-Type-Options, etc.)
   - JSON logging for fail2ban
   - Proper reverse_proxy to localhost:PORT

5. **Backup & Safety:**
   - Caddyfile backed up to: Caddyfile.backup.YYYYMMDD-HHMMSS
   - Existing configs detected and user can choose to overwrite
   - Reload errors show backup file path for restoration

6. **Commands Used:**
   - `docker exec caddy caddy reload --config /etc/caddy/Caddyfile`
   - `docker exec caddy caddy fmt --overwrite /etc/caddy/Caddyfile`

This addresses user request:
"new/reconfigured services are add to the Caddyfile as part of the
install/reconfigure before they are attempt to be brought up, as a
part of the install/reconfigure of the service? (With backup of
Caddyfile and docker exec -w /etc/caddy caddy caddy reload &&
docker exec -w /etc/caddy caddy caddy fmt --overwrite after each
addition to Caddyfile?)"
2026-01-12 17:08:11 +00:00
Claude 52a9617ffe Add uninstall functionality and improve existing server detection
Added comprehensive uninstall functionality to whiptail menu:

1. **Install/Uninstall Menu Choice:**
   - Added action menu: Install new services, Uninstall existing, or Cancel
   - Automatically detects existing services in ~/docker/

2. **Smart Service Detection:**
   - Scans for existing Docker services and marks them in the install menu
   - Install menu shows [*] for already-installed services
   - Helps users identify what's already running on their server

3. **Uninstall Functionality:**
   - Uninstall menu only shows services that are currently installed
   - All services selected by default for quick removal
   - Automatic backup before uninstall to ~/docker/backups/
   - Stops containers, removes directories, backs up data
   - Special handling for system packages (fail2ban)

4. **Improved Re-run Support:**
   - Script detects existing installations on startup
   - Can rerun on configured servers to add new services
   - Uninstall option allows cleanup of unwanted services
   - Backups ensure data safety during removals

Services Supported:
- All 24 Docker services (Immich, Keycloak, Caddy, etc.)
- System packages (fail2ban)
- Backups created with timestamp: YYYYMMDD-HHMMSS-servicename

Usage Examples:
- Fresh install: Select services to install
- Add services: Rerun script, existing services auto-selected
- Remove services: Choose "Uninstall", select what to remove
- Cleanup: All data backed up automatically

This addresses user request for:
- Ability to reinstall on current server
- Option to remove services from whiptail menu
- Better handling of existing installations
2026-01-12 14:36:34 +00:00
Claude 5c9850e2a6 Add documentation for planned script restructuring
Added planning documents for future script reorganization:

NEW-SCRIPT-STRUCTURE.md:
- Outlines two-phase structure (Essential Setup vs Service Selection)
- Documents plan to move optional services to whiptail menu
- Plans for uninstall functionality
- Re-run detection improvements

SCRIPT-FLOW-INTRO.txt:
- Proposed intro text for users
- Explains Phase 1 (required) and Phase 2 (optional)
- Documents re-running behavior

These are planning documents for future enhancements.
Current commit only implements the duplicate prompt fix.
2026-01-12 14:09:32 +00:00
Claude 974b07f51e Fix duplicate prompts after whiptail menu selection
Applied WHIPTAIL_USED flag check to all 25 service prompts that appear
after the whiptail menu to prevent services from being prompted
individually when they weren't selected in the checkbox menu.

This fixes the issue where services like AudioBookshelf were being
prompted even when not selected in whiptail.

Services fixed:
- AudioBookshelf, Emby, ARM, FileBrowser, Magic Mirror
- ActualBudget, Keycloak, Caddy, fail2ban
- Lyrion Music Server, Mealie, Minecraft, Jellyfin, Frigate
- ddclient, ntfy, Uptime Kuma, wg-easy
- Traccar, Portainer, MeshCentral Server
- FindMyDevice, Frigate-Notify, Watchtower

Pattern applied:
  if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_SERVICE" ]; then
      # Show prompt
  fi

This ensures prompts only appear when whiptail was not used OR
the service variable is not yet set.
2026-01-12 14:08:41 +00:00
Claude 9bde91dfb9 Fix whiptail menu resetting variables and causing duplicate prompts
CRITICAL FIX:
The whiptail menu was OVERWRITING all service variables with "n",
which caused duplicate prompts and ignored user's earlier selections.

BEFORE (broken):
- User answers y/n prompts
- Whiptail menu appears
- Whiptail sets INSTALL_IMMICH="n" (overwrites previous "y")
- Individual prompt appears again (because variable check fails)
- User gets prompted twice for same service!

AFTER (fixed):
- Variables only set to "n" if not already set
- Uses bash parameter expansion: : ${VAR:="default"}
- Preserves any earlier choices
- Whiptail menu updates to "y" if selected
- Individual prompts skip if variable already set
- No duplicate prompts!

CHANGES:
Lines 2225-2249: Changed from direct assignment (VAR="n")
to conditional default (: ${VAR:="n"})

This preserves earlier choices while still allowing whiptail
to override them when services are selected.

SIDE EFFECT FIXED:
- Containers now start properly
- No more "containers won't come up" issue
- Proper dependency order maintained
2026-01-12 04:32:54 +00:00
Claude 9d1cbadce9 Fix SSH prompt and add automatic Caddy configuration for Keycloak
FIXES:
1. SSH key import now properly accepts "n" as answer
   - Added y/n prompt before asking for usernames
   - Clearer flow: "Import SSH keys?" → "Which service?"
   - No more confusion about entering "n" vs leaving blank

2. Automatic Caddy configuration for Keycloak
   - Detects if Caddy is installed or being installed
   - Offers to configure Caddy reverse proxy for Keycloak
   - Backs up Caddyfile before changes
   - Adds Keycloak configuration automatically
   - Reloads Caddy after adding configuration
   - Keycloak starts AFTER Caddy is configured
   - Prevents "container won't come up" issue

CADDY AUTO-CONFIGURATION:
When both Keycloak and Caddy are selected:
- Script asks: "Configure Caddy reverse proxy for Keycloak?"
- Prompts for domain (e.g., auth.yourdomain.com)
- Backs up existing Caddyfile
- Adds Keycloak block with:
  * JSON logging for fail2ban
  * Reverse proxy to localhost:8180
  * Security headers (HSTS, X-Frame-Options, etc.)
- Formats and reloads Caddy
- Confirms Keycloak will be available at domain

This ensures correct startup order: Caddy configured → Caddy reloaded → Keycloak starts
2026-01-12 04:30:58 +00:00
Claude 4c69294c65 Add comprehensive Keycloak setup guide and external service support
KEYCLOAK-SETUP-GUIDE.md:
Complete manual explaining Keycloak concepts, manual setup, and external services

WHAT'S A REALM:
- Isolated container for users/clients/config
- Like a "company" or "organization"
- master realm = admin only
- homelab realm = your actual users
- Fully isolated from each other

WHAT'S AN OAUTH2 CLIENT:
- Each service (ActualBudget, etc.) is a "client"
- Needs Client ID, Secret, and Redirect URIs
- Redirect URIs must match EXACTLY
- Guide explains the authentication flow

MANUAL SETUP INSTRUCTIONS:
- Step-by-step via web UI
- Create realm manually
- Create OAuth clients manually
- Configure redirect URIs
- Create users and set passwords
- Test the setup

EXTERNAL SERVICE SUPPORT (Pikapod, etc.):
Script now asks about setup type:
1. Local only (http://localhost)
2. Public domain (https://yourdomain.com)
3. Both local and public

For external services:
- Prompts for your public domain
- Warns that Keycloak MUST be accessible at https://auth.yourdomain.com
- Checks if Caddy/DNS are configured
- Asks for external service URL (e.g., Pikapod)
- Configures redirect URIs for all scenarios

REDIRECT URIS NOW INCLUDE:
- http://localhost:5006/* (local dev)
- https://budget.yourdomain.com/* (self-hosted)
- https://actualbudget-abc.pikapod.net/* (external)
- Multiple patterns for flexibility

SAVED CONFIG FILES UPDATED:
- Shows LOCAL DEVELOPMENT URLs
- Shows PRODUCTION URLs (if public domain set)
- Shows EXTERNAL SERVICE URLs (if external service set)
- Lists all configured redirect URIs
- Clear instructions for each scenario

CADDY CONFIGURATION GUIDE:
- How to configure DNS A/CNAME records
- Caddyfile example for Keycloak
- Security headers included
- Step-by-step setup for external access

RECONFIGURATION SUPPORT:
- Guide explains how to add realms manually
- Guide explains how to add clients manually
- CLI examples for adding realms/users/clients
- Can re-run script to configure additional realms

COMMON USE CASES:
1. All local services
2. Self-hosted with domain
3. Mixed (local + external like Pikapod)

Each use case explained with complete examples

TROUBLESHOOTING:
- Invalid redirect URI
- Client not found
- Invalid client secret
- External service can't reach Keycloak
- CORS/redirect failures
- Admin console login issues

With this update, users can:
 Understand what Keycloak is and how it works
 Configure it manually if they prefer
 Use it with external services like Pikapod
 Set up proper DNS/Caddy for production
 Troubleshoot common issues
 Add realms and clients later
2026-01-11 23:56:55 +00:00
Claude 29f49f0ec3 Add automated Keycloak initial configuration
Keycloak is now fully configured and ready to use immediately after installation!
No more manual realm/client setup required.

AUTOMATED SETUP:
After Keycloak starts, the script automatically:
1.  Waits for Keycloak to be fully ready (health check)
2.  Logs in using Keycloak Admin CLI (kcadm.sh)
3.  Creates a new realm (e.g., "homelab")
4.  Creates OAuth2/OIDC client for ActualBudget (if selected)
5.  Creates generic OAuth2 client template for other services
6.  Optionally creates an initial user
7.  Saves all OAuth credentials to text files
8.  Provides clear next steps

OAUTH2 CLIENT FOR ACTUALBUDGET:
- Client ID: actualbudget
- Auto-generated secure client secret
- Pre-configured redirect URIs for localhost and production
- Saved to: ~/docker/keycloak/actualbudget-oauth.txt
- Includes all URLs needed to configure ActualBudget

GENERIC OAUTH2 CLIENT:
- Client ID: generic-app
- Can be cloned for other services
- Saved to: ~/docker/keycloak/generic-oauth.txt
- Works as a template

INITIAL USER CREATION:
- Prompts for username, email, first name, last name, password
- User is immediately active and can log in
- Can be used for ActualBudget and other services right away

SAVED CONFIGURATION FILES:
~/docker/keycloak/actualbudget-oauth.txt - ActualBudget OAuth config
~/docker/keycloak/generic-oauth.txt - Generic OAuth template

PRODUCTION READY:
- Redirect URIs include both localhost and production domains
- Works with Caddy reverse proxy
- SSL/TLS enforced at proxy level
- Just update domain in configuration

USER EXPERIENCE:
Install Keycloak → Answer prompts → DONE!
- Realm created: "homelab" (or custom name)
- OAuth clients ready
- User created and can log in immediately
- Just go to http://localhost:8180/admin to manage

This eliminates the complex post-install Keycloak setup and makes it
immediately usable for ActualBudget and other services!
2026-01-11 23:41:32 +00:00
Claude 3ff80aee94 Add whiptail service selection menu for Docker applications
Users now get a nice checkbox menu to select which services to install,
instead of being prompted for each service one-by-one.

WHIPTAIL MENU:
- Displays all 24+ Docker services in a single checklist
- Use SPACE to select/deselect services
- Press ENTER to confirm and install selected services
- Falls back to individual prompts if whiptail not available

SERVICES IN MENU:
✓ Immich (Photo & Video Backup)
✓ AudioBookshelf (Audiobooks & Podcasts)
✓ Emby (Media Server)
✓ A.R.M. (Automatic Ripping Machine)
✓ FileBrowser (Web File Manager)
✓ Magic Mirror (Smart Mirror Display)
✓ ActualBudget (Personal Finance)
✓ Keycloak (Identity & Access Management)
✓ Caddy (Reverse Proxy with Auto-HTTPS)
✓ fail2ban (Intrusion Prevention)
✓ Lyrion (Music Streaming)
✓ Mealie (Recipe Manager)
✓ Minecraft (Game Server)
✓ Jellyfin (Free Media Server)
✓ Frigate (AI NVR for Cameras)
✓ Ntfy (Push Notifications)
✓ Uptime Kuma (Service Monitoring)
✓ WG-Easy (WireGuard VPN)
✓ Traccar (GPS Tracking)
✓ Portainer (Docker Web UI)
✓ MeshCentral (Remote Management)
✓ FindMyDevice (Device Tracking)
✓ Frigate-Notify (Frigate Notifications)
✓ Watchtower (Auto Container Updates)

WORKFLOW:
1. Run ubuntu-post-install.sh
2. Get whiptail menu for service selection
3. Select services with SPACE
4. Press ENTER to install
5. Script installs only selected services

FALLBACK:
- If whiptail not available, uses traditional prompts
- Prompts only appear if service wasn't selected in menu
- Fully backwards compatible

This dramatically improves UX for installing multiple services!
2026-01-11 23:32:45 +00:00
Claude 6d66441a69 Integrate Caddy and fail2ban into main ubuntu-post-install.sh script
Users can now install and configure everything by simply running the main script.
Re-running the script allows adding new services to existing installations.

NEW SERVICES IN MAIN SCRIPT:

CADDY WEB SERVER:
- Automatic HTTPS with Let's Encrypt
- Reverse proxy for all services
- Creates example Caddyfile with ActualBudget and Keycloak configs
- Detects existing installations (asks before reconfiguring)
- Automatically backs up existing Caddyfile before changes
- Pre-configured with /var/log/caddy volume for fail2ban integration
- Includes HTTP/3 support

FAIL2BAN INTRUSION PREVENTION:
- Automated installation via apt
- Creates Caddy filter for JSON logs (401, 403, 429 status codes)
- Creates Caddy jail with configurable settings
- Automatically creates /var/log/caddy directory
- Tests configuration before restart
- Verifies jail is active after restart
- Shows status and useful commands

FEATURES:
 Detects if services already exist (won't overwrite)
 Backs up configurations before changes
 Interactive prompts for all settings
 Validates configurations before applying
 Can be re-run to add services to existing setup
 Works alongside existing services
 Follows same pattern as ActualBudget/Keycloak

WORKFLOW:
1. Run ubuntu-post-install.sh
2. Select services to install (ActualBudget, Keycloak, Caddy, fail2ban, etc.)
3. Script handles everything automatically
4. Re-run anytime to add more services

The caddy-setup-helper.sh remains available as a standalone tool for
advanced configuration, but the main script is now the primary method.
2026-01-11 23:04:24 +00:00
Claude d3f412dc28 Make fail2ban setup fully automated with intelligent error handling
The caddy-setup-helper.sh script now handles everything automatically (after asking
for confirmation), only falling back to manual instructions if errors occur.

AUTOMATED WORKFLOW:
1.  Backup Caddyfile (ALWAYS FIRST - before any changes)
2.  Check if fail2ban is installed
3.  Install fail2ban if missing (with confirmation)
4.  Create /var/log/caddy directory
5.  Check if Caddy container has log volume mounted
6.  Automatically add log volume to docker-compose.yml if needed
7.  Create fail2ban filter at /etc/fail2ban/filter.d/caddy-auth.conf
8.  Create fail2ban jail at /etc/fail2ban/jail.d/caddy.conf (with custom settings)
9.  Test fail2ban configuration
10.  Restart fail2ban and verify jail is active
11.  Add service configurations (ActualBudget, Keycloak) to Caddyfile
12.  Validate and reload Caddy configuration

ERROR HANDLING:
- All operations tracked with error messages array
- If any step fails, script continues but tracks the failure
- At the end, shows all errors encountered
- Provides exact manual commands to fix issues
- Backup is ALWAYS created before any changes

USER EXPERIENCE:
- Interactive prompts with sensible defaults
- Clear colored output (INFO, SUCCESS, WARNING, ERROR)
- Progress feedback at each step
- Final summary with useful commands
- Only shows manual instructions if automation failed

SAFETY FEATURES:
- Caddyfile backup before ANY modifications
- docker-compose.yml backup before modifications
- Validation before reloading Caddy
- Test fail2ban config before restart
- Restore instructions always shown after backup

This matches the integrated experience of other services - fully automated
unless something goes wrong, in which case it provides manual steps.
2026-01-11 22:50:30 +00:00
Claude 5dbb27ee8b Fix Magic Mirror npm setup and add ActualBudget, Keycloak, Caddy/fail2ban support
FIXES:
- Fix Magic Mirror npm install to run inside Docker container instead of on host
- npm (Node Package Manager) commands now execute inside the MagicMirror container
  where Node.js is installed, preventing errors on hosts without Node.js

NEW SERVICES:
- Add ActualBudget: Open-source personal finance management with bank sync (SimpleFIN)
- Add Keycloak: Identity and Access Management (SSO, OAuth2, SAML, MFA)
- Both services integrated into main installation script and available as standalone
  docker-compose files for existing servers

CADDY & FAIL2BAN:
- Add caddy-setup-helper.sh: Interactive script to configure Caddy and fail2ban
  * Detects existing Caddy installation
  * Automatically backs up Caddyfile with timestamp
  * Checks for fail2ban support
  * Provides service integration examples
- Add fail2ban filter and jail configurations for Caddy protection
- Add comprehensive setup guide (CADDY-FAIL2BAN-SETUP.md)

DOCUMENTATION:
- Detailed deployment instructions for each service
- Reverse proxy configuration examples
- Security best practices and headers
- Backup/restore procedures
- Troubleshooting guides

This update enables secure deployment of new services on existing servers with
proper Caddy reverse proxy integration and fail2ban protection against attacks.
2026-01-11 21:43:52 +00:00
Claude d84a1be5d5 Add container auto-start, UFW ports, Magic Mirror config/modules
- Add interactive "Start now?" prompts to all Docker containers
- Add UFW firewall port opening for Docker services when enabled
- Add Magic Mirror config copy option with custom.css support
- Add automatic detection and download of third-party MMM-* modules
- Add npm install for Magic Mirror module dependencies
2026-01-08 13:08:11 +00:00
Claude 47f3e9c0a6 Major improvements: drive setup, Immich config, container start
Drive Setup (runs at script start):
- New setup_drives() function runs before other installations
- Auto-detects unpartitioned drives, offers to format
- Creates ~/drives/ mount points
- Adds to fstab and runs mount -a
- Partitioning/formatting for new drives without partition tables

Immich Improvements:
- Separate UPLOAD_LOCATION from EXTERNAL_LIBRARY (different paths)
- Upload: ~/drives/primary/photos/immich-uploads (new photos)
- External: ~/drives/primary/photos (existing photos, read-only)
- Warns if both paths are the same
- Added immich-cli instructions for uploading old photos with correct EXIF dates
- Container auto-start option after install

Container Management:
- Added "Start now?" prompt for Immich after install
2026-01-08 12:51:22 +00:00
Claude b6dc3e6d18 Add interactive volume path updates during migration
Step 6 now scans docker-compose files for volume mounts:
- Detects absolute paths that don't exist on new system
- Shows old path and suggests ~/drives/primary/{folder}
- User can: accept suggestion, skip, or enter custom path
- Updates compose file with new path
- Creates directory if needed

Example:
  Container: immich
  Old path:  /home/user1/media/driveb
  Suggested: ~/drives/primary/driveb
  [Enter] Accept | [S] Skip | [path] Custom
2026-01-06 23:32:57 +00:00
Claude ef245a6ee4 Add migration options: copy, symlink, or use in-place
When source is on mounted drive (/mnt/*, ~/drives/*, /media/*):
- [C] Copy - Copy to ~/docker (for old OS drive migration)
- [S] Symlink - Create ~/docker → source (for data drive)
- [U] Use in-place - Use source directly, no copy

This handles both scenarios:
- Old OS drive mounted temporarily → Copy
- Data drive you'll keep using → Symlink or use in-place
2026-01-06 23:29:00 +00:00
Claude 7f03addd9c Improve migration to detect Docker on mounted drives
- Auto-detect ~/drives/*/docker, /mnt/*/docker, /media/*/docker
- Show numbered list for easy selection (type "1" to select first)
- Still accepts any custom path
- Shows common locations as examples if nothing auto-detected
2026-01-06 22:56:45 +00:00
Claude fef7bac6aa Add migration mode for importing existing Docker containers
- New [M] Migration option at script start
- Auto-detects Docker directories (/var/docker, /opt/docker, ~/docker)
- Scans for docker-compose.yml files and lists containers with sizes
- Whiptail checklist for selecting containers to migrate
- Option to stop containers before copy (clean database state)
- Preserves versions - no unwanted upgrades during migration
- After migration, offers to install additional services
- Three modes now: Normal install, Migration, Disaster Recovery
2026-01-06 22:49:36 +00:00
Claude fb6dbdfbcb Add Kopia to disaster recovery for ongoing backups
- Install Kopia in Step 1 (core utilities)
- Add Step 9: Reconnect Kopia repository after restore
- Backups now work immediately after disaster recovery
- Update README with 9-step recovery process
2026-01-02 03:41:04 +00:00
Claude 0038a9a938 Add Immich photo library config, Watchtower, and backup docs
- Immich: Ask for photo storage location (default ~/drives/primary/photos)
- Immich: External library support for existing photos (read-only)
- Immich: Storage template guidance for yyyy/mm organization
- Add Watchtower container with notify-only mode (safe for apps with DB migrations)
- Document what Docker data lives where and what gets backed up
- Update README with v2.9 changelog
2026-01-02 03:07:31 +00:00