66ef83023498efc9904673967385354e6a18f231
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7f6fcb9166 |
Fix real STORAGE_PATH bug; add Start Podman + format-disk from the WebUI
Root cause of a fresh-install "cannot reach the Podman API socket" report (a friend's Unraid box, cache pool present and mounted): unlike Docker-for-Unraid's docker.img path, this plugin never auto-created STORAGE_PATH itself — only podman.img inside it. A perfectly normal, already-mounted cache pool still failed preflight/storage-create with "does not exist", just because its own .../system/podman subdirectory had never been created. Fixed by walking up to the nearest existing ancestor and checking whether it's on a different device than / (real mount vs. nothing mounted at all) — see podman-common.sh's new podman_path_has_real_mount_ancestor(), used by both podman-preflight.sh and podman-storage.sh. Settings gets a "Podman Service" card (status chip + Start/Restart, backed by new ajax/settings.php service_status/start/restart actions that just shell out to rc.podman) so a fresh install that failed to start can be diagnosed and retried without SSH/terminal access at all — exactly what was missing when this was first needed live. Also adds "Format a Disk for Podman Storage" (new ajax/disks.php) for a single-disk system with no cache pool at all. Only ever lists disks with literally no existing partition/filesystem/RAID-or-ZFS-membership signature and that aren't Unraid's boot flash — found live, twice, during development: the boot USB (FAT, labeled "UNRAID") passed the initial mounted-only check because this host's /boot is backed by a ZFS dataset rather than a direct partition mount, and active RAID-member cache disks passed a data-vs-blank *warning* rather than a hard exclusion. Both are now excluded outright, not just flagged — see disks.php's device_or_children_labeled_unraid() and the hasData exclusion in list_candidate_disks(). A disk formatted this way is remounted by UUID on every boot via a new plugin/sbin/podman-mount-managed-disk.sh, called from plugin/event/disks_mounted before rc.podman start. Unrelated fix bundled in: scripts/lib/slackbuild-common.sh now sets SOURCE_DATE_EPOCH (derived from the repo's last commit) before calling makepkg, so two separate builds of the same commit produce byte-identical .txz files — makepkg already supports this (`--clamp-mtime` when $SOURCE_DATE_EPOCH is set, confirmed by reading a real host's /sbin/makepkg) but nothing was setting the variable, so release.yml's "rebuild in CI and verify it matches the committed checksums" step was guaranteed to fail on the first package it checked alphabetically (observed live: aardvark-dns). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
2b79411b68 |
Replace vendored docker-compose with podman-compose
podman-compose and docker-compose aren't discovered the same way by `podman compose` - verified live (a fake-binary test reading podman's own provider-search error output) that docker-compose is searched for by exact path across a fixed list of CLI-plugin directories, while podman-compose is instead looked up as a plain command on $PATH. This package installs to /usr/local/bin/podman-compose accordingly, not under any cli-plugins/ directory. Unlike docker-compose (a single static Go binary), podman-compose is a Python script with two runtime dependencies neither of which ship with Unraid's own Python3 - PyYAML and python-dotenv, vendored here as plain pure-Python source (no C extension build; PyYAML's own fallback handles its optional C accelerator being absent). Verified end-to-end on a real host: with the previous docker-compose binary temporarily moved aside to confirm podman-compose was actually the one invoked, `podman compose up/ps/down` ran a real compose project correctly, including a live HTTP check against the started service. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
5b47b4cc0a |
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> |
||
|
|
51b7262b72 |
Fix five real bugs found by actually installing and running the plugin
First live end-to-end install on real Unraid hardware (all 8 built
packages installed via upgradepkg, rc.podman started, containers
pulled/run/networked/port-mapped) — surfaced five genuine bugs no
amount of container-based CI testing could have caught, since none of
them exist inside the vbatts/slackware:15.0 build container:
1. rc.podman never created $PODMAN_LOG_DIR before redirecting the
podman system service's output into it, so the service failed to
even start ("No such file or directory"). Added it alongside the
existing PODMAN_RUN_DIR mkdir.
2. config/storage.conf hardcoded a [storage] table, and
podman-config.sh's `sync` step appended a second one at boot with
the real graphroot/runroot — TOML forbids defining the same table
twice. Removed the template's [storage] entirely; sync already
generates the whole thing.
3. config/policy.json had a "_comment" pseudo-field for
documentation, but containers/image's policy parser rejects any
unknown top-level key outright. JSON has no comment syntax; moved
the rationale into docs/ARCHITECTURE.md instead.
4. netavark >= 2.0 dropped its iptables firewall driver entirely
(verified: passing "iptables" is flatly rejected) — nftables or
firewalld are the only remaining options, and firewalld needs
systemd/dbus, which Unraid has neither of. Set firewall_driver =
"nftables" explicitly and documented that Unraid OS doesn't ship
the `nft` binary this needs (a slackware64 nftables package works;
not yet wired into the build/install pipeline — see follow-up).
5. Every container failed with "crun: pivot_root: Invalid argument".
Root cause: Unraid's / is permanently the kernel's initial "rootfs"
pseudo-filesystem (Unraid never pivots to a real one at boot — the
whole OS runs from RAM), and pivot_root(2) unconditionally rejects
that as the old root. This is not new: Docker/runc hits the exact
same kernel restriction on this exact host and silently falls back
to an MS_MOVE-based chroot; crun has no such fallback, only a
--no-pivot flag with no config-file equivalent. Added
plugin/sbin/crun-no-pivot.sh, a thin wrapper that scans crun's full
argument list (podman puts global flags before the subcommand, so
the subcommand isn't reliably $1) and injects --no-pivot right
after create/run, and pointed containers.conf's crun runtime at it.
Also fixed the podman.plg postinstall's chmod glob
(`podman-*.sh` -> `*.sh`), which would have skipped this new
non-podman-prefixed sbin script.
Verified end-to-end on the real host: pull, run, real network
connectivity (wget through the container's bridge), and a published
port actually serving HTTP (curl through -p 8099:80 to nginx) all
work. --no-pivot's security tradeoff (disabling one particular
container-escape mitigation) was explicitly discussed with and
approved by the user before committing, given it must be the default
for any container to start at all on this platform.
Follow-up not yet done: nftables (needed for #4) is not yet a
packages/ component in the reproducible build pipeline — it was only
installed manually on the test host for this verification run.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
2e6832903b |
Fix CI: silence false-positive ShellCheck/EditorConfig findings
- podman-common.sh: file-wide shellcheck disable=SC2034 for its constants, which are intentionally defined for other scripts to source, not used within the file itself (ShellCheck can't see cross-file usage in that direction). Confirmed as the actual cause of the failing ShellCheck job via the real Gitea Actions log. - podman-storage.sh: use the retry counter in cmd_unmount's log message instead of leaving it genuinely unused (real SC2034 hit, not a false positive). - lint.yml: replace the editorconfig-checker/action-* marketplace action with a pinned, checksum-verified direct binary download — more robust than relying on third-party action resolution on self-hosted Gitea Actions runners — and disable its IndentSize check, which false-positives on Markdown's nested-list indentation and shell heredoc bodies. scripts/dev/lint.sh mirrors the same check for local use. All three lint.yml jobs verified passing locally. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
e2fefcdf9c |
Add reproducible build system, native Unraid plugin, and WebUI
- versions.env pins podman, conmon, crun, netavark, aardvark-dns, passt, and fuse-overlayfs to verified upstream source checksums; SlackBuild recipes, scripts/build-packages.sh, checksums.sh, release.sh, and update-versions.sh implement the reproducible pipeline; GitHub Actions workflows build in a Slackware container and publish releases without committing any binaries. - plugin/podman.plg installs/updates/removes all eight packages (the seven components plus the plugin's own unraid-podman scaffolding package) via upgradepkg, using the official Unraid array-event hook mechanism (event/disks_mounted, event/stopping) instead of editing /boot/config/go. rc.podman and the sbin/ helper scripts implement storage creation, config seeding/sync, preflight checks, autostart with per-container Safe-Mode, and package verify/update/rollback. - webui/plugins/podman implements the Dashboard, Containers, Pods, Images, Volumes, Networks, Logs, Terminal, Compose, and Settings panels against the approved mockup (webui/mockups/prototype.html), talking to podman system service exclusively via PodmanClient.php (libpod REST API over the Unix socket), with two documented exceptions: Terminal's one-shot exec model and Compose's use of the podman compose CLI, since libpod has no REST equivalent for either. - docs/ARCHITECTURE.md and docs/ROADMAP.md record the design decisions and honest current status (syntax-checked, unit- and integration-tested against fake sockets/servers; not yet run against a real Unraid/Podman/Slackware system). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |