Skip to content

Management Flow ​

Overview ​

After onboarding completes, the panel becomes the full management interface for the Lamaste. All operations that would traditionally require SSH are handled through the UI.

Management Areas ​

Dashboard ​

  • System stats: CPU, RAM, disk usage (polled every 5s)
  • Service health: nginx, Chisel, Authelia, Panel (green/red indicators)
  • Quick overview: active tunnels count, registered users count, cert expiry warnings

Tunnels ​

Full lifecycle management of tunneled applications.

Add Tunnel Flow:

User fills form:
  Subdomain: [app1]  .example.com
  Local port: [8001]
  Agent:     [laptop]
  Description: [My web app]
           [Add Tunnel]
         │
         ▼
POST /api/tunnels
  ├─ tunnel lock taken (held until the response)
  ├─ agentLabel checked against the agent registry; port not reserved, not in use
  ├─ certbot issues TLS cert for app1.example.com
  ├─ nginx vhost written + symlinked + tested
  ├─ systemctl reload nginx
  ├─ tunnels.json updated
  ├─ chisel-users re-rendered: agent-laptop may bind ^R:127\.0\.0\.1:8001$
  │    (Chisel reloads the file itself — an added grant needs no restart)
  └─ response: { ok: true, tunnel: { ..., agentLabel: "laptop" } }
         │
         ▼
UI updates: new tunnel appears in list with its agent
  └─ within ~30 s laptop's sync timer fetches agent-config and starts forwarding 8001

Remove Tunnel Flow:

DELETE /api/tunnels/:id
  ├─ nginx vhost removed + reload
  ├─ tunnels.json updated
  ├─ chisel-users re-rendered (owner's grant for the port withdrawn)
  ├─ systemctl try-restart chisel (a withdrawn grant must end live sessions)
  └─ response: { ok: true }
         │
         ▼
  within ~30 s the owner's sync timer drops the remote — otherwise Chisel would
  reject the owner's whole session, and all its other tunnels with it

Agent Integration:

  • Every tunnel is carried by one agent (agentLabel). The Chisel authfile grants each agent only the ports of the enabled tunnels it carries, so no agent can bind another's port
  • Each agent's sync timer (lamaste-agent sync, every 30 s) fetches that agent's config via GET /api/tunnels/agent-config and converges its Chisel client; lamaste-agent update does the same at once and restarts the client
  • On macOS, the agent writes a launchd plist; on Linux, a systemd user unit. An agent with no tunnels keeps the client stopped

Users (Authelia) ​

CRUD for Authelia users who access tunneled applications.

Add User:

  • Username + display name + email
  • Password (bcrypt hashed, written to users.yml)
  • TOTP enrollment: generate secret, show QR code
  • systemctl reload authelia after users.yml change

Edit User:

  • Change password, display name, email
  • Reset TOTP (generate new secret + QR)

Delete User:

  • Safety: cannot delete last user
  • Removes from users.yml, reloads Authelia

Certificates ​

Track and manage all TLS certificates.

Certificate Types:

  1. Let's Encrypt — per-subdomain, auto-renewing via certbot
  2. mTLS CA — 10yr validity, internal
  3. mTLS Admin — 2yr validity, full panel access, importable to browser
  4. mTLS Agent — 2yr validity, capability-based access, issued per agent

Actions:

  • View all certs with expiry dates
  • Force renewal of Let's Encrypt certs
  • Download the admin p12 (rotation itself is sudo lamaste-server reset-admin on the server; the panel does not issue admin certificates)
  • Generate agent certificates (label, capabilities, download p12, share password)
  • List and revoke agent certificates
  • Update agent capabilities (without reissuing the certificate)
  • Expiry warnings at 30/14/7 days

Services ​

Direct control over system services.

Service Control:

  • Start / Stop / Restart / Reload for: nginx, chisel, authelia, lamalibre-lamaste-serverd
  • Status indicator (active/inactive/failed)
  • Current uptime

Live Logs:

  • WebSocket streaming of journald logs per service
  • Real-time tail with auto-scroll
  • Service selector dropdown

Invitations ​

Admin can invite new users via a shareable link. The invitation workflow is separate from direct user creation.

Create Invitation:

  • Admin provides username, email, optional groups, and expiry (1-30 days, default 7)
  • Server generates a 64-byte hex token and returns an invite URL
  • Invitation is stored in invitations.json

Accept Invitation (public):

  • Invited user opens the invite URL and sets their password
  • Server creates the Authelia user with bcrypt-hashed password
  • Invitation is marked as used

Revoke Invitation:

  • Admin can delete a pending invitation before it is accepted

Static Sites ​

Host static websites directly on the Lamaste server, served via nginx.

Site Types:

  1. Managed — subdomain of the configured domain (e.g., blog.example.com). Certificate and nginx vhost are provisioned automatically on creation.
  2. Custom — external domain. Requires DNS verification before certificate issuance and vhost activation.

Features:

  • SPA mode (single-page application fallback to index.html)
  • Authelia protection (restrict access to authenticated users)
  • Per-site allowed user lists
  • File management: upload, list, and delete files via the API
  • Max upload size: 50 MB per file

API Routes ​

Tunnel Management ​

MethodPathDescriptionRoles
GET/api/tunnelsList tunnels (an agent sees only its own)admin, agent
POST/api/tunnelsAdd tunnel (triggers nginx + certbot + chisel)admin, agent (tunnels:write)
PATCH/api/tunnels/:idMove (admin), access mode, body limit, enableadmin, agent (tunnels:write)
DELETE/api/tunnels/:idRemove tunneladmin, agent (tunnels:write)
GET/api/tunnels/agent-configOne agent's Chisel configadmin, agent (tunnels:read)
GET/api/tunnels/agent-panel-statusCheck agent panel expose statusadmin, agent (panel:expose)
POST/api/tunnels/expose-panelExpose agent management panel as subdomainadmin, agent (panel:expose)
DELETE/api/tunnels/retract-panelRetract agent management paneladmin, agent (panel:expose)

User Management ​

MethodPathDescription
GET/api/usersList Authelia users
POST/api/usersCreate user (bcrypt hash + TOTP secret)
PUT/api/users/:usernameUpdate user
DELETE/api/users/:usernameDelete user (not last)
POST/api/users/:username/reset-totpGenerate new TOTP secret

Certificate Management ​

MethodPathDescription
GET/api/certsList all certs with expiry
GET/api/certs/auto-renew-statusCertbot auto-renewal timer status
POST/api/certs/:domain/renewForce certbot renewal
POST/api/certs/mtls/rotateGenerate new admin client cert + p12
GET/api/certs/mtls/downloadDownload admin client.p12
POST/api/certs/agentGenerate agent-scoped certificate
GET/api/certs/agentList agent certificates
GET/api/certs/agent/:label/downloadDownload agent .p12
PATCH/api/certs/agent/:label/capabilitiesUpdate agent capabilities
PATCH/api/certs/agent/:label/allowed-sitesUpdate agent site access
DELETE/api/certs/agent/:labelRevoke agent certificate

Service Management ​

MethodPathDescriptionRoles
GET/api/servicesList service statusesadmin, agent (services:read)
POST/api/services/:name/:actionstart/stop/restart/reload serviceadmin, agent (services:write)
GET/api/services/:name/logsWebSocket log streamadmin only

Invitation Management ​

MethodPathDescriptionRoles
GET/api/invitationsList all invitations (tokens redacted)admin
POST/api/invitationsCreate a new invitationadmin
DELETE/api/invitations/:idRevoke an invitationadmin

Public invite routes (no mTLS required):

MethodPathDescription
GET/api/invite/:tokenGet invitation details
POST/api/invite/:token/acceptAccept invitation and set password

Static Sites Management ​

MethodPathDescriptionRoles
GET/api/sitesList all static sitesadmin, agent (sites:read)
POST/api/sitesCreate a static siteadmin
DELETE/api/sites/:idDelete a static siteadmin
PATCH/api/sites/:idUpdate site settingsadmin
POST/api/sites/:id/verify-dnsVerify DNS for custom domain siteadmin
GET/api/sites/:id/filesList files in site directoryadmin, agent (sites:read)
POST/api/sites/:id/filesUpload files (multipart)admin, agent (sites:write)
DELETE/api/sites/:id/filesDelete a file from site directoryadmin, agent (sites:write)

System ​

MethodPathDescriptionRoles
GET/api/system/statsCPU, RAM, disk usageadmin, agent (system:read)
GET/api/healthPanel health checkadmin, agent (all)

Sudoers Rules ​

The panel runs as a non-root user (lamaste) and cannot become root. /etc/sudoers.d/lamaste is written by generateSudoersContent() in packages/provisioners/server/src/lib/service-config.js and contains no wildcard at all: a sudoers * matches spaces too, so a rule like certbot renew --cert-name * --non-interactive would also accept --deploy-hook <command>, and mv /tmp/nginx-* /etc/nginx/sites-available/* would accept -t /etc/sudoers.d. Every rule is a fixed command line or a root-owned program that validates its own arguments:

sudoers
# --- systemctl: managed services (fixed command lines) ---
lamaste ALL=(root) NOPASSWD: /usr/bin/systemctl reload nginx
lamaste ALL=(root) NOPASSWD: /usr/bin/systemctl try-restart chisel
# fail-closed startup reconciliation disables chisel, and re-enables it on success
lamaste ALL=(root) NOPASSWD: /usr/bin/systemctl disable chisel
lamaste ALL=(root) NOPASSWD: /usr/bin/systemctl reload authelia
# ... start/stop/restart/enable for nginx, chisel, authelia, certbot.timer,
#     start/stop/restart for lamalibre-lamaste-serverd and lamalibre-lamaste-gatekeeper

# --- nginx config test ---
lamaste ALL=(root) NOPASSWD: /usr/sbin/nginx -t

# --- root-owned programs that validate their own arguments ---
#   lamaste-priv nginx-site write|backup|restore|discard-backup|enable|disable|remove <name>
#   lamaste-priv authelia-totp <username>                    secret on stdin
#   lamaste-priv self-update <version>                       create-lamaste in a transient unit
#   lamaste-certbot issue <email> <cert-name> <domain>...    certbot certonly --nginx
#   lamaste-certbot renew <cert-name> [force] | renew-all | list
#   lamaste-cert-info <lineage> enddate|checkend|san         read-only openssl queries
lamaste ALL=(root) NOPASSWD: /usr/local/sbin/lamaste-priv
lamaste ALL=(root) NOPASSWD: /usr/local/sbin/lamaste-certbot
lamaste ALL=(root) NOPASSWD: /usr/local/sbin/lamaste-cert-info

Everything else the panel does needs no rule: the PKI directory (agent CSR signing), the web root, /etc/authelia and the Chisel authfile and key belong to lamaste or to a group it is in, and binaries, units and service accounts are installed by create-lamaste as root. lamaste-priv installs a vhost only if every directive is on its allow-list — nginx's root master process opens the files a configuration names. See Security Model.

The certbot wrappers accept only lowercase DNS hostnames (no wildcards or path characters, at most 100 per certificate) and a syntactically valid email address. Renewals the panel triggers pass --no-random-sleep-on-renew, because certbot otherwise sleeps up to about 8 minutes before a non-interactive renewal (a delay meant for certbot.timer) while an operator waits.

Redeploying (npx @lamalibre/create-lamaste on an existing install) reinstalls the programs, removes retired ones (lamaste-sign-csr, lamaste-pki-rename), and replaces this file atomically after visudo -c accepts it, so upgrades pick up new rules.

File Operation Safety ​

  • YAML writes (users.yml): write to temp file, then atomic rename
  • nginx changes: always run nginx -t before reload; rollback on failure
  • Authelia changes: reload service after users.yml update
  • Chisel changes: tunnel state is written first, then the authfile is re-rendered from it (per-agent port grants); Chisel reloads it, and is restarted only when a grant or password is withdrawn
  • Last-user protection: never delete the last Authelia user
  • State persistence: tunnels.json updated atomically after each tunnel operation

Released under the PolyForm Noncommercial License 1.0.0