Anvil Connect commands¶
anvil-serving connect manages application access for API clients and browsers.
It is the Anvil Connect product family. A local deployment JSON selects fixed
resources, component binaries, service identities, and secret references.
The existing edge commands continue to manage Tailscale independently.
This delivery initially targets Linux amd64. Native Connect, Caddy, Authelia, and wstunnel run as separate processes. The Python package adds no runtime dependencies and does not download or start those binaries when imported.
Deployment commands require --manifest /absolute/deployment.json. --service selects
gateway, connector:ID, or client:ID from that manifest. These are local
deployment selectors; the command does not perform implicit SSH or controller
dispatch. Mutations preview by default; --confirm applies the operation and
--dry-run keeps it a preview even when both flags are supplied.
The standalone anvil-connect-ctl displays help when run without arguments.
users lists account operations, and users create --help (or another operation)
shows only relevant arguments. Examples put options after the operation; existing
option-first user commands remain accepted. Invalid arguments
point to the relevant help without echoing private operands. Standalone command
results remain JSON, now indented for readability.
Resources¶
Lists declared browser resource IDs, URLs, native authentication modes and
copyable resource:member / resource:admin values. Use these exact IDs with
users create --grant or users access --grant; application names need not match
resource IDs. API resources are excluded because browser grants do not authorize
API access. Passthrough applications retain their own internal permissions.
The command defaults to /etc/anvil-connect/deployment.json, accepts --manifest,
and works identically as anvil-serving connect resources. It reads only the
declaration; it does not contact services, read referenced secrets or establish
live readiness or current access. A deployment without browser resources returns
an empty list.
Users¶
Follow Invite a developer for password setup, passkey enrollment, terminal connection, and operator-assisted recovery.
Inspect accounts first:
Both require local root access and return only username, email, groups and disabled status from the checked Authelia file backend. They do not restart services or read factor storage. Output remains private account metadata. Groups and disabled status describe sign-in accounts, not Connect service grants; inspect those through Manage access on the service home. A missing username fails explicitly.
Create an invited developer on the authentication host:
sudo anvil-connect-ctl users create developer --email developer@example.test --grant workbench:member --confirm
The standalone manager and anvil-serving connect users expose the same commands.
User administration defaults to /etc/anvil-connect/deployment.json; another
installation can select --manifest. Omit --confirm to preview. This Linux
command manages the pinned Authelia file backend through its native password
hashing and factor-removal commands. Optional authelia.smtp makes Authelia email
password-setup links and verification codes directly; see the
email configuration.
Creation defaults to role member (Authelia group members). Use --role admin
explicitly for group admins. These groups record the intended role; Connect
operator privileges still require separate authorization. --grant assigns
exact service entitlements and an application role; repeat it for each declared
browser service. Omitting grants creates only the Authelia account.
Resets preserve existing groups and do not enable disabled accounts.
Replace an existing person's complete service grant list:
The command resolves the user's actual Authelia OpenID identifier; a username is not an OIDC subject. Create and access send the validated command username only as account metadata alongside that authoritative subject. Resources omitted from this list are withdrawn. A successful access change enables the Connect account and invalidates existing browser and terminal credentials for the person. API principal grants remain separately declared. For a suspended account, it also re-enables the Authelia account, preserving its password, groups and registered factors, after applying the explicit grant list.
Suspend or delete a person by username:
sudo anvil-connect-ctl users suspend developer --confirm
sudo anvil-connect-ctl users delete developer --confirm
Omit --confirm to preview. Suspension disables the Connect identity and revokes
its browser sessions and human-approved terminal credentials, while preserving
the password, factors and service grants. Use users access with the intended
grants to resume it.
Permanent deletion removes the password-file account, authentication factors, Authelia OpenID identifiers and related OAuth records, and the Connect principal, sessions and human-approved terminal credentials. The username can then be used for a new account with a fresh identity and explicitly assigned grants. Configured Connect operators cannot be deleted; change the operator configuration first. Deletion backs up authentication state before removing it, briefly restarts Authelia if active, and retains a protected progress record if interrupted. Retry the same deletion to finish; an incomplete deletion stays disabled.
Backups, application data and separately issued API keys are retained; these keys have no automatic username association and require separate revocation. An old backup can contain a deleted account: review revocations before recovery. Use suspension when access may be needed again.
With filesystem delivery, the result names an exclusive, root-only handoff file beneath
/etc/anvil-connect/handoffs; credentials never appear in command output.
Deliver its contents directly to the intended developer, then remove the file.
Create and password reset store only the hash of a random bootstrap password;
the usable value is discarded and never written to a handoff. The handoff instead
contains Authelia's one-time password-setup link, valid for five minutes. With SMTP,
Authelia emails this link and no local handoff file is created. The
developer opens it and chooses a password before signing in. Authelia must be
running to issue the setup link. A newly created account has no passkey, so it
must complete this setup before signing in. These checks run before account
mutation. Keep the
users file owned by the Authelia service identity with mode 0600, so the
provider can save the password chosen by the developer. The managed service
permits writes to this exact file; existing installations do not need to move it.
Authelia still requires an email attribute for identity-verification messages,
even with manual delivery through its filesystem notifier.
sudo anvil-connect-ctl users code developer --confirm
sudo anvil-connect-ctl users reset-password developer --confirm
sudo anvil-connect-ctl users reset-mfa developer --confirm
With SMTP, users receive codes directly by email; users code explains this and
does not read historical local notifications. With filesystem delivery, after the
developer requests an enrollment code or password reset on the Authelia
page, code exports only a matching recipient's notification less than five
minutes old to a private handoff file. It returns either a verification code or
an exact-provider password-reset link. Use this to replace an expired welcome
link after the developer requests another reset. The filesystem notifier holds
only the latest message; handle invitations one at a time. Export does not prove
that a code or link remains unused. reset-mfa explicitly removes
that user's WebAuthn/passkeys and TOTP so they can enroll again. Password reset
alone retains those factors. Both website login and terminal browser approval
continue to use Authelia's existing browser flow.
Password reset preserves groups, grants and factors, invalidates the old password, and revokes Connect browser sessions and human-approved terminal credentials. Pending browser sign-ins begun before the reset are also rejected. After a successful replacement, old create/reset handoffs for that account are removed. If setup-link delivery fails after the password was replaced, the command reports a partial operation; request a fresh reset link rather than relying on the old password. For SMTP the response reports a requested email, not confirmed delivery: Authelia's reset endpoint conceals delivery errors to prevent account enumeration.
Create/password reset briefly stop and restart the running Authelia service, clearing its in-memory sessions. Factor changes and manual backups restart it only if it was already running and do not themselves revoke Connect credentials. Separately issued API keys require their own revocation.
Account files, email addresses, password hashes, registered factors, storage keys, handoff files and their backups are classified restricted-authentication. Keep them outside Git, ordinary logs, shared folders and unencrypted cloud sync. Use only synthetic identities in tests and published evidence. This is a local handling label, not a legal compliance certification.
sudo anvil-connect-ctl users backup --include-gateway --confirm
sudo anvil-connect-ctl users schedule --confirm
sudo anvil-connect-ctl users restore --input /etc/anvil-connect/backups/ARCHIVE.zip --sha256 DIGEST --destination /etc/anvil-connect/backups/recovery --confirm
A backup runs automatically before create/reset/suspend/delete operations and
when resuming a suspended account. Run users backup
after a developer finishes enrollment or changes their own password/passkeys,
and before maintenance. It includes the users file and, when initialized, a
consistent SQLite copy plus its storage encryption key. The root-only archive
records its classification and member checksums; output includes its SHA-256.
Keep that digest separately. The command retains the newest verified snapshot
for each of the last 14 UTC calendar days, plus the seven newest event snapshots.
It preserves unrecognized, future-dated, and timestamp-mismatched archives.
Archives are limited to 64 MiB and are not encrypted. These are local rollback
copies; they cannot recover a lost disk. Encrypt any copy taken to another device.
Host configuration and other secrets need their own backups; the gateway authority
is included by the option below.
Add --include-gateway for the nightly recovery set. It takes the Authelia
snapshot first, then stops only the native gateway for its offline authority
archive and starts that exact prior gateway again. Caddy and Authelia remain
running for that gateway step. The two archives are sequential rather than
atomic, and the gateway receipt binds the auth archive digest, gateway archive
digest, and native digest. Validated pairs use the same 14-day and seven-recent
retention policy. Both archive types are bounded local copies and are unencrypted.
Restore requires the independently retained digest, checks archive and SQLite integrity, then extracts only into a fresh
root-only directory. It does not overwrite live accounts or activate recovered
factors. Review account/factor revocations before a separately managed recovery
activation. An old authentication snapshot can contain credentials that have
since been revoked. The existing connect backup/connect restore commands
below separately handle gateway authorization state.
users schedule installs an owner-checked systemd service and persistent timer
for 03:17 UTC daily. It supports the default manifest and the verified
standalone gateway installation under /opt/anvil-connect; install this manager
release before enabling it. It uses the same backup operation, including its
sequential Authelia and gateway snapshots. The timer catches up after downtime.
It does not send email notifications.
An existing unrelated unit with the same name is refused.
To enable permanent deletion from the browser, install the verified manager and its fixed worker first:
Then enable gateway.gateway.browser_administration.user_deletion in the managed
deployment. The Connect home access editor and Workbench access console show
Delete user, with the username and full account ID. Self-deletion and deletion
of configured operators are refused. Confirmation immediately disables the
account; the root worker processes one pending deletion every ten seconds.
Refresh accounts to see completion. The worker runs only the fixed
users process-deletions --confirm operation and shares the deployment lock with
configuration changes. No browser request supplies a command or filesystem path.
Service home and application roles¶
Set optional gateway.gateway.portal_host to a dedicated hostname such as
home.example.test to publish the chooser independently of an application.
The gateway serves its root, home assets, and sign-in endpoints directly; it
does not create a connector resource or a service grant. Publish that hostname
through the verified TLS edge like the existing browser hosts. Rendering adds
its exact OIDC callback and makes it Authelia's landing destination. It must be
distinct from every application, authentication, control, and tunnel hostname.
Its cookie is bound to the home host and cannot authorize application access.
Enabled Connect accounts see only their existing service entitlements there.
Access editing remains on the configured administration service's own host.
Open /_anvil-connect/home beneath a declared browser service's path prefix.
For a service rooted at /workbench, the home is
https://workbench.example.test/workbench/_anvil-connect/home. Login returns to
that page. It lists only the person's current browser entitlements, links to
Authelia account/passkey settings, explains terminal approval, and signs out of
Connect. Each service host retains its own Connect cookie; Authelia supplies SSO
when opening another tile. An enabled Connect account can open the chooser even
without access to the service hosting it. This grants no application, device or
administrative access. Those endpoints still require their existing entitlements.
Without a dedicated home host, root sign-ins return to the chooser. With
portal_host configured, opening an application tile returns to that application
after sign-in; its explicit home path remains available for access editing.
Links to deeper application pages retain their destination.
A browser resource may declare up to eight fixed external OIDC return endpoints:
Each endpoint is an exact HTTPS host and non-root path on a host different from
the browser resource. Connect permits only 302 or 303 responses to a
declared scheme, host, and path; the response may add its query parameters.
The operator's home on the configured browser_administration.browser_resource
also has an access editor. It uses the existing CSRF-protected, generation-checked
administration endpoint. Choose no access, member, or admin for each service;
saving invalidates the edited person's sessions. Account IDs are opaque Connect
identifiers. Use the username-based CLI when identifying a new person. To suspend
the final service, disable the account; the authority retains a nonempty grant list.
The last Connect operator cannot be removed. Application admins do not become
Connect operators or inherit other services, and new services are never granted
automatically. A browser gateway resource may also set an optional display_name for chooser tiles and access-editor labels. It does not change rule.id, which remains the authority key for grants, roles, sessions, enrollment, and transport.
For Workbench/Observatory to enforce these roles inside the app, declare
native_auth: signed-identity at the Connect browser resource and configure
the receiver's authentication.connect.roles, for example:
Each value names an existing application principal with explicit resources and
actions in the application's users configuration. A signed role without a
matching receiver mapping is denied. When roles is configured, assertions
without a role are also denied, even if a legacy subject mapping exists. Assign
roles to existing users before enabling this receiver mode. Receivers that omit
roles retain the existing subject-based behavior. A role downgrade changes the signed request identity and
invalidates previous sessions. Passthrough applications, including a separate
Pi deployment without a Connect identity adapter, still manage their own roles;
their editor says that explicitly and their tiles omit the role badge. Merely storing a role label does not
grant or restrict an action inside such an application.
Authelia 4.39.20's file backend has no forced-first-login-change or annual-expiry flag. Connect requires initial password setup by withholding the discarded bootstrap password and using Authelia's supported reset flow. When passkey login is enabled, reset preserves registered factors; with the experimental verified-passkey-as-two-factors option, a registered qualifying passkey can continue passwordless sign-in. The reset link establishes the new password before password sign-in. Annual password expiry is not enabled. The managed passkey profile disables remembered sessions and retains its five-minute inactivity and one-hour expiry limits. Passkey-only login satisfying two factors is experimental.
Root Observatory with Grafana¶
A browser resource rooted at / can use the managed Caddy origin mux when a
single authenticated host must serve Observatory and Grafana. The mux is
loopback-only and uses longest-prefix routing. Its required / fallback points
to Observatory and is the only route that may set preserve_identity: true;
that resource must use native_auth: signed-identity. Route /grafana points
to Grafana with preserve_identity: false, so Connect identity assertions do
not enter Grafana. Keep Grafana's own authentication URL loopback-only and use
relative /grafana/... links so browser navigation stays behind the same
Connect resource.
For Observatory's optional fallback login, fallback_authentication.origin is
an exact HTTPS origin distinct from the Connect origin, and
fallback_authentication.grafana_url is a loopback HTTP(S) URL. Its users
list may contain only existing allowlisted native user IDs; it does not create
accounts or widen Connect access.
Qualify¶
Run the unattended Linux browser baseline with saved qualification settings:
The default settings file is ~/.config/anvil-connect/qualification.toml.
Use --config /absolute/qualification.toml to select another file. This is a
separate test configuration: it contains source, artifact, dependency-cache and
preinstalled tool paths, without production identities or credentials. It does
not select a deployment manifest or contact a model endpoint.
Save these settings once, replacing the example paths with prepared local
paths. playwright_root contains the pinned node_modules directory;
go_module_cache contains the already downloaded Go modules. Select actual
executables, not symlinks. The artifact directory must be owned by the test
user and mode 0700; the command can create it beneath a writable parent.
schema = "anvil-connect.qualification-config/v1"
source_root = "/srv/anvil-serving"
artifact_root = "/srv/connect-qualification/results"
playwright_root = "/srv/connect-qualification/dependencies"
go_module_cache = "/srv/connect-qualification/go-modules"
timeout_seconds = 600
[tools]
go = "/opt/go/bin/go"
node = "/opt/node/bin/node"
chromium = "/opt/chromium/chrome"
certutil = "/usr/bin/certutil"
caddy = "/opt/connect-tools/caddy"
authelia = "/opt/connect-tools/authelia"
wstunnel = "/opt/connect-tools/wstunnel"
The baseline runs the existing Caddy, Authelia, wstunnel and Chromium fixtures with synthetic accounts and isolated state. It checks certificate rejection before trusting the fixture CA, authenticated browser access, and the fixture's logout/revocation behavior. Required binaries are checked against recorded pins; missing prerequisites fail preflight. The command does not install dependencies.
Results distinguish passed, failed, skipped and not-run tests. Preflight failures
report both tests as not-run. A failure after execution begins reports only known
counts; counts: null means no complete test result is available. Cleanup failure
keeps any completed test counts but still fails the qualification. Skipped tests
never qualify the lane, and an unexecuted second test is explicitly not-run.
The private result artifact records revisions, tool identity, test outcomes and
cleanup evidence. A failed qualification exits nonzero. Raw authentication
responses and credential-bearing browser diagnostics are excluded from output.
Failed test evidence includes a safe failure-stage label. Each run keeps
result.json, evidence.json, junit.xml and SHA256SUMS after removing its
temporary source copy, profiles and caches. The source checksum binds the
tracked Connect files actually staged for that run; untracked files are excluded.
This baseline does not qualify virtual passkeys, terminal browser approval, physical biometrics, 1Password, host systemd isolation or the public deployment. Those require their own lanes and evidence. Fixture loopback listeners alone are not proof of operating-system-enforced network isolation.
Prepare the separate pinned Linux amd64 browser toolchain image explicitly:
This preparation uses the same saved settings and the local Docker engine. It may download public dependencies during the image build. Only nine named public build and dependency files enter the build context; it does not copy the checkout, home directory, Docker account configuration or deployment secrets. An owner-only receipt binds the build-input digest to the immutable image ID. Repeating the command reuses that image when its receipt and metadata match. Routine baseline runs remain download-free. Preparation alone does not run or qualify the terminal login flow.
Run the existing browser baseline in the prepared container:
This lane refuses root users and groups. It uses the recorded immutable image with downloads disabled, no external networking, no published ports, no GPUs, and no Docker socket or writable host mount inside the container. Its only host mount contains the staged public source read-only. Runtime state uses private container temporary files; CPU, memory and process counts are bounded. The runner removes its named container after success, failure or interruption and records cleanup and source/image identity with the test results. This qualifies the same two browser fixtures under container isolation. Terminal approval, virtual and physical passkeys, host service identities and production routes need separate evidence.
Run the terminal-login scenarios in the same isolated image:
This drives the actual standalone CLI, synthetic Authelia browser sign-in and approval form, then makes keyed requests through the CLI's loopback listener. Only the CLI child trusts its fixture CA; normal HTTPS hostname and certificate verification stay enabled. The lane checks absent/wrong local keys, declared models access, GET-only grant enforcement, and CLI exit/port release. Its negative scenario also checks unauthenticated approval, forged and foreign-origin CSRF, a real browser denial, and terminal cancellation before approval. A third scenario checks user disable and browser logout: an approved CLI request must return 401 without reaching the origin. The logout check uses a fresh Connect session through the existing identity-provider SSO session. Codes and credentials stay in transient fixture state, outside retained evidence.
A fourth scenario uses Chromium's virtual authenticator to enroll a discoverable
passkey through the pinned provider's real registration and elevation flows.
It requires user verification, clears browser cookies, signs in using the
passkey, and approves an actual CLI request. The fixture's separate operator
identity keeps the tested user unprivileged. Evidence labels this coverage
virtual-webauthn-only: it does not verify physical presence, biometrics,
Touch ID, Face ID, 1Password integration, or credential sync and backup.
The remaining passkey scenarios check missing user verification, a credential for the wrong relying party, an expired signed assertion, sequential replay, and a disabled Connect user. UV and relying-party failures are browser policy checks; replay checks rejection in the resulting authenticated session, without claiming concurrent replay resistance. A pre-enrolled spare credential restores dashboard and CLI access while user administration remains forbidden. The existing browser session and CLI key must remain usable after those forbidden requests; recovery does not grant an operator role. These are synthetic recovery and authorization checks, not validation of a production security audit log.
Device-approval expiry and single-use redemption after a lost response are covered separately by
authority and CLI unit tests, using an injected clock where appropriate. The
device lane does not claim those are browser end-to-end tests. Two browser stream
scenarios hold SSE and WebSocket connections open across human disable and logout.
They require client closure and native-handler return within one second measured
from before the authority mutation, then fresh denial without another origin
dispatch. Passed stream cases retain integer closure_ms in evidence and JUnit; missing
or invalid measurements fail qualification. This is a synthetic fixture target,
not a production latency guarantee.
Two further scenarios exercise SSE and WebSocket through the actual standalone
CLI after browser approval. They validate the native bearer and host, wait for
an SSE marker and a complete WebSocket handshake, then disable the user or log
out. Both clients and native handlers must close within the same one-second
fixture bound. Fresh requests with the formerly approved local key must return
401 without another native stream, and the CLI must exit and release its port.
Other authority events, authority recovery and physical passkeys require
separate coverage.
Run the bounded stream-revocation subset in the same prepared container:
This uses the saved qualification settings, the pinned image, disabled downloads,
the same configured timeout (600 seconds by default), and the existing CPU,
memory and cleanup bounds. It runs exactly ten browser and CLI lifecycle cases:
human disable, browser logout, synthetic session expiry, normal restart,
authority reset, restore, selective key revocation and browser grant removal.
The expiry fixture uses a full-precision inventory deadline across browser SSE
and WebSocket plus CLI SSE and WebSocket transports, then
denies fresh use of the old browser cookie and CLI key. The restart fixture
stops and starts the runtime, retains a valid browser cookie and CLI credential,
rejects an old revoked cookie, and checks that an interrupted POST has exactly
one origin execution. The authority-reset fixture uses the supported local
reset operation, creates a new epoch, denies the old cookie and CLI key, then
re-enrolls a fresh connector and admits new browser and CLI credentials through
the normal flows; its interrupted POST also has one origin execution. Restore
uses the supported backup and fresh-destination restore APIs, denies old
credentials before explicit human/API-principal reapproval and connector
reenrollment, then checks fresh access while the original browser cookie and
still-running old CLI remain denied. Its closure_ms measures the preceding runtime stop, not backup or restore latency.
The key-revocation case keeps a second CLI credential usable while the revoked
one remains denied across restart. The grant-removal case denies the removed
dashboard resource across restart while fresh login to the retained resource
succeeds. Each passed case retains its validated closure_ms observation.
This documents the bounded fixture scope; it does not claim an executed
qualification result, reboot behavior or external-supervisor recovery. Virtual
and physical passkeys and component-level authority checks have separate evidence.
Prepare the pinned systemd guest image, then run service-isolation qualification:
Both commands use the same saved qualification settings. Preparation verifies the signed image checksum and pinned image bytes, then stores an owner-only receipt. Repeating preparation verifies and reuses the cache. The isolation lane requires that prepared image and never downloads it implicitly. It also requires the pinned local component tools, cached Go modules, QEMU, KVM, xorriso and the declared firmware on Linux amd64.
The runner uses a disposable guest with two CPUs and 2 GiB of guest RAM. It has no guest network interface, GPU, shared host directory or host service socket. The payload contains a verified source snapshot and synthetic configuration; accounts, keys and certificates are generated only inside the guest. The host runner remains unprivileged. Host memory, disk, time and output checks bound the run; guest RAM is not a claim of a host cgroup memory limit. Qualification children cannot lock host memory. This lets QEMU consistently use its epoll event loop instead of partially initializing io_uring and failing on a later ring allocation. Address-space and resident-memory bounds remain enforced.
This lane checks actual installed service identities and unit bytes, Unix peer authorization, private-file and administration denials, TLS/provider discovery, certificate replacement, restart, failed-activation rollback and CLI shutdown cleanup. It retains the same four evidence files after removing guest staging. A missing final guest report has unavailable per-case outcomes and cannot pass; it is not evidence that the cases were never attempted. Full browser sign-in and physical passkeys retain their separate qualification scopes. Command availability does not establish that a guest run or production deployment has passed. An interrupted isolation run returns a nonzero, redacted result with its safe execution state and available case counts.
Validate¶
connect validate checks declarations and component prerequisites. An optional
--service narrows the validation to the selected role. Component validation
does not prove public reachability, successful login, or origin readiness.
Render¶
connect render reports the intended configuration generation. With --confirm,
it stages generated files for inspection. It does not start services. Existing
unmanaged files and changes to owned generated files are refused.
Up¶
connect up --service gateway previews the selected deployment. Applying it
validates the candidate, activates only owned configuration and units, and starts
the declared processes. Connector and client selections operate one exact named
installation. A selected update cannot silently change another role's files.
For a policy change spanning roles on this host, use one explicit set such as
--services gateway,connector:dashboard,client:dashboard-api in place of
--service. The selected roles share one activation and rollback transaction.
Artifact upgrades additionally require --upgrade: install the new artifact at
a versioned path and retain the previous verified executable for rollback.
Replacing an executable in place is refused. The preview includes the proposed
artifact digests; ordinary identity/admin commands still refuse binary drift.
anvil-serving connect up --manifest /etc/anvil-connect/deployment.json --service gateway --dry-run
anvil-serving connect up --manifest /etc/anvil-connect/deployment.json --service gateway --confirm
The gateway requires explicit prior initialization. A connector requires its invitation to be redeemed and its fingerprint approved before it can run.
Down¶
connect down --service SERVICE previews stopping the selected owned services.
--confirm applies the stop. Application state, authority records, and secrets
remain separate from generated service configuration.
Status¶
Public reverse tunnels open connections on demand. Zero idle registrations are reported as idle, not a failed tunnel, and do not trigger a connector restart on an unchanged apply. Status does not replace an authenticated application request.
connect status reports bounded owned service metadata. --service narrows it.
A process reported as running is not a claim that its origin is ready.
Doctor¶
connect doctor checks component paths and declared ownership. --service
narrows the checks. Diagnostics exclude secret file contents and request bodies.
Logs¶
connect logs --service SERVICE --tail 100 returns bounded service event metadata.
The maximum tail is 200. Credential-bearing raw process logs are not a public
diagnostic contract.
Init¶
connect init --service gateway previews initial authority creation. Applying
initialization refuses to overwrite existing authorities. Ordinary up never
regenerates a missing authority silently.
For a connector, supply --service connector:ID --bundle /absolute/invitation.json.
The private invitation file is produced by gateway administration. The connector
generates installation keys locally; it never receives a shared private key.
Identity¶
connect identity --service connector:ID returns its public installation
fingerprint. Verify that fingerprint independently before approving enrollment.
The output excludes private key material.
Admin¶
connect admin --request /absolute/request.json previews a closed administrative
operation against the manifest's gateway Unix socket. --confirm performs it.
The native command runs under the declared service identity. Status, principal
grants, API key issuance/revocation, installation invitations/approval/revocation,
human grants, and authority reset use this boundary.
Issuance and invitations require --output /absolute/private/response.json.
The output must not exist; its parent must be owned and mode 0700. It is reserved
as a mode-0600 file before the issuing request is sent. Credentials are never
printed in command output and should not be placed in the deployment manifest.
For the generic deployment example, a request file granting an API principal read access contains:
{"operation":"principal-set","principal":"sdk-reader","grants":[{"resource":"dashboard-api","methods":["GET"]}],"disabled":false}
After applying that request, a separate issuance request is:
{"operation":"api-key-issue","principal":"sdk-reader","grants":[{"resource":"dashboard-api","methods":["GET"]}],"lifetime_seconds":86400}
Apply it with --output to receive the one-time private response. Provision its
secret through the caller's secret mechanism. An ordinary SDK then uses
https://api.example.test/v1 and that key; a native application token stays in
the connector's declared environment. Key grants are explicit and must be a
subset of the principal's current grants; they are not inherited. This example
grants GET only. Chat or
other POST operations require an explicit matching method in both the resource
declaration and caller grant.
A browser grant uses the managed issuer's exact opaque subject, replacing the placeholder before applying:
{"operation":"human-set","issuer":"https://auth.example.test","subject":"REPLACE_WITH_EXACT_OIDC_SUB","resources":["dashboard"],"disabled":false}
The subject is not the username. An invitation for the example connector names its exact resource set:
{"operation":"invite","installation":"dashboard","role":"connector","resources":["dashboard","dashboard-api"],"lifetime_seconds":300}
Save its private output, redeem it with connect init --service
connector:dashboard --bundle ..., then inspect connect identity. The final
approval request uses operation: approve, installation: dashboard, and the
independently checked fingerprint returned by identity inspection.
Keygen¶
connect keygen --service client:ID --output /absolute/private/local-key previews
a local SDK-forwarder key. --confirm creates it exclusively. Provision this key
and the distinct remote Connect API key through the client's declared environment
file. Native application credentials belong only to the origin connector.
Generated configuration rollback does not restore authority databases, sessions, invitations, or revoked credentials. Database recovery requires its separate restore workflow. Public deployment and Observatory migration still require the isolated acceptance and migration evidence described in the delivery plan; command availability alone does not qualify a production cutover.
Backup¶
connect backup --output /absolute/private/backup.json previews an offline gateway
authority backup. Stop the gateway first; --confirm reserves an exclusive private
output before opening state. The archive contains private CA keys and authorization
history and is limited to 1 MiB; an oversized archive fails without truncation.
Keep the returned SHA-256 separately from the backup. The file is not encrypted.
Authelia storage/secrets, operator configuration, and application state have
separate backup procedures.
Restore¶
connect restore --input /absolute/private/backup.json --destination
/absolute/private/fresh-gateway --sha256 DIGEST --native-sha256 BINARY_DIGEST
previews recovery using the independently retained backup digest and approved
native executable digest. The latter is available in Connect validation output.
--confirm restores only into a fresh directory. Recovery retains CA identity,
assigns a new authority epoch, disables recovered human/API grants, and discards
historical credentials, installation bindings, invitations, and sessions. Review
and reapprove grants, reenroll connectors, and issue new keys before resuming
access. The command leaves configuration and running services untouched; updating
the manifest's gateway state directory and activating it are separate operations.
An interrupted recovery can leave an inert private directory: inspect it and retry
with another fresh destination. Never replace the active authority with an old
database as part of a binary or configuration rollback.
Migration¶
connect migration --observatory-config /absolute/observatory.json --resource ID
produces a no-write plan for one browser resource and the existing Observatory
canonical origin. It verifies native passthrough and path compatibility. The plan
preserves native login, session, CSRF, and action authorization; it does not perform
a public cutover or establish public reachability.
Edge status¶
connect edge-status --manifest /absolute/deployment.json --edge-config /absolute/edge-cloudflare.json
compares the resources declared in the deployment manifest with the live
Cloudflare state: the required CNAME record per published host, the required
tunnel ingress rule per host, and the tunnel's connector status. Hosts outside
the configured zone are rejected. Read-only; the API token is read from the
environment reference named in the edge configuration and never appears in
output.
Edge apply¶
connect edge-apply --manifest /absolute/deployment.json --edge-config /absolute/edge-cloudflare.json --confirm
applies exactly the declared difference through the Cloudflare API: the tunnel
ingress rules are merged (managed hosts first, foreign rules preserved, the
catch-all kept last) and the DNS records are created or updated in place.
Ingress rules for hosts that the manifest does not declare are preserved
untouched. A repeated apply converges without API writes, and the apply
verifies the tunnel is reporting an active connector before it reports
success. Without --confirm the command prints the same plan and changes
nothing.
Extend¶
connect extend --manifest /absolute/deployment.json --service connector:<id> --confirm
widen one enrolled connector's resource set to its declaration in one managed
operation: the preflight accepts purely additive resource-set changes
(removals and renames are rejected with revoke-and-redeclare guidance), the
new generation is activated with only gateway units restarted, the native
admin revoke/invite pair runs against the running gateway, and the connector
is stopped before an exact retained local identity and the invitation stage an
explicit replacement. Ordinary init --bundle then redeems that staged
identity, the new fingerprint is approved, and the connector starts without
changing its enablement policy. The whole sequence runs inside the deployment
lock with rollback of the rendered tree and gateway units. Without --confirm
it prints the same plan and changes nothing. Existing principals keep their
prior resource lists until connect admin human-set extends each one.
After a revoke, the operation keeps a private recovery record rather than
restoring the old enrollment. A later connect extend first verifies the
exact native installation status and either completes the retained forward
transition or stops without further authority changes when the status has
drifted. A retained staged replacement can be retried only with the same
invitation and exact prior identity; invitation material is never shown or
recreated from that record.