Skip to content

feat: the first boot asks the fully qualified domain name - #36

Merged
marcos-mendez merged 1 commit into
masterfrom
feat/first-boot-fqdn
Oct 2, 2026
Merged

marcos-mendez merged 1 commit into
masterfrom
feat/first-boot-fqdn

Conversation

@marcos-mendez

@marcos-mendez marcos-mendez commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

What. A new interactive first boot hook, 31fqdn, asks the machine's fully qualified domain name, prefilled with the name the machine has (pct create --hostname; a dotted name as it is). On Apply, /etc/keel/instance.yaml (or the file 00declarative read) records instance.hostname, instance.fqdn and tls.acme.domains: [name] when it declares no domain yet (tls.acme.enabled is never touched; a hostname declared beside the unchanged name is kept; a description the answer does not change is not rewritten, and the file keeps its mode); then the first label becomes the hostname, set the way 09hostname sets it (the rename is now lib/hostname.sh, sourced by both hooks, matching the old name literally as a whole name or a first label, where the sed matched it inside any word), and /etc/hosts gets the entry that makes hostname -f answer the name, rewriting the line pct wrote for the host where it stands. The description comes first so a step that fails leaves one saying what the machine should be. A single label is kept as the hostname alone after a notice that no certificate can be requested without a domain; an empty answer keeps what the machine has. Lower case labels of letters, digits and dashes; anything else is refused and asked again. FQDN preseeds it (instance.fqdn renders it, so a described machine is not asked), FQDN=SKIP asks nothing.

Why. The first boot never asked a domain, so confconsole's Let's Encrypt screen had nothing to offer but example.com. The maintainer wants confconsole driven by the spec: this records the name there (Keel-Linux/confconsole#22 reads it).

How the spec is written. keel exposes no writer (no command, no API); confconsole's keelcli.py is the only one, not importable from here. libinithooks/fqdn.py follows it: PyYAML (sort_keys=False, so the rest of the file is kept in order; comments do not survive, as with every confconsole write), a copy beside the file, keel spec validate --no-secret-files on that copy when keel is installed, then os.replace. Without keel the copy is moved in after this hook's own domain check.

Decisions to note. Numbered 31: an interactive hook must be 30 or above (README; run waits for the boot from 30), and 30rootpass stays the first screen. The hostname written is the first label, never the dotted name (as keel apply does). The reader now accepts tls.acme.agree_tos, which keel's spec has and inithooks refused.

Tested. tests/test_fqdn.py (50) and tests/test_fqdn_cli.py (26) on the fake dialog, keel a stub on PATH; tests/test-hostname.bats (8) and tests/test-fqdn.bats (14), the last three running the real bin/fqdn.py with FQDN preseeded against a scratch instance.yaml and hosts file; test_dialog_brand.py covers bin/fqdn.py. Python 99 percent (both new files 100), shell 99.62 (new files 100), measured as in COVERAGE.md. The dialog texts fit 60 columns and at most 17 rows.

marcos-mendez pushed a commit to Keel-Linux/confconsole that referenced this pull request Oct 2, 2026
The domain boxes are prefilled from /etc/keel/instance.yaml:
tls.acme.domains when it declares any, else instance.fqdn (the name the
first boot records, Keel-Linux/inithooks#36), else from dehydrated's
domains file as before, example.com on a fresh machine. Once the
operator confirms the domains and the certificate is issued, the
description gets tls.acme.domains and tls.acme.enabled: true, written
as every Instance screen writes it (keelcli: staged, keel spec validate
--no-secret-files, moved into place; a refusal is shown and the file
left as it was). A request that fails writes nothing to it. dehydrated
keeps reading its own domains file, written as before; HTTP-01 and
DNS-01 are unchanged.

The screen's text was eleven rows, too tall for a 24 row console with
the five boxes under it; a test now holds it to the room that leaves.
marcos-mendez pushed a commit to Keel-Linux/confconsole that referenced this pull request Oct 2, 2026
The domain boxes are prefilled from /etc/keel/instance.yaml:
tls.acme.domains when it declares any, else instance.fqdn (the name the
first boot records, Keel-Linux/inithooks#36), else from dehydrated's
domains file as before, example.com on a fresh machine. Once the
operator confirms the domains and the certificate is issued, the
description gets tls.acme.domains and tls.acme.enabled: true, written
as every Instance screen writes it (keelcli: staged, keel spec validate
--no-secret-files, moved into place; a refusal is shown and the file
left as it was). A request that fails writes nothing to it. dehydrated
keeps reading its own domains file, written as before; HTTP-01 and
DNS-01 are unchanged.

The screen's text was eleven rows, too tall for a 24 row console with
the five boxes under it; a test now holds it to the room that leaves.
A new interactive hook, 31fqdn, after the root password and before the
application hooks: the box is prefilled with the name the machine has
(what pct create --hostname set; a dotted name as it is). The first
label becomes the hostname, set the way 09hostname sets it: the rename
is now lib/hostname.sh, sourced by both hooks. /etc/hosts gets the entry
that makes hostname -f answer the name, and the instance description
records instance.hostname and instance.fqdn, plus tls.acme.domains with
the name when it declares no domain yet; tls.acme.enabled is never
touched. A name without a domain is kept as the hostname alone after a
notice that no certificate can be requested without one; an empty
answer keeps what the machine has. FQDN preseeds it (instance.fqdn
renders it, so a described machine is not asked); FQDN=SKIP asks
nothing.

keel has no writer for the description, so libinithooks/fqdn.py writes
it as confconsole's keelcli.py does: PyYAML, a copy beside the file,
keel spec validate --no-secret-files when keel is installed, then moved
into place. The reader accepts tls.acme.agree_tos, as keel does.
@marcos-mendez
marcos-mendez merged commit 4f05a07 into master Oct 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant