fix: the site is a route of keel-default, no check page of lnmp, and the commissioning contract #2

Merged
navigator merged 6 commits from feat/commission-contract into 19.x 2026-11-06 01:19:46 -03:00
Owner

Stacked on #1 (fix/ci-runner-label, the 45laravel hook and the tests): this branch starts at its head, dec1fee, so until #1 is merged the diff here shows its commits too. The new commit is 1bae3c0.

The contract of decision 0075 for this layer showed two image defects:

  1. The site cannot start. keel-web's default site, keel-default, is the default server on 80 and 443. The site of 19.0 (1) was a server of its own with default_server on 80, so nginx -t refuses it (a duplicate default server), and 443 served the placeholder page of keel-web. The site is now a route of the default site, /etc/nginx/keel-default.d/60-keel-laravel.conf, made of regular expressions as keel-wordpress has it: only public/index.php runs, other PHP files are 404, hidden files are refused (not /.well-known/), and the site answers 503 until 45laravel has written .env. conf.d/main runs nginx -t on a stand-in of the default site.
  2. The check page of lnmp is in the image. Its hook 40lnmp-check makes the database keel_check, and /keel-check/ shows the stack to anybody. It is lnmp's (decision 0059, point 6), not part of a Laravel product: conf.d/main removes the hook, 50-keel-lnmp.conf and /usr/share/keel-lnmp/www. confconsole's services screen names the Laravel site and Webmin.

Also:

  • keel/instance.example.yaml: appliance, installation.mode and every overlay of the chain (keel 0.23.83 refuses a description that leaves one out). tls.acme.email is not a key of the spec (keel: "tls.acme.email: unknown key"), so acme is off, as in lnmp's example.
  • tests/commission.yaml: questions (root, MariaDB admin of lnmp, Mode, alerts), the description, proofs, services, URLs (/ 200 on 443, /keel-health 204 on 80 of the loopback, /.env 403, /keel-check/ 404), forbidden items (keel_check, 40lnmp-check, the route of lnmp, a SQLite file, build tools).
  • .forgejo/workflows/tests.yml: the job commission / contract.
  • changelog: turnkey-laravel-19.0 (2).

Not run on the real sites. The laravel layer on the 11-05 lnmp was not built: my session could not put this branch into /turnkey/fab-keel/products/laravel on the build host. The coordinator builds it: flock /root/bt.lock bt-layer laravel --parent lnmp from this branch, then the lxc-interactive and lxc-preseed passes on BR1 and BR2.

The first contract asked http://127.0.0.1/ for 200 and the passes answered 404. That is by design: the checks run inside the machine, and on the loopback port 80 is the server of keel-overlay-nginx's conf.d/keel-health.conf (/keel-health 204, everything else 404). keel-default answers 80 on the machine's own addresses. The contract now asks http://127.0.0.1/keel-health for 204.

CI: the appliance job declares allow_unpublished: true: the laravel layer has never been published (the mirror answers 404), and without it the job failed at once, as on #1.

Test plan:

  • tests/layer.bats: 6 new tests, RED before the change, GREEN after; a site with default_server in the overlay fails them
  • nginx -t with nginx 1.26.3 (the image's) and the snippets of the lnmp rootfs: the route in a stand-in of keel-default is ok; the site of 19.0 (1) beside keel-default gives a duplicate default server
  • COVERAGE_THRESHOLD=100 tests/coverage.sh: 100 percent (290/290), 112 tests
  • keel-commission --check tests/commission.yaml: valid
  • keel 0.23.83: the manifest resolves along core, web, lnmp; the example, tests/instance.yaml and the contract's description validate
  • CI green
  • layer build on the 11-05 lnmp, nginx -t in conf.d passes
  • commissioning passes on BR1 and BR2
Stacked on #1 (`fix/ci-runner-label`, the 45laravel hook and the tests): this branch starts at its head, dec1fee, so until #1 is merged the diff here shows its commits too. The new commit is 1bae3c0. The contract of decision 0075 for this layer showed two image defects: 1. **The site cannot start.** keel-web's default site, `keel-default`, is the default server on 80 and 443. The site of 19.0 (1) was a server of its own with `default_server` on 80, so `nginx -t` refuses it (a duplicate default server), and 443 served the placeholder page of keel-web. The site is now a route of the default site, `/etc/nginx/keel-default.d/60-keel-laravel.conf`, made of regular expressions as keel-wordpress has it: only `public/index.php` runs, other PHP files are 404, hidden files are refused (not `/.well-known/`), and the site answers 503 until 45laravel has written `.env`. conf.d/main runs `nginx -t` on a stand-in of the default site. 2. **The check page of lnmp is in the image.** Its hook 40lnmp-check makes the database `keel_check`, and `/keel-check/` shows the stack to anybody. It is lnmp's (decision 0059, point 6), not part of a Laravel product: conf.d/main removes the hook, `50-keel-lnmp.conf` and `/usr/share/keel-lnmp/www`. confconsole's services screen names the Laravel site and Webmin. Also: - `keel/instance.example.yaml`: `appliance`, `installation.mode` and every overlay of the chain (keel 0.23.83 refuses a description that leaves one out). `tls.acme.email` is not a key of the spec (keel: "tls.acme.email: unknown key"), so acme is off, as in lnmp's example. - `tests/commission.yaml`: questions (root, MariaDB admin of lnmp, Mode, alerts), the description, proofs, services, URLs (`/` 200 on 443, `/keel-health` 204 on 80 of the loopback, `/.env` 403, `/keel-check/` 404), forbidden items (`keel_check`, 40lnmp-check, the route of lnmp, a SQLite file, build tools). - `.forgejo/workflows/tests.yml`: the job `commission / contract`. - changelog: turnkey-laravel-19.0 (2). **Not run on the real sites.** The laravel layer on the 11-05 lnmp was not built: my session could not put this branch into `/turnkey/fab-keel/products/laravel` on the build host. The coordinator builds it: `flock /root/bt.lock bt-layer laravel --parent lnmp` from this branch, then the lxc-interactive and lxc-preseed passes on BR1 and BR2. The first contract asked `http://127.0.0.1/` for 200 and the passes answered 404. That is by design: the checks run inside the machine, and on the loopback port 80 is the server of keel-overlay-nginx's `conf.d/keel-health.conf` (`/keel-health` 204, everything else 404). keel-default answers 80 on the machine's own addresses. The contract now asks `http://127.0.0.1/keel-health` for 204. **CI:** the appliance job declares `allow_unpublished: true`: the laravel layer has never been published (the mirror answers 404), and without it the job failed at once, as on #1. Test plan: - [x] `tests/layer.bats`: 6 new tests, RED before the change, GREEN after; a site with `default_server` in the overlay fails them - [x] `nginx -t` with nginx 1.26.3 (the image's) and the snippets of the lnmp rootfs: the route in a stand-in of keel-default is ok; the site of 19.0 (1) beside keel-default gives `a duplicate default server` - [x] `COVERAGE_THRESHOLD=100 tests/coverage.sh`: 100 percent (290/290), 112 tests - [x] `keel-commission --check tests/commission.yaml`: valid - [x] keel 0.23.83: the manifest resolves along core, web, lnmp; the example, tests/instance.yaml and the contract's description validate - [ ] CI green - [ ] layer build on the 11-05 lnmp, `nginx -t` in conf.d passes - [ ] commissioning passes on BR1 and BR2
fix: run CI on the keel-host runner
All checks were successful
tests / shellcheck (pull_request) Successful in 2s
cb1b478f03
The workflow asked for a runner with the label docker. No runner has that
label, so every run failed before it started. Use keel-host and
actions/checkout@v7, as the other Keel repositories do, and shellcheck every
shell file of the layer at severity warning.
fix: name no container runtime in CI
All checks were successful
tests / shellcheck (pull_request) Successful in 2s
bd20fefb61
test: bats coverage at 100 percent and the boot test
Some checks failed
tests / package (pull_request) Successful in 5s
tests / appliance (pull_request) Failing after 9s
tests / tests (pull_request) Successful in 23s
3dda85486a
Add the test suite of keel-redis, changed for this layer. The boot test
library has the checks that this layer adds over lnmp: the site on port
80 over IPv6, the PHP extensions, Composer, Node.js, Webmin and keel diff.
kcov measures tests/lib/boot-test-lib.sh at 100 percent (161/161) and
bin/keel-project-packages at 100 percent (32/32), over 62 bats tests.

The workflow has the three jobs of keel-redis: tests (test-shell.yml,
threshold 100) and package (require-changelog) on keel-host, and
appliance (test-appliance.yml, parent lnmp) on keel-lxc. Add the
changelog that bt-layer and require-changelog read.
fix: make conf.d/main executable
Some checks failed
tests / appliance (pull_request) Failing after 10s
tests / package (pull_request) Successful in 5s
tests / tests (pull_request) Successful in 24s
416176dcac
fab runs only the executable files in conf.d. This file was mode 0644, so
no build ran it and the layer had none of its configuration.
feat: first boot hook that makes the Laravel application of the machine
Some checks failed
tests / package (pull_request) Successful in 5s
tests / appliance (pull_request) Failing after 9s
tests / tests (pull_request) Successful in 32s
dec1feeb7f
The example description promised a first boot that runs composer
create-project, but no hook existed, and the boot test checked a
placeholder page.

The build now runs composer create-project (Laravel 12, --no-scripts) as
www-data in conf.d/main. The download is at build time and not at first
boot, so a machine made from the image needs no network to start. With
no scripts, the image holds no .env, no APP_KEY and no SQLite file.

firstboot.d/45laravel and lib/laravel.sh check every value of the
description and stop with the name of a bad option. They make the MariaDB
database and its user (SQL on stdin, random password when none is
declared), write .env with mode 0600 in one step, with a key from
artisan key:generate --show when none is declared, run the migrations
and wait until the site answers. Debug in production is refused.

The options are name, environment, debug, url, database and
database_user, and the secrets database_password and app_key. LNMP
already uses db_password and db_user for its administrative account, so
this layer uses other names. A new appliance manifest declares them.

The boot test now finds the name of the test description in the title
of the welcome page. tests/hook.bats, manifest.bats and layer.bats add
44 tests; the four measured files are at 100 percent over 106 tests.
fix: the site is a route of keel-default, no check page of lnmp, and the commissioning contract
Some checks failed
tests / package (pull_request) Successful in 5s
tests / appliance (pull_request) Failing after 10s
tests / commission (pull_request) Successful in 6s
tests / tests (pull_request) Successful in 37s
1bae3c03c7
keel-web's default site, keel-default, is the default server on 80 and
443. The site of 19.0 (1) was a server of its own with default_server on
80, so nginx -t refuses it ("a duplicate default server"), and 443 served
the placeholder page of keel-web. Found when the contract of decision 0075
was written for this layer (2026-11-06).

- overlay/etc/nginx/keel-default.d/60-keel-laravel.conf: the route, made of
  regular expressions, as keel-wordpress has it. Only public/index.php
  runs, every other PHP file is 404, hidden files are refused (not
  /.well-known/), and the site answers 503 until 45laravel has written
  .env. sites-available/laravel is removed.
- conf.d/main: nginx -t on a stand-in of the default site with the route
  in it; the real default site must include keel-default.d.
- conf.d/main: the check page of lnmp is removed: 40lnmp-check (it makes
  the database keel_check), 50-keel-lnmp.conf and /usr/share/keel-lnmp/www.
  It is not part of a Laravel product (decisions 0059 and 0075).
- overlay/etc/confconsole/services.txt: the Laravel site and Webmin, not the
  check page of lnmp.
- keel/instance.example.yaml: appliance, installation.mode and every overlay
  of the chain (keel 0.23.83 refuses a description that leaves one out);
  tls.acme.email is not a key of the spec, so acme is off, as in lnmp.
- tests/commission.yaml: the questions (root, MariaDB admin, Mode, alerts),
  the description, the proofs, the services, the URLs (/.env 403,
  /keel-check/ 404) and what is forbidden (keel_check, 40lnmp-check, the
  route of lnmp, a SQLite file).
- .forgejo/workflows/tests.yml: the job "commission / contract".
- tests/layer.bats: 6 new tests; coverage stays 100 percent (290/290).
- changelog: turnkey-laravel-19.0 (2).
navigator force-pushed feat/commission-contract from 1bae3c03c7
Some checks failed
tests / package (pull_request) Successful in 5s
tests / appliance (pull_request) Failing after 10s
tests / commission (pull_request) Successful in 6s
tests / tests (pull_request) Successful in 37s
to 0e8cdec2fa
Some checks failed
tests / package (pull_request) Successful in 5s
tests / commission (pull_request) Successful in 5s
tests / appliance (pull_request) Failing after 9s
tests / tests (pull_request) Successful in 38s
2026-11-06 00:23:09 -03:00
Compare
navigator force-pushed feat/commission-contract from 0e8cdec2fa
Some checks failed
tests / package (pull_request) Successful in 5s
tests / commission (pull_request) Successful in 5s
tests / appliance (pull_request) Failing after 9s
tests / tests (pull_request) Successful in 38s
to d725c81789
All checks were successful
tests / appliance (pull_request) Successful in 9s
tests / package (pull_request) Successful in 6s
tests / commission (pull_request) Successful in 7s
tests / tests (pull_request) Successful in 39s
2026-11-06 01:05:14 -03:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Keel-Linux/keel-laravel!2
No description provided.