Skip to content

Repository files navigation

Mizan

Mizan is a local-first visual configuration architect for HAProxy and Nginx. It runs as a single Go binary, serves an embedded React/Vite WebUI, stores projects as inspectable JSON under ~/.mizan, and translates one Universal IR into target-specific HAProxy or Nginx configuration.

The current codebase is release-ready for the documented v0.1 scope with backend statement coverage at 96.7%, browser E2E coverage for the main operator workflow, clean Go/npm vulnerability scans, and a high/critical container CVE gate.

Latest verified release: v0.1.6, published from commit 2ce1688, with signed/checksummed binaries for Linux, macOS, and Windows.

What Works Today

  • Single-binary Go CLI and HTTP server: mizan serve
  • Optional admin Bearer token, read-only Bearer token, or Basic auth for HTTP access, required when binding outside localhost
  • Hardened HTTP defaults with security headers, request body limits, server timeouts, and graceful shutdown
  • Encrypted local secrets vault foundation using Argon2id-derived AES-GCM envelopes
  • Health, storage-backed readiness, version, and Prometheus-style /metrics endpoints with build, project, and HTTP request counters
  • Embedded React WebUI with project creation, import, IR editing, generation, validation, snapshots, diff, audit, topology, deployment-target, and approval-request panels
  • Project CRUD and filesystem persistence under ~/.mizan/projects
  • Project export endpoint, CLI command, and WebUI download for portable JSON backups
  • Full home backup, inspection, and restore commands with SHA-256 manifest verification for projects, snapshots, targets, audit logs, and encrypted vault envelopes
  • Dockerfile, systemd unit, and Nginx TLS reverse proxy deployment examples
  • mizan doctor preflight checks for data root integrity, projects, targets, secrets, SSH, native validators, and optional production hardening
  • Universal IR with structural linting, deterministic hashes, mutations, canonical JSON, and structural diffs
  • HAProxy and Nginx import for the supported v0 directive subset, including quoted values, bracketed IPv6 endpoints, and supported nested Nginx contexts
  • HAProxy and Nginx generation from the shared IR
  • Validation pipeline with IR linting plus optional native haproxy -c / nginx -t checks when binaries exist on PATH
  • Snapshots, tags, snapshot retrieval, revert, and diff
  • Append-only project audit log in audit.jsonl
  • Filterable audit history through API, CLI, and WebUI
  • Deployment targets and clusters persisted in targets.json
  • CLI secret management for encrypted target credentials
  • Deployment dry-run planning for single targets or clusters via generated rollout steps
  • CLI deployment execution through the local ssh command with vault-backed username/private-key support and snapshot confirmation
  • Deployment results and audit metadata include rollback and remote cleanup summary counts
  • Persisted API, CLI, and WebUI approval requests in approvals.json for snapshot-bound cluster or target rollouts
  • Target probe checks for configured post-reload or monitor endpoints
  • Monitor snapshots for registered targets through API, CLI, and WebUI
  • Monitor SSE stream endpoint for repeated target health snapshots
  • WebUI monitor panel consumes the live SSE stream while a project is open
  • Project metadata, target registry updates, approval requests, and audit events can stream to WebUI over SSE
  • Filterable audit history by actor, action/action prefix, outcome, target engine, time range, target/cluster/approval ids, batch, dry-run, incident, and rollback-failure state
  • Filtered audit CSV export from the API, CLI, and WebUI
  • HAProxy monitor endpoint support for show stat CSV health summaries
  • Nginx monitor endpoint support for OSS stub_status connection summaries
  • Topology canvas with drag/connect gestures that update the IR

Run

go run ./cmd/mizan serve --bind 127.0.0.1:7890

Open http://127.0.0.1:7890.

When binding outside localhost, Mizan requires HTTP auth:

go run ./cmd/mizan serve --bind 0.0.0.0:7890 --auth-token "$MIZAN_AUTH_TOKEN"
go run ./cmd/mizan serve --bind 0.0.0.0:7890 --read-only-token "$MIZAN_READ_ONLY_TOKEN"
go run ./cmd/mizan serve --bind 0.0.0.0:7890 --auth-basic operator:change-me

--auth-token and --auth-basic grant admin access. --read-only-token grants viewer access for safe HTTP methods only (GET, HEAD, and OPTIONS); state-changing API calls return 403 Forbidden.

Runtime hardening controls:

go run ./cmd/mizan serve --bind 127.0.0.1:7890 --max-body-bytes 10485760 --shutdown-timeout 10s

If you already built the embedded binary on Windows:

dist\mizan.exe serve --bind 127.0.0.1:7890

For frontend development:

cd webui
npm install
npm run dev

CLI Examples

go run ./cmd/mizan project new --name edge-prod --engines haproxy,nginx
go run ./cmd/mizan project import ./haproxy.cfg --name imported-edge
go run ./cmd/mizan project export <id> --out mizan-export.json
go run ./cmd/mizan project list
go run ./cmd/mizan backup create --out mizan-backup.zip
go run ./cmd/mizan backup inspect --in mizan-backup.zip
go run ./cmd/mizan backup restore --in mizan-backup.zip --home /tmp/mizan-restore
go run ./cmd/mizan doctor --json
go run ./cmd/mizan doctor --production --json
go run ./cmd/mizan doctor --production --json --out production-doctor.json
go run ./cmd/mizan snapshot list --project <id>
go run ./cmd/mizan snapshot tag --project <id> --label release-1 <snapshot-ref>
go run ./cmd/mizan target add --project <id> --name edge-01 --host 10.0.0.10 --engine haproxy --monitor-endpoint 'http://10.0.0.10:8404/;csv' --rollback-command 'cp /etc/haproxy/haproxy.cfg.bak /etc/haproxy/haproxy.cfg && systemctl reload haproxy'
go run ./cmd/mizan cluster add --project <id> --name prod --target-ids <target-id> --required-approvals 2
go run ./cmd/mizan generate --project <id> --target haproxy
go run ./cmd/mizan validate --project <id> --target nginx
go run ./cmd/mizan deploy --project <id> --target-id <target-id>
go run ./cmd/mizan deploy --project <id> --cluster-id <cluster-id> --batch 1
go run ./cmd/mizan deploy drill --summary
go run ./cmd/mizan deploy drill --format text
go run ./cmd/mizan deploy drill --summary --out staging-drill-summary.json
go run ./cmd/mizan deploy drill verify --file staging-drill-summary.json
go run ./cmd/mizan approval request --project <id> --cluster-id <cluster-id> --batch 1
go run ./cmd/mizan approval approve --project <id> --actor alice <approval-request-id>
go run ./cmd/mizan approval approve --project <id> --actor bob <approval-request-id>
go run ./cmd/mizan deploy --project <id> --approval-request-id <approval-request-id> --execute --vault-passphrase "$MIZAN_VAULT_PASSPHRASE"
go run ./cmd/mizan audit show --project <id> --action deploy.run --dry-run true --csv --out audit.csv
go run ./cmd/mizan audit show --project <id> --incident true --rollback-failed true --cleanup-failed true
go run ./cmd/mizan secret set --id <target-id> --username root --private-key-file ~/.ssh/id_ed25519 --vault-passphrase "$MIZAN_VAULT_PASSPHRASE"
go run ./cmd/mizan deploy --project <id> --cluster-id <cluster-id> --batch 1 --execute --confirm-snapshot <snapshot_hash> --approved-by alice,bob --vault-passphrase "$MIZAN_VAULT_PASSPHRASE"
go run ./cmd/mizan secret list
go run ./cmd/mizan monitor snapshot --project <id>
go run ./cmd/mizan monitor stream --project <id> --limit 10 --interval 5s
go run ./cmd/mizan version --json

Build

Current build baseline:

Area Baseline
Go module/toolchain go 1.25.0 with go1.25.9 toolchain
CI/release actions checkout@v6, setup-go@v6, setup-node@v6, upload-artifact@v7, download-artifact@v8.0.1
Container builder golang:1.26.2-alpine
WebUI stack React 19, TypeScript 6.0, Vite 8
Workflow lint actionlint v1.7.12

With make:

make ui
make binary

On Windows without make:

cd webui
npm install
npm run build
cd ..
Remove-Item -Recurse -Force internal/server/dist
Copy-Item -Recurse webui/dist internal/server/dist
go build -o dist/mizan.exe ./cmd/mizan

Container image:

make ui
docker build --target runtime -t mizan:local .
docker run --rm -p 127.0.0.1:7890:7890 -v mizan-data:/var/lib/mizan -e MIZAN_AUTH_TOKEN=change-me mizan:local

The default container target is the minimal UI/API runtime and intentionally excludes openssh-client. Build the SSH-capable runtime when the container itself must execute remote deployments:

docker build --target runtime-ssh -t mizan:ssh-local .

Deployment examples live under deploy/:

  • deploy/systemd/mizan.service
  • deploy/nginx/mizan.conf

Production and drill runbooks live under docs/:

  • docs/PRODUCTION.md
  • docs/STAGING-DRILLS.md

Test and Coverage

Backend:

go test -coverprofile dist/coverage.out ./...
go tool cover -func dist/coverage.out
go run golang.org/x/vuln/cmd/govulncheck@latest ./...

Frontend:

cd webui
npm run lint
npm run test:coverage
npx playwright install chromium
npm run test:e2e
npm run build
npm audit --audit-level=low

Container high/critical gate:

make container-scan

Full release gate:

make release-check

Local deploy fault-injection drill:

make deploy-drill

For a full step-by-step simulated failure report, run:

go run ./cmd/mizan deploy drill

For a concise terminal summary, run:

go run ./cmd/mizan deploy drill --format text

For archived staging evidence, write drill output directly to a file:

go run ./cmd/mizan deploy drill --summary --out staging-drill-summary.json
go run ./cmd/mizan deploy drill verify --file staging-drill-summary.json

Workflow-only gate:

make workflow-lint

Verify a published GitHub Release:

.\scripts\verify-release.ps1 -Tag v0.1.6

Tag-triggered GitHub Releases run the same verification automatically after publish.

If cosign is installed, also verify the keyless Sigstore signatures:

.\scripts\verify-release.ps1 -Tag v0.1.6 -VerifySignatures

To install the pinned local verification tool with Go:

.\scripts\install-cosign.ps1
$cosign = Join-Path (go env GOPATH) 'bin\cosign.exe'
.\scripts\verify-release.ps1 -Tag v0.1.6 -VerifySignatures -CosignPath $cosign

Current verified gates:

Area Status
Go test pass rate 100%
Go total statement coverage 96.7%
Frontend core statement coverage 100%
Frontend core function coverage 100%
Frontend core line coverage 100%
Frontend core branch coverage 95.89%
Browser E2E workflow Playwright Chromium pass: import, edit, validate, batch approval, rollback dry-run, audit, monitor
GitHub Actions workflow lint actionlint pass
Deploy drill evidence gate CI generates and verifies staging-drill-summary.json
Production doctor mizan doctor --production --json --out production-doctor.json reports cluster gates, approvals, rollback, probes, monitoring, and target credential coverage
Full npm audit 0 vulnerabilities
Go vulnerability scan govulncheck pass: 0 vulnerabilities
Container high/critical scan Anchore/Grype CI gate pass; Docker Scout local gate pass

Frontend coverage is scoped to webui/src/lib/**/*.ts in webui/vitest.config.ts; backend coverage is measured across ./.... make release-check also runs actionlint against .github/workflows, writes dist/production-doctor.json, and CI archives the verified deploy drill summary plus production doctor report as preflight evidence.

For release or deployment scripts, use mizan version --json to verify the embedded version, commit, and date metadata before rollout.

Architecture

See ARCHITECTURE.md for the current architecture, request flows, storage layout, coverage status, and Mermaid diagrams.

For production hardening, release gates, and supported scope boundaries, see docs/PRODUCTION.md.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages