Add catatonit/nftables/docker-compose packages, fix CSRF/streaming/storage bugs found by live testing

- Package #9-11: catatonit (pod infra init), nftables (netavark firewall
  backend), docker-compose (external compose provider for `podman compose`)
  — all vendored prebuilt binaries, versions.env pinned, propagated through
  build-packages.sh/release.sh/podman.plg/verify+update-packages.sh.
- Fix WebUI: every POST action was silently failing (empty response body)
  because Unraid's own CSRF protection was never satisfied — app.js now
  sends the page's csrf_token as X-CSRF-Token.
- Fix WebUI: PodmanClient::pullImage() assumed a single JSON response, but
  /images/pull actually streams newline-delimited JSON — every successful
  pull was throwing "Expected a JSON object/array response".
- Fix WebUI: compose.php's up/down status detection had the same
  single-JSON-vs-NDJSON bug for `podman compose ps`, plus stderr was
  corrupting the parse.
- Add cache-busting (?v=<mtime>) to Podman.page's script/style tags so a
  redeployed JS/CSS fix isn't served stale from browser cache.
- Add a reusable modal dialog (app.js openFormModal) replacing
  prompt()/alert() for New Volume/Network/Pull Image.
- Add host-path (bind-mount) support when creating a named volume.
- Add Create Container (image, name, network mode incl. custom networks,
  ports, volumes, env, restart policy, privileged, start-after-create),
  auto-pulling the image on first use since /containers/create doesn't.

All fixes verified live against a real podman system service and, where
reachable, via the actual WebUI over the real socket — not just unit-level.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 11:51:17 +00:00
co-authored by Claude Sonnet 5
parent 5944ddf722
commit 5b47b4cc0a
33 changed files with 1075 additions and 87 deletions
+66 -8
View File
@@ -32,14 +32,16 @@
Structure of this file:
1. DOCTYPE entity block — plugin metadata + one version/file/md5 triple
per package (the seven upstream components plus this project's own
"unraid-podman" scaffolding package, see packages/unraid-podman/).
per package (the seven upstream components, catatonit/nftables/
docker-compose as vendored runtime dependencies, plus this
project's own "unraid-podman" scaffolding package, see
packages/unraid-podman/).
Entities are rewritten automatically by scripts/release.sh; never
hand-edit a *_txz_version/_file/_md5 entity — see that script.
2. <PLUGIN> body:
a. <CHANGES> — kept in sync with CHANGELOG.md by hand for now.
b. Pre-install architecture sanity check.
c. Eight <FILE> package install/update blocks.
c. Eleven <FILE> package install/update blocks.
d. Postinstall <FILE Run="/bin/bash"> — directory/config seeding,
install-manifest generation, first start.
e. <FILE Run="/bin/bash" Method="remove"> — uninstall.
@@ -65,8 +67,8 @@
<!-- Slackware package naming components — must match versions.env's
PKG_ARCH/PKG_BUILD/PKG_TAG (see that file). Kept as entities here so
the eight removepkg calls in the Method="remove" block don't have to
repeat "x86_64-1_unraidpodman" eight times by hand. -->
the eleven removepkg calls in the Method="remove" block don't have to
repeat "x86_64-1_unraidpodman" eleven times by hand. -->
<!ENTITY pkgArch "x86_64">
<!ENTITY pkgBuild "1">
<!ENTITY pkgTag "_unraidpodman">
@@ -106,6 +108,27 @@
<!ENTITY fuse_overlayfs_txz_file "fuse-overlayfs-&fuse_overlayfs_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
<!ENTITY fuse_overlayfs_txz_md5 "00000000000000000000000000000000">
<!-- catatonit and nftables are runtime dependencies this plugin ships,
not upstream podman-ecosystem components — see packages/catatonit/
and packages/nftables/ READMEs for why each is needed (pod infra
container init; netavark's only viable firewall driver, since it
dropped iptables in 2.0 and Unraid has neither `nft` nor
systemd/dbus for firewalld) and why neither is built from source. -->
<!ENTITY catatonit_txz_version "0.0.0">
<!ENTITY catatonit_txz_file "catatonit-&catatonit_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
<!ENTITY catatonit_txz_md5 "00000000000000000000000000000000">
<!ENTITY nftables_txz_version "0.0.0">
<!ENTITY nftables_txz_file "nftables-&nftables_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
<!ENTITY nftables_txz_md5 "00000000000000000000000000000000">
<!-- docker-compose is the external Compose provider `podman compose`
shells out to (see packages/docker-compose/README.md) — without it
every Compose panel action fails outright on a clean install. -->
<!ENTITY docker_compose_txz_version "0.0.0">
<!ENTITY docker_compose_txz_file "docker-compose-&docker_compose_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
<!ENTITY docker_compose_txz_md5 "00000000000000000000000000000000">
<!-- unraid-podman is this project's OWN scaffolding package (rc.podman,
sbin/ scripts, event/ hooks, config templates — see
packages/unraid-podman/README.md), not an upstream component. Its
@@ -145,7 +168,7 @@
<!--
Pre-install sanity check: this project only builds/ships x86_64 packages
(see versions.env's PKG_ARCH) — fail with a clear message on any other
architecture rather than letting eight package downloads 404 one by one.
architecture rather than letting eleven package downloads 404 one by one.
-->
<FILE Run="/bin/bash">
<INLINE>
@@ -157,7 +180,9 @@ fi
</FILE>
<!--
The seven upstream component packages. Each is downloaded straight into
The seven upstream component packages, plus catatonit, nftables, and
docker-compose (runtime dependencies vendored as-is — see the entity
block above for why). Each is downloaded straight into
its backup slot under /boot/config/plugins/&name;/backup/packages/&version;/
(grouped by PLUGIN version, not each component's own version — a rollback
targets "this plugin release" as one unit, see
@@ -232,6 +257,33 @@ fi
</MD5>
</FILE>
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&catatonit_txz_file;" Run="upgradepkg --install-new --reinstall">
<URL>
&baseURL;/&catatonit_txz_file;
</URL>
<MD5>
&catatonit_txz_md5;
</MD5>
</FILE>
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&nftables_txz_file;" Run="upgradepkg --install-new --reinstall">
<URL>
&baseURL;/&nftables_txz_file;
</URL>
<MD5>
&nftables_txz_md5;
</MD5>
</FILE>
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&docker_compose_txz_file;" Run="upgradepkg --install-new --reinstall">
<URL>
&baseURL;/&docker_compose_txz_file;
</URL>
<MD5>
&docker_compose_txz_md5;
</MD5>
</FILE>
<!--
The plugin's own scaffolding package — rc.podman, sbin/ helper scripts,
the event/ hooks below, and default config templates. See
@@ -247,7 +299,7 @@ fi
</FILE>
<!--
Postinstall: everything that has to happen AFTER the eight packages above
Postinstall: everything that has to happen AFTER the eleven packages above
are on disk, but isn't itself package content — directory/config
seeding, the install-manifest that plugin/sbin/podman-verify-packages.sh
and podman-update-packages.sh read, and the first start. Runs on both
@@ -291,6 +343,9 @@ echo "NETAVARK_INSTALLED_VERSION=\"&netavark_txz_version;\"" >> "$MANIFEST"
echo "AARDVARK_DNS_INSTALLED_VERSION=\"&aardvark_dns_txz_version;\"" >> "$MANIFEST"
echo "PASST_INSTALLED_VERSION=\"&passt_txz_version;\"" >> "$MANIFEST"
echo "FUSE_OVERLAYFS_INSTALLED_VERSION=\"&fuse_overlayfs_txz_version;\"" >> "$MANIFEST"
echo "CATATONIT_INSTALLED_VERSION=\"&catatonit_txz_version;\"" >> "$MANIFEST"
echo "NFTABLES_INSTALLED_VERSION=\"&nftables_txz_version;\"" >> "$MANIFEST"
echo "DOCKER_COMPOSE_INSTALLED_VERSION=\"&docker_compose_txz_version;\"" >> "$MANIFEST"
echo "UNRAID_PODMAN_INSTALLED_VERSION=\"&unraid_podman_txz_version;\"" >> "$MANIFEST"
echo "Seeding /boot/config/plugins/podman/ configuration (existing files left untouched)..."
@@ -351,6 +406,9 @@ removepkg &netavark_txz_file;
removepkg &aardvark_dns_txz_file;
removepkg &passt_txz_file;
removepkg &fuse_overlayfs_txz_file;
removepkg &catatonit_txz_file;
removepkg &nftables_txz_file;
removepkg &docker_compose_txz_file;
removepkg &unraid_podman_txz_file;
echo ""