16 KiB
Faro: Docker Engine Management UI
Living project plan. Add ideas to the backlog, record architectural choices in the decision log, and promote accepted work into a milestone.
1. Product vision
Faro is a small, self-hosted control plane for managing one or more Docker Engines. It provides a clear web UI, an automation-friendly API, and CLI tools, with special attention to easy deployment, reliable backups, and operational visibility.
The initial product should be useful to an individual operator or a small team. It is not intended to replace a full container orchestrator such as Kubernetes.
2. Product principles
- Easy to deploy: a single server binary and container image, with sensible defaults and a documented Docker Compose installation.
- API first: every management operation available in the UI is exposed by a stable, documented API and can be automated.
- Safe by default: destructive actions require explicit confirmation; credentials and Docker access are narrowly scoped.
- Recoverable: configuration, metadata, and named volumes can be backed up, verified, and restored through repeatable workflows.
- Visible: users can quickly understand engine health, resource usage, container state, recent events, and job outcomes.
- Small operational footprint: avoid required external services for the single-node installation.
3. Users and core journeys
Primary users
- A self-hosting user managing one or more Docker hosts.
- A small operations team that needs shared visibility and controlled access.
- An automation author using the REST API or CLI.
Core journeys
- Deploy Faro with Docker Compose and complete first-run setup.
- Register a local or remote Docker Engine and verify connectivity.
- View engine, container, image, network, and volume status.
- Start, stop, restart, inspect, and view logs for a container.
- Create and restore a backup of Faro state and selected Docker volumes.
- Diagnose failures through events, job history, logs, and health information.
- Perform the same common operations using the CLI or API.
4. Initial scope
MVP
- Single Faro server instance.
- Local Docker socket and remote Docker Engine connections over TLS/SSH.
- Engine list and health summary.
- Read-only inventory for containers, images, volumes, and networks.
- Container lifecycle operations and streaming logs.
- Engine event stream and basic CPU, memory, disk, and container metrics.
- Scheduled and on-demand backups of Faro state and selected named volumes.
- Local filesystem backup target, with a provider interface for object storage.
- Backup retention, integrity verification, and guided restore.
- REST API with an OpenAPI specification.
- CLI for engines, containers, backups, health, and authentication.
- Web UI built with Vue 3 and Vuetify0.
- Web UI page for listing containers from the Docker Engine API.
- Initial administrator account, API tokens, and a basic audit log.
- Docker image, Compose file, health check, and upgrade documentation.
Later
- Multi-user roles and granular permissions.
- S3-compatible and other remote backup targets.
- Compose application/stack management.
- Image updates, registry management, and vulnerability information.
- Notifications and alert routing.
- High availability and multiple Faro server replicas.
- Agent-based engine connectivity for restricted networks.
- Swarm-specific management.
Explicitly out of scope for the first release
- Kubernetes or non-Docker runtimes.
- A general-purpose terminal in the browser.
- Full orchestration or scheduling across engines.
- Building a container registry.
5. Proposed architecture
Browser (Vue + Vuetify) CLI
| |
+------ HTTPS API ----+
|
Faro server (Go)
+-----------+------------+
| | |
SQLite Job runner Event/metric cache
|
Docker client layer
+---------+---------+
| |
Local socket Remote engines
(TLS or SSH)
Backend
- Go service organized as a modular monolith.
- Versioned REST endpoints under
/api/v1. - OpenAPI is the API contract and drives documentation/client generation where practical.
- Docker Engine SDK behind an internal interface so connectivity and tests can use alternate implementations.
- SQLite for the default installation; keep persistence boundaries clean enough to support PostgreSQL later if demand justifies it.
- Persistent job records for backups and other long-running operations.
- Server-Sent Events (SSE) for logs, events, job progress, and live status; introduce WebSockets only if bidirectional streaming becomes necessary.
- Structured JSON logs and Prometheus-format application metrics.
- Embed the production frontend in the Go binary for a simple single-artifact deployment; allow separate frontend/backend processes in development.
Frontend
- Vue 3, TypeScript, Vite, Vuetify 3, Vue Router, and Pinia.
- Generated or typed API client based on OpenAPI.
- Primary views: overview, engines, engine detail, containers, container detail, storage, backups, jobs, audit log, and settings.
- Responsive layout, keyboard-accessible actions, clear empty/error/loading states, and a dark theme.
CLI
- Go CLI shipped as a separate
faroctlbinary. - Reuse generated API types/client rather than connecting directly to Docker.
- Human-readable tables by default;
--output jsonfor automation. - Configuration profiles for server URL and credentials.
- Stable exit codes, non-interactive flags, and shell completions.
6. Key domain areas
Engine connections
- Store engine name, endpoint type, labels, connection state, and last check.
- Support local Unix socket, TLS-protected TCP, and SSH connection strategies.
- Encrypt stored credentials at rest with a user-supplied master key.
- Never expose Docker credentials or raw private keys through API responses.
- Use timeouts, reconnect backoff, and explicit capability detection.
Backups and restores
- Treat backups as durable jobs with progress, logs, status, and cancellation.
- Back up Faro's database/configuration separately from Docker volume data.
- Quiesce supported workloads with optional pre/post hooks; clearly label crash- consistent backups when a workload is not paused.
- Stream volume archives without staging the full archive in memory.
- Produce a manifest containing versions, contents, timestamps, checksums, and source engine identity.
- Verify checksums after creation and before restore.
- Apply retention by count and/or age, with a dry-run preview.
- Restore to an alternate volume name by default; overwriting an existing volume requires explicit confirmation.
- Document recovery when the Faro service itself is unavailable.
Visibility
- Engine availability and Docker version.
- Container state, health check, restart count, uptime, and resource usage.
- Host CPU, memory, filesystem, and Docker storage usage.
- Recent Docker events and Faro audit events.
- Backup/job duration, result, bytes processed, and last successful run.
- Correlation/request IDs across API errors, jobs, and structured logs.
Security
- Document that access to the Docker socket is effectively host-level control.
- Run the server as a non-root user where the connection method permits it.
- Password hashing with a modern memory-hard algorithm; short-lived sessions and revocable API tokens.
- CSRF protection for cookie-authenticated browser requests, strict CORS, secure headers, request size limits, and rate limiting on authentication endpoints.
- Audit authentication, engine changes, lifecycle actions, backup restores, and token changes without logging secrets.
- Pin minimal container base images and publish an SBOM and checksums for releases.
7. API outline
The exact resources will be defined in OpenAPI before implementation. Candidate resource groups:
/api/v1/session,/api/v1/tokens/api/v1/engines/api/v1/engines/{engineId}/containers/api/v1/engines/{engineId}/images/api/v1/engines/{engineId}/volumes/api/v1/engines/{engineId}/networks/api/v1/backup-targets,/api/v1/backup-policies,/api/v1/backups/api/v1/jobs,/api/v1/events,/api/v1/audit-events/api/v1/health,/api/v1/version,/metrics
API conventions to decide early:
- Resource IDs, pagination, filtering, sorting, and timestamp format.
- Standard error envelope with a stable machine-readable error code.
- Idempotency behavior for mutating and long-running requests.
- Optimistic concurrency or preconditions for configuration changes.
- SSE event envelope, resume behavior, and connection limits.
- Compatibility and deprecation policy for
/api/v1.
8. Delivery milestones
Each milestone should end with a runnable increment, documentation, and tests.
M0 — Validate and scaffold
- Confirm target users and the exact MVP scope.
- Resolve the open decisions listed below.
- Write threat model for Docker access, credentials, and restores.
- Create repository layout for server, CLI, web app, API spec, and docs.
- Establish formatting, linting, unit tests, and CI.
- Add a development Compose environment and sample Docker Engine.
- Add a minimal end-to-end smoke test.
Exit: one command starts the development stack; CI builds and tests all components.
M1 — Engine connectivity and read-only inventory
- Implement configuration, database migrations, health, and version APIs.
- Add local socket engine registration and connectivity checks.
- Add remote TLS and/or SSH connectivity based on the M0 decision.
- Implement read-only container, image, volume, and network APIs.
- Build overview, engine list, and engine detail UI.
- Add equivalent
faroctl engineand inventory commands. - Add integration tests against supported Docker versions.
Exit: a user can register an engine and inspect its resources through the web UI, CLI, and API.
M2 — Container operations and live visibility
- Add start, stop, restart, and inspect operations with audit records.
- Add log streaming with bounded history and redaction guidance.
- Consume Docker events and expose an SSE stream.
- Collect and display basic engine/container resource metrics.
- Add operation confirmation, actionable errors, and reconnect states.
- Add permission and failure-path tests.
Exit: a user can safely operate and troubleshoot containers in near real time.
M3 — Backup and restore
- Implement persistent background jobs and progress streaming.
- Implement local filesystem target and backup manifests.
- Add named-volume backup, checksums, retention, and verification.
- Add scheduled backup policies with timezone handling.
- Add guided restore, collision protection, and restore validation.
- Back up and restore Faro's own state.
- Run documented disaster-recovery tests on clean infrastructure.
Exit: scheduled backups and tested restores work from the UI, CLI, and API.
M4 — Authentication, hardening, and release
- Implement first-run admin setup, sessions, and API tokens.
- Encrypt stored engine credentials and define key rotation/recovery.
- Complete audit log UI/API and security controls.
- Add retention/cleanup for events, metrics, jobs, and audit data.
- Load-test event streams, logs, and representative engine counts.
- Build a minimal production image, Compose example, and upgrade flow.
- Publish operator, backup recovery, API, and CLI documentation.
- Add release automation, SBOM, checksums, and signed artifacts.
Exit: the first supported release can be installed, upgraded, monitored, and recovered using published documentation.
9. Testing strategy
- Go unit tests for domain logic, validation, retention, and authorization.
- API contract tests against the OpenAPI schema.
- Integration tests using disposable Docker Engines and temporary volumes.
- Frontend component tests for important state and permission variants.
- Playwright end-to-end tests for the web UI, including setup, engine registration, container operations, backup, and restore.
- Restore tests must compare checksums and application-level sample data.
- Compatibility matrix for supported Docker Engine and browser versions.
- Security checks for dependencies, container images, secrets, and common web vulnerabilities.
10. Deployment and operations
Start with three supported modes:
- Docker Compose with Faro connecting to the local Docker socket.
- Docker Compose with Faro managing remote engines over TLS/SSH.
- Standalone binaries for the server and CLI.
Required operational features:
- Environment variables and a configuration file, with documented precedence.
- Persistent data directory and an explicit master-key mechanism.
- Liveness and readiness endpoints.
- Graceful shutdown for HTTP streams and active jobs.
- Schema migration and downgrade/rollback guidance.
- Configurable structured logs and Prometheus metrics.
- Versioned release notes with breaking-change and backup warnings.
11. Open decisions
Record the result and rationale in the decision log.
- D-001: Confirm Vue 3 + Vuetify 3 (assuming “Vuetify0” was a typo).
- D-002: Choose the Go HTTP router and OpenAPI generation approach.
- D-003: Choose database access/migration libraries.
- D-004: Decide whether the MVP includes both TLS and SSH remote engines.
- D-005: Define the authentication bootstrap and master-key experience.
- D-006: Decide whether backups run directly through the Docker API or via a short-lived helper container.
- D-007: Define supported Docker Engine versions and maximum tested scale.
- D-008: Define license and release/distribution channels.
- D-009: Choose a metrics retention model: live-only, local time series, or integration with an external metrics system.
12. Success measures
Initial targets; adjust after a prototype and user feedback.
- A new user can deploy Faro and connect the local engine in under 10 minutes.
- Common UI operations are also possible through documented CLI/API commands.
- Engine disconnects and failed jobs are visible with an actionable reason.
- A backup can be verified and restored on a clean host using only documented steps.
- The idle server has a small, measured CPU and memory footprint.
- Upgrades preserve configuration and include an explicit recovery path.
13. Risks and mitigations
| Risk | Mitigation |
|---|---|
| Docker access permits host compromise | Strong warnings, narrow connection options, authentication, audit, and deployment hardening |
| Volume backups are inconsistent | Pre/post hooks, optional pause, manifests, verification, and clearly stated consistency level |
| Remote connection setup is difficult | Connection wizard, validation endpoint, actionable diagnostics, TLS/SSH examples |
| Metrics storage increases product complexity | Start with bounded retention and an export endpoint; defer a full time-series system |
| UI, CLI, and API behavior diverge | API-first implementation and a shared generated client |
| Restore destroys existing data | Restore to a new name by default, preview changes, require explicit overwrite confirmation |
14. Decision log
Add one row whenever an open decision is resolved.
| ID | Date | Decision | Rationale | Status |
|---|---|---|---|---|
| D-001 | TBD | Vue/Vuetify version | Awaiting confirmation | Proposed |
15. Backlog and idea inbox
Add unrefined ideas here without disrupting the milestones. Give each accepted item an owner and promote it to a milestone when it is ready.
| ID | Idea | Why it matters | Priority | Owner | Status |
|---|---|---|---|---|---|
| I-001 | S3-compatible backup storage | Keeps backups off-host | Later | — | Idea |
| I-002 | Compose stack management | Groups related containers into applications | Later | — | Idea |
| I-003 | Notifications for engine/backup failures | Reduces time to detection | Later | — | Idea |
16. Change log
| Date | Change |
|---|---|
| 2026-08-06 | Initial project plan created. |