diff --git a/.kiro/settings/mcp.json b/.kiro/settings/mcp.json index aa9cc51..de27a53 100644 --- a/.kiro/settings/mcp.json +++ b/.kiro/settings/mcp.json @@ -1,14 +1,5 @@ { "mcpServers": { - "aws-docs": { - "command": "uvx", - "args": ["awslabs.aws-documentation-mcp-server@latest"], - "env": { - "FASTMCP_LOG_LEVEL": "ERROR" - }, - "disabled": false, - "autoApprove": [] - }, "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp@latest"], diff --git a/README.md b/README.md index 27cb045..3e7be3b 100644 --- a/README.md +++ b/README.md @@ -1,256 +1,94 @@ # ArchNest -A self-hosted ops dashboard for a homelab/cloud setup: live infrastructure -monitoring across 9 real integration types, a categorized bookmark hub, a -full SSH suite (terminal, tunnels, file manager, host-to-host transfer, live -host metrics), Docker container management, and RDP/VNC/Telnet remote desktop -— all in one app, with zero mock data anywhere. +A multi-tenant SaaS platform for infrastructure management — SSH terminal, +Docker management, remote desktop, host metrics, file management, and 9 +real integration adapters from a single browser interface. Developer-first +alternative to enterprise RMM tools, starting at $2.50/month. -**This repo is private and will never be public.** This README is written for -the owner and for any AI session picking up the project cold — it should be -detailed enough that neither needs to re-derive context from scratch. +## Pricing -## What this is, in one paragraph +| | Starter | Pro | Team | +|---|---|---|---| +| Monthly | $2.50/mo | $4.25/mo | $12/mo | +| Annual | $25/yr | $45/yr | $95/yr | +| Hosts | 50 | 125 | Unlimited | +| Users | 5 | 50 | 200 | +| Remote Desktop | — | ✓ | ✓ | +| SSO | — | — | ✓ | -ArchNest replaced a Homarr-style bookmark dashboard plus a handful of -disconnected admin tools (Proxmox UI, Portainer, separate SSH terminals, -WinSCP-equivalents) with one app that talks directly to the underlying -systems. It started as a 6-page mockup/portfolio piece and has since grown -into an 11-page real tool with a real Fastify backend, real SSH/Docker/cloud -integrations, and no synthetic data — every number on every page comes from -a live API call, a SQLite-backed table, or an SSH command run against a -managed host. +## Features -## Current state & direction +**SSH Suite** — Terminal (multi-tab, split panes, persistent sessions), tunnels +(local/remote/SOCKS5), SFTP file manager, host-to-host transfer, host metrics +(5s polling), jump-host chaining, tmux, certificate auth (OPKSSH). -**Live and deployed** at `archnest.snsnetlabs.com`, auto-deploying on every -merge to `main` via `.github/workflows/deploy.yml`. All 11 pages and their -backend routes are built and working — there is no pending/on-hold page. +**Docker** — Management via TCP API, CLI over SSH, or push agent. Container +actions, logs, interactive exec, detail views. -Auth is feature-complete for self-hosted (Phases 1-3: user menu wiring, -password/sessions/login-log, multi-user roles with a 10-seat cap); Phase 4 -(Authentik SSO) is **deferred to a paid AWS add-on** — see `ROADMAP.md`. -Recently shipped: persistent terminal sessions across navigation, Docker -container visibility/management three ways (Engine TCP API, `docker` CLI over -SSH, and a read-only push agent — see `docs/docker-agent-monitoring.md`), and -the **Mesh Prerequisite Gate** — a universal CIDR-based mesh-verification -requirement (with a routed-mesh/VPC-peering fallback, not NetBird-specific), -configurable from Settings → Mesh and defaulting OFF so it can't lock the live -instance. +**Remote Desktop** — RDP/VNC/Telnet via Guacamole (Pro+). -There is no feature currently in progress. See `HANDOFF.md` for the latest -status and next steps. +**Integrations** — Proxmox, Docker, AWS, Cloudflare, NetBird, Uptime Kuma, +Weather, SSH, Remote Desktop. All real, no mocks. -If you're a fresh AI session: read this file, then `HANDOFF.md` (current -task state + standing workflow rules), then `design-decisions.md` (visual -conventions + accurate per-page implementation notes), then `ROADMAP.md` -(deferred/tiered work) and the `docs/` design docs (`docker-agent-monitoring.md`, -`mesh-prerequisite-gate.md`), then `TERMIX_MIGRATION.md` -(history of how the SSH/Docker/Guacamole feature set was built) if you need -that context. +**Bookmarks** — Categorized hub with favorites, link health, full CRUD. -## Pages +**Auth** — Cognito (OIDC/SAML SSO for Team), MFA, multi-user roles, audit log. -| Page | Route | What it does | -|------|-------|---------------| -| Glance | `/` | Home dashboard — system/integration health, resource overview, recent activity, shortcuts | -| Infrastructure | `/infrastructure` | Resource inventory across all integrations — distribution donut, per-resource status grid, integration health, activity | -| BookNest | `/booknest` | Categorized bookmark hub — quick access, favorites, link health, full CRUD | -| Terminal | `/terminal` | Web SSH terminal — multi-tab, split panes, tmux attach, cert auth (OPKSSH); **sessions stay connected across page navigation** | -| Tunnels | `/tunnels` | SSH tunnel manager — local/remote/dynamic (SOCKS5) forwarding, auto-start, live status | -| Files | `/files` | SFTP file browser/editor over managed SSH hosts, with host-to-host transfer | -| Containers | `/containers` | Docker containers across **three sources** (Engine TCP API, `docker` CLI over SSH, or a read-only push agent) — list/start/stop/restart/pause/remove, logs, interactive exec; tabbed with a clickable per-container detail view | -| Remote Desktop | `/remote-desktop` | RDP/VNC/Telnet sessions via a Guacamole sidecar | -| Host Metrics | `/host-metrics` | Live CPU/memory/disk/network/processes/ports/firewall/login-activity per SSH host, polled every 5s | -| Settings | `/settings` | Profile, Appearance, Security, Integrations, Notifications, Data & Backup, About — deep-linkable via `?tab=` | -| Help | `/help` | Static guided tour of every page above | -| Login / Enrollment | `/login`, `/enrollment` | Auth entry points — not in the sidebar nav | - -See `design-decisions.md`'s "Page Notes" section for a detailed, per-page -breakdown of layout, real data sources, and known quirks — it's kept in sync -with the actual code, not a spec written before the page existed. +**4 Themes** — ArchNest Dark, Midnight Blue, Forest, Light. ## Architecture -### Frontend (`/src`) -- React 19 + Vite + TypeScript, Tailwind CSS v4, Recharts (donuts/area - charts), Lucide React icons, React Router. -- `src/lib/api.ts` — typed fetch wrapper (`apiFetch`) + one function per - backend endpoint + matching TS interfaces. This is the contract between - frontend and backend; any new backend route needs a matching entry here. -- `src/lib/AuthContext.tsx` — auth state backed by `localStorage` (JWT - carrying a server-tracked session id; signing out revokes the session - server-side). -- `src/lib/TerminalSessionContext.tsx` — keeps SSH terminal sessions - (xterm + WebSocket + DOM node) alive above the router so they survive - in-app navigation; shared constants in `src/lib/terminalPrefs.ts`. -- `src/pages/` — one file per route (see table above), plus `Login.tsx` / - `Enrollment.tsx` for the unauthenticated/first-run flows. -- `src/components/` — `TopBar.tsx` (title, global search across pages/ - integrations/bookmarks, user dropdown), `Sidebar.tsx` (nav + system-health - rollup widget). -- `App.tsx` — route table, plus per-route hero-banner config (`showHero`, - `heroPaddingTop`, `heroObjectPosition` lookup maps) and `topBarHeight` - lookup for pages with a subtitle (currently only BookNest). +Hybrid: Akamai Cloud for compute, AWS for managed services. -### Backend (`/backend`) -- Fastify 5, TypeScript, ESM (`tsx` for dev, `tsc -b` for build), entrypoint - `src/server.ts`. -- `backend/src/db/index.ts` — SQLite schema + `logEvent()` audit log, - plus `sessions`/`login_events` tables and a multi-user `users` schema - (`role` admin/member + `active` columns). -- `backend/src/db/crypto.ts` — AES-256-GCM `encryptSecret`/`decryptSecret`, - keyed by `ARCHNEST_SECRET_KEY`. -- `backend/src/routes/` — one file per feature area: - - `auth.ts` — setup, login, profile, password change, sessions, - login audit log, and admin-only user management (`/api/setup`, - `/api/auth/*`, `/api/users`) - - `integrations.ts` — integration CRUD + connection testing - - `bookmarks.ts` — bookmarks + categories CRUD - - `events.ts` — activity log retrieval - - `terminal.ts` — SSH terminal WebSocket (`connect`/`input`/`resize`/ - `list_tmux`/`disconnect`) - - `tunnels.ts` — SSH tunnel CRUD + connect/disconnect - - `files.ts` — SFTP list/read/write/mkdir/rename/delete/chmod/download/upload - - `docker.ts` — Docker Engine TCP API: container list/stats/logs/actions + exec WebSocket - - `dockerSsh.ts` — Docker over SSH: runs the `docker` CLI on a remote SSH host (list/logs/actions + exec WebSocket); no dockerd socket exposed - - `agents.ts` — Docker monitoring agents: token-gated push ingest (`POST /api/agents/docker/report`) + read-only host/container views - - `guacamole.ts` — Guacamole WebSocket proxy for remote desktop - - `metrics.ts` — live host metrics endpoint - - `transfer.ts` — host-to-host file transfer orchestration (start/poll/cancel) - - `data.ts` — full backup export/import (integrations + secrets + bookmarks + tunnels) -- `backend/src/integrations/` — one adapter per type, all real (none are - stubs): `proxmox.ts`, `docker.ts`, `netbird.ts`, `cloudflare.ts`, `aws.ts`, - `uptimeKuma.ts`, `weather.ts`, `ssh.ts`, `remoteDesktop.ts`. Each implements - `testConnection()` (required) and `listResources()` (optional); - `registry.ts` maps `IntegrationType` → adapter. -- `backend/src/ssh/` — the shared SSH transport layer used by Terminal, - Files, Tunnels, Transfers, and Host Metrics: - - `connect.ts` — jump-host chaining, host-key verification, certificate auth - - `sftp.ts` — ephemeral SFTP connections for file ops - - `transfer.ts` — streamed host-to-host copy/move with progress + cancel - - `docker.ts` — runs the `docker` CLI over SSH for the Containers page's - "Docker over SSH" source (list/logs/actions + interactive exec) - - `metrics/` — 10 sequential collectors (cpu, memory, disk, uptime, - network, system, processes, ports, firewall, login-stats) — sequential - on purpose, to stay under OpenSSH's `MaxSessions` limit per host. -- Docker images run on Alpine; **OpenSSL legacy provider is enabled** in - `backend/Dockerfile` (`OPENSSL_CONF=/etc/ssl/openssl-legacy.cnf`) so - old-format encrypted PEM keys (`BEGIN RSA PRIVATE KEY` + `DEK-Info`) still - decrypt under OpenSSL 3 — don't remove this without understanding why. -- **Required env vars, no defaults**: `ARCHNEST_SECRET_KEY`, - `ARCHNEST_JWT_SECRET`. The server refuses to start without both. Optional: - `ARCHNEST_DB_PATH`, `PORT`, `ARCHNEST_GUAC_CRYPT_KEY` / - `ARCHNEST_GUACD_HOST` / `ARCHNEST_GUACD_PORT`, `ARCHNEST_CORS_ORIGIN`, - `ARCHNEST_SESSION_LOG_DIR` (optional terminal session logging), - `ARCHNEST_AGENT_TOKEN` (shared token enabling the Docker monitoring-agent - ingest endpoint — ingest is disabled / returns 503 when unset), - `ARCHNEST_AGENT_STALE_MS` (default 90000; when an agent report is shown stale). -- `backend/src/docker/` — Docker Engine TCP API client used by `docker.ts`. -- `agent/` — the standalone Docker monitoring agent (`archnest-docker-agent.sh` - + install/README). Runs on each Docker VM and pushes reports to ArchNest. +| Layer | Provider | Service | +|-------|----------|---------| +| Compute | Akamai | G7 Dedicated (4GB, ARM) | +| Load Balancer | Akamai | NodeBalancer | +| Frontend | Akamai | Object Storage | +| Database | Self-managed | PostgreSQL (RLS) | +| Cache | Self-managed | Redis | +| Auth | AWS | Cognito | +| Secrets | AWS | Secrets Manager | +| Storage | AWS | S3 | +| DNS | AWS | Route 53 | +| Email | AWS | SES | -## Development +**Infrastructure cost:** ~$66.50/month at 50 users. Scales to full AWS +(Fargate + Aurora) at 100+ users / $500+ MRR. -Frontend: -```bash -npm install -npm run dev -``` - -Backend: -```bash -cd backend -npm install -ARCHNEST_SECRET_KEY=$(openssl rand -hex 32) ARCHNEST_JWT_SECRET=$(openssl rand -hex 32) npm run dev -``` - -`ARCHNEST_DB_PATH` optionally overrides the SQLite file location (defaults to -a local path under `backend/`). `PORT` overrides the listen port (check -`server.ts` for the default). - -Type-check both before committing — this is the minimum bar, not a substitute -for testing in a browser: -```bash -npx tsc --noEmit # from repo root, frontend -cd backend && npx tsc --noEmit # backend -``` -Vite/the browser surface some runtime errors (e.g. missing icon exports — -see the lucide-react gotcha in `design-decisions.md`) that the type-checker -won't catch. +See [`docs/aws-architecture/system-design.md`](docs/aws-architecture/system-design.md) +for the full system design with diagrams, cost analysis, tier enforcement, +and scale-up path. ## Tech Stack -**Frontend** -- React 19 + Vite + TypeScript, React Router, Tailwind CSS v4 -- Recharts (donuts, line/area charts), Lucide React (icons) -- xterm.js (Terminal page terminal rendering) +**Frontend**: React 19, Vite 8, TypeScript, Tailwind CSS v4, React Router, +Recharts, Lucide React, xterm.js -**Backend** -- Fastify 5 + TypeScript, `tsx` for dev, `tsc -b` for build -- `better-sqlite3` for storage -- `@fastify/jwt` for auth tokens, `bcryptjs` for password hashing -- `zod` for request validation -- AES-256-GCM (Node `crypto`) for encrypting integration secrets at rest -- SSH client library powering the SSH transport layer (`backend/src/ssh/`) -- Guacamole Lite protocol for RDP/VNC/Telnet, proxied to a `guacd` sidecar +**Backend**: Fastify 5, TypeScript, PostgreSQL, Redis, zod, ssh2 -**Integrations**: Proxmox, Docker, NetBird, Cloudflare, AWS, Uptime Kuma, -Weather (wttr.in), SSH, Remote Desktop (RDP/VNC/Telnet via Guacamole) — see -`backend/src/integrations/` for adapter implementations. +**Auth**: AWS Cognito (OIDC/SAML SSO, MFA, PKCE) -**Deploy target:** Docker on `racknerd1` → Nginx Proxy Manager at -`archnest.snsnetlabs.com`. +**CI/CD**: Forgejo Actions → Docker → Akamai VM deploy -## Deployment +## Development -**Live and deployed.** `.github/workflows/deploy.yml` triggers on every push -to `main`: builds, SCPs the repo to `racknerd1`, and runs -`docker compose up -d --build` there, gated on an `/api/health` health check. -No further setup is needed — merging a PR to `main` redeploys automatically. +```bash +npm install && npm run dev # frontend +cd backend && npm install && npm run dev # backend +``` -`docker-compose.yml` runs 3 services: `archnest` (frontend), `archnest-backend`, -and `guacd` (remote desktop sidecar). +Type-check before committing: +```bash +npm run build # frontend +cd backend && npx tsc --noEmit # backend +``` -If a deploy fails, check the workflow run's `deploy` job steps in order: -`Pre-flight` (confirms host `.env` exists) → `Copy repo to racknerd1` → -`Build, restart, and clean up` → `Health check (backend /api/health)`. +## Documentation -One-time setup already done (reference only, shouldn't need repeating): host -provisioning (Docker/Compose on `racknerd1`, deploy SSH user, `/opt/archnest` -directory), `/opt/archnest/.env` populated from `.env.example` with real -secrets, `RACKNERD_HOST`/`RACKNERD_USER`/`RACKNERD_SSH_KEY` added as GitHub -Actions secrets, DNS/Nginx Proxy Manager pointed at the host. - -## Documentation map - -- **`README.md`** (this file) — architecture, tech stack, deployment, page list. -- **`HANDOFF.md`** — current task state, standing workflow rules (git workflow, - mock-data policy, secrets discipline), and the auth/SSO roadmap. Read this - before starting any new work session. -- **`design-decisions.md`** — visual/UX conventions (colors, typography, card - style, animations) plus a detailed, accurate-as-of-now "Page Notes" section - per page — what's actually rendered and where its data comes from. This is - the file to update whenever a page's layout or data source changes. -- **`TERMIX_MIGRATION.md`** — phase-by-phase history of how the SSH/Tunnels/ - Files/Containers/Remote Desktop/Host Metrics/Transfer/Data-export feature - set was built (originally scoped as a migration from a forked Termix - project, hence the name). Useful for historical "why was it built this - way" context on those specific features. -- **`.kiro/steering/design-rules.md`** — a condensed duplicate of - `design-decisions.md`'s Global Rules, auto-injected into every Kiro IDE - session (the Kiro extension reads `.kiro/steering/*` automatically). If you - update a global design rule, update both files in the same change — - `design-decisions.md` is canonical, this one just needs to stay in sync so - Kiro doesn't steer on stale info. - -Three older docs were deleted as part of a documentation cleanup: -`archnest-blueprint.md` and `glance.md` (the original 6-page mockup pitch and -an early Glance-only spec, both describing fictional config files and -placeholder numbers that never matched the real build), and -`.kiro/specs/archnest-dashboard/` (an abandoned Kiro spec — requirements-only, -no `design.md`/`tasks.md` ever followed — describing the same stale 6-page/ -80px-sidebar/Zustand-based vision). Their still-accurate content (color -palette, dropdown menu shape, card styling) was folded into -`design-decisions.md` and `.kiro/steering/design-rules.md`; everything else -was superseded by the real, deployed implementation described above. +| File | Content | +|------|---------| +| [`docs/aws-architecture/system-design.md`](docs/aws-architecture/system-design.md) | Full architecture, costs, tier enforcement | +| [`design-decisions.md`](design-decisions.md) | Visual conventions + per-page notes | +| [`HANDOFF.md`](HANDOFF.md) | Current state, workflow rules | +| [`ROADMAP.md`](ROADMAP.md) | Deferred/tiered work | diff --git a/backend/package-lock.json b/backend/package-lock.json index 9d2c05f..4adaa73 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -28,10 +28,10 @@ }, "devDependencies": { "@types/bcryptjs": "^2.4.6", - "@types/better-sqlite3": "^7.6.12", - "@types/node": "^22.10.5", + "@types/better-sqlite3": "^7.6.13", + "@types/node": "^22.20.0", "tsx": "^4.19.2", - "typescript": "^5.7.3" + "typescript": "^5.9.3" } }, "node_modules/@aws-crypto/crc32": { @@ -1259,9 +1259,9 @@ } }, "node_modules/@types/node": { - "version": "22.19.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.21.tgz", - "integrity": "sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA==", + "version": "22.20.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", + "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==", "dev": true, "license": "MIT", "dependencies": { diff --git a/backend/package.json b/backend/package.json index 480760b..632e243 100644 --- a/backend/package.json +++ b/backend/package.json @@ -29,9 +29,9 @@ }, "devDependencies": { "@types/bcryptjs": "^2.4.6", - "@types/better-sqlite3": "^7.6.12", - "@types/node": "^22.10.5", + "@types/better-sqlite3": "^7.6.13", + "@types/node": "^22.20.0", "tsx": "^4.19.2", - "typescript": "^5.7.3" + "typescript": "^5.9.3" } } diff --git a/docs/aws-architecture/archnest-architecture.png b/docs/aws-architecture/archnest-architecture.png new file mode 100644 index 0000000..b116d85 Binary files /dev/null and b/docs/aws-architecture/archnest-architecture.png differ diff --git a/docs/aws-architecture/generate_diagram.py b/docs/aws-architecture/generate_diagram.py new file mode 100644 index 0000000..12ca4f9 --- /dev/null +++ b/docs/aws-architecture/generate_diagram.py @@ -0,0 +1,73 @@ +from diagrams import Diagram, Cluster, Edge +from diagrams.aws.security import Cognito, SecretsManager +from diagrams.aws.storage import S3 +from diagrams.aws.network import Route53 +from diagrams.aws.compute import Lambda +from diagrams.aws.engagement import SES +from diagrams.onprem.container import Docker +from diagrams.onprem.compute import Server +from diagrams.onprem.database import PostgreSQL +from diagrams.onprem.inmemory import Redis +from diagrams.onprem.network import Nginx +from diagrams.onprem.client import User +from diagrams.generic.storage import Storage + +with Diagram("ArchNest SaaS - Hybrid Architecture", show=False, filename="/tmp/archnest-hybrid", direction="TB", outformat="png"): + + users = User("Tenants") + + with Cluster("Akamai Cloud"): + lb = Nginx("NodeBalancer\nHTTPS/WSS") + + with Cluster("G7 Dedicated (4GB, 2 vCPU, ARM)"): + backend = Server("Fastify\nBackend API") + websocket = Server("Fastify\nWebSocket Service") + guacd = Docker("guacd\n(RDP/VNC)") + + with Cluster("Data (Self-Managed)"): + postgres = PostgreSQL("PostgreSQL\n(RLS Enabled)") + redis = Redis("Redis\n(Sessions/Cache)") + + static = Storage("Object Storage\n(React SPA)") + + with Cluster("AWS (Managed Services Only)"): + cognito = Cognito("Cognito\nUser Pools + SSO") + pre_token = Lambda("Pre-Token\nLambda") + secrets = SecretsManager("Secrets Manager\nSSH Keys") + s3 = S3("S3\nBackups + Logs") + route53 = Route53("Route 53") + ses = SES("SES\nEmail") + stripe_lambda = Lambda("Stripe\nWebhook Lambda") + + with Cluster("Tenant Infrastructure"): + host1 = Server("SSH Host A") + host2 = Server("SSH Host B") + docker_host = Docker("Docker Host") + + # User flow + users >> route53 >> lb + lb >> static + lb >> backend + lb >> websocket + + # Backend connections + backend >> postgres + backend >> redis + backend >> secrets + backend >> s3 + websocket >> redis + websocket >> guacd + + # Auth + cognito >> pre_token + backend >> cognito + stripe_lambda >> cognito + + # Outbound to tenant hosts (direct, no NAT needed) + backend >> host1 + backend >> host2 + websocket >> host1 + websocket >> docker_host + + # Email + backend >> ses diff --git a/docs/aws-architecture/system-design.html b/docs/aws-architecture/system-design.html new file mode 100644 index 0000000..9a72e30 --- /dev/null +++ b/docs/aws-architecture/system-design.html @@ -0,0 +1,419 @@ + + +
+ + +Self-Hosted Product Design — Open Core + Paid Modules
+Free self-hosted ops dashboard. Unlock features with $5 one-time module purchases. Own it forever. No subscriptions.
+| Feature | Free Limit |
|---|---|
| Dashboard (Glance) | Full |
| Infrastructure Overview | Full |
| SSH Terminal | 1 tab, 1 pane |
| SSH Tunnels | Manual start only |
| SFTP File Manager | Full |
| Docker Management | TCP API only, 1 source |
| Host Metrics | Basic (CPU/memory/disk) |
| Bookmarks | 10 max |
| SSH Hosts | 3 max |
| Users | 1 (admin only) |
| Theme | ArchNest Dark only |
| Help Page | Full |
Split panes (2/4), multiple tabs
+Attach to existing tmux sessions
+Connect through intermediary hosts
+OPKSSH certificate-based SSH auth
+Tunnels start automatically on boot
+Terminal sessions survive navigation
+Record terminal sessions to disk
+Copy/move files between SSH hosts
+Manage containers via CLI over SSH
+Outbound-only monitoring agent
+Interactive shell into containers
+Full inspect: ports, networks, env, mounts
+Remove 3-host cap
+VM/LXC management
+EC2 + STS resource inventory
+DNS zones, resource listing
+Mesh peers, connectivity
+Monitor status/health
+Windows RDP via Guacamole
+VNC sessions via Guacamole
+Telnet sessions via Guacamole
+Admin/member roles, up to 10 seats
+Network, processes, ports, firewall, login stats
+Backup/restore full config as JSON
+Full activity log with export
+Remove 10-bookmark cap
+Search pages, integrations, bookmarks
+$25
+All 8 SSH modules (save $15)
+$15
+All 4 Docker modules (save $5)
+$10
+RDP + VNC + Telnet (save $5)
+$10
+3 extra themes (save $5)
+$99
+All 30 modules forever (save $51)
+| Stage | Installs/mo | Avg Modules Bought | Revenue/mo |
|---|---|---|---|
| Early (month 1-3) | 50 | 3 modules ($15) | $750 |
| Growth (month 4-6) | 200 | 4 modules ($20) | $4,000 |
| Steady (month 7-12) | 500 | 5 modules ($25) | $12,500 |
| Mature (year 2) | 1,000 | $30 avg (bundles) | $30,000 |
Infrastructure cost stays at ~$1/month regardless of scale. 95%+ margin at all stages.
+| Area | Current | New |
|---|---|---|
| Database | SQLite | SQLite (stays) |
| Auth | Local JWT | Local JWT (stays) |
| Multi-tenant | N/A | Not needed (single-tenant per install) |
| License | None | Weekly phone-home + signature validation |
| Module gating | None | Fastify middleware + frontend lock UI |
| Settings | Current tabs | + "Module Store" tab |
| Stripe | None | Checkout for purchases |
Key insight: Almost no infrastructure changes. You're adding a license layer and a store UI — not rewriting anything.
+| # | Question | Options |
|---|---|---|
| 1 | Source code visibility | Open-source (MIT) vs source-available (BSL) vs proprietary |
| 2 | Distribution | Docker Hub vs GitHub Container Registry |
| 3 | Landing page | Cloudflare Pages vs separate repo |
| 4 | Refund policy | 30-day vs no refunds ($5 is low) |
| 5 | Module store UX | In-app tab vs external website |
| 6 | License transfer | Unlimited vs 1/year |