Beschrijf dat systemd_user.reachable afgeleid is van helper.ok, dat de container zelf geen D-Bus/systemctl aanroepen doet, en dat alle systemctl-acties (incl. daemon-reload) via de helper-socket lopen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
podman-mvp is a Portainer-like web dashboard for managing rootless user-session Podman containers. It runs as a two-container Podman pod: a FastAPI backend (mvp-backend) that talks to Podman over a Unix socket, and a static Apache frontend (mvp-webui) that reverse-proxies /api/ to the backend.
Architecture
Backend — FastAPI modular monolith (control/)
| File | Role |
|---|---|
app.py |
Bootstrap only — creates FastAPI app, wires routers, no feature logic |
common.py |
Shared helpers: Podman HTTP, systemctl, utilities |
app_system.py |
System/platform router: /health, /daemon-reload, systemctl unit actions |
app_containers.py |
Containers router: dashboard, inspect, logs, stats stream, exec sessions |
app_pods.py |
Pods router: dashboard, pod actions |
app_networks.py |
Networks router |
app_images.py |
Images router |
app_files.py |
Files/workloads router: tree, read, save |
Backend communicates with Podman through the Unix socket at /run/user/1000/podman/podman.sock using requests_unixsocket. Podman API base: http+unix://%2Frun%2Frun%2Fuser%2F1000%2Fpodman%2Fpodman.sock/v5.4.2.
Frontend — Static Apache (webui/)
webui/html/index.html— single-page app shellwebui/html/assets/js/tabs/— per-tab JavaScript modules (containers, networks, images, files)webui/conf/httpd.conf— Apache config, proxies/api/→http://127.0.0.1:8000/api/
Build & Deploy
# Build backend image
podman build -t mvp-control:latest control/
# Create pod
podman pod create --name mvp-pod -p 8080:8000 -p 8081:8081 --userns=keep-id
# Run backend
podman run -d --pod mvp-pod --name mvp-backend \
--ipc=host --pid=host \
-e XDG_RUNTIME_DIR=/run/user/1000 \
-v /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:rw \
-v /run/user/1000/podman-mvp:/run/podman-mvp \
-v /home/kodi/.config/containers:/app/workloads:rw \
mvp-control:latest
# Run frontend
podman run -d --pod mvp-pod --name mvp-webui \
-v $HOME/.config/podman-mvp/webui/html:/usr/local/apache2/htdocs:ro \
-v $HOME/.config/podman-mvp/webui/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro \
docker.io/library/httpd:2.4
Verification Commands
# Syntax check all backend modules
python3 -m py_compile control/app.py control/common.py control/app_system.py \
control/app_containers.py control/app_pods.py control/app_networks.py \
control/app_files.py control/app_images.py
# Smoke test key endpoints (all via proxy on :8081)
curl -fsS http://127.0.0.1:8081/api/health | jq
curl -fsS http://127.0.0.1:8081/api/containers-dashboard >/dev/null && echo OK
curl -fsS http://127.0.0.1:8081/api/pods-dashboard >/dev/null && echo OK
curl -fsS http://127.0.0.1:8081/api/files/tree >/dev/null && echo OK
curl -fsS http://127.0.0.1:8081/api/networks/meta | jq
All test/verification URLs must target 127.0.0.1:8081 (the proxy), not port 8000 directly.
Health Check (/api/health)
GET /api/health geeft drie deelresultaten terug:
| Veld | Wat het meet | Techniek |
|---|---|---|
podman.ok |
Podman API bereikbaar | HTTP GET /libpod/info op Unix socket |
helper.ok |
podman-helper socket bereikbaar | TCP connect op /run/podman-mvp/podman-helper.sock |
systemd_user.reachable |
Afgeleid van helper.ok |
Identiek — helper draait als host-user en voert systemctl --user uit, dus bereikbaarheid van helper impliceert bereikbaarheid van systemd |
ok (toplevel) is true als én podman.ok én helper.ok waar zijn.
De container voert zelf geen systemctl --user of D-Bus aanroepen uit. Alle systemctl-acties (start/stop/restart/daemon-reload) gaan via de helper-socket. D-Bus en /run/user/1000/bus zijn niet gemount.
Hard Rules
Module placement
app.pyis bootstrap-only — no endpoints, no feature logic, no Podman/systemctl calls.- New system/platform endpoints →
app_system.py. - New domain feature endpoints → the corresponding
app_<domain>.py. - Shared helpers →
common.py, never duplicated into routers. allow_list/allowed_units.txthas been removed and must NOT be reintroduced.app_system.pybroad wildcard routes (/{action}/{unit}) must be defined last.
API contract (contracts/API_GOLDEN.md)
- Never remove or rename existing JSON response keys.
- Never change existing key data types.
- Extend via new optional fields or new endpoints only.
- UI-critical endpoints requiring pre-approval before any change:
/containers-dashboard,/pods-dashboard,/images,/networks/meta.
Security
- No
shell=Truein subprocess calls. - All subprocess commands must be explicit lists.
Infrastructure (propose before changing)
- Pod name, port mappings,
userns=keep-id. - DBus/XDG_RUNTIME_DIR mounts, Podman socket path, host PID/IPC namespaces.
control/Containerfile,webui/conf/httpd.conf.
Change Workflow
For non-trivial changes, follow PR_RULES.md:
- Analyse existing behaviour with curl.
- Propose minimal plan identifying affected files.
- Confirm API contract safety.
- Provide curl validation commands showing expected output change.
- Implement after agreement.
Minimize diff size. Do not reformat unrelated code. No large rewrites or hidden refactors.