@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.
Files changed (270) hide show
  1. package/LICENSE.md +118 -0
  2. package/README.md +114 -0
  3. package/bin/create-lamaste.js +15 -0
  4. package/package.json +54 -0
  5. package/scripts/bundle-vendor.js +110 -0
  6. package/scripts/lamaste-cert-info +62 -0
  7. package/scripts/lamaste-certbot +96 -0
  8. package/scripts/lamaste-priv +693 -0
  9. package/src/index.js +646 -0
  10. package/src/lib/accounts.js +86 -0
  11. package/src/lib/binaries.js +137 -0
  12. package/src/lib/cert-help-page.js +160 -0
  13. package/src/lib/env.js +132 -0
  14. package/src/lib/http-redirect.js +38 -0
  15. package/src/lib/ownership.js +231 -0
  16. package/src/lib/relay-services.js +103 -0
  17. package/src/lib/secrets.js +19 -0
  18. package/src/lib/service-config.js +311 -0
  19. package/src/lib/summary.js +131 -0
  20. package/src/lib/wrappers.js +63 -0
  21. package/src/tasks/gatekeeper.js +233 -0
  22. package/src/tasks/harden.js +293 -0
  23. package/src/tasks/mtls.js +193 -0
  24. package/src/tasks/nginx.js +265 -0
  25. package/src/tasks/node.js +110 -0
  26. package/src/tasks/panel.js +408 -0
  27. package/src/tasks/redeploy.js +438 -0
  28. package/vendor/docs/00-introduction/how-it-works.md +447 -0
  29. package/vendor/docs/00-introduction/quickstart.md +472 -0
  30. package/vendor/docs/00-introduction/what-is-lamaste.md +112 -0
  31. package/vendor/docs/01-concepts/authentication.md +464 -0
  32. package/vendor/docs/01-concepts/authorization.md +242 -0
  33. package/vendor/docs/01-concepts/certificates.md +452 -0
  34. package/vendor/docs/01-concepts/dns-and-domains.md +343 -0
  35. package/vendor/docs/01-concepts/mtls.md +490 -0
  36. package/vendor/docs/01-concepts/nginx-reverse-proxy.md +540 -0
  37. package/vendor/docs/01-concepts/security-model.md +600 -0
  38. package/vendor/docs/01-concepts/tickets.md +414 -0
  39. package/vendor/docs/01-concepts/tunneling.md +367 -0
  40. package/vendor/docs/02-guides/agent-setup.md +194 -0
  41. package/vendor/docs/02-guides/certificate-management.md +341 -0
  42. package/vendor/docs/02-guides/cloud-provisioning.md +406 -0
  43. package/vendor/docs/02-guides/desktop-app-setup.md +226 -0
  44. package/vendor/docs/02-guides/disaster-recovery.md +464 -0
  45. package/vendor/docs/02-guides/first-tunnel.md +230 -0
  46. package/vendor/docs/02-guides/installation.md +393 -0
  47. package/vendor/docs/02-guides/managing-users.md +255 -0
  48. package/vendor/docs/02-guides/onboarding.md +244 -0
  49. package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +375 -0
  50. package/vendor/docs/02-guides/static-sites.md +364 -0
  51. package/vendor/docs/03-architecture/e2e-three-vm-sequences.md +457 -0
  52. package/vendor/docs/03-architecture/installer-flow.md +151 -0
  53. package/vendor/docs/03-architecture/installer.md +445 -0
  54. package/vendor/docs/03-architecture/management-flow.md +288 -0
  55. package/vendor/docs/03-architecture/nginx-configuration.md +830 -0
  56. package/vendor/docs/03-architecture/onboarding-flow.md +164 -0
  57. package/vendor/docs/03-architecture/overview.md +541 -0
  58. package/vendor/docs/03-architecture/panel-client.md +416 -0
  59. package/vendor/docs/03-architecture/panel-server.md +695 -0
  60. package/vendor/docs/03-architecture/state-management.md +529 -0
  61. package/vendor/docs/03-architecture/system-overview.md +167 -0
  62. package/vendor/docs/04-api-reference/certificates.md +1141 -0
  63. package/vendor/docs/04-api-reference/gatekeeper.md +592 -0
  64. package/vendor/docs/04-api-reference/onboarding.md +473 -0
  65. package/vendor/docs/04-api-reference/overview.md +404 -0
  66. package/vendor/docs/04-api-reference/services.md +267 -0
  67. package/vendor/docs/04-api-reference/settings.md +343 -0
  68. package/vendor/docs/04-api-reference/sites.md +716 -0
  69. package/vendor/docs/04-api-reference/system.md +268 -0
  70. package/vendor/docs/04-api-reference/tickets.md +618 -0
  71. package/vendor/docs/04-api-reference/tunnels.md +417 -0
  72. package/vendor/docs/04-api-reference/users.md +333 -0
  73. package/vendor/docs/05-operations/backup-and-restore.md +342 -0
  74. package/vendor/docs/05-operations/monitoring.md +285 -0
  75. package/vendor/docs/05-operations/uninstalling.md +344 -0
  76. package/vendor/docs/05-operations/upgrades.md +270 -0
  77. package/vendor/docs/06-reference/config-files.md +1080 -0
  78. package/vendor/docs/06-reference/glossary.md +528 -0
  79. package/vendor/docs/06-reference/installer-flags.md +260 -0
  80. package/vendor/docs/06-reference/ports-and-services.md +244 -0
  81. package/vendor/docs/06-reference/troubleshooting.md +665 -0
  82. package/vendor/docs/_index.json +233 -0
  83. package/vendor/docs/gatekeeper-design.md +953 -0
  84. package/vendor/docs/package.json +15 -0
  85. package/vendor/docs/todo/lib-cli-desktop-refactor.md +641 -0
  86. package/vendor/gatekeeper/dist/boot.d.ts +1 -0
  87. package/vendor/gatekeeper/dist/boot.d.ts.map +1 -0
  88. package/vendor/gatekeeper/dist/boot.js +17 -0
  89. package/vendor/gatekeeper/dist/boot.js.map +1 -0
  90. package/vendor/gatekeeper/dist/cli/commands/access.d.ts +2 -0
  91. package/vendor/gatekeeper/dist/cli/commands/access.d.ts.map +1 -0
  92. package/vendor/gatekeeper/dist/cli/commands/access.js +33 -0
  93. package/vendor/gatekeeper/dist/cli/commands/access.js.map +1 -0
  94. package/vendor/gatekeeper/dist/cli/commands/grants.d.ts +2 -0
  95. package/vendor/gatekeeper/dist/cli/commands/grants.d.ts.map +1 -0
  96. package/vendor/gatekeeper/dist/cli/commands/grants.js +110 -0
  97. package/vendor/gatekeeper/dist/cli/commands/grants.js.map +1 -0
  98. package/vendor/gatekeeper/dist/cli/commands/groups.d.ts +2 -0
  99. package/vendor/gatekeeper/dist/cli/commands/groups.d.ts.map +1 -0
  100. package/vendor/gatekeeper/dist/cli/commands/groups.js +98 -0
  101. package/vendor/gatekeeper/dist/cli/commands/groups.js.map +1 -0
  102. package/vendor/gatekeeper/dist/cli/index.d.ts +3 -0
  103. package/vendor/gatekeeper/dist/cli/index.d.ts.map +1 -0
  104. package/vendor/gatekeeper/dist/cli/index.js +45 -0
  105. package/vendor/gatekeeper/dist/cli/index.js.map +1 -0
  106. package/vendor/gatekeeper/dist/index.d.ts +9 -0
  107. package/vendor/gatekeeper/dist/index.d.ts.map +1 -0
  108. package/vendor/gatekeeper/dist/index.js +13 -0
  109. package/vendor/gatekeeper/dist/index.js.map +1 -0
  110. package/vendor/gatekeeper/dist/lib/authz.d.ts +16 -0
  111. package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -0
  112. package/vendor/gatekeeper/dist/lib/authz.js +42 -0
  113. package/vendor/gatekeeper/dist/lib/authz.js.map +1 -0
  114. package/vendor/gatekeeper/dist/lib/cache-bust.d.ts +15 -0
  115. package/vendor/gatekeeper/dist/lib/cache-bust.d.ts.map +1 -0
  116. package/vendor/gatekeeper/dist/lib/cache-bust.js +19 -0
  117. package/vendor/gatekeeper/dist/lib/cache-bust.js.map +1 -0
  118. package/vendor/gatekeeper/dist/lib/constants.d.ts +82 -0
  119. package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -0
  120. package/vendor/gatekeeper/dist/lib/constants.js +79 -0
  121. package/vendor/gatekeeper/dist/lib/constants.js.map +1 -0
  122. package/vendor/gatekeeper/dist/lib/grants.d.ts +32 -0
  123. package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -0
  124. package/vendor/gatekeeper/dist/lib/grants.js +314 -0
  125. package/vendor/gatekeeper/dist/lib/grants.js.map +1 -0
  126. package/vendor/gatekeeper/dist/lib/groups.d.ts +10 -0
  127. package/vendor/gatekeeper/dist/lib/groups.d.ts.map +1 -0
  128. package/vendor/gatekeeper/dist/lib/groups.js +247 -0
  129. package/vendor/gatekeeper/dist/lib/groups.js.map +1 -0
  130. package/vendor/gatekeeper/dist/lib/migration.d.ts +17 -0
  131. package/vendor/gatekeeper/dist/lib/migration.d.ts.map +1 -0
  132. package/vendor/gatekeeper/dist/lib/migration.js +79 -0
  133. package/vendor/gatekeeper/dist/lib/migration.js.map +1 -0
  134. package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0001_groups.sql +7 -0
  135. package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0002_access_grants.sql +14 -0
  136. package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0003_access_request_log.sql +9 -0
  137. package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +7 -0
  138. package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +14 -0
  139. package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +9 -0
  140. package/vendor/gatekeeper/dist/lib/state-db.d.ts +16 -0
  141. package/vendor/gatekeeper/dist/lib/state-db.d.ts.map +1 -0
  142. package/vendor/gatekeeper/dist/lib/state-db.js +154 -0
  143. package/vendor/gatekeeper/dist/lib/state-db.js.map +1 -0
  144. package/vendor/gatekeeper/dist/lib/templates.d.ts +21 -0
  145. package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -0
  146. package/vendor/gatekeeper/dist/lib/templates.js +151 -0
  147. package/vendor/gatekeeper/dist/lib/templates.js.map +1 -0
  148. package/vendor/gatekeeper/dist/lib/types.d.ts +178 -0
  149. package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -0
  150. package/vendor/gatekeeper/dist/lib/types.js +2 -0
  151. package/vendor/gatekeeper/dist/lib/types.js.map +1 -0
  152. package/vendor/gatekeeper/dist/server/index.d.ts +15 -0
  153. package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -0
  154. package/vendor/gatekeeper/dist/server/index.js +251 -0
  155. package/vendor/gatekeeper/dist/server/index.js.map +1 -0
  156. package/vendor/gatekeeper/dist/server/routes/access-request.d.ts +7 -0
  157. package/vendor/gatekeeper/dist/server/routes/access-request.d.ts.map +1 -0
  158. package/vendor/gatekeeper/dist/server/routes/access-request.js +17 -0
  159. package/vendor/gatekeeper/dist/server/routes/access-request.js.map +1 -0
  160. package/vendor/gatekeeper/dist/server/routes/authz.d.ts +3 -0
  161. package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -0
  162. package/vendor/gatekeeper/dist/server/routes/authz.js +279 -0
  163. package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -0
  164. package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts +13 -0
  165. package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -0
  166. package/vendor/gatekeeper/dist/server/routes/diagnostic.js +249 -0
  167. package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -0
  168. package/vendor/gatekeeper/dist/server/routes/grants.d.ts +3 -0
  169. package/vendor/gatekeeper/dist/server/routes/grants.d.ts.map +1 -0
  170. package/vendor/gatekeeper/dist/server/routes/grants.js +112 -0
  171. package/vendor/gatekeeper/dist/server/routes/grants.js.map +1 -0
  172. package/vendor/gatekeeper/dist/server/routes/groups.d.ts +3 -0
  173. package/vendor/gatekeeper/dist/server/routes/groups.d.ts.map +1 -0
  174. package/vendor/gatekeeper/dist/server/routes/groups.js +139 -0
  175. package/vendor/gatekeeper/dist/server/routes/groups.js.map +1 -0
  176. package/vendor/gatekeeper/package.json +49 -0
  177. package/vendor/server/bin/lamaste-server.js +204 -0
  178. package/vendor/server/package.json +31 -0
  179. package/vendor/server/src/commands/certs.js +224 -0
  180. package/vendor/server/src/commands/chisel.js +132 -0
  181. package/vendor/server/src/commands/logs.js +49 -0
  182. package/vendor/server/src/commands/plugins.js +321 -0
  183. package/vendor/server/src/commands/reset-admin.js +478 -0
  184. package/vendor/server/src/commands/restart.js +94 -0
  185. package/vendor/server/src/commands/sites.js +257 -0
  186. package/vendor/server/src/commands/status.js +158 -0
  187. package/vendor/server/src/commands/tunnels.js +365 -0
  188. package/vendor/server/src/commands/uninstall.js +326 -0
  189. package/vendor/server/src/config.js +38 -0
  190. package/vendor/server/src/exec.js +26 -0
  191. package/vendor/server/src/logger.js +39 -0
  192. package/vendor/server/src/ndjson.js +56 -0
  193. package/vendor/server/src/panel-api.js +85 -0
  194. package/vendor/server/src/state.js +45 -0
  195. package/vendor/server-ui/dist/assets/index-B0nWuUyL.js +257 -0
  196. package/vendor/server-ui/dist/assets/index-BqWWFlTU.css +1 -0
  197. package/vendor/server-ui/dist/index.html +13 -0
  198. package/vendor/serverd/package.json +44 -0
  199. package/vendor/serverd/src/boot.js +13 -0
  200. package/vendor/serverd/src/index.js +191 -0
  201. package/vendor/serverd/src/lib/app-error.js +14 -0
  202. package/vendor/serverd/src/lib/authelia.js +85 -0
  203. package/vendor/serverd/src/lib/certbot.js +74 -0
  204. package/vendor/serverd/src/lib/chisel-args.js +6 -0
  205. package/vendor/serverd/src/lib/chisel-reconcile.js +232 -0
  206. package/vendor/serverd/src/lib/chisel-runtime.js +46 -0
  207. package/vendor/serverd/src/lib/chisel-users.js +109 -0
  208. package/vendor/serverd/src/lib/chisel.js +81 -0
  209. package/vendor/serverd/src/lib/config.js +190 -0
  210. package/vendor/serverd/src/lib/constants.js +8 -0
  211. package/vendor/serverd/src/lib/csr-signing.js +331 -0
  212. package/vendor/serverd/src/lib/enrollment.js +302 -0
  213. package/vendor/serverd/src/lib/files.js +19 -0
  214. package/vendor/serverd/src/lib/gatekeeper-client.js +135 -0
  215. package/vendor/serverd/src/lib/invite-page.js +281 -0
  216. package/vendor/serverd/src/lib/ip-utils.js +79 -0
  217. package/vendor/serverd/src/lib/migrations/state/0001_enrollment_tokens.sql +17 -0
  218. package/vendor/serverd/src/lib/migrations/state/0002_tickets.sql +70 -0
  219. package/vendor/serverd/src/lib/migrations/state/0003_plugins.sql +15 -0
  220. package/vendor/serverd/src/lib/migrations/state/0004_agents.sql +19 -0
  221. package/vendor/serverd/src/lib/mtls.js +795 -0
  222. package/vendor/serverd/src/lib/nginx.js +1090 -0
  223. package/vendor/serverd/src/lib/pki-paths.js +41 -0
  224. package/vendor/serverd/src/lib/pki-sign.js +103 -0
  225. package/vendor/serverd/src/lib/plugins.js +538 -0
  226. package/vendor/serverd/src/lib/push-install.js +390 -0
  227. package/vendor/serverd/src/lib/revocation.js +112 -0
  228. package/vendor/serverd/src/lib/services.js +131 -0
  229. package/vendor/serverd/src/lib/session.js +151 -0
  230. package/vendor/serverd/src/lib/state-db.js +130 -0
  231. package/vendor/serverd/src/lib/state.js +140 -0
  232. package/vendor/serverd/src/lib/storage.js +63 -0
  233. package/vendor/serverd/src/lib/system-stats.js +58 -0
  234. package/vendor/serverd/src/lib/tickets.js +1556 -0
  235. package/vendor/serverd/src/lib/totp.js +76 -0
  236. package/vendor/serverd/src/lib/tunnel-deps.js +41 -0
  237. package/vendor/serverd/src/lib/user-access-session.js +142 -0
  238. package/vendor/serverd/src/lib/user-access.js +52 -0
  239. package/vendor/serverd/src/middleware/errors.js +63 -0
  240. package/vendor/serverd/src/middleware/mtls.js +120 -0
  241. package/vendor/serverd/src/middleware/onboarding-guard.js +30 -0
  242. package/vendor/serverd/src/middleware/role-guard.js +58 -0
  243. package/vendor/serverd/src/middleware/twofa-session.js +65 -0
  244. package/vendor/serverd/src/middleware/user-access-session.js +52 -0
  245. package/vendor/serverd/src/routes/enrollment.js +120 -0
  246. package/vendor/serverd/src/routes/health.js +22 -0
  247. package/vendor/serverd/src/routes/invite.js +163 -0
  248. package/vendor/serverd/src/routes/management/agents.js +182 -0
  249. package/vendor/serverd/src/routes/management/certs.js +911 -0
  250. package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +160 -0
  251. package/vendor/serverd/src/routes/management/identity.js +107 -0
  252. package/vendor/serverd/src/routes/management/invitations.js +166 -0
  253. package/vendor/serverd/src/routes/management/logs.js +218 -0
  254. package/vendor/serverd/src/routes/management/plugins.js +560 -0
  255. package/vendor/serverd/src/routes/management/services.js +63 -0
  256. package/vendor/serverd/src/routes/management/settings.js +325 -0
  257. package/vendor/serverd/src/routes/management/sites.js +522 -0
  258. package/vendor/serverd/src/routes/management/storage.js +192 -0
  259. package/vendor/serverd/src/routes/management/system.js +201 -0
  260. package/vendor/serverd/src/routes/management/tickets.js +457 -0
  261. package/vendor/serverd/src/routes/management/tunnels.js +709 -0
  262. package/vendor/serverd/src/routes/management/users.js +377 -0
  263. package/vendor/serverd/src/routes/management.js +36 -0
  264. package/vendor/serverd/src/routes/onboarding/dns.js +101 -0
  265. package/vendor/serverd/src/routes/onboarding/domain.js +42 -0
  266. package/vendor/serverd/src/routes/onboarding/index.js +18 -0
  267. package/vendor/serverd/src/routes/onboarding/provision.js +327 -0
  268. package/vendor/serverd/src/routes/onboarding/status.js +12 -0
  269. package/vendor/serverd/src/routes/plugin-router.js +79 -0
  270. package/vendor/serverd/src/routes/user-access.js +389 -0
@@ -0,0 +1,447 @@
1
+ # How It Works
2
+
3
+ > Lamaste connects your local web apps to the internet through a cheap VPS relay, using encrypted WebSocket tunnels, with a browser-based admin panel you never need SSH to manage.
4
+
5
+ ## In Plain English
6
+
7
+ Picture a building with a locked front door and no doorbell. People outside cannot get in to visit you. That is your home network — your router blocks all incoming connections for security.
8
+
9
+ Now imagine you rent a tiny storefront on a busy street. You dig a private underground passage from your building to the storefront. When a visitor walks into the storefront, an attendant escorts them through the passage to your building and back again. The visitor never knows they went underground — they just see your building's interior.
10
+
11
+ That is Lamaste in a nutshell:
12
+
13
+ - **Your building** is your machine — a Mac or Linux box — running web apps behind a firewall.
14
+ - **The storefront** is a $4/month DigitalOcean droplet with a public IP address.
15
+ - **The underground passage** is an encrypted WebSocket tunnel (powered by Chisel).
16
+ - **The attendant** is nginx, routing visitors to the right app.
17
+ - **The locked front office** is the admin panel, where only people with a special key card (client certificate) can enter and manage everything.
18
+
19
+ The most unusual part: after you set up the storefront (a single command over SSH), you throw away the SSH key. You never go back through that door. All future management — adding new passages, changing locks, checking security cameras — happens through the front office using your key card.
20
+
21
+ ### Why not just deploy to the cloud?
22
+
23
+ You could rent a bigger server and deploy your apps there. But that means:
24
+
25
+ - Paying for compute (your machine is already sitting there, powered on)
26
+ - Managing deployments, Docker, CI/CD pipelines
27
+ - Migrating databases, file storage, environment configs
28
+ - Losing access to local hardware (GPUs, attached drives, local network devices)
29
+
30
+ Lamaste keeps your apps at home and only relays the HTTP traffic. The VPS does almost no work — it just forwards bytes. That is why a $4 droplet with 512MB RAM is enough.
31
+
32
+ ### Why not use ngrok or Cloudflare Tunnel?
33
+
34
+ Those are great tools. Lamaste differs in a few ways:
35
+
36
+ - **Self-hosted**: You own the relay. No third-party sees your traffic.
37
+ - **Your domain**: Traffic goes through your own domain, not a vendor subdomain.
38
+ - **Your auth**: You control user accounts and 2FA, not a vendor dashboard.
39
+ - **Fixed cost**: $4/month for unlimited tunnels, not per-seat or per-tunnel pricing.
40
+ - **No vendor lock-in**: It is open source. The droplet is yours.
41
+
42
+ ## For Users
43
+
44
+ ### The Big Picture
45
+
46
+ Lamaste has three phases of life: installation, onboarding, and daily operation.
47
+
48
+ **Phase 1: Installation (5 minutes)**
49
+
50
+ There are two ways to get a Lamaste server running:
51
+
52
+ **Option A: SSH (manual)**
53
+
54
+ SSH into a fresh Ubuntu droplet and run one command:
55
+
56
+ ```bash
57
+ apt install -y npm
58
+ npx @lamalibre/create-lamaste@4.0.0
59
+ ```
60
+
61
+ This installs everything the relay needs: nginx, Node.js, firewall rules, certificates, and the management panel. At the end, it prints a client certificate file and password. You download the certificate, import it into your browser, and disconnect SSH. You never SSH in again.
62
+
63
+ **Option B: Desktop app (cloud provisioning)**
64
+
65
+ Install the desktop app (`npx @lamalibre/create-lamaste-desktop@4.0.0`) and use the Servers tab to create a DigitalOcean droplet. The app handles everything — droplet creation, Lamaste installation, certificate download, and connection — without you ever touching SSH. Cloud API tokens are stored in your OS credential store (macOS Keychain or Linux libsecret), never in plaintext. See the [Cloud Provisioning guide](../02-guides/cloud-provisioning.md) for a step-by-step walkthrough.
66
+
67
+ **Phase 2: Onboarding (10 minutes, browser)**
68
+
69
+ You open `https://<droplet-ip>:9292` in your browser. Because you imported the client certificate, the browser proves your identity at the TLS level — no username/password needed.
70
+
71
+ The onboarding wizard walks you through:
72
+
73
+ 1. Enter your domain name and email address
74
+ 2. Point your DNS records to the droplet's IP
75
+ 3. Click "Provision" — Lamaste installs Chisel (tunnel server), Authelia (2FA), and configures nginx with Let's Encrypt certificates
76
+
77
+ **Phase 3: Daily operation (browser)**
78
+
79
+ After onboarding, the same URL shows the management panel:
80
+
81
+ - **Dashboard**: System stats, service health, resource usage
82
+ - **Tunnels**: Create, edit, move, delete tunnels. Each tunnel is carried by one enrolled agent.
83
+ - **Users**: Add people who can access your tunneled apps (each gets TOTP 2FA)
84
+ - **Certificates**: Monitor Let's Encrypt expiry, rotate mTLS certificates
85
+ - **Services**: Start, stop, restart Chisel/Authelia/nginx. View live logs.
86
+
87
+ ### Data Flow: How a Request Reaches Your App
88
+
89
+ When someone visits `https://myapp.example.com`:
90
+
91
+ ```
92
+ 1. Browser sends HTTPS request
93
+ ↓
94
+ 2. DNS resolves example.com → 203.0.113.42 (your droplet)
95
+ ↓
96
+ 3. nginx on the droplet receives the request
97
+ ↓
98
+ 4. nginx checks: does this visitor have a valid 2FA session?
99
+ ├─ No → Authelia login page (username + TOTP code)
100
+ └─ Yes → continue
101
+ ↓
102
+ 5. nginx forwards the request to Chisel server (port 9090)
103
+ ↓
104
+ 6. Chisel server sends it through the WebSocket tunnel
105
+ ↓
106
+ 7. Chisel client on your machine receives the request
107
+ ↓
108
+ 8. Chisel client forwards it to localhost:8001 (your app)
109
+ ↓
110
+ 9. Your app responds
111
+ ↓
112
+ 10. Response travels back: app → Chisel client → tunnel → Chisel server → nginx → browser
113
+ ```
114
+
115
+ The entire round trip is encrypted end-to-end. The tunnel itself runs inside a standard HTTPS connection (WebSocket upgrade), so it passes through corporate firewalls and ISP filters that block custom protocols.
116
+
117
+ ### The Admin Panel: A Different Security Model
118
+
119
+ The admin panel at `https://<ip>:9292` uses a completely different authentication mechanism than your tunneled apps:
120
+
121
+ | | Admin Panel | Tunneled Apps |
122
+ | ------------------------ | ----------------------------- | ------------------------- |
123
+ | **URL** | `https://<ip>:9292` | `https://app.example.com` |
124
+ | **Auth method** | mTLS client certificate | Username + TOTP 2FA |
125
+ | **Who accesses it** | You (the admin) | Your users |
126
+ | **Login required** | No — certificate is the login | Yes — Authelia login page |
127
+ | **Works without domain** | Yes (IP access always works) | No (needs DNS + domain) |
128
+
129
+ This split is deliberate. The admin panel works by IP address so you can always reach it, even if your domain's DNS breaks or your Let's Encrypt certificate expires. It uses client certificates so there is no login form to brute-force.
130
+
131
+ ### Component Map
132
+
133
+ Here is every piece of software running on the droplet after onboarding:
134
+
135
+ ```
136
+ ┌──────────────────────────────────────────────────────────────────┐
137
+ │ Ubuntu 24.04 Droplet (512MB RAM) │
138
+ │ │
139
+ │ ┌─────────────────────────────────────────────────────────────┐ │
140
+ │ │ nginx (public-facing, ports 443 + 9292) │ │
141
+ │ │ │ │
142
+ │ │ Port 9292 — Admin panel vhost (mTLS) │ │
143
+ │ │ └─ proxy_pass → Panel Server (127.0.0.1:3100) │ │
144
+ │ │ │ │
145
+ │ │ Port 443 — Tunnel vhosts (Let's Encrypt TLS) │ │
146
+ │ │ ├─ forward auth → Authelia (127.0.0.1:9091) │ │
147
+ │ │ └─ proxy_pass → Chisel Server (127.0.0.1:9090) │ │
148
+ │ └─────────────────────────────────────────────────────────────┘ │
149
+ │ │
150
+ │ ┌──────────────────┐ ┌──────────────┐ ┌───────────────────┐ │
151
+ │ │ Panel Server │ │ Authelia │ │ Chisel Server │ │
152
+ │ │ (Fastify, :3100) │ │ (TOTP, :9091) │ │ (tunnels, :9090) │ │
153
+ │ │ REST API + │ │ bcrypt users │ │ WebSocket-over- │ │
154
+ │ │ static files │ │ ~25MB RAM │ │ HTTPS │ │
155
+ │ └──────────────────┘ └──────────────┘ └───────────────────┘ │
156
+ │ │
157
+ │ ┌──────────────────┐ ┌──────────────┐ ┌───────────────────┐ │
158
+ │ │ UFW Firewall │ │ fail2ban │ │ certbot │ │
159
+ │ │ ports 22/443/ │ │ SSH + nginx │ │ auto-renewing │ │
160
+ │ │ 9292 only │ │ jails │ │ Let's Encrypt │ │
161
+ │ └──────────────────┘ └──────────────┘ └───────────────────┘ │
162
+ │ │
163
+ │ Total RAM: ~245MB Swap: 1GB safety net │
164
+ └──────────────────────────────────────────────────────────────────┘
165
+ ▲
166
+ │ WebSocket tunnel (encrypted, inside HTTPS)
167
+ │
168
+ ┌────────┴─────────────────────────────────────────────────────────┐
169
+ │ Agent: your Mac or Linux machine (behind firewall) │
170
+ │ │
171
+ │ ┌──────────────────┐ ┌──────────────────────────────────┐ │
172
+ │ │ Chisel Client │ │ Your Web Apps │ │
173
+ │ │ (launchd/systemd │──────→│ localhost:8001 (blog) │ │
174
+ │ │ auto-reconnect, │ │ localhost:3000 (dashboard) │ │
175
+ │ │ 30 s sync timer)│ │ localhost:5173 (dev server) │ │
176
+ │ └──────────────────┘ └──────────────────────────────────┘ │
177
+ │ ┌──────────────────────────────────────────────────────────────┐ │
178
+ │ │ Lamaste Desktop (Tauri v2) │ │
179
+ │ │ ├─ Service discovery + tunnel management │ │
180
+ │ │ ├─ Multi-server registry (~/.lamalibre/lamaste/servers.json) │ │
181
+ │ │ ├─ Cloud provisioning (DigitalOcean) │ │
182
+ │ │ └─ Credential storage (macOS Keychain / Linux libsecret) │ │
183
+ │ └──────────────────────────────────────────────────────────────┘ │
184
+ └──────────────────────────────────────────────────────────────────┘
185
+ ```
186
+
187
+ ### RAM Budget
188
+
189
+ Every component is chosen to fit within 512MB:
190
+
191
+ | Component | RAM Usage | Purpose |
192
+ | ------------------ | ---------- | ------------------------------ |
193
+ | Ubuntu OS baseline | ~120MB | Kernel, systemd, base services |
194
+ | nginx | ~15MB | Reverse proxy, TLS termination |
195
+ | Authelia | ~25MB | TOTP 2FA authentication |
196
+ | Chisel Server | ~20MB | WebSocket tunnel relay |
197
+ | Panel Server | ~30MB | Fastify REST API |
198
+ | fail2ban | ~35MB | Brute-force protection |
199
+ | **Total** | **~245MB** | **Headroom: ~265MB** |
200
+
201
+ A 1GB swap file provides a safety net. Authelia uses bcrypt (not argon2id) specifically because argon2id uses ~93MB per password hash and would cause out-of-memory kills on a 512MB droplet.
202
+
203
+ ## For Developers
204
+
205
+ ### Architecture Philosophy
206
+
207
+ Lamaste follows three core principles:
208
+
209
+ 1. **SSH is disposable.** The installer runs once over SSH and provisions everything. After that, SSH is only a fallback for disaster recovery. All day-to-day management happens through the browser-based panel, authenticated by mTLS client certificates.
210
+
211
+ 2. **nginx is the only public surface.** Every backend service binds to `127.0.0.1`. nginx is the sole process listening on public ports (443 and 9292). This minimizes the attack surface to a single, well-audited reverse proxy.
212
+
213
+ 3. **No database.** State is stored in JSON files (`panel.json`, `tunnels.json`) and YAML files (`users.yml` for Authelia). Writes use atomic rename (`write .tmp` then `rename`) to prevent corruption. At this scale, a database adds complexity without benefit.
214
+
215
+ ### Monorepo Structure
216
+
217
+ ```
218
+ lamaste/
219
+ ├── packages/
220
+ │ ├── create-lamaste/ ← npx installer (runs once on VPS)
221
+ │ │ └── src/
222
+ │ │ ├── index.js ← Listr2 orchestrator
223
+ │ │ ├── tasks/ ← harden, node, mtls, nginx, panel
224
+ │ │ └── lib/ ← secrets, summary, cert-help-page
225
+ │ │
226
+ │ ├── lamaste-serverd/ ← Fastify REST API (runs as systemd service)
227
+ │ │ └── src/
228
+ │ │ ├── index.js ← server entry
229
+ │ │ ├── middleware/ ← mTLS verification, onboarding guard
230
+ │ │ ├── routes/ ← onboarding/ + management/ endpoints
231
+ │ │ └── lib/ ← business logic (nginx, chisel, authelia, certbot)
232
+ │ │
233
+ │ └── lamaste-server-ui/ ← React SPA (served as static files)
234
+ │ └── src/
235
+ │ ├── App.jsx ← mode detection (onboarding vs management)
236
+ │ ├── pages/ ← onboarding wizard + management pages
237
+ │ └── components/ ← shared UI components
238
+ ```
239
+
240
+ ### Installer Pipeline
241
+
242
+ The installer (`create-lamaste`) runs as a Listr2 task pipeline:
243
+
244
+ ```
245
+ Phase 1: Environment Detection
246
+ ├── Verify root access
247
+ ├── Detect OS (must be Ubuntu 24.04)
248
+ └── Detect public IP address
249
+
250
+ Phase 2: Installation
251
+ ├── Harden OS
252
+ │ ├── Create 1GB swap file (swappiness=10)
253
+ │ ├── Configure UFW (allow 22, 443, 9292 only)
254
+ │ ├── Install and configure fail2ban
255
+ │ ├── Harden SSH (disable password auth)
256
+ │ └── Install system packages (nginx, certbot)
257
+ │
258
+ ├── Install Node.js 20 LTS
259
+ │
260
+ ├── Generate mTLS Certificates
261
+ │ ├── Create CA key + certificate (4096-bit RSA, 10-year validity)
262
+ │ ├── Create client key + CSR (4096-bit RSA)
263
+ │ ├── Sign client certificate with CA (2-year validity)
264
+ │ └── Create PKCS12 bundle (.p12) for browser import
265
+ │
266
+ ├── Configure nginx
267
+ │ ├── Generate self-signed TLS certificate for IP access
268
+ │ ├── Write mTLS snippet (ssl_verify_client on)
269
+ │ ├── Write IP-based panel vhost (port 9292)
270
+ │ ├── Enable site, remove default
271
+ │ ├── Port 80 catch-all: redirect plain HTTP to HTTPS
272
+ │ └── Validate config and start nginx
273
+ │
274
+ ├── Deploy Panel
275
+ │ ├── Create lamaste system user
276
+ │ ├── Create directory structure (/opt/lamalibre/lamaste root-owned, /etc/lamalibre/lamaste)
277
+ │ │ and deploy the certificate help page
278
+ │ ├── Install chisel + Authelia
279
+ │ │ ├── lamaste-chisel group (Chisel reads its authfile through it), lamaste-authelia account
280
+ │ │ ├── Pinned releases (Chisel 1.12.0, Authelia 4.39.28), SHA-256 verified
281
+ │ │ ├── Hardened systemd units (chisel.service, authelia.service)
282
+ │ │ └── Ownership: /var/www/lamaste (lamaste:www-data), /etc/authelia (lamaste:lamaste-authelia)
283
+ │ ├── Deploy lamalibre-lamaste-serverd, lamaste-server CLI, lamaste-server-ui, docs
284
+ │ ├── Write panel.json configuration
285
+ │ ├── Write systemd service unit (lamalibre-lamaste-serverd.service)
286
+ │ ├── Install root-owned sudo programs (lamaste-priv, lamaste-certbot, lamaste-cert-info)
287
+ │ ├── Write sudoers rules (fixed command lines, no wildcards; visudo-checked)
288
+ │ └── Start panel service + health check
289
+ └── Deploy Gatekeeper
290
+ ```
291
+
292
+ Every task is idempotent — re-running the installer updates the installation without losing existing configuration. Skip guards check for existing state (swap already exists, certificates already generated, etc.).
293
+
294
+ ### Onboarding Provisioning
295
+
296
+ After the installer runs, the panel is in `FRESH` state. The onboarding wizard (accessed via browser) provisions the remaining stack:
297
+
298
+ ```
299
+ Onboarding Wizard
300
+ ├── Domain Step: user enters domain + email
301
+ ├── DNS Step: panel shows required DNS records, user verifies
302
+ └── Provisioning Step: panel configures and starts the remaining components
303
+ ├── Check Chisel is installed, create its key + authfile, start it
304
+ ├── Check Authelia is installed, write its configuration + first admin user, start it
305
+ ├── Issue Let's Encrypt certificate via certbot
306
+ ├── Write domain-based nginx vhosts (through lamaste-priv)
307
+ ├── Verify all services
308
+ └── Update panel.json → onboarding status: COMPLETED
309
+ ```
310
+
311
+ After provisioning, onboarding endpoints return `410 Gone` and management endpoints become available.
312
+
313
+ ### Security Layers
314
+
315
+ ```
316
+ Layer 1: UFW Firewall
317
+ └─ Only ports 22 (SSH), 443 (HTTPS), 9292 (admin panel) are open
318
+
319
+ Layer 2: fail2ban
320
+ └─ Bans IPs after 5 failed SSH or nginx auth attempts (1 hour ban)
321
+
322
+ Layer 3: nginx TLS
323
+ └─ All traffic is HTTPS. Self-signed cert for IP:9292, Let's Encrypt for domain.
324
+
325
+ Layer 4a: mTLS (admin panel)
326
+ └─ ssl_verify_client on — no certificate = TLS handshake rejected before HTTP
327
+
328
+ Layer 4b: Authelia (tunneled apps)
329
+ └─ Forward auth — username + TOTP 2FA required for every tunneled app
330
+
331
+ Layer 5: Localhost binding
332
+ └─ Panel server, Authelia, Chisel all bind 127.0.0.1 — unreachable from outside
333
+
334
+ Layer 6: Systemd hardening
335
+ └─ NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp
336
+
337
+ Layer 7: Privilege boundary
338
+ └─ lamaste user can only run fixed commands (nginx -t, systemctl for known services)
339
+ and validating root-owned programs (lamaste-priv, lamaste-certbot, lamaste-cert-info);
340
+ no sudoers wildcards. Authelia runs as its own account; code is root-owned
341
+ ```
342
+
343
+ ### Key File Locations on the Droplet
344
+
345
+ | Path | Purpose |
346
+ | ------------------------------------------------------- | -------------------------------------------------- |
347
+ | `/etc/lamalibre/lamaste/panel.json` | Main configuration (IP, domain, onboarding status) |
348
+ | `/etc/lamalibre/lamaste/tunnels.json` | Tunnel definitions |
349
+ | `/etc/lamalibre/lamaste/pki/` | CA cert/key, client cert/key, self-signed cert |
350
+ | `/etc/lamalibre/lamaste/pki/client.p12` | PKCS12 bundle for browser import |
351
+ | `/opt/lamalibre/lamaste/lamaste-serverd/` | Fastify backend (Node.js) |
352
+ | `/opt/lamalibre/lamaste/lamaste-server-ui/dist/` | Built React SPA (static files) |
353
+ | `/var/www/lamaste/` | Static site files served through tunnels |
354
+ | `/etc/nginx/sites-available/lamaste-*` | nginx vhost configurations |
355
+ | `/etc/nginx/snippets/lamalibre-lamaste-mtls.conf` | mTLS client certificate requirement |
356
+ | `/etc/systemd/system/lamalibre-lamaste-serverd.service` | Panel server systemd unit |
357
+ | `/etc/sudoers.d/lamaste` | Fixed sudo rules (no wildcards) |
358
+ | `/etc/fail2ban/jail.d/lamaste.conf` | fail2ban jail configuration |
359
+
360
+ ### State Machine
361
+
362
+ The panel operates in distinct states:
363
+
364
+ ```
365
+ FRESH ──────→ DOMAIN_SET ──────→ DNS_READY ──────→ PROVISIONING ──────→ COMPLETED
366
+ │ │ │ │ │
367
+ │ Onboarding │ Onboarding │ Onboarding │ Onboarding │ Management
368
+ │ endpoints │ endpoints │ endpoints │ endpoints │ endpoints
369
+ │ active │ active │ active │ active │ active
370
+ │ │ │ │ │
371
+ │ Management │ Management │ Management │ Management │ Onboarding
372
+ │ returns 503 │ returns 503 │ returns 503 │ returns 503 │ returns 410
373
+ ```
374
+
375
+ ### Technology Choices Explained
376
+
377
+ | Choice | Why | Alternatives Considered |
378
+ | ----------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------- |
379
+ | Chisel for tunnels | Single Go binary, WebSocket-over-HTTPS (bypasses DPI), ~20MB RAM | frp (heavier), bore (less mature), SSH tunnels (fragile) |
380
+ | Authelia for 2FA | Single Go binary, TOTP support, ~25MB RAM, file-based user store | Keycloak (too heavy), custom auth (security risk) |
381
+ | nginx for reverse proxy | Battle-tested, mTLS support, forward auth, low RAM | Caddy (no mTLS vhost control), Traefik (higher RAM) |
382
+ | Fastify for API | Fast, schema-first validation, native WebSocket, ESM | Express (slower, less structured), Hono (less ecosystem) |
383
+ | JSON files for state | Simple, no database process, atomic writes | SQLite (adds dependency), PostgreSQL (way too heavy) |
384
+ | bcrypt for passwords | Low memory (~4KB per hash) | argon2id (~93MB per hash, causes OOM on 512MB) |
385
+ | Client certificates for admin | Zero-login, unforgeable, works at TLS layer | Session cookies (brute-forceable), API keys (leakable) |
386
+
387
+ ## Quick Reference
388
+
389
+ ### Ports
390
+
391
+ | Port | Service | Access |
392
+ | ---- | ---------------------- | ------------------------------------------- |
393
+ | 22 | SSH | Public (key-only, fail2ban protected) |
394
+ | 443 | nginx (tunnel vhosts) | Public (Let's Encrypt TLS + Authelia 2FA) |
395
+ | 9292 | nginx (admin panel) | Public (self-signed TLS + mTLS client cert) |
396
+ | 3100 | Panel Server (Fastify) | Localhost only |
397
+ | 9090 | Chisel Server | Localhost only |
398
+ | 9091 | Authelia | Localhost only |
399
+
400
+ ### Services
401
+
402
+ | systemd Unit | Binary | Purpose |
403
+ | --------------------------- | -------------------------- | --------------------------------- |
404
+ | `lamalibre-lamaste-serverd` | `node src/index.js` | REST API + static file server |
405
+ | `nginx` | `/usr/sbin/nginx` | Reverse proxy, TLS, mTLS |
406
+ | `chisel` | `/usr/local/bin/chisel` | WebSocket tunnel server |
407
+ | `authelia` | `/usr/local/bin/authelia` | TOTP 2FA authentication |
408
+ | `fail2ban` | `/usr/bin/fail2ban-server` | Brute-force protection |
409
+ | `certbot.timer` | `/usr/bin/certbot` | Auto-renewing Let's Encrypt certs |
410
+
411
+ ### Data Flow Summary
412
+
413
+ ```
414
+ Browser → DNS → nginx:443 → Authelia check → Chisel server → tunnel → Chisel client → local app
415
+ Admin → nginx:9292 → mTLS check → Panel server:3100
416
+ ```
417
+
418
+ ### Key Commands (on the droplet)
419
+
420
+ ```bash
421
+ # Service management
422
+ systemctl status lamalibre-lamaste-serverd
423
+ systemctl restart chisel
424
+ journalctl -u lamalibre-lamaste-serverd -f # live logs
425
+
426
+ # nginx
427
+ nginx -t # validate config
428
+ systemctl reload nginx # apply vhost changes
429
+
430
+ # Certificates
431
+ certbot certificates # list Let's Encrypt certs
432
+ certbot renew # force renewal check
433
+
434
+ # Firewall
435
+ ufw status # show open ports
436
+ fail2ban-client status # show active jails
437
+ ```
438
+
439
+ ### Related Documentation
440
+
441
+ - [What is Lamaste?](./what-is-lamaste.md) — overview and use cases
442
+ - [Quick Start](./quickstart.md) — from zero to first tunnel in 10 minutes
443
+ - [Tunneling](../01-concepts/tunneling.md) — deep dive on Chisel and WebSocket tunnels
444
+ - [mTLS](../01-concepts/mtls.md) — how client certificate authentication works
445
+ - [Authentication](../01-concepts/authentication.md) — Authelia and TOTP 2FA
446
+ - [Security Model](../01-concepts/security-model.md) — defense-in-depth architecture
447
+ - [Glossary](../06-reference/glossary.md) — A-Z term definitions