feat(fleet): normalize docker deploy trees to root:docker setgid
Operator ruling: root:docker, not a personal username and not a new admin account. lkraven is one of three names he uses, so baking it into shared infrastructure guarantees a stale owner later; a dedicated deploy account buys nothing the existing docker group doesn't, since that group already exists on every host holding exactly lkraven + infra-ops. Applied to nh3-dev, nh3-docker, esh-docker-vm, irv-ml1, ana-docker. All five now 2775 root:docker on /opt/docker and /opt/docker/compose. Clears the 0777 on nh3-docker and ana-docker. 55 stack .env files normalized to root:docker 0640, tightening 43 world-readable ones and opening 31 that were readable by only one of the two deploy identities. No containers bounced — inode metadata only, and .env is read at compose up. Deliberately not a recursive chmod. Three acme.json files and an ssh private key are mode 0600 and traefik/ssh refuse to start if that widens, which would have been a delayed failure surfacing at the next restart rather than now. Protection is both mode-based (0600/0400 untouched) and name-based (acme.json, *.key, *.pem, *.pfx, id_*); modes are symbolic so the 53 executable files in these trees keep their exec bit. Two defects found and fixed mid-rollout. The name list was initially reported but not enforced, so a .key already at 0644 on esh-docker-vm was widened to 0664 — reverted, and the list is now enforced in the chgrp and widening steps. And the exec-bit verify asserted every .sh is executable, which was never true and false-FAILED irv-ml1; it now compares the executable-file count against a recorded baseline.
This commit is contained in:
@@ -43,10 +43,20 @@ local Bash already executes here — no SSH-to-self needed for non-privileged wo
|
||||
`rc=1 permission denied`, sudo retry `rc=0 Container beszel-agent Started`.
|
||||
A false FAILED in automation output is worse than a quiet one; it trains
|
||||
readers to skim the failure lines.
|
||||
- **`/opt/docker/compose` ownership — nh3-dev is the fleet outlier.**
|
||||
`root:root` here; `lkraven:lkraven` on irv-ml1, nh3-docker, ana-docker and
|
||||
esh-docker-vm. So "can a project session deploy its own stack" is false only
|
||||
on the box where sessions actually run. `/opt/docker/compose/talk` was created
|
||||
- **`/opt/docker` ownership — normalised fleet-wide 2026-09-14 to
|
||||
`root:docker 2775`** (setgid) via `playbooks/normalize-docker-tree.yaml`,
|
||||
operator ruling. Was a three-way split: `root:root 755` here, `root:root 777`
|
||||
on nh3-docker + ana-docker (world-writable, from a 2024 `chmod -R 777` to get
|
||||
a git clone working), `lkraven 755` elsewhere. Not a personal username
|
||||
(`lkraven` is one of three the operator uses) and not a new admin account —
|
||||
the `docker` group already existed on every host holding exactly `lkraven` +
|
||||
`infra-ops`. ⚠ This is **not** privilege separation: `docker` membership is
|
||||
root-equivalent. A future non-root deployer needs a dedicated `deploy` group.
|
||||
Stack `.env` files went to `root:docker 0640` — previously 31 of 74 were
|
||||
`0600` readable by only ONE of the two deploy identities (varying by file,
|
||||
which is what false-FAILED beszel during the docker-ce upgrade) and 43 were
|
||||
world-readable `0644`. **No containers were bounced**; these are inode
|
||||
metadata changes and `.env` is read only at `compose up`. `/opt/docker/compose/talk` was created
|
||||
`lkraven`-owned 2026-09-14 and **tts-dev migrated `talk` into it the same
|
||||
day** — it had been at `~/talk`, a convention violation that hid it from
|
||||
anything walking `/opt/docker/compose/*/`. Old path parked at
|
||||
|
||||
Reference in New Issue
Block a user