a7d3dc5b5d4a43bcbd7ce6c879f35d3ce20c4abd
21
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a7d3dc5b5d |
Fix imported file ownership in the generated PikaPods migration script
The generated migrate-from-pikapods.sh (services/mattermost.sh's existing "Migrating from an existing Mattermost instance?" prompt on fresh installs) already correctly parameterizes PROJECT_DIR/MM_CONTAINER/DB_CONTAINER per instance — no bug there. What it missed: after rsync/cp-ing files in from the export, it never touched ownership, so the imported ./data landed owned by whoever ran the script instead of the fixed UID 2000 mattermost/mattermost-team-edition runs as. Every file write then failed with permission denied — confirmed live as the actual cause of a client-side "stream closed" error on image/file uploads after a real migration. Adds chown -R 2000:2000 ./data right after the copy step, and a root check up front since chowning to an arbitrary UID needs it (docker/psql access already implied running as root in practice, just never enforced explicitly). Usage lines updated to say `sudo` to match. Verified by reconstructing the exact generated script from the real source heredocs (head + variable substitution + body, the same three pieces the actual cat/cat>> sequence produces) and syntax-checking the result — root check and chown both land in the right place, and PROJECT_DIR/MM_CONTAINER/DB_CONTAINER still resolve correctly per instance. |
||
|
|
767479d113 |
Self-heal Mattermost data/logs/config/plugins ownership on every start
Root-caused a live "stream closed" image-upload failure to data/20260814/.../mkdir: permission denied — the volumes weren't owned by the fixed UID 2000 mattermost/mattermost-team-edition runs as, most likely left that way by the PikaPods data import. The install script already chown -R 2000:2000's these on every run (fresh or update), so re-running the installer would have fixed it — but that still means remembering to re-run it every time ownership drifts for any reason, including causes this repo doesn't control (a future migration, a manual restore, anything that copies files in as a different UID). Added a small mattermost-fix-perms init container (busybox, chown, exit) that the mattermost service now depends on via condition: service_completed_successfully. Runs on every `docker compose up` — including a plain host reboot, since restart: unless-stopped brings the stack back on its own — so this self-heals permanently instead of needing a human to notice and fix it by hand again. Verified the generated compose file (with representative variable values) against real `docker compose config`: valid YAML, and the dependency graph correctly shows mattermost waiting on both db (service_healthy) and mattermost-fix-perms (service_completed_successfully). |
||
|
|
624ae3d2f3 |
Stop Mattermost's WEB_PORT/CALLS_UDP_PORT rescanning on every update
Found while adding a live scanner to the coturn-slot code: WEB_PORT and CALLS_UDP_PORT were scanned unconditionally, before the reinstall-mode prompt even ran and before anything stopped the currently-running container. On an "Update" run that meant find_free_port would see this instance's OWN already-published port as occupied and silently shift it to the next free one — every plain update could have moved the service's port out from under already-configured Caddy routes, bookmarks, and the Calls plugin's client config, without the operator asking for that. services/asterisk.sh already gets this right for WEB_ADMIN_PORT: update reads the existing port back from .env (no rescan), fresh scans from the plain default only after stopping the old container. Brought Mattermost in line with the same shape — the port resolution moved from before the reinstall-mode block to after it, so MODE is known and, for a fresh install/"Full reinstall", the old containers are already stopped by the time it scans. WEB_PORT/CALLS_UDP_PORT are now also written to .env directly (they weren't before), with a fallback to parse them from the existing MM_SERVICESETTINGS_LISTENADDRESS / docker-compose.yml port mapping for installs made before this change — so an update on an already-running instance doesn't regress just because its .env predates the new variables. Verified the explicit-var, fallback-parse, and priority-order (explicit wins over fallback) cases against a mock before shipping. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
cce8147059 |
Live-verify a newly assigned Mattermost coturn slot isn't already bound
Requested check: the slot-allocation scheme added in the previous commit only checked against OTHER mattermost*/.env files on the box, not against what's actually listening. A slot whose numbers happen to be free by that bookkeeping could still be squatted by something this script doesn't track (a manually-run process, an unrelated service) — this box already learned that lesson once, from Asterisk and Mattermost's embedded coturn ranges overlapping without either side knowing. Only a NEWLY assigned slot gets the live check — an already-cached slot (read back from this instance's own .env) is trusted as-is, since a live conflict on an already-configured, already-running instance's own port is a real problem to report, not something to silently route around by moving that instance's TURN port out from under it. Can't scan the full 200-port relay range port-by-port (large ranges use the offset scheme instead of scanning per CLAUDE.md's port-collision section) — checks the control port plus both relay-range boundaries as the practical middle ground. Verified against a mock: a candidate slot whose control port is already bound gets skipped in favor of the next free one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
4a09d3d1de |
Give each Mattermost instance's embedded coturn its own port slot
Follow-up to the Asterisk/Mattermost relay-range overlap fix: that fix only handled the two-service collision, and left a documented gap for what happens when a second (or third...) Mattermost instance also falls back to embedded coturn — they'd have collided with each other on the same fixed 3479/49253-49452 numbers, same bug, different pair. find_free_port-style scanning doesn't work for the relay range itself — it's a scan for a single free port, not a free contiguous 200-port block — so this follows the same fixed-offset-per-instance approach CLAUDE.md documents for traccar.sh's large port range instead. Each instance gets an integer slot (control port = 3479 + slot, relay range = 49253 + slot*200 through +199) computed once as the smallest slot number not already claimed by another mattermost*/.env on the box, then cached in that instance's own .env as EMBEDDED_COTURN_SLOT so it reads back the same value on every later update or full reinstall instead of potentially landing on a different slot (which would silently move an already-configured instance's TURN port out from under it — the same "never touch what's already the box's answer" rule everything else in update mode already follows). Verified the allocation logic against a mock: first instance gets slot 0, a second gets slot 1 without stepping on the first, both instances keep their own slot across a simulated re-run, and a third new instance correctly lands on the next free slot (2) rather than reusing either. Threaded the computed port/range through every place that used to hardcode 3479/49253/49452: the coturn compose block, the UFW rule (now also labeled with the instance suffix, matching this file's other UFW comments), and the Calls-plugin TURN config text in the generated README/System-Console instructions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
158df0d545 |
Fix embedded-coturn relay-port overlap between Asterisk and Mattermost
Confirmed live on a box that retired the shared coturn service in favor of each service running its own dedicated/embedded coturn permanently: Mattermost's embedded-coturn fallback used relay range 49153-49352, which overlaps Asterisk's embedded coturn range (49152-49252) by ~100 UDP ports. Both run network_mode: host, so with shared coturn out of the picture this is the exact same collision CLAUDE.md documents as the original, already-fixed-once bug that the shared coturn service was built to solve in the first place — reintroduced here because Mattermost's embedded-coturn fallback path apparently never got checked against Asterisk's numbers when it was written. Moved Mattermost's embedded relay range to 49253-49452 (same 200-port width, now contiguous with and non-overlapping Asterisk's 49152-49252). Updated the docker-compose command flags, the matching UFW rule, and added a comment explaining the offset so it doesn't drift back into collision — and noting the known residual gap this doesn't cover: two Mattermost instances *both* falling back to embedded coturn at once would still collide with each other on these same fixed numbers. Not fixed here since it requires more than one Mattermost instance to be running without shared coturn at the same time, which isn't this box's situation; flagged in-code for whoever hits it. Also made asterisk.sh's generated README port table stop unconditionally claiming a TURN relay range it isn't actually publishing when the shared coturn service (not this install's own container) is fronting TURN instead — it now branches on USE_EMBEDDED_COTURN, which the function already receives as a parameter. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
aa65b5ef5b |
Make "Full reinstall" a real teardown for asterisk, mattermost, and coturn
Extends the security-dashboard prototype to the shared-coturn trio, since these three are exactly the case that pattern was built for — a fresh reinstall of any of them today just overwrote files in place without stopping old containers first, and coturn's own fresh path never made an informed choice about the consumer credentials/database it happens to leave alone (safe today, but by omission rather than design). - asterisk.sh / mattermost.sh: "Full reinstall" now stops the existing containers (`docker compose down`) before falling through to the normal install flow, and asks a single explicit question — delete stored data (PBX config/spool/voicemail for Asterisk; Postgres db/uploads/config/ plugins for Mattermost) — defaulting to preserve. Their shared-coturn TURN credential is deliberately left alone either way (reused from cache via ensure_coturn_user(), same as update) — it's not this service's own data, and coturn already handles that continuity. Mattermost's existing "_db_has_data" check already reads the filesystem to decide whether to reuse or regenerate DB_PASS, so the wipe/preserve choice composes with that for free — no separate flag needed. Asterisk's warns to re-run pstn-trunk afterward if data is wiped, since that's what actually goes stale (its dialplan patch), not the fabricated "AMI secret" framing an earlier draft of this warning used before I checked the actual code. - coturn.sh: "Full reinstall" now lists which consumers are currently registered (from users/*.env) and asks explicitly whether to also wipe TURN credentials and the user database, instead of silently preserving them as an unexamined side effect of never deleting the directory. Defaults to preserve. If the operator does choose to wipe, the running container is restarted afterward — it holds the old, now-deleted turndb file open, so new turnadmin writes to the fresh file would otherwise go unseen until a restart anyway. Every affected consumer already self-heals a missing credential on its own next Update run via ensure_coturn_user()'s existing cache-miss path — no changes needed there, just confirmed it covers this case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
ad011b2db8 |
Add check_container_health helper, wired into mattermost.sh as reference
A service's "Started" message after docker compose up -d doesn't mean the app is actually working — it can still crash-loop (bad DB password, missing required env var, etc.) with no visible sign until someone separately runs docker ps -a much later, exactly what happened repeatedly this session (mattermost, koha-db, homebox, vaultwarden, filebrowser all showed a clean "Started" message while crash-looping). check_container_health (lib/common.sh) waits briefly, checks the container's actual status and restart count via docker inspect, and prints recent logs automatically if it's not running or has already restarted — instead of a misleading one-line success message. Wired into mattermost.sh's own start step as the reference implementation, guarded by declare -F so standalone runs (no lib/common.sh sourced) degrade gracefully. Not retrofitted across every other service in one pass — this establishes the shared helper so other services can adopt it incrementally. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
74628f3736 |
Fix vaultwarden SMTP false-positive and mattermost DB password mismatch
vaultwarden: SMTP_PORT defaulted to "587" and SMTP_SECURITY was a
hardcoded "starttls" literal in the .env template, written
unconditionally regardless of whether SMTP_HOST was ever provided.
Confirmed live: skipping SMTP entirely (blank SMTP_HOST) still wrote
real values for those two, and Vaultwarden reads that as "some SMTP
config is present," refusing to start ("Both SMTP_HOST and SMTP_FROM
need to be set") even with host/from genuinely blank. Both now stay
empty unless SMTP_HOST is actually set.
mattermost: DB_PASS/MM_SECRET were only reused from the existing .env
when MODE=update — a "fresh" reinstall always generated a new
POSTGRES_PASSWORD. Confirmed live: choosing fresh after removing only
the mattermost app container (not the whole directory) regenerates the
password in .env while db/'s existing Postgres data still enforces the
OLD one from its first init (the entrypoint skips re-init on existing
data), causing "password authentication failed for user mattermost" on
every start. Whether db/ already has real data is what actually
determines whether the old password is still live, not which reinstall
mode was chosen — reuse the existing secrets whenever db/ is non-empty,
regardless of MODE.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn
|
||
|
|
39e7b2ae6e |
Fix Mattermost crash-looping with permission denied on config.json
The official mattermost/mattermost-team-edition image runs as a fixed UID/GID 2000 baked into the image — it does not read PUID/PGID env vars, that's a LinuxServer.io s6-overlay convention this image doesn't use. This file set them anyway (computed from ACTUAL_USER's uid/gid), which did nothing, while the actual host directories (./data, ./logs, ./config, ./plugins) got chowned to ACTUAL_USER instead of 2000:2000. Confirmed live: the container fails on its very first start with "could not create config file: open /mattermost/config/config.json: permission denied" and crash-loops — which then presents as a 502 from Caddy, an easy trail to follow to the wrong place since Caddy itself was fine. Removed the dead PUID/PGID mechanism and chown the app's own volumes to 2000:2000 after the existing ACTUAL_USER chown. db (postgres:15-alpine) isn't affected — its entrypoint fixes its own volume ownership on startup. Runs on both fresh installs and "update" reruns, so re-running the installer on an already-broken instance self-heals it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn |
||
|
|
9e06ed4b83 |
Bake cross-service port collision avoidance into every service script
With 70+ services sharing a handful of common default ports (emby and jellyfin both default to 8096, changedetection and frigate both default to 5000, arm and nextcloud both default to 8080...), nothing previously checked whether a service's default port was actually free on the host. Whichever service installed second would silently write a compose file claiming an already-held port, only failing at `docker compose up` time. Adds two shared helpers to lib/common.sh: - port_in_use PORT [PROTO] — true if something's already listening - find_free_port VARNAME START [PROTO] — scans upward, writes back the first free port Every service that publishes a fixed host port now scans before writing docker-compose.yml, on every install (not just when adding an explicit additional instance). On a normal single-install host this is a silent no-op; it only changes behavior when something else already holds the port. - The 19 services already given multi-instance support this session had their port scan moved out of the "add instance" branch to run unconditionally, since the same collision risk exists on a plain first install. - 20 more services with previously-hardcoded ports gained scanning for the first time: archivebox, arm, calibre-web, changedetection, drum-rhythm-game, gatus, n8n, nextcloud, onlyoffice, stirling-pdf, uptimekuma, portainer, iopaint (both GPU/CPU compose branches), koha (paired), syncthing (paired), wg-easy (paired, plus WG_PORT env so generated peer configs keep the right Endpoint), homeassistant (bridge-mode only — host mode can only warn), frigate and frigate-audio (multi-port stacks, moved together). - caddy.sh is the deliberate exception: 80/443 stay fixed and only warn on collision, since silently moving Caddy itself would leave nothing listening where any client actually looks. - authelia.sh needs no change — it has no published host port at all. - Every service's standalone bootstrap fallback (sudo bash services/x.sh with no sibling files) got the same two helpers duplicated into its stub block, matching how every other shared helper is already handled there. Documents the full pattern in CLAUDE.md's new "Port collision avoidance" section, including the quoted-heredoc/backtick-escaping gotcha and the network_mode:host limitation (can only scan ports the app takes as a configurable env var). Verified via bash -n on every changed file, plus functional runs seeding occupied ports for each collision shape used here (single, paired, multi-port stacks) and confirming the scan/shift and generated compose/README output are correct — including the emby/jellyfin, nextcloud/arm, and frigate/changedetection collision scenarios that originally motivated this. |
||
|
|
5f36b14f93 |
mattermost: add PikaPods migration helper (DB dump + files import)
New opt-in prompt on fresh/new installs (skipped on "update" reruns, where an existing instance is already in real use and importing over it would be destructive): "Migrating from an existing Mattermost instance (e.g. PikaPods)?" -- if yes, generates migrate-from-pikapods.sh in the instance's own directory, same generated-helper pattern as Immich's import-photos.sh. Checked PikaPods' own docs before writing this rather than guessing at their export mechanics: they expose per-pod SFTP (file access) and a Database-access toggle that hands you an Adminer link for a full SQL dump -- their own documented backup/migration flow is stop the pod, SFTP the files, export the DB via Adminer. The generated script assumes that shape (plain-text SQL dump + a files directory) and says so in its header, including that PikaPods' exact SFTP layout wasn't verified against a live pod so the files-argument path needs the user's own confirmation. What the script does: stops the mattermost container (leaves the DB container running), drops and recreates the database owned by the same existing role -- so .env's credentials are never touched or regenerated, avoiding the "restored data, mismatched password" bug class fixed elsewhere in this repo -- imports the dump via psql, rsyncs the files directory into ./data, restarts. Requires typing "YES" to proceed since it's destructive to whatever's currently in the fresh instance's database. Correctly parameterized per-instance: pulled from install_mattermost's own MM_CONTAINER/DB_CONTAINER variables, so it's already correct for either the first instance or an additional named one. Verified end-to-end: prompt fires correctly at the right point in the flow, generated script is syntactically valid, and the container names/paths it's parameterized with match the actual instance being installed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TBtExJcqxnokyZZKmphdug |
||
|
|
cf3d4bf6de |
Extract coturn into a shared service; add Mattermost multi-instance support
Asterisk and Mattermost each used to embed their own dedicated coturn container (network_mode: host), and their default relay port ranges overlapped by ~100 UDP ports — running both on one box meant a coin-flip over which service's active call lost its media relay. - services/coturn.sh: new shared TURN/STUN relay, one instance for every consumer instead of one each. Runs --lt-cred-mech with a SQLite user database (not --use-auth-secret — coturn doesn't support both auth mechanisms on one instance at once, confirmed via coturn's own upstream docs/issues) so each consumer gets its own dedicated username/password without stepping on any other's. - lib/common.sh: ensure_coturn_user() — chain-installs coturn.sh on first need (same declare -F guard pattern as the existing asterisk -> security-dashboard chaining) and registers/reuses a per-consumer credential, mirroring configure_caddy_for_service's out-param convention. - services/asterisk.sh: _asterisk_write_compose gains a USE_EMBEDDED_COTURN flag. New installs use the shared service; existing installs keep their dedicated coturn exactly as-is on every "update" (detected from the existing compose file before regenerating it, so a rebuild can never silently drop the container its own .env TURN_PASSWORD still points at) and only switch on an explicit "fresh" reinstall, with a warning first. - services/mattermost.sh: same embedded/shared coturn handling, plus genuine multi-instance support (separate dir/containers/DB/ports per instance, auto-scanned free ports for extras) for real isolation between groups, as opposed to Team Edition's built-in Teams feature. Calls plugin TURN config switched from the HMAC "TURN Static Auth Secret" field to the verified "ICE Servers Configurations" JSON field, which accepts the same fixed username/credential shared coturn issues. Also fixes a latent bug found while adding proper update-mode detection: DB_PASS/MM_SECRET were regenerated on every single rerun with no existing-install check at all, silently breaking Postgres auth on any reinstall. - CLAUDE.md: documents the ensure_coturn_user pattern (including the auth-mechanism constraint and the embedded-coturn migration-safety rule) for any future service that needs TURN. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NQkdAn3iG5A4WoqU9FHMaN |
||
|
|
883f0d2557 |
Document restricting DMs to teammates in Mattermost's README
Answers a real gap: Teams alone don't limit who can Direct Message whom — that's a separate System Console setting (TeamSettings.RestrictDirectMessage), free in Team Edition. Documented it in the Teams section along with the caveat that it only filters the DM picker UI, not a hard boundary (existing DMs unaffected, multi-team users can still DM across all their teams). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NQkdAn3iG5A4WoqU9FHMaN |
||
|
|
2fc49fa43e |
Document Teams setup in Mattermost's generated README
Team Edition includes multiple Teams natively (no Enterprise license needed), but nothing in the generated README said so or explained how to create one. Added a Teams section covering creation, adding members, and multi-team membership, plus a one-line pointer in the install summary. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NQkdAn3iG5A4WoqU9FHMaN |
||
|
|
1fc0a6edfe |
Apply the local/remote Caddy mode resolution to every service, not just traccar
traccar.sh's caddy_net wiring was fixed to mirror configure_caddy_for_service's
own mode resolution (CADDY_MODE from site config, then a local ~/docker/caddy,
then the legacy CADDY_REMOTE_HOST var) instead of only checking for the local
directory. That same bare directory check was copy-pasted into the caddy_net
wiring of every other Docker service in the repo, so a site with Caddy on a
different box would silently fail to join any of their containers to caddy_net
during setup (or, for homeassistant/koha, only get half the wiring right).
Applied the same fix mechanically across all 37 services using the standard
_CADDY_NET_BLOCK/_CADDY_NET_SECTION pattern (verified identical text via
scripted diff before touching any of them), plus by hand for:
- homeassistant.sh and koha.sh, which use their own differently-shaped
variables (HA_CADDY_NET_LINES / _CADDY_NET_ENTRY) for the same decision
- paintplus.sh and ai-stack.sh, which do a live `docker network connect`
instead of a compose network block
- watchyourlan.sh, whose Caddy note was worded for local-only setups
sms-inbound.sh got more than a mode swap: its Caddy wiring was hand-rolled
(not routed through configure_caddy_for_service) and had no remote-Caddy
path at all — a remote Caddy box would get a misleading "Caddy isn't
installed here" message instead of a snippet. Added
_sms_write_caddy_snippet(), mirroring the snippet-file pattern
configure_caddy_for_service uses everywhere else, and pointed the firewall
gate at the same three-way mode instead of a two-way dir check.
Verified: bash -n across all of services/*.sh, a scripted check that every
touched file has exactly one _CADDY_MODE resolution and no leftover bare
`[ -d "$DOCKER_DIR/caddy" ]` feeding a caddy_net decision, and spot-checked
docker compose config renders (traccar, mattermost) confirming the ${VAR}
interpolation and multi-service usage sites still resolve correctly.
|
||
|
|
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 |
||
|
|
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 |
||
|
|
e9f05cc127 |
Use stored SITE_DOMAIN as default in Caddy domain prompt
lib/common.sh: configure_caddy_for_service now pre-fills the domain prompt with $DEFAULT_SUBDOMAIN.$SITE_DOMAIN when a site domain has been configured (setup.sh configure / ~/docker/.config). No more typing the full domain for every service — just press Enter to accept the default. services/mattermost.sh: remove redundant custom Caddy/domain block added in the previous commit. MATTERMOST_SITE_URL is already computed from SITE_DOMAIN before configure_caddy_for_service is called, so the simple call is sufficient. https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt |
||
|
|
ab778868df |
Fix Mattermost Calls, add Authelia to Asterisk web admin
Mattermost Calls: - Add 8443/udp to compose ports for the Calls plugin RTC server (WebRTC direct path; coturn relay is only the fallback, not the sole path) - Add 8443/udp to UFW rules and router port-forward table - Warn that WebRTC requires HTTPS — calls silently fail over HTTP - Prompt for Caddy domain and update MATTERMOST_SITE_URL in .env to match the HTTPS URL before Caddy is wired (previously SITEURL was written before the domain was known, leaving it as http://localhost:8065) - Update README with RTC server address field and corrected port table Asterisk web admin: - No built-in auth: add Authelia SSO check matching CLAUDE.md pattern - Set WEB_ADMIN_AUTH_DISABLED=true in .env when Authelia handles auth (prevents double-login prompts) https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt |
||
|
|
d948e86341 |
Add Nextcloud, OnlyOffice, and Mattermost services
Nextcloud: custom Dockerfile (nextcloud:apache + smbclient) for SMB external storage support without AIO. All data uses bind mounts so Kopia/Borg coverage is automatic. Enables files_external app after first boot. OnlyOffice: JWT-secured document server wired to Nextcloud via occ commands and FileBrowser Quantum config.yaml if both are installed. Port 8082. Mattermost: Team Edition + PostgreSQL + dedicated coturn on port 3479 (does not conflict with Easy Asterisk's coturn on 3478). Bind mounts throughout. UFW rules and router port-forward instructions printed at install time. https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt |