Initial commit: StackPilot Phase 1 (Core)
Self-hosted Docker Compose manager. - Backend: FastAPI + docker-py + SQLite (JWT auth, file-first stacks, lifecycle, live status, WebSocket logs, docker-run converter, audit log) - Frontend: React + Vite + Tailwind (login/setup, dashboard, stacks, stack detail, Monaco editor, dark/light theme) - Deployment: docker-compose.yml, Dockerfiles, nginx reverse proxy Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# 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) complete. Volume/GPU wizards, image-update checks,
|
||||
> templates, multi-host agents and backups land in later phases.
|
||||
|
||||
## 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.**
|
||||
|
||||
## 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
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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):
|
||||
|
||||
```bash
|
||||
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 GET /api/audit
|
||||
WS /ws/logs/{stack_id}[/{service}] WS /ws/events
|
||||
```
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user