For the complete documentation index, see llms.txt. Markdown versions are available by appending .md to page URLs.
Lookout is local-first. Treat its data directory, master key, API credentials, collector private keys, and backups as security-sensitive. The service should run as an unprivileged account on a dedicated host or VM, behind an authenticated TLS reverse proxy when it is reachable beyond loopback.
Automated installation
The supported installation path on x86-64 or ARM64 Linux with systemd is:LOOKOUT_FLEET_CONCURRENCY to an integer from 1 through 16 to tune the limit for the available network and central-host capacity. The installer streams discovery, central-service, per-node collector, survey, validation, and bootstrap-key cleanup progress to stderr while reserving stdout for its final machine-readable result.
Defaults are intentionally fixed so uninstall can use an exact allowlist. Fleet central traffic uses pinned private TLS; host-local mode remains loopback-only. The generated administrator token is not printed or placed in process arguments; it is stored at /etc/lookout/admin-token with mode 0600.
To remove executable code and services while preserving everything needed for recovery or reinstall:
./uninstall.sh --purge. Purge removes only the installer’s fixed paths and deletes service users only when a protected installer manifest proves that Lookout created them. On an individual host, sudo lookout-uninstall and its explicit --purge --yes form remain available for recovery operations.
Host layout
- Application:
/opt/lookout, root-owned and not writable by either service account. - Server state:
/var/lib/lookout, owned bylookout, mode0700. - Server configuration:
/etc/lookout, files owned bylookout, mode0600. - Collector state:
/var/lib/lookout-collector, owned bylookout-collector, mode0700. - Collector identity:
/etc/lookout-collector/identity, owned bylookout-collector, directory mode0700, private files mode0600.
/etc/systemd/system, inspect them with systemd-analyze security, and then enable the server and continuous collector:
SupplementaryGroups=systemd-journal only when that group exists; it does not run as root or modify audit policy. Missing audit visibility is reported as degraded capability rather than silently treated as coverage. Do not run multiple collector instances against the same state directory.
When collectors.tailscale.enabled is true, the same collector polls bounded network-flow and configuration-audit windows, persists per-log cursor boundaries, and deduplicates inclusive API boundaries. Use a read-only credential with logs:network:read and/or logs:configuration:read, supplied only through an allowlisted environment or owner-only secret file.
Network boundary
Keep the server on127.0.0.1 when a reverse proxy runs on the same machine. For direct Tailscale binding, require API credentials, storage encryption, Tailscale ACL restrictions, and HTTPS at the application boundary or a sidecar proxy. Do not expose Lookout directly to a LAN or the public Internet over plaintext HTTP. Firewall egress to only explicitly configured survey APIs and cloud export endpoints.
The health endpoint does not contain events or graph data and is deliberately unauthenticated for local supervision. All /api/v1 routes require an authenticated principal when configured for production.
Doctor and upgrade preflight
The doctor is read-only and returns nonzero when it finds a blocking issue:/health for a growing pending count, retry state, or a blocked permanent failure. Correct the endpoint or credentials, then run node bin/lookout.js export-resume. Cloud state corruption is reported but does not prevent local ingestion and detection from starting.
Alert webhook health is reported separately. After correcting a permanent webhook endpoint or credential failure, run node bin/lookout.js webhook-resume to unblock its durable queue. The legacy alert-webhook-resume command remains available for installations still using the deprecated alertWebhook configuration block.
Upgrade one node at a time. First run preflight, create and verify an encrypted backup, stop Lookout, install the immutable application tree, run preflight again against the same data, and start the service. Never allow two versions to write the same directory. A future schema-changing release must ship an explicit, tested migration before its supported schema version is incremented.
Rollback application code only when the preflight confirms the stored schema is supported by the older release. Otherwise restore a verified pre-upgrade backup into a new empty directory; restoration intentionally refuses to overwrite an existing directory.
Container deployment
The Dockerfile runs as numeric user10001 with no bundled secrets. Mount a validated config read-only, mount master/auth/collector credential files read-only, and mount /var/lib/lookout on a volume owned by UID/GID 10001. Use a read-only root filesystem, drop all Linux capabilities, set no-new-privileges, and provide a writable tmpfs only if the runtime requires it. Terminate TLS outside the container and restrict published ports to the reverse proxy or private overlay.
Pin the base image by digest in a production build pipeline and rebuild regularly. Do not copy a .env, credentials, state, or backups into the image build context.