landfall 0.4.5 → 0.5.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/README.md CHANGED
@@ -12,7 +12,8 @@ cd my-site && lf deploy -s vps # live at https://my-site.203-0-113-7.sslip.
12
12
  - **No agent on the server.** Every site is a plain Docker Compose project under `/opt/landfall`, so you can read, run and fix it by hand.
13
13
  - **Your compose.yaml is the site.** App, database, worker: `docker compose up` runs it locally, `lf deploy` runs the same file behind HTTPS.
14
14
  - **Every change is journaled** on the server and can be undone with `lf undo`.
15
- - **Two ways in:** plain commands for scripts, CI and agents; a web dashboard (`lf ui`).
15
+ - **The CLI is the product.** Every feature is an `lf` command first, usable from scripts, CI and agents.
16
+ The web UI (`lf ui`) is a front end for those commands: each button runs one and shows it.
16
17
 
17
18
  `lf` is short for `landfall`. Both commands are installed.
18
19
 
@@ -28,7 +29,7 @@ cd my-site && lf deploy -s vps # live at https://my-site.203-0-113-7.sslip.
28
29
  - [Firewall](#firewall)
29
30
  - [History and undo](#history-and-undo)
30
31
  - [Managing servers](#managing-servers)
31
- - [Dashboard](#dashboard)
32
+ - [Web UI](#web-ui)
32
33
  - [Using landfall from scripts and agents](#using-landfall-from-scripts-and-agents)
33
34
  - [Command reference](#command-reference)
34
35
  - [Files and config](#files-and-config)
@@ -37,7 +38,7 @@ cd my-site && lf deploy -s vps # live at https://my-site.203-0-113-7.sslip.
37
38
 
38
39
  ## Install
39
40
 
40
- You need Node.js 22+ plus `ssh`, `ssh-copy-id` and `tar` on your machine. The server must run Ubuntu or Debian
41
+ You need Node.js 22.4+ plus `ssh`, `ssh-copy-id` and `tar` on your machine. The server must run Ubuntu or Debian
41
42
  and accept a login as root or as a user with passwordless sudo. landfall installs Docker itself.
42
43
 
43
44
  ```sh
@@ -54,7 +55,7 @@ lf <command> --help # every option of one command
54
55
  | **site** | One Compose project on a server: your `compose.yaml`, or one landfall generates for a static folder, a Dockerfile or a prebuilt image. Services with `x-landfall: { port }` are routed through Traefik. |
55
56
  | **project file** | `./.landfall.json`, written by the first `lf deploy`: `{ "name", "server", "domains" }`. Commands that take `[name]` default to this site, and `-s` defaults to its server. |
56
57
  | **main domain** | Optional per-server domain (`lf server domain vps example.com`). Sites then default to `<site>.example.com`, and a bare name like `shop` means `shop.example.com`. Without one, sites get `<site>.<ip-with-dashes>.sslip.io` (e.g. `blog.203-0-113-7.sslip.io`), which resolves without any DNS setup. |
57
- | **release** | Every deploy creates one, with an id like `20260122143005`. The last 5 are kept. `lf rollback` switches between them. |
58
+ | **release** | Every deploy creates one, with an id like `20260122143005`. The last 5 are kept (`--keep n` for more). `lf rollback` switches between them, back and forth. |
58
59
  | **run** | One landfall invocation that changed something on a server. Runs are listed by `lf history` and reverted by `lf undo`. |
59
60
 
60
61
  How defaults resolve, for every command:
@@ -71,7 +72,7 @@ lf setup vps --host 203.0.113.7
71
72
  ```
72
73
 
73
74
  1. Creates `~/.ssh/landfall_vps` and installs it with `ssh-copy-id`. You type the root password once.
74
- 2. Installs Docker, ufw (allowing ssh, 80 and 443), fail2ban and unattended-upgrades.
75
+ 2. Installs Docker, ufw (allowing ssh, 80 and 443, plus 443/udp for HTTP/3), fail2ban and unattended-upgrades.
75
76
  3. Creates the user `deploy` in the docker group and disables ssh password login. Root keeps key-only access.
76
77
  4. Writes `Host vps` to `~/.ssh/config`, creating the file if needed. `ssh vps` now logs in as `deploy`.
77
78
  5. Starts Traefik, which gets Let's Encrypt certificates for every site.
@@ -101,13 +102,16 @@ first and prints what is done (`✓`), what it will do (`→`) and what it refus
101
102
  | step | skipped when |
102
103
  |---|---|
103
104
  | firewall | ufw is off and enabling it would block a public port that something listens on (Postgres on 5432, WireGuard on 51820/udp, …). Docker-published ports stay reachable because Docker's NAT bypasses ufw. If Docker uses nftables or has no IPv6 NAT, they would be blocked, so setup skips the firewall. |
104
- | ssh hardening | other users still log in with a password |
105
+ | ssh hardening | other users still log in with a password. Afterwards setup checks the effective config with `sshd -T`, so a drop-in that turns passwords back on is reported. |
105
106
  | traefik | 80/443 are held by something that is not Traefik, or by a `traefik` that landfall didn't create. If it is your own Traefik, setup offers `lf traefik use` instead. |
106
107
 
107
108
  Docker that is installed but stopped gets started. A missing compose, or the old v1 `docker-compose`, is replaced
108
109
  with the newest release. An existing Docker is never reinstalled. In a terminal, setup asks about each conflict
109
110
  (the default is no). `-y` never accepts a conflict. Only `--force` does. Existing sites are never touched.
110
111
 
112
+ Running setup again is safe. If root's key login is gone after hardening, setup logs in as the sudo user it
113
+ remembered from the first run (`--dashboard-user` and `--email` are checked before anything changes).
114
+
111
115
  ### Setup flags
112
116
 
113
117
  | flag | effect |
@@ -146,6 +150,7 @@ lf deploy -d example.com -d www.example.com -s vps # static, name = folder
146
150
  lf deploy -b "npm run build" # build locally first
147
151
  lf deploy -d app.example.com -e DATABASE_URL=postgres://… --env-file .env.production # Dockerfile app
148
152
  lf deploy -n api --image ghcr.io/me/api:1.4 --port 8080 -d api.example.com # image
153
+ lf deploy --no-domain # no domain yet: reach it with lf tunnel, add one later with lf domains --add
149
154
  lf deploy # later: redeploy using ./.landfall.json
150
155
  ```
151
156
 
@@ -156,7 +161,9 @@ The first deploy writes `.landfall.json`. Commit it:
156
161
  ```
157
162
 
158
163
  Local `.env*` files are never used on the server: each site has its own `.env` there. Pass variables with
159
- `-e`/`--env-file`, or later with `lf env`. `--keep 10` keeps more releases.
164
+ `-e`/`--env-file`, or later with `lf env`. `--env-file -` reads the lines from stdin, so secrets stay out of `ps`.
165
+ `--keep 10` keeps more releases. A deploy is refused when another Compose project on the server already uses the
166
+ site's project name, since `docker compose` would otherwise take over its containers.
160
167
 
161
168
  ### Compose sites
162
169
 
@@ -205,7 +212,7 @@ volumes:
205
212
  - Variables in `compose.yaml` come from the site's `.env` on the server (`-e`, `--env-file`, `lf env`).
206
213
  `${VAR:?}` makes a missing one fail the deploy before anything changes.
207
214
  - Your own `traefik.*` labels win: a service with its own router keeps them and landfall adds only the network.
208
- - `-f other.yaml` deploys another file; it is saved in `.landfall.json`. Sites need Docker Compose 2.24 or newer
215
+ - `-f other.yaml` deploys another file from the project folder; it is saved in `.landfall.json`. Sites need Docker Compose 2.24 or newer
209
216
  on the server (`lf update --compose`).
210
217
 
211
218
  The static, Dockerfile and image kinds are Compose sites too: landfall writes their `compose.yaml` for you.
@@ -256,16 +263,19 @@ lf logs -f # follow logs (-n 500 for more lines)
256
263
  lf logs blog db # one service
257
264
  lf rollback # previous release (--to <id> for a specific one)
258
265
  lf env API_KEY=abc # set env (container is recreated); -u KEY removes one
266
+ lf env --env-file - < .env.prod # the same from a file or stdin, values never in ps
259
267
  lf restart | stop | start
260
268
  lf domains # where DNS points, whether HTTPS answers
261
269
  lf domains --add www.example.com # also --rm, --set (updates .landfall.json)
262
270
  lf domains --rm @ # take the main domain off; the last one leaves the site running, unrouted
263
271
  lf auth -u anna # login in front of the site (asks for the password, -p passes it)
264
- lf auth -p '…' # the same for user admin
272
+ lf auth --password-stdin < pw.txt # the same for user admin, password from stdin
265
273
  lf auth --rm-user anna | --off
266
274
  lf open
267
275
  lf tunnel blog # http://localhost:<port> straight to its container: test it without a domain
268
276
  lf tunnel my-compose-app -s het # also any Compose project or container landfall did not deploy
277
+ lf tunnel my-app db # a database: postgresql://localhost:5432 (the port its image exposes; --port picks another)
278
+ lf tunnel blog -l 3000 --lan # local port 3000, also on this machine's network: open it from a phone on the same Wi-Fi
269
279
  lf sites rm blog # delete the site (asks you to type the name)
270
280
  lf logs api -s vps # another site on another server
271
281
  ```
@@ -279,14 +289,14 @@ back. Domain and login changes are journaled, so `lf undo` reverts them.
279
289
  ```sh
280
290
  lf updates # packages (security marked, reboot needed), images, Docker/compose versions
281
291
  lf update # upgrade packages and pull newer images (asks first)
282
- lf update --packages --security # only security updates (apt, dnf)
292
+ lf update --security # only security updates (apt, dnf/yum); images stay
283
293
  lf update --packages --reboot # reboot afterwards if needed
284
294
  lf update --images # Traefik and image sites: pull, recreate
285
295
  lf update blog --images # one site
286
296
  lf update --compose # newest compose, where landfall installed it
287
297
  ```
288
298
 
289
- Package upgrades (apt-get, dnf/yum, apk) cannot be undone. Image and compose updates record the previous version,
299
+ Package upgrades (apt-get, dnf/yum, apk, zypper) cannot be undone. `--security` and `--reboot` imply `--packages`. Image and compose updates record the previous version,
290
300
  so `lf undo` restores it. landfall never touches images pinned by digest, Dockerfile sites or foreign containers.
291
301
  Version-pinned tags show the newest tag of the same shape (`traefik:v3.6` → `traefik:v3.7`).
292
302
 
@@ -311,8 +321,8 @@ publishes 80/443 to it. Sites work the same in both modes:
311
321
  | ufw | Docker's NAT bypasses ufw for 80/443 | ufw applies |
312
322
 
313
323
  HTTP/3 (QUIC) is on by default: Traefik also listens on 443/udp, and browsers switch to it after their first
314
- HTTP/2 request. Setup's firewall opens 443/udp; with `--host-network` on a server whose ufw is already active,
315
- `lf traefik setup` adds the rule. `--no-http3` turns it off (remembered). In the web UI (`lf ui`)
324
+ HTTP/2 request. Setup's firewall opens 443/udp (only with HTTP/3 on); with `--host-network` on a server whose ufw is active,
325
+ `lf traefik setup` opens 80/tcp, 443/tcp and 443/udp. `--no-http3` turns it off (remembered). In the web UI (`lf ui`)
316
326
  these options are in a server's settings under Traefik → Settings….
317
327
 
318
328
  Traefik only answers hosts it has a certificate for (`sniStrict`). A domain pointed at the server but served
@@ -322,11 +332,18 @@ for the seconds until Let's Encrypt issues its certificate. Your own certificate
322
332
  `/opt/landfall/traefik/dynamic/`: landfall rewrites only `landfall.yml` there. If you edit
323
333
  `docker-compose.yml` by hand, `lf traefik setup` shows the diff and stops; `--force` overwrites your edits.
324
334
 
325
- The dashboard password is generated and printed once (`--dashboard-password` sets your own, `--dashboard-user` the user, default `admin`).
326
- The dashboard is always reachable through `lf traefik dashboard`: Traefik serves it on port 8080 to the server itself only
327
- (loopback and the `web` network's gateway), never published. A Traefik set up before this needs `lf traefik setup` once.
328
- With your own Traefik, `lf traefik dashboard` tunnels to the entrypoint of the router that serves the dashboard on a domain and sends that domain along (TLS name and Host), so its login still applies; without such a router, `--port 8080` tunnels to its API port (api.insecure). The web UI shows the domains its dashboard is on. Image, network mode,
329
- e-mail, staging and dashboard are remembered per server.
335
+ **Traefik's dashboard.** `lf traefik dashboard` always reaches it through an SSH tunnel: Traefik serves it on
336
+ port 8080 to the server itself only (loopback and the `web` network's gateway), never published. A Traefik set
337
+ up before this needs `lf traefik setup` once. `--dashboard <domain>` also serves it on a domain behind a login;
338
+ the password is generated and printed once (`--dashboard-password` sets your own, `--dashboard-user` the user,
339
+ default `admin`).
340
+
341
+ With your own Traefik, `lf traefik dashboard` tunnels to the entrypoint of the router that serves the dashboard
342
+ on a domain and sends that domain along (TLS name and Host), so its login still applies. Without such a router,
343
+ `--port 8080` tunnels to its API port (api.insecure).
344
+
345
+ Image, network mode, HTTP/3, e-mail, staging and dashboard are remembered per server, so re-running
346
+ `lf traefik setup` keeps them.
330
347
 
331
348
  **Using a Traefik you already run.** If 80/443 belong to your own Traefik container, landfall does not install a second one:
332
349
 
@@ -336,7 +353,7 @@ lf traefik use proxy-traefik-1 -s vps # or name it
336
353
  ```
337
354
 
338
355
  Containers you run yourself behind that Traefik (compose projects with `traefik.http.routers.*.rule` labels)
339
- show up in `lf ls` and the dashboard as "not deployed by landfall", with their domains and folder. landfall
356
+ show up in `lf ls` and the web UI as "not deployed by landfall", with their domains and folder. landfall
340
357
  never touches them; deploying one of their domains warns, since Traefik would send visitors to only one.
341
358
  `lf adopt <project>` turns one into a site (see [Running without landfall](#running-without-landfall)).
342
359
 
@@ -363,7 +380,8 @@ lf firewall enable | disable # enable installs ufw if needed and all
363
380
  - Changes run as root or with sudo. If the user has neither (like `deploy`), landfall uses root's key login.
364
381
  - A change that would block the ssh port, or `enable` while ports in use have no rule, is refused. `--force` overrides.
365
382
  - Docker-published ports bypass ufw, so a deny rule doesn't close them. Bind them to `127.0.0.1` in their compose file instead.
366
- - `update` replaces the rule. If ufw rejects the new rule, the old one is put back.
383
+ - `update` replaces the rule in the same place, since ufw stops at the first match. If ufw rejects the new rule,
384
+ the old one is put back. `rm` and its undo also keep the rule's position.
367
385
 
368
386
  ## History and undo
369
387
 
@@ -383,8 +401,11 @@ lf undo --all # everything, newest first
383
401
  compose updates.
384
402
  - **Not undoable:** `sites rm`, restarts, package upgrades, and a firewall rule that replaced an existing one.
385
403
  - Steps revert newest first, each as the user that made it. The first failure stops the rest.
404
+ - Undoing an older run is refused while a later run still changed the same site, Traefik or file: undo the
405
+ later one first, or pass `--force`.
386
406
  - Undo changes the server only. Local `~/.config/landfall` and `.landfall.json` stay as they are.
387
407
  - Overwritten files are backed up as `.<name>.landfall-<run>-<n>`, and the newest 10 are kept per file.
408
+ - Two undos at once on the same server wait for each other, and a step already undone is skipped.
388
409
 
389
410
  ## Managing servers
390
411
 
@@ -405,24 +426,52 @@ lf ssh vps -- docker ps
405
426
  only steps in when the key does not work. It then puts the working `IdentityFile` first, drops lines whose file is
406
427
  gone, and keeps a backup as `~/.ssh/config.landfall-bak`.
407
428
 
408
- ## Dashboard
429
+ ## Web UI
430
+
431
+ ```sh
432
+ lf ui # starts on 127.0.0.1:4777 and opens your browser
433
+ lf ui --no-open # only print the login link
434
+ ```
409
435
 
410
- The web dashboard (`lf ui`) listens on `127.0.0.1` and opens your browser. Servers are on the left
411
- (★ marks the default). A server tab has Sites, Updates, Firewall, History and Settings. **Deploy folder…** browses
412
- local folders or takes a dropped folder or `.zip`. Every action streams the output of its plain command into a side
413
- panel. Destructive actions ask first. Login works through the printed `/login?t=…` link. The token is kept in
414
- `~/.config/landfall/ui-token`, and you can delete that file to rotate it. Requests with a foreign `Host` or `Origin`
415
- are refused. Running `lf ui` again while the dashboard is running just opens the page.
436
+ The web UI is a front end for the CLI. Every action runs a plain `lf` command as a subprocess, streams its
437
+ output into a side panel and shows the command (`$ lf rollback blog -s vps --to 20260122143005 -y`), so
438
+ anything you do there you can repeat in a terminal or a script. Runs started there are journaled like any
439
+ other and show up in `lf history`. The pages read the same data the `--json` commands print:
440
+
441
+ | page | commands |
442
+ |---|---|
443
+ | Sites | `lf ls`, `sites info`, `deploy`, `rollback`, `logs`, `restart`/`stop`/`start`, `env`, `domains`, `auth`, `tunnel`, `sites rm` |
444
+ | Updates | `lf updates`, `lf update` |
445
+ | Firewall | `lf firewall` and its subcommands |
446
+ | History | `lf history`, `lf undo` |
447
+ | Settings | `lf server config`, `server domain`, `traefik setup` (Settings…, Dashboard…), `traefik dashboard` |
448
+
449
+ Servers are on the left (★ marks the default). **Deploy folder…** browses local folders, or takes a dropped
450
+ folder or `.zip` (up to 512 MiB; archives with symlinks or hard links are refused). Destructive actions ask first.
451
+
452
+ - **Login:** through the printed `/login?t=…` link. The token is kept in `~/.config/landfall/ui-token`; delete
453
+ that file to rotate it.
454
+ - **Local only:** it listens on `127.0.0.1` and refuses requests with a foreign `Host` or `Origin`.
455
+ - Running `lf ui` again while it runs just opens the page. If another program has port 4777, it takes the next
456
+ free one (an explicit `--port` fails instead).
457
+ - **Limits:** at most 20 commands run at once. Passwords and env values are handed to the `lf` subprocess
458
+ through env vars and stdin, never on its command line.
459
+ - **No screen scraping:** commands report results the UI needs (deploy URL, tunnel address, setup checks, a
460
+ refusal that `--force` would override) on a separate channel, so the UI never parses CLI text.
416
461
 
417
462
  ## Using landfall from scripts and agents
418
463
 
419
- Every dashboard action is a plain command, and the dashboard prints the command it runs (`$ lf logs blog -s vps -f`).
464
+ Everything is a plain command; the web UI only runs those and prints each one (`$ lf logs blog -s vps -f`).
420
465
 
421
466
  - **No prompts:** `-y` accepts confirmations and takes defaults. Without a terminal, prompts are never shown. A
422
467
  command that would ask then **fails** and tells you to pass `-y`. It never silently goes ahead.
423
- - **Passwords:** pass them with `--password-stdin` or `$LANDFALL_PASSWORD` (`setup`, `server add`). For `lf auth`, use `-p`.
424
- - **JSON output:** `--json` works on `ls`, `info`, `server config`, `server domain`, `domains`, `firewall`,
425
- `updates` and `history`.
468
+ - **Passwords:** pass them with `--password-stdin` or `$LANDFALL_PASSWORD` (`setup`, `server add`), and
469
+ `lf auth --password-stdin`. Any `--…password` option also falls back to `$LANDFALL_SECRET_<NAME>`, e.g.
470
+ `LANDFALL_SECRET_DASHBOARD_PASSWORD`.
471
+ Env values: `lf env --env-file -` / `lf deploy --env-file -` read them from stdin.
472
+ - **JSON output:** `--json` works on `ls`, `info`, `server list`, `server config`, `server domain`, `domains`,
473
+ `firewall`, `updates` and `history`. The web UI reads the very same JSON. `ls --json --others` gives the full
474
+ overview; `domains --json` lists the server's addresses under `ips`.
426
475
  - **Dry runs:** `lf setup <name> --check` changes nothing. `lf updates` only reports.
427
476
  - **Exit codes:** `0` means success, `1` means error (the message starts with `error:` on stderr), and `2` means unknown command.
428
477
  - **Safety rails:** `-y` never overrides a safety refusal, for example a firewall change that would lock out ssh, or
@@ -451,7 +500,7 @@ lf undo -s box -y # revert the last run
451
500
  | `lf setup <name> --check` | Reports what is set up and what setup would change. Changes nothing. |
452
501
  | `lf setup <name> --key-only` | Only installs landfall's ssh key. |
453
502
  | `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`. |
454
- | `lf server list [--all]` | Lists registered servers. `--all` adds every ssh alias. Alias: `servers`. |
503
+ | `lf server list [--all] [--json]` | Lists registered servers. `--all` adds every ssh alias. Alias: `servers`. |
455
504
  | `lf server info [name] [--json]` | Shows OS and release support, kernel, uptime, CPU, RAM, disk, addresses and containers. Alias: `info`. |
456
505
  | `lf server config [name] [--json]` | Shows everything landfall and ssh use for a server. Does not connect. |
457
506
  | `lf server domain [name] [domain...] [--add d] [--primary d] [--rm d] [--clear] [--json]` | Manages main domains (the first is primary) and checks their DNS. |
@@ -470,12 +519,13 @@ lf undo -s box -y # revert the last run
470
519
  | `lf ls [--json] [--others]` | Lists sites on the server with their status, plus containers Traefik routes that landfall did not deploy (read only; `--json --others` gives `{sites, others}`). Alias: `sites list`. |
471
520
  | `lf sites info [name]` | Shows services, domains and release history. |
472
521
  | `lf domains [name] [--add d] [--rm d] [--set d] [--json]` | Lists domains with their DNS and HTTPS state, or changes them. Removing the last one leaves the site unrouted. |
473
- | `lf auth [name] -u user [-p pw]` / `--rm-user u` / `--off` | Puts basic-auth login in front of a site. |
522
+ | `lf auth [name] -u user [-p pw \| --password-stdin]` / `--rm-user u` / `--off` | Puts basic-auth login in front of a site. |
474
523
  | `lf open [name]` | Opens the site in the browser. |
475
524
  | `lf logs [name] [service] [-f] [-n lines]` | Shows logs of all services, or one. |
476
- | `lf env [name] [K=V...] [-u K]` | Shows or changes the site's `.env`. Recreates the services. |
525
+ | `lf env [name] [K=V...] [--env-file f\|-] [-u K]` | Shows or changes the site's `.env`. Recreates the services. |
477
526
  | `lf rollback [name] [--to id]` | Switches to the previous release, or to the given one. |
478
527
  | `lf restart` / `stop` / `start [name] [service]` | Restarts, stops or starts the site, or one service. |
528
+ | `lf tunnel [name] [service] [--port p] [-l local] [--lan]` | Opens a site, one of its services or any container on localhost through an SSH tunnel. |
479
529
  | `lf sites rm <name> [--volumes]` | Deletes the site and its files. Named volumes stay unless `--volumes`. |
480
530
  | `lf adopt <project> [--name n]` | Makes a Compose project you started yourself a site, so `ls`, logs, restart and rm work for it. |
481
531
 
@@ -486,6 +536,7 @@ lf undo -s box -y # revert the last run
486
536
  | `lf traefik setup [--email e] [--dashboard host\|traefik\|off] [--staging] [--image img] [--host-network] [--no-http3] [--force]` | Installs or reconfigures landfall's Traefik. `--force` overwrites hand edits. |
487
537
  | `lf traefik use [container] [--network n --entrypoint e --resolver r]` | Routes sites through a Traefik you already run. |
488
538
  | `lf traefik rm [--certs]` | Removes landfall's Traefik (undoable), or stops using yours after `traefik use`. |
539
+ | `lf traefik dashboard [-l local] [--lan] [--port p]` | Opens Traefik's dashboard on localhost through an SSH tunnel. |
489
540
  | `lf traefik status` / `logs [-f]` / `restart` | Inspects or restarts Traefik. `lf traefik` alone means `status`. |
490
541
  | `lf firewall [--json]` | Lists ufw rules and, for each listening port, whether it is reachable. |
491
542
  | `lf firewall allow` / `deny <port[/proto]> [--from ip] [--comment c]` | Adds a rule. A deny goes first, so it wins. |
@@ -494,22 +545,22 @@ lf undo -s box -y # revert the last run
494
545
  | `lf updates [--no-refresh] [--all] [--json]` | Shows pending OS packages, newer images, and Docker/compose versions. Changes nothing. |
495
546
  | `lf update [site...] [--packages] [--security] [--reboot] [--images] [--compose]` | Applies updates. Image and compose updates can be undone. |
496
547
  | `lf history [-n 20] [--json]` | Lists what landfall changed on the server, run by run. Alias: `log`. |
497
- | `lf undo [n \| n.m] [--all] [--force]` | Reverts the latest run, run `n`, step `n.m`, or everything. Alias: `revert`. |
548
+ | `lf undo [n \| n.m] [--all] [--force]` | Reverts the latest run, run `n`, step `n.m`, or everything. Refuses a run when a later one changed the same site or file, unless `--force`. Alias: `revert`. |
498
549
 
499
- **Dashboard**
550
+ **Web UI**
500
551
 
501
552
  | command | what it does |
502
553
  |---|---|
503
- | `lf ui [--port 4777] [--no-open]` | Starts the web dashboard on 127.0.0.1 and prints a login link. |
554
+ | `lf ui [--port 4777] [--no-open]` | Starts the web UI on 127.0.0.1 and prints a login link. Alias: `web`. |
504
555
 
505
556
  ## Files and config
506
557
 
507
558
  | local file | content |
508
559
  |---|---|
509
560
  | `~/.config/landfall/config.json` | registered servers, default server, per-server settings |
510
- | `~/.config/landfall/projects.json` | folders deployed from this machine (dashboard *Recent*/*Redeploy*) |
511
- | `~/.config/landfall/ui-token` | web dashboard login token |
512
- | `~/.config/landfall/uploads/` | folders dropped into the dashboard, removed after a day |
561
+ | `~/.config/landfall/projects.json` | folders deployed from this machine (web UI *Recent*/*Redeploy*) |
562
+ | `~/.config/landfall/ui-token` | web UI login token |
563
+ | `~/.config/landfall/uploads/` | folders dropped into the web UI, removed after a day |
513
564
  | `~/.ssh/landfall_<name>` | generated keys |
514
565
  | `~/.ssh/config` | `Host <name>` blocks between `# >>> landfall:<name>` markers |
515
566
  | `./.landfall.json` | per-project deploy settings |
@@ -519,12 +570,13 @@ lf undo -s box -y # revert the last run
519
570
  | `LANDFALL_CONFIG_DIR` | use another directory than `~/.config/landfall` |
520
571
  | `LANDFALL_SSH_CONFIG` | use another ssh config file (`ssh -F`) |
521
572
  | `LANDFALL_PASSWORD` | login password for `setup`/`server add`/`deploy --host` |
573
+ | `LANDFALL_SECRET_<OPTION>` | value of a `--…password` option, e.g. `LANDFALL_SECRET_PASSWORD` for `lf auth` |
522
574
 
523
575
  On the server:
524
576
 
525
577
  ```
526
578
  /opt/landfall/
527
- traefik/docker-compose.yml Traefik, ports 80/443, Let's Encrypt (HTTP-01)
579
+ traefik/docker-compose.yml Traefik, ports 80/443 (+443/udp for HTTP/3), Let's Encrypt (HTTP-01)
528
580
  traefik/letsencrypt/acme.json
529
581
  proxy.env only with `lf traefik use`
530
582
  README how to run sites by hand