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>
This commit is contained in:
@@ -0,0 +1,365 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
|
||||
<!--
|
||||
podman.plg — Unraid plugin manifest for unraid-podman.
|
||||
|
||||
This file is the single entry point Unraid's Plugin Manager uses to
|
||||
install, update, and remove the plugin. Everything it does is built on
|
||||
OFFICIAL Unraid plugin mechanisms only — verified directly against the
|
||||
real source of two long-established, widely used Unraid plugins
|
||||
(unraid/community.applications and unraid/unassigned.devices) rather than
|
||||
guessed:
|
||||
|
||||
- A FILE block with a Name attribute, an upgradepkg Run command (using
|
||||
its install new and reinstall flags together), and a URL/MD5 child
|
||||
pair is the standard way to download and install a Slackware .txz
|
||||
package, and the same command works for both a fresh install and an
|
||||
update in one step (confirmed: both reference plugins use exactly
|
||||
this pattern rather than separate installpkg/upgradepkg branches).
|
||||
- Plugin uninstall logic lives in a <FILE Run="/bin/bash" Method="remove">
|
||||
block — this exact `Method="remove"` attribute is what Unraid's
|
||||
plugin manager looks for when the user clicks "Remove" (confirmed
|
||||
against community.applications.plg).
|
||||
- Boot/shutdown integration uses the official Unraid plugin EVENT
|
||||
mechanism: any executable at
|
||||
/usr/local/emhttp/plugins/<name>/event/<eventname> is run automatically
|
||||
by emhttpd as the corresponding event fires (confirmed against
|
||||
unassigned.devices, which uses this exact convention for its own
|
||||
disks_mounted/started/stopping_svcs hooks). This project deliberately
|
||||
does NOT hand-edit /boot/config/go — see plugin/event/disks_mounted
|
||||
and plugin/event/stopping for the two hooks used here, and
|
||||
docs/ARCHITECTURE.md section 6.2 for the full event-ordering rationale.
|
||||
|
||||
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/).
|
||||
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.
|
||||
d. Postinstall <FILE Run="/bin/bash"> — directory/config seeding,
|
||||
install-manifest generation, first start.
|
||||
e. <FILE Run="/bin/bash" Method="remove"> — uninstall.
|
||||
-->
|
||||
|
||||
<!DOCTYPE PLUGIN [
|
||||
<!ENTITY name "podman">
|
||||
<!ENTITY author "unraid-podman contributors">
|
||||
<!ENTITY version "0.0.0">
|
||||
<!-- "Podman" (no parent) — Podman.page declares Menu="Podman", making it
|
||||
its own top-level nav tab next to Docker/VMs, not nested under
|
||||
Settings — see webui/plugins/podman/Podman.page. -->
|
||||
<!ENTITY launch "Podman">
|
||||
<!ENTITY github "OWNER/unraid-podman">
|
||||
<!ENTITY gitURL "https://raw.githubusercontent.com/&github;/main">
|
||||
<!ENTITY pluginURL "&gitURL;/plugin/podman.plg">
|
||||
<!ENTITY supportURL "https://github.com/&github;/discussions">
|
||||
|
||||
<!-- Release asset base — matches scripts/release.sh's RELEASE_BASE_URL
|
||||
exactly; both must agree since release.sh is what publishes the
|
||||
packages this URL is expected to find. -->
|
||||
<!ENTITY baseURL "https://github.com/&github;/releases/download/v&version;">
|
||||
|
||||
<!-- 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. -->
|
||||
<!ENTITY pkgArch "x86_64">
|
||||
<!ENTITY pkgBuild "1">
|
||||
<!ENTITY pkgTag "_unraidpodman">
|
||||
|
||||
<!-- One version/file/md5 entity triple per package, filled in by
|
||||
scripts/release.sh from dist/*.txz.md5 at release time (see that
|
||||
script's "Update per-package entities" step). Until a release has been
|
||||
cut, these are placeholders and the FILE blocks below will correctly
|
||||
fail to download anything — that is intentional; there is nothing to
|
||||
install before the first tagged release. -->
|
||||
|
||||
<!ENTITY podman_txz_version "0.0.0">
|
||||
<!ENTITY podman_txz_file "podman-&podman_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY podman_txz_md5 "00000000000000000000000000000000">
|
||||
|
||||
<!ENTITY conmon_txz_version "0.0.0">
|
||||
<!ENTITY conmon_txz_file "conmon-&conmon_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY conmon_txz_md5 "00000000000000000000000000000000">
|
||||
|
||||
<!ENTITY crun_txz_version "0.0.0">
|
||||
<!ENTITY crun_txz_file "crun-&crun_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY crun_txz_md5 "00000000000000000000000000000000">
|
||||
|
||||
<!ENTITY netavark_txz_version "0.0.0">
|
||||
<!ENTITY netavark_txz_file "netavark-&netavark_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY netavark_txz_md5 "00000000000000000000000000000000">
|
||||
|
||||
<!ENTITY aardvark_dns_txz_version "0.0.0">
|
||||
<!ENTITY aardvark_dns_txz_file "aardvark-dns-&aardvark_dns_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY aardvark_dns_txz_md5 "00000000000000000000000000000000">
|
||||
|
||||
<!ENTITY passt_txz_version "0.0.0">
|
||||
<!ENTITY passt_txz_file "passt-&passt_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY passt_txz_md5 "00000000000000000000000000000000">
|
||||
|
||||
<!ENTITY fuse_overlayfs_txz_version "0.0.0">
|
||||
<!ENTITY fuse_overlayfs_txz_file "fuse-overlayfs-&fuse_overlayfs_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY fuse_overlayfs_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
|
||||
version always equals the plugin's own &version; — see
|
||||
packages/unraid-podman/unraid-podman.SlackBuild, which reads it
|
||||
straight out of this very file rather than tracking it twice. -->
|
||||
<!ENTITY unraid_podman_txz_version "&version;">
|
||||
<!ENTITY unraid_podman_txz_file "unraid-podman-&unraid_podman_txz_version;-&pkgArch;-&pkgBuild;&pkgTag;.txz">
|
||||
<!ENTITY unraid_podman_txz_md5 "00000000000000000000000000000000">
|
||||
]>
|
||||
|
||||
<PLUGIN name="&name;"
|
||||
author="&author;"
|
||||
version="&version;"
|
||||
launch="&launch;"
|
||||
pluginURL="&pluginURL;"
|
||||
support="&supportURL;"
|
||||
icon="cubes"
|
||||
min="6.12.0">
|
||||
<!--
|
||||
min="6.12.0": Unraid 6.12 introduced folder-based (non-loopback) Docker
|
||||
storage and is a reasonably conservative baseline for the cgroup v2 /
|
||||
kernel networking features netavark, aardvark-dns, and passt assume. See
|
||||
docs/ARCHITECTURE.md section 21 (open question — revisit if real-world
|
||||
testing shows an earlier or later minimum is actually required).
|
||||
-->
|
||||
|
||||
<CHANGES>
|
||||
##podman
|
||||
|
||||
###0.0.0
|
||||
- Initial scaffolding. Not a functional release — see CHANGELOG.md for the
|
||||
authoritative, up-to-date history; this block is kept in sync with it by
|
||||
hand at release time (scripts/release.sh does not touch this section).
|
||||
</CHANGES>
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<FILE Run="/bin/bash">
|
||||
<INLINE>
|
||||
if [ "$(uname -m)" != "x86_64" ]; then
|
||||
echo "unraid-podman only supports x86_64 (detected: $(uname -m)) - aborting install."
|
||||
exit 1
|
||||
fi
|
||||
</INLINE>
|
||||
</FILE>
|
||||
|
||||
<!--
|
||||
The seven upstream component packages. 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
|
||||
plugin/sbin/podman-backup.sh's header comment) and installed from there
|
||||
in place via upgradepkg's install new / reinstall flags, which handle
|
||||
both a fresh install and an update to a newer version identically (see
|
||||
file header comment). This download-destination-doubles-as-backup approach is
|
||||
what makes plugin/sbin/podman-backup.sh's restore-packages command work
|
||||
with no separate copy step.
|
||||
-->
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&podman_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&podman_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&podman_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&conmon_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&conmon_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&conmon_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&crun_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&crun_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&crun_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&netavark_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&netavark_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&netavark_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&aardvark_dns_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&aardvark_dns_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&aardvark_dns_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&passt_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&passt_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&passt_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&fuse_overlayfs_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&fuse_overlayfs_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&fuse_overlayfs_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<!--
|
||||
The plugin's own scaffolding package — rc.podman, sbin/ helper scripts,
|
||||
the event/ hooks below, and default config templates. See
|
||||
packages/unraid-podman/README.md.
|
||||
-->
|
||||
<FILE Name="/boot/config/plugins/&name;/backup/packages/&version;/&unraid_podman_txz_file;" Run="upgradepkg --install-new --reinstall">
|
||||
<URL>
|
||||
&baseURL;/&unraid_podman_txz_file;
|
||||
</URL>
|
||||
<MD5>
|
||||
&unraid_podman_txz_md5;
|
||||
</MD5>
|
||||
</FILE>
|
||||
|
||||
<!--
|
||||
Postinstall: everything that has to happen AFTER the eight 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
|
||||
fresh install and every update (Unraid re-runs the whole .plg either way)
|
||||
— every step here is written to be idempotent, per
|
||||
docs/ARCHITECTURE.md section 7.
|
||||
-->
|
||||
<!--
|
||||
IMPORTANT for anyone editing this block: it is deliberately NOT wrapped
|
||||
in <![CDATA[ ]]>. CDATA sections suppress XML entity expansion entirely,
|
||||
which would leave literal, unexpanded text like "&version;" in the
|
||||
generated installed-versions.env instead of the real version number —
|
||||
confirmed by direct testing against this exact file. This is also why
|
||||
real Unraid plugins (community.applications, unassigned.devices) never
|
||||
wrap their entity-referencing INLINE scripts in CDATA either. The
|
||||
practical consequence: avoid literal '<' in this script (heredocs
|
||||
included) — a sequence of individual "echo >>" lines is used below
|
||||
instead for exactly that reason. A lone '>' is fine unescaped in XML
|
||||
content (only '<' and '&' are not) — verified empirically, not assumed.
|
||||
-->
|
||||
<FILE Run="/bin/bash">
|
||||
<INLINE>
|
||||
set -u
|
||||
|
||||
echo "Setting permissions..."
|
||||
chmod 0755 /etc/rc.d/rc.podman
|
||||
chmod 0755 /usr/local/sbin/podman-*.sh
|
||||
chmod 0755 /usr/local/emhttp/plugins/podman/event/disks_mounted
|
||||
chmod 0755 /usr/local/emhttp/plugins/podman/event/stopping
|
||||
|
||||
echo "Writing installed-package manifest..."
|
||||
mkdir -p /usr/local/share/unraid-podman
|
||||
MANIFEST=/usr/local/share/unraid-podman/installed-versions.env
|
||||
echo "# Generated by podman.plg postinstall - do not edit by hand." > "$MANIFEST"
|
||||
echo "# Read by podman-verify-packages.sh and podman-update-packages.sh." >> "$MANIFEST"
|
||||
echo "PLUGIN_VERSION=\"&version;\"" >> "$MANIFEST"
|
||||
echo "PODMAN_INSTALLED_VERSION=\"&podman_txz_version;\"" >> "$MANIFEST"
|
||||
echo "CONMON_INSTALLED_VERSION=\"&conmon_txz_version;\"" >> "$MANIFEST"
|
||||
echo "CRUN_INSTALLED_VERSION=\"&crun_txz_version;\"" >> "$MANIFEST"
|
||||
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 "UNRAID_PODMAN_INSTALLED_VERSION=\"&unraid_podman_txz_version;\"" >> "$MANIFEST"
|
||||
|
||||
echo "Seeding /boot/config/plugins/podman/ configuration (existing files left untouched)..."
|
||||
/usr/local/sbin/podman-config.sh seed
|
||||
|
||||
echo "Verifying package installation..."
|
||||
if /usr/local/sbin/podman-verify-packages.sh --quiet; then
|
||||
echo "Package verification OK."
|
||||
else
|
||||
echo "WARNING: package verification reported problems - see /boot/config/plugins/podman/plugin.log"
|
||||
fi
|
||||
|
||||
echo "Starting podman..."
|
||||
if /etc/rc.d/rc.podman start; then
|
||||
echo ""
|
||||
echo "----------------------------------------------------"
|
||||
echo " unraid-podman &version; has been installed and started."
|
||||
echo " CLI: podman --url unix:///var/run/podman/podman.sock ..."
|
||||
echo " Docs: https://github.com/&github;"
|
||||
echo "----------------------------------------------------"
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
echo "----------------------------------------------------"
|
||||
echo " unraid-podman &version; was installed but did not start cleanly."
|
||||
echo " It will be retried automatically the next time the array starts"
|
||||
echo " (see /usr/local/emhttp/plugins/podman/event/disks_mounted)."
|
||||
echo " Check /boot/config/plugins/podman/plugin.log for details."
|
||||
echo "----------------------------------------------------"
|
||||
echo ""
|
||||
fi
|
||||
</INLINE>
|
||||
</FILE>
|
||||
|
||||
<!--
|
||||
Uninstall. Triggered by Unraid's Plugin Manager when the user clicks
|
||||
"Remove" — the Method="remove" attribute is what makes this block
|
||||
(rather than any of the install blocks above) run in that case.
|
||||
|
||||
Order matters: podman-uninstall-cleanup.sh runs FIRST, while the
|
||||
unraid-podman package (which contains it, at /usr/local/sbin/) is still
|
||||
on disk — removepkg-ing it out from under itself mid-script would be a
|
||||
mistake. See that script's own header comment for exactly what is and
|
||||
is not removed by default (user data is preserved unless the purge-data
|
||||
flag is passed, which this normal removal flow deliberately never does).
|
||||
-->
|
||||
<!-- Not CDATA-wrapped — see the comment above the postinstall block for why: this content needs its &..._txz_file; entity references expanded, and CDATA would suppress that. Nothing here needs an unescaped '<'. -->
|
||||
<FILE Run="/bin/bash" Method="remove">
|
||||
<INLINE>
|
||||
echo "Running unraid-podman cleanup..."
|
||||
/usr/local/sbin/podman-uninstall-cleanup.sh
|
||||
|
||||
echo "Removing packages..."
|
||||
removepkg &podman_txz_file;
|
||||
removepkg &conmon_txz_file;
|
||||
removepkg &crun_txz_file;
|
||||
removepkg &netavark_txz_file;
|
||||
removepkg &aardvark_dns_txz_file;
|
||||
removepkg &passt_txz_file;
|
||||
removepkg &fuse_overlayfs_txz_file;
|
||||
removepkg &unraid_podman_txz_file;
|
||||
|
||||
echo ""
|
||||
echo "unraid-podman removed. Your configuration, backups, and container"
|
||||
echo "storage under /boot/config/plugins/podman/ and the configured"
|
||||
echo "STORAGE_PATH were left in place - see docs/INSTALL.md if you want"
|
||||
echo "to remove them too."
|
||||
echo ""
|
||||
</INLINE>
|
||||
</FILE>
|
||||
|
||||
</PLUGIN>
|
||||
Reference in New Issue
Block a user