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:
Executable
+141
@@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# plugin/sbin/podman-config.sh
|
||||
#
|
||||
# "Konfiguration anlegen" — creates and synchronizes unraid-podman's
|
||||
# configuration. Has two responsibilities, run as two subcommands:
|
||||
#
|
||||
# podman-config.sh seed
|
||||
# First-install (or "file went missing") step: ensures
|
||||
# /boot/config/plugins/podman/ exists with its full directory skeleton,
|
||||
# and copies default config templates into it — but ONLY for files that
|
||||
# don't already exist. This is what makes plugin updates safe: an
|
||||
# existing user configuration is never overwritten (see
|
||||
# docs/ARCHITECTURE.md section 3.2 and section 7).
|
||||
#
|
||||
# podman-config.sh sync
|
||||
# Boot-time step: copies the current, authoritative config from
|
||||
# /boot/config/plugins/podman/*.conf into /etc/containers/ (which lives
|
||||
# on Unraid's RAM-root and is empty again after every reboot). Run by
|
||||
# rc.podman on every `start`.
|
||||
#
|
||||
# Template source: the plugin ships its default config templates (from this
|
||||
# repo's config/) to /usr/local/share/unraid-podman/templates/ at install
|
||||
# time (see plugin/podman.plg) — that is what `seed` copies FROM, and
|
||||
# /boot/config/plugins/podman/ is what it copies TO.
|
||||
#
|
||||
# Usage:
|
||||
# podman-config.sh seed
|
||||
# podman-config.sh sync
|
||||
# =============================================================================
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./podman-common.sh
|
||||
. "$SCRIPT_DIR/podman-common.sh"
|
||||
|
||||
TEMPLATES_DIR="/usr/local/share/unraid-podman/templates"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# seed_file <template-filename> <dest-path>
|
||||
#
|
||||
# Copies a template into place only if the destination doesn't already
|
||||
# exist. This single rule is what protects user customizations across
|
||||
# plugin updates — see docs/ARCHITECTURE.md section 7, "Persistenz-Strategie".
|
||||
# -----------------------------------------------------------------------------
|
||||
seed_file() {
|
||||
local template_name="$1"
|
||||
local dest_path="$2"
|
||||
local src_path="$TEMPLATES_DIR/$template_name"
|
||||
|
||||
if [ -f "$dest_path" ]; then
|
||||
podman_log "config: $dest_path already exists, leaving untouched"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ ! -f "$src_path" ]; then
|
||||
podman_log_error "config: template missing: $src_path (plugin install incomplete?)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dest_path")"
|
||||
cp "$src_path" "$dest_path"
|
||||
podman_log "config: seeded $dest_path from template $template_name"
|
||||
}
|
||||
|
||||
cmd_seed() {
|
||||
podman_log "config: seeding /boot/config/plugins/podman/ (first install or repair)"
|
||||
|
||||
# Full directory skeleton — see docs/ARCHITECTURE.md section 4.1 and
|
||||
# plugin/boot-config/plugins/podman/README.md for the reference layout.
|
||||
mkdir -p \
|
||||
"$PODMAN_BOOT_DIR" \
|
||||
"$PODMAN_NETWORKS_BOOT_DIR" \
|
||||
"$PODMAN_BACKUP_DIR/packages" \
|
||||
"$PODMAN_BACKUP_DIR/config"
|
||||
|
||||
seed_file "podman.cfg.example" "$PODMAN_CFG_FILE"
|
||||
seed_file "containers.conf" "$PODMAN_BOOT_DIR/containers.conf"
|
||||
seed_file "storage.conf" "$PODMAN_BOOT_DIR/storage.conf"
|
||||
seed_file "registries.conf" "$PODMAN_BOOT_DIR/registries.conf"
|
||||
seed_file "policy.json" "$PODMAN_BOOT_DIR/policy.json"
|
||||
|
||||
# Autostart files: empty by default, `touch` is the "seed" here (no
|
||||
# template content to copy — see docs/ARCHITECTURE.md section 12).
|
||||
[ -f "$PODMAN_AUTOSTART_FILE" ] || { touch "$PODMAN_AUTOSTART_FILE"; podman_log "config: created empty $PODMAN_AUTOSTART_FILE"; }
|
||||
[ -f "$PODMAN_AUTOSTART_DELAY_FILE" ] || { touch "$PODMAN_AUTOSTART_DELAY_FILE"; podman_log "config: created empty $PODMAN_AUTOSTART_DELAY_FILE"; }
|
||||
[ -f "$PODMAN_PLUGIN_LOG" ] || touch "$PODMAN_PLUGIN_LOG"
|
||||
|
||||
podman_log "config: seeding complete"
|
||||
}
|
||||
|
||||
cmd_sync() {
|
||||
podman_load_cfg
|
||||
|
||||
if [ ! -d "$PODMAN_BOOT_DIR" ]; then
|
||||
podman_log_error "config: $PODMAN_BOOT_DIR does not exist — run 'podman-config.sh seed' first"
|
||||
return 1
|
||||
fi
|
||||
|
||||
podman_log "config: syncing $PODMAN_BOOT_DIR/*.conf -> $PODMAN_ETC_DIR/"
|
||||
mkdir -p "$PODMAN_ETC_DIR"
|
||||
|
||||
local any_missing=0
|
||||
for f in containers.conf storage.conf registries.conf policy.json; do
|
||||
if [ ! -f "$PODMAN_BOOT_DIR/$f" ]; then
|
||||
podman_log_error "config: missing $PODMAN_BOOT_DIR/$f (run 'podman-config.sh seed')"
|
||||
any_missing=1
|
||||
continue
|
||||
fi
|
||||
cp "$PODMAN_BOOT_DIR/$f" "$PODMAN_ETC_DIR/$f"
|
||||
done
|
||||
|
||||
if [ "$any_missing" -ne 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# storage.conf's graphroot/runroot are environment-specific (depend on
|
||||
# STORAGE_PATH from podman.cfg), so they are appended here at sync time
|
||||
# rather than hardcoded in the template — see config/storage.conf's own
|
||||
# comment on this split.
|
||||
{
|
||||
echo ""
|
||||
echo "# --- appended at boot by podman-config.sh sync, from podman.cfg ---"
|
||||
echo "[storage]"
|
||||
echo "driver = \"overlay\""
|
||||
echo "graphroot = \"$PODMAN_GRAPHROOT\""
|
||||
echo "runroot = \"/var/run/containers/storage\""
|
||||
} >> "$PODMAN_ETC_DIR/storage.conf"
|
||||
|
||||
podman_log "config: sync complete"
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
seed) cmd_seed ;;
|
||||
sync) cmd_sync ;;
|
||||
*)
|
||||
echo "usage: $0 {seed|sync}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user