Compare commits
5 Commits
pve-9.2.11
...
pve-9.2.18
| Author | SHA1 | Date | |
|---|---|---|---|
| e1d2c00a97 | |||
| 85c47eddf8 | |||
| 612887bf6b | |||
| 5865198240 | |||
| 4719d30359 |
@@ -37,6 +37,9 @@ jobs:
|
||||
GITEA_API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
KEEP_RELEASES: '3'
|
||||
# Rebuild even without a Proxmox version change once an image reaches this
|
||||
# age, so Debian base security updates make it into the image.
|
||||
MAX_AGE_DAYS: '30'
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
@@ -58,29 +61,12 @@ jobs:
|
||||
run: |
|
||||
set -eu
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
|
||||
UPSTREAM=$(./scripts/ci/upstream-version.sh)
|
||||
TAG="pve-${UPSTREAM}"
|
||||
echo "upstream pve-manager: ${UPSTREAM}"
|
||||
|
||||
PUBLISHED=$(curl -fsS -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_API}/releases?limit=1" \
|
||||
| python3 -c 'import json,sys; r=json.load(sys.stdin); print(r[0]["tag_name"] if r else "")')
|
||||
echo "latest release: ${PUBLISHED:-<none>}"
|
||||
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${UPSTREAM}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
./scripts/ci/decide-build.sh "$MAX_AGE_DAYS" > "$GITHUB_OUTPUT"
|
||||
if [ "${{ inputs.force }}" = "true" ]; then
|
||||
echo "forced by manual trigger"
|
||||
echo "build=yes" >> "$GITHUB_OUTPUT"
|
||||
elif [ "$PUBLISHED" = "$TAG" ]; then
|
||||
echo "${TAG} is already published — nothing to do"
|
||||
echo "build=no" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "new version — building"
|
||||
echo "build=yes" >> "$GITHUB_OUTPUT"
|
||||
sed -i 's/^build=no$/build=yes/' "$GITHUB_OUTPUT"
|
||||
fi
|
||||
cat "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build
|
||||
if: steps.decide.outputs.build == 'yes'
|
||||
|
||||
44
Makefile
44
Makefile
@@ -31,6 +31,9 @@ PVE_EXTRA_PACKAGES ?= ifupdown2 open-iscsi chrony postfix lvm2 thin-provisioning
|
||||
ethtool bridge-utils ipmitool nvme-cli lsscsi sudo
|
||||
|
||||
# ---------------------------------------------------------------- imaj ayarlari
|
||||
# amd64 | arm64. arm64 is wired up but has never been built or deployed -
|
||||
# see "Verified status" in the README. Building arm64 on an x86_64 host means
|
||||
# TCG emulation with no KVM, which is very slow; prefer a native arm64 builder.
|
||||
ARCH ?= amd64
|
||||
SUBARCH ?= generic
|
||||
BOOT ?= uefi
|
||||
@@ -85,8 +88,21 @@ MAAS_IMAGE_NAME ?= custom/$(IMAGE_NAME)
|
||||
# MAAS snap kurulumu icin: /var/snap/maas/current/preseeds
|
||||
MAAS_PRESEED_DIR ?= /var/snap/maas/current/preseeds
|
||||
|
||||
OVMF_DIR ?= /usr/share/OVMF
|
||||
OVMF_SFX ?= $(shell test -f $(OVMF_DIR)/OVMF_CODE.fd && echo "" || echo "_4M")
|
||||
# UEFI firmware, keyed on the TARGET architecture - an aarch64 guest needs
|
||||
# AAVMF whatever the build host is. (Upstream packer-maas keys this on the host
|
||||
# architecture instead, which only works when host and target match.)
|
||||
ifeq ($(strip $(ARCH)),arm64)
|
||||
FW_DIR ?= /usr/share/AAVMF
|
||||
FW ?= AAVMF
|
||||
else
|
||||
FW_DIR ?= /usr/share/OVMF
|
||||
FW ?= OVMF
|
||||
endif
|
||||
FW_SFX ?= $(shell test -f $(FW_DIR)/$(FW)_CODE.fd && echo "" || echo "_4M")
|
||||
|
||||
# KVM is only usable when the host and the guest share an architecture.
|
||||
# Otherwise QEMU falls back to TCG emulation, which is very slow.
|
||||
HOST_IS_ARM := $(shell test "$$(uname -m)" = aarch64 && echo true || echo false)
|
||||
|
||||
# ---------------------------------------------------------------- hedefler
|
||||
.PHONY: help deps deps-cache check-upstream print-var checkout overlay customize image verify preseed install-preseed upload clean distclean lint
|
||||
@@ -158,6 +174,17 @@ image: checkout $(CUSTOMIZE)
|
||||
sed -i -E 's|^([[:space:]]*disk_size[[:space:]]*=[[:space:]]*).*|\1"$(DISK_SIZE)"|' $(TPL)/debian-cloudimg.pkr.hcl
|
||||
sed -i -E 's|^([[:space:]]*cpus[[:space:]]*=[[:space:]]*).*|\1$(BUILD_CPUS)|' $(TPL)/debian-cloudimg.pkr.hcl
|
||||
sed -i -E 's|^([[:space:]]*memory[[:space:]]*=[[:space:]]*).*|\1$(BUILD_MEM)|' $(TPL)/debian-cloudimg.pkr.hcl
|
||||
@echo "==> Build VM apt ayari yamalaniyor (IPv4 zorlama + timeout)"
|
||||
# Every apt fetch over roughly 15 MB inside the build VM used to stall for
|
||||
# exactly 31 seconds regardless of its size, which is a connection timeout
|
||||
# rather than a bandwidth limit: QEMU's user-mode network offers IPv6 that
|
||||
# does not actually work, so apt's parallel connections black-hole on it and
|
||||
# only fall back to IPv4 when the timeout expires. Forcing IPv4 took the
|
||||
# 28.5 MB upstream fetch from 31s to 3s. bootcmd runs in cloud-init's
|
||||
# init-local stage, before SSH is up, so this is in place for the upstream
|
||||
# provisioners too, not just ours.
|
||||
sed -i "/^bootcmd:/a\\ - echo 'Acquire::ForceIPv4 \"true\"; Acquire::http::Timeout \"20\"; Acquire::Retries \"3\";' > /etc/apt/apt.conf.d/99-build-speed" $(TPL)/user-data-cloudimg
|
||||
@sed -n '/^bootcmd:/,+1p' $(TPL)/user-data-cloudimg
|
||||
ifeq ($(strip $(DEBIAN_IMAGE_CHANNEL)),stable)
|
||||
@echo "==> Kararli Debian cloud image kullanilacak (packer onbellegi isabet eder)"
|
||||
sed -i -E 's|/daily/latest/|/latest/|g; s|-daily\.qcow2|.qcow2|g' $(TPL)/debian-cloudimg.pkr.hcl
|
||||
@@ -165,8 +192,13 @@ ifeq ($(strip $(DEBIAN_IMAGE_CHANNEL)),stable)
|
||||
endif
|
||||
sed -i -E 's|--best --force|-$(GZIP_LEVEL) --force|' $(PM)/scripts/fuse-tar-root
|
||||
@grep -nE 'disk_size|^ cpus|^ memory' $(TPL)/debian-cloudimg.pkr.hcl
|
||||
cp -v $(OVMF_DIR)/OVMF_CODE$(OVMF_SFX).fd $(TPL)/OVMF_CODE.fd
|
||||
cp -v $(OVMF_DIR)/OVMF_VARS$(OVMF_SFX).fd $(TPL)/OVMF_VARS.fd
|
||||
cp -v $(FW_DIR)/$(FW)_CODE$(FW_SFX).fd $(TPL)/OVMF_CODE.fd
|
||||
cp -v $(FW_DIR)/$(FW)_VARS$(FW_SFX).fd $(TPL)/OVMF_VARS.fd
|
||||
ifeq ($(strip $(ARCH)),arm64)
|
||||
# AAVMF images must be padded to 64 MiB for QEMU's arm64 "virt" machine.
|
||||
truncate -s 64m $(TPL)/OVMF_CODE.fd
|
||||
truncate -s 64m $(TPL)/OVMF_VARS.fd
|
||||
endif
|
||||
rm -rf $(TPL)/output-cloudimg $(TPL)/seeds-cloudimg.iso
|
||||
cd $(TPL) && PACKER_LOG=$(PACKER_LOG) packer init .
|
||||
cd $(TPL) && PACKER_LOG=$(PACKER_LOG) packer build \
|
||||
@@ -174,8 +206,8 @@ endif
|
||||
-var debian_version=$(DEBIAN_VERSION) \
|
||||
-var architecture=$(ARCH) \
|
||||
-var boot_mode=$(BOOT) \
|
||||
-var ovmf_suffix=$(OVMF_SFX) \
|
||||
-var host_is_arm=false \
|
||||
-var ovmf_suffix=$(FW_SFX) \
|
||||
-var host_is_arm=$(HOST_IS_ARM) \
|
||||
-var timeout=$(TIMEOUT) \
|
||||
-var customize_script=$(CUSTOMIZE) \
|
||||
-var filename=$(OUTPUT) \
|
||||
|
||||
149
README.md
149
README.md
@@ -14,6 +14,7 @@ variable change away (see [Moving to a new Proxmox release](#moving-to-a-new-pro
|
||||
## Table of contents
|
||||
|
||||
- [What this does](#what-this-does)
|
||||
- [Prebuilt images](#prebuilt-images)
|
||||
- [Why Debian + the Proxmox repository, and not the Proxmox ISO](#why-debian--the-proxmox-repository-and-not-the-proxmox-iso)
|
||||
- [How it works](#how-it-works)
|
||||
- [Requirements](#requirements)
|
||||
@@ -27,6 +28,8 @@ variable change away (see [Moving to a new Proxmox release](#moving-to-a-new-pro
|
||||
- [Four traps this image works around](#four-traps-this-image-works-around)
|
||||
- [Moving to a new Proxmox release](#moving-to-a-new-proxmox-release)
|
||||
- [Build performance](#build-performance)
|
||||
- [arm64](#arm64)
|
||||
- [Release automation](#release-automation)
|
||||
- [Repository layout](#repository-layout)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Verified status](#verified-status)
|
||||
@@ -163,6 +166,33 @@ fails is retried on the next boot rather than leaving the node half-configured.
|
||||
|
||||
---
|
||||
|
||||
## Prebuilt images
|
||||
|
||||
Images are built and published automatically:
|
||||
|
||||
**→ [Download the latest image](https://gitea.mynodes.xyz/ilker/maas-proxmox/releases)**
|
||||
|
||||
Each release carries the image, its SHA-256 checksum, the build's metadata
|
||||
(`image-info.txt`) and `SOURCES.md`, the corresponding-source offer required by the
|
||||
licences of the packages inside it. The builds are **unofficial** and not affiliated
|
||||
with Proxmox Server Solutions GmbH.
|
||||
|
||||
```bash
|
||||
curl -LO https://gitea.mynodes.xyz/ilker/maas-proxmox/releases/download/<tag>/maas-image-pve-<version>-amd64.tar.gz
|
||||
curl -LO https://gitea.mynodes.xyz/ilker/maas-proxmox/releases/download/<tag>/maas-image-pve-<version>-amd64.tar.gz.sha256
|
||||
sha256sum -c maas-image-pve-<version>-amd64.tar.gz.sha256
|
||||
|
||||
maas $PROFILE boot-resources create name='custom/proxmox-ve-9' \
|
||||
title='Proxmox VE 9' architecture='amd64/generic' \
|
||||
filetype='tgz' content@=maas-image-pve-<version>-amd64.tar.gz
|
||||
```
|
||||
|
||||
You still need the curtin preseed on your MAAS region controller — see
|
||||
[Quick start](#quick-start) step 5. Downloading an image skips only steps 1-3.
|
||||
|
||||
Prefer building it yourself if you would rather not trust someone else's binary;
|
||||
that is what the rest of this document is about.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
@@ -233,7 +263,7 @@ All of these are `make` variables — `sudo make image DISK_SIZE=24G`, and so on
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `IMAGE_NAME` | `proxmox-ve-9` | MAAS name (`custom/<name>`) and preseed filename |
|
||||
| `ARCH` / `SUBARCH` | `amd64` / `generic` | Target architecture. *Only amd64 was tested.* |
|
||||
| `ARCH` / `SUBARCH` | `amd64` / `generic` | Target architecture. `arm64` is wired up but **never built or deployed** — see [arm64](#arm64). |
|
||||
| `BOOT` | `uefi` | Boot mode baked into the image. *Only UEFI was tested.* |
|
||||
| `DISK_SIZE` | `16G` | Build VM disk. Upstream's 4G cannot fit Debian + Proxmox |
|
||||
| `BUILD_CPUS` / `BUILD_MEM` | `4` / `4096` | Build VM resources |
|
||||
@@ -246,7 +276,7 @@ All of these are `make` variables — `sudo make image DISK_SIZE=24G`, and so on
|
||||
|---|---|---|
|
||||
| `DEBIAN_IMAGE_CHANNEL` | `stable` | `stable` uses a fixed URL so Packer's cache works; `daily` is upstream's default and changes every day. *Only `stable` was tested.* |
|
||||
| `GZIP_LEVEL` | `6` | Tarball compression. Upstream uses 9 |
|
||||
| `APT_PROXY` | *(empty)* | Local APT cache, e.g. `http://10.0.2.2:3142` — see `make deps-cache`. *Untested.* |
|
||||
| `APT_PROXY` | *(empty)* | Local APT cache, e.g. `http://10.0.2.2:3142` — see `make deps-cache`. *Untested on this image; measured on maas-samba-ad.* |
|
||||
|
||||
### MAAS
|
||||
|
||||
@@ -707,9 +737,17 @@ All of them are on by default:
|
||||
- **`GZIP_LEVEL=6`** — upstream uses `--best` (9). With `pigz` this is noticeably faster
|
||||
for a few percent more size.
|
||||
|
||||
For repeated builds, a local APT cache should remove roughly 700 MB of downloads.
|
||||
*This path is untested and the figure is an estimate from package sizes, not a
|
||||
measurement:*
|
||||
- **Forcing IPv4** — the Makefile patches the build VM's cloud-init seed to write
|
||||
`Acquire::ForceIPv4 "true"` before SSH comes up. Without it, every apt download over
|
||||
roughly 15 MB stalled for *exactly* 31 seconds regardless of its size: QEMU's
|
||||
user-mode network offers IPv6 that does not actually work, so apt's parallel
|
||||
connections black-holed on it and only fell back to IPv4 once the timeout expired.
|
||||
Measured on the sibling [maas-samba-ad](https://github.com/ilkermanap/maas-samba-ad)
|
||||
build, the same 28.5 MB fetch went from 31s (914 kB/s) to 3s (9.2 MB/s). The 31s
|
||||
stall is visible in this project's build logs too, but the fix has not yet been
|
||||
measured here.
|
||||
|
||||
For repeated builds you can also put a local APT cache in front:
|
||||
|
||||
```bash
|
||||
sudo make deps-cache # installs apt-cacher-ng
|
||||
@@ -718,10 +756,94 @@ sudo make image APT_PROXY=http://10.0.2.2:3142
|
||||
|
||||
`10.0.2.2` is the build host as seen from Packer's user-mode network. When a proxy is
|
||||
configured, Debian repositories are rewritten from `https` to `http` so the cache can
|
||||
serve them; package signatures are still verified.
|
||||
serve them — a cache cannot see inside a `CONNECT` tunnel — and package signatures are
|
||||
still verified. Note that Debian 13 keeps the real mirror URLs in
|
||||
`/etc/apt/mirrors/*.list` behind the `mirror+file:` method, so rewriting `sources.list`
|
||||
alone is not enough.
|
||||
|
||||
*Do not expect much from the cache on its own.* On the samba-ad build a fully warm cache
|
||||
turned a 26.2 MB fetch from 2s into 0s and a 17.9 MB fetch from 1s into 0s — about three
|
||||
seconds off a 4m40s build. Almost all of the time this project's builds spend on the
|
||||
network is the ~800 MB pulled from the Proxmox repository, which the cache *would* serve
|
||||
on a repeat build; that has not been measured.
|
||||
|
||||
---
|
||||
|
||||
## arm64
|
||||
|
||||
Proxmox VE 9.2 added **official** arm64 support — same code base, same
|
||||
repositories, same release lifecycle as x86-64, with full support on NVIDIA Grace
|
||||
and Vera platforms and best-effort on other UEFI Armv8-A/Armv9-A hardware. The
|
||||
`pve-no-subscription` repository carries `proxmox-ve`, `pve-manager`,
|
||||
`proxmox-default-kernel` and `pve-qemu-kvm` for arm64.
|
||||
|
||||
This repository is wired for it:
|
||||
|
||||
```bash
|
||||
sudo WITH_ARM64=1 ./scripts/install-deps.sh # adds qemu-system-arm, AAVMF
|
||||
sudo make image ARCH=arm64
|
||||
make preseed ARCH=arm64 # -> ..._arm64_generic_proxmox-ve-9
|
||||
make upload ARCH=arm64
|
||||
```
|
||||
|
||||
The firmware is selected from the **target** architecture (`AAVMF` for arm64,
|
||||
`OVMF` for amd64) and padded to 64 MiB as QEMU's arm64 `virt` machine requires;
|
||||
KVM is used only when the host and target architectures match.
|
||||
|
||||
**This has never been run.** Nothing here has been built for arm64, let alone
|
||||
deployed, and it is listed under [Not verified](#not-verified) for that reason.
|
||||
Two things stand between the code and a usable image:
|
||||
|
||||
- **Build speed.** On an x86_64 builder an arm64 build runs under TCG emulation
|
||||
with no KVM. Expect it to be several times slower than the ~11 minutes an amd64
|
||||
build takes; how much slower has not been measured. The I/O optimisations
|
||||
(`eatmydata`, deferred initramfs) help less when the bottleneck is CPU.
|
||||
- **Somewhere to deploy it.** An arm64 image needs arm64 machines behind MAAS to
|
||||
be worth anything, and none were available to test against.
|
||||
|
||||
If you want arm64 seriously, put a native arm64 builder behind a second runner
|
||||
rather than emulating. That removes the speed problem entirely and lets the same
|
||||
pipeline build both architectures.
|
||||
|
||||
## Release automation
|
||||
|
||||
[`.gitea/workflows/build-image.yml`](.gitea/workflows/build-image.yml) builds the image
|
||||
on a self-hosted runner and publishes it as a release.
|
||||
|
||||
It runs **daily**, but rebuilds only when there is a reason to. Proxmox publishes
|
||||
roughly weekly — the trixie repository currently holds 56 `pve-manager` and 28
|
||||
`proxmox-kernel` versions — so an unconditional daily build would produce about
|
||||
45 GB a month of near-identical artifacts. A check that finds nothing costs about
|
||||
30 seconds.
|
||||
|
||||
A rebuild is triggered when any of these holds:
|
||||
|
||||
| Trigger | Why |
|
||||
|---|---|
|
||||
| `pve-manager` differs from the published image | The obvious one |
|
||||
| `proxmox-default-kernel` differs | Kernel security fixes do not bump `pve-manager`, and those matter most |
|
||||
| The newest release is older than `MAX_AGE_DAYS` (30) | Debian base security updates bump neither of the above; without a floor an image could sit unchanged for months |
|
||||
| Manual dispatch with `force` | Escape hatch |
|
||||
|
||||
The comparison reads `image-info.txt` from the last release rather than guessing from
|
||||
tag names, so it reflects what is actually inside the published image.
|
||||
[`scripts/ci/decide-build.sh`](scripts/ci/decide-build.sh) can be run by hand to see the
|
||||
decision without triggering anything.
|
||||
|
||||
Releases are tagged `pve-<version>-<date>` and pruned to the newest
|
||||
`KEEP_RELEASES` (3) — at ~1.5 GB each, unbounded retention fills the server.
|
||||
|
||||
### Runner
|
||||
|
||||
The runner is registered in **host mode**: steps run directly on the build machine as
|
||||
root, because the build needs `/dev/kvm`, `qemu-nbd`, FUSE and root privileges, all of
|
||||
which a container would have to be granted anyway. The consequence is worth stating
|
||||
plainly: anything able to dispatch a workflow in this repository gets root on the build
|
||||
machine. Do not attach this runner to a repository that accepts outside contributions.
|
||||
|
||||
Checkout is a plain `git clone`, not `actions/checkout` — the latter is a JavaScript
|
||||
action and a host-mode runner has no Node.js runtime.
|
||||
|
||||
## Repository layout
|
||||
|
||||
```
|
||||
@@ -730,6 +852,8 @@ scripts/install-deps.sh build host dependencies
|
||||
scripts/customize-proxmox.sh.in template for the script that runs inside the build VM
|
||||
scripts/deploy-cluster.sh deploy a whole cluster through MAAS
|
||||
scripts/verify-image.sh check a built image's contents
|
||||
scripts/ci/ release pipeline helpers (decision, artifacts, publish, prune)
|
||||
.gitea/workflows/ Gitea Actions pipeline
|
||||
overlay/ files baked into the image
|
||||
usr/local/sbin/pve-maas-init first-boot state machine
|
||||
etc/pve-maas/pve-maas.conf defaults, with every option documented
|
||||
@@ -861,12 +985,17 @@ plaintext `PVE_ROOT_PASSWORD`, `PVE_ENABLED=false`, `PVE_FQDN`, and every
|
||||
**Build variants**
|
||||
|
||||
- `pve-enterprise` and `pve-test` repositories
|
||||
- arm64
|
||||
- **arm64** — the Makefile and scripts handle it (firmware selection, MAAS
|
||||
architecture, the Debian-kernel check), but no arm64 image has been built and
|
||||
none deployed. See [arm64](#arm64).
|
||||
- BIOS boot (`BOOT=bios`)
|
||||
- `DEBIAN_IMAGE_CHANNEL=daily`
|
||||
- `APT_PROXY` and `make deps-cache`. The ~700 MB figure quoted under
|
||||
[Build performance](#build-performance) is an estimate from download sizes, not a
|
||||
measurement.
|
||||
- `APT_PROXY` and `make deps-cache` *for this image*. The cache was measured end to end
|
||||
on the sibling maas-samba-ad build, where it saved about three seconds; this project
|
||||
pulls far more from the Proxmox repository, and that case has not been measured.
|
||||
- The `Acquire::ForceIPv4` seed patch *for this image*. It was measured on maas-samba-ad
|
||||
(31s to 3s on the same 28.5 MB fetch); the same 31s stall appears in this project's
|
||||
logs, but no build has been run here since the patch was added.
|
||||
- A non-default `IMAGE_NAME`
|
||||
|
||||
**Make targets** — `make upload` (the image was uploaded with the equivalent `maas`
|
||||
|
||||
96
scripts/ci/decide-build.sh
Executable file
96
scripts/ci/decide-build.sh
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2026 Ilker Manap
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#
|
||||
# Decides whether a rebuild is worth doing, and prints the decision as
|
||||
# key=value lines suitable for $GITHUB_OUTPUT.
|
||||
#
|
||||
# decide-build.sh [max-age-days] (default 30)
|
||||
#
|
||||
# A rebuild happens when any of these is true:
|
||||
#
|
||||
# 1. pve-manager in the repository differs from the published image
|
||||
# 2. proxmox-default-kernel differs — kernel security fixes do not bump
|
||||
# pve-manager, and those are the ones that matter most
|
||||
# 3. the newest release is older than max-age-days — Debian base security
|
||||
# updates bump neither of the above, so without a floor an image could
|
||||
# sit unchanged for months
|
||||
#
|
||||
# Requires GITEA_API and GITEA_TOKEN in the environment.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
MAX_AGE_DAYS="${1:-30}"
|
||||
: "${GITEA_API:?GITEA_API required}"
|
||||
: "${GITEA_TOKEN:?GITEA_TOKEN required}"
|
||||
|
||||
SUITE=$(make -s print-var VAR=DEBIAN_SERIES)
|
||||
COMP=$(make -s print-var VAR=PVE_REPO)
|
||||
URI=$(make -s print-var VAR=PVE_REPO_URI)
|
||||
ARCH=$(make -s print-var VAR=ARCH)
|
||||
|
||||
# Newest version of each package we care about, in one pass over the index.
|
||||
PKGS=$(curl -fsS "${URI}/dists/${SUITE}/${COMP}/binary-${ARCH}/Packages.gz" | gunzip)
|
||||
newest() {
|
||||
printf '%s\n' "$PKGS" \
|
||||
| awk -v want="$1" '$1=="Package:" && $2==want {p=1; next} p && $1=="Version:" {print $2; p=0}' \
|
||||
| sort -V | tail -1
|
||||
}
|
||||
UP_PVE=$(newest pve-manager)
|
||||
UP_KERNEL=$(newest proxmox-default-kernel)
|
||||
[ -n "$UP_PVE" ] || { echo "pve-manager not found in ${URI} ${SUITE}/${COMP}" >&2; exit 1; }
|
||||
[ -n "$UP_KERNEL" ] || { echo "proxmox-default-kernel not found" >&2; exit 1; }
|
||||
|
||||
echo "upstream: pve-manager=${UP_PVE} proxmox-default-kernel=${UP_KERNEL}" >&2
|
||||
|
||||
# What the newest published release actually contains. image-info.txt is a few
|
||||
# hundred bytes and is published with every release, so this needs no guessing
|
||||
# from tag names.
|
||||
LATEST=$(curl -fsS -H "Authorization: token ${GITEA_TOKEN}" "${GITEA_API}/releases?limit=1")
|
||||
INFO_URL=$(printf '%s' "$LATEST" | python3 -c '
|
||||
import json, sys
|
||||
r = json.load(sys.stdin)
|
||||
if r:
|
||||
for a in r[0].get("assets", []):
|
||||
if a["name"] == "image-info.txt":
|
||||
print(a["browser_download_url"]); break
|
||||
')
|
||||
CREATED=$(printf '%s' "$LATEST" | python3 -c '
|
||||
import json, sys
|
||||
r = json.load(sys.stdin); print(r[0]["created_at"] if r else "")')
|
||||
|
||||
PREV_PVE="" PREV_KERNEL=""
|
||||
if [ -n "$INFO_URL" ]; then
|
||||
INFO=$(curl -fsSL "$INFO_URL" || true)
|
||||
PREV_PVE=$(printf '%s' "$INFO" | awk -F= '$1=="pve-manager"{print $2}')
|
||||
PREV_KERNEL=$(printf '%s' "$INFO" | awk -F= '$1=="proxmox-default-kernel"{print $2}')
|
||||
fi
|
||||
echo "published: pve-manager=${PREV_PVE:-<none>} proxmox-default-kernel=${PREV_KERNEL:-<none>}" >&2
|
||||
|
||||
AGE_DAYS=99999
|
||||
if [ -n "$CREATED" ]; then
|
||||
AGE_DAYS=$(CREATED="$CREATED" python3 -c '
|
||||
import datetime, os
|
||||
c = datetime.datetime.fromisoformat(os.environ["CREATED"].replace("Z", "+00:00"))
|
||||
print((datetime.datetime.now(datetime.timezone.utc) - c).days)')
|
||||
echo "newest release is ${AGE_DAYS} day(s) old" >&2
|
||||
fi
|
||||
|
||||
BUILD=no
|
||||
REASON="up to date"
|
||||
if [ -z "$PREV_PVE" ]; then
|
||||
BUILD=yes; REASON="no published image yet"
|
||||
elif [ "$UP_PVE" != "$PREV_PVE" ]; then
|
||||
BUILD=yes; REASON="pve-manager ${PREV_PVE} -> ${UP_PVE}"
|
||||
elif [ "$UP_KERNEL" != "$PREV_KERNEL" ]; then
|
||||
BUILD=yes; REASON="kernel ${PREV_KERNEL} -> ${UP_KERNEL}"
|
||||
elif [ "$AGE_DAYS" -ge "$MAX_AGE_DAYS" ]; then
|
||||
BUILD=yes; REASON="image is ${AGE_DAYS} days old (limit ${MAX_AGE_DAYS}) — picking up Debian updates"
|
||||
fi
|
||||
echo "decision: ${BUILD} (${REASON})" >&2
|
||||
|
||||
printf 'build=%s\n' "$BUILD"
|
||||
printf 'tag=%s\n' "pve-${UP_PVE}-$(date -u +%Y%m%d)"
|
||||
printf 'version=%s\n' "$UP_PVE"
|
||||
printf 'kernel=%s\n' "$UP_KERNEL"
|
||||
printf 'reason=%s\n' "$REASON"
|
||||
@@ -13,6 +13,11 @@ set -euo pipefail
|
||||
TAG="${1:?tag required}"
|
||||
VERSION="${2:?version required}"
|
||||
DIST="${3:?dist directory required}"
|
||||
|
||||
# DIST cagiranin dizinine goreli olabilir; repo kokune gecmeden once mutlaklastir.
|
||||
DIST="$(cd "$DIST" && pwd)"
|
||||
# make degiskenlerini okuyabilmek icin depo koku gerekiyor.
|
||||
cd "$(dirname "$0")/../.."
|
||||
: "${GITEA_API:?GITEA_API required}"
|
||||
: "${GITEA_TOKEN:?GITEA_TOKEN required}"
|
||||
|
||||
@@ -20,6 +25,9 @@ REPO_URL="${GITHUB_SERVER_URL:-}/${GITHUB_REPOSITORY:-}"
|
||||
RUN="${GITHUB_RUN_NUMBER:-manual}"
|
||||
SHA="${GITHUB_SHA:-}"
|
||||
IMAGE=$(basename "$(ls "$DIST"/maas-image-*.tar.gz)")
|
||||
MAAS_ARCH=$(make -s print-var VAR=MAAS_ARCH)
|
||||
PVE_MAJOR=$(make -s print-var VAR=PVE_VERSION)
|
||||
IMAGE_NAME=$(make -s print-var VAR=IMAGE_NAME)
|
||||
|
||||
BODY=$(cat <<BODYEOF
|
||||
Unofficial build of a MAAS-deployable Proxmox VE image.
|
||||
@@ -32,8 +40,8 @@ Unofficial build of a MAAS-deployable Proxmox VE image.
|
||||
Upload to MAAS:
|
||||
|
||||
\`\`\`bash
|
||||
maas \$PROFILE boot-resources create name='custom/proxmox-ve-9' \\
|
||||
title='Proxmox VE 9' architecture='amd64/generic' \\
|
||||
maas \$PROFILE boot-resources create name='custom/${IMAGE_NAME}' \\
|
||||
title='Proxmox VE ${PVE_MAJOR}' architecture='${MAAS_ARCH}' \\
|
||||
filetype='tgz' content@=${IMAGE}
|
||||
\`\`\`
|
||||
|
||||
@@ -45,6 +53,15 @@ the GPL/AGPL licences of the packages inside the image.
|
||||
BODYEOF
|
||||
)
|
||||
|
||||
# A forced rebuild on the same day, of the same upstream version, produces the
|
||||
# tag that is already published and the API answers 409. Disambiguate with the
|
||||
# run number rather than overwriting a release someone may already have used.
|
||||
if curl -fsS -o /dev/null -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${GITEA_API}/releases/tags/${TAG}" 2>/dev/null; then
|
||||
TAG="${TAG}-r${RUN}"
|
||||
echo "tag already exists; publishing as ${TAG} instead"
|
||||
fi
|
||||
|
||||
PAYLOAD=$(TAG="$TAG" VERSION="$VERSION" BODY="$BODY" SHA="$SHA" python3 -c '
|
||||
import json, os
|
||||
print(json.dumps({
|
||||
|
||||
@@ -74,8 +74,11 @@ apt-mark hold cloud-init || true
|
||||
# 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
|
||||
# Debian 13 keeps the actual mirror URLs in /etc/apt/mirrors/*.list, reached
|
||||
# through the "mirror+file:" method, so rewriting sources.list alone misses them.
|
||||
sed -i 's|https://|http://|g' \
|
||||
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources \
|
||||
/etc/apt/sources.list.d/*.list /etc/apt/mirrors/*.list 2>/dev/null || true
|
||||
fi
|
||||
|
||||
log "eatmydata kuruluyor"
|
||||
|
||||
@@ -27,6 +27,14 @@ apt-get install -y --no-install-recommends \
|
||||
qemu-system-x86 qemu-utils ovmf cloud-image-utils \
|
||||
libnbd-bin nbdkit fuse2fs cpu-checker
|
||||
|
||||
# arm64 hedefi icin ek paketler. Varsayilan olarak kurulmaz: x86_64 host'ta
|
||||
# arm64 derlemek TCG emulasyonu demektir (KVM yok) ve cok yavastir. Bu yol
|
||||
# hic denenmedi - README'deki "Verified status" bolumune bakin.
|
||||
if [ "${WITH_ARM64:-0}" = "1" ]; then
|
||||
echo "==> arm64 hedefi icin ek paketler (WITH_ARM64=1)"
|
||||
apt-get install -y --no-install-recommends qemu-system-arm qemu-efi-aarch64
|
||||
fi
|
||||
|
||||
echo "==> HashiCorp APT deposu ekleniyor (packer)"
|
||||
install -d -m 0755 /etc/apt/keyrings
|
||||
curl -fsSL https://apt.releases.hashicorp.com/gpg \
|
||||
|
||||
@@ -55,7 +55,11 @@ check "iSCSI initiator adi yok (dugumde uretilir)" '! present "etc/iscsi/initia
|
||||
check "SSH host anahtarlari yok" '! grep -qE "^\./etc/ssh/ssh_host_.*_key$" "$TMP/list"'
|
||||
check "networking.service etkin DEGIL" '! present "etc/systemd/system/multi-user.target.wants/networking.service"'
|
||||
check "interfaces.new yok (pvenetcommit ezmesin)" '! present "etc/network/interfaces.new"'
|
||||
check "Debian cekirdegi yok" '! grep -qE "^\./boot/vmlinuz-.*[^e]-(cloud-)?amd64$" "$TMP/list"'
|
||||
# Mimariden bagimsiz: /boot altinda -pve ile bitmeyen hicbir cekirdek olmamali.
|
||||
# Debian'inki amd64'te *-amd64, arm64'te *-arm64 diye adlandirilir; Proxmox'unki
|
||||
# her zaman -pve ile biter. Hic cekirdek yoksa da gecer - PVE cekirdeginin
|
||||
# varligini asagidaki ayri kontrol dogruluyor.
|
||||
check "Debian cekirdegi yok" '! grep -E "^\./boot/vmlinuz-" "$TMP/list" | grep -qv -- "-pve$"'
|
||||
|
||||
echo
|
||||
echo "==> Proxmox cekirdegi"
|
||||
|
||||
Reference in New Issue
Block a user