@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,406 @@
|
|
|
1
|
+
# Cloud Provisioning
|
|
2
|
+
|
|
3
|
+
> Create a Lamaste server on DigitalOcean directly from the desktop app — no SSH, no terminal commands, no manual configuration.
|
|
4
|
+
|
|
5
|
+
## In Plain English
|
|
6
|
+
|
|
7
|
+
The traditional way to set up Lamaste involves SSH-ing into a VPS and running an installer command. Cloud provisioning eliminates all of that. You open the desktop app, paste a DigitalOcean API token, pick a region, and click a button. Five minutes later, you have a fully configured Lamaste server with your certificate already installed.
|
|
8
|
+
|
|
9
|
+
Behind the scenes, the app creates a droplet, installs Lamaste over SSH using a temporary key (which is deleted afterward), downloads your admin certificate, and stores your credentials securely in your operating system's credential store (macOS Keychain or Linux libsecret). You never see an SSH session, and no secrets are stored in plaintext files.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
Before you start, make sure you have:
|
|
14
|
+
|
|
15
|
+
| Requirement | Details |
|
|
16
|
+
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| **Desktop app installed** | `npx @lamalibre/create-lamaste-desktop@4.0.0` ([setup guide](desktop-app-setup.md)) |
|
|
18
|
+
| **DigitalOcean account** | A free account at [cloud.digitalocean.com](https://cloud.digitalocean.com). **If you have other infrastructure on DO, create a dedicated team first** (see below) |
|
|
19
|
+
| **Payment method** | A credit card or PayPal on file in DigitalOcean (required to create droplets) |
|
|
20
|
+
| **Domain name** | Optional for initial setup — you can add a domain later through the panel |
|
|
21
|
+
|
|
22
|
+
**Cost:** $4/month for the droplet (512MB RAM, 1 vCPU, 10GB SSD). This is the smallest DigitalOcean droplet and is all Lamaste needs.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Step 1: Create a DigitalOcean API Token
|
|
27
|
+
|
|
28
|
+
Lamaste needs an API token to create and manage droplets on your behalf. The token must have exactly the right permissions — too few and provisioning fails, too many and the app rejects it for safety.
|
|
29
|
+
|
|
30
|
+
### Use a dedicated DigitalOcean team (strongly recommended)
|
|
31
|
+
|
|
32
|
+
DigitalOcean API tokens are account-wide — a token with `droplet:delete` can delete _any_ droplet in the account, not just ones created by Lamaste. While the app enforces a `lamalibre:managed` + `product:lamaste` tag check before destroying a droplet, that is an application-level guard. The token itself still has API-level access to all droplets.
|
|
33
|
+
|
|
34
|
+
**If you have other infrastructure on DigitalOcean (databases, Kubernetes clusters, production droplets, etc.), create a separate DigitalOcean team for Lamaste.** This is the only way to get true resource-level isolation:
|
|
35
|
+
|
|
36
|
+
1. Go to **Settings → Team** in the DigitalOcean console
|
|
37
|
+
2. Click **Create a Team**
|
|
38
|
+
3. Name it something like "Lamaste" and add your account
|
|
39
|
+
4. Switch to the new team context (top-left dropdown in the DO console)
|
|
40
|
+
5. Create the API token _within this team_
|
|
41
|
+
|
|
42
|
+
Tokens created in the Lamaste team can only see and manage resources that belong to that team. Even if the token were compromised, it could not touch any resources in your main account or other teams. This is the strongest isolation DigitalOcean offers and costs nothing extra.
|
|
43
|
+
|
|
44
|
+
> **If you are the only one using your DigitalOcean account and have no other infrastructure there, a separate team is optional.** The custom-scoped token described below is sufficient. But if there is anything else in the account you care about, use a team.
|
|
45
|
+
|
|
46
|
+
### Creating the token
|
|
47
|
+
|
|
48
|
+
1. Log in to [cloud.digitalocean.com](https://cloud.digitalocean.com)
|
|
49
|
+
2. **Switch to your Lamaste team** if you created one (top-left dropdown)
|
|
50
|
+
3. Go to **API** in the left sidebar (or navigate directly to [cloud.digitalocean.com/account/api/tokens](https://cloud.digitalocean.com/account/api/tokens))
|
|
51
|
+
4. Click **Generate New Token**
|
|
52
|
+
5. Give it a name you will recognize (e.g., "Lamaste Desktop")
|
|
53
|
+
6. Set the expiration to your preference (90 days is a good balance)
|
|
54
|
+
7. Under **Custom Scopes**, select these 5 resource groups:
|
|
55
|
+
|
|
56
|
+
| Resource group | Scopes granted | Why Lamaste needs it |
|
|
57
|
+
| ----------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
58
|
+
| **account** | `read` | Validate the token and display your account email |
|
|
59
|
+
| **droplet** | `create`, `read`, `update`, `delete`, `admin` | Create, monitor, and destroy the server |
|
|
60
|
+
| **regions** | `read` | List available regions and measure latency |
|
|
61
|
+
| **ssh_key** | `create`, `read`, `update`, `delete` | Upload a temporary SSH key for installation |
|
|
62
|
+
| **tag** | `create`, `read`, `delete` | Tag managed droplets with `lamalibre:managed` + `product:lamaste` |
|
|
63
|
+
| **domain** _(optional)_ | `read`, `create`, `update`, `delete` | Automatic DNS record creation (see [DNS Management](#dns-management-optional) below) |
|
|
64
|
+
|
|
65
|
+
> **Note:** DigitalOcean's custom scopes UI works at the resource level — you cannot select individual sub-scopes (e.g., `droplet:create` alone). Selecting "droplet" grants all 5 droplet sub-scopes. DO also auto-adds read-only dependency scopes (`sizes:read`, `actions:read`, `image:read`, `snapshot:read`, `vpc:read`). This is normal. Your token will show about 20 total scopes. The app expects this and will not reject these extra scopes — only scopes like `database:delete`, `kubernetes:create`, or `account:write` are rejected.
|
|
66
|
+
>
|
|
67
|
+
> **DNS scopes are optional.** If your token includes the **domain** resource group, the wizard adds a Domain step where you can select a DigitalOcean-managed domain and have A records created automatically. If the token does not have domain scopes, the wizard skips this step and you configure DNS manually after provisioning (the existing behavior).
|
|
68
|
+
|
|
69
|
+
8. Click **Generate Token**
|
|
70
|
+
9. **Copy the token immediately** — DigitalOcean only shows it once
|
|
71
|
+
|
|
72
|
+
> **Do not use a full-access token.** The app intentionally rejects tokens with dangerous scopes like `account:write`, `database:create`, `firewall:delete`, `kubernetes:create`, `volume:create`, etc. This is a safety measure — Lamaste should never have permission to touch your databases, Kubernetes clusters, or account settings. If you see a "dangerous excess scopes" warning, create a new token with only the 5 resource groups listed above.
|
|
73
|
+
|
|
74
|
+
### Isolation summary
|
|
75
|
+
|
|
76
|
+
The combination of a dedicated team and custom-scoped token provides two layers of isolation:
|
|
77
|
+
|
|
78
|
+
| Layer | What it protects against |
|
|
79
|
+
| ----------------------------------------------- | ---------------------------------------------------------- |
|
|
80
|
+
| **Dedicated team** | Token cannot see or touch resources outside the team |
|
|
81
|
+
| **Custom scopes (5 groups)** | Token cannot manage databases, firewalls, Kubernetes, etc. |
|
|
82
|
+
| **`lamalibre:managed` + `product:lamaste` tag** | App-level guard: refuses to destroy untagged droplets |
|
|
83
|
+
| **Dangerous scope rejection** | App rejects tokens that are overly broad |
|
|
84
|
+
|
|
85
|
+
### Where the token is stored
|
|
86
|
+
|
|
87
|
+
The token is stored in your operating system's credential store:
|
|
88
|
+
|
|
89
|
+
- **macOS:** Keychain (service: `com.lamalibre.cloud`)
|
|
90
|
+
- **Linux:** libsecret / GNOME Keyring (via `secret-tool`)
|
|
91
|
+
|
|
92
|
+
The token is never written to a file on disk and never passed as a command-line argument (which would be visible in process listings). When the app needs to use the token, it reads it from the credential store and passes it to the provisioning process via an environment variable.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Step 2: Open the Server Wizard
|
|
97
|
+
|
|
98
|
+
1. Open the Lamaste desktop app
|
|
99
|
+
2. Navigate to the **Servers** tab (cloud icon in the sidebar)
|
|
100
|
+
3. Click **Create New Server** (or, if this is your first time and no servers exist, click the "Create a new server" button in the center of the page)
|
|
101
|
+
|
|
102
|
+
The wizard opens with an overview screen (shown once, dismissable) followed by steps in a breadcrumb bar: **Token → Region → Size → [Domain] → Label → Create**. The Domain step appears only if your token has DNS management scopes (the `domain` resource group).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Step 3: Validate Your Token
|
|
107
|
+
|
|
108
|
+
1. Paste your DigitalOcean API token into the token field
|
|
109
|
+
- If you previously saved a token, the field shows "Token saved in keychain" — you can leave it blank to reuse the saved token
|
|
110
|
+
2. Click **Validate**
|
|
111
|
+
|
|
112
|
+
The app checks three things:
|
|
113
|
+
|
|
114
|
+
- **Is the token valid?** — It calls the DigitalOcean API to verify the token works and reads your account email
|
|
115
|
+
- **Does it have all required scopes?** — All 5 required resource groups listed above must be present
|
|
116
|
+
- **Does it have dangerous scopes?** — Scopes like `account:write` or `database:delete` cause rejection
|
|
117
|
+
|
|
118
|
+
### What you will see
|
|
119
|
+
|
|
120
|
+
**If the token is valid:**
|
|
121
|
+
|
|
122
|
+
A green checkmark appears with your DigitalOcean account email. The **Next** button becomes active.
|
|
123
|
+
|
|
124
|
+
**If scopes are missing:**
|
|
125
|
+
|
|
126
|
+
A red message lists the missing scopes. Go back to DigitalOcean and create a new token with all 5 required resource groups.
|
|
127
|
+
|
|
128
|
+
**If dangerous scopes are detected:**
|
|
129
|
+
|
|
130
|
+
An amber warning lists the excess scopes. This means you used a full-access or overly broad token. Create a new token with custom scopes — only the 5 required resource groups listed above.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Step 4: Choose a Region
|
|
135
|
+
|
|
136
|
+
After validating your token, click **Next**. The app fetches all DigitalOcean regions and measures the network latency from your machine to each one.
|
|
137
|
+
|
|
138
|
+
You will see a grid of region cards, each showing:
|
|
139
|
+
|
|
140
|
+
- **Region name** (e.g., Frankfurt 1, New York 1, Singapore 1)
|
|
141
|
+
- **Region slug** (e.g., `fra1`, `nyc1`, `sgp1`)
|
|
142
|
+
- **Latency** in milliseconds
|
|
143
|
+
|
|
144
|
+
The regions are sorted by latency — the fastest one is at the top and is auto-selected. Pick the region closest to your users (or closest to you, if you are the only user).
|
|
145
|
+
|
|
146
|
+
> **Tip:** If you are in Europe, `fra1` or `ams3` are usually the fastest. In the US, `nyc1`, `nyc3`, or `sfo3`. In Asia-Pacific, `sgp1` or `blr1`.
|
|
147
|
+
|
|
148
|
+
Only regions that support the minimum droplet size (`s-1vcpu-512mb-10gb`) are shown. If a region does not support this size, it is filtered out automatically. All shown regions also support larger sizes available in the Size step.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Step 5: Select a Droplet Size
|
|
153
|
+
|
|
154
|
+
After choosing a region, the wizard shows available droplet sizes sorted by price. The recommended size ($4/month, 512MB RAM, 1 vCPU, 10GB SSD) is pre-selected and sufficient for most Lamaste deployments. Larger sizes are available if you need more resources.
|
|
155
|
+
|
|
156
|
+
Only basic-tier sizes available in your selected region are shown. AMD/Intel-specific variants are filtered out for simplicity.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Step 6: Select a Domain (Optional — DNS Management)
|
|
161
|
+
|
|
162
|
+
This step appears only if your token includes the `domain` resource group. If it does not, the wizard skips directly to "Name Your Server."
|
|
163
|
+
|
|
164
|
+
When the Domain step appears, the app fetches your DigitalOcean-managed domains and displays them as selectable cards:
|
|
165
|
+
|
|
166
|
+
1. **Select a domain** — Click on a domain you already manage in DigitalOcean DNS
|
|
167
|
+
2. **Or create a new domain** — Click "Add a domain," enter the domain name, and click **Create**
|
|
168
|
+
|
|
169
|
+
> **Important:** If you create a new domain, you must point your domain's nameservers to DigitalOcean (`ns1.digitalocean.com`, `ns2.digitalocean.com`, `ns3.digitalocean.com`) at your domain registrar for DNS records to resolve.
|
|
170
|
+
|
|
171
|
+
3. **Optional subdomain prefix** — After selecting a domain, you can enter a subdomain prefix (e.g., `panel`). The resulting FQDN will be `panel.example.com`
|
|
172
|
+
|
|
173
|
+
The wizard shows a preview of the DNS records that will be created:
|
|
174
|
+
|
|
175
|
+
- **A record** — `panel.example.com` → droplet IP
|
|
176
|
+
- **Wildcard A record** — `*.panel.example.com` → droplet IP (for tunnel subdomains)
|
|
177
|
+
|
|
178
|
+
> **DNS records are not auto-removed** when the server is destroyed. You must remove them manually in the DigitalOcean DNS console.
|
|
179
|
+
|
|
180
|
+
### Conflict handling
|
|
181
|
+
|
|
182
|
+
If an A record already exists for the selected domain/subdomain:
|
|
183
|
+
|
|
184
|
+
- **Same IP** — No action needed, the record is already correct
|
|
185
|
+
- **Different IP** — The wizard warns you but does not overwrite. You must update the record manually
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Step 7: Name Your Server
|
|
190
|
+
|
|
191
|
+
Enter a label for your server. This is a short name used to identify the server in the app and on DigitalOcean.
|
|
192
|
+
|
|
193
|
+
**Rules:**
|
|
194
|
+
|
|
195
|
+
- Lowercase letters, numbers, and hyphens only
|
|
196
|
+
- Must start with a letter or number
|
|
197
|
+
- Maximum 64 characters
|
|
198
|
+
|
|
199
|
+
If you leave it blank, it defaults to `lamaste-{region}` (e.g., `lamaste-fra1`).
|
|
200
|
+
|
|
201
|
+
A summary box shows what will be created:
|
|
202
|
+
|
|
203
|
+
- **Size:** Your selected droplet size (e.g., 512MB RAM / 1 vCPU / 10GB SSD)
|
|
204
|
+
- **Image:** Ubuntu 24.04 LTS
|
|
205
|
+
- **Region:** Your selected region
|
|
206
|
+
|
|
207
|
+
Click **Create Server** to begin provisioning.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Step 8: Watch the Provisioning
|
|
212
|
+
|
|
213
|
+
The wizard shows up to 12 steps with live progress indicators. Each step shows a spinning cyan icon while in progress, a green checkmark when complete, or a red X if something fails.
|
|
214
|
+
|
|
215
|
+
| Step | What happens |
|
|
216
|
+
| ------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
217
|
+
| **Validating token** | Re-verifies the API token (defense in depth) |
|
|
218
|
+
| **Generating SSH key** | Creates a temporary ed25519 keypair (used only for this installation, then deleted) |
|
|
219
|
+
| **Uploading SSH key** | Uploads the public key to your DigitalOcean account |
|
|
220
|
+
| **Creating droplet** | Creates a droplet with the selected size, Ubuntu 24.04, and the `lamalibre:managed` + `product:lamaste` tag |
|
|
221
|
+
| **Waiting for boot** | Polls DigitalOcean until the droplet has a public IP and is ready (up to 5 minutes) |
|
|
222
|
+
| **Setting up DNS records** | Creates A and wildcard A records in DigitalOcean DNS (only if a domain was selected in the Domain step) |
|
|
223
|
+
| **Connecting via SSH** | Establishes an SSH connection using the temporary key |
|
|
224
|
+
| **Installing Lamaste** | Runs `npx @lamalibre/create-lamaste@4.0.0` on the droplet (up to 10 minutes) |
|
|
225
|
+
| **Retrieving credentials** | Downloads the admin certificate (`.p12` file) from the droplet |
|
|
226
|
+
| **Enrolling admin certificate** | Imports the certificate into your OS credential store |
|
|
227
|
+
| **Saving configuration** | Writes the server entry to `~/.lamalibre/lamaste/servers.json` |
|
|
228
|
+
| **Cleaning up** | Deletes the temporary SSH key from DigitalOcean and your machine |
|
|
229
|
+
|
|
230
|
+
The entire process typically takes 3–5 minutes, depending on the region and network conditions.
|
|
231
|
+
|
|
232
|
+
> **Do not close the wizard during provisioning.** The close button is disabled while provisioning is in progress. If something goes wrong, the app automatically cleans up — destroying the droplet, removing the SSH key, and deleting temporary files.
|
|
233
|
+
|
|
234
|
+
### Certificate enrollment by platform
|
|
235
|
+
|
|
236
|
+
- **macOS:** The app generates a hardware-bound certificate in your Keychain. The private key is marked as non-extractable — it cannot be exported or copied. This is the most secure option.
|
|
237
|
+
- **Linux:** The app saves the `.p12` certificate file to `~/.lamalibre/lamaste/servers/{id}/client.p12`. The P12 password is stored in libsecret, not in any file.
|
|
238
|
+
|
|
239
|
+
### When provisioning completes
|
|
240
|
+
|
|
241
|
+
A green success message appears. Click **Done** to close the wizard. Your new server appears in the Servers list as the active server, and the app automatically connects to it.
|
|
242
|
+
|
|
243
|
+
### If provisioning fails
|
|
244
|
+
|
|
245
|
+
A red error message appears below the step that failed. The app runs cleanup automatically:
|
|
246
|
+
|
|
247
|
+
1. Destroys the droplet (if it was created)
|
|
248
|
+
2. Removes the SSH key from DigitalOcean (if it was uploaded)
|
|
249
|
+
3. Deletes local temporary files
|
|
250
|
+
|
|
251
|
+
You can click **Retry** to start over from the beginning, or close the wizard and try again later.
|
|
252
|
+
|
|
253
|
+
Common failure causes:
|
|
254
|
+
|
|
255
|
+
| Error | Likely cause |
|
|
256
|
+
| --------------------------------------------- | -------------------------------------------------------------- |
|
|
257
|
+
| Token validation failed | Token expired or scopes changed since step 1 |
|
|
258
|
+
| Droplet creation failed | DigitalOcean account limit reached or payment issue |
|
|
259
|
+
| Timed out waiting for boot | Rare DigitalOcean infrastructure delay — retry usually works |
|
|
260
|
+
| SSH connection failed | Firewall or network issue between your machine and the droplet |
|
|
261
|
+
| Installation failed | Transient npm registry issue — retry usually works |
|
|
262
|
+
| Another provisioning operation is in progress | A previous provisioning attempt is still running |
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## After Provisioning
|
|
267
|
+
|
|
268
|
+
### What you have now
|
|
269
|
+
|
|
270
|
+
- A DigitalOcean droplet running Lamaste, accessible at `https://<ip>:9292`
|
|
271
|
+
- Your admin certificate installed in your OS credential store
|
|
272
|
+
- The server registered in the desktop app as the active server
|
|
273
|
+
|
|
274
|
+
### Next steps
|
|
275
|
+
|
|
276
|
+
1. **Complete onboarding** — Click the **Panel** button on the server card to open the admin panel in your browser. The onboarding wizard will walk you through setting up your domain and provisioning the tunnel stack (Chisel, Authelia, Let's Encrypt).
|
|
277
|
+
|
|
278
|
+
2. **Create your first tunnel** — After onboarding, go to the **Tunnels** tab in the desktop app to expose a local service.
|
|
279
|
+
|
|
280
|
+
3. **Discover services** — The **Services** tab auto-detects running services (Ollama, PostgreSQL, Docker containers, etc.) and lets you expose them with one click.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Managing Multiple Servers
|
|
285
|
+
|
|
286
|
+
The desktop app supports managing multiple Lamaste servers from a single interface.
|
|
287
|
+
|
|
288
|
+
### Switching servers
|
|
289
|
+
|
|
290
|
+
Each server card shows a **Set Active** button. Click it to switch the app's active connection to that server. The switch is instant — the app reloads its configuration to point at the new server.
|
|
291
|
+
|
|
292
|
+
Only one server can be active at a time. The active server is indicated by a cyan "Active" badge on its card.
|
|
293
|
+
|
|
294
|
+
### Server health monitoring
|
|
295
|
+
|
|
296
|
+
Each server card shows an online/offline status indicator (green or red dot). The app checks server health every 30 seconds by pinging the panel's `/api/health` endpoint. If a server is offline, the dot turns red — this does not affect other servers.
|
|
297
|
+
|
|
298
|
+
### Opening the panel
|
|
299
|
+
|
|
300
|
+
Click the **Panel** button on any server card to open that server's admin panel in your browser. This works regardless of which server is currently active in the app.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Adding an Existing Server
|
|
305
|
+
|
|
306
|
+
If you already have a Lamaste server set up (via the manual SSH method), you can add it to the desktop app without cloud provisioning.
|
|
307
|
+
|
|
308
|
+
1. Go to the **Servers** tab
|
|
309
|
+
2. Click **Add Existing Server** (from the dropdown or the empty-state button)
|
|
310
|
+
3. Enter the **Panel URL** (e.g., `https://203.0.113.42:9292`)
|
|
311
|
+
- Must use HTTPS
|
|
312
|
+
- Private/reserved IP addresses are blocked (localhost, 10.x, 192.168.x, etc.)
|
|
313
|
+
4. Optionally enter a **Label** (defaults to the hostname)
|
|
314
|
+
5. Click **Add Server**
|
|
315
|
+
|
|
316
|
+
The app checks that the panel is reachable before adding it. The server is added with `active: false` — click **Set Active** on its card to start using it.
|
|
317
|
+
|
|
318
|
+
> **Note:** Adding an existing server registers it in the app but does not configure authentication. You will still need to set up your agent certificate separately using `lamaste-agent setup` (after `npm install -g @lamalibre/lamaste-agent@4.0.0`) or by importing a certificate manually.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## DNS Management (Optional)
|
|
323
|
+
|
|
324
|
+
If your DigitalOcean API token includes the `domain` resource group, the wizard can automatically manage DNS records during provisioning. This eliminates the need to manually create A records and configure DNS after server creation.
|
|
325
|
+
|
|
326
|
+
### What the wizard creates
|
|
327
|
+
|
|
328
|
+
During provisioning, after the droplet boots and receives a public IP, the wizard creates two A records:
|
|
329
|
+
|
|
330
|
+
| Record type | Name | Value | TTL |
|
|
331
|
+
| ----------- | ------------------------------- | ---------- | ---- |
|
|
332
|
+
| A | `subdomain` (or `@` for apex) | Droplet IP | 300s |
|
|
333
|
+
| A | `*.subdomain` (or `*` for apex) | Droplet IP | 300s |
|
|
334
|
+
|
|
335
|
+
The wildcard record enables tunnel subdomains (e.g., `myapp.panel.example.com`) to resolve automatically.
|
|
336
|
+
|
|
337
|
+
### What the wizard does NOT do
|
|
338
|
+
|
|
339
|
+
- **Does not delete DNS records** when you destroy the server. You must clean them up manually in the DigitalOcean DNS console.
|
|
340
|
+
- **Does not overwrite existing records** that point to a different IP. If a conflict is detected, the wizard shows a warning and continues without modifying the existing record.
|
|
341
|
+
- **Does not configure nameservers** at your domain registrar. If you create a new domain in the wizard, you must point your NS records to DigitalOcean yourself.
|
|
342
|
+
|
|
343
|
+
### Fallback behavior
|
|
344
|
+
|
|
345
|
+
If your token does not have the `domain` resource group, the wizard behaves exactly as before — you enter a domain manually in the Label step (or skip it and configure DNS through the admin panel after provisioning).
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Destroying a Server
|
|
350
|
+
|
|
351
|
+
### Cloud-provisioned servers
|
|
352
|
+
|
|
353
|
+
For servers created through the app (with a DigitalOcean provider ID):
|
|
354
|
+
|
|
355
|
+
1. Click **Destroy** on the server card
|
|
356
|
+
2. Confirm by clicking **Yes** in the inline confirmation
|
|
357
|
+
|
|
358
|
+
This destroys the DigitalOcean droplet, removes the server from the registry, and deletes the stored credentials. The action is irreversible — all data on the droplet is permanently deleted.
|
|
359
|
+
|
|
360
|
+
> **Safety:** The app only destroys droplets tagged with `lamalibre:managed` + `product:lamaste`. If you manually removed this tag from the droplet in the DigitalOcean console, the destroy command will refuse to proceed. In that case, delete the droplet manually in the DigitalOcean console and use **Remove** in the app to clean up the registry entry.
|
|
361
|
+
|
|
362
|
+
### Manually added servers
|
|
363
|
+
|
|
364
|
+
For servers added via "Add Existing Server" (no provider ID):
|
|
365
|
+
|
|
366
|
+
1. Click **Remove** on the server card
|
|
367
|
+
2. Confirm by clicking **Yes**
|
|
368
|
+
|
|
369
|
+
This only removes the server from the desktop app's registry. The actual server is not affected — it continues running. Stored credentials for the server are cleaned up from the OS credential store.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Credential Storage Reference
|
|
374
|
+
|
|
375
|
+
All sensitive credentials are stored in your operating system's credential store, never in plaintext files:
|
|
376
|
+
|
|
377
|
+
| Credential | Service name | Key | Platform |
|
|
378
|
+
| ------------------------- | ------------------------------ | -------------- | -------------------------------- |
|
|
379
|
+
| DigitalOcean API token | `com.lamalibre.cloud` | `digitalocean` | macOS Keychain / Linux libsecret |
|
|
380
|
+
| P12 password (per server) | `com.lamalibre.lamaste.server` | Server UUID | macOS Keychain / Linux libsecret |
|
|
381
|
+
|
|
382
|
+
On macOS, the `security-framework` Rust crate accesses the Keychain directly (no CLI, no process listing exposure). On Linux, `secret-tool` is used with secrets passed via stdin.
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Quick Reference
|
|
387
|
+
|
|
388
|
+
| Action | How |
|
|
389
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
390
|
+
| **Create new server** | Servers tab → Create New Server → wizard |
|
|
391
|
+
| **Add existing server** | Servers tab → Add Existing Server → enter URL |
|
|
392
|
+
| **Switch active server** | Click "Set Active" on server card |
|
|
393
|
+
| **Open admin panel** | Click "Panel" on server card |
|
|
394
|
+
| **Destroy cloud server** | Click "Destroy" on server card → confirm |
|
|
395
|
+
| **Remove managed server** | Click "Remove" on server card → confirm |
|
|
396
|
+
| **Server registry file** | `~/.lamalibre/lamaste/servers.json` |
|
|
397
|
+
| **Token storage** | OS credential store (`com.lamalibre.cloud`) |
|
|
398
|
+
| **Required DO scopes** | `account:read`, `droplet:create/read/delete`, `ssh_key:create/read/delete`, `tag:create/read`, `regions:read` |
|
|
399
|
+
| **Optional DO scopes** | `domain:read/create/update/delete` (enables automatic DNS record creation) |
|
|
400
|
+
|
|
401
|
+
### Related Documentation
|
|
402
|
+
|
|
403
|
+
- [Desktop App Setup](desktop-app-setup.md) — installing and configuring the desktop app
|
|
404
|
+
- [Quick Start](../00-introduction/quickstart.md) — manual server setup via SSH
|
|
405
|
+
- [Certificate Management](certificate-management.md) — generating and managing certificates
|
|
406
|
+
- [First Tunnel](first-tunnel.md) — creating your first tunnel after server setup
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Desktop App Setup
|
|
2
|
+
|
|
3
|
+
> Install the Lamaste Desktop app for a native GUI experience with automatic service discovery and one-click tunnel creation.
|
|
4
|
+
|
|
5
|
+
## In Plain English
|
|
6
|
+
|
|
7
|
+
The Lamaste Desktop app is a native application (built with Tauri) that wraps the Lamaste agent in a graphical interface. Instead of running `lamaste-agent` commands in a terminal, you get a graphical interface that:
|
|
8
|
+
|
|
9
|
+
- **Discovers local services automatically** — it scans your machine for well-known services (Ollama, ComfyUI, PostgreSQL, Redis, Docker containers, etc.) and shows them in a marketplace-style UI
|
|
10
|
+
- **Creates tunnels with one click** — select a detected service, click "Expose," and the app creates the tunnel, updates the Chisel config, and reloads the connection
|
|
11
|
+
- **Manages everything visually** — start/stop Chisel, view logs, manage tunnels, rotate certificates, all from a native window with a system tray icon
|
|
12
|
+
- **Provisions servers from the app** — create a DigitalOcean droplet, install Lamaste, and connect automatically without ever touching SSH
|
|
13
|
+
- **Manages multiple servers** — switch between servers, add existing servers manually, or remove servers from the registry
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
- A completed [Lamaste onboarding](onboarding.md) on your VPS
|
|
18
|
+
- An **agent certificate** (`.p12` file and password) — generated from the panel's Certificates page
|
|
19
|
+
- **macOS** (Apple Silicon or Intel) or **Linux** (x64)
|
|
20
|
+
- **Node.js** >= 20 (for the npx installer)
|
|
21
|
+
|
|
22
|
+
> **Do not use the admin certificate.** Generate a scoped agent certificate from the panel. See [Certificate Management](certificate-management.md#agent-certificates).
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
Run the installer:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx @lamalibre/create-lamaste-desktop@4.0.0
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The installer:
|
|
33
|
+
|
|
34
|
+
1. Detects your platform (macOS arm64/x64 or Linux x64)
|
|
35
|
+
2. Downloads the latest release from GitHub
|
|
36
|
+
3. Caches the download in `~/.lamalibre/lamaste/desktop/`
|
|
37
|
+
4. Installs the app:
|
|
38
|
+
- **macOS:** Mounts the DMG, copies to `/Applications`, clears Gatekeeper quarantine, launches
|
|
39
|
+
- **Linux:** Copies the AppImage to `~/.local/bin/lamaste-desktop`, makes it executable, launches
|
|
40
|
+
|
|
41
|
+
On subsequent runs, the installer uses the cached download if the version hasn't changed.
|
|
42
|
+
|
|
43
|
+
### macOS Gatekeeper Note
|
|
44
|
+
|
|
45
|
+
The app is not code-signed with an Apple Developer certificate. On first launch:
|
|
46
|
+
|
|
47
|
+
- The installer attempts to clear the quarantine attribute automatically
|
|
48
|
+
- If macOS still blocks it: right-click the app → **Open**, or go to **System Settings → Privacy & Security → Open Anyway**
|
|
49
|
+
|
|
50
|
+
## Initial Setup
|
|
51
|
+
|
|
52
|
+
After the app launches, it shows a setup screen with two options:
|
|
53
|
+
|
|
54
|
+
**Option A: Connect to an existing server**
|
|
55
|
+
|
|
56
|
+
Install the agent globally and run its setup command:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g @lamalibre/lamaste-agent@4.0.0
|
|
60
|
+
lamaste-agent setup --label my-server
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The agent must be a global install — setup installs a sync timer that runs it every 30 seconds to pick up tunnel changes, and refuses to run from `npx`. (When the app sets up an agent itself, it installs `@lamalibre/lamaste-agent@4.0.0` globally for you.) The `--label` flag names this agent connection (used for multi-agent support). This command connects to your VPS panel using the agent certificate and configures the local Chisel client. During setup, the client certificate and key are extracted from the P12 bundle for mTLS client authentication. Once setup completes, the app detects the configuration and switches to the main interface.
|
|
64
|
+
|
|
65
|
+
**Option B: Create a new server**
|
|
66
|
+
|
|
67
|
+
Click "Create a new server" on the setup screen. This opens the Servers tab where you can provision a DigitalOcean droplet directly from the app. See the [Servers](#servers) section below for details.
|
|
68
|
+
|
|
69
|
+
## Using the App
|
|
70
|
+
|
|
71
|
+
The desktop app has two modes, toggled via a pill switch in the sidebar header. The mode toggle only appears when an admin certificate is detected for the active server.
|
|
72
|
+
|
|
73
|
+
### Agent Mode (default)
|
|
74
|
+
|
|
75
|
+
Agent mode provides local agent management. The agent-mode pages (Dashboard, Tunnels, Services, Plugins, Logs, Settings) are imported from the shared `@lamalibre/lamaste-agent-ui@4.0.0` package. The landing page is the **Agents** list, showing all configured agents with their connection status. Click an agent to drill into its management pages:
|
|
76
|
+
|
|
77
|
+
- **Agents** (landing) — list of all configured agents with start/stop controls and status
|
|
78
|
+
- **Dashboard** — per-agent connection status, Chisel version, start/stop/restart controls
|
|
79
|
+
- **Tunnels** — per-agent tunnel list with FQDNs, ports, and status
|
|
80
|
+
- **Services** — marketplace-style service discovery with one-click expose
|
|
81
|
+
- **Plugins** — install, enable, disable, and uninstall agent plugins; multi-page plugins inject sidebar navigation
|
|
82
|
+
- **Logs** — per-agent Chisel client stdout and stderr logs
|
|
83
|
+
- **Settings** — per-agent certificate management, agent configuration
|
|
84
|
+
|
|
85
|
+
### Server Mode
|
|
86
|
+
|
|
87
|
+
Server mode provides the full admin panel — the same management pages available in the browser-based panel UI. These pages are imported from the shared `@lamalibre/lamaste-server-ui@4.0.0` package:
|
|
88
|
+
|
|
89
|
+
- **Dashboard** — system stats (CPU, RAM, disk, uptime) + service health
|
|
90
|
+
- **Tunnels** — tunnel CRUD, carrying agent, access mode, body limit
|
|
91
|
+
- **Services** — service control + live log viewer
|
|
92
|
+
- **Static Sites** — site CRUD + file browser + upload
|
|
93
|
+
- **Users** — Authelia user CRUD + TOTP enrollment
|
|
94
|
+
- **Certificates** — Let's Encrypt + mTLS cert listing + renewal + rotation
|
|
95
|
+
- **Tickets** — agent-to-agent authorization scope and session management
|
|
96
|
+
- **Plugins** — plugin management + push install UI
|
|
97
|
+
- **Logs** — live journald log streaming
|
|
98
|
+
- **Settings** — panel configuration, 2FA, admin auth mode
|
|
99
|
+
|
|
100
|
+
**Admin certificate requirements:** Cloud-provisioned servers automatically include an admin certificate, so Server mode is available immediately. For servers set up via `lamaste-agent setup`, you need to manually import an admin certificate (P12 file) to unlock Server mode.
|
|
101
|
+
|
|
102
|
+
### Dashboard
|
|
103
|
+
|
|
104
|
+
Shows connection status (connected/disconnected), Chisel version, and controls to start/stop/restart the tunnel client.
|
|
105
|
+
|
|
106
|
+
### Tunnels
|
|
107
|
+
|
|
108
|
+
Lists all configured tunnels with their FQDNs, ports, and status. Create new tunnels or delete existing ones. Changes automatically reload the Chisel client.
|
|
109
|
+
|
|
110
|
+
### Services
|
|
111
|
+
|
|
112
|
+
The marketplace-style service discovery page:
|
|
113
|
+
|
|
114
|
+
- **Category filters:** All, AI, Database, Docker, Dev, Media, Monitoring, Custom
|
|
115
|
+
- **Automatic detection:** Scans for 17 well-known services plus all Docker containers
|
|
116
|
+
- **Status indicators:** Running (green), Installed (amber), Not Found (gray)
|
|
117
|
+
- **One-click expose:** Click "Expose" on any running service to create a tunnel
|
|
118
|
+
- **Custom services:** Add your own service definitions with name, port, binary, process name, and category
|
|
119
|
+
|
|
120
|
+
**Built-in services detected:**
|
|
121
|
+
|
|
122
|
+
| Service | Default Port | Category |
|
|
123
|
+
| ---------------------- | ------------ | ---------- |
|
|
124
|
+
| Ollama | 11434 | AI |
|
|
125
|
+
| ComfyUI | 8188 | AI |
|
|
126
|
+
| LM Studio | 1234 | AI |
|
|
127
|
+
| Stable Diffusion WebUI | 7860 | AI |
|
|
128
|
+
| Open WebUI | 3000 | AI |
|
|
129
|
+
| LocalAI | 8080 | AI |
|
|
130
|
+
| Jupyter | 8888 | Dev |
|
|
131
|
+
| VS Code Server | 8080 | Dev |
|
|
132
|
+
| n8n | 5678 | Dev |
|
|
133
|
+
| Grafana | 3000 | Monitoring |
|
|
134
|
+
| Home Assistant | 8123 | Media |
|
|
135
|
+
| Plex | 32400 | Media |
|
|
136
|
+
| MinIO | 9000 | Database |
|
|
137
|
+
| PostgreSQL | 5432 | Database |
|
|
138
|
+
| Redis | 6379 | Database |
|
|
139
|
+
| MongoDB | 27017 | Database |
|
|
140
|
+
| Elasticsearch | 9200 | Database |
|
|
141
|
+
|
|
142
|
+
Docker containers with exposed ports are also detected and can be individually exposed.
|
|
143
|
+
|
|
144
|
+
### Servers
|
|
145
|
+
|
|
146
|
+
The multi-server management page:
|
|
147
|
+
|
|
148
|
+
- **Cloud provisioning** — create a DigitalOcean droplet with Lamaste pre-installed. The wizard validates your API token scopes, measures latency to each region, provisions the droplet, installs Lamaste, downloads the certificate, and connects the app automatically
|
|
149
|
+
- **Add existing server** — connect to a server you already set up manually by providing the panel URL and certificate
|
|
150
|
+
- **Server switching** — switch the active server; the app reloads configuration and reconnects
|
|
151
|
+
- **Server removal** — remove a server from the registry (cloud-provisioned servers can also be destroyed)
|
|
152
|
+
|
|
153
|
+
**Cloud provider tokens** are stored in your OS credential store (macOS Keychain or Linux libsecret) — never in plaintext files or process arguments. P12 passwords for each server are also stored in the credential store.
|
|
154
|
+
|
|
155
|
+
**Server registry** is persisted at `~/.lamalibre/lamaste/servers.json`. When this file exists and contains an active entry, it takes precedence over the legacy `~/.lamalibre/lamaste/agent.json` configuration.
|
|
156
|
+
|
|
157
|
+
### Logs
|
|
158
|
+
|
|
159
|
+
View Chisel client stdout and stderr logs.
|
|
160
|
+
|
|
161
|
+
### Settings
|
|
162
|
+
|
|
163
|
+
Certificate management — rotate or re-download the agent certificate, uninstall the agent. Uninstalling an agent from the app stops and removes its Chisel service (`com.lamalibre.lamaste.chisel-<label>` on macOS, `lamalibre-lamaste-chisel-<label>` on Linux) and its sync timer (`…sync-<label>`).
|
|
164
|
+
|
|
165
|
+
Stopping an agent's tunnels from the app is remembered: the agent's sync timer keeps them stopped until you start them again.
|
|
166
|
+
|
|
167
|
+
## Updating
|
|
168
|
+
|
|
169
|
+
Run the installer again to get the latest version:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npx @lamalibre/create-lamaste-desktop@4.0.0
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
If a new release is available, it downloads and installs the update. The previous version is replaced.
|
|
176
|
+
|
|
177
|
+
## Uninstalling
|
|
178
|
+
|
|
179
|
+
**macOS:**
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
rm -rf /Applications/Lamaste.app
|
|
183
|
+
rm -rf ~/.lamalibre/lamaste/desktop/
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Linux:**
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
rm ~/.local/bin/lamaste-desktop
|
|
190
|
+
rm -rf ~/.lamalibre/lamaste/desktop/
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
To also remove every agent — its tunnel service, sync timer and configuration:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
lamaste-agent uninstall --all
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Deleting `~/.lamalibre/lamaste/` by hand instead would leave the agents' services and sync timers installed.
|
|
200
|
+
|
|
201
|
+
## Quick Reference
|
|
202
|
+
|
|
203
|
+
| Action | Command / Location |
|
|
204
|
+
| -------------------- | ------------------------------------------------------------------------------------ |
|
|
205
|
+
| **Install** | `npx @lamalibre/create-lamaste-desktop@4.0.0` |
|
|
206
|
+
| **Update** | `npx @lamalibre/create-lamaste-desktop@4.0.0` |
|
|
207
|
+
| **Agent setup** | `npm install -g @lamalibre/lamaste-agent@4.0.0`, then `lamaste-agent setup --label <name>` |
|
|
208
|
+
| **App location** | `/Applications/Lamaste.app` (macOS) |
|
|
209
|
+
| **Agent registry** | `~/.lamalibre/lamaste/agents.json` |
|
|
210
|
+
| **Per-agent data** | `~/.lamalibre/lamaste/agents/<label>/` |
|
|
211
|
+
| **Config (legacy)** | `~/.lamalibre/lamaste/agent.json` |
|
|
212
|
+
| **Server registry** | `~/.lamalibre/lamaste/servers.json` |
|
|
213
|
+
| **Service registry** | `~/.lamalibre/lamaste/services.json` |
|
|
214
|
+
| **Download cache** | `~/.lamalibre/lamaste/desktop/` |
|
|
215
|
+
| **Chisel logs** | `~/.lamalibre/lamaste/agents/<label>/logs/chisel.log` |
|
|
216
|
+
| **Cloud tokens** | OS credential store (`com.lamalibre.cloud`) |
|
|
217
|
+
| **P12 passwords** | OS credential store (`com.lamalibre.lamaste.server`) |
|
|
218
|
+
| **npm package** | `@lamalibre/create-lamaste-desktop@4.0.0` |
|
|
219
|
+
|
|
220
|
+
### Related Documentation
|
|
221
|
+
|
|
222
|
+
- [Cloud Provisioning](cloud-provisioning.md) — step-by-step guide to creating a server from the desktop app
|
|
223
|
+
- [Agent Setup](agent-setup.md) — command-line agent setup (alternative, and for headless machines)
|
|
224
|
+
- [Certificate Management](certificate-management.md) — generating agent certificates
|
|
225
|
+
- [First Tunnel](first-tunnel.md) — creating tunnels via the panel UI
|
|
226
|
+
- [Quick Start](../00-introduction/quickstart.md) — full setup walkthrough
|