feat: podman-compose stack units and root/user execution scopes

- syncup: podman first, docker only as fallback (podman wins on name clash;
  existing docker units found in podman switch to podman)
- syncup: group podman-compose containers into one `kind: stack` unit per
  project (project, working_dir, compose_files, compose_bin from labels);
  disable existing member units ("part of stack <project>")
- generator: compose mode (podman-compose up/stop, WorkingDirectory) with
  pod start/stop fallback when compose binary/dir/files are missing
- reconcile: stacks disabled with "stack not found" when neither compose
  files nor pod exist
- root: scan root + rootless users listed in `users:` (podman only)
- non-root: config ~/.config/unitdore/units.yaml, own user units only
- sysuser package: runuser with XDG_RUNTIME_DIR/DBUS env, home/linger lookup
- install: warn when linger is not enabled for user units
- testdata/stack: podman-compose test stack and captured podman ps fixture
- docs: README, generated-units, man page, AGENTS, PLAN
This commit is contained in:
2026-10-12 19:05:51 +02:00
parent cc4829046d
commit f0827fcdd7
26 changed files with 1397 additions and 122 deletions
+13 -1
View File
@@ -30,7 +30,9 @@ make release-version # Bump patch version, commit, tag, and push
cmd/ # Cobra commands (edit, install, list, root, start, startall,
# status, stop, stopall, syncup, uninstall, update)
config/ # Config struct + YAML load/save (units.yaml)
runtime/ # Docker and Podman runtime abstraction
runtime/ # Docker and Podman runtime abstraction, compose labels
sysuser/ # run commands as root/user (runuser), home/linger lookup
testdata/stack # podman-compose test stack + captured `podman ps` fixture
systemd/ # .service file generator and systemd manager
docs/ # generated-units.md (unit file examples), unitdore.1 (man page)
```
@@ -48,6 +50,7 @@ docs/ # generated-units.md (unit file examples), unitdore.1 (man page)
```yaml
prefix: "" # prepended to service file name (e.g. "prod-")
suffix: "" # appended to service file name (e.g. "-svc")
users: [] # root only: rootless users scanned by syncup
units:
- name: nginx
@@ -61,8 +64,15 @@ units:
restart: false # Restart=on-failure
restart_sec: 0 # RestartSec
restart_retries: 0 # StartLimitBurst
kind: container # container | stack (podman-compose project)
project: "" # stack: compose project
working_dir: "" # stack: compose dir (from labels)
compose_files: [] # stack: relative to working_dir
compose_bin: "" # stack: podman-compose path
```
Non-root runs use `~/.config/unitdore/units.yaml` and manage only own user units.
### Generated service file locations
| Scenario | Path |
@@ -82,6 +92,8 @@ units:
Tests exist in:
- `config/config_test.go`
- `runtime/runtime_test.go`
- `cmd/syncup_test.go`
- `sysuser/sysuser_test.go`
- `systemd/generator_test.go`
Always run `make test` before marking a task complete. Add tests for new behaviour in the same package as the code under test.