menzeljandClaude Opus 4.8 22d9864436 Phase 3: env masking, image updates, port conflicts, resources, templates (0.3.0)
Backend:
- update_service: registry manifest digest check (Docker Hub/ghcr/lscr/private
  v2 token auth) vs local RepoDigests; in-memory cache + background loop
- port_service: parse compose ports, check /proc/net/tcp[6] + docker bindings
- template_service + bundled templates (jellyfin/vaultwarden/uptime-kuma/
  paperless-ngx/gitea) with {{VAR}} placeholders; custom templates in DB
- compose_edit set_resources (deploy.resources.limits/reservations)
- routers: images, ports, templates, editor/set-resources
- Template model; background update task wired into lifespan

Frontend:
- EnvEditor (table + raw, sensitive masking, quick-insert)
- Images page + UpdateBadge + dashboard 'updates available' banner
- PortConflictDialog pre-deploy check on Deploy
- ResourcePanel (CPU/RAM sliders) as editor Limits tab
- Templates page with per-variable instantiate form

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 16:49:38 +00:00

StackPilot

A self-hosted Docker Compose manager for power users and homelab enthusiasts — as intuitive as Dockge, as capable as Portainer for Compose workflows.

Status: Phase 1 (Core) + Phase 2 (Volumes & GPU) + Phase 3 (Quality of Life) complete. Multi-host agents, backups and notifications land in Phase 4.

What works today (Phase 1)

  • File-first stacks — every stack is a plain compose.yaml (+ optional .env) on disk. The DB only stores metadata; nothing is locked in.
  • Auth — JWT access/refresh tokens, bcrypt hashing, admin/user roles, and a first-launch setup wizard that creates the initial admin account.
  • Stack lifecycle — create, edit, clone, delete, and up / down / start / stop / restart / pull / update via docker compose.
  • Live status — running / partial / stopped / error / updating, computed from Docker container labels.
  • Real-time logs — streamed over WebSocket, color-coded per service.
  • Monaco editor — YAML editing with an .env tab and a docker run → compose converter.
  • Dashboard — system resource bar, stack grid with quick actions, and a recent-activity audit feed.
  • Auto-discovery — stacks created outside the UI (any folder under the stacks dir containing a compose file) are picked up automatically.
  • Dark / light theme.

Phase 2 — Volumes & GPU

  • Volume Wizard in the editor (right-hand helper panel): Bind / Named / NFS / SMB-CIFS / tmpfs, with a sandboxed host path browser for bind mounts and a live YAML preview. NFS/SMB driver_opts are generated for you.
  • GPU assignment per service: auto-detects NVIDIA (nvidia-smi) and AMD/Intel (/dev/dri + sysfs), injects the right YAML (NVIDIA deploy.reservations, or /dev/dri passthrough + render/video groups + LIBVA_DRIVER_NAME=iHD for Intel).
  • Device passthrough: lists host USB / serial-TTY / DRI nodes, add per service, plus a guarded privileged toggle.
  • All wizard edits are merged into the compose YAML server-side (robust, validated) and returned to the editor for review before saving.

GPU/device detection needs host visibility. The bundled compose bind-mounts /dev:/dev:ro; NVIDIA additionally requires the NVIDIA container runtime on the host.

Phase 3 — Quality of Life

  • Env editor: table mode with sensitive-value masking (PASS/SECRET/KEY/… auto-detected) + raw mode, plus PUID/PGID/TZ quick-insert.
  • Image update checker: background task compares the local manifest digest with the registry (Docker Hub / ghcr / lscr / private v2 with token auth); update badges on the Images page + an "updates available" banner on the dashboard.
  • Port conflict detector: pre-deploy check against host-bound ports (/proc/net/tcp[6]) and running container bindings, with a confirm dialog.
  • Resource limits: CPU/memory sliders in the editor → deploy.resources.limits.
  • Template library: bundled templates (Jellyfin, Vaultwarden, Uptime-Kuma, Paperless-NGX, Gitea) with {{VARIABLE}} forms; save any stack as a custom template.
  • Healthcheck status surfaced per container in the stack overview.

Architecture

frontend (React + Vite + Tailwind, served by nginx)
    │  proxies /api and /ws
    ▼
backend (FastAPI + docker-py + SQLite)
    │  docker-py + `docker compose` CLI
    ▼
Docker Engine (via /var/run/docker.sock — never exposed to the browser)

Quick start

cd stackpilot
cp .env.example .env
# edit .env and set a strong SECRET_KEY:  openssl rand -base64 48
docker compose up -d --build

Open http://localhost:5009 and complete the first-launch setup wizard to create your admin account.

Configuration

All backend settings are environment variables (see backend/config.py). The most important ones:

Variable Default Purpose
SECRET_KEY (auto, dev only) JWT signing key — set this in prod
STACKS_DIR /opt/stacks Where stack folders live (in-container)
DATA_DIR /data SQLite DB + app data
CORS_ORIGINS localhost Allowed API origins (comma separated)

The host path for stacks is set via STACKS_HOST_DIR in .env.

Local development

Backend:

cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
SECRET_KEY=dev STACKS_DIR=../data/stacks DATA_DIR=../data uvicorn main:app --reload --port 5008

Frontend (proxies to the backend on :5008):

cd frontend
npm install
npm run dev   # http://localhost:5173

API surface (Phase 1)

POST   /api/auth/setup | login | refresh        GET /api/auth/me | needs-setup
GET    /api/stacks                              POST /api/stacks
GET    /api/stacks/{id}                          PUT /api/stacks/{id}   DELETE /api/stacks/{id}
POST   /api/stacks/{id}/{start|stop|restart|pull|update|down|clone}
GET    /api/stacks/{id}/logs                     GET /api/stacks/{id}/export
POST   /api/stacks/convert                       (docker run → compose)
GET    /api/system/info | gpus | devices         GET /api/audit
WS     /ws/logs/{stack_id}[/{service}]           WS  /ws/events

Phase 2 endpoints

GET    /api/volumes | /orphaned                  DELETE /api/volumes/{name}
POST   /api/volumes/prune                        POST /api/volumes/generate-yaml
GET    /api/host/paths?path=&show_hidden=        (sandboxed browser)
POST   /api/editor/services | add-volume | set-gpu | add-device | remove-device | set-privileged

Phase 3 endpoints

GET    /api/images | /updates                    POST /api/images/check
POST   /api/ports/conflicts                       POST /api/editor/set-resources
GET    /api/templates | /{id}                     POST /api/templates/{id}/instantiate
POST   /api/templates                             DELETE /api/templates/custom/{slug}

Security notes

  • The Docker socket is only ever touched by the backend process; it is never proxied to the browser.
  • Login is rate-limited (10/min/IP).
  • Compose files are backed up to *.bak before every overwrite.
  • Generated YAML never includes the obsolete version: field and uses Compose v2 (docker compose) syntax.
S
Description
No description provided
Readme
1.1 MiB
Languages
Python 55.4%
TypeScript 44.1%
CSS 0.3%
Dockerfile 0.2%