| title | Development setup |
|---|---|
| description | Local development environment for SimpleDeploy, covering prerequisites, dev config, sample apps, make targets, and backend conventions. |
- Go 1.22+
- Node.js 18+
- Docker running locally
Recommended for local dev (hot reload):
make devThis runs both backend (Go, auto-reload via air) and frontend (Svelte, HMR via Vite) in one command.
- Management UI: http://localhost:5173 (Vite, proxies to backend)
- Management API: http://localhost:8080
- Caddy proxy: http://localhost:8080
If you need to develop in a Docker container (e.g., testing Docker networking on Docker Desktop):
make dev-docker # Start in Docker
make dev-docker-rebuild # Rebuild + restart on code changes
make dev-docker-down # StopAccess at https://localhost:8500/ (no hot reload in this mode).
config.dev.yaml at repo root is gitignored so each developer can customize freely. Copy the tracked template on first checkout:
cp config.dev.yaml.example config.dev.yamlDefaults use local CA TLS, /tmp/simpledeploy-dev for data, and domain: localhost. Change domain to e.g. simpledeploy.local and add 127.0.0.1 simpledeploy.local to /etc/hosts for a stable hostname. Trust Caddy's local root CA to skip browser warnings.
Three sample apps in dev/apps/ for testing different features:
| App | What it tests | Direct access | Via proxy |
|---|---|---|---|
| whoami | Proxy/domain routing | http://localhost:9001 | http://whoami.localhost:8080 |
| webapp | Multi-service + postgres backup | http://localhost:9002 | http://webapp.localhost:8080 |
| redis | Volume backup strategy | localhost:6379 | N/A (TCP) |
Deploy all sample apps:
./bin/simpledeploy apply -d ./dev/apps/ --config config.dev.yamlDeploy a single app:
./bin/simpledeploy apply -f ./dev/apps/whoami/docker-compose.yml --name whoami --config config.dev.yamlIf *.localhost domains don't resolve, add to /etc/hosts:
127.0.0.1 whoami.localhost webapp.localhost
| Target | Description |
|---|---|
make dev |
Go backend + UI (both with hot reload) |
make api |
Go backend only (air auto-reload) |
make ui |
Svelte UI dev server only (Vite HMR) |
make build |
Full build (UI + Go) |
make build-go |
Go only (requires ui_dist/) |
make ui-build |
Build Svelte UI |
| Target | Description |
|---|---|
make dev-docker |
Build + run simpledeploy in Docker (~docker compose up) |
make dev-docker-rebuild |
Rebuild binary + restart Docker container |
make dev-docker-down |
Stop and clean up Docker container |
Use make dev-docker when you need the binary in a container (e.g., testing networking features on Docker Desktop). Note: no hot reload in Docker mode; use make dev for faster local iteration.
| Target | Description |
|---|---|
make test |
Run all Go tests |
make e2e |
Full Playwright suite (~20 min) |
make e2e-lite |
Playwright suite without slow specs (~6-8 min) |
make clean |
Remove build artifacts |
go test ./... # all Go tests
go test ./internal/api/ -v # specific Go package
go test ./internal/store/ -run TestUpsert # specific Go test
cd ui && npm test # UI vitest suite (~4s)
make e2e # full Playwright suite (~10-15 min)See Build and test for the full test-placement rules.
- Docker tests skip when Docker is unavailable
- Store tests use temp DB files
- API tests use httptest + real store
- E2E tests build the binary, run a real server + real containers, and verify end-to-end flows. See
e2e/README.mdfor a list of gotchas (container naming, Node fetch+Host header quirk, pg_dump -d, etc.) before writing new functional tests.
- Compose project name is
simpledeploy-<app.Slug>. Containers aresimpledeploy-<slug>-<service>-<replica>. Backup strategies, detection, and any code callingdocker execmust account for this prefix. store.Apphas no JSON tags. Responses from/api/apps/:slugserialize asName,Slug,Status, etc. (PascalCase). Either add tags or handle both cases on the client.- Async deploys return 202.
handleDeployspawns a goroutine withcontext.Background(). Anything that triggers reconciliation from a request handler should do the same.r.Context()is cancelled when the response is sent. - Local backup target stores only the filename in
run.file_path. Resolve against<data_dir>/backups/when reading. superAdminMiddlewarewraps destructive system endpoints (vacuum, prune, audit-clear, audit-config write). Add it to any new endpoint that mutates system-wide state.- Backup strategy credentials come from the container env at exec time via
docker exec ... sh -c '...'reading$POSTGRES_DB,$MYSQL_ROOT_PASSWORD,$MONGO_INITDB_ROOT_*, etc. The scheduler does NOT populateopts.Credentialsfrom container inspection. Don't rely on it. Seedocs/backup-system.md"Credential sourcing pattern". - Proxy handlers must strip port from
r.Hostbefore looking up by domain. Caddy'sr.Hostincludes the listen port (e.g.example.com:8080with curl--resolve), but theRateLimiters/IPAccessRulesregistries are keyed on bare domain.net.SplitHostPortbefore looking up. Deployer.Deploytakes variadicRegistryAuth. If any registry auth is passed, the deploy invokesdocker --config <tmpDir> compose upwith a generatedconfig.json.reconciler.deployAppcallsresolveRegistries(cfg)and threads the result through, so apps withsimpledeploy.registrieslabels can pull private images on initial deploy (not just onpull).- S3 uploads use
manager.Uploader, notPutObject. The backup pipeline streams through pipes that aren't seekable, andPutObjectneeds a seekable body to compute SHA-256. Match this pattern if you add a new S3-based target. - Redis BGSAVE readiness: read
LASTSAVEbefore triggeringBGSAVE. If you read after, a fast save (empty DB) may already have bumped the timestamp, and the poll loop will never observe a change.
cmd/simpledeploy/ CLI entrypoint (cobra commands, wiring)
internal/
api/ REST API + WebSocket handlers
auth/ Password hashing, JWT, API keys, rate limiting
alerts/ Alert evaluator, webhook dispatch
backup/ Strategies (postgres/volume), targets (s3/local), scheduler
client/ HTTP client for remote API, context config
compose/ Compose file parsing, label extraction
config/ YAML config parsing
deployer/ Translates compose specs to Docker API calls
docker/ Docker client wrapper + mock
metrics/ Collector, writer, rollup
proxy/ Caddy embedding, route management, custom modules
reconciler/ Desired-state reconciler, directory watcher
store/ SQLite (all DB access, migrations)
ui/ Svelte SPA (Vite build)
dev/apps/ Sample compose apps for local testing