@lamalibre/create-lamaste 4.5.0 → 4.7.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/bundle-vendor.js +20 -3
- package/scripts/lamaste-priv +56 -5
- package/scripts/pin-release.js +98 -0
- package/src/index.js +8 -1
- package/src/lib/env.js +19 -0
- package/src/lib/service-config.js +7 -0
- package/src/tasks/redeploy.js +8 -0
- 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/authentication.md +6 -2
- package/vendor/docs/01-concepts/authorization.md +4 -0
- package/vendor/docs/01-concepts/certificates.md +3 -3
- package/vendor/docs/01-concepts/dns-and-domains.md +9 -0
- package/vendor/docs/01-concepts/mtls.md +2 -2
- package/vendor/docs/01-concepts/security-model.md +28 -3
- 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/managing-users.md +5 -11
- package/vendor/docs/02-guides/onboarding.md +2 -2
- package/vendor/docs/02-guides/second-domain.md +82 -0
- 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 +80 -12
- 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 +3 -3
- package/vendor/docs/03-architecture/system-overview.md +1 -1
- package/vendor/docs/04-api-reference/agent-hosted-plugins.md +116 -37
- package/vendor/docs/04-api-reference/app-host.md +3 -3
- package/vendor/docs/04-api-reference/domains.md +192 -0
- package/vendor/docs/04-api-reference/gatekeeper.md +54 -8
- 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/overview.md +9 -0
- package/vendor/docs/04-api-reference/registry-and-oidc.md +26 -13
- package/vendor/docs/04-api-reference/sites.md +9 -0
- package/vendor/docs/04-api-reference/tunnels.md +35 -28
- package/vendor/docs/04-api-reference/users.md +41 -29
- 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/_index.json +105 -19
- package/vendor/docs/external-members-design.md +816 -0
- package/vendor/docs/gatekeeper-design.md +8 -8
- package/vendor/docs/identity-directory-design.md +3 -3
- package/vendor/docs/multi-domain-relay-design.md +836 -0
- package/vendor/docs/package.json +1 -1
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +27 -27
- 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/grants.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/grants.js +20 -13
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0004_unconsume_access_grants.sql +8 -0
- package/vendor/gatekeeper/dist/lib/secret.d.ts +6 -0
- package/vendor/gatekeeper/dist/lib/secret.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/secret.js +12 -0
- package/vendor/gatekeeper/dist/lib/secret.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts +20 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/templates.js +80 -14
- package/vendor/gatekeeper/dist/lib/templates.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 +6 -1
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.js +56 -11
- 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 +325 -55
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +5 -2
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -1
- package/vendor/gatekeeper/package.json +2 -2
- package/vendor/server/bin/lamaste-server.js +7 -0
- package/vendor/server/package.json +2 -2
- package/vendor/server/src/commands/domains.js +214 -0
- package/vendor/server/src/commands/plugin-identity.js +2 -16
- package/vendor/server/src/commands/plugin-web-surface.js +269 -0
- package/vendor/server/src/commands/plugins.js +175 -14
- package/vendor/server/src/commands/registry-credential.js +10 -3
- package/vendor/server/src/commands/sites.js +18 -1
- package/vendor/server/src/commands/status.js +19 -0
- package/vendor/server/src/commands/tunnels.js +4 -1
- package/vendor/server/src/commands/users.js +8 -19
- package/vendor/server/src/domains.js +92 -0
- package/vendor/server/src/fail.js +21 -0
- package/vendor/server/src/oidc-client-grants.js +63 -0
- package/vendor/server/src/panel-api.js +15 -0
- 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-B8Tv_ocF.js +84 -0
- package/vendor/server-ui/dist/assets/index-Cb-ADsbB.css +1 -0
- package/vendor/server-ui/dist/index.html +2 -2
- package/vendor/serverd/package.json +2 -2
- package/vendor/serverd/src/index.js +50 -19
- package/vendor/serverd/src/lib/app-error.js +24 -0
- package/vendor/serverd/src/lib/audience.js +12 -3
- package/vendor/serverd/src/lib/authelia.js +341 -35
- package/vendor/serverd/src/lib/chisel-runtime.js +18 -6
- package/vendor/serverd/src/lib/chisel.js +10 -2
- package/vendor/serverd/src/lib/directory.js +67 -52
- package/vendor/serverd/src/lib/domains.js +1792 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +34 -7
- package/vendor/serverd/src/lib/hook-pipelines.js +8 -3
- package/vendor/serverd/src/lib/identity-sync.js +35 -0
- package/vendor/serverd/src/lib/migrations/state/0015_plugin_web_surface.sql +14 -0
- package/vendor/serverd/src/lib/migrations/state/0016_domains.sql +53 -0
- package/vendor/serverd/src/lib/migrations/state/0017_membership_kind.sql +15 -0
- package/vendor/serverd/src/lib/migrations/state/0018_domain_group_keys.sql +23 -0
- package/vendor/serverd/src/lib/nginx.js +576 -131
- package/vendor/serverd/src/lib/owned-groups.js +326 -0
- package/vendor/serverd/src/lib/plugin-domain.js +86 -0
- package/vendor/serverd/src/lib/plugin-hooks.js +40 -11
- package/vendor/serverd/src/lib/plugin-lifecycle.js +129 -5
- package/vendor/serverd/src/lib/plugin-oidc.js +144 -42
- package/vendor/serverd/src/lib/plugin-packages.js +74 -2
- package/vendor/serverd/src/lib/plugins.js +82 -9
- package/vendor/serverd/src/lib/registry-credential.js +39 -6
- package/vendor/serverd/src/lib/services.js +9 -1
- package/vendor/serverd/src/lib/state.js +29 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +2 -4
- package/vendor/serverd/src/lib/user-surface.js +77 -31
- package/vendor/serverd/src/lib/users-lock.js +23 -0
- package/vendor/serverd/src/lib/vhost-reconcile.js +151 -41
- package/vendor/serverd/src/lib/web-surface.js +783 -0
- package/vendor/serverd/src/middleware/user-access-session.js +11 -4
- package/vendor/serverd/src/routes/invite.js +15 -5
- package/vendor/serverd/src/routes/management/domains.js +154 -0
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +44 -8
- package/vendor/serverd/src/routes/management/identity.js +21 -7
- package/vendor/serverd/src/routes/management/invitations.js +33 -4
- package/vendor/serverd/src/routes/management/plugin-web-surface.js +151 -0
- package/vendor/serverd/src/routes/management/plugins.js +6 -2
- package/vendor/serverd/src/routes/management/registry-credential.js +86 -57
- package/vendor/serverd/src/routes/management/sites.js +188 -71
- package/vendor/serverd/src/routes/management/tunnels.js +37 -22
- package/vendor/serverd/src/routes/management/users.js +184 -64
- package/vendor/serverd/src/routes/management.js +4 -0
- package/vendor/serverd/src/routes/onboarding/dns.js +3 -17
- package/vendor/serverd/src/routes/onboarding/provision.js +22 -13
- package/vendor/serverd/src/routes/user-access.js +13 -1
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +0 -7
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +0 -14
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +0 -9
- package/vendor/server-ui/dist/assets/index-D-fer5ef.css +0 -1
- package/vendor/server-ui/dist/assets/index-DSaDPJaw.js +0 -84
|
@@ -19,10 +19,10 @@ If onboarding is not complete, all endpoints return `503 Service Unavailable`.
|
|
|
19
19
|
## Important Behavior
|
|
20
20
|
|
|
21
21
|
- **Password hashing:** Passwords are hashed with bcrypt (not argon2id — argon2id uses ~93MB per hash and causes OOM kills on a 512MB droplet).
|
|
22
|
-
- **Authelia restart:**
|
|
22
|
+
- **No Authelia restart:** Authelia watches `users.yml` (`authentication_backend.file.watch: true`) and re-reads a user's details at each of their requests, so a user change (create, update, disable, delete) applies without a restart and without ending anyone else's session: a disabled or deleted user's session ends at their next request. Authelia skips a reload within 0.5 s of its previous one, so the panel writes the file once more 0.6 s after its last write — the change is always picked up. TOTP reset writes directly to Authelia's SQLite database via the `authelia storage user totp generate` CLI command, which takes effect immediately.
|
|
23
23
|
- **Atomic writes:** The `users.yml` file is written atomically (write to temp file, then rename) to prevent Authelia from reading a partially written file.
|
|
24
|
-
- **One lock for every user write:** creating, updating, disabling and deleting users, and accepting an invitation, are read-modify-writes of `users.yml` under one lock in the panel. Under the same lock the panel brings the directory in line with the file
|
|
25
|
-
- **A change must stick:** Authelia's own password reset rewrites `users.yml` from what
|
|
24
|
+
- **One lock for every user write:** creating, updating, disabling and deleting users, and accepting an invitation, are read-modify-writes of `users.yml` under one lock in the panel. Under the same lock the panel brings the directory in line with the file — so a disabled user is refused by plugins at once — [offboards](#offboarding) every user that stopped being one, renders who may reach each domain, drops Gatekeeper's cached sessions, then recomputes the plugins' audiences. Concurrent user changes therefore run one after the other.
|
|
25
|
+
- **A change must stick:** Authelia's own password reset rewrites `users.yml` from what it holds in memory, so a change written in the instant before can be lost. The panel reads `users.yml` again and checks that it holds the change (the fields set, the user created or gone); when it does not, the change is made once more. When it still does not, the answer carries `"ok": false`, `"persisted": false` and a `persist` warning — never a silent success.
|
|
26
26
|
- **The directory follows `users.yml`, read only:** at start, after onboarding and every minute the panel reconciles the directory with the file without writing it (Authelia's own password reset rewrites it; an operator may edit it): an unknown username gets a new `userId`, a changed display name, email or `disabled` is adopted, and a username gone from the file — seen missing in two reads, so a half-written file never tombstones anyone — is removed as `deleted-outside`. A user the reconcile sees disabled or removed is offboarded exactly as one disabled or deleted through the API. Every change is audited (`directory.user.created`, `.updated`, `.removed`) by `userId` alone; audit entries never name a user.
|
|
27
27
|
- **Audit:** besides the directory's own entries, the users API records `user.password.set` (a password set through `PUT`), `user.groups.changed` (`added`, `removed` group names) and `user.totp.reset` — each by `userId` alone.
|
|
28
28
|
- **Last user protection:** You cannot delete the last remaining user. At least one user must always exist.
|
|
@@ -75,10 +75,11 @@ curl -s --cert client.p12:password \
|
|
|
75
75
|
| `username` | `string` | Unique login identifier |
|
|
76
76
|
| `displayname` | `string` | Human-readable display name |
|
|
77
77
|
| `email` | `string` | User's email address |
|
|
78
|
-
| `groups` | `string[]` | Authelia group memberships
|
|
78
|
+
| `groups` | `string[]` | Authelia group memberships an administrator assigned — never the groups Lamaste owns ([Domains](#domains)) |
|
|
79
79
|
| `disabled` | `boolean` | Authelia's `disabled: true` — the user cannot sign in |
|
|
80
80
|
| `userId` | `string \| null` | The user's directory id; `null` until the directory has seen the user (within a minute of an edit of `users.yml` made outside the panel) |
|
|
81
81
|
| `status` | `string` | `active` or `disabled` |
|
|
82
|
+
| `domains` | `object[]` | Domain memberships, `{ name, kind }` — `kind` `member` or `external` ([Domains](#domains)) |
|
|
82
83
|
|
|
83
84
|
Users deleted from `users.yml` are not listed here; the [directory](#get-api-identity-directory) keeps their tombstones.
|
|
84
85
|
|
|
@@ -106,13 +107,14 @@ Creates a new Authelia user. The password is hashed with bcrypt before being sto
|
|
|
106
107
|
}
|
|
107
108
|
```
|
|
108
109
|
|
|
109
|
-
| Field | Type | Validation
|
|
110
|
-
| ------------- | ---------- |
|
|
111
|
-
| `username` | `string` | 2-32 chars, lowercase alphanumeric + underscores + hyphens, starting with a letter or digit
|
|
112
|
-
| `displayname` | `string` | 1-100 chars
|
|
113
|
-
| `email` | `string` | Valid email format
|
|
114
|
-
| `password` | `string` | 8-128 chars
|
|
115
|
-
| `groups` | `string[]` | Optional, defaults to `[]`
|
|
110
|
+
| Field | Type | Validation | Description |
|
|
111
|
+
| ------------- | ---------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
112
|
+
| `username` | `string` | 2-32 chars, lowercase alphanumeric + underscores + hyphens, starting with a letter or digit | Login identifier |
|
|
113
|
+
| `displayname` | `string` | 1-100 chars | Display name |
|
|
114
|
+
| `email` | `string` | Valid email format | Email address |
|
|
115
|
+
| `password` | `string` | 8-128 chars | Plain-text password (hashed before storage) |
|
|
116
|
+
| `groups` | `string[]` | Optional, defaults to `[]` | Authelia group memberships |
|
|
117
|
+
| `domains` | array | Names or `{ name, kind }`, at most 50; required once the relay has two (400 `domains_required`) | Memberships ([Domains](#domains)); with one domain, a member of it unless named `external` |
|
|
116
118
|
|
|
117
119
|
**Username regex** (the same rule applies to invitations — a leading `-` would read as a flag to Authelia's CLI, which the panel runs per username for TOTP secrets, second factors and OpenID Connect identities):
|
|
118
120
|
|
|
@@ -145,7 +147,7 @@ curl -s --cert client.p12:password \
|
|
|
145
147
|
}
|
|
146
148
|
```
|
|
147
149
|
|
|
148
|
-
A new user gets a new `userId`, even when an earlier, deleted user had the same username. Before the new user is created ([Reused usernames](#reused-usernames)): the username is refused when Authelia holds an OpenID Connect identity for it; and when a deleted user held it, Gatekeeper drops everything it holds under the username (grants, group memberships) and Authelia the second factors (TOTP, WebAuthn) — always, not only when a cleanup was pending — so a reused username inherits no grant, group, role or second factor. `warnings` (`[{ step, message }]`) lists what went wrong after `users.yml` was written — the directory not updated,
|
|
150
|
+
A new user gets a new `userId`, even when an earlier, deleted user had the same username. Before the new user is created ([Reused usernames](#reused-usernames)): the username is refused when Authelia holds an OpenID Connect identity for it; and when a deleted user held it, Gatekeeper drops everything it holds under the username (grants, group memberships) and Authelia the second factors (TOTP, WebAuthn) — always, not only when a cleanup was pending — so a reused username inherits no grant, group, role or second factor. `warnings` (`[{ step, message }]`) lists what went wrong after `users.yml` was written — the directory not updated, domain access not rendered; a change that did not stick answers `200` with `"ok": false`, `"persisted": false`.
|
|
149
151
|
|
|
150
152
|
**Errors:**
|
|
151
153
|
|
|
@@ -179,13 +181,14 @@ If a new password is provided, it is hashed with bcrypt before storage.
|
|
|
179
181
|
}
|
|
180
182
|
```
|
|
181
183
|
|
|
182
|
-
| Field | Type | Validation | Description
|
|
183
|
-
| ------------- | ---------- | --------------------- |
|
|
184
|
-
| `displayname` | `string` | 1-100 chars, optional | New display name
|
|
185
|
-
| `email` | `string` | Valid email, optional | New email address
|
|
186
|
-
| `password` | `string` | 8-128 chars, optional | New password (hashed before storage)
|
|
187
|
-
| `groups` | `string[]` | Optional | New group memberships (replaces entire list)
|
|
188
|
-
| `
|
|
184
|
+
| Field | Type | Validation | Description |
|
|
185
|
+
| ------------- | ---------- | --------------------- | --------------------------------------------------------------------------------- |
|
|
186
|
+
| `displayname` | `string` | 1-100 chars, optional | New display name |
|
|
187
|
+
| `email` | `string` | Valid email, optional | New email address |
|
|
188
|
+
| `password` | `string` | 8-128 chars, optional | New password (hashed before storage) |
|
|
189
|
+
| `groups` | `string[]` | Optional | New group memberships (replaces entire list; Lamaste's own groups are kept) |
|
|
190
|
+
| `domains` | array | Optional | Memberships afterwards, exactly — names or `{ name, kind }` ([Domains](#domains)) |
|
|
191
|
+
| `disabled` | `boolean` | Optional | `true` disables the user, `false` enables them ([below](#disabling-a-user)) |
|
|
189
192
|
|
|
190
193
|
All fields are optional, but at least one must be provided (validated by a Zod `.refine()`).
|
|
191
194
|
|
|
@@ -214,11 +217,11 @@ curl -s --cert client.p12:password \
|
|
|
214
217
|
}
|
|
215
218
|
```
|
|
216
219
|
|
|
217
|
-
`warnings` lists what did not happen after the write (the directory,
|
|
220
|
+
`warnings` lists what did not happen after the write (the directory, rendering domain access, the steps of [offboarding](#offboarding)); `"ok": false` with `"persisted": false` and a `persist` warning says the change did not stick ([above](#important-behavior)). A change of `groups` revokes the user's registry (Feria) tokens, whose scopes were granted from `feria-*` groups at login.
|
|
218
221
|
|
|
219
222
|
#### Disabling a user
|
|
220
223
|
|
|
221
|
-
`{ "disabled": true }` is the offboarding action. It sets Authelia's `disabled: true` — the user can no longer sign in
|
|
224
|
+
`{ "disabled": true }` is the offboarding action. It sets Authelia's `disabled: true` — the user can no longer sign in, and their session ends at their next request — and:
|
|
222
225
|
|
|
223
226
|
- the directory marks the user `disabled`, so every plugin's [user surface](agent-hosted-plugins.md#the-user-surface) refuses them at once (`403`);
|
|
224
227
|
- every plugin audience that holds them shows them `disabled`, and their agent halves are told;
|
|
@@ -256,7 +259,7 @@ Desktop sessions are bound to the `userId` as well as the username: one is valid
|
|
|
256
259
|
|
|
257
260
|
### `DELETE /api/users/:username`
|
|
258
261
|
|
|
259
|
-
Deletes an Authelia user: the user is removed from `users.yml`, the directory turns their row into a **tombstone** (`removed`, reason `deleted`, keeping the `userId`, the username and the last display name and email, so plugins' history stays readable)
|
|
262
|
+
Deletes an Authelia user: the user is removed from `users.yml`, the directory turns their row into a **tombstone** (`removed`, reason `deleted`, keeping the `userId`, the username and the last display name and email, so plugins' history stays readable); their session ends at their next request. With `?erase=true` the tombstone is [erased](#erasing-a-removed-user) at once as well.
|
|
260
263
|
|
|
261
264
|
You cannot delete the last remaining user. This safety check prevents accidentally locking out all users from tunneled applications.
|
|
262
265
|
|
|
@@ -344,6 +347,14 @@ The `totpUri` follows the [Key Uri Format](https://github.com/google/google-auth
|
|
|
344
347
|
| 500 | `{"error":"Failed to read user database"}` | Cannot read `users.yml` |
|
|
345
348
|
| 500 | `{"error":"Failed to write TOTP configuration"}` | Cannot write TOTP secret to Authelia's SQLite database |
|
|
346
349
|
|
|
350
|
+
### Domains
|
|
351
|
+
|
|
352
|
+
Every user listed by `GET /api/users` carries `domains`: their memberships, `{ name, kind }` — `kind` `member` or `external` (empty until the directory has seen them). `PUT /api/users/:username` takes `domains` too — the memberships afterwards, exactly: the difference is applied in one change, each membership audited (409 `user_not_in_directory` until the directory has seen the user, 400 `unknown_domain`, 400 `conflicting_membership` for one domain named twice with two kinds); one membership at a time is the [Domains API](domains.md) (`PUT`/`DELETE /api/domains/:name/members/:user`, by `userId` or username). Wherever a request names memberships, a domain name is a `member` and `{ "name": "…", "kind": "external" }` an external member. On a relay with two domains or more, `POST /api/users` needs a non-empty `domains` (400 `domains_required`). `POST /api/invitations` takes `domains` exactly as `POST /api/users` does, and `GET /api/invitations` lists each invitation's `domains` as `{ name, kind }`; the invitation link is on the sign-in page of the first domain it names (`https://auth.<domain>/invite/<token>`). Disabling a user keeps their memberships (they are let in nowhere while disabled); deleting ends them.
|
|
353
|
+
|
|
354
|
+
**External members** reach only what names them — `restricted` hosts that grant them, static sites that list them, OIDC clients granted to them — and **hold no Authelia groups**: a user who is an external member of any domain cannot be given a group (409 `external_member_groups`), a user with groups cannot be made external (409), and a new user or an invitation asking for both is refused (400 `external_member_groups`).
|
|
355
|
+
|
|
356
|
+
**Groups Lamaste owns.** Who may reach what is written into each user's `groups` in `users.yml` as groups Lamaste owns — `lamaste:m:<key>`, `lamaste:x:<key>` (a random key per domain), `lamaste:s:<site id>`, hostnames (external members' granted hosts), `lamaste:oidc@<client id>` ([Domains API](domains.md#where-membership-is-enforced)). The users and identity APIs never show them and an edit keeps them; an administrator assigns only names of letters, digits, `-` and `_` (400 `reserved_group` for a name with `.`, `:` or `@` the user does not hold already).
|
|
357
|
+
|
|
347
358
|
## The User Directory
|
|
348
359
|
|
|
349
360
|
The directory lives in the panel's `state.db` (migration `0013`): one row per user it ever knew, never deleted, and the directory's own id (`directoryId`, a UUID v4 made with the store), which tells a plugin's agent half when the store it follows was replaced. Admin only.
|
|
@@ -475,13 +486,14 @@ Returned by list and mutation endpoints (sensitive fields excluded):
|
|
|
475
486
|
|
|
476
487
|
### Validation Summary
|
|
477
488
|
|
|
478
|
-
| Field | Rules
|
|
479
|
-
| ------------- |
|
|
480
|
-
| `username` | 2-32 chars, `/^[a-z0-9][a-z0-9_-]*$/`, unique
|
|
481
|
-
| `displayname` | 1-100 chars
|
|
482
|
-
| `email` | Valid email format
|
|
483
|
-
| `password` | 8-128 chars
|
|
484
|
-
| `groups` | Array of strings, optional
|
|
489
|
+
| Field | Rules |
|
|
490
|
+
| ------------- | ----------------------------------------------------------------------------------- |
|
|
491
|
+
| `username` | 2-32 chars, `/^[a-z0-9][a-z0-9_-]*$/`, unique |
|
|
492
|
+
| `displayname` | 1-100 chars |
|
|
493
|
+
| `email` | Valid email format |
|
|
494
|
+
| `password` | 8-128 chars |
|
|
495
|
+
| `groups` | Array of strings, optional; `[A-Za-z0-9_-]{1,64}` each; none for an external member |
|
|
496
|
+
| `domains` | Names or `{ name, kind }`, at most 50 |
|
|
485
497
|
|
|
486
498
|
### curl Cheat Sheet
|
|
487
499
|
|
|
@@ -199,7 +199,7 @@ sudo chown lamaste-authelia:lamaste-authelia /etc/authelia/db.sqlite3* /etc/auth
|
|
|
199
199
|
sudo chmod 600 /etc/authelia/db.sqlite3* /etc/authelia/notifications.txt
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
A backup taken on a version before the privilege boundary holds root-owned Authelia files and older unit files. After restoring one, re-run `npx @lamalibre/create-lamaste@4.
|
|
202
|
+
A backup taken on a version before the privilege boundary holds root-owned Authelia files and older unit files. After restoring one, re-run `npx @lamalibre/create-lamaste@4.7.0 --yes`: the redeploy rewrites the `chisel` and `authelia` units and converts the ownership of `/etc/authelia`, the Chisel key and the PKI directory (see [Upgrades](upgrades.md)).
|
|
203
203
|
|
|
204
204
|
The panel re-applies the authfile's group and mode itself on every start, so a Chisel that fails to read it before the panel is up is started again by the panel's reconciliation.
|
|
205
205
|
|
|
@@ -29,7 +29,7 @@ It stops and disables the panel, gatekeeper, Chisel and Authelia; removes their
|
|
|
29
29
|
The manual guide is also available from the CLI:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
npx @lamalibre/create-lamaste@4.
|
|
32
|
+
npx @lamalibre/create-lamaste@4.7.0 --uninstall
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
This prints the same steps listed below.
|
|
@@ -27,7 +27,7 @@ Coming from 3.x, upgrade the **agents first**, as 4.0 required: agents from befo
|
|
|
27
27
|
On each agent machine, after the server:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
sudo npm install -g @lamalibre/lamaste-agent@4.
|
|
30
|
+
sudo npm install -g @lamalibre/lamaste-agent@4.7.0
|
|
31
31
|
lamaste-agent update
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -35,13 +35,22 @@ lamaste-agent update
|
|
|
35
35
|
|
|
36
36
|
A machine that hosts app plugins' agent halves needs the root-owned install shown above and its app host helper enabled once with `sudo lamaste-agent apphost enable` (see [App host](../04-api-reference/app-host.md)); after replacing the server's relay signing key, run `sudo lamaste-agent apphost pin` there. An upgrade of `lamaste-agent` does not replace that helper: when a release raises the app host protocol (4.4 speaks 2), run `sudo lamaste-agent apphost enable` again there — until then the agent refuses to install agent halves and the server does not offer it for hosting (`lamaste-agent apphost status` shows the helper as out of date).
|
|
37
37
|
|
|
38
|
+
### Upgrading to 4.6
|
|
39
|
+
|
|
40
|
+
4.6 adds plugins' web surfaces ([Web surface](../04-api-reference/agent-hosted-plugins.md#web-surface)). **Only the relay is upgraded**: the panel's **Update** action, or a `create-lamaste@4.6.0 --yes` redeploy.
|
|
41
|
+
|
|
42
|
+
- **`state.db` migration `0015`** adds `plugins.user_surface` and `plugins.web_tree_sha256`. Existing plugins declare no web surface: their approval digests are unchanged.
|
|
43
|
+
- **`lamaste-priv` must be the 4.6 one** before the panel writes a web surface's vhost: it now accepts a server-level `auth_request`, named locations and a named location as `try_files`' last argument. The Update action and the redeploy install it; a relay whose `lamaste-priv` is older refuses the vhost (`nginx site write failed … directive "auth_request" is not allowed in server`) and keeps the vhost it had.
|
|
44
|
+
- **Web trees live under `/var/www/lamaste/apps/`.** They are copies of approved package contents, made again at the panel's start when missing: nothing there needs a backup.
|
|
45
|
+
- **What changes for existing setups.** Gatekeeper reads `sites.json` as well as `tunnels.json`. The check that a tunnel and a site never share a hostname now runs under the tunnel lock, for enabling a tunnel too. The sites API serves `sites.json` under a lock, and an upload's size is recorded from the file as it is then.
|
|
46
|
+
|
|
38
47
|
### Upgrading to 4.5
|
|
39
48
|
|
|
40
49
|
4.5 adds the user directory and users of agent-hosted plugins ([Users and identity](../04-api-reference/agent-hosted-plugins.md#users-and-identity)). **Only the relay is upgraded**: the panel's **Update** action, or a `create-lamaste@4.5.0 --yes` redeploy.
|
|
41
50
|
|
|
42
51
|
- **`state.db` migration `0013`.** On its first start the panel creates the user directory (a `directoryId`, a `userId` per user, tombstones), the plugin audiences, the per-plugin feed state and the erasure records, and adds `plugins.identity`. It then reads `users.yml` — without writing it — and gives every existing user a `userId`. Back up `state.db` before upgrading, as before any upgrade: from now on it holds the mapping from usernames to user ids ([Backup and Restore](backup-and-restore.md#backup-considerations)).
|
|
43
52
|
- **The redeploy now touches the IP panel vhost.** Until 4.4 a redeploy left every panel vhost alone. From 4.5 it refreshes `lamalibre-lamaste-panel-ip` — the vhost the installer writes and the panel cannot — when its text differs from the current generator's: written, checked with `nginx -t`, put back on failure, and nginx reloaded; its `sites-enabled` link (which panel 2FA owns) is left as it is. A failure is reported and skipped (`Refreshing the IP panel vhost — Skipped`): the panel keeps working on the vhost it had, which still passes a client's `X-Lamalibre-Relay-Assertion` through to the panel (which accepts only a valid, single-use one Gatekeeper signed) — fix what `nginx -t` names and redeploy. The panel itself rewrites the domain panel, auth portal and tunnel vhosts at start, as since 4.3; each now clears a client's `X-Lamalibre-Relay-Assertion`.
|
|
44
|
-
- **No agent upgrade is needed**, and no agent half must be rebuilt. An agent half built on `@lamalibre/lamaste@4.
|
|
53
|
+
- **No agent upgrade is needed**, and no agent half must be rebuilt. An agent half built on `@lamalibre/lamaste@4.7.0` 4.4 keeps working and **never receives a user caller**: the panel sends one only after the half has answered the identity feed with protocol 1 for its installed version. A plugin gets users by shipping a version that declares `identity` with a half built on 4.5 — an update that waits for approval — then binding its user surface to a tunnel.
|
|
45
54
|
- **What changes for existing setups.** The admin forwarder no longer reaches an agent half's `/admin/app` or anything under it (on the panel `/api/<route>/app*` is the user surface). The hook preview's `inactiveRoutes` is now `userSurfaceRoutes`. Every write of `users.yml` the panel makes — creating, updating, deleting users, accepting invitations — now runs under one lock, one after the other. Deleting a user keeps a tombstone in the directory and clears the username's grants and group memberships in Gatekeeper. A registry credential must carry the `read` scope as well as `admin` (a `PUT /api/registry-credential` with an admin-only identity is refused).
|
|
46
55
|
|
|
47
56
|
### Updating Lamaste (Panel Server and Client)
|
|
@@ -93,7 +102,7 @@ exit
|
|
|
93
102
|
|
|
94
103
|
### Updating Chisel
|
|
95
104
|
|
|
96
|
-
Chisel is the tunnel server binary at `/usr/local/bin/chisel`. Lamaste pins it: server and agents run Chisel 1.12.0 (`CHISEL_RELEASE` in `@lamalibre/lamaste@4.
|
|
105
|
+
Chisel is the tunnel server binary at `/usr/local/bin/chisel`. Lamaste pins it: server and agents run Chisel 1.12.0 (`CHISEL_RELEASE` in `@lamalibre/lamaste@4.7.0`), downloaded from the fixed release URL and verified against a pinned SHA-256 before it is unpacked. **Do not replace the binary by hand.** On the server, `create-lamaste` installs it (as root) and replaces a binary that reports any other version; the panel cannot install binaries, and only logs an error at startup when the installed Chisel is not the pinned release (it then restarts Chisel on every authfile change). Each agent's sync replaces its own copy.
|
|
97
106
|
|
|
98
107
|
A new Chisel version therefore arrives with a Lamaste release that changes the pin: re-run the installer, which installs it and restarts Chisel. To check what is running:
|
|
99
108
|
|
|
@@ -107,7 +116,7 @@ Tunnel clients reconnect on their own after the brief interruption (they retry a
|
|
|
107
116
|
|
|
108
117
|
### Updating Authelia
|
|
109
118
|
|
|
110
|
-
Authelia is the authentication server binary at `/usr/local/bin/authelia`. Lamaste pins it too: Authelia 4.39.28 (`AUTHELIA_RELEASE` in `@lamalibre/lamaste@4.
|
|
119
|
+
Authelia is the authentication server binary at `/usr/local/bin/authelia`. Lamaste pins it too: Authelia 4.39.28 (`AUTHELIA_RELEASE` in `@lamalibre/lamaste@4.7.0`), downloaded by `create-lamaste` from its fixed release URL and verified against a pinned SHA-256 per architecture. A new Authelia version arrives with a Lamaste release that changes the pin — re-run the installer. It stops Authelia while it replaces the binary and starts it again.
|
|
111
120
|
|
|
112
121
|
An installed Authelia **newer** than the pin is kept, never downgraded: its database may already use a schema the pinned release cannot read, and Authelia refuses to start on a database newer than itself. If you install a newer release by hand, stop the service, replace the binary as root with a `root:root 0755` file, and start it again; check the [Authelia changelog](https://github.com/authelia/authelia/blob/master/CHANGELOG.md) first, since the configuration format may change between versions.
|
|
113
122
|
|
|
@@ -246,7 +255,7 @@ The panel server, CLI, client, docs and gatekeeper are always redeployed (files
|
|
|
246
255
|
|
|
247
256
|
### Version Pinning
|
|
248
257
|
|
|
249
|
-
Chisel and Authelia are pinned by version and SHA-256 in `packages/core/lib/src/constants.ts` (`CHISEL_RELEASE`, `AUTHELIA_RELEASE`); changing a pin means updating the version and every digest there. The downloads are verified by `downloadVerifiedChisel` / `downloadVerifiedAuthelia` (exported from `@lamalibre/lamaste@4.
|
|
258
|
+
Chisel and Authelia are pinned by version and SHA-256 in `packages/core/lib/src/constants.ts` (`CHISEL_RELEASE`, `AUTHELIA_RELEASE`); changing a pin means updating the version and every digest there. The downloads are verified by `downloadVerifiedChisel` / `downloadVerifiedAuthelia` (exported from `@lamalibre/lamaste@4.7.0`) before anything is unpacked; the server installer uses them in `packages/provisioners/server/src/lib/binaries.js`. The configuration the panel writes needs Authelia 4.38 or later.
|
|
250
259
|
|
|
251
260
|
### Automated Updates
|
|
252
261
|
|
|
@@ -268,7 +277,7 @@ sudo dpkg-reconfigure -plow unattended-upgrades
|
|
|
268
277
|
| Panel server | `/opt/lamalibre/lamaste/lamaste-serverd/` | Re-run `npx @lamalibre/create-lamaste@latest` |
|
|
269
278
|
| Panel client | `/opt/lamalibre/lamaste/lamaste-server-ui/` | Re-run `npx @lamalibre/create-lamaste@latest` |
|
|
270
279
|
| Chisel | `/usr/local/bin/chisel` | Pinned; installed by `create-lamaste` |
|
|
271
|
-
| Agents | `sudo npm install -g @lamalibre/lamaste-agent@4.
|
|
280
|
+
| Agents | `sudo npm install -g @lamalibre/lamaste-agent@4.7.0` | Upgrade after the server, then `lamaste-agent update` |
|
|
272
281
|
| Authelia | `/usr/local/bin/authelia` | Pinned; installed by `create-lamaste` (newer is kept) |
|
|
273
282
|
| nginx | System package | `sudo apt-get update && sudo apt-get upgrade` |
|
|
274
283
|
| certbot | System package | `sudo apt-get update && sudo apt-get upgrade` |
|
|
@@ -245,20 +245,24 @@ Stores the array of static sites hosted through Lamaste.
|
|
|
245
245
|
|
|
246
246
|
**Schema:** Array of site objects.
|
|
247
247
|
|
|
248
|
-
| Field | Type | Description
|
|
249
|
-
| ------------------- | --------------------- |
|
|
250
|
-
| `id` | string | UUID
|
|
251
|
-
| `name` | string | Site name (the subdomain for managed sites)
|
|
252
|
-
| `fqdn` | string | Full domain (e.g., `blog.example.com`)
|
|
253
|
-
| `type` | string | `"managed"` (subdomain of the Lamaste domain) or `"custom"` (your own domain)
|
|
254
|
-
| `spaMode` | boolean | If true, `try_files` falls back to `/index.html`
|
|
255
|
-
| `autheliaProtected` | boolean | If true, requires Authelia authentication
|
|
256
|
-
| `allowedUsers` | string[] | Authelia users allowed when protected (empty: all authenticated users)
|
|
257
|
-
| `dnsVerified` | boolean | DNS verified (always `true` for managed sites)
|
|
258
|
-
| `certIssued` | boolean | TLS certificate issued and vhost live
|
|
259
|
-
| `aliases` | string[] \| undefined | Custom sites only: hostnames answered with a 301 to `https://<fqdn>`. One certificate lineage named after `fqdn` covers all
|
|
260
|
-
| `rootPath` | string | Document root (e.g., `/var/www/lamaste/<id>/`)
|
|
261
|
-
| `createdAt` | string | ISO 8601 timestamp
|
|
248
|
+
| Field | Type | Description |
|
|
249
|
+
| ------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
250
|
+
| `id` | string | UUID |
|
|
251
|
+
| `name` | string | Site name (the subdomain for managed sites) |
|
|
252
|
+
| `fqdn` | string | Full domain (e.g., `blog.example.com`) |
|
|
253
|
+
| `type` | string | `"managed"` (subdomain of the Lamaste domain) or `"custom"` (your own domain) |
|
|
254
|
+
| `spaMode` | boolean | If true, `try_files` falls back to `/index.html` |
|
|
255
|
+
| `autheliaProtected` | boolean | If true, requires Authelia authentication |
|
|
256
|
+
| `allowedUsers` | string[] | Authelia users allowed when protected (empty: all authenticated users) |
|
|
257
|
+
| `dnsVerified` | boolean | DNS verified (always `true` for managed sites) |
|
|
258
|
+
| `certIssued` | boolean | TLS certificate issued and vhost live |
|
|
259
|
+
| `aliases` | string[] \| undefined | Custom sites only: hostnames answered with a 301 to `https://<fqdn>`. One certificate lineage named after `fqdn` covers all |
|
|
260
|
+
| `rootPath` | string | Document root (e.g., `/var/www/lamaste/<id>/`) |
|
|
261
|
+
| `createdAt` | string | ISO 8601 timestamp |
|
|
262
|
+
| `owner` | object \| undefined | `{ plugin: <route> }` — a plugin's [web surface](../04-api-reference/agent-hosted-plugins.md#web-surface); its `rootPath` is `/var/www/lamaste/apps/<route>/current` and only the plugin's workflows change it |
|
|
263
|
+
| `accessMode` | string \| undefined | A plugin-owned site's: `"authenticated"` or `"restricted"` (a `site` grant in Gatekeeper) |
|
|
264
|
+
|
|
265
|
+
Gatekeeper reads this file too (the hosts of plugins' user surfaces). Every change runs under the panel's sites lock.
|
|
262
266
|
|
|
263
267
|
**Example:**
|
|
264
268
|
|
|
@@ -818,7 +822,7 @@ Service files use per-agent names:
|
|
|
818
822
|
- macOS: `com.lamalibre.lamaste.chisel-<label>` (plist label), `~/Library/LaunchAgents/com.lamalibre.lamaste.chisel-<label>.plist` — mode 0600, because it carries `AUTH` in `EnvironmentVariables`
|
|
819
823
|
- Linux: `lamalibre-lamaste-chisel-<label>` (unit name), `~/.config/systemd/user/lamalibre-lamaste-chisel-<label>.service` — a systemd **user** unit with `EnvironmentFile=` pointing at `chisel.env`; enable lingering (`sudo loginctl enable-linger <user>`) for it to start at boot without a login
|
|
820
824
|
|
|
821
|
-
Both run `chisel client --max-retry-interval 30s https://tunnel.<domain>:443 R:127.0.0.1:<port>:127.0.0.1:<port> ...` with TLS verification and no credential in argv. They are generated by `@lamalibre/lamaste@4.
|
|
825
|
+
Both run `chisel client --max-retry-interval 30s https://tunnel.<domain>:443 R:127.0.0.1:<port>:127.0.0.1:<port> ...` with TLS verification and no credential in argv. They are generated by `@lamalibre/lamaste@4.7.0/agent` (`chisel-service.ts`) and rewritten by `lamaste-agent setup`, `update` and `sync` — do not edit them by hand. An agent carrying no tunnels has its service unloaded (Chisel cannot run without a remote).
|
|
822
826
|
|
|
823
827
|
The sync timer, which runs `<node> <installed lamaste-agent> sync --label <label> --quiet` (`<node>` is a stable path such as `/opt/homebrew/bin/node` when one on `PATH` resolves to the running binary, so a Node.js upgrade does not break it):
|
|
824
828
|
|
|
@@ -24,7 +24,7 @@ If you are reading documentation and hit an unfamiliar term, this is the place t
|
|
|
24
24
|
|
|
25
25
|
**Where it appears:**
|
|
26
26
|
|
|
27
|
-
- Enrolled from the panel (**Certificates → Enrollment Token**) and `lamaste-agent setup` (installed globally with `npm install -g @lamalibre/lamaste-agent@4.
|
|
27
|
+
- Enrolled from the panel (**Certificates → Enrollment Token**) and `lamaste-agent setup` (installed globally with `npm install -g @lamalibre/lamaste-agent@4.7.0`)
|
|
28
28
|
- Agent registry: `/etc/lamalibre/lamaste/agents.json` on the server; `~/.lamalibre/lamaste/agents/<label>/` on the agent
|
|
29
29
|
- The **Agent** column and field on the panel's Tunnels page
|
|
30
30
|
|
|
@@ -242,7 +242,7 @@ See also: [mTLS](#mtls-mutual-tls), [CA](#ca-certificate-authority), [PKCS12](#p
|
|
|
242
242
|
|
|
243
243
|
**Where it appears:**
|
|
244
244
|
|
|
245
|
-
- Generated by `lamaste-agent setup` / `update` (implementation in `@lamalibre/lamaste@4.
|
|
245
|
+
- Generated by `lamaste-agent setup` / `update` (implementation in `@lamalibre/lamaste@4.7.0/agent`)
|
|
246
246
|
- Installed to `~/Library/LaunchAgents/com.lamalibre.lamaste.chisel-<label>.plist` on the agent
|
|
247
247
|
- Manages the Chisel client process lifecycle
|
|
248
248
|
|
|
@@ -373,7 +373,7 @@ See also: [Client Certificate](#client-certificate), [CA](#ca-certificate-author
|
|
|
373
373
|
|
|
374
374
|
**Plain English:** A small scheduled job on every agent that checks with the panel every 30 seconds and adjusts the tunnel client when the agent's tunnels changed — so tunnels created, disabled or moved in the panel reach the agent without anyone running a command on it.
|
|
375
375
|
|
|
376
|
-
**Technical:** Runs `lamaste-agent sync --label <label>`, which fetches `GET /api/tunnels/agent-config` and converges the agent's Chisel client with it (relay URL, credential, pinned binary, granted remotes, running or stopped). It exists because Chisel rejects a client's whole session when one requested remote is not granted: an agent must drop a revoked tunnel promptly or all its other tunnels go dark. Requires a global install of `@lamalibre/lamaste-agent@4.
|
|
376
|
+
**Technical:** Runs `lamaste-agent sync --label <label>`, which fetches `GET /api/tunnels/agent-config` and converges the agent's Chisel client with it (relay URL, credential, pinned binary, granted remotes, running or stopped). It exists because Chisel rejects a client's whole session when one requested remote is not granted: an agent must drop a revoked tunnel promptly or all its other tunnels go dark. Requires a global install of `@lamalibre/lamaste-agent@4.7.0`.
|
|
377
377
|
|
|
378
378
|
**Where it appears:**
|
|
379
379
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Installer Flags
|
|
2
2
|
|
|
3
|
-
> CLI flags, environment variables, and exit codes for `npx @lamalibre/create-lamaste@4.
|
|
3
|
+
> CLI flags, environment variables, and exit codes for `npx @lamalibre/create-lamaste@4.7.0`.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npx @lamalibre/create-lamaste@4.
|
|
8
|
+
npx @lamalibre/create-lamaste@4.7.0 [flags]
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
The installer runs as root on a fresh Ubuntu 24.04 server. It is completely non-interactive by default — all configuration happens later through the browser-based onboarding wizard.
|
|
@@ -26,7 +26,7 @@ The installer runs as root on a fresh Ubuntu 24.04 server. It is completely non-
|
|
|
26
26
|
Prints a description of what the installer does, lists all flags, and exits with code 0. Does not modify anything on the system.
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npx @lamalibre/create-lamaste@4.
|
|
29
|
+
npx @lamalibre/create-lamaste@4.7.0 --help
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
### `--yes`, `-y`
|
|
@@ -34,7 +34,7 @@ npx @lamalibre/create-lamaste@4.5.0 --help
|
|
|
34
34
|
Skips the interactive confirmation prompt that appears before installation begins. Useful for automated deployments or scripts where you cannot press Enter.
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
npx @lamalibre/create-lamaste@4.
|
|
37
|
+
npx @lamalibre/create-lamaste@4.7.0 --yes
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Without this flag, the installer displays a banner listing all changes it will make and waits for the user to press Enter or Ctrl+C.
|
|
@@ -51,7 +51,7 @@ Skips all OS hardening tasks:
|
|
|
51
51
|
Everything else (Node.js, nginx, mTLS, panel deployment) still runs.
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
npx @lamalibre/create-lamaste@4.
|
|
54
|
+
npx @lamalibre/create-lamaste@4.7.0 --skip-harden
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
Use this if you manage your own firewall rules, already have fail2ban configured, or are running on a platform that handles security at a different layer.
|
|
@@ -61,7 +61,7 @@ Use this if you manage your own firewall rules, already have fail2ban configured
|
|
|
61
61
|
Allows the installer to run on a machine with a private or non-routable IP address (e.g., `192.168.x.x`, `10.x.x.x`). By default, the installer requires a public IP.
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
npx @lamalibre/create-lamaste@4.
|
|
64
|
+
npx @lamalibre/create-lamaste@4.7.0 --dev
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
This is useful for:
|
|
@@ -76,7 +76,7 @@ When `--dev` is active, the installer prints the detected IP with a note: `(dev
|
|
|
76
76
|
Forces the installer to run the complete installation pipeline, ignoring skip guards that would normally detect an existing installation. This is useful when an installation is in an inconsistent state and you want to ensure all components are fully deployed.
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
|
-
npx @lamalibre/create-lamaste@4.
|
|
79
|
+
npx @lamalibre/create-lamaste@4.7.0 --force-full
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
Use this if:
|
|
@@ -90,7 +90,7 @@ Use this if:
|
|
|
90
90
|
Prints a step-by-step guide for manually removing Lamaste from the server, then exits with code 0. Does not modify anything on the system.
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
-
npx @lamalibre/create-lamaste@4.
|
|
93
|
+
npx @lamalibre/create-lamaste@4.7.0 --uninstall
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
The printed guide first points to the automated removal, `sudo lamaste-server uninstall`, then covers:
|
|
@@ -207,25 +207,25 @@ Components that are always redeployed on re-run:
|
|
|
207
207
|
|
|
208
208
|
```bash
|
|
209
209
|
ssh root@203.0.113.42
|
|
210
|
-
npx @lamalibre/create-lamaste@4.
|
|
210
|
+
npx @lamalibre/create-lamaste@4.7.0
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
**Automated install (no confirmation prompt):**
|
|
214
214
|
|
|
215
215
|
```bash
|
|
216
|
-
npx @lamalibre/create-lamaste@4.
|
|
216
|
+
npx @lamalibre/create-lamaste@4.7.0 --yes
|
|
217
217
|
```
|
|
218
218
|
|
|
219
219
|
**Install without OS hardening:**
|
|
220
220
|
|
|
221
221
|
```bash
|
|
222
|
-
npx @lamalibre/create-lamaste@4.
|
|
222
|
+
npx @lamalibre/create-lamaste@4.7.0 --yes --skip-harden
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
**Test in a local VM:**
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
|
-
npx @lamalibre/create-lamaste@4.
|
|
228
|
+
npx @lamalibre/create-lamaste@4.7.0 --dev
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
**Update an existing installation:**
|
|
@@ -237,7 +237,7 @@ npx @lamalibre/create-lamaste@latest --yes
|
|
|
237
237
|
**View the uninstall guide:**
|
|
238
238
|
|
|
239
239
|
```bash
|
|
240
|
-
npx @lamalibre/create-lamaste@4.
|
|
240
|
+
npx @lamalibre/create-lamaste@4.7.0 --uninstall
|
|
241
241
|
```
|
|
242
242
|
|
|
243
243
|
## Quick Reference
|
|
@@ -34,7 +34,7 @@ A tunnel's port is also a loopback port on the relay: its vhost proxies to `127.
|
|
|
34
34
|
| 9292 | IP-based panel listener |
|
|
35
35
|
| 9294 | Gatekeeper |
|
|
36
36
|
|
|
37
|
-
A tunnel on one of them would publish that internal service on a public hostname. For the panel that is an administrator takeover, not a leak: the panel trusts the client-certificate headers nginx sets. `RESERVED_TUNNEL_PORTS` in `@lamalibre/lamaste@4.
|
|
37
|
+
A tunnel on one of them would publish that internal service on a public hostname. For the panel that is an administrator takeover, not a leak: the panel trusts the client-certificate headers nginx sets. `RESERVED_TUNNEL_PORTS` in `@lamalibre/lamaste@4.7.0` is enforced by the request schema, inside the tunnel workflow, and again when the Chisel grants are rendered. Tunnel ports must also be 1024–65535.
|
|
38
38
|
|
|
39
39
|
## Systemd Units
|
|
40
40
|
|
|
@@ -217,7 +217,7 @@ The agent's sync timer applies tunnel changes within about 30 seconds. If that d
|
|
|
217
217
|
lamaste-agent update # apply now and (re)install the sync timer
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
`update` needs the agent installed globally (`npm install -g @lamalibre/lamaste-agent@4.
|
|
220
|
+
`update` needs the agent installed globally (`npm install -g @lamalibre/lamaste-agent@4.7.0`); an agent originally set up with `npx` must be installed first.
|
|
221
221
|
|
|
222
222
|
**Cause 3: The agent does not carry the tunnel.**
|
|
223
223
|
|
|
@@ -320,7 +320,7 @@ ls -la /usr/local/bin/authelia
|
|
|
320
320
|
| Missing `panel.json` | `Config file not found` | Re-run installer or create the file manually |
|
|
321
321
|
| Invalid JSON in `panel.json` | `contains invalid JSON` | Fix the JSON syntax |
|
|
322
322
|
| Port 3100 in use | `EADDRINUSE` | Find and stop the conflicting process: `sudo ss -tlnp sport = :3100` |
|
|
323
|
-
| Missing Node.js modules | `Cannot find module` | Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
323
|
+
| Missing Node.js modules | `Cannot find module` | Re-run the installer (`npx @lamalibre/create-lamaste@4.7.0 --yes`); `/opt/lamalibre/lamaste` is root-owned and redeployed as a whole |
|
|
324
324
|
| Permission denied writing state | `EACCES` under `/etc/lamalibre/lamaste` | Re-run the installer; the redeploy re-applies the ownership of the config and PKI directories |
|
|
325
325
|
|
|
326
326
|
### chisel fails to start
|
|
@@ -329,7 +329,7 @@ ls -la /usr/local/bin/authelia
|
|
|
329
329
|
|
|
330
330
|
| Cause | Log Message | Fix |
|
|
331
331
|
| -------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
332
|
-
| Binary missing | `exec format error` or `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
332
|
+
| Binary missing | `exec format error` or `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.7.0 --yes`) — it installs the pinned, checksum-verified release for the server's architecture; the panel cannot install binaries |
|
|
333
333
|
| Not the pinned release | (panel log) `The installed chisel is not the pinned release — run create-lamaste ...` | Re-run the installer. Until then the panel restarts Chisel on every authfile change |
|
|
334
334
|
| Authfile or key unreadable | `permission denied` on `chisel-users` or `chisel-server.key` | Both must be `0640 lamaste:lamaste-chisel` and the unit `Group=lamaste-chisel`; restart the panel, which re-applies the authfile's. If the group, the unit or the key's ownership is wrong, re-run the installer in redeploy mode |
|
|
335
335
|
| Stopped by the panel | (panel log) `Chisel stopped: ...`; unit disabled, `chisel-failed-closed` present | Reconciliation failed closed; see [Tunnel Client Cannot Connect](#tunnel-client-cannot-connect), Cause 1 |
|
|
@@ -343,7 +343,7 @@ ls -la /usr/local/bin/authelia
|
|
|
343
343
|
| --------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
344
344
|
| Invalid `configuration.yml` | `configuration: error` | Check YAML syntax with `authelia validate-configuration --config /etc/authelia/configuration.yml` |
|
|
345
345
|
| Missing `users.yml` | `cannot open file` | Create an initial users file (see [Config Files](config-files.md)) |
|
|
346
|
-
| Binary missing | `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
346
|
+
| Binary missing | `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.7.0 --yes`); it installs the pinned release |
|
|
347
347
|
| Wrong permissions | `permission denied` | Authelia runs as `lamaste-authelia`: `/etc/authelia` must be `lamaste:lamaste-authelia 2770`, `configuration.yml` `0640`, `users.yml` `0660`, `db.sqlite3` owned by `lamaste-authelia`. Re-run the installer to re-apply (a root-owned `/etc/authelia` from an older version is converted), or see [Config Files](config-files.md#file-permissions-table) |
|
|
348
348
|
| Database newer than binary | storage schema version error at startup | A newer Authelia ran against this database and was replaced by an older one; the installer never downgrades an installed Authelia, so reinstall that newer release by hand |
|
|
349
349
|
|
|
@@ -516,14 +516,14 @@ sudo systemctl restart authelia
|
|
|
516
516
|
|
|
517
517
|
## Onboarding Fails: "Chisel is not installed" / "Authelia is not installed"
|
|
518
518
|
|
|
519
|
-
**Symptom:** The **Starting Chisel** or **Configuring Authelia** provisioning task fails with "Chisel is not installed. Run `npx @lamalibre/create-lamaste@4.
|
|
519
|
+
**Symptom:** The **Starting Chisel** or **Configuring Authelia** provisioning task fails with "Chisel is not installed. Run `npx @lamalibre/create-lamaste@4.7.0` on the server to repair the installation." (or the same for Authelia).
|
|
520
520
|
|
|
521
521
|
**Cause:** Onboarding downloads nothing: the installer installs both binaries (pinned releases), their systemd units and the `lamaste-authelia` account. The binary at `/usr/local/bin/chisel` or `/usr/local/bin/authelia` is missing — the installer was interrupted, or the file was removed.
|
|
522
522
|
|
|
523
523
|
**Fix:** Re-run the installer on the server, then start provisioning again from the wizard:
|
|
524
524
|
|
|
525
525
|
```bash
|
|
526
|
-
npx @lamalibre/create-lamaste@4.
|
|
526
|
+
npx @lamalibre/create-lamaste@4.7.0 --yes
|
|
527
527
|
```
|
|
528
528
|
|
|
529
529
|
If provisioning then fails writing Authelia's configuration with `/etc/authelia is not writable by the panel — run create-lamaste to repair the installation`, the directory's ownership is wrong; the same command repairs it.
|
|
@@ -538,7 +538,7 @@ If provisioning then fails writing Authelia's configuration with `/etc/authelia
|
|
|
538
538
|
|
|
539
539
|
**Fix:**
|
|
540
540
|
|
|
541
|
-
1. Re-run the installer so the helper matches the panel: `npx @lamalibre/create-lamaste@4.
|
|
541
|
+
1. Re-run the installer so the helper matches the panel: `npx @lamalibre/create-lamaste@4.7.0 --yes`
|
|
542
542
|
2. If it persists on a current install, it is a bug: the vhost generators (`packages/server/daemon/src/lib/nginx.js`) and the allow-list (`packages/provisioners/server/scripts/lamaste-priv`) must change together — `npm test` checks every generated vhost against the allow-list. Do not work around it by editing files in `/etc/nginx` by hand.
|
|
543
543
|
|
|
544
544
|
`sudo: a password is required` for `lamaste-priv` means the helper or the sudoers file is missing or outdated: re-run the installer.
|
|
@@ -621,7 +621,7 @@ df -h /
|
|
|
621
621
|
|
|
622
622
|
**Cause 3: The web root is not writable by the panel (`EACCES`).**
|
|
623
623
|
|
|
624
|
-
The panel writes `/var/www/lamaste` itself: it must be `lamaste:www-data`, directories `2750`, files `0640`. An install from before this layout had it owned by `www-data`. Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
624
|
+
The panel writes `/var/www/lamaste` itself: it must be `lamaste:www-data`, directories `2750`, files `0640`. An install from before this layout had it owned by `www-data`. Re-run the installer (`npx @lamalibre/create-lamaste@4.7.0 --yes`); the redeploy converts the tree.
|
|
625
625
|
|
|
626
626
|
---
|
|
627
627
|
|