Skip to content

proto: ddev-freeunit add-on - #41

Draft
andypost wants to merge 10 commits into
freeunit/integrationfrom
proto/ddev-freeunit
Draft

andypost wants to merge 10 commits into
freeunit/integrationfrom
proto/ddev-freeunit

Conversation

@andypost

Copy link
Copy Markdown
Owner

Proposed changes

A DDEV add-on that makes FreeUnit the project's web server. It uses webserver_type: generic + web_extra_daemons, the same pattern as ddev-frankenphp. It is laid out as a standalone add-on repository under pkg/ddev/ddev-freeunit/.

Contents:

  • web-build/Dockerfile.freeunit: builds unitd and the PHP module against sury's phpX.Y-embed;
  • a config renderer: Drupal-aware routes, plus optional schedules when FREEUNIT_CRON_KEY is set;
  • the commands ddev freeunit status|reload|log;
  • an Xdebug toggle that restarts the app over the control API;
  • bats tests and CI copied from ddev-addon-template.

Verified:

  • ./configure php against the sury 8.3 embed builds with no patches;
  • both generated configs are accepted by a live unitd;
  • PHP, static files, a deny rule, /status, app restart and schedules runs work;
  • shellcheck and YAML checks are clean.

Not verified: the docker build and the bats suite. The environment has no Docker daemon or DDEV installed, and pkg.ddev.com and sury are blocked.

Follow-up: a Fable review of this add-on is in progress; its fixes will land on this branch.

Checklist

  • I have read CONTRIBUTING.md
  • If applicable, I have added tests
  • If applicable, I have updated documentation

🤖 Generated with Claude Code

https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA


Generated by Claude Code

Runs FreeUnit as the DDEV web server (generic webserver_type +
web_extra_daemons).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
@andypost andypost mentioned this pull request Sep 24, 2026
5 tasks
Findings are in pkg/ddev/ddev-freeunit/REVIEW.md. The daemon could not
start as shipped (DDEV_APPROOT is not set in the container, /var/run and
/var/lib/freeunit are root-owned while web_extra_daemons run as the
project user, app user/group cannot be set unprivileged). Fixes: run from
/mnt/ddev_config, a /run/freeunit runtime dir owned by the project user,
one configure/make in the Dockerfile from the release tarball, unitd
loads the rendered conf.json from its state dir and is exec'd in the
foreground, X-Forwarded-Proto/-For via the listener's "forwarded" option,
dotfile deny and *.php execution for non-Drupal projects, embed SAPI
shares php-fpm's configuration so stock `ddev xdebug` and .ddev/php/*.ini
apply. Removed: the xdebug command override, cron schedules, FREEUNIT_*
knobs, the pre-install webserver_type check, most of the README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
Trust X-Forwarded-Proto/-For from any source (as DDEV's nginx does; the
RFC1918 list silently broke HTTPS detection on other Docker networks),
pipefail around curl|tar in the Dockerfile, comments out of the RUN
continuation, absolute unitd path, README wording; REVIEW.md rounds 2-3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
Root workflow runs the add-on's bats test on PHP 8.5 with FreeUnit built
from this commit (git archive into .ddev/web-build/freeunit-src.tar.gz,
picked up by the Dockerfile through a bind mount; the release tarball
stays the default), then benchmarks nginx-fpm against the add-on on
Drupal 11 and 12.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
assert_output --regexp anchors ^ at the start of the whole header block,
so the check could never pass (and the refute in the removal test could
never fail).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
composer create-project refuses a non-empty project directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
drush does not install on Drupal 12.0.0-alpha1, so tests/metrics-site.php
does the install, node creation and page_cache toggling through Drupal's
own API. The node page, the front page and the static file must answer
200 to anonymous users before anything is measured (the drupal11 leg
measured a node page that returned 500); on failure the last dblog
errors are printed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
Standard in Drupal 11.4/12 has no article type (the node page died in
NodeThemeHooks::preprocessNode() on a missing bundle) and Drupal 12
alpha1 answers 403 to anonymous users on /. metrics-site.php now creates
a 'bench' type (with body when the storage exists), grants
'access content', and points / at the node if there is no frontpage view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
hey prints "50%% in", so the report found no percentiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YSMMShDBn9zs2gFfTrLqwA
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.

2 participants