From aa721963b38fb5bf9f182e350bbb586efd29fb17 Mon Sep 17 00:00:00 2001 From: Echo Date: Wed, 20 May 2026 02:06:52 +0000 Subject: [PATCH] docs: add detailed Arch, RPM, Alpine installation instructions - README: comprehensive per-platform install/build/verify/remove instructions - README: prerequisites, post-install notes, Alpine OpenRC differences - BUILD_PACKAGES: add Arch and Alpine build sections with troubleshooting - BUILD_PACKAGES: fix Service Account table (runs as root, not system user) - BUILD_PACKAGES: add Arch/Alpine supported distributions tables --- BUILD_PACKAGES.md | 246 ++++++++++++++++++++++++++++++++++++++++++++-- README.md | 164 +++++++++++++++++++++++++++---- 2 files changed, 384 insertions(+), 26 deletions(-) diff --git a/BUILD_PACKAGES.md b/BUILD_PACKAGES.md index 6ceee95..dbf7141 100644 --- a/BUILD_PACKAGES.md +++ b/BUILD_PACKAGES.md @@ -1,6 +1,6 @@ # Linux Patch API - Package Build Guide -This document provides comprehensive instructions for building production-ready Debian (.deb) and RPM (.rpm) packages for the Linux Patch API. +This document provides comprehensive instructions for building production-ready packages for the Linux Patch API across all supported platforms: Debian/Ubuntu (.deb), RHEL/CentOS/Fedora (.rpm), Arch Linux (.pkg.tar.zst), and Alpine Linux (.apk). ## Prerequisites @@ -173,6 +173,152 @@ rpm -ql linux-patch-api rpm -e linux-patch-api ``` +## Building Arch Package (.pkg.tar.zst) + +### Quick Build + +```bash +cd /path/to/linux_patch_api + +# Build release binary +cargo build --release + +# Build Arch package +chmod +x build-arch.sh +SKIP_CARGO_BUILD=1 ./build-arch.sh + +# Package will be created in releases/ +ls -la releases/*.pkg.tar.zst +``` + +### Detailed Build Process + +```bash +# 1. Install build dependencies (Arch Linux) +sudo pacman -Syu --noconfirm rust cargo systemd git base-devel gcc + +# 2. Build release binary +cargo build --release + +# 3. Run build script +chmod +x build-arch.sh +./build-arch.sh + +# 4. Verify package contents +bsdtar -tf releases/linux-patch-api-*.pkg.tar.zst + +# 5. Verify package info +pacman -Qi releases/linux-patch-api-*.pkg.tar.zst +``` + +### Install Script Hooks + +The Arch package includes an `.install` file (`configs/linux-patch-api.install`) that runs automatically on install: + +- **post_install**: Creates directories, copies example configs, enables systemd service +- **post_upgrade**: Reloads systemd daemon +- **pre_remove**: Stops and disables service +- **post_remove**: Cleans up empty directories + +### Installation Test + +```bash +# Install the package +sudo pacman -U ./releases/linux-patch-api-*.pkg.tar.zst + +# Verify installation +systemctl status linux-patch-api +linux-patch-api --version + +# Check installed files +pacman -Ql linux-patch-api + +# Verify config files exist +ls -la /etc/linux_patch_api/ + +# Remove package +sudo pacman -R linux-patch-api +``` + +**Note:** The build script creates a `builduser` for `makepkg` when running as root (typical in CI environments). The `.install` hook handles directory creation, config copying, and service enablement. + +## Building Alpine Package (.apk) + +### Quick Build + +```bash +cd /path/to/linux_patch_api + +# Build release binary (MUSL target for Alpine) +cargo build --release --target x86_64-unknown-linux-musl + +# Build Alpine package +chmod +x build-alpine.sh +SKIP_CARGO_BUILD=1 ./build-alpine.sh + +# Package will be created in releases/ +ls -la releases/*.apk +``` + +### Detailed Build Process + +```bash +# 1. Install build dependencies (Alpine Linux) +apk add --no-cache alpine-sdk rust cargo openssl openssl-dev elogind-dev musl-dev abuild gcc + +# 2. Add Rust MUSL target +rustup target add x86_64-unknown-linux-musl + +# 3. Build release binary +cargo build --release --target x86_64-unknown-linux-musl + +# 4. Run build script +chmod +x build-alpine.sh +./build-alpine.sh + +# 5. Verify package contents +apk verify releases/*.apk + +# 6. List package contents +tar -tzf releases/*.apk +``` + +### Install Script Hooks + +The Alpine package includes an install script (`configs/linux-patch-api.apk-install`) that runs automatically on install: + +- **pre_install**: Creates directories, sets ownership and permissions +- **post_install**: Copies example configs, adds service to default runlevel +- **pre_deinstall**: Stops and removes service from runlevel +- **post_deinstall**: Cleans up empty directories + +### Installation Test + +```bash +# Install the package +sudo apk add --allow-unstable ./releases/linux-patch-api-*.apk + +# Verify installation +rc-service linux-patch-api status +linux-patch-api --version + +# Check installed files +apk info -L linux-patch-api + +# Verify config files exist +ls -la /etc/linux_patch_api/ + +# Remove package +sudo apk del linux-patch-api +``` + +**Important:** Alpine uses **OpenRC** instead of systemd. Key differences: +- Start service: `rc-service linux-patch-api start` +- Stop service: `rc-service linux-patch-api stop` +- Check status: `rc-service linux-patch-api status` +- Service init script: `/etc/init.d/linux-patch-api` +- The `abuild` tool generates signing keys automatically for CI builds + ## Using the Interactive Installer For manual deployment without package managers: @@ -209,15 +355,17 @@ The installer will: | `/var/lib/linux_patch_api/` | Data directory | 755 | | `/var/log/linux_patch_api/` | Log directory | 755 | -### System User/Group +### Service Account | Property | Value | |----------|-------| -| User | linux-patch-api | -| Group | linux-patch-api | +| User | root | +| Group | root | | Home | /var/lib/linux_patch_api | -| Shell | /usr/sbin/nologin | -| Type | System account | +| Shell | N/A (systemd service) | +| Type | Runs as root (required for package management) | + +**Note:** The service runs as root because package management operations (apt, dnf, apk, pacman) require root privileges. Security is provided by mTLS + IP whitelist, not process isolation. ## Supported Distributions @@ -240,6 +388,19 @@ The installer will: | AlmaLinux | 8, 9 | ✅ Supported | | Rocky Linux | 8, 9 | ✅ Supported | +### Arch Package (.pkg.tar.zst) + +| Distribution | Versions | Status | +|--------------|----------|--------| +| Arch Linux | Rolling | ✅ Supported | +| Manjaro | Rolling | ✅ Supported | + +### Alpine Package (.apk) + +| Distribution | Versions | Status | +|--------------|----------|--------| +| Alpine Linux | 3.18+ | ✅ Supported | + ## Troubleshooting ### Debian Package Issues @@ -276,9 +437,62 @@ cat ~/rpmbuild/BUILDROOT/*/var/log/rpmbuild.log dnf install -y systemd-devel pkgconfig ``` +### Arch Package Issues + +**Error: `makepkg: cannot run as root`** +```bash +# The build script handles this automatically by creating builduser +# If running manually: +useradd -m builduser +su - builduser -c "cd /path/to/repo && makepkg -f --noconfirm" +``` + +**Error: `install script not found`** +```bash +# Ensure linux-patch-api.install is in the same directory as PKGBUILD +ls -la configs/linux-patch-api.install +# The build script copies it automatically +``` + +**Error: `Permission denied` on config files** +```bash +# Verify ownership is root:root +ls -la /etc/linux_patch_api/ +# Fix if needed: +sudo chown -R root:root /etc/linux_patch_api/ +sudo chmod 750 /etc/linux_patch_api /etc/linux_patch_api/certs +``` + +### Alpine Package Issues + +**Error: `abuild: UNTRUSTED signature`** +```bash +# The build script handles key generation automatically +# If running manually: +abuild-keygen -a -n +cp /root/.abuild/*.rsa.pub /etc/apk/keys/ +``` + +**Error: `apk add: ERROR: failed to create directory`** +```bash +# Verify the install script ran correctly +ls -la /etc/linux_patch_api/ +ls -la /var/lib/linux_patch_api/ +# Manually create if needed: +sudo mkdir -p /etc/linux_patch_api/certs /var/lib/linux_patch_api /var/log/linux_patch_api +``` + +**Error: `rc-service: service not found`** +```bash +# Verify the init script exists +ls -la /etc/init.d/linux-patch-api +# Re-add to default runlevel +sudo rc-update add linux-patch-api default +``` + ### Service Issues -**Service fails to start:** +**Service fails to start (systemd):** ```bash # Check service status systemctl status linux-patch-api @@ -293,6 +507,22 @@ linux-patch-api --config /etc/linux_patch_api/config.yaml --check ls -la /etc/linux_patch_api/certs/ ``` +**Service fails to start (OpenRC/Alpine):** +```bash +# Check service status +rc-service linux-patch-api status + +# View logs +cat /var/log/linux_patch_api/linux-patch-api.log +cat /var/log/linux_patch_api/linux-patch-api.err + +# Check configuration +linux-patch-api --config /etc/linux_patch_api/config.yaml --check + +# Verify certificates +ls -la /etc/linux_patch_api/certs/ +``` + ## CI/CD Integration ### GitHub Actions Example @@ -383,7 +613,7 @@ jobs: - Packages are signed with maintainer GPG key for production deployments - All maintainer scripts run with `set -e` for fail-fast behavior - Configuration files are marked as conffiles to preserve user modifications -- System user has minimal privileges (nologin shell, no home directory) +- Service runs as root (required for package management operations) - Directory permissions follow principle of least privilege - TLS certificates should be replaced with CA-signed certs in production diff --git a/README.md b/README.md index 36cde36..d615406 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,13 @@ For detailed enrollment procedures, see [DEPLOYMENT_GUIDE.md - Self-Enrollment D ### Package Installation +All platform packages produce identical installation results: +- Creates `/etc/linux_patch_api/`, `/etc/linux_patch_api/certs/`, `/var/lib/linux_patch_api/`, `/var/log/linux_patch_api/` +- Copies example configs to live configs if not already present +- Enables the service (does not start automatically) +- Sets correct permissions (750 on config dirs, 755 on data/log dirs) +- Ownership: root:root (service runs as root) + #### Debian/Ubuntu (.deb) ```bash @@ -197,52 +204,173 @@ apt-get install -f -y # Verify installation systemctl status linux-patch-api linux-patch-api --version + +# Check installed files +dpkg -L linux-patch-api + +# Remove package (keeping configs) +dpkg -r linux-patch-api + +# Purge package (removing all configs) +dpkg -P linux-patch-api ``` +**Prerequisites:** `systemd`, `libsystemd0` + +**Post-install:** The package automatically copies example configs, enables the service, and prints next steps. Configure `/etc/linux_patch_api/config.yaml` and place TLS certificates in `/etc/linux_patch_api/certs/` before starting. + #### RHEL/CentOS/Fedora (.rpm) ```bash -# Install the package -rpm -ivh linux-patch-api-1.0.0-1.x86_64.rpm +# Install the package (recommended - resolves dependencies automatically) +dnf install -y ./linux-patch-api-1.0.0-1.el9.x86_64.rpm + +# Or with yum +yum install -y ./linux-patch-api-1.0.0-1.el9.x86_64.rpm + +# Or with rpm (does NOT resolve dependencies) +rpm -ivh linux-patch-api-1.0.0-1.el9.x86_64.rpm # Verify installation systemctl status linux-patch-api linux-patch-api --version + +# Check installed files +rpm -ql linux-patch-api + +# Remove package +rpm -e linux-patch-api ``` +**Prerequisites (auto-resolved with dnf/yum):** `systemd`, `libsystemd`, `openssl-libs`, `ca-certificates` + +**Post-install:** The package automatically creates directories, copies example configs, enables the service, and prints next steps. Configure `/etc/linux_patch_api/config.yaml` and place TLS certificates in `/etc/linux_patch_api/certs/` before starting. + +**Note:** Use `dnf install` or `yum install` instead of `rpm -ivh` to automatically resolve dependencies. The `rpm -ivh` command will fail if required packages are not already installed. + +#### Arch Linux (.pkg.tar.zst) + +```bash +# Install the package +sudo pacman -U ./linux-patch-api-1.0.0-1-x86_64.pkg.tar.zst + +# Verify installation +systemctl status linux-patch-api +linux-patch-api --version + +# Check installed files +pacman -Ql linux-patch-api + +# Remove package +sudo pacman -R linux-patch-api +``` + +**Prerequisites:** `systemd` (included by default on Arch) + +**Post-install:** The package automatically creates directories, copies example configs, enables the service, and prints next steps. Configure `/etc/linux_patch_api/config.yaml` and place TLS certificates in `/etc/linux_patch_api/certs/` before starting. + +**Note:** Arch uses systemd by default. The install hook runs `systemctl enable` but does not start the service. You must configure before starting. + +#### Alpine Linux (.apk) + +```bash +# Install the package +sudo apk add --allow-unstable ./linux-patch-api-1.0.0-r0.apk + +# Verify installation +rc-service linux-patch-api status +linux-patch-api --version + +# Check installed files +apk info -L linux-patch-api + +# Remove package +sudo apk del linux-patch-api +``` + +**Prerequisites:** `openrc` (included by default on Alpine) + +**Post-install:** The package automatically creates directories, copies example configs, adds the service to the default runlevel, and prints next steps. Configure `/etc/linux_patch_api/config.yaml` and place TLS certificates in `/etc/linux_patch_api/certs/` before starting. + +**Important differences from systemd-based systems:** +- Alpine uses **OpenRC** instead of systemd. Use `rc-service` commands instead of `systemctl` +- Start service: `rc-service linux-patch-api start` +- Stop service: `rc-service linux-patch-api stop` +- Check status: `rc-service linux-patch-api status` +- The service is added to the `default` runlevel automatically on install +- Service init script: `/etc/init.d/linux-patch-api` + ### Manual Installation For systems without package manager support: ```bash # Run interactive installer (requires root) -./install.sh +sudo ./install.sh ``` The installer will: - Detect operating system -- Create system user and group -- Set up directory structure -- Install binary and configuration files +- Create directory structure (`/etc/linux_patch_api/`, `/var/lib/linux_patch_api/`, `/var/log/linux_patch_api/`) +- Install binary to `/usr/bin/linux-patch-api` +- Install example configs - Configure systemd service +- Set correct permissions ### Building from Source +#### Prerequisites (all platforms) + +- Rust toolchain (stable channel, 1.75+) +- OpenSSL development headers +- systemd development headers +- C compiler (gcc) + +#### Build Debian Package (.deb) + ```bash -# Clone repository -git clone https://gitea.internal/linux-patch-api.git -cd linux-patch-api - -# Build release binary -cargo build --release --target x86_64-unknown-linux-gnu - -# Build Debian package -dpkg-buildpackage -us -uc -b - -# Or build RPM package -rpmbuild -ba linux-patch-api.spec +# On Debian/Ubuntu +apt-get install -y build-essential debhelper pkg-config libsystemd-dev libssl-dev cargo rustc +cargo build --release +sudo dpkg-buildpackage -us -uc -b ``` +#### Build RPM Package (.rpm) + +```bash +# On Fedora/RHEL/CentOS +dnf install -y rpm-build cargo rust gcc openssl-devel systemd-devel pkgconfig +cargo build --release --target x86_64-unknown-linux-gnu +chmod +x build-rpm.sh +./build-rpm.sh +``` + +**Note:** The RPM spec includes `BuildRequires` for native RPM build environments. When building in CI containers (where deps are pre-installed via apt-get), these are informational only. + +#### Build Arch Package (.pkg.tar.zst) + +```bash +# On Arch Linux/Manjaro +pacman -Syu --noconfirm rust cargo systemd git base-devel gcc +cargo build --release +chmod +x build-arch.sh +SKIP_CARGO_BUILD=1 ./build-arch.sh +``` + +**Note:** The build script creates a `builduser` for `makepkg` when running as root (typical in CI). The `.install` hook handles directory creation, config copying, and service enablement. + +#### Build Alpine Package (.apk) + +```bash +# On Alpine Linux 3.18+ +apk add --no-cache alpine-sdk rust cargo openssl openssl-dev elogind-dev musl-dev abuild gcc +cargo build --release --target x86_64-unknown-linux-musl +chmod +x build-alpine.sh +SKIP_CARGO_BUILD=1 ./build-alpine.sh +``` + +**Important:** Alpine requires the `x86_64-unknown-linux-musl` target for static linking. The build script handles `abuild` key generation and runs as a `builduser` when executed as root. + See [BUILD_PACKAGES.md](./BUILD_PACKAGES.md) for detailed build instructions. ---