@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,364 @@
1
+ # Static Sites
2
+
3
+ > Host static websites, landing pages, and single-page applications through Lamaste without a tunnel.
4
+
5
+ ## In Plain English
6
+
7
+ Not everything needs a tunnel. If you have a static website — a marketing page, a blog built with a static site generator, or a single-page application — you can host it directly on your Lamaste server. Upload your files through the panel, and they are served via nginx with a Let's Encrypt certificate. No local machine needed, no Chisel client required.
8
+
9
+ Static sites come in two flavors: **managed subdomains** (like `blog.example.com`) where Lamaste handles everything, and **custom domains** (like `myblog.com`) where you bring your own domain and point it at the server.
10
+
11
+ ## Prerequisites
12
+
13
+ - A completed [Lamaste onboarding](onboarding.md)
14
+ - Access to the Lamaste admin panel
15
+ - Static files to upload (HTML, CSS, JS, images, etc.)
16
+ - For custom domains: access to DNS management for the custom domain
17
+
18
+ ## Step-by-Step
19
+
20
+ ### 1. Open the Sites Page
21
+
22
+ Log in to the Lamaste admin panel at `https://panel.example.com` (or `https://<ip>:9292`).
23
+
24
+ Click **Sites** in the sidebar navigation (if available) or navigate to the Sites section.
25
+
26
+ ### 2. Create a Managed Subdomain Site
27
+
28
+ A managed subdomain site uses your Lamaste domain (e.g., `blog.example.com`). Certificate issuance, DNS, and nginx configuration are handled automatically.
29
+
30
+ 1. Click **Add Site**.
31
+ 2. Select **Managed Subdomain** as the domain type.
32
+ 3. Enter a name (this becomes the subdomain):
33
+
34
+ | Field | Rules | Example |
35
+ | -------- | -------------------------------------------------- | ------- |
36
+ | **Name** | Lowercase alphanumeric with hyphens, max 100 chars | `blog` |
37
+
38
+ The name must not conflict with existing tunnels or reserved subdomains (`panel`, `auth`, `tunnel`, `www`, `mail`, `ftp`, `api`).
39
+
40
+ 4. Configure options:
41
+
42
+ | Option | Default | Description |
43
+ | ---------------------- | ------- | ------------------------------------------------------------------------------------ |
44
+ | **SPA Mode** | Off | If enabled, all non-file requests return `index.html` (for React, Vue, Angular apps) |
45
+ | **Authelia Protected** | Off | If enabled, visitors must log in through Authelia before accessing the site |
46
+
47
+ 5. Click **Create Site**.
48
+
49
+ **What happens:**
50
+
51
+ 1. A Let's Encrypt certificate is issued for `blog.example.com`.
52
+ 2. An nginx vhost is written to serve static files from `/var/www/lamaste/<site-id>/`.
53
+ 3. The site directory is created.
54
+ 4. The site record is saved to `/etc/lamalibre/lamaste/sites.json`.
55
+
56
+ The site appears in the list with a "Live" status badge. It is ready for file uploads.
57
+
58
+ ### 3. Create a Custom Domain Site
59
+
60
+ A custom domain site uses a domain you own (e.g., `myblog.com`). You must configure DNS before the site goes live.
61
+
62
+ 1. Click **Add Site**.
63
+ 2. Select **Custom Domain** as the domain type.
64
+ 3. Enter a name and the custom domain:
65
+
66
+ | Field | Example |
67
+ | ------------------------------- | ---------------- |
68
+ | **Name** | `myblog` |
69
+ | **Custom Domain** | `myblog.com` |
70
+ | **Redirect aliases** (optional) | `www.myblog.com` |
71
+
72
+ 4. Optionally list **redirect aliases** — other hostnames (typically `www.<domain>`) that should answer with a permanent (301) redirect to the custom domain. Separate several with commas or spaces; up to 10.
73
+ 5. Configure SPA Mode and Authelia Protection as needed.
74
+ 6. Click **Create Site**.
75
+
76
+ The site is created with a "DNS Pending" status. No certificate is issued yet because Let's Encrypt needs the domain to resolve to your server first.
77
+
78
+ ### 4. Verify DNS for a Custom Domain
79
+
80
+ 1. Add an A record at your domain registrar for the domain **and every alias**:
81
+
82
+ | Type | Name | Value |
83
+ | ----- | ------------------------ | ------------------------------------- |
84
+ | **A** | `myblog.com` (or `@`) | Your server IP (e.g., `203.0.113.42`) |
85
+ | **A** | `www.myblog.com` (alias) | Your server IP (e.g., `203.0.113.42`) |
86
+
87
+ 2. Wait for DNS propagation (usually a few minutes).
88
+ 3. In the Lamaste panel, click **Verify DNS** next to the site.
89
+ 4. The panel checks that the domain and every alias resolve to your server — one certificate covers them all, so every name must pass Let's Encrypt's HTTP challenge.
90
+
91
+ **If DNS is verified:**
92
+
93
+ - One Let's Encrypt certificate, named after the domain, is issued for the domain and all its aliases.
94
+ - An nginx vhost is configured; aliases redirect (301) to `https://myblog.com`.
95
+ - The site status changes to "Live".
96
+
97
+ ### Change Aliases Later
98
+
99
+ Open **Settings** on a custom-domain site and edit **Redirect aliases**. On a live site the change takes effect immediately: every newly added alias must already resolve to your server (otherwise nothing changes and the panel says which names are missing), the certificate is first issued for the old and new names together (so the site stays valid while the switch happens), the vhost is rewritten, and then the certificate is re-issued for exactly the new names — so a later renewal never has to validate a name you removed, whose DNS may already point elsewhere. If that last re-issue fails, the new aliases are live anyway and the API response (`PATCH /api/sites/:id`) carries a `warning`: the certificate still names the removed aliases, and renewing it will fail once they stop resolving to your server. The next alias change retries it. On a site still awaiting DNS verification the list is simply saved, and **Verify DNS** checks every name.
100
+
101
+ An alias cannot be a Lamaste hostname (`panel.`, `auth.`, `tunnel.`, or the base domain), the site's own domain, or a name another site or a tunnel already serves. Managed-subdomain sites do not take aliases.
102
+
103
+ **If DNS is not verified:**
104
+
105
+ - The panel shows the current resolution and expected IP.
106
+ - Wait longer and try again.
107
+
108
+ ### 5. Upload Files
109
+
110
+ After creating a site (whether managed or custom with verified DNS), upload your static files:
111
+
112
+ 1. Click the **Files** button next to the site.
113
+ 2. The file browser opens, showing the site's root directory.
114
+ 3. Click **Upload** to select and upload files.
115
+ 4. Files are uploaded to the site directory and served immediately.
116
+
117
+ **File upload details:**
118
+
119
+ - Files are uploaded via multipart form data to `POST /api/sites/:id/files`.
120
+ - The upload target directory can be specified with the `?path=` query parameter.
121
+ - Files are served directly by nginx — no Node.js involvement in serving static content.
122
+ - The site's total size is tracked and displayed.
123
+
124
+ **Directory structure example:**
125
+
126
+ For a typical static site, upload:
127
+
128
+ ```
129
+ index.html
130
+ styles.css
131
+ scripts.js
132
+ images/
133
+ logo.png
134
+ hero.jpg
135
+ ```
136
+
137
+ ### 6. Enable SPA Mode
138
+
139
+ If your site is a single-page application (React, Vue, Angular, Svelte, etc.), enable SPA mode:
140
+
141
+ 1. When creating the site, check the **SPA Mode** checkbox.
142
+ 2. Or edit the site configuration after creation.
143
+
144
+ With SPA mode enabled, nginx is configured with a `try_files` directive: any request that does not match a physical file is served `index.html`. This allows client-side routing to work correctly.
145
+
146
+ **Without SPA mode:** A request to `blog.example.com/about` looks for a file at `/about` or `/about/index.html`. If neither exists, nginx returns 404.
147
+
148
+ **With SPA mode:** A request to `blog.example.com/about` first checks for a file at `/about`. If no file exists, it serves `index.html`, and your JavaScript router handles the route.
149
+
150
+ ### 7. Enable Authelia Protection
151
+
152
+ If you want visitors to log in before accessing your static site:
153
+
154
+ 1. When creating the site, check the **Authelia Protected** checkbox.
155
+ 2. Or edit the site configuration after creation.
156
+
157
+ With Authelia protection enabled, nginx adds an `auth_request` directive. Every request is checked against Authelia before serving the file. Visitors are redirected to `auth.example.com` to log in with username, password, and TOTP code.
158
+
159
+ This is useful for internal documentation, staging sites, or any content you want to restrict to authenticated users.
160
+
161
+ ### 8. Manage Files
162
+
163
+ The file browser lets you:
164
+
165
+ - **Browse directories** — Navigate the file tree
166
+ - **Upload files** — Add new files to any directory
167
+ - **Delete files** — Remove individual files
168
+ - **View file sizes** — See the total site size
169
+
170
+ ### 9. Delete a Site
171
+
172
+ 1. Go to the **Sites** page.
173
+ 2. Click the **Delete** button next to the site.
174
+ 3. Confirm the deletion.
175
+
176
+ **What is removed:**
177
+
178
+ - The nginx vhost configuration
179
+ - All uploaded files in the site directory
180
+ - The site record from `sites.json`
181
+
182
+ The Let's Encrypt certificate is left in place (certbot manages its lifecycle).
183
+
184
+ ## For Developers
185
+
186
+ ### Site Data Model
187
+
188
+ Each site is stored in `/etc/lamalibre/lamaste/sites.json` as a JSON array:
189
+
190
+ ```json
191
+ [
192
+ {
193
+ "id": "550e8400-e29b-41d4-a716-446655440000",
194
+ "name": "blog",
195
+ "fqdn": "blog.example.com",
196
+ "type": "managed",
197
+ "spaMode": false,
198
+ "autheliaProtected": false,
199
+ "allowedUsers": [],
200
+ "dnsVerified": true,
201
+ "certIssued": true,
202
+ "rootPath": "/var/www/lamaste/550e8400-e29b-41d4-a716-446655440000",
203
+ "createdAt": "2024-01-15T10:30:00.000Z",
204
+ "totalSize": 245760
205
+ }
206
+ ]
207
+ ```
208
+
209
+ Custom-domain sites may also carry `"aliases": ["www.myblog.com"]` — present only when non-empty.
210
+
211
+ ### API Endpoints
212
+
213
+ | Method | Path | Purpose |
214
+ | -------- | --------------------------- | ------------------------------------------------------------------------ |
215
+ | `GET` | `/api/sites` | List all sites |
216
+ | `POST` | `/api/sites` | Create a new site |
217
+ | `PATCH` | `/api/sites/:id` | Update site settings (spaMode, autheliaProtected, allowedUsers, aliases) |
218
+ | `DELETE` | `/api/sites/:id` | Delete a site |
219
+ | `POST` | `/api/sites/:id/verify-dns` | Verify DNS for custom domain sites |
220
+ | `GET` | `/api/sites/:id/files` | List files in a directory |
221
+ | `POST` | `/api/sites/:id/files` | Upload files (multipart) |
222
+ | `DELETE` | `/api/sites/:id/files` | Delete a file |
223
+
224
+ ### Create Site Request
225
+
226
+ **Managed subdomain:**
227
+
228
+ ```json
229
+ POST /api/sites
230
+ {
231
+ "name": "blog",
232
+ "type": "managed",
233
+ "spaMode": false,
234
+ "autheliaProtected": false
235
+ }
236
+ ```
237
+
238
+ **Custom domain:**
239
+
240
+ ```json
241
+ POST /api/sites
242
+ {
243
+ "name": "myblog",
244
+ "type": "custom",
245
+ "customDomain": "myblog.com",
246
+ "aliases": ["www.myblog.com"],
247
+ "spaMode": true,
248
+ "autheliaProtected": false
249
+ }
250
+ ```
251
+
252
+ ### Validation Rules
253
+
254
+ | Field | Rules |
255
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
256
+ | `name` | 1-100 chars, regex `^[a-z0-9]([a-z0-9-]*[a-z0-9])?$`, unique across sites, not reserved, not colliding with tunnels |
257
+ | `type` | `managed` or `custom` |
258
+ | `customDomain` | Required for `custom` type, max 253 chars, valid domain format |
259
+ | `aliases` | Custom sites only, at most 10 hostnames; not the site's domain, not a Lamaste hostname, not served by another site or tunnel |
260
+ | `spaMode` | Boolean, defaults to `false` |
261
+ | `autheliaProtected` | Boolean, defaults to `false` |
262
+ | `allowedUsers` | Array of strings (Authelia usernames), defaults to `[]` |
263
+
264
+ ### File Storage
265
+
266
+ Static files are stored under `/var/www/lamaste/<site-id>/` and served directly by nginx. The web root belongs to the panel's user with nginx's group: `lamaste:www-data`, directories `2750` (setgid, so everything created inside inherits the `www-data` group) and files `0640`. nginx reads through the group; no other user can read the files.
267
+
268
+ The panel therefore manages site files itself, without sudo: it creates site directories, writes uploads to a temporary file next to their destination and renames them into place (mode `0640`), lists and sizes directories with `readdir`/`lstat` (symbolic links are neither listed nor followed), and deletes with `rm`. The installer sets up this ownership, and converts a web root left `www-data`-owned by an earlier version on the next redeploy.
269
+
270
+ Path validation prevents directory traversal attacks. The `validatePath()` function rejects paths containing `..`, absolute paths, and paths outside the site root.
271
+
272
+ ### Managed vs. Custom Domain Flow
273
+
274
+ **Managed subdomain:**
275
+
276
+ ```
277
+ Create → Issue cert → Write vhost → Create dir → Save state → Live
278
+ ```
279
+
280
+ Everything happens in one request. The site is immediately live after creation (assuming wildcard DNS is configured, or the subdomain has its own A record).
281
+
282
+ **Custom domain:**
283
+
284
+ ```
285
+ Create → Create dir → Save state → DNS Pending
286
+ ↓
287
+ Verify DNS (domain + every alias) → Issue one cert for all names → Write vhost (+ alias 301 block) → Save state → Live
288
+ ```
289
+
290
+ The site is created in a pending state. DNS verification is a separate step that triggers certificate issuance and vhost creation.
291
+
292
+ ### nginx Vhost Features
293
+
294
+ Each static site vhost includes:
295
+
296
+ - TLS termination with Let's Encrypt certificate
297
+ - Optional `try_files $uri $uri/ /index.html` for SPA mode
298
+ - Optional Authelia `auth_request` for protected sites
299
+ - For custom sites with aliases, a second server block on the same certificate returning `301 https://<domain>$request_uri`
300
+ - Standard security headers
301
+ - Gzip compression for text-based assets
302
+
303
+ ## CLI Deployment
304
+
305
+ As an alternative to the browser-based file management described above, you can manage static sites and deploy files directly from the command line using the Lamaste agent CLI.
306
+
307
+ ### Prerequisites
308
+
309
+ - The Lamaste agent CLI installed on your machine (see [Agent Setup](agent-setup.md))
310
+ - An agent certificate with `sites:read` and `sites:write` capabilities. Generate one from the panel: **Certificates** > **Agent Certificates** > **Generate**, and check the `sites:read` and `sites:write` capability boxes.
311
+ - The agent certificate must have the target site listed in its **Site Access** configuration. The admin assigns sites to agents from **Panel** > **Certificates** > edit agent > **Site Access**.
312
+
313
+ ### Workflow
314
+
315
+ Site creation and deletion are admin-only operations. The admin creates the site through the panel or admin certificate, then assigns it to the agent. The agent can then deploy files to the site.
316
+
317
+ ```bash
318
+ # Admin creates the site through the panel UI first, then:
319
+
320
+ # Build your app and deploy (agent cert must have the site in its allowedSites)
321
+ npm run build
322
+ lamaste-agent deploy blog ./dist
323
+ ```
324
+
325
+ The `deploy` command clears all existing files on the site and uploads all non-hidden files from the specified local directory. It is a full replacement, not a merge. Every deploy is a clean slate.
326
+
327
+ You can also list sites assigned to your agent from the CLI:
328
+
329
+ ```bash
330
+ # List sites assigned to this agent
331
+ lamaste-agent sites
332
+ ```
333
+
334
+ For the full list of flags and options, see the [agent CLI README](https://github.com/lamalibre/lamaste/tree/main/packages/lamaste-agent).
335
+
336
+ ## Quick Reference
337
+
338
+ | Feature | Managed Subdomain | Custom Domain |
339
+ | -------------- | -------------------- | ----------------------- |
340
+ | DNS setup | Automatic (wildcard) | Manual (A record) |
341
+ | Certificate | Automatic | After DNS verification |
342
+ | Goes live | Immediately | After DNS + cert |
343
+ | Example domain | `blog.example.com` | `myblog.com` |
344
+ | Aliases | Not supported | Optional, 301 to domain |
345
+
346
+ | Action | Steps |
347
+ | ----------------------- | ---------------------------------------------------- |
348
+ | **Create managed site** | Add Site, Managed Subdomain, enter name, Create |
349
+ | **Create custom site** | Add Site, Custom Domain, enter name + domain, Create |
350
+ | **Verify DNS** | Click "Verify DNS" next to pending site |
351
+ | **Upload files** | Click "Files", then "Upload" |
352
+ | **Enable SPA mode** | Check "SPA Mode" when creating |
353
+ | **Enable auth** | Check "Authelia Protected" when creating |
354
+ | **Delete site** | Click "Delete", confirm |
355
+
356
+ | Reserved Names | Cannot Use As Site Name |
357
+ | -------------- | ----------------------- |
358
+ | `panel` | Admin panel subdomain |
359
+ | `auth` | Authelia subdomain |
360
+ | `tunnel` | Chisel tunnel subdomain |
361
+ | `www` | Common web prefix |
362
+ | `mail` | Email subdomain |
363
+ | `ftp` | File transfer subdomain |
364
+ | `api` | API subdomain |