@lamalibre/create-lamaste 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +118 -0
- package/README.md +114 -0
- package/bin/create-lamaste.js +15 -0
- package/package.json +54 -0
- package/scripts/bundle-vendor.js +110 -0
- package/scripts/lamaste-cert-info +62 -0
- package/scripts/lamaste-certbot +96 -0
- package/scripts/lamaste-priv +693 -0
- package/src/index.js +646 -0
- package/src/lib/accounts.js +86 -0
- package/src/lib/binaries.js +137 -0
- package/src/lib/cert-help-page.js +160 -0
- package/src/lib/env.js +132 -0
- package/src/lib/http-redirect.js +38 -0
- package/src/lib/ownership.js +231 -0
- package/src/lib/relay-services.js +103 -0
- package/src/lib/secrets.js +19 -0
- package/src/lib/service-config.js +311 -0
- package/src/lib/summary.js +131 -0
- package/src/lib/wrappers.js +63 -0
- package/src/tasks/gatekeeper.js +233 -0
- package/src/tasks/harden.js +293 -0
- package/src/tasks/mtls.js +193 -0
- package/src/tasks/nginx.js +265 -0
- package/src/tasks/node.js +110 -0
- package/src/tasks/panel.js +408 -0
- package/src/tasks/redeploy.js +438 -0
- package/vendor/docs/00-introduction/how-it-works.md +447 -0
- package/vendor/docs/00-introduction/quickstart.md +472 -0
- package/vendor/docs/00-introduction/what-is-lamaste.md +112 -0
- package/vendor/docs/01-concepts/authentication.md +464 -0
- package/vendor/docs/01-concepts/authorization.md +242 -0
- package/vendor/docs/01-concepts/certificates.md +452 -0
- package/vendor/docs/01-concepts/dns-and-domains.md +343 -0
- package/vendor/docs/01-concepts/mtls.md +490 -0
- package/vendor/docs/01-concepts/nginx-reverse-proxy.md +540 -0
- package/vendor/docs/01-concepts/security-model.md +600 -0
- package/vendor/docs/01-concepts/tickets.md +414 -0
- package/vendor/docs/01-concepts/tunneling.md +367 -0
- package/vendor/docs/02-guides/agent-setup.md +194 -0
- package/vendor/docs/02-guides/certificate-management.md +341 -0
- package/vendor/docs/02-guides/cloud-provisioning.md +406 -0
- package/vendor/docs/02-guides/desktop-app-setup.md +226 -0
- package/vendor/docs/02-guides/disaster-recovery.md +464 -0
- package/vendor/docs/02-guides/first-tunnel.md +230 -0
- package/vendor/docs/02-guides/installation.md +393 -0
- package/vendor/docs/02-guides/managing-users.md +255 -0
- package/vendor/docs/02-guides/onboarding.md +244 -0
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +375 -0
- package/vendor/docs/02-guides/static-sites.md +364 -0
- package/vendor/docs/03-architecture/e2e-three-vm-sequences.md +457 -0
- package/vendor/docs/03-architecture/installer-flow.md +151 -0
- package/vendor/docs/03-architecture/installer.md +445 -0
- package/vendor/docs/03-architecture/management-flow.md +288 -0
- package/vendor/docs/03-architecture/nginx-configuration.md +830 -0
- package/vendor/docs/03-architecture/onboarding-flow.md +164 -0
- package/vendor/docs/03-architecture/overview.md +541 -0
- package/vendor/docs/03-architecture/panel-client.md +416 -0
- package/vendor/docs/03-architecture/panel-server.md +695 -0
- package/vendor/docs/03-architecture/state-management.md +529 -0
- package/vendor/docs/03-architecture/system-overview.md +167 -0
- package/vendor/docs/04-api-reference/certificates.md +1141 -0
- package/vendor/docs/04-api-reference/gatekeeper.md +592 -0
- package/vendor/docs/04-api-reference/onboarding.md +473 -0
- package/vendor/docs/04-api-reference/overview.md +404 -0
- package/vendor/docs/04-api-reference/services.md +267 -0
- package/vendor/docs/04-api-reference/settings.md +343 -0
- package/vendor/docs/04-api-reference/sites.md +716 -0
- package/vendor/docs/04-api-reference/system.md +268 -0
- package/vendor/docs/04-api-reference/tickets.md +618 -0
- package/vendor/docs/04-api-reference/tunnels.md +417 -0
- package/vendor/docs/04-api-reference/users.md +333 -0
- package/vendor/docs/05-operations/backup-and-restore.md +342 -0
- package/vendor/docs/05-operations/monitoring.md +285 -0
- package/vendor/docs/05-operations/uninstalling.md +344 -0
- package/vendor/docs/05-operations/upgrades.md +270 -0
- package/vendor/docs/06-reference/config-files.md +1080 -0
- package/vendor/docs/06-reference/glossary.md +528 -0
- package/vendor/docs/06-reference/installer-flags.md +260 -0
- package/vendor/docs/06-reference/ports-and-services.md +244 -0
- package/vendor/docs/06-reference/troubleshooting.md +665 -0
- package/vendor/docs/_index.json +233 -0
- package/vendor/docs/gatekeeper-design.md +953 -0
- package/vendor/docs/package.json +15 -0
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +641 -0
- package/vendor/gatekeeper/dist/boot.d.ts +1 -0
- package/vendor/gatekeeper/dist/boot.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/boot.js +17 -0
- package/vendor/gatekeeper/dist/boot.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js +33 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js +110 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js +98 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts +3 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.js +45 -0
- package/vendor/gatekeeper/dist/cli/index.js.map +1 -0
- package/vendor/gatekeeper/dist/index.d.ts +9 -0
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/index.js +13 -0
- package/vendor/gatekeeper/dist/index.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.js +42 -0
- package/vendor/gatekeeper/dist/lib/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts +15 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js +19 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts +82 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.js +79 -0
- package/vendor/gatekeeper/dist/lib/constants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts +32 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.js +314 -0
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts +10 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.js +247 -0
- package/vendor/gatekeeper/dist/lib/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts +17 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.js +79 -0
- package/vendor/gatekeeper/dist/lib/migration.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/state-db.js +154 -0
- package/vendor/gatekeeper/dist/lib/state-db.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts +21 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.js +151 -0
- package/vendor/gatekeeper/dist/lib/templates.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts +178 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.js +2 -0
- package/vendor/gatekeeper/dist/lib/types.js.map +1 -0
- package/vendor/gatekeeper/dist/server/index.d.ts +15 -0
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/index.js +251 -0
- package/vendor/gatekeeper/dist/server/index.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts +7 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js +17 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js +279 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts +13 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +249 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js +112 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js +139 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js.map +1 -0
- package/vendor/gatekeeper/package.json +49 -0
- package/vendor/server/bin/lamaste-server.js +204 -0
- package/vendor/server/package.json +31 -0
- package/vendor/server/src/commands/certs.js +224 -0
- package/vendor/server/src/commands/chisel.js +132 -0
- package/vendor/server/src/commands/logs.js +49 -0
- package/vendor/server/src/commands/plugins.js +321 -0
- package/vendor/server/src/commands/reset-admin.js +478 -0
- package/vendor/server/src/commands/restart.js +94 -0
- package/vendor/server/src/commands/sites.js +257 -0
- package/vendor/server/src/commands/status.js +158 -0
- package/vendor/server/src/commands/tunnels.js +365 -0
- package/vendor/server/src/commands/uninstall.js +326 -0
- package/vendor/server/src/config.js +38 -0
- package/vendor/server/src/exec.js +26 -0
- package/vendor/server/src/logger.js +39 -0
- package/vendor/server/src/ndjson.js +56 -0
- package/vendor/server/src/panel-api.js +85 -0
- package/vendor/server/src/state.js +45 -0
- package/vendor/server-ui/dist/assets/index-B0nWuUyL.js +257 -0
- package/vendor/server-ui/dist/assets/index-BqWWFlTU.css +1 -0
- package/vendor/server-ui/dist/index.html +13 -0
- package/vendor/serverd/package.json +44 -0
- package/vendor/serverd/src/boot.js +13 -0
- package/vendor/serverd/src/index.js +191 -0
- package/vendor/serverd/src/lib/app-error.js +14 -0
- package/vendor/serverd/src/lib/authelia.js +85 -0
- package/vendor/serverd/src/lib/certbot.js +74 -0
- package/vendor/serverd/src/lib/chisel-args.js +6 -0
- package/vendor/serverd/src/lib/chisel-reconcile.js +232 -0
- package/vendor/serverd/src/lib/chisel-runtime.js +46 -0
- package/vendor/serverd/src/lib/chisel-users.js +109 -0
- package/vendor/serverd/src/lib/chisel.js +81 -0
- package/vendor/serverd/src/lib/config.js +190 -0
- package/vendor/serverd/src/lib/constants.js +8 -0
- package/vendor/serverd/src/lib/csr-signing.js +331 -0
- package/vendor/serverd/src/lib/enrollment.js +302 -0
- package/vendor/serverd/src/lib/files.js +19 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +135 -0
- package/vendor/serverd/src/lib/invite-page.js +281 -0
- package/vendor/serverd/src/lib/ip-utils.js +79 -0
- package/vendor/serverd/src/lib/migrations/state/0001_enrollment_tokens.sql +17 -0
- package/vendor/serverd/src/lib/migrations/state/0002_tickets.sql +70 -0
- package/vendor/serverd/src/lib/migrations/state/0003_plugins.sql +15 -0
- package/vendor/serverd/src/lib/migrations/state/0004_agents.sql +19 -0
- package/vendor/serverd/src/lib/mtls.js +795 -0
- package/vendor/serverd/src/lib/nginx.js +1090 -0
- package/vendor/serverd/src/lib/pki-paths.js +41 -0
- package/vendor/serverd/src/lib/pki-sign.js +103 -0
- package/vendor/serverd/src/lib/plugins.js +538 -0
- package/vendor/serverd/src/lib/push-install.js +390 -0
- package/vendor/serverd/src/lib/revocation.js +112 -0
- package/vendor/serverd/src/lib/services.js +131 -0
- package/vendor/serverd/src/lib/session.js +151 -0
- package/vendor/serverd/src/lib/state-db.js +130 -0
- package/vendor/serverd/src/lib/state.js +140 -0
- package/vendor/serverd/src/lib/storage.js +63 -0
- package/vendor/serverd/src/lib/system-stats.js +58 -0
- package/vendor/serverd/src/lib/tickets.js +1556 -0
- package/vendor/serverd/src/lib/totp.js +76 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +41 -0
- package/vendor/serverd/src/lib/user-access-session.js +142 -0
- package/vendor/serverd/src/lib/user-access.js +52 -0
- package/vendor/serverd/src/middleware/errors.js +63 -0
- package/vendor/serverd/src/middleware/mtls.js +120 -0
- package/vendor/serverd/src/middleware/onboarding-guard.js +30 -0
- package/vendor/serverd/src/middleware/role-guard.js +58 -0
- package/vendor/serverd/src/middleware/twofa-session.js +65 -0
- package/vendor/serverd/src/middleware/user-access-session.js +52 -0
- package/vendor/serverd/src/routes/enrollment.js +120 -0
- package/vendor/serverd/src/routes/health.js +22 -0
- package/vendor/serverd/src/routes/invite.js +163 -0
- package/vendor/serverd/src/routes/management/agents.js +182 -0
- package/vendor/serverd/src/routes/management/certs.js +911 -0
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +160 -0
- package/vendor/serverd/src/routes/management/identity.js +107 -0
- package/vendor/serverd/src/routes/management/invitations.js +166 -0
- package/vendor/serverd/src/routes/management/logs.js +218 -0
- package/vendor/serverd/src/routes/management/plugins.js +560 -0
- package/vendor/serverd/src/routes/management/services.js +63 -0
- package/vendor/serverd/src/routes/management/settings.js +325 -0
- package/vendor/serverd/src/routes/management/sites.js +522 -0
- package/vendor/serverd/src/routes/management/storage.js +192 -0
- package/vendor/serverd/src/routes/management/system.js +201 -0
- package/vendor/serverd/src/routes/management/tickets.js +457 -0
- package/vendor/serverd/src/routes/management/tunnels.js +709 -0
- package/vendor/serverd/src/routes/management/users.js +377 -0
- package/vendor/serverd/src/routes/management.js +36 -0
- package/vendor/serverd/src/routes/onboarding/dns.js +101 -0
- package/vendor/serverd/src/routes/onboarding/domain.js +42 -0
- package/vendor/serverd/src/routes/onboarding/index.js +18 -0
- package/vendor/serverd/src/routes/onboarding/provision.js +327 -0
- package/vendor/serverd/src/routes/onboarding/status.js +12 -0
- package/vendor/serverd/src/routes/plugin-router.js +79 -0
- package/vendor/serverd/src/routes/user-access.js +389 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
# System Architecture Overview
|
|
2
|
+
|
|
3
|
+
> Lamaste is a relay-based tunneling platform where a $4 VPS acts as a gateway between the public internet and web apps running behind a firewall.
|
|
4
|
+
|
|
5
|
+
## In Plain English
|
|
6
|
+
|
|
7
|
+
Lamaste has three main pieces:
|
|
8
|
+
|
|
9
|
+
1. **The Installer** (`npx @lamalibre/create-lamaste@4.0.0`) — a one-shot script you run once on a fresh VPS. It sets up nginx, generates security certificates, and deploys a web-based control panel. After it finishes, you never SSH into the server again.
|
|
10
|
+
|
|
11
|
+
2. **The Panel** (browser UI + backend API) — a management interface protected by a client certificate. Through it, you configure your domain, create tunnels, manage users, and monitor services.
|
|
12
|
+
|
|
13
|
+
3. **The Tunnel Stack** (Chisel + Authelia + nginx + certbot) — the runtime infrastructure that routes traffic from the internet to your local apps through encrypted WebSocket tunnels, protected by two-factor authentication.
|
|
14
|
+
|
|
15
|
+
These three pieces interact through a clear lifecycle: the installer creates the panel, the panel provisions the tunnel stack, and the tunnel stack serves your apps.
|
|
16
|
+
|
|
17
|
+
## System Diagram
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌──────────────────────────────────────────────────────┐
|
|
21
|
+
│ VPS (Ubuntu 24.04) │
|
|
22
|
+
│ │
|
|
23
|
+
Admin Browser │ ┌──────────────────────────────────────────────┐ │
|
|
24
|
+
(with client cert) │ │ nginx (public-facing) │ │
|
|
25
|
+
│ │ │ │ │
|
|
26
|
+
│ HTTPS :9292 │ │ :9292 (mTLS, self-signed) │ │
|
|
27
|
+
├─────────────────►│ │ └─► 127.0.0.1:3100 (Panel Server) │ │
|
|
28
|
+
│ │ │ │ │
|
|
29
|
+
│ HTTPS :443 │ │ :443 (Let's Encrypt) │ │
|
|
30
|
+
│ │ │ panel.<domain> │ │
|
|
31
|
+
│ │ │ └─► 127.0.0.1:3100 (Panel Server) │ │
|
|
32
|
+
│ │ │ auth.<domain> │ │
|
|
33
|
+
End Users │ │ └─► 127.0.0.1:9091 (Authelia) │ │
|
|
34
|
+
│ │ │ tunnel.<domain> │ │
|
|
35
|
+
├─────────────────►│ │ └─► 127.0.0.1:9090 (Chisel Server) │ │
|
|
36
|
+
│ │ │ <app>.<domain> │ │
|
|
37
|
+
│ │ │ └─► auth_request to Authelia │ │
|
|
38
|
+
│ │ │ └─► 127.0.0.1:<port> (tunneled app) │ │
|
|
39
|
+
│ │ └──────────────────────────────────────────────┘ │
|
|
40
|
+
│ │ │
|
|
41
|
+
│ │ ┌──────────────┐ ┌──────────────┐ │
|
|
42
|
+
│ │ │ Panel Server │ │ Authelia │ │
|
|
43
|
+
│ │ │ (Fastify) │ │ (TOTP 2FA) │ │
|
|
44
|
+
│ │ │ 127.0.0.1 │ │ 127.0.0.1 │ │
|
|
45
|
+
│ │ │ :3100 │ │ :9091 │ │
|
|
46
|
+
│ │ └──────────────┘ └──────────────┘ │
|
|
47
|
+
│ │ │
|
|
48
|
+
│ │ ┌──────────────────────┐ │
|
|
49
|
+
│ │ │ Chisel Server │ │
|
|
50
|
+
│ │ │ 127.0.0.1:9090 │◄────── WebSocket ──────┐ │
|
|
51
|
+
│ │ │ (reverse mode) │ │ │
|
|
52
|
+
│ │ └──────────────────────┘ │ │
|
|
53
|
+
│ │ │ │
|
|
54
|
+
│ └───────────────────────────────────────────────────┼──┘
|
|
55
|
+
│ │
|
|
56
|
+
│ │
|
|
57
|
+
│ ┌──────────────────────────────────────────┐ │
|
|
58
|
+
│ │ Agent (Mac or Linux, behind NAT) │ │
|
|
59
|
+
│ │ │ │
|
|
60
|
+
│ │ ┌──────────────────────┐ │ │
|
|
61
|
+
│ │ │ Chisel Client │───────────────┼────────┘
|
|
62
|
+
│ │ │ (launchd / systemd) │ │
|
|
63
|
+
│ │ │ auto-reconnect │ │
|
|
64
|
+
│ │ └──────────┬───────────┘ │
|
|
65
|
+
│ │ │ │
|
|
66
|
+
│ │ ┌──────────┴───────────┐ │
|
|
67
|
+
│ │ │ Your Web Apps │ │
|
|
68
|
+
│ │ │ :3000, :8001, etc. │ │
|
|
69
|
+
│ │ └──────────────────────┘ │
|
|
70
|
+
│ └──────────────────────────────────────────┘
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Component Roles
|
|
74
|
+
|
|
75
|
+
| Component | Binary / Process | Role |
|
|
76
|
+
| ----------------- | -------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
77
|
+
| **nginx** | `nginx` (system package) | Only public-facing service. TLS termination, mTLS enforcement, reverse proxy, forward auth |
|
|
78
|
+
| **Panel Server** | `node src/index.js` (Fastify 5) | REST API + WebSocket backend for all management operations |
|
|
79
|
+
| **Panel Client** | Static files (React SPA) | Browser-based UI served by Panel Server via `@fastify/static` |
|
|
80
|
+
| **Chisel Server** | `/usr/local/bin/chisel` | WebSocket tunnel server accepting reverse connections from clients |
|
|
81
|
+
| **Chisel Client** | `/usr/local/bin/chisel` (on Mac) | Connects outbound to VPS, exposes local ports via reverse tunneling |
|
|
82
|
+
| **Authelia** | `/usr/local/bin/authelia` | TOTP two-factor authentication for tunneled apps via nginx forward auth |
|
|
83
|
+
| **Gatekeeper** | `node src/index.js` (Fastify 5) | Tunnel authorization service — nginx auth_request target for grant-based access control |
|
|
84
|
+
| **certbot** | `certbot` (system package) | Issues and auto-renews Let's Encrypt TLS certificates |
|
|
85
|
+
| **fail2ban** | `fail2ban` (system package) | Rate-limits brute-force attempts on SSH and nginx |
|
|
86
|
+
|
|
87
|
+
## Port Allocation
|
|
88
|
+
|
|
89
|
+
| Port | Listener | Protocol | Exposure | Purpose |
|
|
90
|
+
| ------ | ------------- | -------- | ------------- | ------------------------------------------ |
|
|
91
|
+
| `22` | sshd | TCP | Public (UFW) | SSH access (key-only after hardening) |
|
|
92
|
+
| `443` | nginx | TCP | Public (UFW) | All domain-based HTTPS traffic |
|
|
93
|
+
| `9292` | nginx | TCP | Public (UFW) | IP-based admin panel access (mTLS) |
|
|
94
|
+
| `3100` | Panel Server | TCP | Loopback only | Fastify API + static file serving |
|
|
95
|
+
| `9090` | Chisel Server | TCP | Loopback only | WebSocket tunnel endpoint |
|
|
96
|
+
| `9091` | Authelia | TCP | Loopback only | Authentication portal + forward auth API |
|
|
97
|
+
| `9294` | Gatekeeper | TCP | Loopback only | Tunnel authorization (auth_request target) |
|
|
98
|
+
|
|
99
|
+
All backend services (Panel Server, Chisel, Authelia) bind exclusively to `127.0.0.1`. nginx is the only process listening on public interfaces.
|
|
100
|
+
|
|
101
|
+
## RAM Budget (512MB Droplet)
|
|
102
|
+
|
|
103
|
+
The platform is designed to run on the cheapest possible VPS. Every technology choice was made with this constraint in mind.
|
|
104
|
+
|
|
105
|
+
| Component | Approximate RAM | Notes |
|
|
106
|
+
| ---------------------- | --------------- | ------------------------------------------------ |
|
|
107
|
+
| Ubuntu 24.04 baseline | ~120 MB | Systemd, kernel, base services |
|
|
108
|
+
| nginx | ~15 MB | Efficient C-based reverse proxy |
|
|
109
|
+
| Authelia | ~25 MB | Go binary, **must use bcrypt** (not argon2id) |
|
|
110
|
+
| Chisel Server | ~20 MB | Go binary, lightweight |
|
|
111
|
+
| Panel Server (Node.js) | ~30 MB | Fastify is one of the leanest Node.js frameworks |
|
|
112
|
+
| fail2ban | ~35 MB | Python-based, runs as daemon |
|
|
113
|
+
| **Total** | **~245 MB** | |
|
|
114
|
+
| **Headroom** | **~265 MB** | Plus 1 GB swap as safety net |
|
|
115
|
+
|
|
116
|
+
Authelia is configured with bcrypt (cost factor 12) instead of argon2id. argon2id uses ~93 MB per hash operation and causes OOM kills on 512 MB droplets. This is a hard constraint documented in Authelia's configuration at `packages/lamaste-serverd/src/lib/authelia.js`.
|
|
117
|
+
|
|
118
|
+
## Data Flow: Admin Panel Access
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
1. Admin opens https://203.0.113.42:9292 in browser
|
|
122
|
+
|
|
123
|
+
2. nginx :9292 performs TLS handshake with self-signed server cert
|
|
124
|
+
└─ ssl_verify_client optional → requests client certificate
|
|
125
|
+
└─ Enforcement per-location: if ($ssl_client_verify != SUCCESS) { return 496; }
|
|
126
|
+
└─ Public endpoints (/api/enroll, /api/invite) skip the check
|
|
127
|
+
|
|
128
|
+
3. Browser presents client.p12 certificate (imported during setup)
|
|
129
|
+
└─ nginx validates against CA at /etc/lamalibre/lamaste/pki/ca.crt
|
|
130
|
+
└─ Sets X-SSL-Client-Verify: SUCCESS header
|
|
131
|
+
|
|
132
|
+
4. nginx proxies to 127.0.0.1:3100
|
|
133
|
+
└─ Passes X-SSL-Client-Verify and X-SSL-Client-DN headers
|
|
134
|
+
|
|
135
|
+
5. Panel Server (Fastify) onRequest hook checks X-SSL-Client-Verify
|
|
136
|
+
└─ If not SUCCESS → 403 (never reached in production, nginx blocks first)
|
|
137
|
+
└─ If SUCCESS → check certificate serial against revoked.json
|
|
138
|
+
└─ If revoked → 403 "Certificate has been revoked"
|
|
139
|
+
└─ Parse X-SSL-Client-DN for CN: admin → certRole=admin; agent:<label> → certRole=agent
|
|
140
|
+
└─ Set request.certRole, request.certLabel, request.certCapabilities
|
|
141
|
+
|
|
142
|
+
6. Route handler executes business logic via lib/ layer
|
|
143
|
+
└─ Returns JSON response
|
|
144
|
+
|
|
145
|
+
7. For SPA routes (non-/api paths), Fastify serves index.html from lamaste-server-ui dist/
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Data Flow: Tunnel Traffic
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
1. Mac Chisel Client connects outbound to wss://tunnel.example.com:443
|
|
152
|
+
└─ nginx :443 terminates TLS, proxies WebSocket to 127.0.0.1:9090
|
|
153
|
+
└─ Chisel Server accepts reverse tunnel registration
|
|
154
|
+
|
|
155
|
+
2. End user visits https://myapp.example.com
|
|
156
|
+
└─ nginx :443 matches server_name myapp.example.com
|
|
157
|
+
└─ Let's Encrypt TLS certificate serves the connection
|
|
158
|
+
|
|
159
|
+
3. nginx sends auth_request to Authelia at 127.0.0.1:9091
|
|
160
|
+
└─ Authelia checks session cookie
|
|
161
|
+
└─ If no session → 401 → nginx redirects to auth.example.com
|
|
162
|
+
└─ User enters username + TOTP code
|
|
163
|
+
└─ Authelia sets session cookie → redirect back
|
|
164
|
+
|
|
165
|
+
4. With valid session, nginx proxies to 127.0.0.1:<port>
|
|
166
|
+
└─ Chisel Server forwards the request through the WebSocket tunnel
|
|
167
|
+
└─ Chisel Client on the Mac receives the request
|
|
168
|
+
└─ Chisel Client forwards to 127.0.0.1:<port> on the Mac
|
|
169
|
+
└─ Response travels back through the same path
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Gatekeeper (Tunnel Authorization)
|
|
173
|
+
|
|
174
|
+
The Gatekeeper is a dedicated Fastify service on `127.0.0.1:9294` that acts as an nginx `auth_request` target for tunnel authorization. It decouples access control decisions from both the Panel Server and Authelia, providing a generic grant-based authorization layer for tunnel traffic.
|
|
175
|
+
|
|
176
|
+
**Architecture:**
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
End User → nginx :443 → auth_request → 127.0.0.1:9294/authz/check
|
|
180
|
+
│
|
|
181
|
+
┌─────────┴──────────┐
|
|
182
|
+
│ Gatekeeper │
|
|
183
|
+
│ (Fastify, :9294) │
|
|
184
|
+
│ │
|
|
185
|
+
│ In-memory session │
|
|
186
|
+
│ cache (Map) │
|
|
187
|
+
│ │
|
|
188
|
+
│ State files: │
|
|
189
|
+
│ - groups.json │
|
|
190
|
+
│ - access-grants.json│
|
|
191
|
+
│ - gatekeeper.json │
|
|
192
|
+
└─────────────────────┘
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Grant model:** The Gatekeeper uses a generic principal-to-resource grant model. A principal is an Authelia user or a Lamaste group. A resource is a tunnel subdomain or other protected endpoint. Grants are stored in `/etc/lamalibre/lamaste/access-grants.json`.
|
|
196
|
+
|
|
197
|
+
**Lamaste groups:** Separate from Authelia groups. Stored in `/etc/lamalibre/lamaste/groups.json`. Lamaste groups allow the admin to organize users for access control without modifying Authelia's `users.yml`.
|
|
198
|
+
|
|
199
|
+
**Two-layer caching:**
|
|
200
|
+
|
|
201
|
+
1. **nginx `proxy_cache`** — the `lamaste_authz` cache zone (1m keys, 10m storage) caches authorization responses. Cache key is `$cookie_authelia_session$http_host`. Positive responses (200) are cached for 30 seconds, negative responses (401/403) for 10 seconds. This eliminates redundant auth_request subrequests for rapid page loads.
|
|
202
|
+
2. **In-memory session cache** — the Gatekeeper maintains a `Map` of recent authorization decisions keyed by session + host. This avoids re-reading state files on every check within the cache TTL.
|
|
203
|
+
|
|
204
|
+
**State files:** All stored in `/etc/lamalibre/lamaste/` with 0600 permissions, `lamaste:lamaste` ownership, and atomic writes (tmp, fsync, rename):
|
|
205
|
+
|
|
206
|
+
- `groups.json` — Lamaste group definitions and membership
|
|
207
|
+
- `access-grants.json` — Principal-to-resource access grants
|
|
208
|
+
- `gatekeeper.json` — Settings (admin contact info, cache TTL, logging configuration)
|
|
209
|
+
- `access-request-log.json` — Optional log of denied access attempts (for admin review)
|
|
210
|
+
|
|
211
|
+
**Service:** Runs as `lamalibre-lamaste-gatekeeper.service` (systemd), binding `127.0.0.1:9294`. nginx is the sole entry point — the Gatekeeper is never directly accessible from the internet.
|
|
212
|
+
|
|
213
|
+
## Data Flow: Onboarding Provisioning
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
1. Admin completes domain + DNS verification in the panel UI
|
|
217
|
+
|
|
218
|
+
2. Panel Client sends POST /api/onboarding/provision
|
|
219
|
+
└─ Panel Server starts background provisioning task
|
|
220
|
+
└─ Returns 202 Accepted immediately
|
|
221
|
+
|
|
222
|
+
3. Panel Client opens WebSocket to /api/onboarding/provision/stream
|
|
223
|
+
└─ Receives real-time progress events for each task
|
|
224
|
+
|
|
225
|
+
4. Provisioning sequence (in Panel Server):
|
|
226
|
+
a. Check Chisel is installed (create-lamaste installed the pinned release
|
|
227
|
+
and its unit), create its key and authfile, start it
|
|
228
|
+
b. Check Authelia is installed (likewise: pinned release, unit, account)
|
|
229
|
+
c. Write Authelia config (bcrypt, TOTP, session cookies)
|
|
230
|
+
d. Create admin user with random password
|
|
231
|
+
e. Issue Let's Encrypt certs for panel/auth/tunnel subdomains
|
|
232
|
+
f. Write nginx vhosts for panel-domain, auth, tunnel
|
|
233
|
+
g. Enable sites + test nginx config + reload
|
|
234
|
+
h. Verify all services are running + healthy
|
|
235
|
+
i. Update panel.json onboarding.status to COMPLETED
|
|
236
|
+
|
|
237
|
+
5. Panel Client receives completion event with admin credentials
|
|
238
|
+
└─ Displays TOTP enrollment QR code
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Monorepo Structure
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
lamaste/
|
|
245
|
+
├── packages/
|
|
246
|
+
│ ├── create-lamaste/ ← npx installer (zero-prompt)
|
|
247
|
+
│ │ ├── bin/create-lamaste.js ← CLI entry point
|
|
248
|
+
│ │ ├── src/
|
|
249
|
+
│ │ │ ├── index.js ← Listr2 orchestrator
|
|
250
|
+
│ │ │ ├── tasks/
|
|
251
|
+
│ │ │ │ ├── harden.js ← OS hardening (swap, UFW, fail2ban, SSH)
|
|
252
|
+
│ │ │ │ ├── node.js ← Node.js 20 installation
|
|
253
|
+
│ │ │ │ ├── mtls.js ← mTLS CA + client cert generation
|
|
254
|
+
│ │ │ │ ├── nginx.js ← IP-based nginx vhost + mTLS snippet
|
|
255
|
+
│ │ │ │ ├── panel.js ← Panel deployment + systemd service
|
|
256
|
+
│ │ │ │ ├── gatekeeper.js ← Gatekeeper deployment
|
|
257
|
+
│ │ │ │ └── redeploy.js ← Redeployment (upgrade, self-update)
|
|
258
|
+
│ │ │ └── lib/
|
|
259
|
+
│ │ │ ├── env.js ← OS detection, IP detection, root check
|
|
260
|
+
│ │ │ ├── secrets.js ← crypto.randomBytes wrappers
|
|
261
|
+
│ │ │ ├── summary.js ← Post-install summary box
|
|
262
|
+
│ │ │ ├── cert-help-page.js ← HTML page for visitors without certs
|
|
263
|
+
│ │ │ ├── relay-services.js ← Pinned chisel + Authelia, units, accounts, ownership
|
|
264
|
+
│ │ │ ├── ownership.js ← Symlink-safe root writes and ownership migrations
|
|
265
|
+
│ │ │ ├── wrappers.js ← Installs lamaste-priv etc. and the sudoers file
|
|
266
|
+
│ │ │ └── service-config.js ← Systemd unit + sudoers content generators
|
|
267
|
+
│ │ ├── scripts/ ← lamaste-priv, lamaste-certbot, lamaste-cert-info
|
|
268
|
+
│ │ └── vendor/ ← Bundled lamalibre-lamaste-serverd + lamaste-server-ui at publish time
|
|
269
|
+
│ │
|
|
270
|
+
│ ├── lamaste-serverd/ ← Fastify REST API (127.0.0.1:3100)
|
|
271
|
+
│ │ └── src/
|
|
272
|
+
│ │ ├── index.js ← Server entry, plugin registration
|
|
273
|
+
│ │ ├── middleware/
|
|
274
|
+
│ │ │ ├── mtls.js ← Client cert verification + revocation + role parsing
|
|
275
|
+
│ │ │ ├── role-guard.js ← Role-based access control (admin vs agent capabilities)
|
|
276
|
+
│ │ │ ├── onboarding-guard.js ← Route access control by onboarding state
|
|
277
|
+
│ │ │ ├── twofa-session.js ← 2FA session validation (runs after mTLS, before roleGuard)
|
|
278
|
+
│ │ │ └── errors.js ← Global error handler (Zod, AppError, 500)
|
|
279
|
+
│ │ ├── routes/
|
|
280
|
+
│ │ │ ├── health.js ← GET /api/health
|
|
281
|
+
│ │ │ ├── invite.js ← Public invite acceptance routes (no mTLS)
|
|
282
|
+
│ │ │ ├── enrollment.js ← Public /api/enroll endpoint for agent certificate enrollment
|
|
283
|
+
│ │ │ ├── onboarding/
|
|
284
|
+
│ │ │ │ ├── index.js ← Route registration + guard
|
|
285
|
+
│ │ │ │ ├── status.js ← GET /api/onboarding/status
|
|
286
|
+
│ │ │ │ ├── domain.js ← POST /api/onboarding/domain
|
|
287
|
+
│ │ │ │ ├── dns.js ← POST /api/onboarding/verify-dns
|
|
288
|
+
│ │ │ │ └── provision.js ← POST + WebSocket provisioning
|
|
289
|
+
│ │ │ ├── management.js ← Route registration + guard
|
|
290
|
+
│ │ │ └── management/
|
|
291
|
+
│ │ │ ├── invitations.js ← Invitation CRUD (admin-only)
|
|
292
|
+
│ │ │ ├── system.js ← GET /api/system/stats
|
|
293
|
+
│ │ │ ├── services.js ← Service start/stop/restart
|
|
294
|
+
│ │ │ ├── logs.js ← WebSocket live log streaming
|
|
295
|
+
│ │ │ ├── tunnels.js ← Tunnel CRUD, ownership, agent-config
|
|
296
|
+
│ │ │ ├── sites.js ← Static site CRUD + file management
|
|
297
|
+
│ │ │ ├── users.js ← Authelia user CRUD + TOTP
|
|
298
|
+
│ │ │ ├── certs.js ← Certificate listing + renewal + mTLS rotation
|
|
299
|
+
│ │ │ ├── plugins.js ← Plugin management + push install API
|
|
300
|
+
│ │ │ ├── settings.js ← 2FA and admin auth mode endpoints
|
|
301
|
+
│ │ │ └── tickets.js ← Agent-to-agent authorization endpoints
|
|
302
|
+
│ │ ├── plugin-router.js ← Dynamic plugin route mounting + disabled-plugin guard
|
|
303
|
+
│ │ └── lib/
|
|
304
|
+
│ │ ├── config.js ← panel.json loading + Zod validation + atomic updates
|
|
305
|
+
│ │ ├── state.js ← tunnels.json + sites.json + invitations.json atomic read/write
|
|
306
|
+
│ │ ├── revocation.js ← Certificate revocation list management (revoked.json)
|
|
307
|
+
│ │ ├── invite-page.js ← Invitation acceptance HTML page generator
|
|
308
|
+
│ │ ├── nginx.js ← Vhost generation + write-with-rollback + reload
|
|
309
|
+
│ │ ├── chisel.js ← Chisel key + service management + syncChisel
|
|
310
|
+
│ │ ├── chisel-users.js ← Per-agent Chisel credentials + authfile grants
|
|
311
|
+
│ │ ├── chisel-reconcile.js ← Startup reconciliation of Chisel (fail closed)
|
|
312
|
+
│ │ ├── chisel-runtime.js ← Restart decision for authfile changes
|
|
313
|
+
│ │ ├── tunnel-deps.js ← Dependencies for the core tunnel workflows
|
|
314
|
+
│ │ ├── authelia.js ← Authelia install + config + user CRUD
|
|
315
|
+
│ │ ├── certbot.js ← Let's Encrypt issuance + renewal
|
|
316
|
+
│ │ ├── mtls.js ← mTLS cert info + rotation + dynamic capabilities
|
|
317
|
+
│ │ ├── plugins.js ← Plugin install/uninstall/enable/disable + manifest validation
|
|
318
|
+
│ │ ├── push-install.js ← Push install config, policies, sessions, agent enable/disable
|
|
319
|
+
│ │ ├── services.js ← systemctl wrapper for managed services
|
|
320
|
+
│ │ ├── system-stats.js ← CPU, memory, disk stats via systeminformation
|
|
321
|
+
│ │ ├── files.js ← Static site file operations (upload, delete, list)
|
|
322
|
+
│ │ └── app-error.js ← Operational error class (AppError)
|
|
323
|
+
│ │
|
|
324
|
+
│ ├── lamaste-server-ui/ ← React 18 + Vite + Tailwind SPA + shared admin components (@lamalibre/lamaste-server-ui@4.0.0)
|
|
325
|
+
│ │ └── src/
|
|
326
|
+
│ │ ├── index.js ← Package exports (pages, context, utilities)
|
|
327
|
+
│ │ ├── context/
|
|
328
|
+
│ │ │ ├── AdminClientContext.jsx ← Host-agnostic data client abstraction
|
|
329
|
+
│ │ │ └── TwoFaContext.jsx ← 2FA verification state management
|
|
330
|
+
│ │ ├── components/
|
|
331
|
+
│ │ │ ├── Toast.jsx ← Toast notification system
|
|
332
|
+
│ │ │ ├── TwoFaVerifyModal.jsx ← 2FA verification modal
|
|
333
|
+
│ │ │ ├── FileBrowser.jsx ← File tree for static site management
|
|
334
|
+
│ │ │ └── PluginLoader.jsx ← Plugin micro-frontend loader
|
|
335
|
+
│ │ ├── lib/
|
|
336
|
+
│ │ │ ├── cn.js ← Class name utility
|
|
337
|
+
│ │ │ └── formatters.js ← Byte, uptime, relative time formatters
|
|
338
|
+
│ │ └── pages/ ← Admin pages (Dashboard, Tunnels, Sites, Users, Certs, Services, Plugins, Tickets, Settings)
|
|
339
|
+
│ │
|
|
340
|
+
│ ├── lamaste-agent-ui/ ← Shared React agent UI (pages, context, components) (@lamalibre/lamaste-agent-ui@4.0.0)
|
|
341
|
+
│ │
|
|
342
|
+
│ ├── lamaste-tickets/ ← Agent-to-agent authorization SDK (mTLS, undici)
|
|
343
|
+
│ │ └── src/
|
|
344
|
+
│ │ ├── index.ts ← Client + types
|
|
345
|
+
│ │ └── ...
|
|
346
|
+
│ │
|
|
347
|
+
│ ├── lamaste-cloud/ ← Cloud provider abstraction for server provisioning
|
|
348
|
+
│ │ ├── bin/lamaste-cloud.js ← CLI entry point (NDJSON progress on stdout)
|
|
349
|
+
│ │ └── src/
|
|
350
|
+
│ │ ├── index.ts ← Provider exports
|
|
351
|
+
│ │ ├── provider.ts ← CloudProvider interface
|
|
352
|
+
│ │ ├── provisioner.ts ← Provisioning orchestrator (create → install → configure)
|
|
353
|
+
│ │ ├── registry.ts ← Server registry (servers.json, atomic writes)
|
|
354
|
+
│ │ ├── ssh.ts ← SSH/SCP with temporary ed25519 keys
|
|
355
|
+
│ │ ├── types.ts ← Shared types
|
|
356
|
+
│ │ ├── errors.ts ← Error types
|
|
357
|
+
│ │ └── digitalocean/ ← DigitalOcean provider implementation
|
|
358
|
+
│ │
|
|
359
|
+
│ └── lamaste-server-ui/ ← (continued) SPA entry point, onboarding pages, browser-specific code
|
|
360
|
+
│ └── src/
|
|
361
|
+
│ ├── App.jsx ← Mode detection, routing, provider wrappers
|
|
362
|
+
│ ├── main.jsx ← React root mount
|
|
363
|
+
│ ├── lib/
|
|
364
|
+
│ │ ├── api.js ← API fetch helper with 2FA detection
|
|
365
|
+
│ │ ├── cn.js ← className utility
|
|
366
|
+
│ │ ├── formatters.js ← Byte/time formatters
|
|
367
|
+
│ │ └── web-admin-client.js ← AdminClient implementation via apiFetch
|
|
368
|
+
│ ├── hooks/
|
|
369
|
+
│ │ ├── useOnboardingStatus.js ← Determines onboarding vs management mode
|
|
370
|
+
│ │ └── useProvisioningStream.js ← WebSocket hook for provisioning progress
|
|
371
|
+
│ ├── pages/
|
|
372
|
+
│ │ ├── onboarding/
|
|
373
|
+
│ │ │ ├── OnboardingShell.jsx ← Step container + progress indicator
|
|
374
|
+
│ │ │ ├── DomainStep.jsx ← Domain + email form
|
|
375
|
+
│ │ │ ├── DnsStep.jsx ← DNS record display + verification
|
|
376
|
+
│ │ │ ├── ProvisioningStep.jsx ← Real-time progress + log viewer
|
|
377
|
+
│ │ │ └── CompleteStep.jsx ← Credentials + TOTP QR + next steps
|
|
378
|
+
│ │ ├── management/ ← Legacy standalone implementations (kept for reference)
|
|
379
|
+
│ │ │ ├── Certificates.jsx ← Standalone certificates page (dead code)
|
|
380
|
+
│ │ │ ├── Dashboard.jsx ← Standalone dashboard (not imported — App.jsx uses @lamalibre/lamaste-server-ui@4.0.0)
|
|
381
|
+
│ │ │ ├── Plugins.jsx ← Standalone plugins page (dead code)
|
|
382
|
+
│ │ │ ├── Services.jsx ← Standalone services page (dead code)
|
|
383
|
+
│ │ │ ├── Settings.jsx ← Standalone settings page (dead code)
|
|
384
|
+
│ │ │ ├── Sites.jsx ← Standalone sites page (dead code)
|
|
385
|
+
│ │ │ ├── Tickets.jsx ← Standalone tickets page (dead code)
|
|
386
|
+
│ │ │ └── Tunnels.jsx ← Standalone tunnels page (dead code)
|
|
387
|
+
│ │ └── docs/
|
|
388
|
+
│ │ └── DocsPage.jsx ← Documentation viewer (markdown)
|
|
389
|
+
│ └── components/
|
|
390
|
+
│ ├── layout/
|
|
391
|
+
│ │ ├── Layout.jsx ← Sidebar + content area
|
|
392
|
+
│ │ ├── Sidebar.jsx ← Navigation with mobile responsive
|
|
393
|
+
│ │ └── SidebarLink.jsx ← Active-state nav link
|
|
394
|
+
│ ├── PluginLoaderRoute.jsx ← Bridges React Router params to shared PluginLoader
|
|
395
|
+
│ ├── PluginLoader.jsx ← Legacy plugin loader (dead code — shared package version used)
|
|
396
|
+
│ ├── Toast.jsx ← Toast notification system
|
|
397
|
+
│ ├── LoadingScreen.jsx ← Full-page loading state
|
|
398
|
+
│ ├── ErrorScreen.jsx ← Full-page error with retry
|
|
399
|
+
│ └── FileBrowser.jsx ← File tree for static site management
|
|
400
|
+
│
|
|
401
|
+
└── CLAUDE.md ← Project context for AI agents
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Security Layers
|
|
405
|
+
|
|
406
|
+
The platform implements defense-in-depth with multiple security layers:
|
|
407
|
+
|
|
408
|
+
```
|
|
409
|
+
Layer 1: Network (UFW)
|
|
410
|
+
└─ Only ports 22, 443, 9292 open
|
|
411
|
+
└─ Everything else is firewalled
|
|
412
|
+
|
|
413
|
+
Layer 2: fail2ban
|
|
414
|
+
└─ SSH brute-force protection (5 attempts → 1 hour ban)
|
|
415
|
+
└─ nginx auth failure protection
|
|
416
|
+
|
|
417
|
+
Layer 3: SSH Hardening
|
|
418
|
+
└─ Password authentication disabled
|
|
419
|
+
└─ Root login with key only
|
|
420
|
+
|
|
421
|
+
Layer 4: mTLS (Admin Panel)
|
|
422
|
+
└─ nginx rejects connections without valid client certificate
|
|
423
|
+
└─ Panel Server double-checks X-SSL-Client-Verify header
|
|
424
|
+
└─ Panel Server checks certificate serial against revoked.json
|
|
425
|
+
└─ Panel Server parses DN for role (admin vs agent) and sets certRole/certLabel/certCapabilities
|
|
426
|
+
└─ Agent capabilities: tunnels:read/write, services:read/write, system:read, sites:read/write, plus plugin-declared capabilities
|
|
427
|
+
|
|
428
|
+
Layer 5: Authelia (Tunneled Apps)
|
|
429
|
+
└─ nginx forward auth for every app request
|
|
430
|
+
└─ TOTP two-factor authentication
|
|
431
|
+
└─ Session cookies scoped to domain
|
|
432
|
+
|
|
433
|
+
Layer 6: Service Isolation
|
|
434
|
+
└─ All backend services bind 127.0.0.1 only
|
|
435
|
+
└─ lamaste user runs with minimal privileges; code in /opt/lamalibre/lamaste is root-owned
|
|
436
|
+
└─ Fixed sudoers command lines + the validating lamaste-priv helper (no wildcards)
|
|
437
|
+
└─ Authelia runs as its own account (lamaste-authelia), Chisel as nobody:lamaste-chisel
|
|
438
|
+
└─ systemd security hardening (NoNewPrivileges, ProtectSystem, ProtectHome)
|
|
439
|
+
|
|
440
|
+
Layer 7: TLS Everywhere
|
|
441
|
+
└─ IP access: self-signed cert (port 9292)
|
|
442
|
+
└─ Domain access: Let's Encrypt (port 443)
|
|
443
|
+
└─ Tunnel traffic: WebSocket over HTTPS
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Design Decisions
|
|
447
|
+
|
|
448
|
+
### Why a $4 VPS as relay instead of a VPN or cloud deploy?
|
|
449
|
+
|
|
450
|
+
VPNs like Tailscale or Cloudflare Tunnel work well but lock you into a service provider. Cloud deployment means maintaining infrastructure and paying for compute. Lamaste uses the cheapest possible VPS purely as a relay — your actual compute stays on hardware you own and control.
|
|
451
|
+
|
|
452
|
+
### Why nginx instead of Caddy or Traefik?
|
|
453
|
+
|
|
454
|
+
nginx has the smallest memory footprint of production-grade reverse proxies (~15 MB). On a 512 MB budget, every megabyte matters. nginx also has the most mature mTLS support and the widest documentation base. The tradeoff is more configuration complexity, which is managed programmatically through the Panel Server's `nginx.js` library.
|
|
455
|
+
|
|
456
|
+
### Why Chisel instead of SSH tunneling or WireGuard?
|
|
457
|
+
|
|
458
|
+
Chisel tunnels over WebSocket-over-HTTPS, which passes through virtually any firewall or DPI system. SSH tunnels are often blocked by corporate firewalls, and WireGuard requires a separate UDP port. Chisel also has built-in auto-reconnect and runs as a single Go binary with ~20 MB RAM usage.
|
|
459
|
+
|
|
460
|
+
### Why Authelia instead of a simpler auth solution?
|
|
461
|
+
|
|
462
|
+
Authelia provides TOTP 2FA as a single binary with ~25 MB RAM usage and file-based user storage. Alternatives like Keycloak (~500 MB RAM) or Auth0 (SaaS dependency) do not fit the constraints. Authelia integrates with nginx via the standard `auth_request` module.
|
|
463
|
+
|
|
464
|
+
### Why mTLS instead of passwords for the admin panel?
|
|
465
|
+
|
|
466
|
+
mTLS provides zero-login authentication — the browser presents the certificate automatically at the TLS level, before any HTTP request is processed. This eliminates credential stuffing, phishing, and session hijacking for admin access. The tradeoff is a one-time certificate import process during setup.
|
|
467
|
+
|
|
468
|
+
### Why JSON files instead of a database?
|
|
469
|
+
|
|
470
|
+
At this scale (single admin, handful of tunnels), a database adds RAM overhead and operational complexity for no benefit. JSON files with atomic writes (write temp, fsync, rename) provide crash-safe persistence. The entire state fits in a few kilobytes. Authelia's user database is YAML-based for the same reason.
|
|
471
|
+
|
|
472
|
+
### Why IP:9292 always works?
|
|
473
|
+
|
|
474
|
+
The IP-based panel access on port 9292 is the ultimate fallback. If your domain expires, DNS breaks, or Let's Encrypt fails to renew, you can always reach the panel via `https://<ip>:9292` to fix things. This is a core safety invariant of the system.
|
|
475
|
+
|
|
476
|
+
### Why systemd for all services?
|
|
477
|
+
|
|
478
|
+
systemd provides automatic restart on failure, structured logging via journal, dependency ordering, and resource isolation (cgroups). All Lamaste services (`lamalibre-lamaste-serverd`, `chisel`, `authelia`) are managed through systemd, giving a consistent interface for the Panel Server to start, stop, restart, and query status. The `services.js` library wraps `systemctl` commands with an allowlist to prevent arbitrary service manipulation.
|
|
479
|
+
|
|
480
|
+
### Why sudoers instead of running as root?
|
|
481
|
+
|
|
482
|
+
The Panel Server runs as the `lamaste` user with minimal privileges and cannot become root. The files it manages (state, PKI, web root, Authelia configuration, Chisel authfile) belong to it or to a group it is in, so most work needs no privileges at all. What does — service control, `nginx -t`, installing its nginx vhosts, storing an Authelia TOTP secret, certbot, starting a self-update — goes through fixed `sudoers` command lines and three root-owned programs that validate their arguments (`lamaste-priv`, `lamaste-certbot`, `lamaste-cert-info`). There is no wildcard rule and no blanket `lamaste ALL=(ALL) NOPASSWD: ALL`. Binaries, units and service accounts are installed by `create-lamaste` as root. This limits the blast radius of a compromised Panel Server process; see [Security Model](../01-concepts/security-model.md#privilege-boundary).
|
|
483
|
+
|
|
484
|
+
## Lifecycle Summary
|
|
485
|
+
|
|
486
|
+
The full lifecycle of a Lamaste installation:
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
Phase 1: Installation (npx @lamalibre/create-lamaste@4.0.0)
|
|
490
|
+
└─ OS hardening, Node.js, mTLS certs, nginx, panel deploy
|
|
491
|
+
└─ Result: Panel accessible at https://<ip>:9292
|
|
492
|
+
|
|
493
|
+
Phase 2: Onboarding (browser UI)
|
|
494
|
+
└─ Domain input → DNS verification → stack provisioning
|
|
495
|
+
└─ Provisions: Chisel, Authelia, Let's Encrypt, domain nginx vhosts
|
|
496
|
+
└─ Result: Panel accessible at https://panel.<domain>
|
|
497
|
+
|
|
498
|
+
Phase 3: Operation (browser UI)
|
|
499
|
+
└─ Create tunnels → apps accessible at https://<app>.<domain>
|
|
500
|
+
└─ Manage users → TOTP enrollment for app access
|
|
501
|
+
└─ Host static sites → served via nginx at https://<site>.<domain>
|
|
502
|
+
└─ Monitor services → dashboard, live logs
|
|
503
|
+
└─ Manage certificates → auto-renewal, mTLS rotation
|
|
504
|
+
└─ Install plugins → extend functionality via @lamalibre/ npm packages
|
|
505
|
+
|
|
506
|
+
Phase 4: Recovery (if needed)
|
|
507
|
+
└─ Domain lost? → https://<ip>:9292 always works
|
|
508
|
+
└─ Service down? → Panel shows status, restart from UI
|
|
509
|
+
└─ Cert expired? → Renew from certificates page
|
|
510
|
+
└─ Need to re-install? → Re-run installer, config preserved
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## Key Files
|
|
514
|
+
|
|
515
|
+
| File | Role |
|
|
516
|
+
| ------------------------------------------------------- | ------------------------------------------------------- |
|
|
517
|
+
| `/etc/lamalibre/lamaste/panel.json` | Central configuration (IP, domain, onboarding state) |
|
|
518
|
+
| `/etc/lamalibre/lamaste/tunnels.json` | Tunnel definitions |
|
|
519
|
+
| `/etc/lamalibre/lamaste/sites.json` | Static site definitions |
|
|
520
|
+
| `/etc/lamalibre/lamaste/pki/` | mTLS certificates (CA, client, server, PKCS12) |
|
|
521
|
+
| `/opt/lamalibre/lamaste/lamaste-serverd/` | Deployed Panel Server code |
|
|
522
|
+
| `/opt/lamalibre/lamaste/lamaste-server-ui/dist/` | Built Panel Client SPA |
|
|
523
|
+
| `/var/www/lamaste/` | Static site file roots |
|
|
524
|
+
| `/etc/nginx/sites-available/lamaste-*` | nginx vhost configurations |
|
|
525
|
+
| `/etc/nginx/snippets/lamalibre-lamaste-mtls.conf` | Shared mTLS snippet |
|
|
526
|
+
| `/etc/authelia/configuration.yml` | Authelia main config |
|
|
527
|
+
| `/etc/authelia/users.yml` | Authelia user database |
|
|
528
|
+
| `/etc/systemd/system/lamalibre-lamaste-serverd.service` | Panel Server systemd unit |
|
|
529
|
+
| `/etc/systemd/system/chisel.service` | Chisel Server systemd unit |
|
|
530
|
+
| `/etc/systemd/system/authelia.service` | Authelia systemd unit |
|
|
531
|
+
| `/etc/lamalibre/lamaste/plugins.json` | Plugin registry (installed plugins and status) |
|
|
532
|
+
| `/etc/lamalibre/lamaste/plugins/` | Per-plugin data directories |
|
|
533
|
+
| `/etc/lamalibre/lamaste/groups.json` | Lamaste group definitions and membership |
|
|
534
|
+
| `/etc/lamalibre/lamaste/access-grants.json` | Generic access grants (principal → resource) |
|
|
535
|
+
| `/etc/lamalibre/lamaste/gatekeeper.json` | Gatekeeper settings (cache TTL, admin contact, logging) |
|
|
536
|
+
| `/etc/lamalibre/lamaste/push-install-config.json` | Push install configuration and policies |
|
|
537
|
+
| `/etc/lamalibre/lamaste/push-install-sessions.json` | Push install session audit log |
|
|
538
|
+
| `/etc/sudoers.d/lamaste` | Fixed sudo rules for lamaste user (no wildcards) |
|
|
539
|
+
| `/usr/local/sbin/lamaste-priv` | Root helper: panel vhosts, Authelia TOTP, self-update |
|
|
540
|
+
| `~/.lamalibre/lamaste/servers.json` | Desktop app server registry (multi-server support) |
|
|
541
|
+
| `~/.lamalibre/lamaste/services.json` | Desktop app service discovery registry |
|