9. Security hardening of the server
This guide describes Lawliet 1.5.13.s (the current release). Screens, commands and procedures may change in later versions; the usage guide is updated with each release. Check the version your server runs under Settings > Platform or with ./lawliet version, and see the Releases page for what changed.
What to lock down on the Lawliet server before real data goes in, and what to keep checking afterwards. Work through 9.1 and use the sections after it for the detail.
| You need | |
|---|---|
| Who | The server administrator (root), and a console administrator for 9.6 |
| Four-eyes | Console user, role and policy changes in 9.6 are critical actions once a second approver exists |
9.1 Checklist#
| # | Item | Check with |
|---|---|---|
| 1 | TLS is on, with a certificate from a CA your browsers and agent hosts trust | sudo ./lawliet tls status |
| 2 | No agent still uses plain HTTP | sudo ./lawliet tls status (Agents on plain HTTP) |
| 3 | Only the ports in 9.2 are reachable, from the networks that need them | Your network firewall rules |
| 4 | Shell access to the server limited to the people who would hold the Super administrator account | getent group sudo docker wheel |
| 5 | .env is mode 600 and owned by root | ls -l .env |
| 6 | Backups run, are copied off the server, keys stored apart, a restore has been tested | Backup and restore |
| 7 | NTP synchronised on the server and every agent host | timedatectl, sudo ./lawliet doctor |
| 8 | Named console accounts, two-factor for all, a second approver, the install account sealed | Settings > Users |
| 9 | Dual control on, Super administrators act alone off | Settings > Access control |
| 10 | The settings in 9.8 unchanged from what the installer wrote | grep -E '^(DEBUG|LICENSE_ENFORCE|CORS_ORIGINS|TRUSTED_HOSTS|REQUIRE_TWO_FACTOR)=' .env |
| 11 | METRICS_TOKEN set if anything scrapes /metrics | .env |
| 12 | sudo ./lawliet doctor reports nothing | Weekly |
9.2 Network ports#
Inbound to the Lawliet server#
| From | Port | HTTPS mode | Plain-HTTP mode |
|---|---|---|---|
| Operator workstations | 443/tcp | Console and API | - |
| Operator workstations | 80/tcp | Optional; redirects to 443 | - |
| Operator workstations | 3000/tcp and 8000/tcp | - | Console, and the API the browser calls directly |
| Monitored hosts (agents) | 443/tcp | Agents | - |
| Monitored hosts (agents) | 8000/tcp | Only agents of a former plain-HTTP install that have not been reinstalled | Agents |
| Monitored hosts enrolled while TLS was off | 80/tcp | Until each is reinstalled over HTTPS | - |
| Log senders | 5514/udp, 5514/tcp | Only if you collect syslog | Same |
If the installer moved a port because the default was taken, use the port it printed (sudo ./lawliet status shows the console URL).
Never reachable from outside the server: PostgreSQL, Redis and ClickHouse are not published to the host. In HTTPS mode the backend and the console are reachable only through nginx, and nginx serves /docs, /redoc, /openapi.json and /metrics only to loopback and private address ranges.
Nothing connects to an agent. No inbound rule is needed on any monitored host.
Outbound from the Lawliet server#
None is needed for the platform to run. Each row is used only when an operator configures the feature.
| To | Port | Feature |
|---|---|---|
| Your NTP source | 123/udp | Time (needed) |
| Hosts on your networks | TCP 22, 80, 443, 445, 3306, 3389, 5432, 6379, 8080, 8443 (quick scan; a full scan adds more); UDP 137, 161, 1900, 5353; ICMP | Network discovery, only the ranges you enter |
| Firewall appliances | 22/tcp or 443/tcp | Firewall configuration import and policy push |
| Hosts to install agents on | 22/tcp (SSH), 5986/tcp (WinRM HTTPS), 5985/tcp (WinRM HTTP, insecure) | Remote deployment |
| Domain controllers | 636/tcp (LDAPS) or 389/tcp (StartTLS); 88/tcp (Kerberos) | Directory sign-in, Kerberos for remote deployment and Windows sign-in |
| Your mail relay | 587/tcp (as configured) | Password-reset links, scheduled reports, alert e-mail |
| Your SIEM | As configured | SIEM forwarding |
| The vendor's update feed | 443/tcp | Only if UPDATE_FEED_URL is set. Leave it empty on an air-gapped site |
Licensing never needs any outbound connection.
Agents#
| From | To | Port |
|---|---|---|
| Monitored hosts | Lawliet server | 443/tcp (plain HTTP: 8000/tcp) |
| Monitored hosts | Your NTP source | 123/udp |
9.3 The host firewall#
Enforce the inbound rules on a network firewall in front of the server. On the server itself, a host firewall such as ufw is useful for everything else, but Docker publishes container ports through its own iptables rules, which bypass ufw on many distributions. Do not rely on ufw alone for 443, 80, 5514, 3000 or 8000.
Example for the host's own services (SSH from the admin network only):
sudo ufw default deny incoming
sudo ufw allow from <admin-network> to any port 22 proto tcp
sudo ufw enable9.4 Shell access to the server#
Root on the server, and membership of the docker group (which is equivalent to root), can:
- read every secret in
.envand every backup; - run
./lawliet passwdand take over the administrator account; - install a licence, build an offline agent package with an enrolment code, change the certificate or turn encryption off - all without console four-eyes.
So:
- Give shell access only to the people who would hold the Super administrator account.
- Use personal accounts with
sudo; no shared root password; SSH keys, not passwords. - Do not add operator accounts to the
dockergroup. - Log
sudouse to your central log collection. - Review the audit trail for CLI actions that are recorded there:
doctor_fix, offline agent packages made through the CLI, and TLS changes (who ran them and when, as the host saw it).
9.5 Files that hold secrets#
| File | Holds | Protect by |
|---|---|---|
.env | Database password, JWT signing key, data encryption key, enrolment secret, licence key | Mode 600, root-owned. Copy off the server only encrypted |
backups/*.sql.gz | The whole database | Mode 600 (as written). Off-server copies access-controlled |
backups/*.keys | The keys stored secrets are encrypted with | Store apart from the dumps |
infra/docker/ssl/privkey.pem | The TLS private key | Mode 600 |
.tls-snapshots/ | Copies of .env and the private key from TLS switches | Owner-only; doctor --fix removes old ones |
lawliet-agent-*-offline-* | An enrolment code | Delete after use; doctor --fix removes expired ones; revoke a lost one under Environment > Install agent > Offline package |
.env.backup.* | Earlier copies of .env | Delete old ones you do not need |
lawliet-support-*.txt and lawliet-diag-*.tar.gz are redacted, but still describe your deployment: send them only to support and delete them afterwards.
9.6 Console accounts and four-eyes#
- One named account per person. No shared accounts.
- Two-factor for everyone. Keep
REQUIRE_TWO_FACTOR=true(the default). - A second approver on day one (Installation 2.9, step 5).
- Seal the install account. With an LSO and an RSO in place, store the Super administrator's password and recovery codes offline for recovery only.
- Least privilege. Analysts as Analyst, read-only staff as Viewer or Auditor. Use per-user denials rather than broad roles.
- Dual control on. Settings > Access control: Dual control is on ticked, Super administrators act alone unticked, a reason required.
- Review bypasses. In Settings > Audit trail, look for
dual_control_bypassedevents. After the first day there should be none with reasonno_second_approver. - API keys. Create them only for integrations that need them, with the narrowest scope, and revoke unused ones (Settings > API keys).
- Disable accounts of leavers the same day (Settings > Users).
Procedures: Users, roles and approvals.
9.7 TLS#
- Use a certificate from your CA, naming every address in use. Browsers then do not warn and agents need no certificate file.
- Keep TLS on. If it was ever turned off,
tls onoffers to sign everyone out, revoke API keys used while off and rotate the enrolment secret: answer yes. - Reinstall every agent still on plain HTTP.
- Watch the expiry: the console's Certificate card and the notification bell warn at 30 and 7 days;
sudo ./lawliet doctorwarns at 30.
nginx serves TLS 1.2 and 1.3 only and sends HSTS while TLS is on.
9.8 Settings to keep#
The installer writes these. Do not change them on a production server.
Setting in .env | Keep | Why |
|---|---|---|
DEBUG | false | true is for development: among other things it switches off the TRUSTED_HOSTS check |
LICENSE_ENFORCE | true | |
CORS_ORIGINS | The exact console origin(s), never * | Stops other web pages from calling the API with a user's session |
TRUSTED_HOSTS | The server's names and addresses, localhost, 127.0.0.1; never * | Refuses requests for other host names |
REQUIRE_TWO_FACTOR | true | |
DEMO_DATA_ENABLED | false | Demo data is for vendor labs and training |
UPDATE_FEED_URL | Empty on an air-gapped site | No outbound requests |
METRICS_TOKEN | Set, if anything scrapes /metrics | Without it /metrics is unauthenticated to the networks nginx allows |
AGENT_REGISTRATION_SECRET | Set (never empty) | Empty refuses every enrolment; rotate with ./lawliet token --rotate if it leaked |
After editing .env, apply with sudo ./lawliet start (a restart does not re-read it).
Retention of collected data#
| Setting | Default | Meaning |
|---|---|---|
RETENTION_LOG_EVENT_DAYS | 90 | Collected log events older than this are deleted. 0 keeps them for ever |
RETENTION_CORRELATION_ALERT_DAYS | 365 | Detection alerts |
Set them to what your regulations require, and watch disk use.
9.9 Keep it healthy#
| How often | Task |
|---|---|
| Daily | Backups copied off the server (Backup 5.3) |
| Weekly | sudo ./lawliet doctor; review Approvals > History and the audit trail |
| Monthly | Check disk growth; check the certificate and licence expiry (Settings > Platform) |
| Twice a year | Test a restore (Backup 5.6) |
| Each release | Read the notes; apply security updates promptly (Updates) |
Monitor /health and /health/ready from your monitoring system (Doctor, diag and support 7.4).
Syslog sources#
Syslog carries no authentication. Restrict every syslog log source to the networks of its senders (its allowed networks setting), and open 5514 only from those networks.

