landfall 0.1.0 → 0.3.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 +260 -163
- package/dist/cli.mjs +333 -189
- package/dist/index.html +305 -91
- package/dist/{job-CypEf1ud.mjs → job-DOi_DnYQ.mjs} +1 -1
- package/dist/server-Cj4TXzYj.mjs +4 -0
- package/dist/tui-0-Gcinq3.mjs +8 -0
- package/package.json +4 -3
- package/dist/server-CkG3c5Za.mjs +0 -4
- package/dist/tui-B0KECXvO.mjs +0 -8
package/README.md
CHANGED
|
@@ -4,14 +4,15 @@ Set up Linux servers and deploy sites to them behind [Traefik](https://traefik.i
|
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npm i -g landfall
|
|
7
|
-
lf setup
|
|
8
|
-
cd my-site && lf deploy -s
|
|
7
|
+
lf setup vps --host 203.0.113.7 # fresh Ubuntu/Debian box → Docker, firewall, Traefik, ssh key
|
|
8
|
+
cd my-site && lf deploy -s vps # live at https://my-site.203-0-113-7.sslip.io
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
- **Servers are ssh targets.** Any `~/.ssh/config` alias works. If `ssh
|
|
12
|
-
- **No agent on the server.**
|
|
11
|
+
- **Servers are ssh targets.** Any `~/.ssh/config` alias works. If `ssh vps` works, `lf deploy -s vps` works.
|
|
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
|
+
- **Your compose.yaml is the site.** App, database, worker: `docker compose up` runs it locally, `lf deploy` runs the same file behind HTTPS.
|
|
13
14
|
- **Every change is journaled** on the server and can be undone with `lf undo`.
|
|
14
|
-
- **Three ways in:** plain commands for scripts, CI and agents; a web dashboard (`lf`); a terminal dashboard (`lf tui`).
|
|
15
|
+
- **Three ways in:** plain commands for scripts, CI and agents; a web dashboard (`lf ui`); a terminal dashboard (`lf tui`).
|
|
15
16
|
|
|
16
17
|
`lf` is short for `landfall`. Both commands are installed.
|
|
17
18
|
|
|
@@ -19,8 +20,6 @@ cd my-site && lf deploy -s het # live at https://my-site.203-0-113-7.sslip.
|
|
|
19
20
|
|
|
20
21
|
- [Install](#install)
|
|
21
22
|
- [Concepts](#concepts)
|
|
22
|
-
- [Using landfall from scripts and agents](#using-landfall-from-scripts-and-agents)
|
|
23
|
-
- [Command reference](#command-reference)
|
|
24
23
|
- [Prepare a server](#prepare-a-server)
|
|
25
24
|
- [Deploy a site](#deploy-a-site)
|
|
26
25
|
- [Day-to-day](#day-to-day)
|
|
@@ -30,6 +29,8 @@ cd my-site && lf deploy -s het # live at https://my-site.203-0-113-7.sslip.
|
|
|
30
29
|
- [History and undo](#history-and-undo)
|
|
31
30
|
- [Managing servers](#managing-servers)
|
|
32
31
|
- [Dashboards](#dashboards)
|
|
32
|
+
- [Using landfall from scripts and agents](#using-landfall-from-scripts-and-agents)
|
|
33
|
+
- [Command reference](#command-reference)
|
|
33
34
|
- [Files and config](#files-and-config)
|
|
34
35
|
- [Troubleshooting](#troubleshooting)
|
|
35
36
|
- [Development](#development)
|
|
@@ -50,124 +51,39 @@ lf <command> --help # every option of one command
|
|
|
50
51
|
| term | meaning |
|
|
51
52
|
|---|---|
|
|
52
53
|
| **server** | An ssh target: a `~/.ssh/config` alias, or one landfall registered with `lf server add`/`lf setup`. Pass it as `-s <name>`. The first server you add becomes the default. |
|
|
53
|
-
| **site** | One
|
|
54
|
-
| **project file** |
|
|
55
|
-
| **main domain** | Optional per-server domain (`lf server domain
|
|
54
|
+
| **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
|
+
| **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
|
+
| **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. |
|
|
56
57
|
| **release** | Every deploy creates one, with an id like `20260122143005`. The last 5 are kept. `lf rollback` switches between them. |
|
|
57
58
|
| **run** | One landfall invocation that changed something on a server. Runs are listed by `lf history` and reverted by `lf undo`. |
|
|
58
59
|
|
|
59
60
|
How defaults resolve, for every command:
|
|
60
61
|
|
|
61
|
-
- **site** `[name]`: the argument, else `name` from
|
|
62
|
-
- **server** `-s`: the flag, else `server` from
|
|
63
|
-
|
|
64
|
-
## Using landfall from scripts and agents
|
|
65
|
-
|
|
66
|
-
Every dashboard action is a plain command, and both dashboards print the command they run (`$ lf logs blog -s het -f`).
|
|
67
|
-
|
|
68
|
-
- **No prompts:** `-y` accepts confirmations and takes defaults. Without a terminal, prompts are never shown. A
|
|
69
|
-
command that would ask then **fails** and tells you to pass `-y`. It never silently goes ahead.
|
|
70
|
-
- **Passwords:** pass them with `--password-stdin` or `$SRV_PASSWORD` (`setup`, `server add`). For `lf auth`, use `-p`.
|
|
71
|
-
- **JSON output:** `--json` works on `ls`, `info`, `server config`, `server domain`, `domains`, `firewall`,
|
|
72
|
-
`updates` and `history`.
|
|
73
|
-
- **Dry runs:** `lf setup <name> --check` changes nothing. `lf updates` only reports.
|
|
74
|
-
- **Exit codes:** `0` means success, `1` means error (the message starts with `error:` on stderr), and `2` means unknown command.
|
|
75
|
-
- **Safety rails:** `-y` never overrides a safety refusal, for example a firewall change that would lock out ssh, or
|
|
76
|
-
setup steps that would break running services. Only `--force` does.
|
|
77
|
-
|
|
78
|
-
A typical unattended flow:
|
|
79
|
-
|
|
80
|
-
```sh
|
|
81
|
-
printf '%s' "$ROOT_PW" | lf setup box --host 203.0.113.7 --password-stdin -y
|
|
82
|
-
lf server domain box example.com -y
|
|
83
|
-
lf deploy ./dist -n blog -s box -y # → https://blog.example.com
|
|
84
|
-
lf ls -s box --json
|
|
85
|
-
lf history -s box --json
|
|
86
|
-
lf undo -s box -y # revert the last run
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Command reference
|
|
90
|
-
|
|
91
|
-
`[name]` is a site or server and is optional (see [Concepts](#concepts)). Most site and server commands take `-s <server>`. Every command takes `-y` and `--help`.
|
|
92
|
-
|
|
93
|
-
**Servers**
|
|
94
|
-
|
|
95
|
-
| command | what it does |
|
|
96
|
-
|---|---|
|
|
97
|
-
| `lf setup <name> [--host ip]` | Turns a box into a deploy target: ssh key, Docker, ufw, fail2ban, deploy user, ssh hardening and Traefik. Idempotent. |
|
|
98
|
-
| `lf setup <name> --check` | Reports what is set up and what setup would change. Changes nothing. |
|
|
99
|
-
| `lf setup <name> --key-only` | Only installs landfall's ssh key. |
|
|
100
|
-
| `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`. |
|
|
101
|
-
| `lf server list [--all]` | Lists registered servers. `--all` adds every ssh alias. Alias: `servers`. |
|
|
102
|
-
| `lf server info [name] [--json]` | Shows OS and release support, kernel, uptime, CPU, RAM, disk, addresses and containers. Alias: `info`. |
|
|
103
|
-
| `lf server config [name] [--json]` | Shows everything landfall and ssh use for a server. Does not connect. |
|
|
104
|
-
| `lf server domain [name] [domain...] [--add d] [--primary d] [--rm d] [--clear] [--json]` | Manages main domains (the first is primary) and checks their DNS. |
|
|
105
|
-
| `lf server use <name>` | Sets the default server. |
|
|
106
|
-
| `lf server rm <name>` | Forgets a server locally. The server is untouched. |
|
|
107
|
-
| `lf ssh [name] [-- cmd]` | Opens a shell or runs a one-off command. |
|
|
108
|
-
| `lf keygen <name>` | Creates `~/.ssh/srv_<name>` and prints the public key. |
|
|
109
|
-
|
|
110
|
-
**Sites**
|
|
111
|
-
|
|
112
|
-
| command | what it does |
|
|
113
|
-
|---|---|
|
|
114
|
-
| `lf deploy [dir] [-d domain...] [-n name] [-b cmd] [--spa] [--image img] [--port n] [-e K=V] [--env-file f] [--static] [--keep n]` | Deploys a static folder, a Dockerfile app or an image. |
|
|
115
|
-
| `lf ls [--json]` | Lists sites on the server with their status. Alias: `sites list`. |
|
|
116
|
-
| `lf sites info [name]` | Shows domains, container and release history. |
|
|
117
|
-
| `lf domains [name] [--add d] [--rm d] [--set d] [--json]` | Lists domains with their DNS and HTTPS state, or changes them. |
|
|
118
|
-
| `lf auth [name] -u user [-p pw]` / `--rm-user u` / `--off` | Puts basic-auth login in front of a site. |
|
|
119
|
-
| `lf open [name]` | Opens the site in the browser. |
|
|
120
|
-
| `lf logs [name] [-f] [-n lines]` | Shows container logs. |
|
|
121
|
-
| `lf env [name] [K=V...] [-u K]` | Shows or changes env vars. Recreates the container. |
|
|
122
|
-
| `lf rollback [name] [--to id]` | Switches to the previous release, or to the given one. |
|
|
123
|
-
| `lf restart` / `stop` / `start [name]` | Restarts, stops or starts the site. |
|
|
124
|
-
| `lf sites rm <name>` | Deletes the site and its files. |
|
|
125
|
-
|
|
126
|
-
**Traefik, firewall, updates, history**
|
|
127
|
-
|
|
128
|
-
| command | what it does |
|
|
129
|
-
|---|---|
|
|
130
|
-
| `lf traefik setup [--email e] [--dashboard host\|traefik\|off] [--staging] [--image img] [--host-network]` | Installs or reconfigures landfall's Traefik. |
|
|
131
|
-
| `lf traefik use [container] [--network n --entrypoint e --resolver r]` | Routes sites through a Traefik you already run. |
|
|
132
|
-
| `lf traefik status` / `logs [-f]` / `restart` | Inspects or restarts Traefik. `lf traefik` alone means `status`. |
|
|
133
|
-
| `lf firewall [--json]` | Lists ufw rules and, for each listening port, whether it is reachable. |
|
|
134
|
-
| `lf firewall allow` / `deny <port[/proto]> [--from ip] [--comment c]` | Adds a rule. A deny goes first, so it wins. |
|
|
135
|
-
| `lf firewall update <n> [--port p] [--from ip] [--action allow\|deny\|limit]` | Changes a rule. |
|
|
136
|
-
| `lf firewall rm <n>` / `enable` / `disable` | Removes a rule, or turns ufw on or off. |
|
|
137
|
-
| `lf updates [--no-refresh] [--all] [--json]` | Shows pending OS packages, newer images, and Docker/compose versions. Changes nothing. |
|
|
138
|
-
| `lf update [site...] [--packages] [--security] [--reboot] [--images] [--compose]` | Applies updates. Image and compose updates can be undone. |
|
|
139
|
-
| `lf history [-n 20] [--json]` | Lists what landfall changed on the server, run by run. Alias: `log`. |
|
|
140
|
-
| `lf undo [n \| n.m] [--all] [--force]` | Reverts the latest run, run `n`, step `n.m`, or everything. Alias: `revert`. |
|
|
141
|
-
|
|
142
|
-
**Dashboards**
|
|
143
|
-
|
|
144
|
-
| command | what it does |
|
|
145
|
-
|---|---|
|
|
146
|
-
| `lf` / `lf ui [--port 4777] [--no-open]` | Starts the web dashboard on 127.0.0.1 and prints a login link. |
|
|
147
|
-
| `lf tui` | Starts the terminal dashboard. |
|
|
62
|
+
- **site** `[name]`: the argument, else `name` from `./.landfall.json`.
|
|
63
|
+
- **server** `-s`: the flag, else `server` from `./.landfall.json`, else the default server (`lf server use`).
|
|
148
64
|
|
|
149
65
|
## Prepare a server
|
|
150
66
|
|
|
151
67
|
### A fresh server (only a root password)
|
|
152
68
|
|
|
153
69
|
```sh
|
|
154
|
-
lf setup
|
|
70
|
+
lf setup vps --host 203.0.113.7
|
|
155
71
|
```
|
|
156
72
|
|
|
157
|
-
1. Creates `~/.ssh/
|
|
73
|
+
1. Creates `~/.ssh/landfall_vps` and installs it with `ssh-copy-id`. You type the root password once.
|
|
158
74
|
2. Installs Docker, ufw (allowing ssh, 80 and 443), fail2ban and unattended-upgrades.
|
|
159
75
|
3. Creates the user `deploy` in the docker group and disables ssh password login. Root keeps key-only access.
|
|
160
|
-
4. Writes `Host
|
|
76
|
+
4. Writes `Host vps` to `~/.ssh/config`, creating the file if needed. `ssh vps` now logs in as `deploy`.
|
|
161
77
|
5. Starts Traefik, which gets Let's Encrypt certificates for every site.
|
|
162
78
|
|
|
163
79
|
Setup shows what it is about to change and asks once (`-y` skips the question). Key login is checked **before**
|
|
164
80
|
password login is turned off, so a failed key setup can't lock you out.
|
|
165
81
|
|
|
166
|
-
### A server you already reach with `ssh
|
|
82
|
+
### A server you already reach with `ssh vps`
|
|
167
83
|
|
|
168
84
|
```sh
|
|
169
|
-
lf setup
|
|
170
|
-
lf setup
|
|
85
|
+
lf setup vps --check # what is there, what would change
|
|
86
|
+
lf setup vps
|
|
171
87
|
```
|
|
172
88
|
|
|
173
89
|
landfall reads host, user, port and key from your ssh config (`ssh -G`) and keeps a key that works. It inspects
|
|
@@ -189,7 +105,7 @@ with the newest release. An existing Docker is never reinstalled. In a terminal,
|
|
|
189
105
|
|---|---|
|
|
190
106
|
| `-u admin` / `-p 2222` | log in as `admin` (needs passwordless sudo) / ssh port |
|
|
191
107
|
| `-i ~/.ssh/id_ed25519` | use an existing key instead of generating one |
|
|
192
|
-
| `--password-stdin` | read the login password from stdin (or set `$
|
|
108
|
+
| `--password-stdin` | read the login password from stdin (or set `$LANDFALL_PASSWORD`) |
|
|
193
109
|
| `--deploy-user ""` | deploy as the login user instead of creating `deploy` |
|
|
194
110
|
| `--domain example.com` | primary main domain |
|
|
195
111
|
| `--staging` / `--no-staging` | use Let's Encrypt's staging CA while testing (remembered) |
|
|
@@ -209,59 +125,135 @@ No domain yet? Leave out `-d`. landfall offers `<name>.<ip-with-dashes>.sslip.io
|
|
|
209
125
|
|
|
210
126
|
| kind | when | how |
|
|
211
127
|
|---|---|---|
|
|
212
|
-
| **
|
|
128
|
+
| **compose** | the folder has a `compose.yaml` | Uploads the folder and runs it as one Compose project. See [Compose sites](#compose-sites). |
|
|
129
|
+
| **static** | no compose file, no Dockerfile | Uploads the folder and serves it with `nginx:alpine` (gzip, long cache headers for assets). The folder is `.` if it has an `index.html`, else the first of `dist/ build/ out/ public/ _site/ site/`. `--spa` sends unknown paths to `index.html`. |
|
|
213
130
|
| **dockerfile** | the folder has a `Dockerfile` | Uploads the folder and builds it on the server. The port comes from `EXPOSE`, else `--port` (default 3000). `--static` forces static. |
|
|
214
|
-
| **image** | `--image ghcr.io/me/app:1.2` | Pulls the image and runs it. Needs `--port`. For private registries: `lf ssh
|
|
131
|
+
| **image** | `--image ghcr.io/me/app:1.2` | Pulls the image and runs it. Needs `--port`. For private registries: `lf ssh vps -- docker login ghcr.io`. |
|
|
215
132
|
|
|
216
133
|
```sh
|
|
217
134
|
cd my-site
|
|
218
|
-
lf deploy -d example.com -d www.example.com -s
|
|
135
|
+
lf deploy -d example.com -d www.example.com -s vps # static, name = folder name (-n to override)
|
|
219
136
|
lf deploy -b "npm run build" # build locally first
|
|
220
137
|
lf deploy -d app.example.com -e DATABASE_URL=postgres://… --env-file .env.production # Dockerfile app
|
|
221
138
|
lf deploy -n api --image ghcr.io/me/api:1.4 --port 8080 -d api.example.com # image
|
|
222
|
-
lf deploy # later: redeploy using
|
|
139
|
+
lf deploy # later: redeploy using ./.landfall.json
|
|
223
140
|
```
|
|
224
141
|
|
|
225
|
-
The first deploy writes
|
|
142
|
+
The first deploy writes `.landfall.json`. Commit it:
|
|
226
143
|
|
|
227
144
|
```json
|
|
228
|
-
{ "name": "my-site", "server": "
|
|
145
|
+
{ "name": "my-site", "server": "vps", "domains": ["example.com", "www.example.com"] }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Local `.env*` files are never used on the server: each site has its own `.env` there. Pass variables with
|
|
149
|
+
`-e`/`--env-file`, or later with `lf env`. `--keep 10` keeps more releases.
|
|
150
|
+
|
|
151
|
+
### Compose sites
|
|
152
|
+
|
|
153
|
+
A site can be a whole Compose project: the app, its database, a worker. The same `compose.yaml` runs locally
|
|
154
|
+
with `docker compose up` and on the server with `lf deploy`. `lf init` writes one for an existing project:
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
lf init --postgres # compose.yaml (app + db + volume) and compose.override.yaml (local ports)
|
|
158
|
+
echo POSTGRES_PASSWORD=dev > .env # local only
|
|
159
|
+
docker compose up --build # http://localhost:3000
|
|
160
|
+
lf deploy -e POSTGRES_PASSWORD=$(openssl rand -hex 16) # the first time; later just lf deploy
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
services:
|
|
165
|
+
app:
|
|
166
|
+
build: .
|
|
167
|
+
env_file: [{ path: .env, required: false }]
|
|
168
|
+
environment:
|
|
169
|
+
DATABASE_URL: postgres://app:${POSTGRES_PASSWORD}@db:5432/app
|
|
170
|
+
depends_on: { db: { condition: service_healthy } }
|
|
171
|
+
x-landfall:
|
|
172
|
+
port: 3000 # Traefik serves the site's domains from here
|
|
173
|
+
admin:
|
|
174
|
+
image: adminer
|
|
175
|
+
x-landfall: { port: 8080, domains: [db.example.com] } # its own domains
|
|
176
|
+
db:
|
|
177
|
+
image: postgres:17-alpine
|
|
178
|
+
environment: { POSTGRES_USER: app, POSTGRES_DB: app, POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?}" }
|
|
179
|
+
volumes: [db:/var/lib/postgresql/data]
|
|
180
|
+
healthcheck: { test: pg_isready -U app, interval: 5s }
|
|
181
|
+
volumes:
|
|
182
|
+
db:
|
|
229
183
|
```
|
|
230
184
|
|
|
231
|
-
|
|
232
|
-
|
|
185
|
+
- **`x-landfall`** on a service routes it: `port` is where Traefik sends requests, `domains` gives it its own
|
|
186
|
+
(a bare name or `@` works as in `-d`). One routed service without `domains` serves the site's domains, which
|
|
187
|
+
`-d` and `lf domains` manage. Services without `x-landfall` (the database) stay off Traefik's network.
|
|
188
|
+
- **`ports:` is refused**, since a published port bypasses Traefik and the firewall. Put local ports in
|
|
189
|
+
`compose.override.yaml`: `docker compose` merges it locally, `lf deploy` leaves it out. To publish a port on
|
|
190
|
+
the server anyway, add `x-landfall: { publish: true }` to that service.
|
|
191
|
+
- **Named volumes keep your data** across deploys and rollbacks. `lf sites rm` keeps them, so deploying the
|
|
192
|
+
site again finds its data; `lf sites rm --volumes` deletes them. Each deploy gets a new release folder, so
|
|
193
|
+
a writable bind mount like `./data` is refused: write data to a named volume (read-only `./dist:…:ro` is fine).
|
|
194
|
+
- **Images built on the server** are tagged `<site>-<service>:<release>`, so a rollback runs the exact image again.
|
|
195
|
+
- Variables in `compose.yaml` come from the site's `.env` on the server (`-e`, `--env-file`, `lf env`).
|
|
196
|
+
`${VAR:?}` makes a missing one fail the deploy before anything changes.
|
|
197
|
+
- Your own `traefik.*` labels win: a service with its own router keeps them and landfall adds only the network.
|
|
198
|
+
- `-f other.yaml` deploys another file; it is saved in `.landfall.json`. Sites need Docker Compose 2.24 or newer
|
|
199
|
+
on the server (`lf update --compose`).
|
|
200
|
+
|
|
201
|
+
The static, Dockerfile and image kinds are Compose sites too: landfall writes their `compose.yaml` for you.
|
|
202
|
+
|
|
203
|
+
### Running without landfall
|
|
204
|
+
|
|
205
|
+
Nothing on the server depends on the CLI. Each site is a folder you can drive with plain `docker compose`:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
cd -P /opt/landfall/sites/blog/current # -P: into the release folder itself
|
|
209
|
+
docker compose ps # or logs -f, restart, up -d, down
|
|
210
|
+
cd /opt/landfall/sites/blog # roll back by hand: point current at an older release …
|
|
211
|
+
ln -sfn releases/20260122143005 current
|
|
212
|
+
cd -P current && docker compose up -d # … and bring it up
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`/opt/landfall/README` on the server explains the same. A project you started yourself behind landfall's
|
|
216
|
+
Traefik shows up in `lf sites` as not deployed by landfall; `lf adopt <project>` makes it a site that `lf` can
|
|
217
|
+
list, show logs for, restart and remove, while it keeps running from its own folder.
|
|
233
218
|
|
|
234
219
|
### Main domains
|
|
235
220
|
|
|
236
221
|
```sh
|
|
237
|
-
lf server domain
|
|
222
|
+
lf server domain vps example.com # checks DNS for example.com and *.example.com
|
|
238
223
|
lf deploy # site "blog" → blog.example.com
|
|
239
224
|
lf deploy -d shop # no dot → shop.example.com
|
|
240
225
|
lf domains blog --add www # www.example.com
|
|
241
|
-
lf
|
|
242
|
-
lf
|
|
243
|
-
lf server domain
|
|
226
|
+
lf deploy -d @ # @ → example.com itself
|
|
227
|
+
lf domains blog --add @ # blog also serves example.com
|
|
228
|
+
lf server domain vps --add other.org # more main domains; the first stays primary
|
|
229
|
+
lf server domain vps --primary other.org # switch the primary
|
|
230
|
+
lf server domain vps --rm other.org # drop one; --clear drops all (back to sslip.io)
|
|
244
231
|
```
|
|
245
232
|
|
|
246
233
|
`server domain` prints the A records to add: one for the domain and a wildcard `*.example.com`. With those in
|
|
247
234
|
place, every new site resolves without touching DNS again. For non-primary main domains, write the full name (`-d shop.other.org`).
|
|
248
235
|
|
|
236
|
+
A domain belongs to one site. Giving it to another one (`lf deploy -d @`, `lf domains shop --add example.com`)
|
|
237
|
+
asks, then moves it: the old site keeps its other domains. A move that would leave a site with none is refused,
|
|
238
|
+
and so is a redeploy whose domain comes only from `.landfall.json` (pass `-d` to move it on purpose).
|
|
239
|
+
|
|
249
240
|
## Day-to-day
|
|
250
241
|
|
|
251
242
|
```sh
|
|
252
|
-
lf ls # sites with status
|
|
253
|
-
lf sites info #
|
|
243
|
+
lf ls # sites with status, and your own containers behind Traefik
|
|
244
|
+
lf sites info # services, domains, releases
|
|
254
245
|
lf logs -f # follow logs (-n 500 for more lines)
|
|
246
|
+
lf logs blog db # one service
|
|
255
247
|
lf rollback # previous release (--to <id> for a specific one)
|
|
256
248
|
lf env API_KEY=abc # set env (container is recreated); -u KEY removes one
|
|
257
249
|
lf restart | stop | start
|
|
258
250
|
lf domains # where DNS points, whether HTTPS answers
|
|
259
|
-
lf domains --add www.example.com # also --rm, --set (updates
|
|
251
|
+
lf domains --add www.example.com # also --rm, --set (updates .landfall.json)
|
|
260
252
|
lf auth -u anna # login in front of the site (asks for the password, -p passes it)
|
|
261
253
|
lf auth --rm-user anna | --off
|
|
262
254
|
lf open
|
|
263
255
|
lf sites rm blog # delete the site (asks you to type the name)
|
|
264
|
-
lf logs api -s
|
|
256
|
+
lf logs api -s vps # another site on another server
|
|
265
257
|
```
|
|
266
258
|
|
|
267
259
|
Commands that remove something ask first: `sites rm`, `domains --rm/--set`, `server domain --rm/--clear`,
|
|
@@ -281,7 +273,7 @@ lf update --compose # newest compose, where landfall installed it
|
|
|
281
273
|
```
|
|
282
274
|
|
|
283
275
|
Package upgrades (apt-get, dnf/yum, apk) cannot be undone. Image and compose updates record the previous version,
|
|
284
|
-
so `lf undo` restores it.
|
|
276
|
+
so `lf undo` restores it. landfall never touches images pinned by digest, Dockerfile sites or foreign containers.
|
|
285
277
|
Version-pinned tags show the newest tag of the same shape (`traefik:v3.6` → `traefik:v3.7`).
|
|
286
278
|
|
|
287
279
|
## Traefik
|
|
@@ -294,7 +286,7 @@ lf traefik setup --dashboard traefik # dashboard at traefik.<main doma
|
|
|
294
286
|
lf traefik setup --host-network # bind 80/443 on the host
|
|
295
287
|
```
|
|
296
288
|
|
|
297
|
-
landfall's Traefik is the container `traefik` from `/opt/
|
|
289
|
+
landfall's Traefik is the container `traefik` from `/opt/landfall/traefik/docker-compose.yml`. By default Docker
|
|
298
290
|
publishes 80/443 to it. Sites work the same in both modes:
|
|
299
291
|
|
|
300
292
|
| | ports published (default) | `--host-network` |
|
|
@@ -302,24 +294,36 @@ publishes 80/443 to it. Sites work the same in both modes:
|
|
|
302
294
|
| client IP in logs / `X-Forwarded-For` | real IPv4; IPv6 may show Docker's gateway | always real |
|
|
303
295
|
| ufw | Docker's NAT bypasses ufw for 80/443 | ufw applies |
|
|
304
296
|
|
|
297
|
+
Traefik only answers hosts it has a certificate for (`sniStrict`). A domain pointed at the server but served
|
|
298
|
+
by no site fails the TLS handshake, as if nothing listened there, instead of showing a 404 or Traefik's own
|
|
299
|
+
certificate; plain HTTP to it redirects to HTTPS and fails the same way. A new site's domain fails the same way
|
|
300
|
+
for the seconds until Let's Encrypt issues its certificate. Your own certificates and Traefik config go into
|
|
301
|
+
`/opt/landfall/traefik/dynamic/`: landfall rewrites only `landfall.yml` there. If you edit
|
|
302
|
+
`docker-compose.yml` by hand, `lf traefik setup` shows the diff and stops; `--force` overwrites your edits.
|
|
303
|
+
|
|
305
304
|
The dashboard password is generated and printed once (`--dashboard-password` sets your own). Image, network mode,
|
|
306
305
|
e-mail, staging and dashboard are remembered per server.
|
|
307
306
|
|
|
308
307
|
**Using a Traefik you already run.** If 80/443 belong to your own Traefik container, landfall does not install a second one:
|
|
309
308
|
|
|
310
309
|
```sh
|
|
311
|
-
lf traefik use -s
|
|
312
|
-
lf traefik use traefik-
|
|
310
|
+
lf traefik use -s vps # finds the container on :80/:443
|
|
311
|
+
lf traefik use proxy-traefik-1 -s vps # or name it
|
|
313
312
|
```
|
|
314
313
|
|
|
314
|
+
Containers you run yourself behind that Traefik (compose projects with `traefik.http.routers.*.rule` labels)
|
|
315
|
+
show up in `lf ls` and the dashboard as "not deployed by landfall", with their domains and folder. landfall
|
|
316
|
+
never touches them; deploying one of their domains warns, since Traefik would send visitors to only one.
|
|
317
|
+
`lf adopt <project>` turns one into a site (see [Running without landfall](#running-without-landfall)).
|
|
318
|
+
|
|
315
319
|
landfall reads the network, HTTPS entrypoint and cert resolver from the container's flags. If your Traefik is
|
|
316
320
|
configured by a file, pass `--network proxy --entrypoint websecure --resolver letsencrypt`. The choice is stored
|
|
317
|
-
in `/opt/
|
|
321
|
+
in `/opt/landfall/proxy.env`. landfall never changes that Traefik.
|
|
318
322
|
|
|
319
323
|
## Firewall
|
|
320
324
|
|
|
321
325
|
```sh
|
|
322
|
-
lf firewall -s
|
|
326
|
+
lf firewall -s vps # rules + each listening port: open, limited, blocked, localhost only
|
|
323
327
|
lf firewall allow 51820/udp
|
|
324
328
|
lf firewall allow 5432 --from 10.0.0.0/8 --comment "db, lan only"
|
|
325
329
|
lf firewall deny 8080 # goes before the allow rules, so it wins
|
|
@@ -335,12 +339,12 @@ lf firewall enable | disable # enable installs ufw if needed and all
|
|
|
335
339
|
|
|
336
340
|
## History and undo
|
|
337
341
|
|
|
338
|
-
Every change landfall makes is appended to `/opt/
|
|
342
|
+
Every change landfall makes is appended to `/opt/landfall/journal.log` on the server: when, which local user and
|
|
339
343
|
command, what changed and the shell that reverts it.
|
|
340
344
|
|
|
341
345
|
```sh
|
|
342
|
-
lf history -s
|
|
343
|
-
lf undo -s
|
|
346
|
+
lf history -s vps # newest first; ↺ undoable, · not undoable, ✓ already undone
|
|
347
|
+
lf undo -s vps # revert the latest run with something left to undo
|
|
344
348
|
lf undo 4 # run #4
|
|
345
349
|
lf undo 4.2 # only its second step
|
|
346
350
|
lf undo --all # everything, newest first
|
|
@@ -351,42 +355,42 @@ lf undo --all # everything, newest first
|
|
|
351
355
|
compose updates.
|
|
352
356
|
- **Not undoable:** `sites rm`, restarts, package upgrades, and a firewall rule that replaced an existing one.
|
|
353
357
|
- Steps revert newest first, each as the user that made it. The first failure stops the rest.
|
|
354
|
-
- Undo changes the server only. Local `~/.config/
|
|
355
|
-
- Overwritten files are backed up as `.<name>.
|
|
358
|
+
- Undo changes the server only. Local `~/.config/landfall` and `.landfall.json` stay as they are.
|
|
359
|
+
- Overwritten files are backed up as `.<name>.landfall-<run>-<n>`, and the newest 10 are kept per file.
|
|
356
360
|
|
|
357
361
|
## Managing servers
|
|
358
362
|
|
|
359
363
|
```sh
|
|
360
|
-
lf server add
|
|
361
|
-
lf server add box --host
|
|
362
|
-
lf server add web --host
|
|
363
|
-
lf server config
|
|
364
|
+
lf server add vps # register an existing ssh alias
|
|
365
|
+
lf server add box --host 198.51.100.4 -u ubuntu -i ~/.ssh/box --default
|
|
366
|
+
lf server add web --host 198.51.100.5 -u admin # asks the password once, installs ~/.ssh/landfall_web
|
|
367
|
+
lf server config vps # landfall entry, Traefik settings, ssh login, keys, Host block
|
|
364
368
|
lf server list --all
|
|
365
|
-
lf server use
|
|
366
|
-
lf server rm
|
|
367
|
-
lf ssh
|
|
369
|
+
lf server use vps
|
|
370
|
+
lf server rm vps # forget locally
|
|
371
|
+
lf ssh vps -- docker ps
|
|
368
372
|
```
|
|
369
373
|
|
|
370
|
-
`server add` installs nothing on the server. It writes a `Host <name>` block between `# >>>
|
|
374
|
+
`server add` installs nothing on the server. It writes a `Host <name>` block between `# >>> landfall:<name>` markers
|
|
371
375
|
(`--no-ssh-config` keeps the details in landfall's config instead). In a Host block you wrote yourself, landfall
|
|
372
376
|
only steps in when the key does not work. It then puts the working `IdentityFile` first, drops lines whose file is
|
|
373
|
-
gone, and keeps a backup as `~/.ssh/config.
|
|
377
|
+
gone, and keeps a backup as `~/.ssh/config.landfall-bak`.
|
|
374
378
|
|
|
375
379
|
## Dashboards
|
|
376
380
|
|
|
377
|
-
**Web (`lf
|
|
381
|
+
**Web (`lf ui`).** The dashboard listens on `127.0.0.1` and opens your browser. Servers are on the left
|
|
378
382
|
(★ marks the default). A server tab has Sites, Updates, Firewall, History and Settings. **Deploy folder…** browses
|
|
379
383
|
local folders or takes a dropped folder or `.zip`. Every action streams the output of its plain command into a side
|
|
380
384
|
panel. Destructive actions ask first. Login works through the printed `/login?t=…` link. The token is kept in
|
|
381
|
-
`~/.config/
|
|
382
|
-
are refused. Running `lf` again while the dashboard is running just opens the page.
|
|
385
|
+
`~/.config/landfall/ui-token`, and you can delete that file to rotate it. Requests with a foreign `Host` or `Origin`
|
|
386
|
+
are refused. Running `lf ui` again while the dashboard is running just opens the page.
|
|
383
387
|
|
|
384
388
|
**Terminal (`lf tui`).**
|
|
385
389
|
|
|
386
390
|
```
|
|
387
|
-
landfall
|
|
388
|
-
╭ Servers ──────────╮╭ Sites on
|
|
389
|
-
│ › ●
|
|
391
|
+
landfall this folder: blog → vps · blog.example.com
|
|
392
|
+
╭ Servers ──────────╮╭ Sites on vps traefik Up 3 days ─────────────────────╮
|
|
393
|
+
│ › ● vps default │ │ › ● blog static blog.example.com 2h ago │
|
|
390
394
|
│ ● box │ │ ● api dockerfile api.example.com 5d ago │
|
|
391
395
|
│ ○ nas ssh config│ │ │
|
|
392
396
|
│ + add a server │ │ │
|
|
@@ -397,42 +401,131 @@ landfall 0.1.0 this folder: blog → het · blog.ex
|
|
|
397
401
|
Keys: `↵` connect/open, `d` deploy this folder, `u` check and set up, `a` add a server, `f` firewall, `h` history,
|
|
398
402
|
`z` undo, `x` shell, `esc` stop/back, `?` all keys. Dot colors: green ready, yellow not set up, red unreachable, ○ not connected.
|
|
399
403
|
|
|
404
|
+
## Using landfall from scripts and agents
|
|
405
|
+
|
|
406
|
+
Every dashboard action is a plain command, and both dashboards print the command they run (`$ lf logs blog -s vps -f`).
|
|
407
|
+
|
|
408
|
+
- **No prompts:** `-y` accepts confirmations and takes defaults. Without a terminal, prompts are never shown. A
|
|
409
|
+
command that would ask then **fails** and tells you to pass `-y`. It never silently goes ahead.
|
|
410
|
+
- **Passwords:** pass them with `--password-stdin` or `$LANDFALL_PASSWORD` (`setup`, `server add`). For `lf auth`, use `-p`.
|
|
411
|
+
- **JSON output:** `--json` works on `ls`, `info`, `server config`, `server domain`, `domains`, `firewall`,
|
|
412
|
+
`updates` and `history`.
|
|
413
|
+
- **Dry runs:** `lf setup <name> --check` changes nothing. `lf updates` only reports.
|
|
414
|
+
- **Exit codes:** `0` means success, `1` means error (the message starts with `error:` on stderr), and `2` means unknown command.
|
|
415
|
+
- **Safety rails:** `-y` never overrides a safety refusal, for example a firewall change that would lock out ssh, or
|
|
416
|
+
setup steps that would break running services. Only `--force` does.
|
|
417
|
+
|
|
418
|
+
A typical unattended flow:
|
|
419
|
+
|
|
420
|
+
```sh
|
|
421
|
+
printf '%s' "$ROOT_PW" | lf setup box --host 203.0.113.7 --password-stdin -y
|
|
422
|
+
lf server domain box example.com -y
|
|
423
|
+
lf deploy ./dist -n blog -s box -y # → https://blog.example.com
|
|
424
|
+
lf ls -s box --json
|
|
425
|
+
lf history -s box --json
|
|
426
|
+
lf undo -s box -y # revert the last run
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Command reference
|
|
430
|
+
|
|
431
|
+
`[name]` is a site or server and is optional (see [Concepts](#concepts)). Most site and server commands take `-s <server>`. Every command takes `-y` and `--help`.
|
|
432
|
+
|
|
433
|
+
**Servers**
|
|
434
|
+
|
|
435
|
+
| command | what it does |
|
|
436
|
+
|---|---|
|
|
437
|
+
| `lf setup <name> [--host ip]` | Turns a box into a deploy target: ssh key, Docker, ufw, fail2ban, deploy user, ssh hardening and Traefik. Idempotent. |
|
|
438
|
+
| `lf setup <name> --check` | Reports what is set up and what setup would change. Changes nothing. |
|
|
439
|
+
| `lf setup <name> --key-only` | Only installs landfall's ssh key. |
|
|
440
|
+
| `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`. |
|
|
441
|
+
| `lf server list [--all]` | Lists registered servers. `--all` adds every ssh alias. Alias: `servers`. |
|
|
442
|
+
| `lf server info [name] [--json]` | Shows OS and release support, kernel, uptime, CPU, RAM, disk, addresses and containers. Alias: `info`. |
|
|
443
|
+
| `lf server config [name] [--json]` | Shows everything landfall and ssh use for a server. Does not connect. |
|
|
444
|
+
| `lf server domain [name] [domain...] [--add d] [--primary d] [--rm d] [--clear] [--json]` | Manages main domains (the first is primary) and checks their DNS. |
|
|
445
|
+
| `lf server use <name>` | Sets the default server. |
|
|
446
|
+
| `lf server rm <name>` | Forgets a server locally. The server is untouched. |
|
|
447
|
+
| `lf ssh [name] [-- cmd]` | Opens a shell or runs a one-off command. |
|
|
448
|
+
| `lf keygen <name>` | Creates `~/.ssh/landfall_<name>` and prints the public key. |
|
|
449
|
+
|
|
450
|
+
**Sites**
|
|
451
|
+
|
|
452
|
+
| command | what it does |
|
|
453
|
+
|---|---|
|
|
454
|
+
| `lf init [dir] [--postgres] [--port n]` | Writes `compose.yaml` and `compose.override.yaml` for the project, to run it locally and deploy it. |
|
|
455
|
+
| `lf deploy [dir] [-d domain...] [-n name] [-f file] [-b cmd] [--spa] [--image img] [--port n] [-e K=V] [--env-file f] [--static] [--keep n]` | Deploys a Compose project, static folder, Dockerfile app or image. |
|
|
456
|
+
| `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`. |
|
|
457
|
+
| `lf sites info [name]` | Shows services, domains and release history. |
|
|
458
|
+
| `lf domains [name] [--add d] [--rm d] [--set d] [--json]` | Lists domains with their DNS and HTTPS state, or changes them. |
|
|
459
|
+
| `lf auth [name] -u user [-p pw]` / `--rm-user u` / `--off` | Puts basic-auth login in front of a site. |
|
|
460
|
+
| `lf open [name]` | Opens the site in the browser. |
|
|
461
|
+
| `lf logs [name] [service] [-f] [-n lines]` | Shows logs of all services, or one. |
|
|
462
|
+
| `lf env [name] [K=V...] [-u K]` | Shows or changes the site's `.env`. Recreates the services. |
|
|
463
|
+
| `lf rollback [name] [--to id]` | Switches to the previous release, or to the given one. |
|
|
464
|
+
| `lf restart` / `stop` / `start [name] [service]` | Restarts, stops or starts the site, or one service. |
|
|
465
|
+
| `lf sites rm <name> [--volumes]` | Deletes the site and its files. Named volumes stay unless `--volumes`. |
|
|
466
|
+
| `lf adopt <project> [--name n]` | Makes a Compose project you started yourself a site, so `ls`, logs, restart and rm work for it. |
|
|
467
|
+
|
|
468
|
+
**Traefik, firewall, updates, history**
|
|
469
|
+
|
|
470
|
+
| command | what it does |
|
|
471
|
+
|---|---|
|
|
472
|
+
| `lf traefik setup [--email e] [--dashboard host\|traefik\|off] [--staging] [--image img] [--host-network] [--force]` | Installs or reconfigures landfall's Traefik. `--force` overwrites hand edits. |
|
|
473
|
+
| `lf traefik use [container] [--network n --entrypoint e --resolver r]` | Routes sites through a Traefik you already run. |
|
|
474
|
+
| `lf traefik status` / `logs [-f]` / `restart` | Inspects or restarts Traefik. `lf traefik` alone means `status`. |
|
|
475
|
+
| `lf firewall [--json]` | Lists ufw rules and, for each listening port, whether it is reachable. |
|
|
476
|
+
| `lf firewall allow` / `deny <port[/proto]> [--from ip] [--comment c]` | Adds a rule. A deny goes first, so it wins. |
|
|
477
|
+
| `lf firewall update <n> [--port p] [--from ip] [--action allow\|deny\|limit]` | Changes a rule. |
|
|
478
|
+
| `lf firewall rm <n>` / `enable` / `disable` | Removes a rule, or turns ufw on or off. |
|
|
479
|
+
| `lf updates [--no-refresh] [--all] [--json]` | Shows pending OS packages, newer images, and Docker/compose versions. Changes nothing. |
|
|
480
|
+
| `lf update [site...] [--packages] [--security] [--reboot] [--images] [--compose]` | Applies updates. Image and compose updates can be undone. |
|
|
481
|
+
| `lf history [-n 20] [--json]` | Lists what landfall changed on the server, run by run. Alias: `log`. |
|
|
482
|
+
| `lf undo [n \| n.m] [--all] [--force]` | Reverts the latest run, run `n`, step `n.m`, or everything. Alias: `revert`. |
|
|
483
|
+
|
|
484
|
+
**Dashboards**
|
|
485
|
+
|
|
486
|
+
| command | what it does |
|
|
487
|
+
|---|---|
|
|
488
|
+
| `lf ui [--port 4777] [--no-open]` | Starts the web dashboard on 127.0.0.1 and prints a login link. |
|
|
489
|
+
| `lf tui` | Starts the terminal dashboard. |
|
|
490
|
+
|
|
400
491
|
## Files and config
|
|
401
492
|
|
|
402
493
|
| local file | content |
|
|
403
494
|
|---|---|
|
|
404
|
-
| `~/.config/
|
|
405
|
-
| `~/.config/
|
|
406
|
-
| `~/.config/
|
|
407
|
-
| `~/.config/
|
|
408
|
-
| `~/.ssh/
|
|
409
|
-
| `~/.ssh/config` | `Host <name>` blocks between `# >>>
|
|
410
|
-
|
|
|
495
|
+
| `~/.config/landfall/config.json` | registered servers, default server, per-server settings |
|
|
496
|
+
| `~/.config/landfall/projects.json` | folders deployed from this machine (dashboard *Recent*/*Redeploy*) |
|
|
497
|
+
| `~/.config/landfall/ui-token` | web dashboard login token |
|
|
498
|
+
| `~/.config/landfall/uploads/` | folders dropped into the dashboard, removed after a day |
|
|
499
|
+
| `~/.ssh/landfall_<name>` | generated keys |
|
|
500
|
+
| `~/.ssh/config` | `Host <name>` blocks between `# >>> landfall:<name>` markers |
|
|
501
|
+
| `./.landfall.json` | per-project deploy settings |
|
|
411
502
|
|
|
412
503
|
| env var | effect |
|
|
413
504
|
|---|---|
|
|
414
|
-
| `
|
|
415
|
-
| `
|
|
416
|
-
| `
|
|
505
|
+
| `LANDFALL_CONFIG_DIR` | use another directory than `~/.config/landfall` |
|
|
506
|
+
| `LANDFALL_SSH_CONFIG` | use another ssh config file (`ssh -F`) |
|
|
507
|
+
| `LANDFALL_PASSWORD` | login password for `setup`/`server add` |
|
|
417
508
|
|
|
418
509
|
On the server:
|
|
419
510
|
|
|
420
511
|
```
|
|
421
|
-
/opt/
|
|
512
|
+
/opt/landfall/
|
|
422
513
|
traefik/docker-compose.yml Traefik, ports 80/443, Let's Encrypt (HTTP-01)
|
|
423
514
|
traefik/letsencrypt/acme.json
|
|
424
515
|
proxy.env only with `lf traefik use`
|
|
516
|
+
README how to run sites by hand
|
|
425
517
|
sites/<name>/
|
|
426
518
|
site.json metadata + release history
|
|
427
|
-
|
|
428
|
-
nginx.conf static sites
|
|
429
|
-
.env app sites (0600)
|
|
519
|
+
.env the site's variables (0600)
|
|
430
520
|
releases/<id>/ last 5 kept
|
|
521
|
+
compose.yaml yours, or generated for static/Dockerfile/image
|
|
522
|
+
compose.override.yaml written by landfall: project name, Traefik labels, networks
|
|
523
|
+
.env -> ../../.env
|
|
431
524
|
current -> releases/<id>
|
|
432
525
|
journal.log every change, with the shell that reverts it
|
|
433
526
|
```
|
|
434
527
|
|
|
435
|
-
`cd /opt/
|
|
528
|
+
`cd -P /opt/landfall/sites/blog/current && docker compose ps` works as usual.
|
|
436
529
|
|
|
437
530
|
## Troubleshooting
|
|
438
531
|
|
|
@@ -441,8 +534,12 @@ On the server:
|
|
|
441
534
|
| `setup needs root or passwordless sudo` | use `-u root`, or give your user passwordless sudo |
|
|
442
535
|
| certificate warning in the browser | you used `--staging`: `lf setup <name> --no-staging` |
|
|
443
536
|
| no certificate at all | DNS must point at the server and 80/443 must be open; see `lf traefik logs` |
|
|
444
|
-
|
|
|
445
|
-
| site container keeps restarting | `lf logs`; for apps check `--port` and env |
|
|
537
|
+
| TLS handshake fails | no site serves the domain (`lf domains --add …`), or its certificate isn't issued yet: `lf traefik logs` |
|
|
538
|
+
| site container keeps restarting | `lf logs`; for apps check `--port` / `x-landfall.port` and env |
|
|
539
|
+
| `… publishes 5432 on the server, past Traefik and the firewall` | move `ports:` to `compose.override.yaml`, or allow it with `x-landfall: { publish: true }` |
|
|
540
|
+
| `sites need docker compose 2.24 or newer` | `lf update --compose` |
|
|
541
|
+
| `required variable … is missing` | set it on the server: `lf env KEY=…` or `lf deploy -e KEY=…` |
|
|
542
|
+
| `… was edited by hand` (traefik setup) | move your change to `dynamic/` or flags, or `lf traefik setup --force` |
|
|
446
543
|
| `skipping firewall/ssh hardening: …` | setup protected something running there. Fix it, or re-run with `--force` |
|
|
447
544
|
| `skipping traefik: port 80 is in use by …` | free the port, then `lf traefik setup`. If it's a Traefik, `lf traefik use` |
|
|
448
545
|
| `… blocks ssh port 22 … (--force to do it anyway)` | `lf firewall allow 22/tcp` first, or force if you have another way in |
|