Commit Graph
1163 Commits
Author SHA1 Message Date
Claude fce2e7caf1 Document Android push-notification troubleshooting for Mattermost
Covers the migrated-from-PikaPods case: stale device registrations
carried over by the DB import, server-to-push-proxy connectivity,
OEM battery optimization, and the push-content setting — the likely
causes when only some Android users stop getting background pushes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AddPmva5bfrUW3MoPriq21
2026-08-25 22:56:58 +00:00
Outis 74b5a0dc7a Merge pull request #394 from outis1one/claude/frigate-authelia-openid-0l1htj
Claude/frigate authelia openid 0l1htj
2026-08-25 13:27:36 -04:00
Claude 493ee30916 Add bulk user-to-group assignment and show access privileges in listings
_authelia_bulk_assign_group() (menu option 17) picks several users and one
target group in a single step, repeatable for multiple batches in one
visit (e.g. "1 4 5 6" -> internal, then "2 3 7 8" -> external1) — the
missing third combination alongside the existing per-user (option 6) and
per-group (option 16) toggles, which only handle one user or one group at
a time respectively. "Internal" clears every outside-access group instead
of assigning one, since internal access is the absence of a group.

_authelia_describe_user_access() is a new shared one-line summary (admin /
internal / group names) used both here and in edit_authelia_user()'s own
listing, so current access is visible right where you're about to change
it instead of requiring a separate trip to option 15's report.

Verified end-to-end against a mock users.yml: batch 1 correctly cleared
an existing group from 4 users, batch 2 correctly added a brand-new group
to a different 4, with the listing reflecting each change before the next
batch starts.
2026-08-25 15:52:13 +00:00
Claude 1e625b9955 Relabel "native" access as "internal" throughout Authelia's menus
Pure wording change, no behavior difference — internal already meant
exactly this (any registered Authelia user, no group) before the rename.
Also brings CLAUDE.md's description of the outside-access/admin-bypass
feature up to date; it still described the pre-generalization one-group-
per-service shape from earlier in this branch.
2026-08-25 15:42:23 +00:00
Claude e9286c8360 Fix wrong Beszel OAuth2 navigation instructions
Printed "hub Settings -> Auth providers", which doesn't exist. The real
location is PocketBase's own admin panel underneath the hub
(/_/#/settings -> unhide collection edit controls -> edit the "users"
collection -> Options tab -> OAuth2), confirmed against beszel.dev's
OAuth guide directly. Fixed in both beszel.sh's own offer and authelia.sh's
generic OIDC menu preset.
2026-08-25 13:25:03 +00:00
Claude 7209a32d43 Split "disable local login" from the initial SSO setup step
Confirmed live: offering DISABLE_PASSWORD_AUTH/ALLOW_PASSWORD_LOGIN in the
same breath as printing the Authelia paste-in values lets an admin say yes
before actually pasting those values into the app's own settings and
testing the button — leaving neither login path working (password form
gone, OAuth provider never actually finished on the app's side).

Both are now their own function, only reachable on a later run (Beszel:
independently after the SSO offer; Mealie: from the "already configured,
not reconfiguring" branch), and gated behind an explicit "have you already
logged in successfully via the Authelia button?" confirmation before the
disable prompt is even offered.
2026-08-25 13:18:15 +00:00
Outis 294e935ffd Merge pull request #393 from outis1one/claude/frigate-authelia-openid-0l1htj
Claude/frigate authelia openid 0l1htj
2026-08-25 06:55:30 -04:00
Claude 49b965bd1d Add group-first membership management (menu option 16)
Group membership was previously only editable per-user (option 4's user
menu, option 6 toggles that one user's groups) — no way to pick a group
and see/toggle its members directly. Adds the reverse entry point: pick
a group, then toggle which users are in it. Same _authelia_toggle_group()
underneath, just entered from the other direction.
2026-08-24 16:32:34 +00:00
Claude 879cb24d3b Wire Authelia SSO into Immich, Audiobookshelf, and Beszel
_authelia_provision_oidc_client gains an optional PKCE flag (new 5th
positional arg; every existing caller updated to pass "n", producing an
identical client block to before) — Audiobookshelf and Beszel's own
Authelia integration docs both require require_pkce/pkce_challenge_method,
which Authelia doesn't turn on by default.

immich.sh: _immich_offer_authelia_oidc() is real server-side automation,
not just paste-in instructions — confirmed the exact system-config "oauth"
JSON field names against Immich's own config-file.md and source (not
guessed, closing out the "needs one more verification pass" note this
repo's own CLAUDE.md already had on file). GET/PUT exchange the whole
config object, so it round-trips everything else unchanged. Needs an
admin API key that doesn't exist until first web-UI visit, so it's wired
into both the fresh-install path and the "update" rerun path.

audiobookshelf.sh, beszel.sh: both apps' OIDC config is UI-only (checked
against audiobookshelf.org and beszel.dev directly — no config API or env
var for the provider fields), so their new offers automate the Authelia
side and print exact paste-in values. Beszel also gets a real, separate
DISABLE_PASSWORD_AUTH/USER_CREATION toggle to fully replace its login,
gated behind a warning to register a working account first.

Also adds Audiobookshelf and Beszel as presets in authelia.sh's own
generic "Register another app" menu, and updates CLAUDE.md's OIDC
verification table to match reality (Immich now wired, Audiobookshelf
was wrongly listed as "high-confidence no", Beszel added).
2026-08-24 16:08:33 +00:00
Outis 8e7ffc5185 Merge pull request #392 from outis1one/claude/frigate-authelia-openid-0l1htj
Correct stale Mealie vision-import guidance in ai-stack.md
2026-08-24 12:02:25 -04:00
Claude 8745f5ad01 Correct stale Mealie vision-import guidance in ai-stack.md
The old note pointed at an OPENAI_MODEL env var for Mealie's "import
recipe from photo" feature. Checked against docs.mealie.io directly:
Mealie moved AI provider config off env vars entirely — it's a live
Group Settings > AI Providers UI setting now (base_url/api_key/model,
with a separate toggle for which provider handles image recognition).
Also spells out how to actually reach this stack's Ollama from Mealie's
separate compose project (host-published port, not a shared network).
2026-08-24 15:40:38 +00:00
Outis 2d2e6aae88 Merge pull request #391 from outis1one/claude/frigate-authelia-openid-0l1htj
Add group/site summary view; let Mealie fully hand off login to Authelia
2026-08-24 11:30:17 -04:00
Claude 8808de0dbb Add group/site summary view; let Mealie fully hand off login to Authelia
authelia.sh: menu option 15 lists every outside-access group with its
site membership (from access_control.rules, excluding each group's own
deny-elsewhere rule) and user membership (from users.yml) in one place —
previously only visible by grepping both files by hand.

mealie.sh: _mealie_offer_authelia_oidc now offers to set
ALLOW_PASSWORD_LOGIN=false (hides Mealie's own login form) and
OIDC_AUTO_REDIRECT=true (skip the login page, go straight to Authelia),
both confirmed against docs.mealie.io rather than assumed. Off by
default since it's a real access-control change, not just an additive
SSO button — anyone without an Authelia account loses their login path.
2026-08-24 12:58:44 +00:00
Outis 5747eebf86 Merge pull request #390 from outis1one/claude/frigate-authelia-openid-0l1htj
Claude/frigate authelia openid 0l1htj
2026-08-24 08:36:08 -04:00
Claude 8aea505541 Generalize site scoping into reusable, named "outside access" groups
_authelia_scope_access previously derived a throwaway "<service>-only" group
every time it ran, so scoping two different sites to the same set of people
meant either duplicating membership by hand or hitting a false "already
scoped" early-return that silently skipped adding the second site's own
rule. Now it offers existing groups by number (any site can join one), lets
a new name be typed freely (e.g. "customer1"), and the already-scoped check
is keyed to the (domain, group) pair instead of the group name alone.

Reframes the access question as native (default, unrestricted) vs. outside
access (a named group) per the AD-style users/groups mental model, and adds
menu option 14 to rename an existing group everywhere it's referenced
(access_control.rules subjects + every member's users.yml entry). The
"-only" suffix stays internal only — every other function that already
keys off it (reporting, per-user group toggle, unprotect cleanup) is
untouched.
2026-08-24 04:28:32 +00:00
Claude 753a8fdd43 Give admins guaranteed access to every Authelia-protected site, old and new
Adds a "subject: group:admins" rule ahead of every domain's other rules, so
admins always match first regardless of any per-service scoping (existing or
future) on that domain — a group's deny-elsewhere rule can no longer catch an
admin even if they're accidentally added to that group later.

- install_authelia and add_authelia_domain bake the rule in at creation time
- _authelia_scope_access retrofits it just-in-time before inserting its own
  deny-elsewhere rule, and anchors that rule below it instead of at the top
- new menu option 13 (_authelia_ensure_admin_access_everywhere) backfills it
  across every domain on an install that predates this
- remove_authelia_domain cleans the rule up too when a domain is removed,
  and its domain picker dedupes since two rules now share one domain string
2026-08-24 04:17:35 +00:00
Outis ee7d40b0ce Merge pull request #389 from outis1one/claude/frigate-authelia-openid-0l1htj
Claude/frigate authelia openid 0l1htj
2026-08-23 21:42:17 -04:00
Claude 9a7989b31d Add Authelia menu option to export/import user data
Lets accounts (users.yml, portable argon2id hashes included) and 2FA/session
state (data/db.sqlite3 + the storage_secret needed to decrypt it) round-trip
through a reinstall without resetting passwords or forcing everyone to
re-enroll their authenticator.
2026-08-24 00:54:14 +00:00
Claude bd5aa223fb Prevent a doubled portal domain when the full domain is typed by mistake
install_authelia()'s and add_authelia_domain()'s "subdomain for the
login portal" prompts concatenated whatever was typed directly with
the apex domain (AUTHELIA_PORTAL_SUBDOMAIN + "." + AUTHELIA_DOMAIN),
with no guard against someone typing the full portal domain they
actually want (e.g. "authelia.mydomain.com") instead of just the
subdomain label ("authelia"). That produces a silently broken,
doubled hostname like "authelia.mydomain.com.mydomain.com" -- which
never matches a real request, so Caddy falls through to some default
response instead of ever reaching real Authelia policy evaluation.

Confirmed live: this is exactly what happened on a real box, and
explains a much bigger symptom than the obviously-wrong hostname alone
would suggest -- every forward_auth-gated site on the instance
silently bypassed Authelia entirely, not just requests to the portal
itself, since the forward_auth subrequest to the (wrong) portal URL
never got a real answer either.

Both prompts now detect and strip an accidentally-included apex suffix
(with a one-line notice), and fall back to "auth" if someone enters
the bare apex domain itself (which can't work as the portal -- it
would collide with the wildcard rule protecting every other domain).
Verified against the exact doubled-domain input, a bare-apex input,
and two ordinary short-label inputs before shipping.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-24 00:15:33 +00:00
Outis 6995afdc66 Merge pull request #388 from outis1one/claude/frigate-authelia-openid-0l1htj
Make every authelia.sh menu numbered with 0 = exit, and fix leftover …
2026-08-23 20:08:36 -04:00
Claude b57c266b84 Make every authelia.sh menu numbered with 0 = exit, and fix leftover "auth." prose
Two changes:

1. Fixed several places that still described the login portal as
   literally "auth.<domain>" in user-facing text, even though the
   actual subdomain has been prompt-configurable since the last
   session's fix (AUTHELIA_PORTAL_SUBDOMAIN) -- the prose just never
   caught up. add_authelia_domain()'s intro, install_authelia()'s
   generated README, and remove_authelia_domain()'s note now describe
   the portal as "you'll pick the subdomain" instead of asserting a
   fixed prefix that was no longer true.

2. Every menu in this file now uses a consistent 0-to-exit/cancel
   convention instead of each one doing its own thing (a numbered
   "leave as-is" as the highest number, blank-to-cancel, no cancel
   option at all, etc.):
   - Top-level "Authelia already exists" menu: "Leave as-is" moved
     from option 12 to 0 (still the default).
   - _authelia_add_oidc_client's app-choice menu: added explicit
     "0) Cancel" (previously a blank Enter silently defaulted to
     "Other/custom app" -- surprising, now it cancels instead).
   - _authelia_manage_one_user's per-user action menu: "Done" moved
     from 8 to 0.
   - edit_authelia_user's user-selection list and its service-group
     toggle sub-list: "blank to cancel" became "0 (or blank) to
     cancel", explicit and documented instead of implicit.
   - _authelia_protect_site / _authelia_unprotect_site: added
     explicit 0-to-cancel (previously a literal "0" typed would have
     been treated as a domain name, not a cancel).
   - _authelia_remove_oidc_client_menu: same explicit 0, default
     changed from blank to "0".
   - remove_authelia_domain: was free-text domain entry against an
     unnumbered list; now a proper numbered list with 0 to cancel,
     consistent with every other domain/site picker in this file.
   - _authelia_scope_access: renumbered so "0) Any Authelia user"
     (the safe no-op default) takes the 0 slot, "1) Specific users
     only" is the one real choice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-24 00:04:31 +00:00
Outis 65a8de0ab9 Merge pull request #387 from outis1one/claude/frigate-authelia-openid-0l1htj
Self-install a PATH wrapper so setup.sh works from any directory
2026-08-23 19:50:28 -04:00
Claude a5085cc65b Self-install a PATH wrapper so setup.sh works from any directory
Every invocation of setup.sh (bare, --list/--status, or with a service
name) now ensures /usr/local/bin/post-install exists and execs this
checkout's setup.sh by its real resolved path -- idempotent (only
writes when missing or pointing somewhere else) and silent except for
a one-line notice the first time it's actually created. Previously
this required cd'ing into the repo (or a manually-created wrapper) on
every box separately; now it's automatic on first run, no separate
setup step.

A plain symlink wouldn't have worked here: setup.sh finds its own
directory via ${BASH_SOURCE[0]}, which bash doesn't resolve through
symlinks, so a symlinked invocation would have set HERE to the
symlink's own directory instead of the repo's.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-23 23:45:12 +00:00
Outis ad4758e331 Merge pull request #386 from outis1one/claude/frigate-authelia-openid-0l1htj
Let OIDC app registration pick a domain from Caddy too, not just type it
2026-08-23 19:36:06 -04:00
Claude 8bd0c0f66d Let OIDC app registration pick a domain from Caddy too, not just type it
_authelia_add_oidc_client()'s "what domain is this app on" prompt only
ever took typed text (with a guessed SITE_DOMAIN-based default) even
though _authelia_protect_site already offered a numbered pick-from-
Caddy-or-type-a-domain UX for the equivalent question elsewhere in
this same file -- an inconsistency a user flagged directly after
registering Mealie's OIDC client and getting a plain text prompt where
they expected the same numbered list.

Factored the shared part into _authelia_pick_domain(): lists this
box's local Caddy sites by number, or accepts a typed domain
(including one not on this box's Caddy at all). Echoes the chosen
domain on stdout with the listing itself on stderr, verified separable
under $(...) capture before wiring it in. Used now by the OIDC domain
prompt; _authelia_protect_site/_authelia_unprotect_site keep their own
inline listing since they additionally annotate each site's current
protection status, which this shared version doesn't need to know
about.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-23 23:35:21 +00:00
Outis 23592a43bf Merge pull request #385 from outis1one/claude/frigate-authelia-openid-0l1htj
Claude/frigate authelia openid 0l1htj
2026-08-23 19:30:26 -04:00
Claude b2b83948d8 Add site un-protect and OIDC client removal; fix a duplicate-ID dead end
Three related fixes so undoing an Authelia change never requires
hand-editing configuration.yml or the Caddyfile:

- _authelia_add_oidc_client() had its own redundant duplicate-client-ID
  check that dead-ended with "pick a different app, or edit that entry
  by hand" -- even though _authelia_provision_oidc_client (called a
  few lines later in the same function) already handles that exact
  case safely by replacing the stale registration. Removed the
  redundant check; the flow now always reaches the safe path. This was
  the actual blocker in the reported "client with ID 'actualbudget' is
  already registered" error -- re-registering the same app a second
  time was never actually broken, just gated by dead code.

- New option 6, _authelia_remove_oidc_client_menu(): lists registered
  OIDC clients by ID and name, removes one via the existing internal
  _authelia_remove_oidc_client() helper (previously only reachable
  from the replace-on-duplicate path, never exposed directly).

- New option 11, _authelia_unprotect_site(): reverse of option 10
  (_authelia_protect_site). Removes a local site's "import authelia"
  or forward_auth block from its own Caddy block and reloads Caddy;
  for a domain on a different box's Caddy, cleans up its access-
  scoping rules here (the actual gate needs removing on that box by
  hand, same one-way limitation option 10 already has in reverse).
  Also removes any _authelia_scope_access rules for the domain, found
  by the same "<domain>-only" group name convention, verified against
  a synthetic multi-domain configuration.yml before shipping so an
  unrelated domain's rules sharing the same "*.<apex>" line are left
  untouched. Both the local-block removal (import authelia one-liner
  and multi-line forward_auth block shapes) and the access-rule
  removal were tested against realistic fixtures first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-23 19:41:47 +00:00
Claude 098bb833cf Add a generic "protect a site with Authelia" menu action
Every individual service so far offers its own "Protect X with
Authelia SSO?" prompt on install, but there was no way to gate an
arbitrary existing site from Authelia's own menu -- especially useful
for a site on a DIFFERENT box's Caddy than the one Authelia runs on,
this repo's own recurring case (a DigitalOcean droplet's site,
protected by an Authelia instance on a separate IONOS box).

New option 9, _authelia_protect_site(): lists this box's own local
Caddy sites by number (flagging ones already protected), or accepts a
typed domain that isn't on this box's Caddy at all. A local site gets
"import authelia" inserted as the first line of its existing block --
before reverse_proxy, same ordering rule as everywhere else in this
codebase, since Caddy runs directives in the order written and an auth
check after reverse_proxy never runs at all. A remote site can't be
edited from here, so it prints (and saves to caddy-snippets/) the
remote-hop-safe forward_auth block that box's own Caddyfile needs
instead, with the portal's actual domain read back from
configuration.yml rather than assumed. Either way finishes by calling
_authelia_scope_access for the domain, so protecting a site and
restricting who can reach it happen in one pass.

Verified the site-listing regex, insertion, idempotency detection, and
remote-domain/portal lookup against synthetic Caddyfile/configuration.yml
fixtures before shipping.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 20:55:14 +00:00
Claude ae77992869 Wire the Security Dashboard into Authelia's per-user access scoping
_authelia_scope_access() (services/authelia.sh) already works for any
Authelia-protected service, forward_auth-gated or OIDC alike -- it's
just never been called from security-dashboard.sh on either the
domain-takeover path (_secdash_offer_asterisk_domain) or the plain
separate-subdomain path, so every domain this dashboard ever protected
defaulted to "any Authelia user", with no way to restrict it to
specific people. That's why the Authelia menu's "Promote to a
specific service's access group" reported no scoped groups existing
yet even after protecting this dashboard with Authelia.

_secdash_configure_caddy() now offers scoping right after the domain
is Authelia-protected (guarded on EXTRA_BLOCK being non-empty, so
Basic-Auth-only or no-auth setups aren't offered a scoping question
for a gate that doesn't exist), guarded by declare -F for standalone
runs where authelia.sh was never sourced. Runs whether the Caddy block
was just freshly written or already existed, so re-running the
installer on an already-configured domain still offers it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 20:44:19 +00:00
Outis 845e06e079 Merge pull request #384 from outis1one/claude/frigate-authelia-openid-0l1htj
Make the Authelia login portal's subdomain configurable, not hardcoded
2026-08-22 13:06:00 -04:00
Claude cd25903865 Make the Authelia login portal's subdomain configurable, not hardcoded
install_authelia() and add_authelia_domain() both hardcoded "auth." as
the login portal's subdomain prefix everywhere -- configuration.yml's
authelia_url, the Caddy portal block/domain, generated README/OIDC
text. No prompt ever offered anything else, despite this repo
otherwise treating "auth.<domain>" as just this one instance's own
choice, not a protocol requirement.

Both now prompt for the portal subdomain (default "auth", so existing
behavior is unchanged for anyone who doesn't care) and use the actual
chosen value throughout. Every function that operates on an EXISTING
domain (remove_authelia_domain, _authelia_add_oidc_client) now reads
the real portal domain back from that domain's own session.cookies
authelia_url entry instead of assuming "auth.<domain>" -- matching the
same read-back pattern _authelia_add_oidc_client already used for the
apex domain itself, and _authelia_provision_oidc_client already used
for the portal URL. _authelia_remove_caddy_portal_block now takes the
portal's full domain directly rather than reconstructing it, so
removing a domain whose portal used a custom prefix actually finds and
removes the right Caddy block.

Also fixed a real, separate small bug found while in here: the
primary portal's Caddy log path was hardcoded to a generic auth.log
(collides across instances/domains) instead of following every other
site block's own <domain>.log convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 17:04:37 +00:00
Outis d3553ee168 Merge pull request #383 from outis1one/claude/frigate-authelia-openid-0l1htj
Serve a keep-alive page instead of Asterisk's own web admin publicly
2026-08-22 12:42:21 -04:00
Claude 5fbc1f2ec5 Serve a keep-alive page instead of Asterisk's own web admin publicly
_asterisk_configure_caddy_public() used to reverse-proxy Asterisk's own
web admin at its public domain, optionally gated by local or remote
Authelia, flipping WEB_ADMIN_AUTH_DISABLED=true in .env to hand auth
off to it. That coupling was the root cause of a real live exposure:
a box where Authelia protection was accepted once, but the Authelia
import/forward_auth block itself later went missing from the Caddyfile
(e.g. lost on a restore), was left with the web admin's own login off
and nothing else gating it -- extension/device data reachable with no
password at all. A remote Authelia's forward_auth also proved fragile
in practice for something that only ever needed to keep a domain's
cert alive (DNS/routing/access-rule mismatches spanning two boxes,
hard to diagnose from either one alone).

This domain now just serves a minimal keep-alive page (a bare "OK" 200
response) so Caddy can still issue/renew the SIP TLS cert -- cert
issuance only needs Caddy to own the site block, it's unrelated to
what the block serves. Auth is now optional Basic Auth handled
entirely inside Caddy itself, no external subrequest, so it can't fail
this way. Asterisk's own web admin is no longer exposed publicly by
this function at all -- reachable only via the CLI:
docker exec -it <container> easy-asterisk

The Security Dashboard's own domain-takeover offer
(_secdash_offer_asterisk_domain in security-dashboard.sh) is the
supported way to put something meaningful on this domain instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 13:02:29 +00:00
Outis 758adf744e Merge pull request #382 from outis1one/claude/frigate-authelia-openid-0l1htj
Add "remove a protected domain" to Authelia's existing-install menu
2026-08-22 00:47:22 -04:00
Outis 560c33f737 Merge pull request #381 from outis1one/claude/nvidia-gpu-flux-2-c7y9fg
docs(ai-stack): give exact claude mcp add commands for gitea-mcp
2026-08-22 00:46:53 -04:00
Claude b0c9d73030 feat(claude-cli): add dual-account setup with model/effort defaults
New extras service: installs the Claude Code CLI, creates separate
work/personal CLAUDE_CONFIG_DIR accounts behind claude-work/claude-personal
aliases, and applies settings.json defaults to both (model=claude-sonnet-5,
effortLevel=medium, ENABLE_PROMPT_CACHING_1H=1). A shared ~/.claude-shared/
CLAUDE.md holds the durable personal conventions (modular/reuse code,
numbered CLI menus with 0=exit, Playwright verification for UI changes)
and both accounts pull it in via @import so there's one copy to maintain.

Login itself (browser OAuth) can't be scripted - this only prepares the
directories/aliases/config; each account still needs one interactive
login. Tested fresh-install, rerun/cancel detection, and the jq settings
merge (preserves hand-added keys) in a scratch HOME.
2026-08-22 04:46:43 +00:00
Claude 3e9f9dbfed Add "remove a protected domain" to Authelia's existing-install menu
add_authelia_domain() (menu option 1) had no reverse operation -- once
a domain was added there was no way to undo it short of hand-editing
configuration.yml and the Caddyfile. remove_authelia_domain() (new
option 2) does the reverse cleanly: removes the access_control.rules
entry, the session.cookies entry, and the auth.<domain> Caddy portal
block for one domain, verified against a synthetic multi-domain
configuration.yml before shipping. Warns loudly that any service still
pointed at the removed domain will stop authenticating, and requires
confirmation before touching anything.

The menu's own text now also flags the likely real mistake this
surfaces: adding a domain that's actually just a SUBDOMAIN of an apex
already on the instance creates a *.subdomain.apex wildcard rule that
doesn't match the bare subdomain itself, plus a redundant separate
auth.subdomain.apex portal -- when the subdomain was already covered
by the existing apex's own wildcard rule and portal all along.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 04:45:45 +00:00
Claude b7411b236e docs(ai-stack): give exact claude mcp add commands for gitea-mcp
Replace the vague "add it with claude mcp add" with real commands for
both stdio (single local CLI) and HTTP (shared server) transport,
verified against gitea/gitea-mcp's actual distribution (binary/Docker/
go run, -t stdio|http flags, GITEA_HOST/GITEA_ACCESS_TOKEN env vars).
2026-08-22 04:29:14 +00:00
Outis f52713b67d Merge pull request #380 from outis1one/claude/nvidia-gpu-flux-2-c7y9fg
Claude/nvidia gpu flux 2 c7y9fg
2026-08-22 00:25:15 -04:00
Outis 3614342807 Merge pull request #379 from outis1one/claude/frigate-authelia-openid-0l1htj
Let Security Dashboard take over Asterisk's public domain
2026-08-22 00:24:47 -04:00
Claude cfee4b292b docs(ai-stack): add local-GPU + Claude Code hybrid workflow section
Covers the CLAUDE.md tiering (user/project/local/one-off task) for
splitting instructions between the local coder model and Claude Code,
plus how Claude Code reads from self-hosted Gitea (plain git vs. the
official gitea/gitea-mcp server for PR/issue-level integration).
2026-08-22 04:22:51 +00:00
Claude 92ebbdf9ef Let Security Dashboard take over Asterisk's public domain
Asterisk's own web admin was only Caddy-fronted at its own domain so
Caddy could issue it a trusted TLS cert for SIP -- cert issuance only
needs Caddy to own that domain's site block, it's unrelated to what
reverse_proxy target the block forwards to. _asterisk_configure_caddy_public
also never rewrites an existing site block on a repeat run, so a box
where WEB_ADMIN_AUTH_DISABLED got set true (from an earlier "protect
with Authelia" answer) but the Authelia import itself never landed or
got lost on a restore was stuck silently unauthenticated with no
reconfigure path ever revisiting it -- confirmed live: a real box was
found exposing its extensions/device list with no login at all.

_secdash_offer_asterisk_domain() now offers, whenever Security
Dashboard's Caddy setup runs (fresh install or reconfigure) and
Asterisk already has a public domain, to serve the dashboard there
instead of a separate subdomain: removes Asterisk's old site block for
that domain, rebuilds it fresh under this dashboard's own (always-on)
Authelia gate, and re-enables Asterisk's own web admin login in .env
as defense-in-depth now that its port isn't published at all.
Declining falls through to the normal separate-domain prompt
unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 04:15:16 +00:00
Claude c703b1c4b4 docs(ai-stack): disambiguate Tesla brand name from Tesla microarchitecture
"Tesla" was NVIDIA's datacenter-card brand (retired after Volta), spanning
four unrelated architecture generations (Kepler/Maxwell/Pascal/Volta) - a
different, much older thing than the Tesla microarchitecture itself, which
actually predates Fermi/Kepler/Maxwell/Pascal/Volta. Clarify to avoid
reading the power-connector note as claiming Tesla == Volta.
2026-08-22 03:55:27 +00:00
Claude 7f23860078 docs(ai-stack): name the R580 driver branch for Volta/Pascal cards
Confirmed via NVIDIA's own release notes: R580 is the last branch
adding Volta/Pascal support (through ~June 2028). Also flag the
proprietary-vs-open kernel module split, since -open only covers
Turing and newer and autoinstall could pick it on a newer distro.
2026-08-22 03:52:39 +00:00
Claude 503945e7c3 docs(ai-stack): correct CUDA deprecation status, add Tesla power/cooling note
CUDA 13 already dropped Pascal/Volta (not a future warning anymore) -
call out pinning the driver branch instead. Also flag the 8-pin
CPU/EPS12V power connector and passive cooling on Tesla PCIe cards,
since it trips up anyone repurposing one in a tower case.
2026-08-22 03:46:06 +00:00
Claude f5a23b06ac docs(ai-stack): note MoE models as a coding option for Pascal/Volta
MoE VRAM tracks total params but compute tracks active params, so a
model like qwen3-coder:30b-a3b (30B total, ~3.3B active) runs light
enough that old GPUs' weak/missing tensor cores barely matter.
2026-08-22 03:41:25 +00:00
Outis a595e45294 Merge pull request #378 from outis1one/claude/nvidia-gpu-flux-2-c7y9fg
docs(ai-stack): add server GPU generation capability table
2026-08-21 23:36:00 -04:00
Outis 2b69cfac1d Merge pull request #377 from outis1one/claude/frigate-authelia-openid-0l1htj
Claude/frigate authelia openid 0l1htj
2026-08-21 23:22:07 -04:00
Claude e54c7827de docs(ai-stack): add server GPU generation capability table
Reference table for Blackwell/Hopper/Ampere/Volta/Pascal/Maxwell covering
Flux 2, Flux.1/SDXL, chat, and coding model capability per generation.
2026-08-22 03:22:02 +00:00
Claude 90da2f5a91 Rename Asterisk container from easy-asterisk to asterisk
New installs now name the container "asterisk", matching every other
service's container_name == service name convention, instead of
reusing the vendored easy-asterisk CLI tool's own name (which stays
/usr/local/bin/easy-asterisk inside the container, unrelated and
unchanged).

An existing "easy-asterisk" install is never silently renamed: every
place that resolves the container name (_asterisk_resolve_layout in
asterisk.sh, plus the duplicated copies in security-dashboard.sh,
sms-inbound.sh, pstn-trunk.sh, and tools/pstn-test-check.sh's docker ps
detection) now reads it from the box's own docker-compose.yml instead
of assuming it, falling back to "asterisk" only when there's no
existing install to read. Migrating a live box to the new name is a
one-time manual action (edit docker-compose.yml's container_name for
Asterisk and its coturn sidecar, docker compose down + up -d); every
sibling service then picks it up automatically on its next run.

The DigitalOcean-droplet layout (asterisk-digital-ocean directory,
easy-asterisk-do container) is untouched by this - that naming stays
exactly as documented for pre-merge droplet installs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
2026-08-22 03:20:36 +00:00