@lamalibre/create-lamaste 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +118 -0
- package/README.md +114 -0
- package/bin/create-lamaste.js +15 -0
- package/package.json +54 -0
- package/scripts/bundle-vendor.js +110 -0
- package/scripts/lamaste-cert-info +62 -0
- package/scripts/lamaste-certbot +96 -0
- package/scripts/lamaste-priv +693 -0
- package/src/index.js +646 -0
- package/src/lib/accounts.js +86 -0
- package/src/lib/binaries.js +137 -0
- package/src/lib/cert-help-page.js +160 -0
- package/src/lib/env.js +132 -0
- package/src/lib/http-redirect.js +38 -0
- package/src/lib/ownership.js +231 -0
- package/src/lib/relay-services.js +103 -0
- package/src/lib/secrets.js +19 -0
- package/src/lib/service-config.js +311 -0
- package/src/lib/summary.js +131 -0
- package/src/lib/wrappers.js +63 -0
- package/src/tasks/gatekeeper.js +233 -0
- package/src/tasks/harden.js +293 -0
- package/src/tasks/mtls.js +193 -0
- package/src/tasks/nginx.js +265 -0
- package/src/tasks/node.js +110 -0
- package/src/tasks/panel.js +408 -0
- package/src/tasks/redeploy.js +438 -0
- package/vendor/docs/00-introduction/how-it-works.md +447 -0
- package/vendor/docs/00-introduction/quickstart.md +472 -0
- package/vendor/docs/00-introduction/what-is-lamaste.md +112 -0
- package/vendor/docs/01-concepts/authentication.md +464 -0
- package/vendor/docs/01-concepts/authorization.md +242 -0
- package/vendor/docs/01-concepts/certificates.md +452 -0
- package/vendor/docs/01-concepts/dns-and-domains.md +343 -0
- package/vendor/docs/01-concepts/mtls.md +490 -0
- package/vendor/docs/01-concepts/nginx-reverse-proxy.md +540 -0
- package/vendor/docs/01-concepts/security-model.md +600 -0
- package/vendor/docs/01-concepts/tickets.md +414 -0
- package/vendor/docs/01-concepts/tunneling.md +367 -0
- package/vendor/docs/02-guides/agent-setup.md +194 -0
- package/vendor/docs/02-guides/certificate-management.md +341 -0
- package/vendor/docs/02-guides/cloud-provisioning.md +406 -0
- package/vendor/docs/02-guides/desktop-app-setup.md +226 -0
- package/vendor/docs/02-guides/disaster-recovery.md +464 -0
- package/vendor/docs/02-guides/first-tunnel.md +230 -0
- package/vendor/docs/02-guides/installation.md +393 -0
- package/vendor/docs/02-guides/managing-users.md +255 -0
- package/vendor/docs/02-guides/onboarding.md +244 -0
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +375 -0
- package/vendor/docs/02-guides/static-sites.md +364 -0
- package/vendor/docs/03-architecture/e2e-three-vm-sequences.md +457 -0
- package/vendor/docs/03-architecture/installer-flow.md +151 -0
- package/vendor/docs/03-architecture/installer.md +445 -0
- package/vendor/docs/03-architecture/management-flow.md +288 -0
- package/vendor/docs/03-architecture/nginx-configuration.md +830 -0
- package/vendor/docs/03-architecture/onboarding-flow.md +164 -0
- package/vendor/docs/03-architecture/overview.md +541 -0
- package/vendor/docs/03-architecture/panel-client.md +416 -0
- package/vendor/docs/03-architecture/panel-server.md +695 -0
- package/vendor/docs/03-architecture/state-management.md +529 -0
- package/vendor/docs/03-architecture/system-overview.md +167 -0
- package/vendor/docs/04-api-reference/certificates.md +1141 -0
- package/vendor/docs/04-api-reference/gatekeeper.md +592 -0
- package/vendor/docs/04-api-reference/onboarding.md +473 -0
- package/vendor/docs/04-api-reference/overview.md +404 -0
- package/vendor/docs/04-api-reference/services.md +267 -0
- package/vendor/docs/04-api-reference/settings.md +343 -0
- package/vendor/docs/04-api-reference/sites.md +716 -0
- package/vendor/docs/04-api-reference/system.md +268 -0
- package/vendor/docs/04-api-reference/tickets.md +618 -0
- package/vendor/docs/04-api-reference/tunnels.md +417 -0
- package/vendor/docs/04-api-reference/users.md +333 -0
- package/vendor/docs/05-operations/backup-and-restore.md +342 -0
- package/vendor/docs/05-operations/monitoring.md +285 -0
- package/vendor/docs/05-operations/uninstalling.md +344 -0
- package/vendor/docs/05-operations/upgrades.md +270 -0
- package/vendor/docs/06-reference/config-files.md +1080 -0
- package/vendor/docs/06-reference/glossary.md +528 -0
- package/vendor/docs/06-reference/installer-flags.md +260 -0
- package/vendor/docs/06-reference/ports-and-services.md +244 -0
- package/vendor/docs/06-reference/troubleshooting.md +665 -0
- package/vendor/docs/_index.json +233 -0
- package/vendor/docs/gatekeeper-design.md +953 -0
- package/vendor/docs/package.json +15 -0
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +641 -0
- package/vendor/gatekeeper/dist/boot.d.ts +1 -0
- package/vendor/gatekeeper/dist/boot.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/boot.js +17 -0
- package/vendor/gatekeeper/dist/boot.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js +33 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js +110 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js +98 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts +3 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.js +45 -0
- package/vendor/gatekeeper/dist/cli/index.js.map +1 -0
- package/vendor/gatekeeper/dist/index.d.ts +9 -0
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/index.js +13 -0
- package/vendor/gatekeeper/dist/index.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.js +42 -0
- package/vendor/gatekeeper/dist/lib/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts +15 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js +19 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts +82 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.js +79 -0
- package/vendor/gatekeeper/dist/lib/constants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts +32 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.js +314 -0
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts +10 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.js +247 -0
- package/vendor/gatekeeper/dist/lib/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts +17 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.js +79 -0
- package/vendor/gatekeeper/dist/lib/migration.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/state-db.js +154 -0
- package/vendor/gatekeeper/dist/lib/state-db.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts +21 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.js +151 -0
- package/vendor/gatekeeper/dist/lib/templates.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts +178 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.js +2 -0
- package/vendor/gatekeeper/dist/lib/types.js.map +1 -0
- package/vendor/gatekeeper/dist/server/index.d.ts +15 -0
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/index.js +251 -0
- package/vendor/gatekeeper/dist/server/index.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts +7 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js +17 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js +279 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts +13 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +249 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js +112 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js +139 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js.map +1 -0
- package/vendor/gatekeeper/package.json +49 -0
- package/vendor/server/bin/lamaste-server.js +204 -0
- package/vendor/server/package.json +31 -0
- package/vendor/server/src/commands/certs.js +224 -0
- package/vendor/server/src/commands/chisel.js +132 -0
- package/vendor/server/src/commands/logs.js +49 -0
- package/vendor/server/src/commands/plugins.js +321 -0
- package/vendor/server/src/commands/reset-admin.js +478 -0
- package/vendor/server/src/commands/restart.js +94 -0
- package/vendor/server/src/commands/sites.js +257 -0
- package/vendor/server/src/commands/status.js +158 -0
- package/vendor/server/src/commands/tunnels.js +365 -0
- package/vendor/server/src/commands/uninstall.js +326 -0
- package/vendor/server/src/config.js +38 -0
- package/vendor/server/src/exec.js +26 -0
- package/vendor/server/src/logger.js +39 -0
- package/vendor/server/src/ndjson.js +56 -0
- package/vendor/server/src/panel-api.js +85 -0
- package/vendor/server/src/state.js +45 -0
- package/vendor/server-ui/dist/assets/index-B0nWuUyL.js +257 -0
- package/vendor/server-ui/dist/assets/index-BqWWFlTU.css +1 -0
- package/vendor/server-ui/dist/index.html +13 -0
- package/vendor/serverd/package.json +44 -0
- package/vendor/serverd/src/boot.js +13 -0
- package/vendor/serverd/src/index.js +191 -0
- package/vendor/serverd/src/lib/app-error.js +14 -0
- package/vendor/serverd/src/lib/authelia.js +85 -0
- package/vendor/serverd/src/lib/certbot.js +74 -0
- package/vendor/serverd/src/lib/chisel-args.js +6 -0
- package/vendor/serverd/src/lib/chisel-reconcile.js +232 -0
- package/vendor/serverd/src/lib/chisel-runtime.js +46 -0
- package/vendor/serverd/src/lib/chisel-users.js +109 -0
- package/vendor/serverd/src/lib/chisel.js +81 -0
- package/vendor/serverd/src/lib/config.js +190 -0
- package/vendor/serverd/src/lib/constants.js +8 -0
- package/vendor/serverd/src/lib/csr-signing.js +331 -0
- package/vendor/serverd/src/lib/enrollment.js +302 -0
- package/vendor/serverd/src/lib/files.js +19 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +135 -0
- package/vendor/serverd/src/lib/invite-page.js +281 -0
- package/vendor/serverd/src/lib/ip-utils.js +79 -0
- package/vendor/serverd/src/lib/migrations/state/0001_enrollment_tokens.sql +17 -0
- package/vendor/serverd/src/lib/migrations/state/0002_tickets.sql +70 -0
- package/vendor/serverd/src/lib/migrations/state/0003_plugins.sql +15 -0
- package/vendor/serverd/src/lib/migrations/state/0004_agents.sql +19 -0
- package/vendor/serverd/src/lib/mtls.js +795 -0
- package/vendor/serverd/src/lib/nginx.js +1090 -0
- package/vendor/serverd/src/lib/pki-paths.js +41 -0
- package/vendor/serverd/src/lib/pki-sign.js +103 -0
- package/vendor/serverd/src/lib/plugins.js +538 -0
- package/vendor/serverd/src/lib/push-install.js +390 -0
- package/vendor/serverd/src/lib/revocation.js +112 -0
- package/vendor/serverd/src/lib/services.js +131 -0
- package/vendor/serverd/src/lib/session.js +151 -0
- package/vendor/serverd/src/lib/state-db.js +130 -0
- package/vendor/serverd/src/lib/state.js +140 -0
- package/vendor/serverd/src/lib/storage.js +63 -0
- package/vendor/serverd/src/lib/system-stats.js +58 -0
- package/vendor/serverd/src/lib/tickets.js +1556 -0
- package/vendor/serverd/src/lib/totp.js +76 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +41 -0
- package/vendor/serverd/src/lib/user-access-session.js +142 -0
- package/vendor/serverd/src/lib/user-access.js +52 -0
- package/vendor/serverd/src/middleware/errors.js +63 -0
- package/vendor/serverd/src/middleware/mtls.js +120 -0
- package/vendor/serverd/src/middleware/onboarding-guard.js +30 -0
- package/vendor/serverd/src/middleware/role-guard.js +58 -0
- package/vendor/serverd/src/middleware/twofa-session.js +65 -0
- package/vendor/serverd/src/middleware/user-access-session.js +52 -0
- package/vendor/serverd/src/routes/enrollment.js +120 -0
- package/vendor/serverd/src/routes/health.js +22 -0
- package/vendor/serverd/src/routes/invite.js +163 -0
- package/vendor/serverd/src/routes/management/agents.js +182 -0
- package/vendor/serverd/src/routes/management/certs.js +911 -0
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +160 -0
- package/vendor/serverd/src/routes/management/identity.js +107 -0
- package/vendor/serverd/src/routes/management/invitations.js +166 -0
- package/vendor/serverd/src/routes/management/logs.js +218 -0
- package/vendor/serverd/src/routes/management/plugins.js +560 -0
- package/vendor/serverd/src/routes/management/services.js +63 -0
- package/vendor/serverd/src/routes/management/settings.js +325 -0
- package/vendor/serverd/src/routes/management/sites.js +522 -0
- package/vendor/serverd/src/routes/management/storage.js +192 -0
- package/vendor/serverd/src/routes/management/system.js +201 -0
- package/vendor/serverd/src/routes/management/tickets.js +457 -0
- package/vendor/serverd/src/routes/management/tunnels.js +709 -0
- package/vendor/serverd/src/routes/management/users.js +377 -0
- package/vendor/serverd/src/routes/management.js +36 -0
- package/vendor/serverd/src/routes/onboarding/dns.js +101 -0
- package/vendor/serverd/src/routes/onboarding/domain.js +42 -0
- package/vendor/serverd/src/routes/onboarding/index.js +18 -0
- package/vendor/serverd/src/routes/onboarding/provision.js +327 -0
- package/vendor/serverd/src/routes/onboarding/status.js +12 -0
- package/vendor/serverd/src/routes/plugin-router.js +79 -0
- package/vendor/serverd/src/routes/user-access.js +389 -0
|
@@ -0,0 +1,1080 @@
|
|
|
1
|
+
# Config Files
|
|
2
|
+
|
|
3
|
+
> Complete reference for every configuration and state file Lamaste uses.
|
|
4
|
+
|
|
5
|
+
## File Overview
|
|
6
|
+
|
|
7
|
+
| File | Format | Owner | Mode | Purpose |
|
|
8
|
+
| ---------------------------------------------------------- | ---------- | ------------------------ | ---- | ------------------------------------------------------------------------------- |
|
|
9
|
+
| `/etc/lamalibre/lamaste/panel.json` | JSON | lamaste:lamaste | 0600 | Panel server configuration |
|
|
10
|
+
| `/etc/lamalibre/lamaste/tunnels.json` | JSON | lamaste:lamaste | 0600 | Tunnel definitions |
|
|
11
|
+
| `/etc/lamalibre/lamaste/sites.json` | JSON | lamaste:lamaste | 0600 | Static site definitions |
|
|
12
|
+
| `/etc/lamalibre/lamaste/chisel-credentials.json` | JSON | lamaste:lamaste | 0600 | Per-agent Chisel credentials (source of truth for the authfile) |
|
|
13
|
+
| `/etc/lamalibre/lamaste/chisel-users` | JSON | lamaste:lamaste-chisel | 0640 | Chisel `--authfile`: per-agent credentials and port grants (rendered) |
|
|
14
|
+
| `/etc/lamalibre/lamaste/chisel-sentinel` | text | lamaste:lamaste | 0600 | Password of the `lamaste-no-grants` sentinel user |
|
|
15
|
+
| `/etc/lamalibre/lamaste/chisel-server.key` | PEM | lamaste:lamaste-chisel | 0640 | Chisel SSH host key (`--keyfile`), generated by the panel at onboarding |
|
|
16
|
+
| `/etc/authelia/configuration.yml` | YAML | lamaste:lamaste-authelia | 0640 | Authelia server configuration |
|
|
17
|
+
| `/etc/authelia/users.yml` | YAML | lamaste:lamaste-authelia | 0660 | User database (Authelia rewrites it on a password change) |
|
|
18
|
+
| `/etc/authelia/.secrets.json` | JSON | lamaste:lamaste-authelia | 0600 | Authelia secrets (panel only) |
|
|
19
|
+
| `/etc/lamalibre/lamaste/ticket-scopes.json` | JSON | lamaste:lamaste | 0600 | Ticket scope registry |
|
|
20
|
+
| `/etc/lamalibre/lamaste/tickets.json` | JSON | lamaste:lamaste | 0600 | Ticket and session store |
|
|
21
|
+
| `/etc/lamalibre/lamaste/invitations.json` | JSON | lamaste:lamaste | 0600 | Pending user invitations |
|
|
22
|
+
| `/etc/lamalibre/lamaste/plugins.json` | JSON | lamaste:lamaste | 0600 | Plugin registry |
|
|
23
|
+
| `/etc/lamalibre/lamaste/storage-config.json` | JSON | lamaste:lamaste | 0600 | Storage server registry and plugin bindings (credentials AES-256-GCM encrypted) |
|
|
24
|
+
| `/etc/lamalibre/lamaste/storage-master.key` | Binary | lamaste:lamaste | 0600 | 32-byte master key for storage credential encryption |
|
|
25
|
+
| `/etc/lamalibre/lamaste/groups.json` | JSON | lamaste:lamaste | 0600 | Lamaste group definitions and membership |
|
|
26
|
+
| `/etc/lamalibre/lamaste/access-grants.json` | JSON | lamaste:lamaste | 0600 | Generic access grants (principal → resource) |
|
|
27
|
+
| `/etc/lamalibre/lamaste/gatekeeper.json` | JSON | lamaste:lamaste | 0600 | Gatekeeper settings (cache TTL, admin contact, logging) |
|
|
28
|
+
| `/etc/lamalibre/lamaste/access-request-log.json` | JSON | lamaste:lamaste | 0600 | Optional denied access log |
|
|
29
|
+
| `/etc/lamalibre/lamaste/pki/enrollment-tokens.json` | JSON | lamaste:lamaste | 0600 | One-time enrollment tokens for hardware-bound enrollment |
|
|
30
|
+
| `/etc/lamalibre/lamaste/pki/revoked.json` | JSON | lamaste:lamaste | 0600 | Revoked certificate serial numbers |
|
|
31
|
+
| `/etc/lamalibre/lamaste/pki/agents/registry.json` | JSON | lamaste:lamaste | 0600 | Agent certificate metadata |
|
|
32
|
+
| `/etc/nginx/sites-available/lamalibre-lamaste-*` | nginx conf | root:root | 0644 | Vhost configurations (the panel's are installed by `lamaste-priv`) |
|
|
33
|
+
| `/etc/nginx/snippets/lamalibre-lamaste-mtls.conf` | nginx conf | root:root | 0644 | mTLS snippet |
|
|
34
|
+
| `/etc/nginx/snippets/lamalibre-lamaste-authz-cache.conf` | nginx conf | root:root | 0644 | Gatekeeper proxy_cache zone |
|
|
35
|
+
| `/etc/systemd/system/lamalibre-lamaste-gatekeeper.service` | systemd | root:root | 0644 | Gatekeeper systemd unit |
|
|
36
|
+
| `/etc/systemd/system/chisel.service` | systemd | root:root | 0644 | Chisel unit, written by `create-lamaste` |
|
|
37
|
+
| `/etc/systemd/system/authelia.service` | systemd | root:root | 0644 | Authelia unit, written by `create-lamaste` |
|
|
38
|
+
| `~/.lamalibre/lamaste/servers.json` | JSON | user | 0600 | Desktop app server registry |
|
|
39
|
+
| `~/.lamalibre/lamaste/agents.json` | JSON | user | 0600 | Multi-agent registry |
|
|
40
|
+
| `~/.lamalibre/lamaste/agents/<label>/config.json` | JSON | user | 0600 | Per-agent configuration |
|
|
41
|
+
| `~/.lamalibre/lamaste/agents/<label>/client.p12` | PKCS#12 | user | 0600 | Per-agent mTLS certificate |
|
|
42
|
+
| `~/.lamalibre/lamaste/agents/<label>/ca.crt` | PEM | user | 0644 | Per-agent CA certificate |
|
|
43
|
+
| `~/.lamalibre/lamaste/agents/<label>/chisel.json` | JSON | user | 0600 | Per-agent Chisel credential (source of truth for the service) |
|
|
44
|
+
| `~/.lamalibre/lamaste/agents/<label>/chisel.env` | env file | user | 0600 | Linux only: `AUTH=` for the systemd unit's `EnvironmentFile=` |
|
|
45
|
+
| `~/.lamalibre/lamaste/agents/<label>/` | directory | user | 0700 | Per-agent data directory |
|
|
46
|
+
| `~/.lamalibre/lamaste/agents/<label>/sync-state.json` | JSON | user | 0600 | Outcome of the last `lamaste-agent sync` |
|
|
47
|
+
| `~/.lamalibre/lamaste/agents/<label>/logs/` | directory | user | 0700 | Per-agent Chisel and sync log files |
|
|
48
|
+
| `~/.lamalibre/lamaste/agent.json` | JSON | user | 0600 | Legacy single-server config |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## `/etc/lamalibre/lamaste/panel.json`
|
|
53
|
+
|
|
54
|
+
The primary configuration file for the panel server. Created by the installer, updated during onboarding and tunnel management.
|
|
55
|
+
|
|
56
|
+
**Schema:**
|
|
57
|
+
|
|
58
|
+
| Field | Type | Required | Default | Description |
|
|
59
|
+
| ------------------------ | -------------- | -------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `ip` | string | Yes | — | Server public IP address |
|
|
61
|
+
| `domain` | string \| null | Yes | `null` | Base domain (set during onboarding) |
|
|
62
|
+
| `serverId` | string | No | — | Auto-generated UUIDv4, used as bucket prefix for multi-server storage isolation |
|
|
63
|
+
| `email` | string \| null | Yes | `null` | Admin email for Let's Encrypt (set during onboarding) |
|
|
64
|
+
| `dataDir` | string | Yes | `/etc/lamalibre/lamaste` | Path to data/state directory |
|
|
65
|
+
| `staticDir` | string | No | — | Path to lamaste-server-ui dist directory |
|
|
66
|
+
| `maxSiteSize` | number | No | `524288000` | Max static site upload size in bytes (500 MB) |
|
|
67
|
+
| `adminAuthMode` | string | No | `"p12"` | `"p12"` or `"hardware-bound"`. When `"hardware-bound"`, P12 download and rotation are disabled; admin authenticates via Keychain-backed certificate. |
|
|
68
|
+
| `panel2fa` | object | No | — | Built-in TOTP 2FA configuration (see sub-fields below) |
|
|
69
|
+
| `panel2fa.enabled` | boolean | No | `false` | Whether 2FA is active for admin panel access |
|
|
70
|
+
| `panel2fa.secret` | string \| null | No | `null` | Base32-encoded TOTP secret |
|
|
71
|
+
| `panel2fa.setupComplete` | boolean | No | `false` | Whether the 2FA setup flow has been confirmed |
|
|
72
|
+
| `sessionSecret` | string | No | — | HMAC key for signing session cookies (auto-generated during 2FA setup) |
|
|
73
|
+
| `onboarding.status` | enum | Yes | `FRESH` | Current onboarding state |
|
|
74
|
+
|
|
75
|
+
**Onboarding status values:**
|
|
76
|
+
|
|
77
|
+
| Value | Meaning |
|
|
78
|
+
| -------------- | --------------------------------------------------- |
|
|
79
|
+
| `FRESH` | No onboarding started — shows onboarding wizard |
|
|
80
|
+
| `DOMAIN_SET` | Domain and email entered, awaiting DNS verification |
|
|
81
|
+
| `DNS_READY` | DNS verified, ready to provision |
|
|
82
|
+
| `PROVISIONING` | Stack provisioning in progress |
|
|
83
|
+
| `COMPLETED` | Onboarding complete — shows management UI |
|
|
84
|
+
|
|
85
|
+
**Example (fresh install):**
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"ip": "203.0.113.42",
|
|
90
|
+
"domain": null,
|
|
91
|
+
"email": null,
|
|
92
|
+
"dataDir": "/etc/lamalibre/lamaste",
|
|
93
|
+
"staticDir": "/opt/lamalibre/lamaste/lamaste-server-ui/dist",
|
|
94
|
+
"onboarding": {
|
|
95
|
+
"status": "FRESH"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Example (after onboarding):**
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"ip": "203.0.113.42",
|
|
105
|
+
"domain": "example.com",
|
|
106
|
+
"email": "admin@example.com",
|
|
107
|
+
"dataDir": "/etc/lamalibre/lamaste",
|
|
108
|
+
"staticDir": "/opt/lamalibre/lamaste/lamaste-server-ui/dist",
|
|
109
|
+
"maxSiteSize": 524288000,
|
|
110
|
+
"onboarding": {
|
|
111
|
+
"status": "COMPLETED"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Example (with 2FA enabled):**
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"ip": "203.0.113.42",
|
|
121
|
+
"domain": "example.com",
|
|
122
|
+
"email": "admin@example.com",
|
|
123
|
+
"dataDir": "/etc/lamalibre/lamaste",
|
|
124
|
+
"staticDir": "/opt/lamalibre/lamaste/lamaste-server-ui/dist",
|
|
125
|
+
"maxSiteSize": 524288000,
|
|
126
|
+
"onboarding": {
|
|
127
|
+
"status": "COMPLETED"
|
|
128
|
+
},
|
|
129
|
+
"panel2fa": {
|
|
130
|
+
"enabled": true,
|
|
131
|
+
"secret": "JBSWY3DPEHPK3PXP...",
|
|
132
|
+
"setupComplete": true
|
|
133
|
+
},
|
|
134
|
+
"sessionSecret": "a1b2c3d4..."
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Config resolution order:**
|
|
139
|
+
|
|
140
|
+
1. `LAMALIBRE_LAMASTE_CONFIG` environment variable (if set)
|
|
141
|
+
2. In development (`NODE_ENV=development` or `NODE_ENV` unset): `<package-root>/dev/panel.json`
|
|
142
|
+
3. In production (`NODE_ENV=production`): `/etc/lamalibre/lamaste/panel.json`
|
|
143
|
+
|
|
144
|
+
> **Note:** The systemd service unit sets `CONFIG_FILE` in the environment, but the panel server code reads `LAMALIBRE_LAMASTE_CONFIG`. The systemd variable `CONFIG_FILE` is not used by the application. In production deployments this has no effect because the code falls back to `/etc/lamalibre/lamaste/panel.json` when `LAMALIBRE_LAMASTE_CONFIG` is unset and `NODE_ENV=production`.
|
|
145
|
+
|
|
146
|
+
**Write pattern:** Atomic — writes to `.tmp` file then `rename()`.
|
|
147
|
+
|
|
148
|
+
**Validated with:** Zod schema in `packages/lamaste-serverd/src/lib/config.js`.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## `/etc/lamalibre/lamaste/tunnels.json`
|
|
153
|
+
|
|
154
|
+
Stores the array of configured tunnels. Created automatically when the first tunnel is added.
|
|
155
|
+
|
|
156
|
+
**Schema:** Array of tunnel objects.
|
|
157
|
+
|
|
158
|
+
| Field | Type | Description |
|
|
159
|
+
| --------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
160
|
+
| `id` | string | UUID |
|
|
161
|
+
| `subdomain` | string | Subdomain name (e.g., `myapp`) |
|
|
162
|
+
| `fqdn` | string | Full domain (e.g., `myapp.example.com`) |
|
|
163
|
+
| `port` | number | Port forwarded between `127.0.0.1` on the server and `127.0.0.1` on the carrying agent |
|
|
164
|
+
| `description` | string \| null | Optional description (max 200 characters) |
|
|
165
|
+
| `type` | string | `"app"` (default), `"panel"` (agent web panel), or `"plugin"` |
|
|
166
|
+
| `enabled` | boolean | Whether the tunnel is active |
|
|
167
|
+
| `accessMode` | string \| undefined | `"public"`, `"authenticated"`, or `"restricted"`. Controls whether nginx skips auth, requires Authelia login only, or requires Authelia login plus a Gatekeeper grant. Absent for panel tunnels. |
|
|
168
|
+
| `agentLabel` | string \| undefined | The agent that carries the tunnel. Only that agent receives it in `agent-config`, and only its Chisel user is granted the port. Absent only on a legacy tunnel that could not be bound at upgrade (carried by no agent until an administrator assigns it). |
|
|
169
|
+
| `maxBodySizeMb` | number \| undefined | Largest request body in MiB (1–10240, default 10), rendered as `client_max_body_size`. Absent on panel tunnels and on tunnels created before the setting existed, which keep nginx's 1 MiB until reconfigured. |
|
|
170
|
+
| `createdAt` | string | ISO 8601 timestamp |
|
|
171
|
+
|
|
172
|
+
Tunnels of type `plugin` also carry `pluginName` and `pluginRoute`.
|
|
173
|
+
|
|
174
|
+
**Example:**
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
[
|
|
178
|
+
{
|
|
179
|
+
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
180
|
+
"subdomain": "myapp",
|
|
181
|
+
"fqdn": "myapp.example.com",
|
|
182
|
+
"port": 3000,
|
|
183
|
+
"description": "My web app",
|
|
184
|
+
"type": "app",
|
|
185
|
+
"accessMode": "restricted",
|
|
186
|
+
"agentLabel": "laptop",
|
|
187
|
+
"maxBodySizeMb": 10,
|
|
188
|
+
"enabled": true,
|
|
189
|
+
"createdAt": "2026-03-13T10:30:45.000Z"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
|
|
193
|
+
"subdomain": "api",
|
|
194
|
+
"fqdn": "api.example.com",
|
|
195
|
+
"port": 8080,
|
|
196
|
+
"description": null,
|
|
197
|
+
"type": "app",
|
|
198
|
+
"accessMode": "authenticated",
|
|
199
|
+
"agentLabel": "build-server",
|
|
200
|
+
"maxBodySizeMb": 100,
|
|
201
|
+
"enabled": true,
|
|
202
|
+
"createdAt": "2026-03-13T11:00:00.000Z"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Ownership reconciliation:** On startup the panel binds tunnels without an `agentLabel` (written by versions before tunnel ownership): an `agent-<label>` panel tunnel only to the agent it names, when that agent is active; any other tunnel to the sole active machine agent when exactly one exists (plugin-agents are not counted). The rest stay unassigned and are logged, as are tunnels on a reserved port or sharing a port (granted to no one and left out of `agent-config` — delete and recreate them on a free port). It then rewrites `chisel-users` and restarts Chisel when the grants were narrowed (see [Tunneling](../01-concepts/tunneling.md#startup-reconciliation)).
|
|
208
|
+
|
|
209
|
+
**Revocation:** revoking an agent certificate removes `agentLabel` from its app and plugin tunnels (unassigned, dark) and deletes its `agent-<label>` panel tunnel.
|
|
210
|
+
|
|
211
|
+
**Concurrency:** every workflow that rewrites this file holds the panel's single tunnel lock, validation included.
|
|
212
|
+
|
|
213
|
+
**Write pattern:** Atomic — writes to `.tmp`, calls `fsync()`, then `rename()`.
|
|
214
|
+
|
|
215
|
+
**State directory:** Configurable via `LAMALIBRE_LAMASTE_STATE_DIR` environment variable, defaults to `/etc/lamalibre/lamaste`.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## `/etc/lamalibre/lamaste/sites.json`
|
|
220
|
+
|
|
221
|
+
Stores the array of static sites hosted through Lamaste.
|
|
222
|
+
|
|
223
|
+
**Schema:** Array of site objects.
|
|
224
|
+
|
|
225
|
+
| Field | Type | Description |
|
|
226
|
+
| ------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
227
|
+
| `id` | string | UUID |
|
|
228
|
+
| `name` | string | Site name (the subdomain for managed sites) |
|
|
229
|
+
| `fqdn` | string | Full domain (e.g., `blog.example.com`) |
|
|
230
|
+
| `type` | string | `"managed"` (subdomain of the Lamaste domain) or `"custom"` (your own domain) |
|
|
231
|
+
| `spaMode` | boolean | If true, `try_files` falls back to `/index.html` |
|
|
232
|
+
| `autheliaProtected` | boolean | If true, requires Authelia authentication |
|
|
233
|
+
| `allowedUsers` | string[] | Authelia users allowed when protected (empty: all authenticated users) |
|
|
234
|
+
| `dnsVerified` | boolean | DNS verified (always `true` for managed sites) |
|
|
235
|
+
| `certIssued` | boolean | TLS certificate issued and vhost live |
|
|
236
|
+
| `aliases` | string[] \| undefined | Custom sites only: hostnames answered with a 301 to `https://<fqdn>`. One certificate lineage named after `fqdn` covers all |
|
|
237
|
+
| `rootPath` | string | Document root (e.g., `/var/www/lamaste/<id>/`) |
|
|
238
|
+
| `createdAt` | string | ISO 8601 timestamp |
|
|
239
|
+
|
|
240
|
+
**Example:**
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
[
|
|
244
|
+
{
|
|
245
|
+
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
|
|
246
|
+
"fqdn": "blog.example.com",
|
|
247
|
+
"spaMode": false,
|
|
248
|
+
"autheliaProtected": false,
|
|
249
|
+
"rootPath": "/var/www/lamaste/c3d4e5f6-a7b8-9012-cdef-123456789012/",
|
|
250
|
+
"createdAt": "2026-03-13T12:00:00.000Z"
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Write pattern:** Same as `tunnels.json` — atomic with `fsync()`.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## `/etc/lamalibre/lamaste/chisel-credentials.json`
|
|
260
|
+
|
|
261
|
+
Per-agent Chisel credentials, keyed by agent label. Written when an agent is enrolled, rotated, or revoked; agents fetch their own entry over the panel API.
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"laptop": { "password": "<48 hex chars>", "createdAt": "2026-03-13T10:00:00.000Z" }
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Write pattern:** Atomic — temp file with mode 0600, `fsync()`, then `rename()`.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## `/etc/lamalibre/lamaste/chisel-users`
|
|
274
|
+
|
|
275
|
+
The Chisel server's `--authfile`. **Never edit by hand** — the panel renders it from `chisel-credentials.json` and `tunnels.json` whenever either changes, and again on every panel start. Each `agent-<label>` user is granted exactly the reverse remotes of the enabled tunnels it owns:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"lamaste-no-grants:<sentinel password>": [],
|
|
280
|
+
"agent-laptop:<password>": ["^R:127\\.0\\.0\\.1:3000$"],
|
|
281
|
+
"agent-build-server:<password>": []
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The patterns are anchored because Chisel matches them unanchored. An agent with an empty list can connect but bind nothing. Reserved ports (3100, 9090, 9091, 9292, 9294) and a port claimed by two tunnels are never granted.
|
|
286
|
+
|
|
287
|
+
**Ownership and mode:** `0640`, owner `lamaste`, group `lamaste-chisel`. The file holds every agent's password; Chisel runs as `User=nobody`, `Group=lamaste-chisel` and is the only reader besides the panel. The installer creates the group and adds `lamaste` to it; the panel's unit carries `SupplementaryGroups=lamaste-chisel`. The Chisel SSH host key, `chisel-server.key`, has the same owner, group and mode; the panel generates it at onboarding (earlier versions made it `nobody:nogroup 0400`; a redeploy converts it).
|
|
288
|
+
|
|
289
|
+
**Write pattern:** Written by the panel itself, no sudo: a `0600` temp file in `/etc/lamalibre/lamaste/`, `chgrp lamaste-chisel`, `chmod 0640`, `fsync()`, `rename()` — Chisel's watcher never sees the file with the wrong permissions. Renders are serialized by a mutex.
|
|
290
|
+
|
|
291
|
+
**Reload:** Chisel 1.12.0 reloads the file on every replace for new sessions, so additions need no restart. A change that revokes something (removed or rotated password, withdrawn grant) restarts Chisel with `systemctl try-restart`.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## `/etc/lamalibre/lamaste/chisel-failed-closed`
|
|
296
|
+
|
|
297
|
+
Present only while startup reconciliation holds Chisel down: when the panel cannot establish a correct authfile it stops **and disables** `chisel.service` and writes this file (mode 0600, containing the time). The next successful reconciliation re-enables and starts Chisel and removes it. Do not delete it by hand to bring Chisel back — fix what the panel log names and restart the panel.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## `/etc/lamalibre/lamaste/chisel-sentinel`
|
|
302
|
+
|
|
303
|
+
The random password of the `lamaste-no-grants` sentinel user. Chisel disables authentication entirely when its authfile holds no users; the sentinel keeps the file non-empty on a fresh server or one whose agents are all revoked. It is granted nothing and never handed out. Created on first render (mode 0600).
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## `/etc/lamalibre/lamaste/ticket-scopes.json`
|
|
308
|
+
|
|
309
|
+
Stores the ticket scope registry: registered scopes, active instances, and agent-to-instance assignments. Created automatically on first use.
|
|
310
|
+
|
|
311
|
+
**Schema:**
|
|
312
|
+
|
|
313
|
+
| Field | Type | Description |
|
|
314
|
+
| ------------- | ----- | -------------------------------------------------------- |
|
|
315
|
+
| `scopes` | array | Registered scope definitions (name, version, transport) |
|
|
316
|
+
| `instances` | array | Active instances (scope, instanceId, agentLabel, status) |
|
|
317
|
+
| `assignments` | array | Agent-to-instance assignments |
|
|
318
|
+
|
|
319
|
+
**Example:**
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{
|
|
323
|
+
"scopes": [
|
|
324
|
+
{
|
|
325
|
+
"name": "shell",
|
|
326
|
+
"version": "1.0.0",
|
|
327
|
+
"description": "Remote shell access",
|
|
328
|
+
"scopes": [
|
|
329
|
+
{ "name": "shell:connect", "description": "Connect to shell", "instanceScoped": true }
|
|
330
|
+
],
|
|
331
|
+
"transport": {
|
|
332
|
+
"strategies": ["tunnel"],
|
|
333
|
+
"preferred": "tunnel",
|
|
334
|
+
"port": 9000,
|
|
335
|
+
"protocol": "wss"
|
|
336
|
+
},
|
|
337
|
+
"hooks": {}, // Reserved for future hook configuration
|
|
338
|
+
"installedAt": "2026-03-26T10:00:00.000Z"
|
|
339
|
+
}
|
|
340
|
+
],
|
|
341
|
+
"instances": [
|
|
342
|
+
{
|
|
343
|
+
"scope": "shell:connect",
|
|
344
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
345
|
+
"agentLabel": "macbook-pro",
|
|
346
|
+
"registeredAt": "2026-03-26T10:05:00.000Z",
|
|
347
|
+
"lastHeartbeat": "2026-03-26T10:15:30.000Z",
|
|
348
|
+
"status": "active",
|
|
349
|
+
"transport": { "strategies": ["tunnel"], "preferred": "tunnel" }
|
|
350
|
+
}
|
|
351
|
+
],
|
|
352
|
+
"assignments": [
|
|
353
|
+
{
|
|
354
|
+
"agentLabel": "linux-agent",
|
|
355
|
+
"instanceScope": "shell:connect:a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
356
|
+
"assignedAt": "2026-03-26T10:10:00.000Z",
|
|
357
|
+
"assignedBy": "admin"
|
|
358
|
+
}
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**Instance transport sub-schema:**
|
|
364
|
+
|
|
365
|
+
The instance `transport` object may include a `direct` sub-object when the `direct` strategy is listed:
|
|
366
|
+
|
|
367
|
+
| Field | Type | Required | Description |
|
|
368
|
+
| ----------------------- | -------- | -------- | ------------------------------------------------------------------------------------ |
|
|
369
|
+
| `transport.strategies` | string[] | Yes | Array of `"tunnel"`, `"relay"`, `"direct"` |
|
|
370
|
+
| `transport.preferred` | string | No | Preferred strategy (must be in `strategies`) |
|
|
371
|
+
| `transport.direct` | object | No | Direct connection details (required when using `direct` strategy) |
|
|
372
|
+
| `transport.direct.host` | string | Yes\* | Public hostname or IP (1-255 chars). Private/reserved IPs rejected (SSRF prevention) |
|
|
373
|
+
| `transport.direct.port` | number | Yes\* | Port number (1024-65535) |
|
|
374
|
+
|
|
375
|
+
\* Required when `transport.direct` is provided.
|
|
376
|
+
|
|
377
|
+
**Host validation:** The `transport.direct.host` field rejects private and reserved addresses: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16`, loopback (`localhost`, `127.0.0.1`, `::1`), cloud metadata endpoints (`169.254.169.254`, `metadata.google.internal`), and the zero network (`0.0.0.0/8`).
|
|
378
|
+
|
|
379
|
+
**Write pattern:** Atomic — temp file, `fsync()`, `rename()`. Concurrency controlled by promise-chain mutex.
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## `/etc/lamalibre/lamaste/tickets.json`
|
|
384
|
+
|
|
385
|
+
Stores active tickets and sessions for agent-to-agent authorization. Created automatically on first use.
|
|
386
|
+
|
|
387
|
+
**Schema:**
|
|
388
|
+
|
|
389
|
+
| Field | Type | Description |
|
|
390
|
+
| ---------- | ----- | ------------------------------------------------------------------------- |
|
|
391
|
+
| `tickets` | array | Issued tickets (id, scope, instanceId, source, target, expiry) |
|
|
392
|
+
| `sessions` | array | Active sessions (server-generated sessionId, ticketId, status, heartbeat) |
|
|
393
|
+
|
|
394
|
+
**Example:**
|
|
395
|
+
|
|
396
|
+
```json
|
|
397
|
+
{
|
|
398
|
+
"tickets": [
|
|
399
|
+
{
|
|
400
|
+
"id": "64-hex-char-ticket-id",
|
|
401
|
+
"scope": "shell:connect",
|
|
402
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
403
|
+
"source": "macbook-pro",
|
|
404
|
+
"target": "linux-agent",
|
|
405
|
+
"createdAt": "2026-03-26T10:15:00.000Z",
|
|
406
|
+
"expiresAt": "2026-03-26T10:15:30.000Z",
|
|
407
|
+
"used": false,
|
|
408
|
+
"usedAt": null,
|
|
409
|
+
"sessionId": null,
|
|
410
|
+
"transport": {}
|
|
411
|
+
}
|
|
412
|
+
],
|
|
413
|
+
"sessions": [
|
|
414
|
+
{
|
|
415
|
+
"sessionId": "c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8",
|
|
416
|
+
"ticketId": "64-hex-char-ticket-id",
|
|
417
|
+
"scope": "shell:connect",
|
|
418
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
419
|
+
"source": "macbook-pro",
|
|
420
|
+
"target": "linux-agent",
|
|
421
|
+
"createdAt": "2026-03-26T10:15:30.000Z",
|
|
422
|
+
"lastActivityAt": "2026-03-26T10:20:00.000Z",
|
|
423
|
+
"status": "active",
|
|
424
|
+
"reconnectGraceSeconds": 60
|
|
425
|
+
}
|
|
426
|
+
]
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Write pattern:** Same as `ticket-scopes.json` — atomic with mutex.
|
|
431
|
+
|
|
432
|
+
**Cleanup:** Tickets older than 1 hour are removed. Dead sessions older than 24 hours are removed.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## `/etc/lamalibre/lamaste/groups.json`
|
|
437
|
+
|
|
438
|
+
Stores Lamaste group definitions and membership. Separate from Authelia groups — Lamaste groups are used exclusively for Gatekeeper access control without modifying `users.yml`.
|
|
439
|
+
|
|
440
|
+
**Schema:**
|
|
441
|
+
|
|
442
|
+
| Field | Type | Description |
|
|
443
|
+
| ---------------------- | -------- | ------------------------------------------------------- |
|
|
444
|
+
| `groups` | array | Array of group objects |
|
|
445
|
+
| `groups[].name` | string | Group name (unique, lowercase alphanumeric, 2-63 chars) |
|
|
446
|
+
| `groups[].description` | string | Human-readable description |
|
|
447
|
+
| `groups[].members` | string[] | Array of Authelia usernames |
|
|
448
|
+
| `groups[].createdAt` | string | ISO 8601 timestamp |
|
|
449
|
+
| `groups[].createdBy` | string | Admin who created the group |
|
|
450
|
+
|
|
451
|
+
**Example:**
|
|
452
|
+
|
|
453
|
+
```json
|
|
454
|
+
{
|
|
455
|
+
"groups": [
|
|
456
|
+
{
|
|
457
|
+
"name": "developers",
|
|
458
|
+
"description": "Backend and frontend developers",
|
|
459
|
+
"members": ["alice", "bob"],
|
|
460
|
+
"createdAt": "2026-04-01T10:00:00.000Z",
|
|
461
|
+
"createdBy": "admin"
|
|
462
|
+
}
|
|
463
|
+
]
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Write pattern:** Atomic — temp file, `fsync()`, `rename()`. Concurrency controlled by promise-chain mutex.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## `/etc/lamalibre/lamaste/access-grants.json`
|
|
472
|
+
|
|
473
|
+
Stores generic access grants mapping principals (users or groups) to resources (tunnel subdomains or other protected endpoints).
|
|
474
|
+
|
|
475
|
+
**Schema:**
|
|
476
|
+
|
|
477
|
+
| Field | Type | Description |
|
|
478
|
+
| ------------------------ | -------------- | ----------------------------------------------- |
|
|
479
|
+
| `grants` | array | Array of grant objects |
|
|
480
|
+
| `grants[].grantId` | string | Unique identifier (e.g., `g_abc123`) |
|
|
481
|
+
| `grants[].principalType` | string | `"user"` or `"group"` |
|
|
482
|
+
| `grants[].principalId` | string | Authelia username or Lamaste group name |
|
|
483
|
+
| `grants[].resourceType` | string | `"tunnel"`, `"plugin"`, or custom resource type |
|
|
484
|
+
| `grants[].resourceId` | string | Resource identifier (e.g., tunnel subdomain) |
|
|
485
|
+
| `grants[].context` | object | Optional metadata (empty `{}` by default) |
|
|
486
|
+
| `grants[].used` | boolean | Whether the grant has been consumed |
|
|
487
|
+
| `grants[].createdAt` | string | ISO 8601 timestamp |
|
|
488
|
+
| `grants[].usedAt` | string \| null | ISO 8601 timestamp of consumption, or `null` |
|
|
489
|
+
|
|
490
|
+
**Example:**
|
|
491
|
+
|
|
492
|
+
```json
|
|
493
|
+
{
|
|
494
|
+
"grants": [
|
|
495
|
+
{
|
|
496
|
+
"grantId": "g_b2c3d4e5",
|
|
497
|
+
"principalType": "user",
|
|
498
|
+
"principalId": "alice",
|
|
499
|
+
"resourceType": "tunnel",
|
|
500
|
+
"resourceId": "myapp",
|
|
501
|
+
"context": {},
|
|
502
|
+
"used": false,
|
|
503
|
+
"createdAt": "2026-04-01T10:05:00.000Z",
|
|
504
|
+
"usedAt": null
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
"grantId": "g_c3d4e5f6",
|
|
508
|
+
"principalType": "group",
|
|
509
|
+
"principalId": "developers",
|
|
510
|
+
"resourceType": "tunnel",
|
|
511
|
+
"resourceId": "staging",
|
|
512
|
+
"context": {},
|
|
513
|
+
"used": false,
|
|
514
|
+
"createdAt": "2026-04-01T10:10:00.000Z",
|
|
515
|
+
"usedAt": null
|
|
516
|
+
}
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Write pattern:** Atomic — temp file, `fsync()`, `rename()`. Concurrency controlled by promise-chain mutex.
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## `/etc/lamalibre/lamaste/gatekeeper.json`
|
|
526
|
+
|
|
527
|
+
Gatekeeper service settings. Controls cache behavior, admin contact information (displayed on the access-denied page), and logging configuration.
|
|
528
|
+
|
|
529
|
+
**Schema:**
|
|
530
|
+
|
|
531
|
+
| Field | Type | Default | Description |
|
|
532
|
+
| ------------------------ | -------------------- | ------- | ----------------------------------------------------------- |
|
|
533
|
+
| `adminEmail` | string \| undefined | — | Admin email shown on access-denied page |
|
|
534
|
+
| `adminName` | string \| undefined | — | Admin display name shown on access-denied page |
|
|
535
|
+
| `slackChannel` | string \| undefined | — | Slack channel for access request templates |
|
|
536
|
+
| `teamsChannel` | string \| undefined | — | Teams channel for access request templates |
|
|
537
|
+
| `sessionCacheTtlMs` | number \| undefined | — | In-memory session cache TTL in milliseconds (default 30000) |
|
|
538
|
+
| `accessLoggingEnabled` | boolean \| undefined | — | Whether to log denied access attempts |
|
|
539
|
+
| `accessLogRetentionDays` | number \| undefined | — | How many days to retain access log entries |
|
|
540
|
+
|
|
541
|
+
**Example:**
|
|
542
|
+
|
|
543
|
+
```json
|
|
544
|
+
{
|
|
545
|
+
"adminEmail": "admin@example.com",
|
|
546
|
+
"adminName": "Admin",
|
|
547
|
+
"slackChannel": "#access-requests",
|
|
548
|
+
"sessionCacheTtlMs": 30000,
|
|
549
|
+
"accessLoggingEnabled": true,
|
|
550
|
+
"accessLogRetentionDays": 90
|
|
551
|
+
}
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
**Write pattern:** Atomic — temp file, `fsync()`, `rename()`.
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## `/etc/lamalibre/lamaste/access-request-log.json`
|
|
559
|
+
|
|
560
|
+
Optional log of denied access attempts. Written by the Gatekeeper when `accessLoggingEnabled` is true. Read by the Panel Server for the admin UI access request review page.
|
|
561
|
+
|
|
562
|
+
**Schema:** Array of access request entries.
|
|
563
|
+
|
|
564
|
+
| Field | Type | Description |
|
|
565
|
+
| -------------- | ------ | -------------------------------------------- |
|
|
566
|
+
| `timestamp` | string | ISO 8601 timestamp of the denied request |
|
|
567
|
+
| `username` | string | Authelia username of the denied user |
|
|
568
|
+
| `resourceType` | string | Resource type (e.g., `"tunnel"`, `"plugin"`) |
|
|
569
|
+
| `resourceId` | string | Resource identifier (e.g., tunnel subdomain) |
|
|
570
|
+
| `resourceFqdn` | string | Full domain the user attempted to access |
|
|
571
|
+
|
|
572
|
+
**Example:**
|
|
573
|
+
|
|
574
|
+
```json
|
|
575
|
+
[
|
|
576
|
+
{
|
|
577
|
+
"timestamp": "2026-04-01T14:30:00.000Z",
|
|
578
|
+
"username": "charlie",
|
|
579
|
+
"resourceType": "tunnel",
|
|
580
|
+
"resourceId": "internal",
|
|
581
|
+
"resourceFqdn": "internal.example.com"
|
|
582
|
+
}
|
|
583
|
+
]
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Write pattern:** Atomic — temp file, `fsync()`, `rename()`.
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
## `/etc/authelia/configuration.yml`
|
|
591
|
+
|
|
592
|
+
Authelia server configuration. Written during onboarding provisioning.
|
|
593
|
+
|
|
594
|
+
**Key fields:**
|
|
595
|
+
|
|
596
|
+
```yaml
|
|
597
|
+
server:
|
|
598
|
+
host: 127.0.0.1
|
|
599
|
+
port: 9091
|
|
600
|
+
|
|
601
|
+
log:
|
|
602
|
+
level: info
|
|
603
|
+
file_path: /var/log/authelia/authelia.log
|
|
604
|
+
|
|
605
|
+
jwt_secret: <random-secret>
|
|
606
|
+
|
|
607
|
+
authentication_backend:
|
|
608
|
+
file:
|
|
609
|
+
path: /etc/authelia/users.yml
|
|
610
|
+
password:
|
|
611
|
+
algorithm: bcrypt
|
|
612
|
+
bcrypt:
|
|
613
|
+
cost: 12
|
|
614
|
+
|
|
615
|
+
access_control:
|
|
616
|
+
default_policy: one_factor
|
|
617
|
+
|
|
618
|
+
session:
|
|
619
|
+
name: lamaste_session
|
|
620
|
+
secret: <random-secret>
|
|
621
|
+
domain: example.com
|
|
622
|
+
expiration: 12h
|
|
623
|
+
inactivity: 2h
|
|
624
|
+
|
|
625
|
+
storage:
|
|
626
|
+
encryption_key: <random-secret>
|
|
627
|
+
local:
|
|
628
|
+
path: /etc/authelia/db.sqlite3
|
|
629
|
+
|
|
630
|
+
notifier:
|
|
631
|
+
filesystem:
|
|
632
|
+
filename: /etc/authelia/notifications.txt
|
|
633
|
+
|
|
634
|
+
totp:
|
|
635
|
+
issuer: Lamaste
|
|
636
|
+
period: 30
|
|
637
|
+
digits: 6
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**Critical settings:**
|
|
641
|
+
|
|
642
|
+
| Setting | Value | Why |
|
|
643
|
+
| -------------------- | ----------- | ------------------------------------------------------------ |
|
|
644
|
+
| `server.host` | `127.0.0.1` | Never bind to `0.0.0.0` — nginx handles public access |
|
|
645
|
+
| `password.algorithm` | `bcrypt` | Argon2id uses ~93 MB per hash, causes OOM on 512 MB droplets |
|
|
646
|
+
| `bcrypt.cost` | `12` | Balance between security and performance |
|
|
647
|
+
| `session.domain` | Your domain | Must match the domain in `panel.json` |
|
|
648
|
+
|
|
649
|
+
**Ownership and mode:** `lamaste:lamaste-authelia`, `0640`. The panel writes it without sudo (atomic temp file + rename in `/etc/authelia`, which is `lamaste:lamaste-authelia 2770`, setgid); Authelia, running as `lamaste-authelia`, reads it through its group. The database (`db.sqlite3`) and `notifications.txt` belong to `lamaste-authelia` (`0600`).
|
|
650
|
+
|
|
651
|
+
**Do not edit this file directly** unless you understand Authelia configuration. Changes require a service restart: `sudo systemctl restart authelia`.
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
## `/etc/authelia/users.yml`
|
|
656
|
+
|
|
657
|
+
The user database. Authelia reads this file live (no restart needed for user changes, but Lamaste restarts Authelia after writes for safety).
|
|
658
|
+
|
|
659
|
+
**Format:**
|
|
660
|
+
|
|
661
|
+
```yaml
|
|
662
|
+
users:
|
|
663
|
+
admin:
|
|
664
|
+
displayname: admin
|
|
665
|
+
password: $2b$12$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ012
|
|
666
|
+
email: admin@lamaste.local
|
|
667
|
+
groups:
|
|
668
|
+
- admins
|
|
669
|
+
alice:
|
|
670
|
+
displayname: alice
|
|
671
|
+
password: $2b$12$xyzdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ012
|
|
672
|
+
email: alice@lamaste.local
|
|
673
|
+
groups:
|
|
674
|
+
- admins
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
**Password format:** bcrypt hash (starts with `$2b$12$`). Never use argon2id on a 512 MB droplet.
|
|
678
|
+
|
|
679
|
+
**Write pattern:** Written by the panel without sudo — a temp file in `/etc/authelia`, `fsync()`, `rename()` — mode `0660`, group `lamaste-authelia` (Authelia rewrites the file in place when a user changes a password). After writing, Authelia is restarted.
|
|
680
|
+
|
|
681
|
+
**Warning:** Never delete the last user. The panel server prevents this, but manual editing could bypass the guard.
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## `/etc/authelia/.secrets.json`
|
|
686
|
+
|
|
687
|
+
Stores the randomly generated secrets used in the Authelia configuration. Backed up here so they can be referenced if the configuration file is regenerated.
|
|
688
|
+
|
|
689
|
+
```json
|
|
690
|
+
{
|
|
691
|
+
"jwtSecret": "<64-char-random-string>",
|
|
692
|
+
"sessionSecret": "<64-char-random-string>",
|
|
693
|
+
"storageEncryptionKey": "<64-char-random-string>"
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Mode:** 0600, owner `lamaste` (the panel only; Authelia reads the secrets from its configuration). If these values change, all active sessions are invalidated.
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
## Client-Side Configuration
|
|
702
|
+
|
|
703
|
+
### `~/.lamalibre/lamaste/servers.json`
|
|
704
|
+
|
|
705
|
+
Stores the server registry for the desktop app's multi-server support. Created by cloud provisioning or manual server addition. When this file exists and contains an active entry, `load_effective_config()` uses it instead of `agent.json`.
|
|
706
|
+
|
|
707
|
+
**Schema:** Array of server entry objects.
|
|
708
|
+
|
|
709
|
+
| Field | Type | Description |
|
|
710
|
+
| ---------------------------- | -------------- | --------------------------------------------------------------------------------------------------- |
|
|
711
|
+
| `id` | string | UUID |
|
|
712
|
+
| `label` | string | Display name (typically the domain) |
|
|
713
|
+
| `panelUrl` | string | Panel URL (e.g., `https://203.0.113.42:9292`) |
|
|
714
|
+
| `ip` | string | Server IP address |
|
|
715
|
+
| `provider` | string \| null | Cloud provider name (e.g., `digitalocean`) |
|
|
716
|
+
| `providerId` | string \| null | Provider-specific resource ID (e.g., droplet ID) |
|
|
717
|
+
| `region` | string \| null | Provider region slug |
|
|
718
|
+
| `createdAt` | string | ISO 8601 timestamp |
|
|
719
|
+
| `active` | boolean | Whether this is the currently active server |
|
|
720
|
+
| `authMethod` | string | `"p12"` or `"keychain"` |
|
|
721
|
+
| `keychainIdentity` | string \| null | Keychain identity name (when `authMethod` is `"keychain"`) |
|
|
722
|
+
| `p12Path` | string \| null | Path to P12 file (when `authMethod` is `"p12"`) |
|
|
723
|
+
| `activeMode` | string | `"agent"` or `"admin"` — which UI mode the desktop app shows for this server. Defaults to `"agent"` |
|
|
724
|
+
| `adminAuth` | object \| null | Admin certificate details for Server mode access (see sub-fields below) |
|
|
725
|
+
| `adminAuth.method` | string | `"p12"` or `"keychain"` — how the admin cert is stored |
|
|
726
|
+
| `adminAuth.p12Path` | string \| null | Path to admin P12 file (when method is `"p12"`) |
|
|
727
|
+
| `adminAuth.keychainIdentity` | string \| null | Keychain identity for admin cert (when method is `"keychain"`) |
|
|
728
|
+
|
|
729
|
+
**Example:**
|
|
730
|
+
|
|
731
|
+
```json
|
|
732
|
+
[
|
|
733
|
+
{
|
|
734
|
+
"id": "d4e5f6a7-b8c9-0123-defg-456789012345",
|
|
735
|
+
"label": "example.com",
|
|
736
|
+
"panelUrl": "https://203.0.113.42:9292",
|
|
737
|
+
"ip": "203.0.113.42",
|
|
738
|
+
"provider": "digitalocean",
|
|
739
|
+
"providerId": "123456789",
|
|
740
|
+
"region": "fra1",
|
|
741
|
+
"createdAt": "2026-03-27T10:00:00.000Z",
|
|
742
|
+
"active": true,
|
|
743
|
+
"authMethod": "p12",
|
|
744
|
+
"p12Path": "/Users/admin/.lamaste/servers/d4e5f6a7/client.p12",
|
|
745
|
+
"keychainIdentity": null,
|
|
746
|
+
"activeMode": "admin",
|
|
747
|
+
"adminAuth": {
|
|
748
|
+
"method": "p12",
|
|
749
|
+
"p12Path": "/Users/admin/.lamaste/servers/d4e5f6a7/admin.p12",
|
|
750
|
+
"keychainIdentity": null
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
]
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
**Notes on `adminAuth`:** When `adminAuth` is present and valid, the desktop app shows the Agents/Servers mode toggle in the sidebar. Cloud-provisioned servers populate `adminAuth` automatically (the admin certificate is downloaded during provisioning). For manually added servers, the user must import an admin certificate to enable Server mode.
|
|
757
|
+
|
|
758
|
+
**P12 password:** Not stored in the JSON file. Retrieved from the OS credential store (`com.lamalibre.lamaste.server` service, keyed by server UUID).
|
|
759
|
+
|
|
760
|
+
**Cloud API token:** Not stored in this file. Retrieved from the OS credential store (`com.lamalibre.cloud` service).
|
|
761
|
+
|
|
762
|
+
**Write pattern:** Atomic — temp file with mode 0600, `fsync()`, then `rename()`.
|
|
763
|
+
|
|
764
|
+
**Config resolution:** `load_effective_config()` checks `agents.json` first (multi-agent registry), then `servers.json` (active entry), then falls back to `agent.json` (legacy).
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
768
|
+
### `~/.lamalibre/lamaste/agents.json`
|
|
769
|
+
|
|
770
|
+
Multi-agent registry. Created by `lamaste-agent setup`. Tracks all configured agents and the current default.
|
|
771
|
+
|
|
772
|
+
```json
|
|
773
|
+
{
|
|
774
|
+
"version": 1,
|
|
775
|
+
"currentLabel": "my-server",
|
|
776
|
+
"agents": [
|
|
777
|
+
{
|
|
778
|
+
"label": "my-server",
|
|
779
|
+
"panelUrl": "https://1.2.3.4:9292",
|
|
780
|
+
"authMethod": "p12",
|
|
781
|
+
"p12Path": "~/.lamalibre/lamaste/agents/my-server/client.p12",
|
|
782
|
+
"keychainIdentity": null,
|
|
783
|
+
"agentLabel": "agent:my-machine",
|
|
784
|
+
"domain": "example.com",
|
|
785
|
+
"chiselVersion": "1.12.0",
|
|
786
|
+
"setupAt": "2026-03-28T10:00:00.000Z",
|
|
787
|
+
"updatedAt": null
|
|
788
|
+
}
|
|
789
|
+
]
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
**Write pattern:** Atomic — temp file with mode 0600, `fsync()`, then `rename()`.
|
|
794
|
+
|
|
795
|
+
Per-agent data is stored at `~/.lamalibre/lamaste/agents/<label>/`:
|
|
796
|
+
|
|
797
|
+
The directory itself is mode 0700 (re-applied on every sync).
|
|
798
|
+
|
|
799
|
+
- `config.json` — agent configuration (mode 0600): `panelUrl`, `authMethod`, credentials, the enrolled `domain` (the agent refuses a panel that reports another one), `chiselVersion`, the panel TLS pin (`panelServerPubkeySha256`, `panelServerCertSha256Hex`, `panelServerCertPinnedAt`), and:
|
|
800
|
+
- `chiselCredentialSealedAt` — when the agent last received a Chisel credential that has only ever lived in 0600 files. Set at setup. Absent on agents set up by versions that passed the credential in process arguments and 0644 unit files; their next sync rotates the credential once (`POST /api/agents/me/chisel-credential/rotate`) and then sets it
|
|
801
|
+
- `tunnelsStopped` — `true` when the operator stopped the tunnels (agent panel or desktop app); sync keeps the Chisel client stopped. Start and restart remove it
|
|
802
|
+
- `client.p12` — mTLS certificate (mode 0600)
|
|
803
|
+
- `ca.crt` — CA certificate (mode 0644)
|
|
804
|
+
- `chisel.json` — the agent's Chisel credential `{ "user": "agent-<label>", "password": "...", "fetchedAt": "...", "issuedAt": "..." }` (mode 0600). `issuedAt` is when the panel issued the password; when the panel's `chiselCredentialIssuedAt` differs, sync fetches the current credential. Source of truth: every rewrite of the service re-applies it. `lamaste-agent chisel refresh-credential` refreshes it immediately
|
|
805
|
+
- `chisel.env` — Linux only: `AUTH=agent-<label>:<password>`, read by the systemd unit through `EnvironmentFile=` (mode 0600)
|
|
806
|
+
- `sync-state.json` — outcome of the last `lamaste-agent sync` (mode 0600): `lastRunAt`, `lastOkAt`, `lastError` (null after a success), `lastState` (`running`, `idle` — no tunnels, client stopped — or `stopped` by the operator), `tunnels`, `lastWarnings`. Shown on the **Sync** line of `lamaste-agent status` (flagged when `lastRunAt` is over 2 minutes old), and used to log only changes and new warnings
|
|
807
|
+
- `agent.lock` — present while an operation (setup, update, sync, the agent panel or daemon) changes this agent's service or `config.json`; holds the owner's PID, boot id and start time. A stale lock (dead process, earlier boot, older than 15 minutes) is taken over
|
|
808
|
+
- `logs/chisel.log` — Chisel stdout log
|
|
809
|
+
- `logs/chisel.error.log` — Chisel stderr log
|
|
810
|
+
- `logs/sync.log` — sync timer log: only runs that changed something, and each error when it first appears and when it clears
|
|
811
|
+
- `plugins.json` — agent plugin registry
|
|
812
|
+
- `plugins/` — per-plugin data directories
|
|
813
|
+
|
|
814
|
+
Service files use per-agent names:
|
|
815
|
+
|
|
816
|
+
- macOS: `com.lamalibre.lamaste.chisel-<label>` (plist label), `~/Library/LaunchAgents/com.lamalibre.lamaste.chisel-<label>.plist` — mode 0600, because it carries `AUTH` in `EnvironmentVariables`
|
|
817
|
+
- 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
|
|
818
|
+
|
|
819
|
+
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.0.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).
|
|
820
|
+
|
|
821
|
+
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):
|
|
822
|
+
|
|
823
|
+
- macOS: `com.lamalibre.lamaste.sync-<label>` (plist label), `~/Library/LaunchAgents/com.lamalibre.lamaste.sync-<label>.plist` — `StartInterval` 30, `RunAtLoad`
|
|
824
|
+
- Linux: `~/.config/systemd/user/lamalibre-lamaste-sync-<label>.service` (`Type=oneshot`) and `lamalibre-lamaste-sync-<label>.timer` (`OnActiveSec=5s`, `OnUnitInactiveSec=30s`) — also needs lingering to run without a login
|
|
825
|
+
|
|
826
|
+
Both contain no secret (mode 0644) and are removed by `lamaste-agent uninstall` and by the desktop app's uninstall.
|
|
827
|
+
|
|
828
|
+
---
|
|
829
|
+
|
|
830
|
+
### `~/.lamalibre/lamaste/agent.json`
|
|
831
|
+
|
|
832
|
+
Legacy single-server configuration. Automatically migrated to the multi-agent registry on first use. After migration, renamed to `agent.json.backup`.
|
|
833
|
+
|
|
834
|
+
---
|
|
835
|
+
|
|
836
|
+
## nginx Vhost Patterns
|
|
837
|
+
|
|
838
|
+
### `/etc/nginx/sites-available/lamalibre-lamaste-panel-ip`
|
|
839
|
+
|
|
840
|
+
The IP-based panel vhost. Created by the installer. Active as a fallback unless panel 2FA is enabled, which disables it (domain-only access).
|
|
841
|
+
|
|
842
|
+
```nginx
|
|
843
|
+
# Rate limit zone for public enrollment endpoint (5 requests/minute per IP)
|
|
844
|
+
limit_req_zone $binary_remote_addr zone=enroll:1m rate=5r/m;
|
|
845
|
+
|
|
846
|
+
map $http_upgrade $connection_upgrade {
|
|
847
|
+
default upgrade;
|
|
848
|
+
'' close;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
server {
|
|
852
|
+
listen 9292 ssl;
|
|
853
|
+
server_name _;
|
|
854
|
+
|
|
855
|
+
ssl_certificate /etc/lamalibre/lamaste/pki/self-signed.pem;
|
|
856
|
+
ssl_certificate_key /etc/lamalibre/lamaste/pki/self-signed-key.pem;
|
|
857
|
+
|
|
858
|
+
include /etc/nginx/snippets/lamalibre-lamaste-mtls.conf;
|
|
859
|
+
|
|
860
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
|
861
|
+
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
862
|
+
ssl_prefer_server_ciphers on;
|
|
863
|
+
|
|
864
|
+
error_page 495 496 /cert-help.html;
|
|
865
|
+
location = /cert-help.html {
|
|
866
|
+
root /opt/lamalibre/lamaste/lamaste-server-ui;
|
|
867
|
+
internal;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
# Protected locations — reject if client cert missing or invalid
|
|
871
|
+
location / {
|
|
872
|
+
if ($ssl_client_verify != SUCCESS) {
|
|
873
|
+
return 496;
|
|
874
|
+
}
|
|
875
|
+
proxy_pass http://127.0.0.1:3100;
|
|
876
|
+
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
|
|
877
|
+
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
|
|
878
|
+
proxy_set_header X-SSL-Client-Serial $ssl_client_serial;
|
|
879
|
+
proxy_set_header Host $host;
|
|
880
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
881
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
882
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
# Public API paths — no mTLS check, cert headers cleared
|
|
886
|
+
location /api/enroll {
|
|
887
|
+
limit_req zone=enroll burst=5 nodelay;
|
|
888
|
+
proxy_pass http://127.0.0.1:3100;
|
|
889
|
+
proxy_http_version 1.1;
|
|
890
|
+
proxy_set_header X-SSL-Client-Verify "";
|
|
891
|
+
proxy_set_header X-SSL-Client-DN "";
|
|
892
|
+
proxy_set_header X-SSL-Client-Serial "";
|
|
893
|
+
# ... standard proxy headers
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
location /api/invite {
|
|
897
|
+
proxy_pass http://127.0.0.1:3100;
|
|
898
|
+
proxy_http_version 1.1;
|
|
899
|
+
proxy_set_header X-SSL-Client-Verify "";
|
|
900
|
+
proxy_set_header X-SSL-Client-DN "";
|
|
901
|
+
proxy_set_header X-SSL-Client-Serial "";
|
|
902
|
+
# ... standard proxy headers
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
# API paths with WebSocket upgrade support (mTLS required)
|
|
906
|
+
location /api {
|
|
907
|
+
if ($ssl_client_verify != SUCCESS) {
|
|
908
|
+
return 496;
|
|
909
|
+
}
|
|
910
|
+
proxy_pass http://127.0.0.1:3100;
|
|
911
|
+
proxy_http_version 1.1;
|
|
912
|
+
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
|
|
913
|
+
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
|
|
914
|
+
proxy_set_header X-SSL-Client-Serial $ssl_client_serial;
|
|
915
|
+
proxy_set_header Host $host;
|
|
916
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
917
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
918
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
919
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
920
|
+
proxy_set_header Connection $connection_upgrade;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
### `/etc/nginx/sites-available/lamalibre-lamaste-panel-domain`
|
|
926
|
+
|
|
927
|
+
The domain-based panel vhost. Created during onboarding provisioning. Uses Let's Encrypt certificates and mTLS.
|
|
928
|
+
|
|
929
|
+
```nginx
|
|
930
|
+
server {
|
|
931
|
+
listen 443 ssl;
|
|
932
|
+
server_name panel.example.com;
|
|
933
|
+
|
|
934
|
+
ssl_certificate /etc/letsencrypt/live/panel.example.com/fullchain.pem;
|
|
935
|
+
ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;
|
|
936
|
+
|
|
937
|
+
include /etc/nginx/snippets/lamalibre-lamaste-mtls.conf;
|
|
938
|
+
# ... (same proxy headers and locations as IP vhost)
|
|
939
|
+
}
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
### `/etc/nginx/sites-available/lamalibre-lamaste-auth`
|
|
943
|
+
|
|
944
|
+
The Authelia authentication portal. Proxies to `127.0.0.1:9091`.
|
|
945
|
+
|
|
946
|
+
### `/etc/nginx/sites-available/lamalibre-lamaste-tunnel`
|
|
947
|
+
|
|
948
|
+
The Chisel WebSocket tunnel endpoint. Proxies to `127.0.0.1:9090` with WebSocket upgrade and 24-hour timeout.
|
|
949
|
+
|
|
950
|
+
### `/etc/nginx/sites-available/lamalibre-lamaste-app-<subdomain>`
|
|
951
|
+
|
|
952
|
+
Per-tunnel vhosts. `restricted` and `authenticated` tunnels authorize through Gatekeeper (`auth_request` to `127.0.0.1:9294`), `public` tunnels proxy directly. Each proxies to the tunnel's port with WebSocket support and sets `client_max_body_size` from the tunnel's `maxBodySizeMb` (no directive — nginx's 1 MiB — on legacy tunnels without the field).
|
|
953
|
+
|
|
954
|
+
### `/etc/nginx/sites-available/lamalibre-lamaste-site-<uuid>`
|
|
955
|
+
|
|
956
|
+
Per-static-site vhosts. Serve files from `/var/www/lamaste/<uuid>/` with optional Authelia protection and SPA mode. A custom site with `aliases` gets an extra server block answering those hostnames with a 301 to `https://<fqdn>`, on the same certificate.
|
|
957
|
+
|
|
958
|
+
---
|
|
959
|
+
|
|
960
|
+
## `/etc/nginx/snippets/lamalibre-lamaste-mtls.conf`
|
|
961
|
+
|
|
962
|
+
The mTLS configuration snippet included by all panel vhosts:
|
|
963
|
+
|
|
964
|
+
```nginx
|
|
965
|
+
ssl_client_certificate /etc/lamalibre/lamaste/pki/ca.crt;
|
|
966
|
+
ssl_verify_client optional;
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
This enables client certificate verification at the TLS level. The `optional` setting allows connections without a certificate (needed for public endpoints like `/api/enroll` and `/api/invite`). Protected locations enforce mTLS via `if ($ssl_client_verify != SUCCESS) { return 496; }` in each vhost's location blocks.
|
|
970
|
+
|
|
971
|
+
---
|
|
972
|
+
|
|
973
|
+
## `/etc/nginx/snippets/lamalibre-lamaste-authz-cache.conf`
|
|
974
|
+
|
|
975
|
+
Defines the nginx proxy_cache zone installed by the Gatekeeper installer task:
|
|
976
|
+
|
|
977
|
+
```nginx
|
|
978
|
+
proxy_cache_path /var/cache/nginx/authz levels=1:2 keys_zone=lamaste_authz:1m max_size=10m inactive=5m;
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
This cache zone is available for nginx-level caching of Gatekeeper authorization responses. However, the generated vhosts (`buildGatekeeperVhost()`) do not currently include `proxy_cache` directives. Authorization caching relies on the Gatekeeper's in-memory session cache (30-second default TTL).
|
|
982
|
+
|
|
983
|
+
---
|
|
984
|
+
|
|
985
|
+
## `/etc/systemd/system/lamalibre-lamaste-gatekeeper.service`
|
|
986
|
+
|
|
987
|
+
Systemd unit for the Gatekeeper tunnel authorization service. Runs as the `lamaste` user on `127.0.0.1:9294`.
|
|
988
|
+
|
|
989
|
+
```ini
|
|
990
|
+
[Unit]
|
|
991
|
+
Description=Lamaste Gatekeeper
|
|
992
|
+
After=network.target
|
|
993
|
+
|
|
994
|
+
[Service]
|
|
995
|
+
Type=simple
|
|
996
|
+
User=lamaste
|
|
997
|
+
Group=lamaste
|
|
998
|
+
WorkingDirectory=/opt/lamalibre/lamaste/gatekeeper
|
|
999
|
+
ExecStart=/usr/bin/node src/index.js
|
|
1000
|
+
Restart=on-failure
|
|
1001
|
+
RestartSec=5
|
|
1002
|
+
Environment=NODE_ENV=production
|
|
1003
|
+
|
|
1004
|
+
[Install]
|
|
1005
|
+
WantedBy=multi-user.target
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
---
|
|
1009
|
+
|
|
1010
|
+
## File Permissions Table
|
|
1011
|
+
|
|
1012
|
+
| Path | Owner | Mode | Notes |
|
|
1013
|
+
| ---------------------------------------------------------------------- | --------------------------------- | ---- | --------------------------------------------------------- |
|
|
1014
|
+
| `/etc/lamalibre/lamaste/` | lamaste:lamaste | 0755 | State directory |
|
|
1015
|
+
| `/etc/lamalibre/lamaste/panel.json` | lamaste:lamaste | 0600 | Panel config |
|
|
1016
|
+
| `/etc/lamalibre/lamaste/tunnels.json` | lamaste:lamaste | 0600 | Tunnel state |
|
|
1017
|
+
| `/etc/lamalibre/lamaste/sites.json` | lamaste:lamaste | 0600 | Site state |
|
|
1018
|
+
| `/etc/lamalibre/lamaste/chisel-credentials.json` | lamaste:lamaste | 0600 | Chisel credentials |
|
|
1019
|
+
| `/etc/lamalibre/lamaste/chisel-users` | lamaste:lamaste-chisel | 0640 | Chisel authfile |
|
|
1020
|
+
| `/etc/lamalibre/lamaste/chisel-sentinel` | lamaste:lamaste | 0600 | Sentinel password |
|
|
1021
|
+
| `/etc/lamalibre/lamaste/pki/` | lamaste:lamaste | 0700 | PKI directory |
|
|
1022
|
+
| `/etc/lamalibre/lamaste/pki/ca.key` | lamaste:lamaste | 0600 | CA private key |
|
|
1023
|
+
| `/etc/lamalibre/lamaste/pki/ca.crt` | lamaste:lamaste | 0644 | CA certificate |
|
|
1024
|
+
| `/etc/lamalibre/lamaste/pki/client.key` | lamaste:lamaste | 0600 | Client private key |
|
|
1025
|
+
| `/etc/lamalibre/lamaste/pki/client.crt` | lamaste:lamaste | 0644 | Client certificate |
|
|
1026
|
+
| `/etc/lamalibre/lamaste/pki/client.p12` | lamaste:lamaste | 0600 | PKCS12 bundle |
|
|
1027
|
+
| `/etc/lamalibre/lamaste/pki/.p12-password` | lamaste:lamaste | 0600 | PKCS12 password |
|
|
1028
|
+
| `/etc/lamalibre/lamaste/pki/self-signed.pem` | lamaste:lamaste | 0644 | Self-signed TLS cert |
|
|
1029
|
+
| `/etc/lamalibre/lamaste/pki/self-signed-key.pem` | lamaste:lamaste | 0600 | Self-signed TLS key |
|
|
1030
|
+
| `/etc/lamalibre/lamaste/ticket-scopes.json` | lamaste:lamaste | 0600 | Ticket scope registry |
|
|
1031
|
+
| `/etc/lamalibre/lamaste/tickets.json` | lamaste:lamaste | 0600 | Ticket/session store |
|
|
1032
|
+
| `/etc/lamalibre/lamaste/invitations.json` | lamaste:lamaste | 0600 | Pending invitations |
|
|
1033
|
+
| `/etc/lamalibre/lamaste/plugins.json` | lamaste:lamaste | 0600 | Plugin registry |
|
|
1034
|
+
| `/etc/lamalibre/lamaste/storage-config.json` | lamaste:lamaste | 0600 | Storage registry |
|
|
1035
|
+
| `/etc/lamalibre/lamaste/storage-master.key` | lamaste:lamaste | 0600 | Storage encryption key |
|
|
1036
|
+
| `/etc/lamalibre/lamaste/groups.json` | lamaste:lamaste | 0600 | Lamaste groups |
|
|
1037
|
+
| `/etc/lamalibre/lamaste/access-grants.json` | lamaste:lamaste | 0600 | Access grants |
|
|
1038
|
+
| `/etc/lamalibre/lamaste/gatekeeper.json` | lamaste:lamaste | 0600 | Gatekeeper settings |
|
|
1039
|
+
| `/etc/lamalibre/lamaste/access-request-log.json` | lamaste:lamaste | 0600 | Denied access log |
|
|
1040
|
+
| `/etc/lamalibre/lamaste/pki/enrollment-tokens.json` | lamaste:lamaste | 0600 | Enrollment tokens |
|
|
1041
|
+
| `/etc/lamalibre/lamaste/pki/revoked.json` | lamaste:lamaste | 0600 | Revocation list |
|
|
1042
|
+
| `/etc/lamalibre/lamaste/pki/agents/registry.json` | lamaste:lamaste | 0600 | Agent cert metadata |
|
|
1043
|
+
| `/etc/lamalibre/lamaste/chisel-server.key` | lamaste:lamaste-chisel | 0640 | Chisel SSH host key |
|
|
1044
|
+
| `/etc/authelia/` | lamaste:lamaste-authelia | 2770 | Authelia config (setgid) |
|
|
1045
|
+
| `/etc/authelia/configuration.yml` | lamaste:lamaste-authelia | 0640 | Auth config |
|
|
1046
|
+
| `/etc/authelia/users.yml` | lamaste:lamaste-authelia | 0660 | User database |
|
|
1047
|
+
| `/etc/authelia/.secrets.json` | lamaste:lamaste-authelia | 0600 | Auth secrets (panel only) |
|
|
1048
|
+
| `/etc/authelia/db.sqlite3`, `notifications.txt` | lamaste-authelia:lamaste-authelia | 0600 | Authelia's own files |
|
|
1049
|
+
| `/var/log/authelia/` | lamaste-authelia:lamaste-authelia | 0750 | Authelia log |
|
|
1050
|
+
| `/opt/lamalibre/lamaste/` | root:root | 0755 | Install directory (read-only for lamaste) |
|
|
1051
|
+
| `/var/www/lamaste/` | lamaste:www-data | 2750 | Static site files (files 0640; nginx reads via the group) |
|
|
1052
|
+
| `/etc/sudoers.d/lamaste` | root:root | 0440 | Sudo rules (no wildcards) |
|
|
1053
|
+
| `/usr/local/sbin/lamaste-priv`, `lamaste-certbot`, `lamaste-cert-info` | root:root | 0755 | Validating sudo programs |
|
|
1054
|
+
| `/usr/local/bin/chisel`, `/usr/local/bin/authelia` | root:root | 0755 | Pinned releases (`create-lamaste`) |
|
|
1055
|
+
| `~/.lamalibre/lamaste/servers.json` | user | 0600 | Server registry |
|
|
1056
|
+
| `~/.lamalibre/lamaste/agent.json` | user | 0600 | Legacy agent config |
|
|
1057
|
+
| `~/.lamalibre/lamaste/agents/<label>/` | user | 0700 | Agent data directory |
|
|
1058
|
+
| `~/.lamalibre/lamaste/agents/<label>/chisel.json` | user | 0600 | Agent Chisel credential |
|
|
1059
|
+
| `~/.lamalibre/lamaste/agents/<label>/chisel.env` | user | 0600 | Linux `AUTH=` env file |
|
|
1060
|
+
| `~/Library/LaunchAgents/com.lamalibre.lamaste.chisel-<label>.plist` | user | 0600 | macOS service (has `AUTH`) |
|
|
1061
|
+
| `~/.lamalibre/lamaste/services.json` | user | 0600 | Service registry |
|
|
1062
|
+
|
|
1063
|
+
## Quick Reference
|
|
1064
|
+
|
|
1065
|
+
| Config File | Read By | Modified By | Restart Needed? |
|
|
1066
|
+
| ---------------------------- | ------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
1067
|
+
| `panel.json` | lamalibre-lamaste-serverd | lamalibre-lamaste-serverd (atomic write) | No (hot reload) |
|
|
1068
|
+
| `tunnels.json` | lamalibre-lamaste-serverd | lamalibre-lamaste-serverd (atomic write + fsync) | No |
|
|
1069
|
+
| `sites.json` | lamalibre-lamaste-serverd | lamalibre-lamaste-serverd (atomic write + fsync) | No |
|
|
1070
|
+
| `chisel-users` | chisel | lamalibre-lamaste-serverd (rendered, atomic rename, no sudo) | No for additions (hot reload); the panel restarts `chisel` on revocations |
|
|
1071
|
+
| `ticket-scopes.json` | lamalibre-lamaste-serverd | lamalibre-lamaste-serverd (atomic write + mutex) | No |
|
|
1072
|
+
| `tickets.json` | lamalibre-lamaste-serverd | lamalibre-lamaste-serverd (atomic write + mutex) | No |
|
|
1073
|
+
| `storage-config.json` | lamalibre-lamaste-serverd | lamalibre-lamaste-serverd (atomic write + mutex) | No |
|
|
1074
|
+
| `groups.json` | gatekeeper | lamalibre-lamaste-serverd (atomic write + mutex) | No (gatekeeper watches file) |
|
|
1075
|
+
| `access-grants.json` | gatekeeper | lamalibre-lamaste-serverd (atomic write + mutex) | No (gatekeeper watches file) |
|
|
1076
|
+
| `gatekeeper.json` | gatekeeper | lamalibre-lamaste-serverd (atomic write) | Yes (`systemctl restart lamalibre-lamaste-gatekeeper`) |
|
|
1077
|
+
| `access-request-log.json` | lamalibre-lamaste-serverd | gatekeeper (atomic write) | No |
|
|
1078
|
+
| `configuration.yml` | authelia | onboarding provisioning | Yes (`systemctl restart authelia`) |
|
|
1079
|
+
| `users.yml` | authelia | lamalibre-lamaste-serverd (atomic rename, no sudo) | Yes (`systemctl restart authelia`) |
|
|
1080
|
+
| `lamalibre-lamaste-*` vhosts | nginx | lamalibre-lamaste-serverd (via `sudo lamaste-priv nginx-site`) | Yes (`nginx -t && systemctl reload nginx`) |
|