Files
maas-proxmox/scripts/customize-proxmox.sh.in
ilkermanap 40b5d50ec9 License under AGPL-3.0-or-later and publish documentation via GitHub Pages
Parts of this repository are derived from canonical/packer-maas, which Canonical
distributes under the AGPLv3, so its copyleft carries over and a permissive or
plain-GPL licence is not available:

  * maas/curtin_userdata_custom.in is adapted from upstream's
    debian/curtin_userdata_custom_amd64, with several late_commands copied
    verbatim (the PXE-disable call, the target bind mount, the cloud.cfg rewrite
    and the zz-update-grub fix)
  * overlay/curtin/curtin-hooks follows upstream's debian/scripts/curtin-hooks:
    same imports, same load_command_environment -> load_command_config ->
    builtin_curthooks -> cleanup structure, near-identical cleanup(). The
    kernel-disabling and interface-pinning functions are original.

The upstream template itself is not vendored; it is cloned at build time and
pinned by PM_REF.

Adds the full AGPL-3.0 text as LICENSE and SPDX-License-Identifier headers to
every source file, placed after the shebang or the #cloud-config marker so both
keep working. deploy-cluster.sh's --help filters the new header lines out of the
usage text it extracts from its own comment block.

GitHub Pages serves index.md, which includes README.md, so the site cannot drift
from the repository documentation. Nothing but build/ is excluded, which keeps
the README's relative links to LICENSE, scripts/ and maas/examples/ resolving on
the published site.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 21:57:03 +02:00

288 lines
12 KiB
Bash

#!/bin/bash
# Copyright (C) 2026 Ilker Manap
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# customize-proxmox.sh - packer-maas'in debian sablonu icinde, build VM'inde calisir.
#
# Debian cloud image uzerine Proxmox VE kurar ve MAAS ile deploy edilebilecek
# hale getirir. Bu dosya bir sablondur; Makefile @@...@@ yer tutucularini
# doldurur ve sonuna base64 kodlu overlay arsivini ekler.
#
# NOT: Bu script packer tarafindan "expect_disconnect = true" ile calistirilir.
#
set -euo pipefail
PVE_SUITE="@@PVE_SUITE@@"
PVE_REPO="@@PVE_REPO@@"
PVE_REPO_URI="@@PVE_REPO_URI@@"
PVE_KEYRING_URL="@@PVE_KEYRING_URL@@"
PVE_VERSION="@@PVE_VERSION@@"
PVE_EXTRA_PACKAGES="@@PVE_EXTRA_PACKAGES@@"
PACKER_MAAS_REF="@@PM_REF@@"
export DEBIAN_FRONTEND=noninteractive
APT="apt-get -y -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef"
# eatmydata kurulduktan sonra $APT bunun uzerinden calisir; dpkg'nin her paket
# icin yaptigi fsync'ler devre disi kalir. Imaj derlemede guvenli (VM diski
# zaten atilabilir) ve paket kurulumunu belirgin sekilde hizlandirir.
use_eatmydata() {
command -v eatmydata >/dev/null 2>&1 || return 0
APT="eatmydata ${APT}"
log "eatmydata etkin (dpkg fsync'leri devre disi)"
}
log() { echo "==> [pve-image] $*"; }
# ---------------------------------------------------------------------------
# 1. Gomulu overlay arsivini ac
# ---------------------------------------------------------------------------
log "Overlay dosyalari aciliyor"
sed -n '/^__PVE_MAAS_OVERLAY__$/,$p' "$0" | tail -n +2 | base64 -d \
| tar xzf - -C / --no-same-owner --no-same-permissions
chown -R root:root /usr/local/sbin/pve-maas-init /etc/pve-maas \
/etc/systemd/system/pve-maas-init.service /curtin
chmod 0755 /usr/local/sbin/pve-maas-init
chmod 0755 /curtin /curtin/curtin-hooks
chmod 0644 /etc/systemd/system/pve-maas-init.service
chmod 0644 /etc/pve-maas/pve-maas.conf
mkdir -p /etc/pve-maas/conf.d /var/lib/pve-maas
# ---------------------------------------------------------------------------
# 2. Build sirasinda hostname cozulebilir olmali (pve-cluster bunu ister)
# ---------------------------------------------------------------------------
BUILD_HOST="$(hostname -s)"
BUILD_IP="$(ip -4 -o route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1)}' | head -1)"
: "${BUILD_IP:=127.0.1.1}"
log "Build hostname=${BUILD_HOST} ip=${BUILD_IP}"
cp -a /etc/hosts /etc/hosts.pve-image-backup
sed -i "/[[:space:]]${BUILD_HOST}\([[:space:]]\|$\)/d" /etc/hosts
echo "${BUILD_IP} ${BUILD_HOST}.local ${BUILD_HOST}" >> /etc/hosts
hostname -f || echo "UYARI: hostname -f cozulemedi" >&2
# ---------------------------------------------------------------------------
# 3. packer-maas'in kurdugu MAAS uyumlu cloud-init'i koru
#
# packer-maas, Debian'in cloud-init'i MAAS datasource'unu tam desteklemedigi
# icin Ubuntu build'ini kuruyor. full-upgrade bunu geri almasin.
# ---------------------------------------------------------------------------
log "cloud-init paketi hold'a aliniyor"
apt-mark hold cloud-init || true
# apt-cacher-ng gibi bir HTTP onbellegi verilmisse Debian depolarini https'ten
# http'ye cevir - aksi halde onbellek isabet etmez (CONNECT tunelini cache'leyemez).
# Paket imzalari yine dogrulandigi icin guvenlik kaybi yok.
if [ -n "${http_proxy:-}" ]; then
log "APT onbellegi kullaniliyor (${http_proxy}); Debian depolari http'ye cevriliyor"
sed -i 's|https://deb.debian.org|http://deb.debian.org|g; s|https://security.debian.org|http://security.debian.org|g' \
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources /etc/apt/sources.list.d/*.list 2>/dev/null || true
fi
log "eatmydata kuruluyor"
$APT install eatmydata || true
use_eatmydata
# ---------------------------------------------------------------------------
# 4. Proxmox APT deposu
# ---------------------------------------------------------------------------
log "Proxmox anahtarligi indiriliyor: ${PVE_KEYRING_URL}"
curl -fsSL --retry 5 --retry-delay 3 "${PVE_KEYRING_URL}" \
-o /usr/share/keyrings/proxmox-archive-keyring.gpg
chmod 0644 /usr/share/keyrings/proxmox-archive-keyring.gpg
log "APT deposu ekleniyor: ${PVE_REPO_URI} ${PVE_SUITE} ${PVE_REPO}"
cat > /etc/apt/sources.list.d/proxmox.sources <<EOF
Types: deb
URIs: ${PVE_REPO_URI}
Suites: ${PVE_SUITE}
Components: ${PVE_REPO}
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF
# Depo dogru mu, paketler gorunuyor mu?
apt-get update
apt-cache policy proxmox-ve | sed -n '1,6p'
if ! apt-cache show proxmox-ve >/dev/null 2>&1; then
echo "HATA: proxmox-ve paketi bulunamadi. PVE_SUITE=${PVE_SUITE} PVE_REPO=${PVE_REPO} dogru mu?" >&2
exit 1
fi
# ---------------------------------------------------------------------------
# 5. Sistemi guncelle
# ---------------------------------------------------------------------------
log "full-upgrade"
$APT full-upgrade
# ---------------------------------------------------------------------------
# 6. Etkilesimsiz kurulum icin debconf yanitlari
# ---------------------------------------------------------------------------
debconf-set-selections <<EOF
postfix postfix/main_mailer_type select Local only
postfix postfix/mailname string ${BUILD_HOST}.local
samba-common samba-common/dhcp boolean false
EOF
# ---------------------------------------------------------------------------
# 7. Proxmox cekirdegi + proxmox-ve
#
# Resmi rehber cekirdek kurulumundan sonra reboot onerir; bu reboot yalnizca
# ZFS/DKMS gibi calisan cekirdege bagimli islemler icin gereklidir. proxmox-ve
# paketleri kurulum sirasinda calisan cekirdege ihtiyac duymaz, bu yuzden imaj
# derlerken reboot atlaniyor. Dugum zaten ilk acilista PVE cekirdegi ile acilir.
# ---------------------------------------------------------------------------
# initramfs, cekirdek/firmware/dkms tetikleyicileriyle kurulum sirasinda
# defalarca yeniden uretiliyor. Kurulum boyunca devre disi birakip en sonda
# bir kez uretmek birkac dakika kazandiriyor.
log "update-initramfs gecici olarak devre disi"
dpkg-divert --local --rename --add /usr/sbin/update-initramfs >/dev/null
ln -sf /bin/true /usr/sbin/update-initramfs
log "proxmox-default-kernel kuruluyor"
$APT install proxmox-default-kernel
log "proxmox-ve kuruluyor"
$APT install proxmox-ve
if [ -n "${PVE_EXTRA_PACKAGES}" ]; then
log "Ek paketler kuruluyor: ${PVE_EXTRA_PACKAGES}"
# shellcheck disable=SC2086
$APT install ${PVE_EXTRA_PACKAGES}
fi
log "Kurulan surumler:"
dpkg-query -W -f='${Package} ${Version}\n' proxmox-ve pve-manager proxmox-default-kernel ifupdown2 || true
# ---------------------------------------------------------------------------
# 8. Debian cekirdegini ve os-prober'i kaldir
# ---------------------------------------------------------------------------
log "Debian cekirdegi ve os-prober kaldiriliyor"
$APT purge os-prober || true
# Yalnizca Debian'in kendi cekirdeklerini hedefle; Proxmox paketlerine dokunma.
DEB_KERNELS="$(dpkg-query -W -f='${Package}\n' 'linux-image*' 2>/dev/null \
| grep -E '^linux-image' | grep -vE 'pve|proxmox' || true)"
if [ -n "${DEB_KERNELS}" ]; then
log "Kaldirilacak: ${DEB_KERNELS}"
# shellcheck disable=SC2086
$APT purge ${DEB_KERNELS} || true
fi
$APT autoremove --purge || true
log "update-initramfs geri aliniyor ve bir kez calistiriliyor"
rm -f /usr/sbin/update-initramfs
dpkg-divert --local --rename --remove /usr/sbin/update-initramfs >/dev/null
update-initramfs -u -k all
update-grub
# ---------------------------------------------------------------------------
# 9. Abonelik gerektiren depolari devre disi birak (varsa)
# ---------------------------------------------------------------------------
for f in /etc/apt/sources.list.d/*enterprise*; do
[ -e "$f" ] || continue
log "Devre disi birakiliyor: $f"
mv "$f" "$f.disabled"
done
# ---------------------------------------------------------------------------
# 10. Dugum kimligini sifirla
#
# pmxcfs (/etc/pve) dugum adini config.db icinde saklar. Imaj build hostname'i
# ile olusur; MAAS baska bir hostname ile deploy edecegi icin veritabanini
# tamamen siliyoruz. pve-cluster ilk acilista guncel hostname ile yeni bir
# config.db uretir ve ExecStartPost'taki 'pvecm updatecerts' sertifikalari
# yeniden olusturur.
# ---------------------------------------------------------------------------
log "Proxmox dugum kimligi sifirlaniyor"
systemctl stop pve-guests pve-ha-lrm pve-ha-crm pvescheduler pvestatd pveproxy \
pvedaemon pve-firewall pvefw-logger spiceproxy corosync pve-cluster 2>/dev/null || true
sleep 2
umount /etc/pve 2>/dev/null || true
rm -f /var/lib/pve-cluster/config.db /var/lib/pve-cluster/config.db-wal \
/var/lib/pve-cluster/config.db-shm /var/lib/pve-cluster/.pmxcfs.lockfile
rm -rf /etc/corosync/* /var/lib/corosync/*
rm -rf /var/lib/rrdcached/db/*
rm -f /etc/pve/* 2>/dev/null || true
# iSCSI initiator adi dugume ozeldir; ilk acilista yeniden uretilir.
rm -f /etc/iscsi/initiatorname.iscsi
# Kume icin uretilen SSH bilgileri imaja sizmasin.
rm -f /root/.ssh/known_hosts /etc/ssh/ssh_known_hosts
find /root/.ssh -type l -delete 2>/dev/null || true
# ---------------------------------------------------------------------------
# 11. Ilk acilis servisini etkinlestir
# ---------------------------------------------------------------------------
log "pve-maas-init.service etkinlestiriliyor"
systemctl daemon-reload
systemctl enable pve-maas-init.service
# ---------------------------------------------------------------------------
# 12. Temizlik
# ---------------------------------------------------------------------------
# Kalici journald: dugum ilk acilista bir kez yeniden baslayabildigi icin
# (PVE_NET_APPLY=reboot) ucucu journal ile pve-maas-init kayitlari kayboluyor.
# ---------------------------------------------------------------------------
# Ilk acilista agi MAAS'a birak
#
# ifupdown2 kurulumu /etc/network/interfaces dosyasina build VM'inin arayuz
# adini yaziyor (or. "iface ens4 inet manual") ve networking.service etkin
# geliyor. Deploy edilen dugumde MAAS agi netplan/systemd-networkd ile
# yapilandirir; ayni anda ifupdown2 devreye girince gercek arayuzu kapatiyor
# ve dugum daha pve-maas-init calismadan agini kaybediyor.
#
# Cozum: imajda temiz/bos bir interfaces dosyasi birak ve networking.service'i
# devre disi birak. pve-maas-init ag asamasinda vmbr0'i yazip bu servisi
# kendisi etkinlestirir.
# ---------------------------------------------------------------------------
log "networking.service devre disi birakiliyor (ilk acilista ag MAAS'ta)"
cat > /etc/network/interfaces <<'EOF'
# Bu dosya pve-maas-init tarafindan, dugum ilk acilista vmbr0 koprusune
# gecirilirken yeniden yazilir. O ana kadar ag MAAS/cloud-init (netplan)
# tarafindan yonetilir; bu yuzden burada yalnizca loopback tanimlidir.
auto lo
iface lo inet loopback
source /etc/network/interfaces.d/*
EOF
rm -f /etc/network/interfaces.d/* 2>/dev/null || true
# Proxmox, ag degisikliklerini once /etc/network/interfaces.new dosyasina
# yaziyor; pvenetcommit.service acilista bunu interfaces uzerine TASIYOR.
# Build sirasinda olusan bir .new dosyasi imajda kalirsa dugumun ilk
# acilisinda temiz yapilandirmamizi ezer.
rm -f /etc/network/interfaces.new
systemctl disable networking.service 2>/dev/null || true
# Imajin kunyesi - dagitilmis bir dugumde "bu hangi imajdan geldi?" sorusunu
# cevaplar; 'make check-upstream' de bunu okur.
log "Imaj kunyesi yaziliyor: /etc/pve-maas/image-info"
{
echo "build_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "pve_version=@@PVE_VERSION@@"
echo "debian_suite=${PVE_SUITE}"
echo "pve_repo=${PVE_REPO}"
echo "packer_maas_ref=${PACKER_MAAS_REF}"
dpkg-query -W -f='${Package}=${Version}\n' proxmox-ve pve-manager proxmox-default-kernel 2>/dev/null
echo "kernel=$(ls -1 /boot/vmlinuz-*-pve 2>/dev/null | sed 's|.*/vmlinuz-||' | head -1)"
} > /etc/pve-maas/image-info
cat /etc/pve-maas/image-info
log "Kalici journald etkinlestiriliyor"
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal 2>/dev/null || true
log "Temizlik"
mv /etc/hosts.pve-image-backup /etc/hosts
rm -f /etc/postfix/main.cf.proto 2>/dev/null || true
[ -f /etc/postfix/main.cf ] && postconf -e "myhostname = localhost" >/dev/null 2>&1 || true
$APT clean
rm -rf /var/lib/apt/lists/*
find /var/log/journal -mindepth 1 -delete 2>/dev/null || true
rm -rf /var/log/*.gz /var/log/*.1
: > /var/log/wtmp || true
: > /var/log/btmp || true
cloud-init clean --logs || true
log "Imaj hazir: Proxmox VE ${PVE_VERSION} / Debian ${PVE_SUITE}"
exit 0
# Bu satirdan sonrasi Makefile tarafindan eklenen base64 overlay arsividir.