Commit Graph
7 Commits
Author SHA1 Message Date
Yann Autissier f429b8c38d derive the certificates a server needs from what it routes
The hostnames are already declared, once, in the fabio route tags. A
domains.txt would be a second source of truth free to disagree with what is
actually served, so myos cert reads the tags instead and decides on its own
which name needs a wildcard: one is asked for where a tag uses one, and it
absorbs the concrete names it covers. A wildcard covers a single label, so
a.b.example.org keeps its own certificate.

dehydrated issues them: a shell script, no python, which fits a tool that has
to install on any server. It answers http-01 itself on a port bound to the
loopback and routed by fabio, and delegates dns-01 to a provider hook. The
deploy hook writes the two file names fabio watches for, through a temporary
name so fabio never reads half a certificate.

Fixed on the way: the port parser wanted six spaces of indentation and the
catalogue writes four, so every stack that binds its ports was reported
unbound.
2026-09-05 13:41:16 +02:00
Yann Autissier be777fc9e6 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.
2026-09-05 13:22:04 +02:00
Yann Autissier 90bb97cca8 replace the linux-only firewall patching with a portable exposure model
The catalogue publishes 51 compose files with the bare form 'ports: [80]',
which binds a random host port on 0.0.0.0: every service answers the internet.
ufw-docker existed to take that back afterwards, as root, on linux only,
because docker writes its own firewall rules and ufw never sees those ports.

Publishing where you mean to solves it at the source. Verified against the
daemon: '- 80' gives 0.0.0.0:32768, '127.0.0.1::80' gives 127.0.0.1:32769.
Same on macOS and on linux, no privilege, and visible in docker ps.

A stack binds with ${MYOS_BIND_PRIVATE|PUBLIC|MESH} and declares what it
means with <PREFIX>_SERVICE[_<port>]_EXPOSE. myos expose reads the resolved
compose configuration and reports what would be opened; --strict fails when a
port faces the world without declaring it, which is what an agent runs against
a server it did not set up.
2026-09-05 13:07:13 +02:00
Yann Autissier 3e55cdcd14 chain commands, and let a project refine a catalogue stack
myos build up logs host/fabio runs the three in order and stops at the first
failure, the way make build up logs STACK=host/fabio did. Leading words that
name commands are commands; the first word that is not one starts the stacks.

A stack found in several directories of the stack path is now merged rather
than shadowed, least specific first, so a project drops
stack/postgres/postgres.local.yml next to the catalogue's postgres.yml and
refines it. Settings hooks follow the same order, so a project can redefine a
default the catalogue ships. Neither engine did this before: the project
directory simply hid the catalogue one.

An unknown command now says so and suggests the command to type, instead of
printing the whole usage.
2026-09-03 21:17:17 +02:00
Yann Autissier 55fae625d6 keep the dynamism of make in pure shell
Two mechanisms, matching what the make engine actually did:

Lazy defaults. A stack setting is a function myos_default_<VAR>, called only
when the variable has no value, and called again at every reference. That is
exactly a recursive ?=: an explicit value wins, and the default follows a
DOMAIN that a .env changes later. The prefix is what makes it safe; the first
version used a bare function named after the variable, and the test suite
caught it running /usr/bin/host for a stack group called host.

Templates. myos env-update fills a .env from the .env.dist files, expanding
${VAR} against the current values and running $(command), forward references
included.

Also fixed: the project .env now wins over /etc/conf.d/myos, which is what the
documentation claimed and the code did not.

share/make/shim.mk lets a project keep make as a front end: every myos command
becomes a target that shells out to bin/myos, and the project keeps its own
targets and its stack .mk files. It sits outside make/ because the legacy
engine globs every .mk in there.
2026-09-03 20:46:28 +02:00
Yann Autissier f541ca418b let a stack compute its settings without make
A stack can now ship <name>.env and <name>.sh next to its compose files. The
hook is sourced with the tag helpers available, which is what the computing
.mk files of the catalogue were using make for: 29 of its 44 .mk files only
exist to build variables like the fabio tags.

Converting stack/host/fabio.mk by hand gives byte-identical output for the
route tag, and drops a trailing comma the make version left in the listener
list.

Also: APP_HOST and APP_URI are computed (the tag helpers build on them),
--color controls the escape codes rather than always emitting them, and
make test-portability runs the CLI under busybox ash and dash.
2026-09-03 20:22:52 +02:00
Yann Autissier 32e2624245 add exec, run and scale, and the agent skill
The skill documents how to use myos: what to check before touching a host
stack, how a reference resolves, what the three kinds of stack mean, and where
each failure comes from. Every command it shows was run against the fixtures
before being written down, which is how exec, run and scale turned out to be
missing.

AGENTS.md covers the other side: how to change myos without breaking the
deployments that already run it.
2026-09-03 18:46:00 +02:00