You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(rhel): add kickstart version stamp, drop dead rm calls, document logs
* Add LF_KICKSTART_VERSION=2026041501 at the top of %pre. The stamp is
echoed into the pre-log, re-echoed at the start of the generated
%post (so it shows up in ks-script-*.log), and embedded as a comment
at the top of the rendered dynamic.ks. Since dynamic.ks is archived
to /root on the installed system, any host can be traced back to the
exact lf-rhel.cfg build that installed it. CONTRIBUTING gets a new
"Versioning the Kickstart File" section that documents the
YYYYMMDDNN format and when to bump.
* Drop the dead `rm -f /root/anaconda-ks.cfg` and
`rm -f /root/original-ks.cfg` calls from the cloud post-install
script. Anaconda writes both files via _writeKS_via_boss and
CopyLogsTask AFTER all %post scripts, so the rm -f calls ran before
the files existed and had no effect. A comment at the same spot
explains the ordering for future maintainers.
* README: add a "Log Files" section to each of the RHEL, Debian and
Ubuntu chapters, grouping the install-time and post-install log
files by symptom so an operator can go straight to the right one.
* README: document where to read the kickstart version stamp on an
installed system and fix the `ll /root` test to match the actual
cloud image state.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+7-2Lines changed: 7 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
9
9
## [Unreleased]
10
10
11
+
### Added
12
+
13
+
*`lf-rhel.cfg`: Add a running `LF_KICKSTART_VERSION` build stamp (format `YYYYMMDDNN`) declared at the top of `%pre`. The stamp is echoed during install (ends up in `/tmp/kickstart.install.pre.log`, `/var/log/anaconda/anaconda.log`, and the `%post``ks-script-*.log`) and embedded as a comment at the top of the rendered `dynamic.ks`, which is archived as `/root/dynamic.ks` on the installed system. This lets admins trace any installed host back to the exact `lf-rhel.cfg` variant that built it. CONTRIBUTING documents when and how to bump the stamp; the README documents where to read it on an installed system
14
+
11
15
### Fixed
12
16
13
17
*`lf-rhel.cfg`: Fix `grub2-mkconfig` being silently skipped on every target version. The `%pre` script was built via an unquoted heredoc (`cat << EOT`), which let bash eat every `"$var"` and `$(cmd)` reference embedded in the generated shell code before the Python helper was even written. As a result the grub finder always ran with empty variables and printed "Could not find a grub.cfg in /boot" — hiding the fact that `/etc/default/grub` edits had not been regenerated since the first release. The heredoc is now quoted (`cat << 'EOT'`), the finder targets `/boot/grub2/grub.cfg` directly (which is the right target on RHEL/Rocky 8/9/10 for both BIOS and UEFI — on 9+ UEFI the `/boot/efi/EFI/<vendor>/grub.cfg` is only a thin wrapper that `configfile`s `/boot/grub2/grub.cfg`), and the console-ordering change in `/etc/default/grub` is actually reflected in the generated `grub.cfg`
@@ -17,12 +21,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
21
18
22
### Changed
19
23
20
-
*`lf-rhel.cfg`: On `lftype=cloud` and `lftype=cloud-cis`, the post-install script now also removes `/root/original-ks.cfg` in addition to `/root/anaconda-ks.cfg`. Both files are written by modern Anaconda and both contain the raw bootstrap kickstart — removing both keeps the base image clean for cloud deployments
21
-
* README: Correct and sharpen the "Modifying this Kickstart" and "Tests" sections. The `lfkeys`, `users_<lftype>` and `post_<lftype>` descriptions now match the actual Python data structures and interpreter behavior, and the `ll /root` test is now explicit about which files to expect per `lftype`
24
+
*README: Add a "Log Files" section to each of the RHEL, Debian and Ubuntu chapters that lists the log files most relevant for diagnosing install-time and post-install problems, grouped by "during install" and "after install", so an operator can go straight to the right log for a given symptom
25
+
* README: Correct and sharpen the "Modifying this Kickstart" and "Tests" sections. The `lfkeys`, `users_<lftype>` and `post_<lftype>` descriptions now match the actual Python data structures and interpreter behavior, and the `ll /root` test now reflects that Anaconda's own kickstart copies (`anaconda-ks.cfg`, `original-ks.cfg`) are present on every install because they are written after all `%post` scripts and cannot be removed from within the kickstart
22
26
23
27
### Removed
24
28
25
29
*`lf-rhel.cfg`: Drop the dead `yum erase authconfig` call from the cloud post-install script. `authconfig` has not existed since RHEL 8 (replaced by `authselect`), so the call was a no-op on every supported target
30
+
*`lf-rhel.cfg`: Drop the dead `rm -f /root/anaconda-ks.cfg` and `rm -f /root/original-ks.cfg` calls from the cloud post-install script. Both files are written by Anaconda's boss module (`_writeKS_via_boss` and `CopyLogsTask`) **after** all `%post` scripts have run, so the removals ran against non-existent files and had no effect. A comment at the same spot now documents the ordering so future maintainers do not reintroduce this
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,6 +71,20 @@ Python packages installed via `pip` inside workflows follow a two-tier policy:
71
71
- One-shot installs such as `ansible-builder`, `build`, `mkdocs`, `pdoc`, and `ruff` in release, docs, or test workflows are version-pinned only (`package==X.Y.Z`) and kept fresh by Dependabot. Scorecard's `pipCommand not pinned by hash` findings for these are considered acceptable risk and may be dismissed.
72
72
73
73
74
+
### Versioning the Kickstart File
75
+
76
+
`lf-rhel.cfg` carries a running build stamp in the shell variable `LF_KICKSTART_VERSION` at the top of the `%pre` section. The value is logged at install time (to `/tmp/kickstart.install.pre.log`, the Anaconda logs, and the `%post``ks-script-*.log`) and embedded as a comment in the `dynamic.ks` archived under `/root/dynamic.ks` on the installed system, so the origin of any installed host can be traced back to a specific build.
77
+
78
+
The format is `YYYYMMDDNN`, where `YYYYMMDD` is the build date and `NN` is a two-digit daily sequence number starting at `01`. Example: `2026041501` for the first build on 2026-04-15, `2026041502` for the second on the same day.
79
+
80
+
Rules:
81
+
82
+
- Bump `LF_KICKSTART_VERSION` in every commit that changes the effective content of `lf-rhel.cfg` (kickstart logic, embedded shell/Python, comments that end up in the generated output).
83
+
- Pure documentation commits (`README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`) and commits that only touch `lf-debian.cfg` or `lf-ubuntu.cfg` do not bump the RHEL kickstart version.
84
+
- If multiple commits on the same day change `lf-rhel.cfg`, increment `NN` accordingly.
85
+
- Releases (as described in the `Changelog` section) also imply a version bump, because they are also content changes.
86
+
87
+
74
88
### Coding Conventions
75
89
76
90
- Sort variables, parameters, lists, and similar items alphabetically where possible.
Copy file name to clipboardExpand all lines: README.md
+73-1Lines changed: 73 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -147,7 +147,41 @@ What to test within the VM:
147
147
*`sudo dnf -y install nano`: Should work.
148
148
*`systemctl status cloud-init`: Not found on non-cloud, should work on cloud.
149
149
*`systemctl status firewalld`: Should be inactive on non-cloud. On cloud, firewalld is removed.
150
-
*`ll /root`: On `lftype=cis` and `lftype=minimal`, should list `anaconda-ks.cfg` and `original-ks.cfg` (both written by Anaconda), `dynamic.ks` (the rendered kickstart fragment Linuxfabrik applied) and `70-install-ssh-keys.ks` (the SSH key deployment fragment). On `lftype=cloud` and `lftype=cloud-cis`, should list only `dynamic.ks` — both of Anaconda's kickstart copies (`anaconda-ks.cfg` and `original-ks.cfg`) are removed by the cloud post-install script, and no SSH key fragment is generated because `cloud-init` handles keys.
150
+
*`ll /root`: Should list `dynamic.ks` (the rendered kickstart fragment Linuxfabrik applied, always present). Anaconda additionally writes `original-ks.cfg` on every install and, on most targets, `anaconda-ks.cfg` — both are written after all `%post` scripts, so they are not cleaned up by this kickstart. On `lftype=cis` and `lftype=minimal`, `70-install-ssh-keys.ks` is also archived (the SSH key deployment fragment); on `lftype=cloud` and `lftype=cloud-cis`, no SSH key fragment is generated because `cloud-init` handles keys.
151
+
*`grep 'Linuxfabrik Kickstart version' /root/dynamic.ks`: Should show the `YYYYMMDDNN` build stamp of the `lf-rhel.cfg` variant that was applied during installation. The same stamp is also written to `/var/log/anaconda/anaconda.log` and to the `%post``ks-script-*.log` under `/var/log/anaconda/`, so the origin of any installed host is traceable to a specific `lf-rhel.cfg` build.
152
+
153
+
154
+
### Log Files
155
+
156
+
During and after an Anaconda install, the following log files are the fastest path to diagnosing problems.
157
+
158
+
**During the install (installer environment, switch to a shell with `Ctrl+Alt+F2` or `Ctrl+Alt+F3`):**
159
+
160
+
*`/tmp/dynamic.ks`: The dynamically generated kickstart fragment that `%pre` produced. If Anaconda reports a kickstart syntax error in an included file, `cat` this file to see what was actually rendered.
161
+
*`/tmp/kickstart.install.pre.log`: Output of the `%pre` script, including the `LF_KICKSTART_VERSION` stamp, the `lftype`/`lfdisk` detection, and the Python helper's progress messages. First place to look if the install aborts before the package selection.
162
+
*`/tmp/ks-script-*.log`: Per-script output of each `%post` block and each post-script under `/usr/share/anaconda/post-scripts/`. Same files that will later be copied to `/var/log/anaconda/`.
163
+
*`/tmp/pre-script.py`: The Python helper itself. Useful if `%pre` crashes on a specific Python line.
164
+
165
+
**After a successful install (on the installed system, under `/var/log/anaconda/`):**
166
+
167
+
*`anaconda.log`: Main Anaconda narrative for the whole install. Start here when a post-install symptom shows up after first boot.
168
+
*`dbus.log`: Anaconda DBus module communication. Only needed for deeper Anaconda-internal issues (for example when the `boss` or `storage` module misbehaves, as with the `original-ks.cfg` write ordering).
169
+
*`journal.log`: Snapshot of the installer's journal at the end of install. Covers kernel, dracut and systemd messages; useful when the installer itself had boot problems.
170
+
*`ks-script-*.log`: Output of each `%post` block. `grep -l 'Linuxfabrik Kickstart version' /var/log/anaconda/ks-script-*.log` identifies the script that ran our `post_cloud`/`post_cis` block; that file contains the yum/dnf transaction output, the systemd-in-chroot warnings, the `grub2-mkconfig` result, and any messages from our cleanup/tweaks.
171
+
*`packaging.log`: DNF/yum transaction detail during the install. Goes deeper than `ks-script-*.log` when a package install or removal looks wrong.
172
+
*`program.log`: External programs Anaconda invoked (e.g. `grub2-mkconfig`, `mkfs.xfs`). Complements the other logs when the failing step was an external binary.
173
+
*`storage.log`: Partitioning, LVM creation, filesystem formatting. First stop for "disk not found", `ignoredisk` or LVM-related failures.
174
+
175
+
**On the installed system, outside `/var/log/anaconda/`:**
176
+
177
+
*`/root/anaconda-ks.cfg`: Anaconda's generated copy of the effective kickstart. Not present on targets where `can_save_output_kickstart=False` (including Rocky 10 cloud).
178
+
*`/root/dynamic.ks`: The kickstart fragment Linuxfabrik archived on the installed system. The first comment line reads `# Linuxfabrik Kickstart version: YYYYMMDDNN`, which attributes the host to a specific `lf-rhel.cfg` build.
179
+
*`/root/original-ks.cfg`: Anaconda's verbatim copy of the `lf-rhel.cfg` served from the `inst.ks=` URL.
180
+
181
+
**For `cloud-init` problems on `lftype=cloud` and `lftype=cloud-cis` (after first boot):**
182
+
183
+
*`/var/log/cloud-init-output.log`: Stdout/stderr of any user-data scripts that cloud-init executed.
184
+
*`/var/log/cloud-init.log`: Full cloud-init log with DEBUG-level entries. First stop for "my SSH keys aren't there" or "hostname not set".
151
185
152
186
153
187
### Troubleshooting
@@ -217,6 +251,26 @@ What to test within the VM:
217
251
*`sudo apt install -y nano`: Should work.
218
252
219
253
254
+
### Log Files
255
+
256
+
During and after a Debian Installer (d-i) preseed run, the following log files are the fastest path to diagnosing problems.
257
+
258
+
**During the install (switch to a shell with `Ctrl+Alt+F2`; live installer syslog tails on `Ctrl+Alt+F4`):**
259
+
260
+
*`/var/log/partman`: Partition manager log. First stop for disk, LVM or filesystem errors during install.
261
+
*`/var/log/syslog`: Main installer syslog. First stop for any preseed or d-i failure.
262
+
263
+
**After a successful install (on the installed system, under `/var/log/installer/`):**
264
+
265
+
*`cdebconf/questions.dat`: Preseed questions and the answers that were given (by our preseed file or interactively). Useful to verify that a preseed directive actually reached debconf.
266
+
*`cdebconf/templates.dat`: The debconf template catalogue, in case a preseed key was silently ignored because the template changed.
267
+
*`hardware-summary`: Detected hardware and driver decisions.
268
+
*`lsb-release`, `media-info`: Base distribution and installation media metadata.
269
+
*`partman`: Partition manager log, persisted from the install.
270
+
*`status`: `apt`/`dpkg` status of every package installed during the install phase.
271
+
*`syslog`: Main installer narrative for the whole install.
During and after a subiquity autoinstall run, the following log files are the fastest path to diagnosing problems.
334
+
335
+
**During the install (switch to a shell with `Ctrl+Alt+F2`):**
336
+
337
+
*`/var/log/installer/autoinstall-user-data`: The autoinstall YAML subiquity actually consumed. Useful to verify that the `user-data` file served over HTTP is what subiquity actually parsed.
338
+
*`/var/log/installer/subiquity-server-debug.log`: Subiquity server-side debug log, streams live during install. First stop for any autoinstall/subiquity failure.
339
+
340
+
**After a successful install (on the installed system, under `/var/log/installer/`):**
341
+
342
+
*`autoinstall-user-data`: The autoinstall YAML subiquity consumed, persisted.
343
+
*`cloud-init-output.log`, `cloud-init.log`: Cloud-init logs from inside the installer — subiquity uses cloud-init internally to fetch `user-data` and apply some steps.
344
+
*`curtin-install-cfg.yaml`, `curtin-install.log`: Curtin (the actual installer under subiquity) effective config and run log. First stop for partitioning, LVM or grub issues.
345
+
*`installer-journal.txt`: Journal snapshot from the installer environment.
346
+
*`subiquity-client-debug.log`, `subiquity-server-debug.log`: Subiquity's full debug logs.
0 commit comments