read the exposure scope from the compose file, drop the _EXPOSE variable
The variable declared an intent and changed nothing: it fed the report and
never the binding, so it could say public while the file published on the
loopback, or the reverse. A declaration that cannot be wrong is better than one
that has to be kept in step.
The scope is now which binding the file asks for, read from the compose files
as written: ${MYOS_BIND_PUBLIC} is public, a hand-written address is pinned,
and a bare '- 80' or '9000:9000' is unbound, meaning docker opens it on every
address and nobody chose that. --strict fails on those.
Reading the resolved configuration instead would lose the distinction: every
form ends up as a plain address, and an unbound port looks exactly like a
deliberate public one.
What is left to configure per host is the address of each scope, which is the
part that belongs to the host rather than to the stack.
This commit is contained in:
@@ -85,7 +85,8 @@ See `references/conventions.md`.
|
||||
- Check what a stack opens before starting it on a server that faces the
|
||||
internet: `myos expose <stack>`. A port shown on `0.0.0.0` answers the world,
|
||||
and on linux the host firewall does not see it, because docker writes its own
|
||||
rules. Bind it instead: `ports: ["${MYOS_BIND_PRIVATE}::<port>"]`.
|
||||
rules. A port reported as `unbound` was published without anyone choosing an
|
||||
address: bind it with `ports: ["${MYOS_BIND_PRIVATE}::<port>"]`.
|
||||
- Never run `myos clean` on a host stack: it removes images **and volumes**,
|
||||
including the certificates.
|
||||
- Secrets belong in a file outside the repository, never in a compose file.
|
||||
|
||||
@@ -198,21 +198,23 @@ services:
|
||||
addresses; `MYOS_MESH_IFACE` names the interface when it is not one of
|
||||
easytier, tun0, tailscale0, mycelium or wg0.
|
||||
|
||||
A stack also declares what it means, so an audit can tell a deliberate choice
|
||||
from an oversight:
|
||||
There is nothing else to declare: the scope **is** the binding the file asks
|
||||
for. A port written `- 80` or `- "9000:9000"` is *unbound*, which means docker
|
||||
opens it on every address and nobody chose that.
|
||||
|
||||
```sh
|
||||
<PREFIX>_SERVICE_EXPOSE=public # the whole stack
|
||||
<PREFIX>_SERVICE_443_EXPOSE=public # one port
|
||||
myos expose # what each stack publishes, on which address
|
||||
myos expose --strict # exits 1 when a port is published without a binding
|
||||
```
|
||||
|
||||
`<PREFIX>` is `HOST_<name>` for a host stack, `USER_<name>` for a user stack,
|
||||
`<name>` otherwise.
|
||||
The command reads the compose files as written **and** the resolved
|
||||
configuration, and shows both: the binding the stack asked for, and the address
|
||||
it ends up on. Resolving first would lose the difference, since
|
||||
`${MYOS_BIND_PRIVATE}` and a hand-written `127.0.0.1` both become `127.0.0.1`,
|
||||
and an unbound port becomes `0.0.0.0` exactly like a deliberate public one.
|
||||
|
||||
```sh
|
||||
myos expose # what each stack publishes, and its declared scope
|
||||
myos expose --strict # exits 1 when a port faces the world undeclared
|
||||
```
|
||||
The split of responsibility: the **scope** belongs to the stack, in its compose
|
||||
file; the **address** of a scope belongs to the host, in its configuration.
|
||||
|
||||
## Groups
|
||||
|
||||
|
||||
Reference in New Issue
Block a user