Files
unraid-podman/plugin/sbin/podman-config.sh
T
maggesandClaude Sonnet 5 e2fefcdf9c
Build Packages / Build .txz packages (push) Failing after 9s
Lint / ShellCheck (push) Failing after 43s
Lint / Validate .plg XML (push) Successful in 10s
Lint / EditorConfig (push) Failing after 6s
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>
2026-07-11 10:51:14 +00:00

142 lines
5.0 KiB
Bash
Executable File

#!/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