landfall 0.5.5 → 0.6.1

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/README.md CHANGED
@@ -29,6 +29,8 @@ cd my-site && lf deploy -s vps # live at https://my-site.203-0-113-7.sslip.
29
29
  - [Firewall](#firewall)
30
30
  - [History and undo](#history-and-undo)
31
31
  - [Managing servers](#managing-servers)
32
+ - [Traffic, certificates and checks](#traffic-certificates-and-checks)
33
+ - [Server system](#server-system)
32
34
  - [Web UI](#web-ui)
33
35
  - [Using landfall from scripts and agents](#using-landfall-from-scripts-and-agents)
34
36
  - [Command reference](#command-reference)
@@ -38,7 +40,7 @@ cd my-site && lf deploy -s vps # live at https://my-site.203-0-113-7.sslip.
38
40
 
39
41
  ## Install
40
42
 
41
- You need Node.js 22.4+ plus `ssh`, `ssh-copy-id` and `tar` on your machine. The server must run Ubuntu or Debian
43
+ You need Node.js 22.4+ plus `ssh`, `ssh-copy-id` and `tar` on your machine (`rsync` makes redeploys faster). The server must run Ubuntu or Debian
42
44
  and accept a login as root or as a user with passwordless sudo. landfall installs Docker itself.
43
45
 
44
46
  ```sh
@@ -72,7 +74,7 @@ lf setup vps --host 203.0.113.7
72
74
  ```
73
75
 
74
76
  1. Creates `~/.ssh/landfall_vps` and installs it with `ssh-copy-id`. You type the root password once.
75
- 2. Installs Docker, ufw (allowing ssh, 80 and 443, plus 443/udp for HTTP/3), fail2ban and unattended-upgrades.
77
+ 2. Installs Docker, rsync, ufw (allowing ssh, 80 and 443, plus 443/udp for HTTP/3), fail2ban and unattended-upgrades.
76
78
  3. Creates the user `deploy` in the docker group and disables ssh password login. Root keeps key-only access.
77
79
  4. Writes `Host vps` to `~/.ssh/config`, creating the file if needed. `ssh vps` now logs in as `deploy`.
78
80
  5. Starts Traefik, which gets Let's Encrypt certificates for every site.
@@ -162,6 +164,9 @@ The first deploy writes `.landfall.json`. Commit it:
162
164
 
163
165
  Local `.env*` files are never used on the server: each site has its own `.env` there. Pass variables with
164
166
  `-e`/`--env-file`, or later with `lf env`. `--env-file -` reads the lines from stdin, so secrets stay out of `ps`.
167
+ Changed something locally? Run `lf deploy` again (or **Redeploy** in `lf ui`). When both sides have `rsync`, a redeploy sends
168
+ only the files that changed and copies the rest from the live release on the server (files you removed stay
169
+ removed); otherwise it uploads the whole folder. Either way it becomes a new release, so `lf rollback` still goes back.
165
170
  `--keep 10` keeps more releases. A deploy is refused when another Compose project on the server already uses the
166
171
  site's project name, since `docker compose` would otherwise take over its containers.
167
172
 
@@ -305,7 +310,7 @@ Version-pinned tags show the newest tag of the same shape (`traefik:v3.6` → `t
305
310
 
306
311
  ```sh
307
312
  lf traefik status # container state, routes, mode
308
- lf traefik logs -f # certificate errors show up here
313
+ lf traefik logs -f # certificate errors show up here (--access adds requests)
309
314
  lf traefik setup --email you@example.com # reconfigure (safe to re-run)
310
315
  lf traefik setup --dashboard traefik # dashboard at traefik.<main domain> behind a login; `off` removes it
311
316
  lf traefik dashboard # the dashboard on localhost through an SSH tunnel, no domain needed
@@ -421,13 +426,99 @@ lf config --tunnel-only --keep 3 # defaults for every ser
421
426
  lf server rm vps # forget locally
422
427
  lf server uninstall vps # remove landfall from the server (type the name back)
423
428
  lf ssh vps -- docker ps
429
+ lf stats # CPU, memory, disks, network, busiest processes, every container's usage
430
+ lf stats blog -w # only the containers of one site, refreshed every 5s (--interval)
431
+ lf disk # where the space goes: images, volumes, build cache, sites, container logs
432
+ lf prune # remove unused images and the build cache (--all: unused tagged images too)
433
+ lf reboot # reboot, wait until it is back, check its containers run again
424
434
  ```
425
435
 
436
+ `stats` samples the server for one second over ssh; nothing runs on the server between calls. CPU of a
437
+ process counts one core as 100%. `disk` adds up folders, so it takes a few seconds on a full disk; without
438
+ root or passwordless sudo, root-owned folders and container logs may be missing.
439
+
440
+ `prune` keeps images any container uses (stopped ones too), images built for a site release (rollback runs
441
+ them without rebuilding) and images an undo in the journal puts back. Containers and volumes stay. `--dry-run`
442
+ shows what would go.
443
+
444
+ ### NAS, Steam Deck and other systems without a package manager
445
+
446
+ Synology DSM, SteamOS and other systems without apt, dnf, yum, apk or zypper install software their own way.
447
+ `lf setup` refuses on them (`--check` and `--key-only` still work). Register them with `lf server add` and deploy
448
+ to them as they are. `lf server info` shows what landfall can do on a server and why not:
449
+
450
+ ```
451
+ login root · root or sudo
452
+ init systemd
453
+ docker 24.0.2 · compose 2.20.1
454
+ firewall DSM has its own firewall: Control Panel → Security → Firewall
455
+ ```
456
+
457
+ On Synology, Docker comes from Container Manager in Package Center, so `lf update --compose` leaves it alone.
458
+ DSM's Control Panel keeps the host name, time zone, swap and Docker's settings, and its own firewall replaces
459
+ ufw, so landfall refuses those changes there. On SteamOS, install Docker in your home directory (landfall does not run podman). A
460
+ login without passwordless sudo can still deploy but not change the system. The web UI shows only the tabs and
461
+ actions that work on the server.
462
+
463
+ Non-interactive ssh sessions often lack `/usr/local/bin` (where DSM keeps `docker`), so landfall adds
464
+ `/usr/local/sbin` and `/usr/local/bin` to `PATH` for every command it runs.
465
+
426
466
  `server add` installs nothing on the server. It writes a `Host <name>` block between `# >>> landfall:<name>` markers
427
467
  (`--no-ssh-config` keeps the details in landfall's config instead). In a Host block you wrote yourself, landfall
428
468
  only steps in when the key does not work. It then puts the working `IdentityFile` first, drops lines whose file is
429
469
  gone, and keeps a backup as `~/.ssh/config.landfall-bak`.
430
470
 
471
+ ## Traffic, certificates and checks
472
+
473
+ ```sh
474
+ lf traffic # last 24h per site: requests, 4xx/5xx, median and 95% response time, bytes sent
475
+ lf traffic blog --since 1h # one site (or a host): requests per minute, busiest paths, failing requests, clients
476
+ lf certs # each site domain's certificate: days left, issuer, why getting one failed
477
+ lf check # request every site over HTTPS from this machine; exits 1 when one fails
478
+ lf check example.com --resolve 198.51.100.4 # one domain, against an address before DNS points there
479
+ ```
480
+
481
+ `traffic` reads Traefik's access log (JSON lines on its stdout, written by `lf traefik setup`) and adds it up
482
+ on the server with awk, so only the counts cross ssh. It reaches back as far as the container log does:
483
+ `lf log-limit` caps it, `--since` takes up to 30d. Spans up to 6h count per minute, longer ones per hour;
484
+ response times come from a histogram and are within about 20%. Traefik installed before this version logs
485
+ plain text: `lf traefik setup` switches it to JSON (Traefik restarts for a moment). A server's own Traefik
486
+ (`lf traefik use`) needs `--accesslog=true --accesslog.format=json` in its command.
487
+
488
+ `certs` reads certificates from what Traefik mounts: `acme.json` (Let's Encrypt; needs root or passwordless
489
+ sudo when it is root-owned) and certificate files in `dynamic/`. Only certificates leave the server, never
490
+ keys. Errors come from Traefik's log of the last 7 days (`--since`). Let's Encrypt renews 30 days ahead, so
491
+ under 30 days means renewal is due, under 7 that it is failing.
492
+
493
+ `check` runs on your machine, the way a visitor sees a site: status, time to the response, and whether the
494
+ certificate is trusted and valid for at least 7 more days. Give it domains and it needs no server, so it
495
+ works from cron or CI. The web UI checks a server's domains each minute while its Sites tab is open (the
496
+ dot on each domain; hover for the details).
497
+
498
+ ## Server system
499
+
500
+ ```sh
501
+ lf system # host name, time zone, clock, swap, Docker log limit, services, keys, bans
502
+ lf services # what landfall relies on (docker, ssh, fail2ban …) and failed ones; --all for every one
503
+ lf services restart docker # also start, stop; asks first for docker, refuses ssh without --force
504
+ lf services logs fail2ban -f # journald, else the service's log file; -n lines
505
+ lf keys # who may log in, per user; ★ is the key this machine uses
506
+ lf keys add ~/.ssh/anna.pub # to the login user; --user root for another
507
+ lf keys rm anna@laptop # by comment or (part of) the fingerprint
508
+ lf bans # what fail2ban blocks, per jail
509
+ lf unban 203.0.113.9
510
+ lf swap 2G # a swap file at /swapfile, on at boot; lf swap off removes it
511
+ lf hostname web-1
512
+ lf timezone Europe/Berlin
513
+ lf log-limit 10m --files 3 # cap Docker's json-file logs per container; --restart applies it now
514
+ ```
515
+
516
+ Every change is journaled, and all but `swap off` and `services restart` can be undone: `lf undo` stops a
517
+ started service, puts a removed key back, bans an unbanned IP again or restores the old name, zone or
518
+ `daemon.json`. These commands need root or passwordless sudo, else landfall uses root's key login like the
519
+ firewall does. Services work with systemd and OpenRC. The Docker log limit applies to containers created
520
+ afterwards (and Docker restarts only with `--restart`), so redeploy or restart sites to apply it to them.
521
+
431
522
  ## Web UI
432
523
 
433
524
  ```sh
@@ -444,8 +535,11 @@ other and show up in `lf history`. The pages read the same data the `--json` com
444
535
  |---|---|
445
536
  | Overview | `lf server list --check`, recent deploys, `lf config` (defaults, and where landfall puts things) |
446
537
  | Sites | `lf ls`, `sites info`, `deploy`, `rollback`, `logs`, `restart`/`stop`/`start`, `env`, `domains`, `auth`, `tunnel`, `sites rm` |
538
+ | Stats | `lf stats` (a new sample every 5s while the tab is open), `lf disk` on request, Clean up… (`lf prune`) |
539
+ | Traffic | `lf traffic --since 1h/24h/7d`, `lf certs`; the Sites tab shows failing requests of the last 24h and `lf check` on each domain |
447
540
  | Updates | `lf updates`, `lf update` |
448
541
  | Firewall | `lf firewall` and its subcommands |
542
+ | System | `lf system`, `services`, `keys`, `unban`, `swap`, `hostname`, `timezone`, `log-limit` |
449
543
  | History | `lf history`, `lf undo` |
450
544
  | Settings | `lf server config`, `server domain`, `traefik setup` (Settings…, Dashboard…), `traefik dashboard` |
451
545
 
@@ -509,6 +603,26 @@ lf undo -s box -y # revert the last run
509
603
  | `lf server add <name> [--host ip] [-u user] [-p port] [-i key] [--password-stdin] [--domain d] [--default]` | Registers a server without installing anything on it. Writes `Host <name>` to `~/.ssh/config`. |
510
604
  | `lf server list [--all] [--check] [--json]` | Lists registered servers. `--all` adds every ssh alias except git hosts (github.com, `gitlab.*`, `User git` …). `--check` tries a key login to each: `ok`, `login` (sshd refuses the key) or `down`. Alias: `servers`. |
511
605
  | `lf server info [name] [--json]` | Shows OS and release support, kernel, uptime, CPU, RAM, disk, addresses and containers. Alias: `info`. |
606
+ | `lf stats [site] [-w] [--interval s] [--json]` | Shows live CPU, memory, swap, disks, network, the busiest processes and each container's CPU, memory, network and restarts. With a site, only its containers. `-w` refreshes until Ctrl-C. Alias: `server stats`. |
607
+ | `lf disk [--json]` | Shows where disk space goes: filesystems, Docker images, containers, volumes and build cache (with what is reclaimable), each site and its releases, the largest volumes and container logs, the systemd journal. Alias: `server disk`. |
608
+ | `lf traffic [site] [--since 24h] [--json]` | Shows requests, 4xx/5xx, median and 95% response time and bytes per site from Traefik's access log; with a site or host, requests per minute or hour, busiest paths, failing requests and clients. Alias: `server traffic`. |
609
+ | `lf certs [--since 7d] [--json]` | Shows each site domain's certificate (days left, expiry, issuer, staging), other certificates Traefik has, and its recent certificate errors. Alias: `server certs`. |
610
+ | `lf check [site\|domain…] [--resolve ip[:port]] [--json]` | Requests sites over HTTPS from this machine: status, response time, certificate trust and days left. Exits 1 when one fails. Domains need no server. Alias: `sites check`. |
611
+ | `lf prune [--all] [--dry-run] [--json]` | Removes unused Docker images and the build cache. Keeps images in use (stopped containers too), release images for rollback and images undo needs. `--all` also removes unused tagged images (pulled again when needed) and all build cache. Journaled, not reversible. Alias: `server prune`. |
612
+ | `lf reboot [--timeout s]` | Reboots the server (needs root or passwordless sudo), waits until ssh answers again (default 300s) and checks that the containers that ran before run again. Alias: `server reboot`. |
613
+ | `lf system [--json]` | Shows the host name, time zone, clock sync, swap, Docker's log driver and limit, services, SSH keys and fail2ban bans, with hints (no swap on a small server, unlimited Docker logs). Alias: `server system`. |
614
+ | `lf services [--all] [--json]` | Lists services landfall relies on and failed ones; `--all` lists every one. systemd or OpenRC. Alias: `services ls`. |
615
+ | `lf services restart\|start\|stop <service>` | Controls a service. Stopping ssh needs `--force`; stopping or restarting docker asks first. Start and stop can be undone. |
616
+ | `lf services logs <service> [-f] [-n lines]` | Shows a service's log: journald, else its log file. |
617
+ | `lf keys [--json]` | Lists the SSH keys in each user's `authorized_keys` (root and `/home/*`). ★ marks the key this machine logs in with. Alias: `keys ls`. |
618
+ | `lf keys add <key\|file.pub> [--user u]` | Adds a public key, to the login user by default. Undoable. |
619
+ | `lf keys rm <fingerprint\|comment> [--user u]` | Removes a key by comment or fingerprint prefix. Refuses the key this machine uses without `--force`. Undoable. |
620
+ | `lf bans [--json]` | Shows banned IPs per fail2ban jail. |
621
+ | `lf unban <ip>` | Unbans an IP in every jail that bans it. Undo bans it again. |
622
+ | `lf swap [size\|off]` | Shows swap, adds a swap file at `/swapfile` (at least 64M, keeps 2 GB of disk free) or removes it. Adding is undoable. Alias: `server swap`. |
623
+ | `lf hostname [name]` | Shows or sets the host name (and its `/etc/hosts` line). Undoable. Alias: `server hostname`. |
624
+ | `lf timezone [zone]` | Shows or sets the time zone, e.g. `Europe/Berlin`. Undoable. Alias: `server timezone`. |
625
+ | `lf log-limit [size\|off] [--files n] [--restart]` | Shows or sets Docker's json-file log limit per container in `daemon.json` (default 3 files). `--restart` restarts Docker so it applies now. Undoable. |
512
626
  | `lf server config [name] [--json]` | Shows everything landfall and ssh use for a server. Does not connect. |
513
627
  | `lf server domain [name] [domain...] [--add d] [--primary d] [--rm d] [--clear] [--tunnel-only] [--json]` | Manages main domains (the first is primary) and checks their DNS; `--tunnel-only` makes new sites deploy with no domain. |
514
628
  | `lf server use <name>` | Sets the default server. |
@@ -600,7 +714,7 @@ On the server:
600
714
  /etc/ssh/sshd_config.d/00-landfall.conf ssh hardening from `lf setup`
601
715
  ```
602
716
 
603
- `lf setup` also installs Docker with the compose plugin, ufw, fail2ban and unattended-upgrades, and creates the
717
+ `lf setup` also installs Docker with the compose plugin, rsync, ufw, fail2ban and unattended-upgrades, and creates the
604
718
  `deploy` user (group docker). Before changing a file, landfall keeps a backup next to it as
605
719
  `.<file>.landfall-<run>` (the newest 10). `lf config` and the web UI's *Overview* list all of these places.
606
720