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