initial commit

This commit is contained in:
2026-06-30 13:51:06 -04:00
commit d529284141
10 changed files with 439 additions and 0 deletions

91
README.md Normal file
View File

@@ -0,0 +1,91 @@
# container_isolation Ansible role
Creates per-app service accounts (UID/GID 2000+) on every host, so each
Docker container can run as its own dedicated UID instead of root or a
shared user. `jerick` is added as a secondary member of every app
group (and the shared `mediapipeline` group), so jerick retains access
everywhere regardless of whatever folder permissions you set up
separately on the NFS server.
**Scope:** this role only manages accounts (groups + users). NFS
folder creation, ownership, and permission bits are handled outside
Ansible, by you, on the NFS server.
## Layout
```
ansible/
├── site.yml # top-level playbook, hosts: all
└── roles/container_isolation/
├── tasks/
│ ├── main.yml # entry point, includes the others
│ ├── sync_users.yml # creates groups + users on every host
│ └── jerick_access.yml # adds jerick to every group, every host
├── vars/main.yml # source of truth: app list, uids, shared groups
└── files/
├── passwd.containers # reference copy, human-readable
└── group.containers # reference copy, human-readable
```
`vars/main.yml` is what Ansible actually reads. The `files/*.containers`
files are a human-readable reference / diff-friendly changelog — not
consumed directly by any task, since the built-in `group`/`user`
modules create accounts idempotently rather than appending raw lines
to `/etc/passwd`.
## Before running
1. Point this at your dynamic inventory however you normally do, e.g.:
```bash
ansible-playbook -i your_dynamic_inventory.py site.yml
```
No inventory group targeting is needed — `site.yml` runs against
`hosts: all`, and the role applies the same logic everywhere.
2. Confirm `jerick` already exists as a real user on every host. The
role does **not** create jerick's account (treated as a
pre-existing human user) — it only adds jerick to the app groups.
If jerick is missing on a host, the role prints a warning and skips
the group-membership tasks for that host rather than failing the
whole run.
## Running
```bash
ansible-playbook -i your_dynamic_inventory.py site.yml --check --diff # dry run first
ansible-playbook -i your_dynamic_inventory.py site.yml
```
Safe to re-run any time — every task uses Ansible's built-in
idempotent modules (`group`, `user`), so a second run produces no
changes.
## Adding a new app later
1. Add a line to `roles/container_isolation/vars/main.yml` under
`container_apps`, with the next free UID (currently up to 2026 —
use 2027 next). **Never reuse or renumber an existing UID** once
real folders have been chowned to it on the NFS server.
2. If it needs shared access to another app's data, add it to the
relevant `shared_groups[].members` list (or create a new shared
group, GID 3001+).
3. Update `files/passwd.containers` and `files/group.containers` to
match, for the human-readable record.
4. Re-run the playbook.
## What you still need to do yourself
- **NFS folder creation/ownership/permissions** on the NFS server —
`chown <uid>:<gid>` and `chmod` each app's folder using the UIDs/GIDs
from `vars/main.yml`. With jerick in every app's group, `770`
(owner+group rw, others none) gives jerick read-write access
everywhere while keeping apps isolated from each other; `750` would
make jerick read-only.
- **`/etc/exports`** on the NFS server — not touched by this role.
- **`docker-compose.yml` edits** — add `user: "UID:GID"` (and
`group_add:` for apps in `mediapipeline`) to each service, using the
UIDs from `vars/main.yml`. Happy to generate these once you share
your compose files.
- **NFS protocol version / idmapping verification** — confirm with
`nfsstat -m` on a client before relying on numeric UID/GID matching
across hosts; NFSv4 idmapping misconfiguration is the most common
cause of permissions silently not working as expected.