0065 โ Zammad is an optional Argo CD service of the dev box
Status: Accepted. Date: 22 October 2026. Supersedes how decision 0064 installs Zammad; its configuration-by-name stays.
Support (Beto) needs a Zammad to be tested against. Decision 0064 installed one
per dev box with make legacy-controller-zammad, a command of the older
controller loop, which main is retiring (decision 0045) and which no longer
provisions Beto's broker there. The Argo dev box (decisions 0040, 0041, 0047,
0048) deployed Beto and Support but no Zammad.
Decision
Zammad is the dev box's first optional Argo CD service, selected per target with
make deploy PROFILES=zammad. gitops/manifests/zammad holds a wrapper chart
around the vendored upstream chart (19.1.3, Zammad 7.2.1), pinned by SHA-256 and
its images by digest, installed by the component gitops/apps/components/zammad
in the bootstrap-owned zammad namespace after the platform.
- Shared PostgreSQL, private Redis. Zammad's role and database are on the
shared PostgreSQL (decision 0048): pharos-infra creates them and publishes
zammad-postgresql. A record written before Zammad existed gains the new password once rather than being refused. - Elasticsearch as one plain StatefulSet, not the ECK operator, which needs cluster-scoped resources the services project may not create.
- Baseline Pod Security. Upstream's privileged root
chmodof the temporary directory is replaced by an init step that runs as Zammad's own user and gives Rails a privateTMPDIR. - Set up after every sync, idempotently. A PostSync hook runs the desk's own
tools from
chart/desk/: the first start from generated logins, the desk's configuration (decision 0064, unchanged), Beto's integration, staff group access and the dev box AAI as sign-in provider. - Zammad adopts Beto's token. The pharos namespace's credential Job already
generates Beto's
ZAMMAD_TOKENandZAMMAD_WEBHOOK_SECRET; it publishes a copy of only those two to thezammadnamespace. Zammad always generates a token's value, so the hook creates the integration user's token (ticket.agent, 100 days, decision 0063) and sets Beto's value through Rails, on standard input, then checks it signs in. Nothing writes into the pharos namespace and Beto never restarts. The alternative, Zammad issuing a token and patching Beto's Secret and Deployment, needed write access from thezammadnamespace into the platform's. - Reached through the edge, signed in through the AAI. The catalogue routes
https://zammad.localtest.me. The AAI gains an opt-in public client type for a service that keeps no secret:pharos-zammaduses PKCE and gets no offline access or token exchange, as GRNET registers the team's Zammad. - The legacy commands are retired with
devops/zammad. Support reset is not needed: Zammad's and Support's databases are on the same shared PostgreSQL, andmake devbox-resetempties both together.
What the first installation showed
dev-iasonas was converted from the legacy layout to the Argo one for this, and the installation exposed defects that unit tests and renders could not:
- the route chart's own profile list lacked
zammad, and its NetworkPolicy needed Zammad's pod label; the GitOps checks now require every profile list to agree and render the route chart with every profile active; - K3s installed before decision 0045 had no registry mirror for in-cluster builds; the k3s role now keeps it on every installation it owns;
- Support's retry job had no egress to the shared PostgreSQL;
- the bootstrap could not read its own mounted Secrets (now
fsGroup), and Rails refused the shared temporary directory (now its ownTMPDIR); - a delivery that ended a child's operation for an earlier revision left Argo nothing to do when the new revision changed no resource, so PostSync hooks never ran at that revision; the delivery now starts that one sync.
On 22 October 2026, with those fixed, dev-iasonas linked the local operator to a
Zammad customer, filed the operator's ticket in Zammad, imported a reply the test
agent wrote there through the webhook, and closed it from Pharos with Zammad
closing it too. Support's contract test passed its create, find, claim, token
permission and route-table checks; its two ticket-update checks failed only on
the adaptor's 10-second timeout. Zammad completed those updates after about 16
seconds of database time: on the dev box the shared PostgreSQL's synchronous
writes to single-node Ceph took up to seconds each (pg_test_fsync: about 9 s per
fdatasync, 22 ms per fsync). That storage latency affects every service on the
shared PostgreSQL and is left to its own investigation.
Consequences
- A dev box tests Support end to end with one command, and Zammad lives with the platform it serves rather than beside it.
- On a dev box Beto's token value changes only when its credential is rotated
(
gitops/manifests/zammad/README.md), not every 90 days as decision 0063 asks of a shared Zammad; its 100-day expiry is renewed by the hook. - Zammad adds about 4 GiB of memory to a dev box that selects it.
- The bootstrap relies on Zammad storing tokens in plain text (7.2.1 does); the contract test and the hook's own sign-in check fail if that changes.
Page source
Source snapshot ยท Revision f928834c8.