Commit Graph
310 Commits
Author SHA1 Message Date
Claude 3aab169fbc wolf: fix config.toml corruption when re-running on an existing install
Wolf rewrites config.toml on every start and reformats `mounts` as a
multi-line TOML array. update_mounts() only replaced the single line
starting with `mounts =`, leaving the remaining array elements and the
closing `]` orphaned — producing invalid TOML ("Expected '=' after a key")
that crashed Wolf on the next start. This bit any re-run of the installer
(or `./manage.sh apps`) against a config Wolf had already reformatted.

Replace the entire array (from `mounts =` to its closing `]`), and also
clean up orphaned remnants left by a previously corrupted single-line
rewrite so re-running the script repairs a broken config in place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 15:55:44 +00:00
Claude 37f85d6adf wolf: add ./manage.sh add-web — URL shortcut tiles in Moonlight via Firefox kiosk
Prompts for a display name and URL, auto-fetches the site's apple-touch-icon
or favicon.png, falls back to a manual URL/local-PNG prompt, then injects a
[[profiles.apps]] block using ghcr.io/games-on-whales/firefox:edge with
START_URL set to the target URL. Wolf's virtual gamepad injection means
controller-aware sites (Gamepad API) work naturally through the stream.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 15:21:30 +00:00
Claude b72e2bf549 wolf: add interactive 'manage.sh reorder' for Moonlight tile order
Moonlight shows app tiles in config.toml order with no in-client reordering.
Add ./manage.sh reorder: lists the current [[profiles.apps]] blocks by title,
prompts for a new order (read from /dev/tty since stdin is the heredoc),
rewrites config.toml preserving each block's nested runner subtable and
spacing, then restarts Wolf. Updated help text and README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 15:11:34 +00:00
Claude f71edf1aad wolf: read WOLF_STATE_DIR from .env at runtime, not baked into compose
docker compose reads variables from .env automatically. Use ${WOLF_STATE_DIR}
in docker-compose.yml so the state folder path is dynamic — editing .env is
enough to relocate it without regenerating the compose file. IP/MAC/render
node stay baked in (hardware-specific, not in .env).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 13:56:22 +00:00
Claude 1a85ddf063 wolf: relocate Wolf's state folder to the game drive (no symlinks/vdf)
The right fix, finally. Instead of fighting Steam's libraryfolders.vdf or
symlinking individual app session homes, point Wolf's entire state folder at
the game drive. Steam's install, downloaded games, and Proton prefixes are
born there because Wolf creates every app's session home under
HOST_APPS_STATE_FOLDER.

- docker-compose.yml: mount $WOLF_STATE_DIR (=<game_dir>/wolf-state) at the
  SAME path inside and outside the wolf container, set HOST_APPS_STATE_FOLDER
  and WOLF_CFG_FOLDER to it. Same-path mount is required because Wolf hands
  host paths to the Docker daemon when spawning sibling app containers.
- config.toml now lives at $WOLF_STATE_DIR/cfg/config.toml; all WOLF_CFG
  references updated (install + manage.sh, via WOLF_STATE_DIR in .env).
- Optional migration: move existing /etc/wolf data onto the drive on upgrade.
- Removed all symlink machinery: relocate_steam_home, steam-home dir,
  _relocate_steam_home in manage.sh, and the fix-perms relocation step.
  fix-perms now just re-owns the state folder + game storage.
- Dropped the redundant Steam app mount; updated README/summary text.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 13:44:10 +00:00
Claude df988cca3c wolf: put Steam home on the game drive via symlink, not libraryfolders.vdf
Seeding libraryfolders.vdf never stuck: Steam rewrites that file on every
launch and forces its primary library back to its own install dir
(/home/retro/.local/share/Steam), which is the Wolf session home on the OS
drive. That's why Steam Storage kept showing /home/retro with the OS drive's
size no matter how many times we seeded the vdf.

New approach: relocate_steam_home symlinks each Wolf Steam session home
(/etc/wolf/<id>/Steam, bind-mounted to /home/retro) at
$GAME_STORAGE_DIR/steam-home. Steam's one and only library is then the game
drive, so installs, game files, and Proton prefixes all land there and the
Storage screen reports the game drive's free space. An existing Steam install
is moved over once (no re-download) before the symlink is created.

Wired into first install, manage.sh start (self-heals on reboot), and
manage.sh fix-perms. Dropped the redundant /mnt/games/steam mount and the
vdf seeding everywhere; updated the README heredoc with the one-time
connect / fix-perms / reconnect sequence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 13:13:50 +00:00
Claude 2ac7d6898d wolf: seed Steam libraryfolders.vdf into session dirs after first install
After app injection + docker compose restart, Wolf creates per-app session
dirs under /etc/wolf/<id>/Steam. Wait up to 30s for those dirs to appear,
then copy the pre-built libraryfolders.vdf into each one so Steam sees the
game storage location on its very first launch — no manual setup needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 12:53:50 +00:00
Claude b3b5cc9b6e wolf: auto-seed Steam library config on manage.sh start
Wolf creates /etc/wolf/<id>/Steam/ session dirs when the container starts,
not at install time. Previously the user had to manually run fix-perms after
first start to propagate libraryfolders.vdf.

manage.sh start now calls _seed_steam_library() after docker compose up,
which copies libraryfolders.vdf from game storage into any Wolf session dir
that doesn't have it yet — so the correct library path (/mnt/games/steam)
is in place before the first Moonlight connection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 12:17:02 +00:00
Claude 16f4f56168 wolf: seed Steam libraryfolders.vdf into Wolf session home dir
Steam reads libraryfolders.vdf from /home/retro/.local/share/Steam/steamapps/
which Wolf serves from /etc/wolf/<session-id>/Steam/. Seeding it only in
/mnt/games/steam/steamapps/ was ignored since Steam doesn't know to look there.

- Seed the VDF into any existing /etc/wolf/<id>/Steam session dirs at install time
- manage.sh fix-perms now propagates the VDF from game storage into every
  Wolf session dir so running fix-perms is the one-command remedy on existing
  installs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 06:11:44 +00:00
Claude f735825ad9 wolf: list mounted drives via lsblk -P so whole-disk mounts show in picker
The drive picker enumerated mounts with `lsblk MOUNTPOINT | df` round-trips,
which could miss a whole-disk mount (e.g. an nvme formatted directly with no
partition table). Switch to `lsblk -Pno NAME,MOUNTPOINT,SIZE,LABEL,UUID` and
parse the key="value" pairs directly — handles whole-disk mounts and empty
LABEL/UUID fields reliably, so every mounted data drive appears as a numbered
choice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 06:00:46 +00:00
Claude bd84f1df1e wolf: pre-seed Steam libraryfolders.vdf so game storage dir is set on first launch
Creates steamapps/libraryfolders.vdf pointing at /mnt/games/steam during
install so Steam uses the correct library path without needing the user to
navigate Settings → Storage on first launch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 05:50:19 +00:00
Claude e7f65d127c wolf: add fix-perms command and document app home-dir ownership fix
Wolf mounts each app's home dir from /etc/wolf/<session-id>/<App> into the
container as /home/retro. If anything there is root-owned (e.g. left over
from an earlier mount layout), the in-container retro user (uid 1000) hits
"Permission denied" creating ~/.steam and the app exits on launch.

- Add `./manage.sh fix-perms`: chowns every /etc/wolf/<id>/ app home dir
  and the on-disk game storage to uid/gid 1000
- Document the /mnt/games mount layout, first-Steam-launch library step,
  3DS/Azahar emulator path, and the fix-perms troubleshooting flow in the
  generated README

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 05:44:13 +00:00
Claude 01c4dd8525 wolf: mount game storage at /mnt/games/* not /home/retro/* paths
Mounting into /home/retro subpaths causes Docker to create intermediate
directories (/.local/share/Steam etc.) as root-owned in the container
overlay before init runs. The GoW init chown step doesn't fully fix these,
so the retro user hits Permission denied on first write.

Move all mounts to neutral /mnt/games/* paths that don't interfere with
the container's home directory setup:
  steam    → /mnt/games/steam    (add as Steam Library Folder via UI)
  lutris   → /mnt/games/lutris
  kodi     → /mnt/games/kodi
  firefox  → /mnt/games/firefox
  minecraft → /mnt/games/minecraft
  saves    → /mnt/games/saves
  emulators → /mnt/games/emulators

ROMs stay at /ROMs (GoW ES-DE hardcodes that path).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 05:17:41 +00:00
Claude c10bf62c79 wolf: fix duplicate /home/retro mount — target Steam library path directly
Mounting steam:/home/retro conflicted with the GoW Steam image's own
internal /home/retro mount. Mount steam:/home/retro/.local/share/Steam
instead — this is where steamapps/ and Proton prefixes actually live,
persists all game data, and doesn't collide.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 04:59:37 +00:00
Claude 87414bdc44 wolf: fix manage.sh apps permission denied on /etc/wolf/cfg/config.toml
config.toml is root-owned (Wolf container writes it as root). manage.sh
runs as the regular user, so python3 and grep against the file need sudo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 04:56:04 +00:00
Claude 54082ad8b0 wolf: fix Steam storage mount, add Azahar 3DS emulator, emulators/ dir
- Steam mount was steam:/home/retro/.steam — games download to
  /home/retro/.local/share/Steam/steamapps/ which was NOT mounted and
  lived in the ephemeral container layer. Fixed to steam:/home/retro
  so the full home dir (library, user data, Proton prefixes) persists.
- Add emulators/ subdir to game storage layout; mounted into ES-DE
  container at /home/retro/Applications (ES-DE's default AppImage search path)
- Add optional Azahar (open-source Citra fork) AppImage download at
  install time — fetches latest release from GitHub, chmod +x, places
  in emulators/ where ES-DE finds it automatically for nintendo3ds ROMs
- Update README to document new storage layout and 3DS emulation setup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 04:46:48 +00:00
Claude 73a41e7252 wolf: redesign app selection with numbered menu, ES-DE ROM dirs, and manage.sh apps command
- Drive picker: numbered list with UUID display, mounted + unmounted drives,
  explicit system-path exclusions (no regex bare-/ bug), skip whole disks
  with mounted partitions
- Pre-create ES-DE ROM system directories (~50 systems) so ES-DE detects
  all platforms on first launch
- App selection at install time: numbered menu for Steam, ES-DE, Lutris,
  RetroArch, Prism Launcher, Kodi, Firefox, Desktop
- Python catalog-driven TOML injector shared between install and manage.sh;
  supports update_mounts() to patch paths on re-run without duplicating entries
- manage.sh `apps` command replaces `add-apps` / `update-storage`: shows
  installed apps, interactive picker, updates game storage path from .env
- Game storage written to ~/docker/wolf/.env as GAME_STORAGE_DIR

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 04:41:59 +00:00
Claude fa906186c3 fix(services): conditional caddy_net across all Docker service scripts
Only include the caddy_net network block in generated docker-compose.yml
files when ~/docker/caddy exists. Prevents "network caddy_net declared
as external, but could not be found" on standalone installs without Caddy.

Affected: actualbudget, archivebox, arm, audiobookshelf, calibre-web,
changedetection, drum-rhythm-game, emby, fmd, frigate, frigate-audio,
frigate-notify, gatus, homeassistant, immich, iopaint, jellyfin, joplin,
koha, lyrion, magicmirror, mail-archiver, mattermost, mealie, meshcentral,
n8n, nextcloud, ntfy, onlyoffice, portainer, stirling-pdf, syncthing,
traccar, unifi, uptimekuma, vaultwarden, wg-easy

Skipped: authelia (creates caddy_net itself), caddy, crowdsec, wolf,
wolf-pair, and services using network_mode: host with no caddy_net.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 04:16:41 +00:00
Claude 68a4effad5 fix(services): conditional caddy_net for filebrowser, homebox, watchtower
Only include the caddy_net network block in docker-compose.yml when
~/docker/caddy exists, preventing "network not found" errors on
standalone installs without Caddy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 04:06:51 +00:00
Claude 07d09a73fe fix(js99er): missing write_readme stub + conditional caddy_net
- Add write_readme() to the standalone bootstrap stubs (was defined in
  wolf-pair.sh and other services but missing here)
- Only include the caddy_net network block in docker-compose.yml when
  ~/docker/caddy exists; otherwise docker compose up fails with
  "network caddy_net declared as external, but could not be found"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 03:49:53 +00:00
Claude 88ac2ac06a fix(wolf-pair): set allow_reuse_address so restarts don't hit EADDRINUSE
HTTPServer.allow_reuse_address must be set before __init__ calls
server_bind(). Setting it as a class attribute before instantiation
is the correct pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 03:29:58 +00:00
Claude 63ee2e8aff fix(wolf-pair): remove stray networks block from docker-compose.yml
network_mode: host containers cannot join Docker networks, so the
caddy_net networks: block was dead code. The ${CADDY_NET:-caddy_net}
value (colon inside unquoted YAML scalar) was also causing
"mapping values are not allowed in this context" at parse time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 03:19:38 +00:00
Claude c34dd29cd1 fix(wolf): regex bug was skipping all mounted drives in picker
^(/|/boot|...) — the bare / alternate matches every absolute path,
so every non-home mount was silently skipped. Replace with explicit
glob checks so only root, system paths, and [SWAP] are excluded.
Fixes /home/user/drives/1tb-space (and any other secondary mount)
not appearing in the numbered list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 03:07:20 +00:00
Claude 96e9705c88 fix(wolf): show UUIDs in drive picker; fix false-unmounted for whole disks
- Display UUID under each mounted and unmounted entry so users can
  cross-reference with fstab / blkid output
- Fix detection bug: a whole disk (e.g. sdb) with a mounted partition
  (sdb1) was incorrectly listed as unmounted; now checks lsblk children
  before including a disk in the unmounted list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 03:02:50 +00:00
Claude 051fed8dd2 feat(wolf): numbered drive picker for game storage location
Replace the free-text path prompt with an interactive menu:
- Lists mounted non-system drives as numbered choices (1, 2, ...)
- Each shows mount point, drive label/name, total size, and free space
- Default path is <selected-mountpoint>/games
- Unmounted drives shown as U1, U2, ... (script formats + mounts them)
- Option c for a fully custom path
- Final confirm/edit step lets user tweak the subdir before committing
- Unattended mode defaults to ~/games

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 02:52:11 +00:00
Claude 7974bf11ef fix(wolf): persist game storage path and update mounts on re-run
- Write GAME_STORAGE_DIR to ~/docker/wolf/.env so the chosen path is
  visible and editable after setup
- Fix inline Python injection to UPDATE existing Steam/ES-DE mounts in
  config.toml instead of silently skipping when entries already exist
  (previously re-running setup with a new path had no effect)
- Add update-storage subcommand to manage.sh so the path can be changed
  post-install without a full re-run: ./manage.sh update-storage /new/path
- Same fix applied to add-apps in manage.sh
- chown game storage dir to ACTUAL_USER after creating subdirectories

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
2026-06-20 02:46:43 +00:00
Outis ed018e289b Merge pull request #79 from outis1one/claude/nifty-carson-tbh7ji
Add optional Groq Cloud API support to ai-gpu's Open WebUI
2026-06-18 22:15:53 -04:00
Claude 2edc719a7a Add optional Groq Cloud API support to ai-gpu's Open WebUI
Wires Groq (api.groq.com) into Open WebUI as an OpenAI-compatible
connection so its hosted models show up alongside local Ollama models.
Prompts for an API key during install, stores it in llm/.env, and
patches the cloned docker-compose.yml's open-webui environment block
(idempotently) to reference it.
2026-06-19 02:13:24 +00:00
Outis 0231d4a5c6 Merge pull request #78 from outis1one/claude/great-knuth-ao7wuq
Claude/great knuth ao7wuq
2026-06-11 18:48:49 -04:00
Claude 5b340552c3 Replace CADDY_REMOTE_HOST with explicit CADDY_MODE in site config
The old CADDY_REMOTE_HOST variable was confusingly named — it sounded like
the Caddy server's address but actually stored this machine's IP (so Caddy
knew how to reach services here). Services don't need to know where Caddy
is; they only need to know whether to write a Caddyfile or create a snippet.

Changes in lib/common.sh:
- Add CADDY_MODE=local|remote|none as the authoritative setting
- load_site_config: parse CADDY_MODE; if old CADDY_REMOTE_HOST present and
  CADDY_MODE unset, infer CADDY_MODE=remote (backward compat)
- save_site_config: write CADDY_MODE, drop CADDY_REMOTE_HOST output
- configure_caddy_for_service: use CADDY_MODE for mode detection; for remote
  snippets auto-detect this machine's primary IP via hostname -I instead of
  requiring a stored value (still falls back to CADDY_REMOTE_HOST if present
  in an old .config)

Changes in setup.sh (run_site_configure wizard):
- Replace free-text "Caddy remote host" prompt with a 3-choice menu:
  [1] This machine  [2] Remote machine  [3] None/skip
- Existing installs with CADDY_REMOTE_HOST pre-select option 2 automatically

https://claude.ai/code/session_01S7UecmQRG6CKTYPoBqbVLj
2026-06-10 00:49:41 +00:00
Claude ec9aa605cf Fix named volumes in koha/asterisk for backup coverage; add Koha setup wizard
koha.sh:
- Replace named volume `koha_db_data` with bind-mount `./data:/var/lib/mysql`
  so the MariaDB database is inside ~/docker/koha/ and covered by backup.sh
- Add interactive setup wizard: collects library name, code, admin credentials,
  item types (with custom additions), and shelf locations before first start
- Generate ~/docker/koha/post-setup.sh at install time; after completing the
  web installer the user runs it to auto-configure the library branch, item
  types, shelf locations, and system preferences via the Koha REST API
- Updated README with exact step-by-step web installer instructions and
  admin password prominently displayed

asterisk.sh:
- Replace all 5 named volumes (asterisk-config, easy-asterisk-config,
  asterisk-logs, asterisk-spool, asterisk-lib) with bind-mounts inside
  ~/docker/asterisk/ so all config and state is covered by backup.sh
- mkdir -p for all bind-mount dirs before compose up
- Replace SSH-based standalone configure_caddy_for_service stub with the
  snippet approach used everywhere else (local Caddy writes Caddyfile;
  remote Caddy via VPN/Netbird saves ~/docker/caddy-snippets/<name>.caddy)

https://claude.ai/code/session_01S7UecmQRG6CKTYPoBqbVLj
2026-06-09 18:39:27 +00:00
Outis 1664001a9e Merge pull request #77 from outis1one/claude/exciting-allen-uea3dx
Claude/exciting allen uea3dx
2026-06-09 13:37:42 -04:00
Claude f9013287d9 iopaint, ai-gpu: interactive model selection, auto-pull, fixes
iopaint:
- Add model selection menu (10 choices) with CPU/GPU/SD tiers and
  size/use-case descriptions shown at install time
- Fix volume mount: ./models:/root/.cache (was only /root/.cache/iopaint)
  — now persists both torch hub cache (LaMa) and HuggingFace cache (SD/PowerPaint)
- Refactor compose to use ${MODEL} and ${DEVICE} env vars so switching
  models only requires editing .env + restart, no compose file edit needed
- Add PowerPaint-V2-filling and SD 1.5 inpainting as explicit menu choices
  for text-guided object replacement
- Update header and README to document all three use cases (erase, fill, replace)
  and note that IOPaint is local-only (cannot use a remote GPU)

ai-gpu:
- Add Ollama model selection menu (8 models, multi-select with sizes/descriptions)
  defaulting to llama3.2:3b + nomic-embed-text
- Auto-pull selected Ollama models immediately after LLM stack starts
- Add InvokeAI starter model selection (SD 1.5 / SDXL Turbo / SDXL Base / skip)
- Queue InvokeAI model download via REST API (POST /api/v2/models/install)
  with fallback instructions if the API is unavailable
- Add HuggingFace token prompt; stored as HUGGING_FACE_HUB_TOKEN in image-gen .env
- Wire SearXNG into Open WebUI via ENABLE_RAG_WEB_SEARCH + SEARXNG_QUERY_URL in llm .env
- Default start choice is now 2 (portal + LLM + Ollama pull) so the stack
  is ready to use immediately after install

https://claude.ai/code/session_01JEu7LgCWXKhXo18MeYFRZp
2026-06-09 03:57:01 +00:00
Claude 5c394815b4 Add iopaint and ai-gpu services
iopaint: AI image inpainting (object removal, fill, restore) via IOPaint +
LaMa model. Runs CPU by default; GPU option writes nvidia deploy block.
No built-in auth — Authelia SSO prompt included. Port 8100.

ai-gpu: GPU AI stack from outis1one/ai-6gb-gpu. Clones repo and sets up
three stacks under ~/docker/ai-gpu/: InvokeAI image gen (port 9090),
Ollama + Open WebUI + SearXNG LLM stack (ports 11434/3000), and Flask
portal (port 8080) that hot-swaps the GPU between stacks. Patches
hardcoded home paths in portal docker-compose.yml to use ACTUAL_HOME.
Prompts for TZ (replaces hardcoded America/New_York). Caddy for both
portal (localai) and InvokeAI (images).

https://claude.ai/code/session_01JEu7LgCWXKhXo18MeYFRZp
2026-06-09 03:13:51 +00:00
Claude b6f499295f Add koha: full ILS for physical book library (catalog, shelf locations, loans) 2026-06-09 02:29:54 +00:00
Outis 201ab6c433 Merge pull request #76 from outis1one/claude/zealous-feynman-odDrh
Claude/zealous feynman od drh
2026-06-08 22:06:12 -04:00
Outis 7218359de1 Merge branch 'main' into claude/zealous-feynman-odDrh 2026-06-08 22:06:02 -04:00
Claude 12795a27fd Add drum-rhythm-game: nginx-served browser rhythm game with Authelia SSO support 2026-06-09 01:58:30 +00:00
Claude d47d8dc26f unifi.sh: add remote Caddy snippet support, fix standalone CADDY_REMOTE_HOST global 2026-06-09 00:58:57 +00:00
Claude 8bdc4ca025 Improve changedetection.sh: explicit env vars in compose, chmod 600 .env, better readme 2026-06-09 00:30:43 +00:00
Claude 5ee08523e3 Improve n8n.sh: explicit env vars in compose, chmod 600 .env, better readme 2026-06-09 00:28:40 +00:00
Claude f21c96c1a7 Add 7 new services: Joplin, Stirling PDF, n8n, Changedetection, ArchiveBox, Calibre-Web, Homebox
- joplin: self-hosted sync server (PostgreSQL sidecar, APP_BASE_URL from SITE_DOMAIN)
- stirling-pdf: PDF toolkit with optional Authelia SSO (no built-in auth)
- n8n: workflow automation connecting self-hosted services (WEBHOOK_URL from SITE_DOMAIN)
- changedetection: web page change monitoring with playwright-chrome renderer
- archivebox: personal Wayback Machine, initializes data dir at install time
- calibre-web: ebook library UI with Calibre conversion support (linuxserver image)
- homebox: home inventory and asset management

All services follow the standalone bootstrap pattern and support local/remote Caddy.
README.md updated with new services in appropriate group rows.
2026-06-09 00:28:40 +00:00
Claude 7c3f101fe0 Add asterisk, nextcloud, onlyoffice, mattermost services + vendor/easy-asterisk
asterisk.sh (homelab):
- Easy Asterisk PBX with self-hosted coturn TURN server
- Vendored from outis1one/easy-asterisk v0.10.0 for offline install
- LAN-only or FQDN mode (TLS + TURN relay for remote access)
- Auto-answer SIP headers for intercom use case
- Authelia SSO for web admin; WEB_ADMIN_AUTH_DISABLED=true when chosen
- UFW rules: 5060-5061, 8080, 8088-8089, 3478, 10000-20000/udp, 49152-49252/udp
- Builds custom Docker image from vendor/easy-asterisk/

nextcloud.sh (utilities):
- Custom Dockerfile: nextcloud:apache + smbclient (SMB external storage)
- MariaDB 10.11 sidecar with matching env vars
- OVERWRITEPROTOCOL/OVERWRITECLIURL/TRUSTED_PROXIES set for Caddy
- Enables files_external app after first-run init (waits up to 90s)

onlyoffice.sh (utilities):
- JWT generated once, preserved across re-runs
- _ensure_yq: auto-installs yq v4 for FileBrowser config patching
- _wire_nextcloud: idempotent occ wiring (DocumentServerUrl, jwt_secret)
- _wire_filebrowser: patches config.yaml + restarts container
- Caddy block overrides X-Frame-Options to allow iframe embedding

mattermost.sh (utilities):
- PostgreSQL 15-alpine + Mattermost Team Edition + coturn (port 3479)
- 8443/udp for Calls plugin RTC server
- coturn uses --use-auth-secret HMAC mode (required by Calls plugin)
- SITE_URL computed from SITE_DOMAIN, promptable
- UFW: 8443/udp, 3479, 49153-49352/udp

vendor/easy-asterisk/:
- All upstream source files vendored for offline/self-contained installs
- Dockerfile, docker/entrypoint.sh, docker/coturn-entrypoint.sh
- easy-asterisk-v0.10.0.sh (6929-line management script)
- scripts/vpn-diagnostics.sh, scripts/dns-whitelist.sh
- .env.example

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
2026-06-09 00:28:38 +00:00
Claude ec3f9bfd3f Add remote Caddy support — generate snippet files when Caddy is on another host
New site config key: CADDY_REMOTE_HOST (set via 'sudo ./setup.sh configure').
When set, configure_caddy_for_service operates in "remote" mode instead of
writing to a local Caddyfile:
- Upstream uses CADDY_REMOTE_HOST:PORT (host IP, not container name)
- Snippet saved to ~/docker/caddy-snippets/<subdomain>.caddy
- User is shown scp/rsync commands to copy it to the Caddy machine

Three modes in configure_caddy_for_service (lib/common.sh and inline stubs):
  local:  ~/docker/caddy/ exists → write Caddyfile + reload (existing behavior)
  remote: CADDY_REMOTE_HOST set → save snippet, print copy instructions
  none:   neither configured → silent return (unchanged)

All 31 service standalone bootstrap stubs updated with the new logic.
CADDY_REMOTE_HOST global added to all 42 standalone bootstrap sections.
setup.sh configure now prompts for CADDY_REMOTE_HOST with a clear explanation.
wolf.sh: add missing stubs (configure_caddy_for_service, write_readme,
  prompt_yn, ensure_docker_dir_ownership) and the Authelia/Caddy/start calls
  that were missing from the install function.

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
2026-06-09 00:28:30 +00:00
Claude 13dec9a857 Add asterisk, nextcloud, onlyoffice, mattermost services + vendor/easy-asterisk
asterisk.sh (homelab):
- Easy Asterisk PBX with self-hosted coturn TURN server
- Vendored from outis1one/easy-asterisk v0.10.0 for offline install
- LAN-only or FQDN mode (TLS + TURN relay for remote access)
- Auto-answer SIP headers for intercom use case
- Authelia SSO for web admin; WEB_ADMIN_AUTH_DISABLED=true when chosen
- UFW rules: 5060-5061, 8080, 8088-8089, 3478, 10000-20000/udp, 49152-49252/udp
- Builds custom Docker image from vendor/easy-asterisk/

nextcloud.sh (utilities):
- Custom Dockerfile: nextcloud:apache + smbclient (SMB external storage)
- MariaDB 10.11 sidecar with matching env vars
- OVERWRITEPROTOCOL/OVERWRITECLIURL/TRUSTED_PROXIES set for Caddy
- Enables files_external app after first-run init (waits up to 90s)

onlyoffice.sh (utilities):
- JWT generated once, preserved across re-runs
- _ensure_yq: auto-installs yq v4 for FileBrowser config patching
- _wire_nextcloud: idempotent occ wiring (DocumentServerUrl, jwt_secret)
- _wire_filebrowser: patches config.yaml + restarts container
- Caddy block overrides X-Frame-Options to allow iframe embedding

mattermost.sh (utilities):
- PostgreSQL 15-alpine + Mattermost Team Edition + coturn (port 3479)
- 8443/udp for Calls plugin RTC server
- coturn uses --use-auth-secret HMAC mode (required by Calls plugin)
- SITE_URL computed from SITE_DOMAIN, promptable
- UFW: 8443/udp, 3479, 49153-49352/udp

vendor/easy-asterisk/:
- All upstream source files vendored for offline/self-contained installs
- Dockerfile, docker/entrypoint.sh, docker/coturn-entrypoint.sh
- easy-asterisk-v0.10.0.sh (6929-line management script)
- scripts/vpn-diagnostics.sh, scripts/dns-whitelist.sh
- .env.example

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
2026-06-08 23:42:44 +00:00
Claude d4e06914e7 Add remote Caddy support — generate snippet files when Caddy is on another host
New site config key: CADDY_REMOTE_HOST (set via 'sudo ./setup.sh configure').
When set, configure_caddy_for_service operates in "remote" mode instead of
writing to a local Caddyfile:
- Upstream uses CADDY_REMOTE_HOST:PORT (host IP, not container name)
- Snippet saved to ~/docker/caddy-snippets/<subdomain>.caddy
- User is shown scp/rsync commands to copy it to the Caddy machine

Three modes in configure_caddy_for_service (lib/common.sh and inline stubs):
  local:  ~/docker/caddy/ exists → write Caddyfile + reload (existing behavior)
  remote: CADDY_REMOTE_HOST set → save snippet, print copy instructions
  none:   neither configured → silent return (unchanged)

All 31 service standalone bootstrap stubs updated with the new logic.
CADDY_REMOTE_HOST global added to all 42 standalone bootstrap sections.
setup.sh configure now prompts for CADDY_REMOTE_HOST with a clear explanation.
wolf.sh: add missing stubs (configure_caddy_for_service, write_readme,
  prompt_yn, ensure_docker_dir_ownership) and the Authelia/Caddy/start calls
  that were missing from the install function.

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
2026-06-08 21:10:37 +00:00
Outis 70aacc5075 Merge pull request #75 from outis1one/claude/zealous-feynman-odDrh
Fix functional bugs found in service audit
2026-06-08 16:55:09 -04:00
Claude e95e82be2f Fix functional bugs found in service audit
wg-easy: PASSWORD env var removed in v14+; generate bcrypt hash at install
  time via 'docker run wg-easy wgpw' and write PASSWORD_HASH instead.

ntfy: write config/server.yml with base-url, cache-file, auth-file, and
  behind-proxy:true so push notification links work when behind Caddy.
  auth-default-access: deny-all (require topic auth).

mealie: BASE_URL was hardcoded to http://localhost:9925; email links and
  OAuth redirects broke when served via Caddy. Now computed from SITE_DOMAIN
  and written to .env so it's easy to update.

nextcloud: add OVERWRITEPROTOCOL=https, OVERWRITECLIURL, TRUSTED_PROXIES to
  .env so share links and internal redirects use https:// behind Caddy.

onlyoffice: Caddy's default X-Frame-Options: SAMEORIGIN header blocked
  OnlyOffice from being embedded as an iframe in Nextcloud. Override it in
  the Caddy site block to allow framing.

vaultwarden: remove exposed port 3012 (WebSocket — not needed since v1.29+,
  all handled on port 80). Publish port 8888 for direct host access instead.
  Remove WEBSOCKET_ENABLED=true (ignored in current versions).

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
2026-06-08 19:13:09 +00:00
Outis 6d2ffaac4a Merge pull request #74 from outis1one/claude/zealous-feynman-odDrh
Claude/zealous feynman od drh
2026-06-08 15:08:33 -04:00
Claude 551c254b89 Add Authelia SSO prompt to js99er, magicmirror, wolf-pair
These services have no built-in auth. Per CLAUDE.md they should check for
Authelia and offer to protect them with SSO before calling
configure_caddy_for_service. Adds the standard prompt_yn + import authelia
extra block pattern to all three.

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
2026-06-08 19:02:00 +00:00