Compare commits
No commits in common. "0cd352da007a9532fe1952a7d36633f1de440777" and "d0bf9b2f1200072cb8a500e1905cd8e7ef058014" have entirely different histories.
0cd352da00
...
d0bf9b2f12
|
|
@ -207,26 +207,6 @@ fi
|
||||||
############################################
|
############################################
|
||||||
# REQUIRED PACKAGES FOR INSTALL ENVIRONMENT
|
# REQUIRED PACKAGES FOR INSTALL ENVIRONMENT
|
||||||
############################################
|
############################################
|
||||||
# Wait for the live ISO's keyring initialization before any install. archiso
|
|
||||||
# initializes the pacman keyring asynchronously at boot via pacman-init.service
|
|
||||||
# (master-key generation can take a minute+ in VMs with little entropy), and
|
|
||||||
# this installer autostarts at login — racing that service leaves keys
|
|
||||||
# unpopulated/untrusted, so every package fails with "signature is unknown
|
|
||||||
# trust" / "invalid or corrupted package (PGP signature)". Do NOT run
|
|
||||||
# pacman-key --init ourselves here: doing so concurrently with
|
|
||||||
# pacman-init.service corrupts the half-built keyring. Wait, then refresh
|
|
||||||
# archlinux-keyring so an ISO built weeks ago still trusts current packager keys.
|
|
||||||
if systemctl cat pacman-init.service &>/dev/null; then
|
|
||||||
echo "Waiting for pacman keyring initialization (pacman-init.service)..."
|
|
||||||
while [[ "$(systemctl is-active pacman-init.service 2>/dev/null)" == "activating" ]]; do
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
else
|
|
||||||
# Not on archiso (e.g. re-run from an installed system) — ensure a keyring exists.
|
|
||||||
[[ -d /etc/pacman.d/gnupg ]] || { pacman-key --init; pacman-key --populate archlinux; }
|
|
||||||
fi
|
|
||||||
pacman -Sy --noconfirm archlinux-keyring
|
|
||||||
|
|
||||||
# Install tools needed by this script into the live environment before partitioning:
|
# Install tools needed by this script into the live environment before partitioning:
|
||||||
# parted — disk partitioning; cryptsetup — LUKS; libfido2/pam-u2f — FIDO2 enrollment.
|
# parted — disk partitioning; cryptsetup — LUKS; libfido2/pam-u2f — FIDO2 enrollment.
|
||||||
pacman -Sy --noconfirm parted cryptsetup libfido2 pam-u2f
|
pacman -Sy --noconfirm parted cryptsetup libfido2 pam-u2f
|
||||||
|
|
@ -609,14 +589,6 @@ sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"$KERNEL_CMD\"|" /etc/defau
|
||||||
|
|
||||||
# Install GRUB to the EFI partition; --bootloader-id sets the NVRAM entry name.
|
# Install GRUB to the EFI partition; --bootloader-id sets the NVRAM entry name.
|
||||||
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=M-Archy-GRUB
|
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=M-Archy-GRUB
|
||||||
# Also install to the UEFI removable-media fallback path (/EFI/BOOT/BOOTX64.EFI).
|
|
||||||
# The --bootloader-id install above only creates an NVRAM boot variable; a machine
|
|
||||||
# whose NVRAM is empty or gets cleared (fresh board, CMOS reset, firmware that
|
|
||||||
# drops stale entries, or — critically for this imaging/netboot installer — a disk
|
|
||||||
# cloned or redeployed to different hardware) then has "No bootable device". The
|
|
||||||
# removable fallback is what firmware boots when no NVRAM entry matches, so it makes
|
|
||||||
# the installed disk portable and self-booting regardless of NVRAM state.
|
|
||||||
grub-install --target=x86_64-efi --efi-directory=/boot --removable
|
|
||||||
# Generate grub.cfg from /etc/default/grub and detected kernels.
|
# Generate grub.cfg from /etc/default/grub and detected kernels.
|
||||||
grub-mkconfig -o /boot/grub/grub.cfg
|
grub-mkconfig -o /boot/grub/grub.cfg
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,28 +255,18 @@ else
|
||||||
DRIVE=$(ask "Enter install drive (e.g., /dev/sda)")
|
DRIVE=$(ask "Enter install drive (e.g., /dev/sda)")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Passwords ───────────────────────────────────────────────────────────────
|
# ── Passwords (always interactive; shown in clear text, each entered twice) ────
|
||||||
# In answerfile mode, honor a password embedded by the operator (needed for
|
# Never read from the answerfile. Captured once here and reused everywhere so the
|
||||||
# truly unattended netboot/WDS deployments where no one is at the console);
|
# operator is never prompted for them again mid-install.
|
||||||
# otherwise fall back to the interactive prompt. Captured once here and reused
|
|
||||||
# everywhere so the operator is never prompted for them again mid-install.
|
|
||||||
if $AF_MODE && [[ -n "$(af_get '.password')" ]]; then
|
|
||||||
USERPASS=$(af_get '.password')
|
|
||||||
else
|
|
||||||
USERPASS=$(ask_password "Password for $USERNAME")
|
USERPASS=$(ask_password "Password for $USERNAME")
|
||||||
fi
|
|
||||||
|
|
||||||
# LUKS passphrase — only needed when encrypting. Reused below for luksFormat /
|
# LUKS passphrase — only needed when encrypting. Reused below for luksFormat /
|
||||||
# open / luksAddKey / cryptenroll so it is typed exactly once (plus confirmation),
|
# open / luksAddKey / cryptenroll so it is typed exactly once (plus confirmation),
|
||||||
# never again during the destructive phase.
|
# never again during the destructive phase.
|
||||||
LUKS_PASS=""
|
LUKS_PASS=""
|
||||||
if [[ "$ENCRYPT_DISK" == "YES" ]]; then
|
if [[ "$ENCRYPT_DISK" == "YES" ]]; then
|
||||||
if $AF_MODE && [[ -n "$(af_get '.luks_password')" ]]; then
|
|
||||||
LUKS_PASS=$(af_get '.luks_password')
|
|
||||||
else
|
|
||||||
LUKS_PASS=$(ask_password "Disk encryption (LUKS) passphrase")
|
LUKS_PASS=$(ask_password "Disk encryption (LUKS) passphrase")
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Final confirmation ────────────────────────────────────────────────────────
|
# ── Final confirmation ────────────────────────────────────────────────────────
|
||||||
# A single gate before anything destructive happens. Summarise the choices so the
|
# A single gate before anything destructive happens. Summarise the choices so the
|
||||||
|
|
@ -305,26 +295,6 @@ else
|
||||||
[[ "$_final_ans" == "YES" ]] || { echo "Aborted."; exit 1; }
|
[[ "$_final_ans" == "YES" ]] || { echo "Aborted."; exit 1; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Wait for the live ISO's keyring initialization before any install. archiso
|
|
||||||
# initializes the pacman keyring asynchronously at boot via pacman-init.service
|
|
||||||
# (master-key generation can take a minute+ in VMs with little entropy), and
|
|
||||||
# this installer autostarts at login — racing that service leaves keys
|
|
||||||
# unpopulated/untrusted, so every package fails with "signature is unknown
|
|
||||||
# trust" / "invalid or corrupted package (PGP signature)". Do NOT run
|
|
||||||
# pacman-key --init ourselves here: doing so concurrently with
|
|
||||||
# pacman-init.service corrupts the half-built keyring. Wait, then refresh
|
|
||||||
# archlinux-keyring so an ISO built weeks ago still trusts current packager keys.
|
|
||||||
if systemctl cat pacman-init.service &>/dev/null; then
|
|
||||||
echo "Waiting for pacman keyring initialization (pacman-init.service)..."
|
|
||||||
while [[ "$(systemctl is-active pacman-init.service 2>/dev/null)" == "activating" ]]; do
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
else
|
|
||||||
# Not on archiso (e.g. re-run from an installed system) — ensure a keyring exists.
|
|
||||||
[[ -d /etc/pacman.d/gnupg ]] || { pacman-key --init; pacman-key --populate archlinux; }
|
|
||||||
fi
|
|
||||||
pacman -Sy --noconfirm archlinux-keyring
|
|
||||||
|
|
||||||
# Required packages — installed into the live environment before partitioning.
|
# Required packages — installed into the live environment before partitioning.
|
||||||
# -d skips full dependency resolution for speed (these are standalone tools).
|
# -d skips full dependency resolution for speed (these are standalone tools).
|
||||||
# systemd-ukify included for Unified Kernel Image support if needed post-install.
|
# systemd-ukify included for Unified Kernel Image support if needed post-install.
|
||||||
|
|
@ -609,13 +579,6 @@ sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"$GRUB_CMDLINE\"|" /etc/def
|
||||||
|
|
||||||
# Install GRUB to the EFI partition; --bootloader-id names the NVRAM/EFI menu entry.
|
# Install GRUB to the EFI partition; --bootloader-id names the NVRAM/EFI menu entry.
|
||||||
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
|
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
|
||||||
# Also install to the UEFI removable-media fallback path (/EFI/BOOT/BOOTX64.EFI).
|
|
||||||
# The --bootloader-id install above only creates an NVRAM boot variable; a machine
|
|
||||||
# whose NVRAM is empty or gets cleared (fresh board, CMOS reset, firmware that drops
|
|
||||||
# stale entries, or a disk cloned/redeployed to different hardware) then has "No
|
|
||||||
# bootable device". The removable fallback is what firmware boots when no NVRAM entry
|
|
||||||
# matches, making the installed disk portable and self-booting regardless of NVRAM.
|
|
||||||
grub-install --target=x86_64-efi --efi-directory=/boot --removable
|
|
||||||
# Generate grub.cfg from /etc/default/grub and discovered kernels/initramfs images.
|
# Generate grub.cfg from /etc/default/grub and discovered kernels/initramfs images.
|
||||||
grub-mkconfig -o /boot/grub/grub.cfg
|
grub-mkconfig -o /boot/grub/grub.cfg
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,7 @@ fi
|
||||||
# ── Clean and create working directories ─────────────────────────────────────
|
# ── Clean and create working directories ─────────────────────────────────────
|
||||||
# Remove any previous build artifacts to ensure a clean, reproducible build.
|
# Remove any previous build artifacts to ensure a clean, reproducible build.
|
||||||
# mkarchiso can behave unexpectedly if the profile or work directory has stale state.
|
# mkarchiso can behave unexpectedly if the profile or work directory has stale state.
|
||||||
# Use sudo: mkarchiso runs as root below and leaves root-owned files in WORK_DIR
|
rm -rf "$WORK_DIR"
|
||||||
# if a prior build was interrupted before its own end-of-script chown; a plain
|
|
||||||
# `rm -rf` would then fail on those files and (under set -e) abort the script
|
|
||||||
# before mkarchiso ever runs.
|
|
||||||
sudo rm -rf "$WORK_DIR"
|
|
||||||
mkdir -p "$WORK_DIR" "$OUT_DIR"
|
mkdir -p "$WORK_DIR" "$OUT_DIR"
|
||||||
|
|
||||||
# ── Assemble the profile from releng + M-Archy overlay ───────────────────────
|
# ── Assemble the profile from releng + M-Archy overlay ───────────────────────
|
||||||
|
|
|
||||||
|
|
@ -156,12 +156,6 @@ enable_service NetworkManager.service
|
||||||
# '|| true' prevents abort if the unit is already disabled or doesn't exist.
|
# '|| true' prevents abort if the unit is already disabled or doesn't exist.
|
||||||
sudo systemctl disable getty@tty1.service || true
|
sudo systemctl disable getty@tty1.service || true
|
||||||
|
|
||||||
# Disable greetd, which core.sh enables by default for every install. This DE
|
|
||||||
# uses ly as its greeter, so leaving greetd enabled means two display managers
|
|
||||||
# both race to claim tty1 — and the stale greetd/tuigreet greeter can win,
|
|
||||||
# showing the old text login instead of ly. Disable it so ly is the sole greeter.
|
|
||||||
disable_service greetd.service
|
|
||||||
|
|
||||||
# ly is the TUI display manager that runs on tty1 and launches Hyprland after
|
# ly is the TUI display manager that runs on tty1 and launches Hyprland after
|
||||||
# the user logs in.
|
# the user logs in.
|
||||||
enable_service ly@tty1.service
|
enable_service ly@tty1.service
|
||||||
|
|
|
||||||
|
|
@ -159,12 +159,6 @@ enable_service NetworkManager.service
|
||||||
# '|| true' prevents abort if the unit is already disabled.
|
# '|| true' prevents abort if the unit is already disabled.
|
||||||
sudo systemctl disable getty@tty1.service || true
|
sudo systemctl disable getty@tty1.service || true
|
||||||
|
|
||||||
# Disable greetd, which core.sh enables by default for every install. hyprlua
|
|
||||||
# uses ly as its greeter, so leaving greetd enabled means two display managers
|
|
||||||
# both race to claim tty1 — and the stale greetd/tuigreet greeter can win,
|
|
||||||
# showing the old text login instead of ly. Disable it so ly is the sole greeter.
|
|
||||||
disable_service greetd.service
|
|
||||||
|
|
||||||
# ly: TUI display manager that presents the login screen on tty1.
|
# ly: TUI display manager that presents the login screen on tty1.
|
||||||
enable_service ly@tty1.service
|
enable_service ly@tty1.service
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
# PKGBUILD — autofs (ansipa self-hosted build)
|
|
||||||
#
|
|
||||||
# WHY THIS EXISTS:
|
|
||||||
# The AUR `autofs` package is a hard dependency of the AUR `freeipa-client`
|
|
||||||
# package (which ansipa needs to enroll Arch hosts into FreeIPA). As of the
|
|
||||||
# autofs 5.2.0 upstream release, the kernel.org mirror pruned the
|
|
||||||
# autofs-5.1.9.tar.xz tarball that the AUR PKGBUILD pins, so the AUR autofs
|
|
||||||
# build fails with a 404 on its source — which in turn makes freeipa-client
|
|
||||||
# (and therefore every Arch FreeIPA enrollment) impossible to install.
|
|
||||||
#
|
|
||||||
# Rather than depend on that fragile, currently-broken tarball URL, this
|
|
||||||
# PKGBUILD builds autofs from the upstream git repository pinned to a fixed
|
|
||||||
# commit on the 5.1.9 maintenance series. That commit already contains the
|
|
||||||
# upstream fix for "incompatible function pointer types in cyrus-sasl module"
|
|
||||||
# (commit b7ff971b) that GCC 14+ requires, so we do not need the separate
|
|
||||||
# downstream compiler patch the AUR fetched from the (also fragile) mirror.
|
|
||||||
#
|
|
||||||
# freeipa-enroll.sh builds and installs this package before invoking the AUR
|
|
||||||
# helper for freeipa-client, so the dependency is already satisfied and the
|
|
||||||
# broken AUR autofs is never touched.
|
|
||||||
#
|
|
||||||
# Based on the AUR autofs PKGBUILD (maintainers: Alexander Jacocks, Hyacinthe
|
|
||||||
# Cartiaux et al.), reworked to build from git.
|
|
||||||
|
|
||||||
pkgname=autofs
|
|
||||||
pkgver=5.1.9
|
|
||||||
pkgrel=99 # high pkgrel so this local build wins over a stale AUR copy
|
|
||||||
pkgdesc='A kernel-based automounter for Linux (ansipa git build — fixes dead AUR tarball)'
|
|
||||||
arch=('x86_64')
|
|
||||||
url='https://git.kernel.org/pub/scm/linux/storage/autofs/autofs.git'
|
|
||||||
license=('GPL-2.0-or-later')
|
|
||||||
depends=('libxml2')
|
|
||||||
makedepends=('git' 'libldap' 'krb5' 'kmod' 'sssd' 'libnsl' 'rpcsvc-proto' 'systemd')
|
|
||||||
optdepends=('krb5: for LDAP support'
|
|
||||||
'sssd: for SSSD integration')
|
|
||||||
backup=('etc/autofs/auto.master'
|
|
||||||
'etc/autofs/auto.misc'
|
|
||||||
'etc/autofs/auto.net'
|
|
||||||
'etc/autofs/auto.smb'
|
|
||||||
'etc/autofs/autofs.conf'
|
|
||||||
'etc/autofs/autofs_ldap_auth.conf'
|
|
||||||
'etc/default/autofs')
|
|
||||||
# Pinned commit on the 5.1.9 maintenance branch (tip as of this writing).
|
|
||||||
# Includes b7ff971b (cyrus-sasl function-pointer fix, needed for GCC 14+).
|
|
||||||
_commit='dec0b32389b670398ef1351193977daa629a6dea'
|
|
||||||
source=("${pkgname}::git+https://git.kernel.org/pub/scm/linux/storage/autofs/autofs.git#commit=${_commit}"
|
|
||||||
'autofs-arch-configuration-path.patch')
|
|
||||||
sha256sums=('SKIP'
|
|
||||||
'9974887b47de70f0b871230da96fa4620562289915b55401383232794578d18c')
|
|
||||||
|
|
||||||
prepare() {
|
|
||||||
cd "${pkgname}"
|
|
||||||
# Relocate config paths to Arch's /etc/autofs layout (matches the AUR package).
|
|
||||||
patch --forward --strip=1 --input=../autofs-arch-configuration-path.patch
|
|
||||||
# configure is committed upstream; refresh its mtime so make does not try to
|
|
||||||
# regenerate it (autofs uses a hand-written build system, not automake, so no
|
|
||||||
# autoreconf is required — a stale-timestamp regen would just fail).
|
|
||||||
touch configure
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
cd "${pkgname}"
|
|
||||||
./configure --prefix=/usr \
|
|
||||||
--sysconfdir=/etc/autofs \
|
|
||||||
--sbindir=/usr/bin \
|
|
||||||
--with-mapdir=/etc/autofs \
|
|
||||||
--with-confdir=/etc/default \
|
|
||||||
--without-hesiod \
|
|
||||||
--enable-ignore-busy \
|
|
||||||
--with-libtirpc \
|
|
||||||
--with-systemd
|
|
||||||
make
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
cd "${pkgname}"
|
|
||||||
make INSTALLROOT="${pkgdir}" install install_samples
|
|
||||||
install -dm755 "${pkgdir}/etc/autofs/auto.master.d"
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
--- a/samples/auto.master
|
|
||||||
+++ b/samples/auto.master
|
|
||||||
@@ -4,7 +4,7 @@
|
|
||||||
# mount-point [map-type[,format]:]map [options]
|
|
||||||
# For details of the format look at auto.master(5).
|
|
||||||
#
|
|
||||||
-/misc /etc/auto.misc
|
|
||||||
+/misc /etc/autofs/auto.misc
|
|
||||||
#
|
|
||||||
# NOTE: mounts done from a hosts map will be mounted with the
|
|
||||||
# "nosuid" and "nodev" options unless the "suid" and "dev"
|
|
||||||
@@ -12,14 +12,14 @@
|
|
||||||
#
|
|
||||||
/net -hosts
|
|
||||||
#
|
|
||||||
-# Include /etc/auto.master.d/*.autofs
|
|
||||||
+# Include /etc/autofs/auto.master.d/*.autofs
|
|
||||||
# To add an extra map using this mechanism you will need to add
|
|
||||||
-# two configuration items - one /etc/auto.master.d/extra.autofs file
|
|
||||||
+# two configuration items - one /etc/autofs/auto.master.d/extra.autofs file
|
|
||||||
# (using the same line format as the auto.master file)
|
|
||||||
# and a separate mount map (e.g. /etc/auto.extra or an auto.extra NIS map)
|
|
||||||
# that is referred to by the extra.autofs file.
|
|
||||||
#
|
|
||||||
-+dir:/etc/auto.master.d
|
|
||||||
++dir:/etc/autofs/auto.master.d
|
|
||||||
#
|
|
||||||
# If you have fedfs set up and the related binaries, either
|
|
||||||
# built as part of autofs or installed from another package,
|
|
||||||
|
|
@ -80,10 +80,6 @@ if [[ "$MODE" == "answerfile" ]]; then
|
||||||
[[ -n "$AF_NTP" ]] && ARGS+=(--ntp-server "$AF_NTP")
|
[[ -n "$AF_NTP" ]] && ARGS+=(--ntp-server "$AF_NTP")
|
||||||
|
|
||||||
if [[ -z "$AF_PASSWORD" ]]; then
|
if [[ -z "$AF_PASSWORD" ]]; then
|
||||||
if [[ "${MARCHY_UNATTENDED:-0}" == "1" || ! -t 0 ]]; then
|
|
||||||
echo "Error: answerfile has no password and no terminal is attached to prompt for one — skipping enrollment." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
printf '[?] Password for %s@%s: ' "${AF_PRINCIPAL:-admin}" "${AF_REALM:-REALM}"
|
printf '[?] Password for %s@%s: ' "${AF_PRINCIPAL:-admin}" "${AF_REALM:-REALM}"
|
||||||
read -rs AF_PASSWORD; echo
|
read -rs AF_PASSWORD; echo
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,6 @@
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Absolute path of this script's directory, so bundled build files (e.g. the
|
|
||||||
# autofs-pkgbuild/ fallback for Arch) resolve regardless of the caller's CWD.
|
|
||||||
SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
|
|
||||||
# ─── Colours ────────────────────────────────────────────────────────────────
|
# ─── Colours ────────────────────────────────────────────────────────────────
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
|
|
@ -144,7 +140,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$OS_ID" in
|
case "$OS_ID" in
|
||||||
fedora)
|
rhel|centos|rocky|almalinux|fedora)
|
||||||
PKG_MANAGER="dnf"
|
PKG_MANAGER="dnf"
|
||||||
IPA_CLIENT_PKG="freeipa-client"
|
IPA_CLIENT_PKG="freeipa-client"
|
||||||
SSSD_PKGS="sssd sssd-ipa sssd-tools"
|
SSSD_PKGS="sssd sssd-ipa sssd-tools"
|
||||||
|
|
@ -153,18 +149,6 @@ case "$OS_ID" in
|
||||||
FIDO2_PKGS="pam-u2f"
|
FIDO2_PKGS="pam-u2f"
|
||||||
FIDO2_TOOLS_PKGS="pamu2fcfg"
|
FIDO2_TOOLS_PKGS="pamu2fcfg"
|
||||||
;;
|
;;
|
||||||
rhel|centos|rocky|almalinux)
|
|
||||||
PKG_MANAGER="dnf"
|
|
||||||
# RHEL 8+ (and derivatives Rocky/Alma/CentOS Stream) renamed the
|
|
||||||
# freeipa-client package to ipa-client — freeipa-client does not
|
|
||||||
# exist in these repos, so `dnf install freeipa-client` fails outright.
|
|
||||||
IPA_CLIENT_PKG="ipa-client"
|
|
||||||
SSSD_PKGS="sssd sssd-ipa sssd-tools"
|
|
||||||
ODDJOB_PKGS="oddjob oddjob-mkhomedir"
|
|
||||||
CHRONY_PKG="chrony"
|
|
||||||
FIDO2_PKGS="pam-u2f"
|
|
||||||
FIDO2_TOOLS_PKGS="pamu2fcfg"
|
|
||||||
;;
|
|
||||||
debian|ubuntu)
|
debian|ubuntu)
|
||||||
PKG_MANAGER="apt-get"
|
PKG_MANAGER="apt-get"
|
||||||
IPA_CLIENT_PKG="freeipa-client"
|
IPA_CLIENT_PKG="freeipa-client"
|
||||||
|
|
@ -177,16 +161,13 @@ case "$OS_ID" in
|
||||||
;;
|
;;
|
||||||
arch)
|
arch)
|
||||||
PKG_MANAGER="pacman"
|
PKG_MANAGER="pacman"
|
||||||
# freeipa-client is AUR-only on Arch (the official repos only carry
|
IPA_CLIENT_PKG="freeipa"
|
||||||
# sssd); it must be installed via an AUR helper, NOT plain pacman —
|
|
||||||
# `pacman -S freeipa-client` fails with "target not found".
|
|
||||||
IPA_CLIENT_PKG="freeipa-client"
|
|
||||||
SSSD_PKGS="sssd"
|
SSSD_PKGS="sssd"
|
||||||
ODDJOB_PKGS="oddjob"
|
ODDJOB_PKGS="oddjob"
|
||||||
CHRONY_PKG="chrony"
|
CHRONY_PKG="chrony"
|
||||||
FIDO2_PKGS="pam-u2f"
|
FIDO2_PKGS="pam-u2f"
|
||||||
FIDO2_TOOLS_PKGS="pamu2fcfg"
|
FIDO2_TOOLS_PKGS="pamu2fcfg"
|
||||||
warn "Arch Linux: ensure an AUR helper (yay/paru) is available for AUR packages"
|
warn "Arch Linux: ensure the AUR helper (yay/paru) is available for AUR packages"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "Unsupported OS: $OS_ID"
|
error "Unsupported OS: $OS_ID"
|
||||||
|
|
@ -274,79 +255,15 @@ fi
|
||||||
# ─── Install packages ─────────────────────────────────────────────────────────
|
# ─── Install packages ─────────────────────────────────────────────────────────
|
||||||
section "Installing packages"
|
section "Installing packages"
|
||||||
|
|
||||||
# aur_install <pkg...> — install AUR packages via yay/paru. AUR helpers refuse
|
# On Arch, freeipa pulls ipa-client; sssd is separate
|
||||||
# to run as root, so drop to the invoking sudo user (makepkg builds as them,
|
|
||||||
# their sudo rights handle the final pacman -U).
|
|
||||||
aur_install() {
|
|
||||||
local helper=""
|
|
||||||
command -v yay &>/dev/null && helper="yay"
|
|
||||||
[[ -z "$helper" ]] && command -v paru &>/dev/null && helper="paru"
|
|
||||||
if [[ -z "$helper" ]]; then
|
|
||||||
error "No AUR helper (yay/paru) found — cannot install: $*"
|
|
||||||
error "Install one first, e.g.: pacman -S --needed base-devel git && <build yay>"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
local run_as="${SUDO_USER:-}"
|
|
||||||
if [[ -n "$run_as" && "$run_as" != "root" ]]; then
|
|
||||||
sudo -u "$run_as" "$helper" -S --noconfirm --needed "$@"
|
|
||||||
else
|
|
||||||
# Running as plain root (no sudo user to drop to) — makepkg forbids root.
|
|
||||||
error "AUR install of '$*' needs a non-root user; re-run via sudo from a regular account."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# build_local_pkg <pkgbuild-dir> — build a bundled PKGBUILD and pacman -U it.
|
|
||||||
# makepkg refuses to run as root, so the build runs as the invoking sudo user in
|
|
||||||
# a writable copy of the dir (the repo copy may be read-only); we then install
|
|
||||||
# the resulting package as root. Used to satisfy freeipa-client's autofs
|
|
||||||
# dependency without the broken AUR autofs (see autofs-pkgbuild/PKGBUILD).
|
|
||||||
build_local_pkg() {
|
|
||||||
local src_dir="$1" run_as="${SUDO_USER:-}"
|
|
||||||
[[ -d "$src_dir" ]] || { error "PKGBUILD dir not found: $src_dir"; return 1; }
|
|
||||||
if [[ -z "$run_as" || "$run_as" == "root" ]]; then
|
|
||||||
error "Local package build needs a non-root user; re-run via sudo from a regular account."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
local build_dir
|
|
||||||
build_dir=$(sudo -u "$run_as" mktemp -d) || return 1
|
|
||||||
cp -r "$src_dir"/. "$build_dir/"
|
|
||||||
chown -R "$run_as": "$build_dir"
|
|
||||||
# Build only (as the user); -s pulls makedepends, -f overwrites a stale build.
|
|
||||||
if ! sudo -u "$run_as" bash -c "cd '$build_dir' && makepkg -sf --noconfirm --needed"; then
|
|
||||||
error "makepkg failed in $build_dir"
|
|
||||||
rm -rf "$build_dir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
# Install every package artifact produced (as root — we already are).
|
|
||||||
pacman -U --noconfirm "$build_dir"/*.pkg.tar.* || { rm -rf "$build_dir"; return 1; }
|
|
||||||
rm -rf "$build_dir"
|
|
||||||
}
|
|
||||||
|
|
||||||
# On Arch, sssd comes from the official repos but freeipa-client is AUR-only
|
|
||||||
if [[ "$OS_ID" == "arch" ]]; then
|
if [[ "$OS_ID" == "arch" ]]; then
|
||||||
# Ensure pacman db is fresh
|
# Ensure pacman db is fresh
|
||||||
pacman -Sy --noconfirm
|
pacman -Sy --noconfirm
|
||||||
# sssd and Kerberos tooling are in the official repos
|
# freeipa is AUR-only; skip if ipa-client-install already present
|
||||||
pkg_install $SSSD_PKGS krb5 cyrus-sasl-gssapi
|
|
||||||
# freeipa-client is AUR-only; skip if ipa-client-install already present
|
|
||||||
if command -v ipa-client-install &>/dev/null; then
|
if command -v ipa-client-install &>/dev/null; then
|
||||||
log "ipa-client-install already present — skipping AUR freeipa-client install"
|
log "ipa-client-install already present — skipping AUR freeipa install"
|
||||||
else
|
else
|
||||||
# freeipa-client (AUR) hard-depends on autofs, but the AUR autofs package
|
pkg_install $IPA_CLIENT_PKG $SSSD_PKGS
|
||||||
# is currently unbuildable: its pinned source tarball (autofs-5.1.9.tar.xz)
|
|
||||||
# was pruned from the kernel.org mirror when 5.2.0 released, so it 404s and
|
|
||||||
# takes freeipa-client — and thus the whole enrollment — down with it.
|
|
||||||
# Build autofs ourselves from upstream git (see autofs-pkgbuild/) and install
|
|
||||||
# it first so the AUR helper sees the dependency already satisfied and never
|
|
||||||
# touches the broken AUR autofs.
|
|
||||||
if ! pacman -Qq autofs &>/dev/null; then
|
|
||||||
log "Building autofs from bundled git PKGBUILD (works around broken AUR autofs)..."
|
|
||||||
build_local_pkg "$SELF_DIR/autofs-pkgbuild" \
|
|
||||||
|| { error "autofs build failed — cannot satisfy freeipa-client dependency"; exit 1; }
|
|
||||||
fi
|
|
||||||
log "Installing $IPA_CLIENT_PKG from the AUR (this builds from source — can take a while)..."
|
|
||||||
aur_install $IPA_CLIENT_PKG || { error "freeipa-client install failed"; exit 1; }
|
|
||||||
fi
|
fi
|
||||||
# oddjob (for mkhomedir) — skip if not available in official repos
|
# oddjob (for mkhomedir) — skip if not available in official repos
|
||||||
if pacman -Si oddjob &>/dev/null 2>&1; then
|
if pacman -Si oddjob &>/dev/null 2>&1; then
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,9 @@ LUKS_KEY_UPLOAD_PASSWORD=ChangeMe_LuksUpload!
|
||||||
# CMK_ADMIN_PASSWORD — web UI password for cmkadmin.
|
# CMK_ADMIN_PASSWORD — web UI password for cmkadmin.
|
||||||
# CMK_SITE_ID — OMD site name (default: cmk). Used in all CheckMK URLs and
|
# CMK_SITE_ID — OMD site name (default: cmk). Used in all CheckMK URLs and
|
||||||
# agent registration. Must match whatever was used on first start.
|
# agent registration. Must match whatever was used on first start.
|
||||||
# CMK_ADVERTISED_URL — URL enrolled CLIENTS use to reach CheckMK; stored in the
|
|
||||||
# dev_mon_base hostgroup description. Must be routable from
|
|
||||||
# the clients' network (the docker HOST address + published
|
|
||||||
# port, e.g. http://mon.corp.example.com:8090) — NOT the
|
|
||||||
# container-internal 172.30.0.12:5000. Leave empty only if
|
|
||||||
# all monitored clients run inside the same docker network.
|
|
||||||
# Web UI: http://localhost:8090/cmk/ after `docker compose up -d`
|
# Web UI: http://localhost:8090/cmk/ after `docker compose up -d`
|
||||||
CMK_ADMIN_PASSWORD=ChangeMe_CMK!
|
CMK_ADMIN_PASSWORD=ChangeMe_CMK!
|
||||||
CMK_SITE_ID=cmk
|
CMK_SITE_ID=cmk
|
||||||
CMK_ADVERTISED_URL=
|
|
||||||
|
|
||||||
# ── Keycloak ──────────────────────────────────────────────────────────────────
|
# ── Keycloak ──────────────────────────────────────────────────────────────────
|
||||||
KC_HOSTNAME=keycloak.corp.example.com
|
KC_HOSTNAME=keycloak.corp.example.com
|
||||||
|
|
|
||||||
|
|
@ -124,13 +124,7 @@ curl -sf \
|
||||||
|
|
||||||
# ── Store CheckMK credentials in IPA host-group descriptions ─────────────────
|
# ── Store CheckMK credentials in IPA host-group descriptions ─────────────────
|
||||||
# Format: cmk://<host>:<port>/<site>:automation:<secret>
|
# Format: cmk://<host>:<port>/<site>:automation:<secret>
|
||||||
# CMK_ADVERTISED_URL is what CLIENTS use to reach CheckMK. It must be a
|
CMK_HOST=$(echo "$CMK_URL" | sed 's|http://||')
|
||||||
# host-routable address (e.g. http://<docker-host>:8090), NOT the container's
|
|
||||||
# internal 172.30.0.x address — clients outside the docker network cannot
|
|
||||||
# reach that, and every dev_mon_* policy would silently fail to register.
|
|
||||||
# Falls back to CMK_URL for docker-network-internal test setups.
|
|
||||||
CMK_CLIENT_URL="${CMK_ADVERTISED_URL:-$CMK_URL}"
|
|
||||||
CMK_HOST=$(echo "$CMK_CLIENT_URL" | sed 's|http://||')
|
|
||||||
CMK_DESC="cmk://${CMK_HOST}/${CMK_SITE}:automation:${CMK_SECRET}"
|
CMK_DESC="cmk://${CMK_HOST}/${CMK_SITE}:automation:${CMK_SECRET}"
|
||||||
|
|
||||||
echo "$IPA_ADMIN_PASS" | kinit "admin@${IPA_REALM}" &>/dev/null || {
|
echo "$IPA_ADMIN_PASS" | kinit "admin@${IPA_REALM}" &>/dev/null || {
|
||||||
|
|
|
||||||
|
|
@ -25,29 +25,14 @@
|
||||||
#
|
#
|
||||||
# On plain cgroup v1 hosts `docker compose up -d` works without run.sh.
|
# On plain cgroup v1 hosts `docker compose up -d` works without run.sh.
|
||||||
|
|
||||||
# Volume names are pinned (name:) so they match what run.sh creates with plain
|
|
||||||
# `docker volume create` on cgroup-v2 hosts. Without this, compose prefixes the
|
|
||||||
# project name (image_cmk-creds, ...) and the freeipa container started by
|
|
||||||
# run.sh mounts a DIFFERENT cmk-creds volume than the compose-managed checkmk
|
|
||||||
# container writes to — the automation secret then never reaches IPA and the
|
|
||||||
# CheckMK integration retries forever.
|
|
||||||
volumes:
|
volumes:
|
||||||
freeipa-data:
|
freeipa-data:
|
||||||
name: freeipa-data
|
|
||||||
keycloak-db:
|
keycloak-db:
|
||||||
name: keycloak-db
|
|
||||||
cmk-data: # CheckMK site data (persistent across restarts)
|
cmk-data: # CheckMK site data (persistent across restarts)
|
||||||
name: cmk-data
|
|
||||||
cmk-creds: # shared: CheckMK writes automation.secret here; FreeIPA reads it
|
cmk-creds: # shared: CheckMK writes automation.secret here; FreeIPA reads it
|
||||||
name: cmk-creds
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
ipa-net:
|
ipa-net:
|
||||||
# Pin the real network name: run.sh (cgroup-v2 hosts) creates/uses a bare
|
|
||||||
# "ipa-net", while compose would otherwise create a project-prefixed
|
|
||||||
# "image_ipa-net" on the same subnet — the second one to run then fails
|
|
||||||
# with "Pool overlaps with other one on this address space".
|
|
||||||
name: ipa-net
|
|
||||||
ipam:
|
ipam:
|
||||||
config:
|
config:
|
||||||
- subnet: 172.30.0.0/24
|
- subnet: 172.30.0.0/24
|
||||||
|
|
@ -80,9 +65,6 @@ services:
|
||||||
IPA_SETUP_KRA: ${IPA_SETUP_KRA:-false}
|
IPA_SETUP_KRA: ${IPA_SETUP_KRA:-false}
|
||||||
SMB_SCAN_PASSWORD: ${SMB_SCAN_PASSWORD:?set SMB_SCAN_PASSWORD in .env}
|
SMB_SCAN_PASSWORD: ${SMB_SCAN_PASSWORD:?set SMB_SCAN_PASSWORD in .env}
|
||||||
CMK_URL: http://172.30.0.12:5000
|
CMK_URL: http://172.30.0.12:5000
|
||||||
# Client-facing CheckMK URL stored in the dev_mon_base description —
|
|
||||||
# must be routable from enrolled clients (e.g. http://<docker-host>:8090).
|
|
||||||
CMK_ADVERTISED_URL: ${CMK_ADVERTISED_URL:-}
|
|
||||||
CMK_SITE_ID: ${CMK_SITE_ID:-cmk}
|
CMK_SITE_ID: ${CMK_SITE_ID:-cmk}
|
||||||
ports:
|
ports:
|
||||||
- "389:389"
|
- "389:389"
|
||||||
|
|
@ -183,11 +165,7 @@ services:
|
||||||
ipa-net:
|
ipa-net:
|
||||||
ipv4_address: 172.30.0.12
|
ipv4_address: 172.30.0.12
|
||||||
healthcheck:
|
healthcheck:
|
||||||
# Probe the login page, not /api/1.0/version: the REST API version
|
test: ["CMD-SHELL", "curl -sf http://localhost:5000/${CMK_SITE_ID:-cmk}/check_mk/api/1.0/version >/dev/null 2>&1"]
|
||||||
# endpoint requires authentication in CheckMK 2.3, so an unauthenticated
|
|
||||||
# curl -f gets 401 and the container stays "unhealthy" forever even
|
|
||||||
# though the site is fully up.
|
|
||||||
test: ["CMD-SHELL", "curl -sf http://localhost:5000/${CMK_SITE_ID:-cmk}/check_mk/login.py -o /dev/null"]
|
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 15s
|
timeout: 15s
|
||||||
retries: 20
|
retries: 20
|
||||||
|
|
@ -210,7 +188,6 @@ services:
|
||||||
KC_HTTP_PORT: 8080
|
KC_HTTP_PORT: 8080
|
||||||
KC_HTTPS_PORT: 8443
|
KC_HTTPS_PORT: 8443
|
||||||
KC_HTTP_ENABLED: "true"
|
KC_HTTP_ENABLED: "true"
|
||||||
KC_HEALTH_ENABLED: "true" # exposes /health/* on management port 9000 (KC 25+)
|
|
||||||
KC_FEATURES: preview
|
KC_FEATURES: preview
|
||||||
KEYCLOAK_ADMIN: ${KC_ADMIN:-admin}
|
KEYCLOAK_ADMIN: ${KC_ADMIN:-admin}
|
||||||
KEYCLOAK_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:?set KC_ADMIN_PASSWORD in .env}
|
KEYCLOAK_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:?set KC_ADMIN_PASSWORD in .env}
|
||||||
|
|
@ -225,11 +202,7 @@ services:
|
||||||
networks:
|
networks:
|
||||||
ipa-net:
|
ipa-net:
|
||||||
healthcheck:
|
healthcheck:
|
||||||
# The official Keycloak image ships neither curl nor wget, and since
|
test: ["CMD-SHELL", "curl -fs http://localhost:8080/health/ready || exit 1"]
|
||||||
# KC 25 the health endpoints live on the management port (9000) and are
|
|
||||||
# only served when KC_HEALTH_ENABLED=true. Use bash's /dev/tcp instead
|
|
||||||
# of curl so the check works inside the stock image.
|
|
||||||
test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000 && echo -e 'GET /health/ready HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && grep -q '\"status\": \"UP\"' <&3"]
|
|
||||||
interval: 20s
|
interval: 20s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 20
|
retries: 20
|
||||||
|
|
|
||||||
|
|
@ -35,23 +35,12 @@ start_freeipa() {
|
||||||
docker compose up --no-start freeipa 2>/dev/null || true
|
docker compose up --no-start freeipa 2>/dev/null || true
|
||||||
NETWORK=$(docker network ls --filter name=ipa-net --format '{{.Name}}' | grep ipa-net | head -1)
|
NETWORK=$(docker network ls --filter name=ipa-net --format '{{.Name}}' | grep ipa-net | head -1)
|
||||||
if [[ -z "$NETWORK" ]]; then
|
if [[ -z "$NETWORK" ]]; then
|
||||||
# Label the network exactly as compose would so a later
|
docker network create --subnet=172.30.0.0/24 ipa-net
|
||||||
# `docker compose up` (checkmk/postgres/keycloak) adopts it instead of
|
|
||||||
# failing with "network exists but was not created by compose".
|
|
||||||
docker network create --subnet=172.30.0.0/24 \
|
|
||||||
--label com.docker.compose.network=ipa-net \
|
|
||||||
--label com.docker.compose.project=image \
|
|
||||||
--label com.docker.compose.version=2 \
|
|
||||||
ipa-net
|
|
||||||
NETWORK=ipa-net
|
NETWORK=ipa-net
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure the data volumes exist (cmk-creds is shared with the checkmk
|
# Ensure the data volume exists
|
||||||
# container: CheckMK writes automation.secret there, the IPA container's
|
|
||||||
# ansipa-checkmk-setup.sh reads it — without this mount the whole
|
|
||||||
# dev_mon_* CheckMK integration silently never activates)
|
|
||||||
docker volume create freeipa-data 2>/dev/null || true
|
docker volume create freeipa-data 2>/dev/null || true
|
||||||
docker volume create cmk-creds 2>/dev/null || true
|
|
||||||
|
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name freeipa \
|
--name freeipa \
|
||||||
|
|
@ -62,7 +51,6 @@ start_freeipa() {
|
||||||
--tmpfs /tmp \
|
--tmpfs /tmp \
|
||||||
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
|
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
|
||||||
-v freeipa-data:/data \
|
-v freeipa-data:/data \
|
||||||
-v cmk-creds:/cmk-creds \
|
|
||||||
--network "$NETWORK" \
|
--network "$NETWORK" \
|
||||||
--ip 172.30.0.10 \
|
--ip 172.30.0.10 \
|
||||||
-e IPA_DOMAIN="${IPA_DOMAIN:?}" \
|
-e IPA_DOMAIN="${IPA_DOMAIN:?}" \
|
||||||
|
|
@ -74,9 +62,6 @@ start_freeipa() {
|
||||||
-e IPA_SETUP_KRA="${IPA_SETUP_KRA:-false}" \
|
-e IPA_SETUP_KRA="${IPA_SETUP_KRA:-false}" \
|
||||||
-e SMB_SCAN_PASSWORD="${SMB_SCAN_PASSWORD:?}" \
|
-e SMB_SCAN_PASSWORD="${SMB_SCAN_PASSWORD:?}" \
|
||||||
-e LUKS_KEY_UPLOAD_PASSWORD="${LUKS_KEY_UPLOAD_PASSWORD:?}" \
|
-e LUKS_KEY_UPLOAD_PASSWORD="${LUKS_KEY_UPLOAD_PASSWORD:?}" \
|
||||||
-e CMK_URL="http://172.30.0.12:5000" \
|
|
||||||
-e CMK_ADVERTISED_URL="${CMK_ADVERTISED_URL:-}" \
|
|
||||||
-e CMK_SITE_ID="${CMK_SITE_ID:-cmk}" \
|
|
||||||
-p 389:389 \
|
-p 389:389 \
|
||||||
-p 636:636 \
|
-p 636:636 \
|
||||||
-p 88:88 \
|
-p 88:88 \
|
||||||
|
|
@ -103,8 +88,8 @@ case "$MODE" in
|
||||||
;;
|
;;
|
||||||
all)
|
all)
|
||||||
start_freeipa
|
start_freeipa
|
||||||
docker compose up -d postgres keycloak checkmk
|
docker compose up -d postgres keycloak
|
||||||
echo "Full stack started (freeipa + postgres + keycloak + checkmk)."
|
echo "Full stack started (freeipa + postgres + keycloak)."
|
||||||
;;
|
;;
|
||||||
"")
|
"")
|
||||||
start_freeipa
|
start_freeipa
|
||||||
|
|
|
||||||
|
|
@ -75,16 +75,6 @@ enable_service() {
|
||||||
|| warn "Could not enable: $* — enable it after first boot."
|
|| warn "Could not enable: $* — enable it after first boot."
|
||||||
}
|
}
|
||||||
|
|
||||||
# disable_service: disable units so they don't start at boot. Best-effort —
|
|
||||||
# a failure (e.g. unit absent) is warned, never fatal. Used when a DE module
|
|
||||||
# needs to turn off a greeter/service that core.sh or another module enabled
|
|
||||||
# (e.g. a ly-based DE disabling the greetd core.sh enables by default) so two
|
|
||||||
# display managers don't both try to claim tty1.
|
|
||||||
disable_service() {
|
|
||||||
sudo systemctl disable "$@" 2>/dev/null \
|
|
||||||
|| warn "Could not disable: $* — disable it after first boot."
|
|
||||||
}
|
|
||||||
|
|
||||||
# start_service: start units only when a system manager is actually running.
|
# start_service: start units only when a system manager is actually running.
|
||||||
# Inside the installer chroot there is none, so we skip — the unit starts on
|
# Inside the installer chroot there is none, so we skip — the unit starts on
|
||||||
# first boot via its enable symlink.
|
# first boot via its enable symlink.
|
||||||
|
|
|
||||||
|
|
@ -77,69 +77,6 @@ fi
|
||||||
# (it will exist after freeipa-client is installed).
|
# (it will exist after freeipa-client is installed).
|
||||||
systemctl enable sssd.service 2>/dev/null || true
|
systemctl enable sssd.service 2>/dev/null || true
|
||||||
|
|
||||||
# ── run_enroll helper ─────────────────────────────────────────────────────────
|
|
||||||
# Runs the enrolment either via the server-generated freeipa-client.sh wrapper
|
|
||||||
# (preferred, because it already has the correct domain/realm baked in) or by
|
|
||||||
# falling back to calling ipa-client-install directly with the same arguments.
|
|
||||||
run_enroll() {
|
|
||||||
local args=("$@")
|
|
||||||
if [[ -x "$CLIENT_SCRIPT" ]]; then
|
|
||||||
# Preferred path: use the pre-generated client script from the server
|
|
||||||
exec "$CLIENT_SCRIPT" "${args[@]}"
|
|
||||||
else
|
|
||||||
# Fall back to ipa-client-install directly
|
|
||||||
local cmd=(ipa-client-install --unattended)
|
|
||||||
local dom="" rlm="" srv="" hst="" pri="admin" pwd="" ntp=""
|
|
||||||
local mkhomedir=true sudo_=true dns=true fido2=false
|
|
||||||
declare -a fido2_users=()
|
|
||||||
|
|
||||||
# Parse our internal argument format and translate to ipa-client-install flags
|
|
||||||
for ((i=0; i<${#args[@]}; i++)); do
|
|
||||||
case "${args[$i]}" in
|
|
||||||
--domain) dom="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--realm) rlm="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--server) srv="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--hostname) hst="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--principal) pri="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--password) pwd="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--ntp-server) ntp="${args[$((i+1))]}"; ((i++)) ;;
|
|
||||||
--no-mkhomedir) mkhomedir=false ;;
|
|
||||||
--no-sudo) sudo_=false ;;
|
|
||||||
--no-dns-update) dns=false ;;
|
|
||||||
--fido2) fido2=true ;;
|
|
||||||
--fido2-user) fido2_users+=("${args[$((i+1))]}"); ((i++)) ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Build the ipa-client-install command from parsed values
|
|
||||||
[[ -n "$dom" ]] && cmd+=(--domain "$dom")
|
|
||||||
[[ -n "$rlm" ]] && cmd+=(--realm "$rlm")
|
|
||||||
[[ -n "$srv" ]] && cmd+=(--server "$srv")
|
|
||||||
[[ -n "$hst" ]] && cmd+=(--hostname "$hst")
|
|
||||||
[[ -n "$ntp" ]] && cmd+=(--ntp-server "$ntp")
|
|
||||||
cmd+=(--principal "$pri" --password "$pwd")
|
|
||||||
$mkhomedir && cmd+=(--mkhomedir) || cmd+=(--no-mkhomedir)
|
|
||||||
$sudo_ && cmd+=(--enable-dns-updates) || true
|
|
||||||
! $dns && cmd+=(--no-dns-update) || true
|
|
||||||
exec "${cmd[@]}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Unattended mode (answerfile-driven install, no TTY): the interactive dialog
|
|
||||||
# TUI below would hang forever with no one to answer it. Auto-enroll from the
|
|
||||||
# default answerfile if the server already provisioned one, otherwise skip
|
|
||||||
# cleanly — packages are installed and the module can be re-run manually later.
|
|
||||||
if [[ "${MARCHY_UNATTENDED:-0}" == "1" || ! -t 0 ]]; then
|
|
||||||
if [[ -f "$DEFAULT_AF" ]]; then
|
|
||||||
echo "[+] Unattended mode — enrolling from $DEFAULT_AF"
|
|
||||||
run_enroll --answerfile "$DEFAULT_AF"
|
|
||||||
else
|
|
||||||
echo "[!] Unattended mode — no answerfile at $DEFAULT_AF, skipping enrollment."
|
|
||||||
echo " Enroll later with: $CLIENT_SCRIPT --answerfile $DEFAULT_AF"
|
|
||||||
fi
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure dialog is available for the TUI; install it on-the-fly if missing.
|
# Ensure dialog is available for the TUI; install it on-the-fly if missing.
|
||||||
command -v dialog &>/dev/null || pacman -S --noconfirm --needed dialog
|
command -v dialog &>/dev/null || pacman -S --noconfirm --needed dialog
|
||||||
|
|
||||||
|
|
@ -203,6 +140,54 @@ CHOICE=$(d --title " FreeIPA Client Enrollment " \
|
||||||
"manual" "Enter enrollment data manually" \
|
"manual" "Enter enrollment data manually" \
|
||||||
"skip" "Skip — enroll later") || CHOICE="skip"
|
"skip" "Skip — enroll later") || CHOICE="skip"
|
||||||
|
|
||||||
|
# ── run_enroll helper ─────────────────────────────────────────────────────────
|
||||||
|
# Runs the enrolment either via the server-generated freeipa-client.sh wrapper
|
||||||
|
# (preferred, because it already has the correct domain/realm baked in) or by
|
||||||
|
# falling back to calling ipa-client-install directly with the same arguments.
|
||||||
|
run_enroll() {
|
||||||
|
local args=("$@")
|
||||||
|
if [[ -x "$CLIENT_SCRIPT" ]]; then
|
||||||
|
# Preferred path: use the pre-generated client script from the server
|
||||||
|
exec "$CLIENT_SCRIPT" "${args[@]}"
|
||||||
|
else
|
||||||
|
# Fall back to ipa-client-install directly
|
||||||
|
local cmd=(ipa-client-install --unattended)
|
||||||
|
local dom="" rlm="" srv="" hst="" pri="admin" pwd="" ntp=""
|
||||||
|
local mkhomedir=true sudo_=true dns=true fido2=false
|
||||||
|
declare -a fido2_users=()
|
||||||
|
|
||||||
|
# Parse our internal argument format and translate to ipa-client-install flags
|
||||||
|
for ((i=0; i<${#args[@]}; i++)); do
|
||||||
|
case "${args[$i]}" in
|
||||||
|
--domain) dom="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--realm) rlm="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--server) srv="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--hostname) hst="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--principal) pri="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--password) pwd="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--ntp-server) ntp="${args[$((i+1))]}"; ((i++)) ;;
|
||||||
|
--no-mkhomedir) mkhomedir=false ;;
|
||||||
|
--no-sudo) sudo_=false ;;
|
||||||
|
--no-dns-update) dns=false ;;
|
||||||
|
--fido2) fido2=true ;;
|
||||||
|
--fido2-user) fido2_users+=("${args[$((i+1))]}"); ((i++)) ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build the ipa-client-install command from parsed values
|
||||||
|
[[ -n "$dom" ]] && cmd+=(--domain "$dom")
|
||||||
|
[[ -n "$rlm" ]] && cmd+=(--realm "$rlm")
|
||||||
|
[[ -n "$srv" ]] && cmd+=(--server "$srv")
|
||||||
|
[[ -n "$hst" ]] && cmd+=(--hostname "$hst")
|
||||||
|
[[ -n "$ntp" ]] && cmd+=(--ntp-server "$ntp")
|
||||||
|
cmd+=(--principal "$pri" --password "$pwd")
|
||||||
|
$mkhomedir && cmd+=(--mkhomedir) || cmd+=(--no-mkhomedir)
|
||||||
|
$sudo_ && cmd+=(--enable-dns-updates) || true
|
||||||
|
! $dns && cmd+=(--no-dns-update) || true
|
||||||
|
exec "${cmd[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ── Answerfile mode ───────────────────────────────────────────────────────────
|
# ── Answerfile mode ───────────────────────────────────────────────────────────
|
||||||
# The answerfile is a JSON file pre-generated by freeipa-server.sh with domain,
|
# The answerfile is a JSON file pre-generated by freeipa-server.sh with domain,
|
||||||
# realm, and server already filled in. The user only needs to add the password.
|
# realm, and server already filled in. The user only needs to add the password.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue