@lamalibre/create-lamaste 4.5.0 → 4.6.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/package.json +2 -2
- package/scripts/lamaste-priv +34 -2
- package/vendor/docs/00-introduction/how-it-works.md +2 -2
- package/vendor/docs/00-introduction/quickstart.md +5 -5
- package/vendor/docs/00-introduction/what-is-lamaste.md +5 -5
- package/vendor/docs/01-concepts/certificates.md +3 -3
- package/vendor/docs/01-concepts/mtls.md +2 -2
- package/vendor/docs/01-concepts/security-model.md +2 -2
- package/vendor/docs/01-concepts/tickets.md +2 -2
- package/vendor/docs/01-concepts/tunneling.md +4 -4
- package/vendor/docs/02-guides/agent-setup.md +5 -5
- package/vendor/docs/02-guides/certificate-management.md +2 -2
- package/vendor/docs/02-guides/cloud-provisioning.md +3 -3
- package/vendor/docs/02-guides/desktop-app-setup.md +10 -10
- package/vendor/docs/02-guides/installation.md +3 -3
- package/vendor/docs/02-guides/onboarding.md +2 -2
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +2 -2
- package/vendor/docs/02-guides/static-sites.md +4 -0
- package/vendor/docs/03-architecture/installer-flow.md +2 -2
- package/vendor/docs/03-architecture/installer.md +4 -4
- package/vendor/docs/03-architecture/management-flow.md +1 -1
- package/vendor/docs/03-architecture/nginx-configuration.md +65 -7
- package/vendor/docs/03-architecture/overview.md +5 -5
- package/vendor/docs/03-architecture/panel-client.md +6 -6
- package/vendor/docs/03-architecture/panel-server.md +2 -2
- package/vendor/docs/03-architecture/state-management.md +2 -2
- package/vendor/docs/03-architecture/system-overview.md +1 -1
- package/vendor/docs/04-api-reference/agent-hosted-plugins.md +112 -37
- package/vendor/docs/04-api-reference/app-host.md +3 -3
- package/vendor/docs/04-api-reference/gatekeeper.md +19 -1
- package/vendor/docs/04-api-reference/lifecycle-hooks.md +4 -4
- package/vendor/docs/04-api-reference/onboarding.md +1 -1
- package/vendor/docs/04-api-reference/sites.md +4 -0
- package/vendor/docs/04-api-reference/tunnels.md +21 -19
- package/vendor/docs/05-operations/backup-and-restore.md +1 -1
- package/vendor/docs/05-operations/uninstalling.md +1 -1
- package/vendor/docs/05-operations/upgrades.md +15 -6
- package/vendor/docs/06-reference/config-files.md +19 -15
- package/vendor/docs/06-reference/glossary.md +3 -3
- package/vendor/docs/06-reference/installer-flags.md +13 -13
- package/vendor/docs/06-reference/ports-and-services.md +1 -1
- package/vendor/docs/06-reference/troubleshooting.md +8 -8
- package/vendor/docs/gatekeeper-design.md +8 -8
- package/vendor/docs/identity-directory-design.md +3 -3
- package/vendor/docs/package.json +1 -1
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +27 -27
- package/vendor/gatekeeper/dist/cli/index.js +0 -0
- package/vendor/gatekeeper/dist/index.d.ts +3 -3
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/index.js +2 -2
- package/vendor/gatekeeper/dist/index.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/authz.d.ts +9 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/authz.js +31 -0
- package/vendor/gatekeeper/dist/lib/authz.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/constants.d.ts +5 -2
- package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/constants.js +5 -2
- package/vendor/gatekeeper/dist/lib/constants.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/tunnels.d.ts +3 -6
- package/vendor/gatekeeper/dist/lib/tunnels.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/tunnels.js +4 -16
- package/vendor/gatekeeper/dist/lib/tunnels.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/types.d.ts +0 -19
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.d.ts +2 -1
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.js +29 -10
- package/vendor/gatekeeper/dist/server/index.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.js +103 -22
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -1
- package/vendor/gatekeeper/package.json +2 -2
- package/vendor/server/package.json +2 -2
- package/vendor/server/src/commands/plugin-web-surface.js +269 -0
- package/vendor/server/src/commands/plugins.js +63 -6
- package/vendor/server/src/commands/sites.js +15 -1
- package/vendor/server/src/plugin-approval.js +80 -1
- package/vendor/server/src/plugin-web-surface.js +307 -0
- package/vendor/server-ui/dist/assets/index-BZwQ_aQc.css +1 -0
- package/vendor/server-ui/dist/assets/index-BvEfCZYS.js +84 -0
- package/vendor/server-ui/dist/index.html +2 -2
- package/vendor/serverd/package.json +2 -2
- package/vendor/serverd/src/index.js +9 -4
- package/vendor/serverd/src/lib/chisel-runtime.js +18 -6
- package/vendor/serverd/src/lib/chisel.js +10 -2
- package/vendor/serverd/src/lib/gatekeeper-client.js +18 -7
- package/vendor/serverd/src/lib/hook-pipelines.js +8 -3
- package/vendor/serverd/src/lib/migrations/state/0015_plugin_web_surface.sql +14 -0
- package/vendor/serverd/src/lib/nginx.js +269 -2
- package/vendor/serverd/src/lib/plugin-hooks.js +40 -11
- package/vendor/serverd/src/lib/plugin-lifecycle.js +128 -5
- package/vendor/serverd/src/lib/plugin-packages.js +74 -2
- package/vendor/serverd/src/lib/plugins.js +39 -6
- package/vendor/serverd/src/lib/state.js +18 -0
- package/vendor/serverd/src/lib/user-surface.js +48 -27
- package/vendor/serverd/src/lib/vhost-reconcile.js +5 -3
- package/vendor/serverd/src/lib/web-surface.js +766 -0
- package/vendor/serverd/src/routes/management/plugin-web-surface.js +151 -0
- package/vendor/serverd/src/routes/management/plugins.js +2 -0
- package/vendor/serverd/src/routes/management/sites.js +143 -65
- package/vendor/serverd/src/routes/management/tunnels.js +11 -20
- package/vendor/serverd/src/routes/management.js +2 -0
- package/vendor/server-ui/dist/assets/index-D-fer5ef.css +0 -1
- package/vendor/server-ui/dist/assets/index-DSaDPJaw.js +0 -84
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## In Plain English
|
|
6
6
|
|
|
7
|
-
When you run `npx @lamalibre/create-lamaste@4.
|
|
7
|
+
When you run `npx @lamalibre/create-lamaste@4.6.0` on a fresh VPS, the installer takes over and does everything automatically: hardens the OS, installs dependencies, generates security certificates, configures nginx, deploys the panel, and starts the service. It prints a summary with instructions for downloading your client certificate and accessing the panel. No prompts, no questions, no configuration files to edit.
|
|
8
8
|
|
|
9
9
|
The installer is deliberately limited in scope. It sets up just enough to serve the panel UI over a secure connection. Everything else — domain configuration, tunnel setup, user management — happens through the browser-based onboarding wizard after the installer finishes.
|
|
10
10
|
|
|
11
11
|
## Overview
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
npx @lamalibre/create-lamaste@4.
|
|
14
|
+
npx @lamalibre/create-lamaste@4.6.0
|
|
15
15
|
│
|
|
16
16
|
├── bin/create-lamaste.js ← CLI entry point
|
|
17
17
|
│ └── calls main() from src/index.js
|
|
@@ -181,7 +181,7 @@ Six task groups run sequentially through Listr2:
|
|
|
181
181
|
**Chisel and Authelia** (`lib/relay-services.js`, run on install and on every redeploy):
|
|
182
182
|
|
|
183
183
|
- Creates the `lamaste-chisel` group (and adds `lamaste` to it) and the `lamaste-authelia` system account (no login shell, no home)
|
|
184
|
-
- Installs Chisel 1.12.0 and Authelia 4.39.28 to `/usr/local/bin` (`lib/binaries.js`): downloaded from fixed release URLs, verified against the SHA-256 digests pinned in `@lamalibre/lamaste@4.
|
|
184
|
+
- Installs Chisel 1.12.0 and Authelia 4.39.28 to `/usr/local/bin` (`lib/binaries.js`): downloaded from fixed release URLs, verified against the SHA-256 digests pinned in `@lamalibre/lamaste@4.6.0` (`CHISEL_RELEASE`, `AUTHELIA_RELEASE`) before anything is unpacked, staged in a `mkdtemp` directory and renamed into place. A binary already at the pinned version is left alone; an Authelia **newer** than the pin is kept, never downgraded (its database may use a schema the pinned release cannot read)
|
|
185
185
|
- Writes `/etc/systemd/system/chisel.service` (`User=nobody`, `Group=lamaste-chisel`) and `/etc/systemd/system/authelia.service` (`User=lamaste-authelia`, `UMask=027`, `Environment=X_AUTHELIA_CONFIG_FILTERS=template`, `ProtectSystem=strict` with `ReadWritePaths=/etc/authelia /var/log/authelia`, `SystemCallFilter=@system-service`, empty `CapabilityBoundingSet`, `NoNewPrivileges`); both are enabled and started later by onboarding
|
|
186
186
|
- Generates the OpenID Connect issuer key `/etc/authelia/oidc-issuer.pem` if it is missing (`lib/oidc-issuer-key.js`): RSA 4096 generated in the installer process, written by a child process running as `lamaste-authelia` (`wx`, 0600, renamed into place) so root never writes through `/etc/authelia`. The panel references it from Authelia's configuration with a `{{ secret "…" }}` template expression — which is why the unit and `lamaste-priv authelia-totp` set the `template` configuration filter — and can never read it. A key owned by anyone else is replaced; one owned by the Authelia account is kept (its mode fixed through a descriptor if it drifted)
|
|
187
187
|
- Sets ownership (`lib/ownership.js`): `/var/www/lamaste` `lamaste:www-data 2750`; `/etc/authelia` `lamaste:lamaste-authelia 2770` (setgid) with `configuration.yml` `0640`, `users.yml` `0660`, `.secrets.json` `0600` (lamaste), `db.sqlite3*` and `notifications.txt` `lamaste-authelia 0600`; `/var/log/authelia` `lamaste-authelia 0750`; `chisel-server.key` (if present) `lamaste:lamaste-chisel 0640`; the PKI directory `lamaste:lamaste` (the panel is the CA)
|
|
@@ -253,7 +253,7 @@ When the installer detects an existing Lamaste installation (`/etc/lamalibre/lam
|
|
|
253
253
|
|
|
254
254
|
Redeploy mode stops the panel and gatekeeper, secures the install directory (a non-root-owned tree is moved aside and removed at the end), redeploys the panel server, `lamaste-server` CLI, UI, docs, gatekeeper and cert help page, merges `panel.json`, runs the same Chisel/Authelia step as a fresh install (stopping a running Authelia while its files change hands), rewrites the panel's systemd unit, the root-owned programs and the sudoers rules, ensures the port-80 redirect, then restarts Chisel if its binary or unit changed, starts Authelia and the gatekeeper if they were running, and restarts the panel. It does not touch OS hardening, mTLS certificates or the panel's vhosts. The panel's self-update (`sudo lamaste-priv self-update <version>`) runs this path as root, so it never writes through a path the `lamaste` user controls.
|
|
255
255
|
|
|
256
|
-
This provides a fast upgrade path: re-running `npx @lamalibre/create-lamaste@4.
|
|
256
|
+
This provides a fast upgrade path: re-running `npx @lamalibre/create-lamaste@4.6.0` on an existing installation updates the code and the pinned services while preserving all configuration and certificates. Use `--force-full` to bypass this and run the complete installer.
|
|
257
257
|
|
|
258
258
|
The redeploy logic lives in `tasks/redeploy.js`, with shared systemd unit and sudoers content generators in `lib/service-config.js`.
|
|
259
259
|
|
|
@@ -278,7 +278,7 @@ Everything else the panel does needs no rule: the PKI directory (agent CSR signi
|
|
|
278
278
|
|
|
279
279
|
The certbot wrappers accept only lowercase DNS hostnames (no wildcards or path characters, at most 100 per certificate) and a syntactically valid email address. Renewals the panel triggers pass `--no-random-sleep-on-renew`, because certbot otherwise sleeps up to about 8 minutes before a non-interactive renewal (a delay meant for `certbot.timer`) while an operator waits.
|
|
280
280
|
|
|
281
|
-
Redeploying (`npx @lamalibre/create-lamaste@4.
|
|
281
|
+
Redeploying (`npx @lamalibre/create-lamaste@4.6.0` on an existing install) reinstalls the programs, removes retired ones (`lamaste-sign-csr`, `lamaste-pki-rename`), and replaces this file atomically after `visudo -c` accepts it, so upgrades pick up new rules.
|
|
282
282
|
|
|
283
283
|
## File Operation Safety
|
|
284
284
|
|
|
@@ -410,6 +410,64 @@ Optional Authelia protection is controlled by the `autheliaProtected` flag on th
|
|
|
410
410
|
|
|
411
411
|
A custom-domain site may list `aliases` (e.g. `www.myblog.net`). They are served by a second server block that answers with a 301 to the primary host. One certificate lineage, named after the site's domain (`certbot certonly --nginx --cert-name <fqdn> -d <fqdn> -d <alias> ...`), covers the primary name and every alias, so both blocks point at the same `live/<fqdn>/` directory.
|
|
412
412
|
|
|
413
|
+
### Web-surface vhosts
|
|
414
|
+
|
|
415
|
+
A site a plugin owns for its [web surface](../04-api-reference/agent-hosted-plugins.md#web-surface) has a vhost of its own kind under the site name (`lamalibre-lamaste-site-<id>`), rendered by the panel from the plugin's state (`renderWebSurfaceVhost`) — never by the static-site generator. While the surface is served:
|
|
416
|
+
|
|
417
|
+
```nginx
|
|
418
|
+
server {
|
|
419
|
+
listen 443 ssl;
|
|
420
|
+
server_name piyasa.example.com;
|
|
421
|
+
ssl_certificate /etc/letsencrypt/live/piyasa.example.com/fullchain.pem;
|
|
422
|
+
ssl_certificate_key /etc/letsencrypt/live/piyasa.example.com/privkey.pem;
|
|
423
|
+
|
|
424
|
+
root /var/www/lamaste/apps/market-indicators/current;
|
|
425
|
+
index index.html;
|
|
426
|
+
|
|
427
|
+
# Every path of the shell: Gatekeeper first (the API's locations ask on their own)
|
|
428
|
+
auth_request /internal/lamaste/shell-authz;
|
|
429
|
+
error_page 401 =302 https://auth.example.com/?rd=https://piyasa.example.com$request_uri;
|
|
430
|
+
error_page 403 = /internal/lamaste/shell-authz;
|
|
431
|
+
|
|
432
|
+
location = /internal/lamaste/shell-authz {
|
|
433
|
+
internal;
|
|
434
|
+
auth_request off;
|
|
435
|
+
proxy_pass http://127.0.0.1:9294/authz/user-surface-shell/piyasa.example.com;
|
|
436
|
+
# ... as every Gatekeeper subrequest
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
# /internal/lamaste/user-surface-authz, -401 and the /api/market-indicators/app
|
|
440
|
+
# locations — exactly the user-surface locations of a bound tunnel
|
|
441
|
+
|
|
442
|
+
# A script, style, font or image the current tree lacks: the previous
|
|
443
|
+
# tree's (a page still running the old shell), else 404
|
|
444
|
+
location ~* [.](?:js|mjs|css|woff2?|ttf|otf|png|jpe?g|gif|webp|avif|ico)$ {
|
|
445
|
+
if ($request_method !~ ^(GET|HEAD)$) { return 405; }
|
|
446
|
+
if ($http_service_worker) { return 404; }
|
|
447
|
+
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
|
|
448
|
+
# X-Content-Type-Options, X-Frame-Options DENY, Referrer-Policy, COOP, CORP, Cache-Control no-cache
|
|
449
|
+
types { text/javascript js mjs; text/css css; ... } # core WEB_TREE_CONTENT_TYPES
|
|
450
|
+
try_files $uri @previous;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
# Everything else: the current tree's file, else the shell
|
|
454
|
+
location / {
|
|
455
|
+
# the same method check, worker refusal, headers and types
|
|
456
|
+
try_files $uri /index.html;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
location @previous {
|
|
460
|
+
# the same headers and types
|
|
461
|
+
root /var/www/lamaste/apps/market-indicators/previous;
|
|
462
|
+
try_files $uri =404;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
`auth_request` sits at server level so every location of the shell asks Gatekeeper — the API's locations name their own subrequest, and the internal ones turn it `off`. The API's prefix location is `^~`, so the subresource regex never takes an API path. The shell's headers are set in its locations only: the API's answers are the panel's to head. A document, an SVG or a manifest is never served from the previous tree, and a service worker's script (`Service-Worker: script`) is always `404` — a worker would outlive the tree that installed it. The `types` block names each extension's content type from core's list (`lamaste-priv` accepts a `types` block in a location — `media/type ext…` entries only, no `include`) rather than trust the host's `mime.types`, which differs between nginx versions. `current` and `previous` are links the panel switches with a rename (see [Serving the tree](../04-api-reference/agent-hosted-plugins.md#serving-the-tree)); nginx follows them per request. While the surface is not served, the vhost answers everything with `503` (`Cache-Control: no-store`, a worker's script `404`) — and, once the plugin is uninstalled, `Clear-Site-Data: "storage"`.
|
|
468
|
+
|
|
469
|
+
Moving a bound tunnel's host to a web surface hands the hostname over in **one reload**: the tunnel's vhost is unlinked, the site's written and linked, `nginx -t` run, nginx reloaded once; the tunnel's file stays installed, unlinked, so the tunnel can be enabled again once the site is deleted. On a failed test both are put back.
|
|
470
|
+
|
|
413
471
|
### 7. Public Tunnel Vhost (`lamalibre-lamaste-app-<name>`, access mode: public)
|
|
414
472
|
|
|
415
473
|
Created when a tunnel is configured with public access. Direct proxy with no authentication.
|
|
@@ -642,7 +700,7 @@ An `authenticated` or `restricted` app tunnel bound as the user surface of agent
|
|
|
642
700
|
# The user surface of plugin "market-indicators"
|
|
643
701
|
location = /api/market-indicators/app { ... } # the same block as below
|
|
644
702
|
|
|
645
|
-
location /api/market-indicators/app/ {
|
|
703
|
+
location ^~ /api/market-indicators/app/ {
|
|
646
704
|
auth_request /internal/lamaste/user-surface-authz;
|
|
647
705
|
auth_request_set $relay_assertion $upstream_http_x_lamalibre_relay_assertion;
|
|
648
706
|
|
|
@@ -852,12 +910,12 @@ nginx's master process runs as root and opens the files a configuration names
|
|
|
852
910
|
- its **name** is one the panel manages: `lamalibre-lamaste-panel-domain`, `-auth`, `-tunnel`, `-app-<subdomain>`, `-agent-panel-<label>` or `-site-<uuid>`. `lamalibre-lamaste-panel-ip` (written by the installer) may only be enabled or disabled — which is how panel 2FA turns the IP vhost off;
|
|
853
911
|
- every **directive** is on the allow-list for its context, with arguments that cannot name a file outside what Lamaste serves:
|
|
854
912
|
|
|
855
|
-
| Context | Allowed
|
|
856
|
-
| ---------- |
|
|
857
|
-
| top level | `server`, `map` (plain `key value;` entries, no `include`), `limit_req_zone`
|
|
858
|
-
| `server` | `listen 443` / `[::]:443` with optional `ssl` / `http2`; `server_name` (hostnames); `ssl_certificate(_key)` only `/etc/letsencrypt/live/<name>/{fullchain,privkey}.pem`; `include` only `/etc/nginx/snippets/lamalibre-lamaste-*.conf`; `root` only under `/var/www/lamaste/`; `ssl_protocols`, `ssl_ciphers`, `ssl_prefer_server_ciphers`, `client_max_body_size`, `index`, `add_header`, `proxy_set_header`, `error_page`, `return`, `rewrite`, `location` |
|
|
859
|
-
| `location` | `proxy_pass` only `http://127.0.0.1:<port>[/path]`; `root` / `alias` only under `/var/www/lamaste/`; `proxy_set_header`, `proxy_http_version`, `proxy_read_timeout`, `proxy_send_timeout`, `proxy_buffers`, `proxy_next_upstream`, `proxy_pass_request_body`, `auth_request`, `auth_request_set`, `limit_req`, `try_files
|
|
860
|
-
| `if` | `return`, `rewrite`
|
|
913
|
+
| Context | Allowed |
|
|
914
|
+
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
915
|
+
| top level | `server`, `map` (plain `key value;` entries, no `include`), `limit_req_zone` |
|
|
916
|
+
| `server` | `listen 443` / `[::]:443` with optional `ssl` / `http2`; `server_name` (hostnames); `ssl_certificate(_key)` only `/etc/letsencrypt/live/<name>/{fullchain,privkey}.pem`; `include` only `/etc/nginx/snippets/lamalibre-lamaste-*.conf`; `root` only under `/var/www/lamaste/`; `auth_request` only a URI of the server or `off`; `ssl_protocols`, `ssl_ciphers`, `ssl_prefer_server_ciphers`, `client_max_body_size`, `index`, `add_header`, `proxy_set_header`, `error_page`, `return`, `rewrite`, `location` (a path, or a named location `@name`) |
|
|
917
|
+
| `location` | `proxy_pass` only `http://127.0.0.1:<port>[/path]`; `root` / `alias` only under `/var/www/lamaste/`; `proxy_set_header`, `proxy_http_version`, `proxy_read_timeout`, `proxy_send_timeout`, `proxy_buffers`, `proxy_next_upstream`, `proxy_pass_request_body`, `auth_request`, `auth_request_set`, `limit_req`, `try_files` (the last argument may name a location, `@name`), `index`, `add_header`, `error_page`, `client_max_body_size`, `internal`, `return`, `rewrite`, `if`, nested `location` |
|
|
918
|
+
| `if` | `return`, `rewrite` |
|
|
861
919
|
|
|
862
920
|
Port 80 is not allowed: it belongs to the installer's HTTPS redirect and to certbot's HTTP-01 challenges. Backslashes, `${`, control characters and non-ASCII text outside comments are refused rather than interpreted, as is any directive not listed — including ones nginx would accept (`access_log`, `log_format`, `ssl_*` files elsewhere, `proxy_pass` to another host, ...). A refused `write` fails with `nginx site write failed for <name>: lamaste-priv: vhost line <n>: ...` and leaves the previous vhost in place.
|
|
863
921
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Lamaste has three main pieces:
|
|
8
8
|
|
|
9
|
-
1. **The Installer** (`npx @lamalibre/create-lamaste@4.
|
|
9
|
+
1. **The Installer** (`npx @lamalibre/create-lamaste@4.6.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
10
|
|
|
11
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
12
|
|
|
@@ -318,7 +318,7 @@ lamaste/
|
|
|
318
318
|
│ │ ├── files.js ← Static site file operations (upload, delete, list)
|
|
319
319
|
│ │ └── app-error.js ← Operational error class (AppError)
|
|
320
320
|
│ │
|
|
321
|
-
│ ├── lamaste-server-ui/ ← React 18 + Vite + Tailwind SPA + shared admin components (@lamalibre/lamaste-server-ui@4.
|
|
321
|
+
│ ├── lamaste-server-ui/ ← React 18 + Vite + Tailwind SPA + shared admin components (@lamalibre/lamaste-server-ui@4.6.0)
|
|
322
322
|
│ │ └── src/
|
|
323
323
|
│ │ ├── index.js ← Package exports (pages, context, utilities)
|
|
324
324
|
│ │ ├── context/
|
|
@@ -334,7 +334,7 @@ lamaste/
|
|
|
334
334
|
│ │ │ └── formatters.js ← Byte, uptime, relative time formatters
|
|
335
335
|
│ │ └── pages/ ← Admin pages (Dashboard, Tunnels, Sites, Users, Certs, Services, Plugins, Tickets, Settings)
|
|
336
336
|
│ │
|
|
337
|
-
│ ├── lamaste-agent-ui/ ← Shared React agent UI (pages, context, components) (@lamalibre/lamaste-agent-ui@4.
|
|
337
|
+
│ ├── lamaste-agent-ui/ ← Shared React agent UI (pages, context, components) (@lamalibre/lamaste-agent-ui@4.6.0)
|
|
338
338
|
│ │
|
|
339
339
|
│ ├── lamaste-tickets/ ← Agent-to-agent authorization SDK (mTLS, undici)
|
|
340
340
|
│ │ └── src/
|
|
@@ -374,7 +374,7 @@ lamaste/
|
|
|
374
374
|
│ │ │ └── CompleteStep.jsx ← Credentials + TOTP QR + next steps
|
|
375
375
|
│ │ ├── management/ ← Legacy standalone implementations (kept for reference)
|
|
376
376
|
│ │ │ ├── Certificates.jsx ← Standalone certificates page (dead code)
|
|
377
|
-
│ │ │ ├── Dashboard.jsx ← Standalone dashboard (not imported — App.jsx uses @lamalibre/lamaste-server-ui@4.
|
|
377
|
+
│ │ │ ├── Dashboard.jsx ← Standalone dashboard (not imported — App.jsx uses @lamalibre/lamaste-server-ui@4.6.0)
|
|
378
378
|
│ │ │ ├── Plugins.jsx ← Standalone plugins page (dead code)
|
|
379
379
|
│ │ │ ├── Services.jsx ← Standalone services page (dead code)
|
|
380
380
|
│ │ │ ├── Settings.jsx ← Standalone settings page (dead code)
|
|
@@ -483,7 +483,7 @@ The Panel Server runs as the `lamaste` user with minimal privileges and cannot b
|
|
|
483
483
|
The full lifecycle of a Lamaste installation:
|
|
484
484
|
|
|
485
485
|
```
|
|
486
|
-
Phase 1: Installation (npx @lamalibre/create-lamaste@4.
|
|
486
|
+
Phase 1: Installation (npx @lamalibre/create-lamaste@4.6.0)
|
|
487
487
|
└─ OS hardening, Node.js, mTLS certs, nginx, panel deploy
|
|
488
488
|
└─ Result: Panel accessible at https://<ip>:9292
|
|
489
489
|
|
|
@@ -10,9 +10,9 @@ The client has two modes. On first visit, it shows an onboarding wizard that wal
|
|
|
10
10
|
|
|
11
11
|
## Shared Panel Packages
|
|
12
12
|
|
|
13
|
-
The management-mode admin pages (Dashboard, Tunnels, Sites, Users, Certificates, Services, Plugins, Tickets, Logs, Settings) live in `@lamalibre/lamaste-server-ui@4.
|
|
13
|
+
The management-mode admin pages (Dashboard, Tunnels, Sites, Users, Certificates, Services, Plugins, Tickets, Logs, Settings) live in `@lamalibre/lamaste-server-ui@4.6.0`. This package provides both the browser SPA build and the shared admin components consumed by `lamaste-desktop` (Tauri app).
|
|
14
14
|
|
|
15
|
-
The agent-mode pages (Dashboard, Tunnels, Services, Plugins, Logs, Settings) are extracted into a separate shared package: `@lamalibre/lamaste-agent-ui@4.
|
|
15
|
+
The agent-mode pages (Dashboard, Tunnels, Services, Plugins, Logs, Settings) are extracted into a separate shared package: `@lamalibre/lamaste-agent-ui@4.6.0`. This package is consumed by `lamaste-desktop` for agent mode.
|
|
16
16
|
|
|
17
17
|
The shared package exposes an `AdminClientContext` abstraction that decouples admin UI pages from their data transport. Each host provides its own client implementation:
|
|
18
18
|
|
|
@@ -118,7 +118,7 @@ The shell renders the appropriate step component and shows a progress indicator
|
|
|
118
118
|
|
|
119
119
|
### Management Mode
|
|
120
120
|
|
|
121
|
-
React Router handles navigation within the `Layout` component (sidebar + content area). Management page components are imported from the shared `@lamalibre/lamaste-server-ui@4.
|
|
121
|
+
React Router handles navigation within the `Layout` component (sidebar + content area). Management page components are imported from the shared `@lamalibre/lamaste-server-ui@4.6.0` package and wrapped with the `AdminClientProvider` (which supplies the web-specific data client):
|
|
122
122
|
|
|
123
123
|
| Path | Component | Description |
|
|
124
124
|
| ------------------------ | ------------------- | ------------------------------------------------------------------- |
|
|
@@ -350,9 +350,9 @@ The app root wraps all content in five providers:
|
|
|
350
350
|
```
|
|
351
351
|
|
|
352
352
|
1. **QueryClientProvider** — react-query cache with global defaults (`retry: 1`, `refetchOnWindowFocus: false`)
|
|
353
|
-
2. **AdminClientProvider** — from `@lamalibre/lamaste-server-ui@4.
|
|
354
|
-
3. **ToastProvider** — from `@lamalibre/lamaste-server-ui@4.
|
|
355
|
-
4. **TwoFaProvider** — from `@lamalibre/lamaste-server-ui@4.
|
|
353
|
+
2. **AdminClientProvider** — from `@lamalibre/lamaste-server-ui@4.6.0`, supplies the host-specific data client (`webAdminClient` for browser fetch, Tauri `invoke` for desktop)
|
|
354
|
+
3. **ToastProvider** — from `@lamalibre/lamaste-server-ui@4.6.0`, notification toast system
|
|
355
|
+
4. **TwoFaProvider** — from `@lamalibre/lamaste-server-ui@4.6.0`, handles 2FA verification prompts when the panel has 2FA enabled
|
|
356
356
|
5. **BrowserRouter** — React Router for client-side navigation
|
|
357
357
|
|
|
358
358
|
## Documentation Viewer
|
|
@@ -453,7 +453,7 @@ See [nginx-configuration.md](./nginx-configuration.md) for detailed coverage.
|
|
|
453
453
|
|
|
454
454
|
### chisel-users.js — Chisel Credentials and Grants
|
|
455
455
|
|
|
456
|
-
- Thin shim over `@lamalibre/lamaste@4.
|
|
456
|
+
- Thin shim over `@lamalibre/lamaste@4.6.0/server`: per-agent credentials in `chisel-credentials.json` (0600)
|
|
457
457
|
- Renders the authfile `chisel-users` from the credentials and `tunnels.json`: each `agent-<label>` may bind exactly `^R:127\.0\.0\.1:<port>$` for its enabled tunnels
|
|
458
458
|
- Adds the `lamaste-no-grants` sentinel user (password in `chisel-sentinel`, 0600) so the authfile is never empty — Chisel disables authentication on an empty authfile
|
|
459
459
|
- Never grants a reserved port (3100, 9090, 9091, 9292, 9294) or a port claimed by two tunnels
|
|
@@ -536,7 +536,7 @@ Agent-to-agent authorization with scopes, instances, tickets, and sessions. Prov
|
|
|
536
536
|
- **Periodic cleanup** — stale/dead instances, expired tickets, dead sessions
|
|
537
537
|
- **Concurrency** — promise-chain mutex with atomic file writes (temp → fsync → rename)
|
|
538
538
|
|
|
539
|
-
Client SDK: `@lamalibre/lamaste-tickets@4.
|
|
539
|
+
Client SDK: `@lamalibre/lamaste-tickets@4.6.0` (TypeScript, undici) provides `TicketClient`, `TicketInstanceManager` (source side), and `TicketSessionManager` (target side) for plugin integration.
|
|
540
540
|
|
|
541
541
|
State files: `/etc/lamalibre/lamaste/ticket-scopes.json` (scopes, instances, assignments) and `/etc/lamalibre/lamaste/tickets.json` (tickets, sessions).
|
|
542
542
|
|
|
@@ -329,7 +329,7 @@ Read returns `[]` for missing files (ENOENT), enabling the system to start with
|
|
|
329
329
|
5. `DELETE /api/certs/agent/:label` (revocation) — the agent's app and plugin tunnels lose their `agentLabel` (unassigned), and its `agent-<label>` panel tunnel is removed
|
|
330
330
|
6. At startup (background, fail closed): an ownerless `agent-<label>` panel tunnel is bound to the agent it names when that agent is active; other ownerless tunnels (from versions before tunnel ownership) are bound to the sole active agent, or left unassigned when there are several. Then the pinned Chisel binary, the unit and the authfile are re-established — and Chisel is stopped if they cannot be
|
|
331
331
|
|
|
332
|
-
Every one of these workflows runs under the single tunnel lock (`withTunnelLock` in `@lamalibre/lamaste@4.
|
|
332
|
+
Every one of these workflows runs under the single tunnel lock (`withTunnelLock` in `@lamalibre/lamaste@4.6.0/server`), with its validation inside the lock.
|
|
333
333
|
|
|
334
334
|
## Site State (`sites.json`)
|
|
335
335
|
|
|
@@ -482,7 +482,7 @@ The PKI directory belongs to `lamaste` because the panel is the CA (it signs age
|
|
|
482
482
|
|
|
483
483
|
The Panel Server is a single-process Node.js application, but a single-threaded event loop does not serialize asynchronous workflows: two requests that each read `tunnels.json`, await a certificate or an nginx test, and then write it back would interleave, and both could pass the same uniqueness check. Serialization is therefore explicit:
|
|
484
484
|
|
|
485
|
-
**Tunnel state** is guarded by one promise-chain lock, `withTunnelLock` in `@lamalibre/lamaste@4.
|
|
485
|
+
**Tunnel state** is guarded by one promise-chain lock, `withTunnelLock` in `@lamalibre/lamaste@4.6.0/server`'s `tunnels.ts`. Every tunnel workflow — create, delete, toggle, assign, reconfigure, the combined `PATCH /api/tunnels/:id`, releasing a revoked agent's tunnels, and startup reconciliation — takes it for its whole duration, and does its validation (subdomain and port uniqueness, reserved ports, agent checks, authorization against the current entry) inside it.
|
|
486
486
|
|
|
487
487
|
**Chisel authfile renders** are serialized by a promise-chain mutex in `chisel-users.ts`, keyed by the credentials file, around every render (enroll, revoke, rotate, tunnel change). The daemon's `syncChisel()` renders after the tunnel state is written and restarts Chisel (`systemctl try-restart`) only when the render withdrew something.
|
|
488
488
|
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
│ │ │ │
|
|
59
59
|
│ │ Lamaste Desktop (Tauri v2) — dual mode │ │
|
|
60
60
|
│ │ ├─ Agent mode: service discovery + tunnel management │ │
|
|
61
|
-
│ │ │ (pages from @lamalibre/lamaste-agent-ui@4.
|
|
61
|
+
│ │ │ (pages from @lamalibre/lamaste-agent-ui@4.6.0) │ │
|
|
62
62
|
│ │ ├─ Server mode: full admin panel (via lamaste-server-ui) │ │
|
|
63
63
|
│ │ ├─ Multi-server registry (~/.lamalibre/lamaste/servers.json) │ │
|
|
64
64
|
│ │ ├─ Cloud provisioning (DigitalOcean via lamaste-cloud) │ │
|