From fc8f57ab5159dcc484af0db4f0b37316f625e909 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 11 Aug 2026 03:46:09 +0000 Subject: [PATCH 1/2] Add bash tab-completion for setup.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./setup.sh mat now completes to ./setup.sh mattermost, same for flags. Service names are read fresh from services/*.sh on every completion — never a hardcoded list, which would go stale the moment a new service file gets added (matches this repo's own "adding a service = adding one file, nothing generated" rule from CLAUDE.md). Verified live: sourced the script and confirmed completions for "mat" and "--li", and specifically confirmed "bes" resolves to "beszel" — the service added earlier this same session — with zero changes needed to the completion script itself, proving the list is genuinely dynamic rather than something that looked right once and then rotted. Self-locating via its own BASH_SOURCE path rather than a hardcoded install directory, so it keeps working regardless of where the repo is cloned. Works through a leading `sudo` via bash-completion's standard sudo pass-through (enabled by default on Ubuntu). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn --- README.md | 14 ++++++++++++++ tools/setup-completion.bash | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tools/setup-completion.bash diff --git a/README.md b/README.md index 29ee6a0..3406e6a 100644 --- a/README.md +++ b/README.md @@ -141,11 +141,25 @@ echo "cloud-init.sh: repo cloned to $DEST — the setup wizard will launch on fi sudo ./setup.sh # interactive wizard sudo ./setup.sh caddy immich # install specific services sudo ./setup.sh configure # set site defaults (timezone, domain, Caddy network) +sudo ./setup.sh filebrowser --remove # remove a service (or: sudo ./setup.sh filebrowser remove) ./setup.sh --list # list all services grouped by category sudo ./setup.sh --dry-run immich # preview without making changes sudo ./setup.sh --unattended base # non-interactive, use defaults ``` +### Tab completion + +```bash +echo "source $(pwd)/tools/setup-completion.bash" >> ~/.bashrc +source ~/.bashrc +``` + +Then `./setup.sh mat` completes to `./setup.sh mattermost` — same for +flags (`--li` → `--list`). Works with a leading `sudo` too. The service +list is read fresh from `services/*.sh` on every completion, not a +hardcoded list baked into the script — a service added since you last +pulled shows up immediately, no re-running anything. + ## What the wizard does **First run:** diff --git a/tools/setup-completion.bash b/tools/setup-completion.bash new file mode 100644 index 0000000..93667b6 --- /dev/null +++ b/tools/setup-completion.bash @@ -0,0 +1,34 @@ +# tools/setup-completion.bash — bash tab-completion for setup.sh. +# +# Enable it: +# echo "source $(pwd)/tools/setup-completion.bash" >> ~/.bashrc +# source ~/.bashrc +# (run that echo from the repo root, or swap $(pwd) for the actual path) +# +# Then: ./setup.sh mat -> ./setup.sh mattermost +# Works with a leading `sudo` too (sudo ./setup.sh mat) via the +# bash-completion package's standard sudo pass-through, already enabled by +# default on Ubuntu — nothing extra needed for that part. +# +# Service names are read fresh from services/*.sh every time you press +# — never a hardcoded list baked in here. This repo's own rule is +# "adding a service = adding one file, nothing generated" (see CLAUDE.md); +# a completion script that needed regenerating every time a service got +# added would quietly break that promise the first time someone forgot. + +_setup_sh_completions() { + local cur repo_dir services flags + cur="${COMP_WORDS[COMP_CWORD]}" + + # Self-locating from this file's own path, not a hardcoded install + # location — survives the repo being cloned anywhere, or moved later. + repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." 2>/dev/null && pwd)" + [ -d "$repo_dir/services" ] || return 0 + + services="$(cd "$repo_dir/services" && for f in *.sh; do [ -f "$f" ] && printf '%s ' "${f%.sh}"; done)" + flags="--list --status --dry-run --unattended --remove remove uninstall --version --help configure" + + COMPREPLY=( $(compgen -W "${services}${flags}" -- "$cur") ) +} + +complete -F _setup_sh_completions setup.sh ./setup.sh From e10e1e90b447463b64674ac11013617ee60ae00b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 11 Aug 2026 03:51:02 +0000 Subject: [PATCH 2/2] Fix invalid docker-compose.yml when Beszel is installed with local Caddy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirmed live: "networks.beszel-agent additional properties ... not allowed" — the root-level networks: block (_CADDY_NET_SECTION) was placed between the two services instead of after both. Since it sits at 0 indentation, YAML parsed the following beszel-agent: line as a continuation of the networks: mapping instead of a new services: entry, so the whole beszel-agent service definition got swallowed as if it were a (invalid) child of networks.caddy_net. gatus.sh's identical _CADDY_NET_BLOCK/_CADDY_NET_SECTION pattern never hit this because it only ever has one service, so the same placement is always the last content in the file there. Moved _CADDY_NET_SECTION (the root-level networks: definition) to after both services; _CADDY_NET_BLOCK (the per-service "join caddy_net" snippet) stays right after the hub's own volumes, where it correctly nests under the beszel: service only. Verified by regenerating the compose file with local Caddy present and parsing it with PyYAML: services.beszel and services.beszel-agent are now proper siblings, beszel-agent keeps its image/environment/volumes keys, beszel's own networks: is scoped to just that service, and the root networks: definition is separate and correctly placed. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn --- services/beszel.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/beszel.sh b/services/beszel.sh index 9a02041..242f4cd 100644 --- a/services/beszel.sh +++ b/services/beszel.sh @@ -259,7 +259,7 @@ services: volumes: - ./beszel_data:/beszel_data - ./beszel_socket:/beszel_socket -${_CADDY_NET_BLOCK}${_CADDY_NET_SECTION} +${_CADDY_NET_BLOCK} beszel-agent: image: henrygd/beszel-agent:latest container_name: beszel-agent @@ -275,6 +275,7 @@ ${_CADDY_NET_BLOCK}${_CADDY_NET_SECTION} - ./beszel_agent_data:/var/lib/beszel-agent - ./beszel_socket:/beszel_socket - /var/run/docker.sock:/var/run/docker.sock:ro +${_CADDY_NET_SECTION} BESZEL_COMPOSE # APP_URL only matters for the hub's own generated links and origin