# [2026-08-23] Every secret-bearing `.env` on ana-docker tightened to 0600

Found while taking uptime ownership of hrafn: its `.env` was mode 0644 with a live
bearer token. Not a hrafn lapse — **0644 was the de facto pattern on the host**.
Eight stacks carried secret-shaped vars in world-readable `.env` files on a box with
four interactive accounts, verified as real exposure by reading one as `nobody`.

Swept: **vaultwarden, traefik**, beszel, gitea-runner, miniflux, news-digest,
searxng, vor. (hrafn and nevermore were fixed separately the same day.) Six other
stacks already used 0600, so this converged on the existing house pattern rather
than inventing one. Post-sweep the host has **zero** secret-bearing `.env` readable
by `nobody`.

Playbook: `playbooks/tighten-env-perms.yaml`, one run per stack, re-runnable.

## The check that matters

Every run asserts `docker compose config` still renders **as the deploy user**
(`lkraven`), not as root. Checking the mode proves the bits changed; only rendering
as the deploy user proves the next deploy can still resolve its variables.

## Two gotchas recorded in the playbook

- **vaultwarden looked like it bind-mounted its `.env`** — which would mean the
  *container's* UID reads it and 0600 could break the password vault. It does not:
  that `- .env` is under `env_file:`, not `volumes:`. My grep matched the YAML list
  item without checking its parent key. The playbook now **refuses** any stack that
  genuinely bind-mounts its `.env`, since that case is read by the container UID.
- **elway prompted for a sudo password.** The `ana-docker` ssh alias resolves to
  `lkraven`, who needs one; **`infra-ops@10.250.50.70` has NOPASSWD**. `corviduo-dev`
  was repointed to infra-ops at some point and `ana-docker` was not. Run elway against
  the infra-ops target on this host.

Commit `a896c0a`.
