@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,404 @@
|
|
|
1
|
+
# API Overview
|
|
2
|
+
|
|
3
|
+
> Nearly every interaction between the Lamaste management UI and the backend happens through a JSON REST API protected by mTLS client certificates. The exceptions are the invitation acceptance flow (`/api/invite/*`) and the agent enrollment endpoint (`/api/enroll`), which are public.
|
|
4
|
+
|
|
5
|
+
## In Plain English
|
|
6
|
+
|
|
7
|
+
When you open the Lamaste management panel in your browser, the page you see is a single-page application (SPA) built with React. Every button you click — creating a tunnel, adding a user, renewing a certificate — sends a request to the panel server's REST API running on the same machine. The server processes the request, makes changes to the system (writing config files, reloading services), and sends back a JSON response.
|
|
8
|
+
|
|
9
|
+
The API sits behind nginx, which enforces mTLS on the panel vhost — meaning your browser must present a valid client certificate before the connection is even established. Without that certificate, the TLS handshake fails and no HTTP traffic reaches the API at all.
|
|
10
|
+
|
|
11
|
+
There are two exceptions to the mTLS requirement. The `/api/invite/*` routes are registered in a public context without mTLS middleware, so that invited users can accept their invitation and set a password without needing a client certificate. The `/api/enroll` endpoint is also public, allowing agents to complete hardware-bound certificate enrollment using a token previously generated by an admin.
|
|
12
|
+
|
|
13
|
+
## Base URL
|
|
14
|
+
|
|
15
|
+
The API is served by the Fastify panel server at `127.0.0.1:3100`. In production, nginx reverse-proxies to this address. You never call port 3100 directly — all requests go through nginx on port 9292.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
https://<droplet-ip>:9292/api/...
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If a domain has been configured and provisioned:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
https://panel.<your-domain>/api/...
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Both URLs reach the same server. The IP-based URL always works, even if DNS is misconfigured.
|
|
28
|
+
|
|
29
|
+
## Authentication
|
|
30
|
+
|
|
31
|
+
### mTLS Client Certificates
|
|
32
|
+
|
|
33
|
+
All API endpoints except `/api/invite/*` and `/api/enroll` require a valid mTLS client certificate. nginx verifies the certificate at the TLS layer and forwards the result to the panel server via the `X-SSL-Client-Verify` header.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Browser ──HTTPS + client cert──▶ nginx (port 9292)
|
|
37
|
+
nginx checks ssl_client_verify
|
|
38
|
+
✓ SUCCESS → proxies to 127.0.0.1:3100 with X-SSL-Client-Verify: SUCCESS
|
|
39
|
+
✗ FAILED → TLS handshake rejected, no HTTP traffic reaches the API
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
In development mode (`NODE_ENV=development`), the mTLS check is bypassed. A warning is logged once on startup.
|
|
43
|
+
|
|
44
|
+
**Rejection response (403):**
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"error": "mTLS certificate required",
|
|
49
|
+
"details": {
|
|
50
|
+
"hint": "Access to the Lamaste panel requires a valid client certificate."
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### No Session Tokens (with One Exception)
|
|
56
|
+
|
|
57
|
+
The client certificate is the primary authentication mechanism — there are no login endpoints and no bearer tokens. If the certificate is valid, every request is authorized. This is the same model used by LXD.
|
|
58
|
+
|
|
59
|
+
The one exception is the optional **two-factor authentication (2FA)** feature. When 2FA is enabled, admin requests must also carry a valid `lamaste_2fa_session` cookie. This cookie is issued by `POST /api/settings/2fa/verify` after the admin presents a correct TOTP code, and it is HMAC-SHA256 signed, HttpOnly, Secure, SameSite=Strict with a 12-hour absolute expiry and 2-hour inactivity timeout. If a request arrives with a valid mTLS certificate but without a valid 2FA session cookie, the API returns:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"error": "2fa_required"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
with HTTP 401. The 2FA status and verification endpoints are themselves exempt from the 2FA session requirement so that the admin can check status and submit a code without already having a session.
|
|
68
|
+
|
|
69
|
+
## Content Type
|
|
70
|
+
|
|
71
|
+
All request and response bodies use `application/json` unless explicitly noted otherwise:
|
|
72
|
+
|
|
73
|
+
- **File downloads** (certificates) return their native MIME type
|
|
74
|
+
- **File uploads** use `multipart/form-data`
|
|
75
|
+
- **WebSocket connections** use the standard WebSocket upgrade handshake
|
|
76
|
+
|
|
77
|
+
Requests with a JSON body must include the `Content-Type: application/json` header.
|
|
78
|
+
|
|
79
|
+
## Error Format
|
|
80
|
+
|
|
81
|
+
Every error response follows a consistent contract:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"error": "Human-readable error summary",
|
|
86
|
+
"details": {}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Field | Type | Presence | Description |
|
|
91
|
+
| --------- | -------- | -------- | ------------------------------------------------- |
|
|
92
|
+
| `error` | `string` | Always | A short, human-readable error message |
|
|
93
|
+
| `details` | `object` | Optional | Additional structured information about the error |
|
|
94
|
+
|
|
95
|
+
### Validation Errors (400)
|
|
96
|
+
|
|
97
|
+
All request bodies are validated with [Zod](https://zod.dev/) schemas at the route level. When validation fails, the error handler returns a 400 with the Zod issues:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"error": "Validation failed",
|
|
102
|
+
"details": {
|
|
103
|
+
"issues": [
|
|
104
|
+
{
|
|
105
|
+
"path": ["subdomain"],
|
|
106
|
+
"message": "Subdomain must be lowercase alphanumeric with optional hyphens, cannot start or end with a hyphen"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"path": ["port"],
|
|
110
|
+
"message": "Port must be at least 1024"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Operational Errors (4xx)
|
|
118
|
+
|
|
119
|
+
Business logic errors return appropriate HTTP status codes with descriptive messages:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"error": "Cannot delete the last user"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Common status codes:
|
|
128
|
+
|
|
129
|
+
| Code | Meaning | Example |
|
|
130
|
+
| ---- | ----------------------------------- | -------------------------------------------- |
|
|
131
|
+
| 400 | Bad request / validation failed | Invalid subdomain format |
|
|
132
|
+
| 401 | 2FA session required | Valid mTLS cert but no 2FA session cookie |
|
|
133
|
+
| 403 | mTLS certificate missing or invalid | No client cert presented |
|
|
134
|
+
| 404 | Resource not found | Tunnel ID does not exist |
|
|
135
|
+
| 409 | Conflict | Username already exists |
|
|
136
|
+
| 410 | Gone | Onboarding endpoint called after completion |
|
|
137
|
+
| 503 | Service unavailable | Management endpoint called before onboarding |
|
|
138
|
+
|
|
139
|
+
### Internal Errors (500)
|
|
140
|
+
|
|
141
|
+
Unexpected errors return a generic message in production to avoid leaking internal details:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"error": "Internal server error"
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
In development mode, the response includes a `details` object with the error message and stack trace.
|
|
150
|
+
|
|
151
|
+
## Onboarding Guard
|
|
152
|
+
|
|
153
|
+
The API is split into two groups with mutual exclusion enforced by middleware:
|
|
154
|
+
|
|
155
|
+
| Route Group | Prefix | Available When | Otherwise Returns |
|
|
156
|
+
| -------------- | -------------------------------------------------------- | --------------------- | ------------------------- |
|
|
157
|
+
| **Onboarding** | `/api/onboarding/*` | `status != COMPLETED` | `410 Gone` |
|
|
158
|
+
| **Management** | `/api/*` (except health, onboarding, invite, and enroll) | `status == COMPLETED` | `503 Service Unavailable` |
|
|
159
|
+
| **Public** | `/api/invite/*`, `/api/enroll` | Always (no mTLS) | N/A |
|
|
160
|
+
|
|
161
|
+
The `GET /api/onboarding/status` endpoint is always accessible regardless of onboarding state. The `GET /api/health` endpoint is also always accessible — it is registered outside both guards. The `/api/invite/*` and `/api/enroll` routes are registered in a separate public context with no mTLS middleware and no onboarding guard.
|
|
162
|
+
|
|
163
|
+
**410 response (onboarding complete):**
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"error": "Onboarding already completed"
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**503 response (onboarding incomplete):**
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"error": "Onboarding not complete",
|
|
176
|
+
"onboardingStatus": "FRESH"
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Onboarding States
|
|
181
|
+
|
|
182
|
+
The onboarding progresses through a linear state machine:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
FRESH → DOMAIN_SET → DNS_READY → PROVISIONING → COMPLETED
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Each state transition is triggered by a specific API call and validated server-side. You cannot skip states.
|
|
189
|
+
|
|
190
|
+
## CORS Policy
|
|
191
|
+
|
|
192
|
+
Cross-Origin Resource Sharing is configured to accept requests from the panel UI origins:
|
|
193
|
+
|
|
194
|
+
- **Before domain setup:** `https://<droplet-ip>:9292`
|
|
195
|
+
- **After domain setup:** both `https://<droplet-ip>:9292` and `https://panel.<domain>`
|
|
196
|
+
|
|
197
|
+
Requests from other origins are rejected by the CORS policy.
|
|
198
|
+
|
|
199
|
+
## WebSocket Connections
|
|
200
|
+
|
|
201
|
+
Two endpoints use WebSocket for real-time streaming:
|
|
202
|
+
|
|
203
|
+
| Endpoint | Purpose | Protocol |
|
|
204
|
+
| ------------------------------------- | ------------------------ | ------------- |
|
|
205
|
+
| `WS /api/onboarding/provision/stream` | Provisioning progress | JSON messages |
|
|
206
|
+
| `WS /api/services/:name/logs` | Live service log tailing | JSON messages |
|
|
207
|
+
|
|
208
|
+
WebSocket connections follow the standard upgrade handshake over the same HTTPS connection. The `wss://` protocol is used in production since all traffic goes through nginx with TLS.
|
|
209
|
+
|
|
210
|
+
WebSocket messages are always JSON objects. There is no binary framing.
|
|
211
|
+
|
|
212
|
+
## Common Response Patterns
|
|
213
|
+
|
|
214
|
+
### Success with Data
|
|
215
|
+
|
|
216
|
+
Most GET endpoints return the requested resource directly:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"tunnels": [{ "id": "...", "subdomain": "app", "port": 8080 }]
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Success with Confirmation
|
|
225
|
+
|
|
226
|
+
Mutating endpoints typically return an `ok` field:
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"ok": true,
|
|
231
|
+
"tunnel": { "id": "...", "subdomain": "app", "port": 8080 }
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Success with Warning
|
|
236
|
+
|
|
237
|
+
Some operations succeed but produce a non-fatal warning (for example, nginx reload failure after certificate renewal):
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"ok": true,
|
|
242
|
+
"domain": "app.example.com",
|
|
243
|
+
"newExpiry": "2026-06-11T00:00:00.000Z",
|
|
244
|
+
"warning": "Certificate renewed but nginx reload failed"
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## File Upload Limits
|
|
249
|
+
|
|
250
|
+
The server accepts multipart file uploads up to 50 MB per file, used by the static sites file management endpoints.
|
|
251
|
+
|
|
252
|
+
## Rate Limiting
|
|
253
|
+
|
|
254
|
+
There is no general application-level rate limiting. The mTLS requirement means only authenticated administrators can reach the API, and the expected number of concurrent users is one or two. If you are self-hosting and want rate limits, configure them in nginx.
|
|
255
|
+
|
|
256
|
+
There are two exceptions:
|
|
257
|
+
|
|
258
|
+
- **2FA endpoints** (`/confirm`, `/verify`, `/disable`) enforce per-IP rate limiting: 5 attempts per 2-minute window, with a 5-minute ban once the limit is exceeded. This protects against brute-force TOTP guessing even though the caller already holds a valid mTLS certificate.
|
|
259
|
+
- **Ticket requests** (`POST /api/tickets`) enforce per-agent rate limiting: 10 tickets per minute per agent. This protects against resource exhaustion from automated ticket generation.
|
|
260
|
+
|
|
261
|
+
## Quick Reference
|
|
262
|
+
|
|
263
|
+
| Item | Value |
|
|
264
|
+
| --------------------------- | -------------------------------------- |
|
|
265
|
+
| **Base URL (IP)** | `https://<ip>:9292/api` |
|
|
266
|
+
| **Base URL (domain)** | `https://panel.<domain>/api` |
|
|
267
|
+
| **Authentication** | mTLS client certificate |
|
|
268
|
+
| **Content-Type** | `application/json` (default) |
|
|
269
|
+
| **Validation** | Zod schemas at route level |
|
|
270
|
+
| **Error format** | `{ "error": "...", "details": {...} }` |
|
|
271
|
+
| **WebSocket protocol** | `wss://` with JSON messages |
|
|
272
|
+
| **Max upload size** | 50 MB per file |
|
|
273
|
+
| **Internal listen address** | `127.0.0.1:3100` |
|
|
274
|
+
|
|
275
|
+
### Endpoint Summary
|
|
276
|
+
|
|
277
|
+
| Method | Path | Group | Description |
|
|
278
|
+
| ------ | ----------------------------------------------------- | ---------- | ---------------------------------------- |
|
|
279
|
+
| GET | `/api/health` | Always | Health check |
|
|
280
|
+
| GET | `/api/onboarding/status` | Always | Onboarding state |
|
|
281
|
+
| POST | `/api/onboarding/domain` | Onboarding | Set domain and email |
|
|
282
|
+
| POST | `/api/onboarding/verify-dns` | Onboarding | Verify DNS records |
|
|
283
|
+
| POST | `/api/onboarding/provision` | Onboarding | Start provisioning |
|
|
284
|
+
| WS | `/api/onboarding/provision/stream` | Onboarding | Provisioning progress |
|
|
285
|
+
| GET | `/api/invite/:token` | Public | Get invitation details |
|
|
286
|
+
| POST | `/api/invite/:token/accept` | Public | Accept invitation |
|
|
287
|
+
| POST | `/api/enroll` | Public | Enroll agent with token (hardware-bound) |
|
|
288
|
+
| GET | `/api/system/stats` | Management | System statistics |
|
|
289
|
+
| POST | `/api/system/update` | Management | Trigger background server update |
|
|
290
|
+
| POST | `/api/agents/plugins/report` | Management | Report agent plugin capabilities |
|
|
291
|
+
| GET | `/api/agents/me/chisel-credential` | Management | The calling agent's Chisel credential |
|
|
292
|
+
| POST | `/api/agents/me/chisel-credential/rotate` | Management | Rotate own Chisel credential (agent) |
|
|
293
|
+
| POST | `/api/agents/:label/chisel-credential/rotate` | Management | Rotate an agent's Chisel credential |
|
|
294
|
+
| GET | `/api/tunnels/agent-config` | Management | One agent's tunnel configuration |
|
|
295
|
+
| GET | `/api/tunnels` | Management | List tunnels |
|
|
296
|
+
| POST | `/api/tunnels` | Management | Create tunnel |
|
|
297
|
+
| PATCH | `/api/tunnels/:id` | Management | Move, access mode, body limit, enable |
|
|
298
|
+
| DELETE | `/api/tunnels/:id` | Management | Delete tunnel |
|
|
299
|
+
| GET | `/api/sites` | Management | List static sites |
|
|
300
|
+
| POST | `/api/sites` | Management | Create static site |
|
|
301
|
+
| DELETE | `/api/sites/:id` | Management | Delete static site |
|
|
302
|
+
| PATCH | `/api/sites/:id` | Management | Update site settings |
|
|
303
|
+
| POST | `/api/sites/:id/verify-dns` | Management | Verify site DNS |
|
|
304
|
+
| GET | `/api/sites/:id/files` | Management | List site files |
|
|
305
|
+
| POST | `/api/sites/:id/files` | Management | Upload site files |
|
|
306
|
+
| DELETE | `/api/sites/:id/files` | Management | Delete site file |
|
|
307
|
+
| GET | `/api/invitations` | Management | List invitations |
|
|
308
|
+
| POST | `/api/invitations` | Management | Create invitation |
|
|
309
|
+
| DELETE | `/api/invitations/:id` | Management | Revoke invitation |
|
|
310
|
+
| GET | `/api/users` | Management | List users |
|
|
311
|
+
| POST | `/api/users` | Management | Create user |
|
|
312
|
+
| PUT | `/api/users/:username` | Management | Update user |
|
|
313
|
+
| DELETE | `/api/users/:username` | Management | Delete user |
|
|
314
|
+
| POST | `/api/users/:username/reset-totp` | Management | Reset TOTP secret |
|
|
315
|
+
| GET | `/api/certs` | Management | List certificates |
|
|
316
|
+
| GET | `/api/certs/auto-renew-status` | Management | Auto-renew timer status |
|
|
317
|
+
| POST | `/api/certs/:domain/renew` | Management | Force-renew certificate |
|
|
318
|
+
| POST | `/api/certs/mtls/rotate` | Management | Rotate mTLS cert |
|
|
319
|
+
| GET | `/api/certs/mtls/download` | Management | Download client.p12 |
|
|
320
|
+
| POST | `/api/certs/agent` | Management | Generate agent certificate |
|
|
321
|
+
| GET | `/api/certs/agent` | Management | List agent certificates |
|
|
322
|
+
| GET | `/api/certs/agent/:label/download` | Management | Download agent .p12 |
|
|
323
|
+
| PATCH | `/api/certs/agent/:label/capabilities` | Management | Update agent capabilities |
|
|
324
|
+
| PATCH | `/api/certs/agent/:label/allowed-sites` | Management | Update agent site access |
|
|
325
|
+
| DELETE | `/api/certs/agent/:label` | Management | Revoke agent certificate |
|
|
326
|
+
| POST | `/api/certs/agent/enroll` | Management | Generate enrollment token |
|
|
327
|
+
| DELETE | `/api/certs/agent/enroll/:label` | Management | Revoke unused enrollment token |
|
|
328
|
+
| POST | `/api/certs/agent/upgrade-cert` | Management | Upgrade agent cert to hardware-bound |
|
|
329
|
+
| POST | `/api/certs/admin/upgrade-to-hardware-bound` | Management | Upgrade admin to hardware-bound |
|
|
330
|
+
| GET | `/api/certs/admin/auth-mode` | Management | Get admin auth mode |
|
|
331
|
+
| GET | `/api/settings/2fa` | Management | Get 2FA status |
|
|
332
|
+
| POST | `/api/settings/2fa/setup` | Management | Generate TOTP secret |
|
|
333
|
+
| POST | `/api/settings/2fa/confirm` | Management | Confirm initial code, enable 2FA |
|
|
334
|
+
| POST | `/api/settings/2fa/verify` | Management | Verify code, issue session cookie |
|
|
335
|
+
| POST | `/api/settings/2fa/disable` | Management | Disable 2FA |
|
|
336
|
+
| GET | `/api/services` | Management | List service statuses |
|
|
337
|
+
| POST | `/api/services/:name/:action` | Management | Control a service (start/stop/restart) |
|
|
338
|
+
| WS | `/api/services/:name/logs` | Management | Stream service logs |
|
|
339
|
+
| GET | `/api/plugins` | Management | List installed plugins |
|
|
340
|
+
| GET | `/api/plugins/:name` | Management | Get plugin details |
|
|
341
|
+
| POST | `/api/plugins/install` | Management | Install a plugin |
|
|
342
|
+
| POST | `/api/plugins/:name/enable` | Management | Enable a plugin |
|
|
343
|
+
| POST | `/api/plugins/:name/disable` | Management | Disable a plugin |
|
|
344
|
+
| DELETE | `/api/plugins/:name` | Management | Uninstall a plugin |
|
|
345
|
+
| GET | `/api/plugins/push-install/config` | Management | Get push install configuration |
|
|
346
|
+
| PATCH | `/api/plugins/push-install/config` | Management | Update push install configuration |
|
|
347
|
+
| GET | `/api/plugins/push-install/policies` | Management | List push install policies |
|
|
348
|
+
| POST | `/api/plugins/push-install/policies` | Management | Create push install policy |
|
|
349
|
+
| PATCH | `/api/plugins/push-install/policies/:id` | Management | Update push install policy |
|
|
350
|
+
| DELETE | `/api/plugins/push-install/policies/:id` | Management | Delete push install policy |
|
|
351
|
+
| POST | `/api/plugins/push-install/enable/:label` | Management | Enable push install for agent |
|
|
352
|
+
| DELETE | `/api/plugins/push-install/enable/:label` | Management | Disable push install for agent |
|
|
353
|
+
| GET | `/api/plugins/push-install/agent-status` | Management | Agent checks own push install status |
|
|
354
|
+
| POST | `/api/plugins/push-install/:label` | Management | Send push install command to agent |
|
|
355
|
+
| GET | `/api/plugins/push-install/sessions` | Management | List push install audit log |
|
|
356
|
+
| POST | `/api/tickets/scopes` | Management | Register ticket scope |
|
|
357
|
+
| GET | `/api/tickets/scopes` | Management | List scopes, instances, assignments |
|
|
358
|
+
| DELETE | `/api/tickets/scopes/:name` | Management | Delete ticket scope |
|
|
359
|
+
| POST | `/api/tickets/instances` | Management | Register instance |
|
|
360
|
+
| DELETE | `/api/tickets/instances/:instanceId` | Management | Deregister instance |
|
|
361
|
+
| POST | `/api/tickets/instances/:instanceId/heartbeat` | Management | Instance heartbeat |
|
|
362
|
+
| POST | `/api/tickets/assignments` | Management | Assign agent to instance |
|
|
363
|
+
| DELETE | `/api/tickets/assignments/:agentLabel/:instanceScope` | Management | Remove assignment |
|
|
364
|
+
| GET | `/api/tickets/assignments` | Management | List assignments |
|
|
365
|
+
| POST | `/api/tickets` | Management | Request ticket |
|
|
366
|
+
| GET | `/api/tickets/inbox` | Management | Check ticket inbox |
|
|
367
|
+
| POST | `/api/tickets/validate` | Management | Validate and consume ticket |
|
|
368
|
+
| GET | `/api/tickets` | Management | List all tickets (admin) |
|
|
369
|
+
| DELETE | `/api/tickets/:ticketId` | Management | Revoke ticket |
|
|
370
|
+
| POST | `/api/tickets/sessions` | Management | Create session from ticket |
|
|
371
|
+
| POST | `/api/tickets/sessions/:sessionId/heartbeat` | Management | Session heartbeat |
|
|
372
|
+
| PATCH | `/api/tickets/sessions/:sessionId` | Management | Update session status |
|
|
373
|
+
| DELETE | `/api/tickets/sessions/:sessionId` | Management | Kill session |
|
|
374
|
+
| GET | `/api/tickets/sessions` | Management | List sessions |
|
|
375
|
+
| POST | `/api/storage/servers` | Management | Register a storage server |
|
|
376
|
+
| GET | `/api/storage/servers` | Management | List registered storage servers |
|
|
377
|
+
| DELETE | `/api/storage/servers/:id` | Management | Remove a storage server |
|
|
378
|
+
| POST | `/api/storage/bindings` | Management | Bind storage to plugin |
|
|
379
|
+
| GET | `/api/storage/bindings` | Management | List all bindings |
|
|
380
|
+
| GET | `/api/storage/bindings/:pluginName` | Management | Get binding for plugin |
|
|
381
|
+
| DELETE | `/api/storage/bindings/:pluginName` | Management | Unbind storage from plugin |
|
|
382
|
+
|
|
383
|
+
### Agent Capabilities
|
|
384
|
+
|
|
385
|
+
Agent certificates use capability-based access control. Base capabilities are always available; plugins can declare additional capabilities in their manifest.
|
|
386
|
+
|
|
387
|
+
**Base capabilities:**
|
|
388
|
+
|
|
389
|
+
| Capability | Description |
|
|
390
|
+
| ---------------- | ------------------------------------------------------------------------ |
|
|
391
|
+
| `tunnels:read` | List own tunnels, fetch own Chisel config (always-on, cannot be removed) |
|
|
392
|
+
| `tunnels:write` | Create, update and delete tunnels the agent carries |
|
|
393
|
+
| `services:read` | View service status |
|
|
394
|
+
| `services:write` | Start, stop, and restart services |
|
|
395
|
+
| `system:read` | View system stats (CPU, RAM, disk) |
|
|
396
|
+
| `sites:read` | List sites and browse files |
|
|
397
|
+
| `sites:write` | Upload and delete files on assigned sites |
|
|
398
|
+
| `panel:expose` | Expose agent management panel at `agent-<label>.<domain>` |
|
|
399
|
+
| `identity:read` | Parse Authelia identity headers on plugin routes |
|
|
400
|
+
| `identity:query` | Query panel for Authelia user metadata |
|
|
401
|
+
|
|
402
|
+
**Plugin-declared capabilities:** Plugins can declare additional capabilities in their `lamaste-plugin.json` manifest using either a flat array (`"capabilities": ["scope:action"]`) or a nested object (`"capabilities": { "agent": ["scope:action"] }`). Both formats are normalized to a flat array internally. These are merged with base capabilities and available for assignment to agent certificates. Capabilities are validated dynamically via `getValidCapabilities()`.
|
|
403
|
+
|
|
404
|
+
**Ticket scope capabilities:** Ticket scopes (registered via `POST /api/tickets/scopes`) declare capabilities that are dynamically merged with base and plugin capabilities. For example, a scope named `shell` declaring `scopes: [{ name: "shell:connect" }]` makes `shell:connect` available for assignment to agent certificates. See the [Tickets API](tickets.md) for details.
|