feat: Add .deb packaging for Ubuntu 24.04 release
- debian/control: Package metadata with dependencies - debian/postinst: Service user, dirs, JWT key gen, config, cron setup - debian/prerm: Graceful service stop before upgrade - debian/postrm: Purge cleanup (user, data, config, cron) - debian/changelog: 1.0.0-1 initial release - debian/install: File manifest - scripts/build-package.sh: Full build pipeline (cargo release, frontend, dpkg-deb) - .gitignore: Exclude *.deb and package-build/
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -23,3 +23,7 @@ venv/**
|
|||||||
# Frontend dependencies
|
# Frontend dependencies
|
||||||
frontend/node_modules
|
frontend/node_modules
|
||||||
frontend/dist
|
frontend/dist
|
||||||
|
|
||||||
|
# Package build artifacts
|
||||||
|
*.deb
|
||||||
|
package-build/
|
||||||
|
|||||||
8
debian/changelog
vendored
Normal file
8
debian/changelog
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
linux-patch-manager (1.0.0-1) noble; urgency=medium
|
||||||
|
|
||||||
|
* Initial release of Linux Patch Manager
|
||||||
|
* Full M1-M12 feature set implemented
|
||||||
|
* MFA, RBAC, mTLS, CA, reporting, audit integrity
|
||||||
|
* HIPAA/PCI-DSS compliance mapping documented
|
||||||
|
|
||||||
|
-- Echo <echo@moon-dragon.us> Thu, 24 Apr 2026 00:00:00 +0000
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
10
|
||||||
26
debian/control
vendored
Normal file
26
debian/control
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Package: linux-patch-manager
|
||||||
|
Version: 1.0.0-1
|
||||||
|
Architecture: amd64
|
||||||
|
Maintainer: Moon Dragon <echo@moon-dragon.us>
|
||||||
|
Installed-Size: 45000
|
||||||
|
Depends: postgresql-16, libssl3, libc6 (>= 2.39)
|
||||||
|
Recommends: postgresql-client-16
|
||||||
|
Suggests: gpg
|
||||||
|
Section: admin
|
||||||
|
Priority: optional
|
||||||
|
Description: Enterprise Linux Patch Management System
|
||||||
|
Linux Patch Manager is a secure, web-based management interface for
|
||||||
|
controlling patching and updates on Linux servers and workstations.
|
||||||
|
.
|
||||||
|
Features include:
|
||||||
|
- Multi-factor authentication (TOTP + WebAuthn)
|
||||||
|
- Role-based access control (Admin/Operator)
|
||||||
|
- Mutual TLS agent communication
|
||||||
|
- Internal Certificate Authority
|
||||||
|
- Automated patch deployment with rollback
|
||||||
|
- Maintenance window scheduling
|
||||||
|
- Real-time WebSocket job monitoring
|
||||||
|
- CSV/PDF compliance reporting
|
||||||
|
- Audit logging with hash-chain integrity
|
||||||
|
- Email notifications
|
||||||
|
- Azure SSO (OAuth2/OIDC with PKCE)
|
||||||
9
debian/install
vendored
Normal file
9
debian/install
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
usr/local/bin/pm-web
|
||||||
|
usr/local/bin/pm-worker
|
||||||
|
usr/local/bin/backup.sh
|
||||||
|
usr/share/patch-manager/frontend/*
|
||||||
|
usr/share/patch-manager/config.example.toml
|
||||||
|
usr/share/patch-manager/migrations/*
|
||||||
|
lib/systemd/system/patch-manager-web.service
|
||||||
|
lib/systemd/system/patch-manager-worker.service
|
||||||
|
lib/systemd/system/patch-manager.target
|
||||||
80
debian/postinst
vendored
Normal file
80
debian/postinst
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Linux Patch Manager — Post-install script
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
configure)
|
||||||
|
# Create service user if not exists
|
||||||
|
if ! id patch-manager &>/dev/null; then
|
||||||
|
useradd --system --no-create-home --shell /usr/sbin/nologin \
|
||||||
|
--comment "Linux Patch Manager service account" patch-manager
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create required directories
|
||||||
|
mkdir -p /etc/patch-manager/ca /etc/patch-manager/certs \
|
||||||
|
/etc/patch-manager/jwt /etc/patch-manager/tls \
|
||||||
|
/var/log/patch-manager /opt/patch-manager \
|
||||||
|
/var/backups/patch-manager
|
||||||
|
|
||||||
|
chown -R patch-manager:patch-manager \
|
||||||
|
/etc/patch-manager /var/log/patch-manager \
|
||||||
|
/opt/patch-manager /usr/share/patch-manager/frontend
|
||||||
|
|
||||||
|
chmod 750 /etc/patch-manager/ca /etc/patch-manager/jwt
|
||||||
|
chmod 700 /var/backups/patch-manager
|
||||||
|
|
||||||
|
# Generate JWT signing key if not present
|
||||||
|
if [[ ! -f /etc/patch-manager/jwt/signing.pem ]]; then
|
||||||
|
openssl genpkey -algorithm ed25519 -out /etc/patch-manager/jwt/signing.pem 2>/dev/null
|
||||||
|
openssl pkey -in /etc/patch-manager/jwt/signing.pem -pubout -out /etc/patch-manager/jwt/verify.pem 2>/dev/null
|
||||||
|
chown patch-manager:patch-manager /etc/patch-manager/jwt/signing.pem /etc/patch-manager/jwt/verify.pem
|
||||||
|
chmod 600 /etc/patch-manager/jwt/signing.pem
|
||||||
|
chmod 644 /etc/patch-manager/jwt/verify.pem
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Write default config if not present
|
||||||
|
if [[ ! -f /etc/patch-manager/config.toml ]]; then
|
||||||
|
cp /usr/share/patch-manager/config.example.toml /etc/patch-manager/config.toml
|
||||||
|
chown patch-manager:patch-manager /etc/patch-manager/config.toml
|
||||||
|
chmod 640 /etc/patch-manager/config.toml
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install backup cron if not present
|
||||||
|
if ! crontab -l 2>/dev/null | grep -qF "backup.sh"; then
|
||||||
|
(crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/backup.sh >> /var/log/patch-manager/backup.log 2>&1") | crontab -
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Linux Patch Manager installed successfully!"
|
||||||
|
echo "==========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Install and configure PostgreSQL:"
|
||||||
|
echo " apt install postgresql-16"
|
||||||
|
echo " 2. Create the database:"
|
||||||
|
echo " sudo -u postgres createdb -O patch_manager patch_manager"
|
||||||
|
echo " 3. Edit /etc/patch-manager/config.toml with your database URL"
|
||||||
|
echo " 4. Enable and start services:"
|
||||||
|
echo " systemctl enable --now patch-manager.target"
|
||||||
|
echo " 5. Access the web UI at https://localhost"
|
||||||
|
echo " Default admin credentials are set via the seed migration."
|
||||||
|
echo ""
|
||||||
|
echo "IMPORTANT: Change the default admin password immediately after first login!"
|
||||||
|
echo ""
|
||||||
|
;;
|
||||||
|
|
||||||
|
abort-upgrade|abort-remove|abort-deconfigure)
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "postinst called with unknown argument \`$1'" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
36
debian/postrm
vendored
Normal file
36
debian/postrm
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
purge)
|
||||||
|
# Remove service user (only if purge)
|
||||||
|
if id patch-manager &>/dev/null; then
|
||||||
|
userdel patch-manager 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove runtime data
|
||||||
|
rm -rf /var/log/patch-manager
|
||||||
|
rm -rf /opt/patch-manager
|
||||||
|
rm -rf /var/backups/patch-manager
|
||||||
|
|
||||||
|
# Remove configuration and keys (purge only)
|
||||||
|
rm -rf /etc/patch-manager
|
||||||
|
|
||||||
|
# Remove backup cron
|
||||||
|
crontab -l 2>/dev/null | grep -vF "backup.sh" | crontab - 2>/dev/null || true
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
systemctl daemon-reload
|
||||||
|
;;
|
||||||
|
|
||||||
|
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||||
|
# On remove (not purge), keep config and keys
|
||||||
|
systemctl daemon-reload 2>/dev/null || true
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "postrm called with unknown argument \`$1'" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
20
debian/prerm
vendored
Normal file
20
debian/prerm
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
remove|upgrade|deconfigure)
|
||||||
|
# Stop services gracefully
|
||||||
|
if systemctl is-active --quiet patch-manager.target 2>/dev/null; then
|
||||||
|
systemctl stop patch-manager.target 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
failed-upgrade)
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "prerm called with unknown argument \`$1'" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
148
scripts/build-package.sh
Executable file
148
scripts/build-package.sh
Executable file
@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Linux Patch Manager — Build .deb Package for Ubuntu 24.04
|
||||||
|
# =============================================================================
|
||||||
|
# Produces: linux-patch-manager_1.0.0-1_amd64.deb
|
||||||
|
# Prerequisites:
|
||||||
|
# - Rust toolchain (cargo, rustc >= 1.75)
|
||||||
|
# - Node.js >= 18 + npm
|
||||||
|
# - dpkg-deb
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
VERSION="1.0.0"
|
||||||
|
RELEASE="1"
|
||||||
|
PKG_NAME="linux-patch-manager"
|
||||||
|
DEB_NAME="${PKG_NAME}_${VERSION}-${RELEASE}_amd64.deb"
|
||||||
|
BUILD_DIR="${PROJECT_ROOT}/package-build"
|
||||||
|
|
||||||
|
info "=== Linux Patch Manager — Package Build ==="
|
||||||
|
info "Version: ${VERSION}-${RELEASE}"
|
||||||
|
info "Target: Ubuntu 24.04 (noble) amd64"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1. Build Rust binaries (release mode)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
info "Step 1/5: Building Rust binaries (release mode)..."
|
||||||
|
cd "${PROJECT_ROOT}"
|
||||||
|
cargo build --release 2>&1 | tail -5
|
||||||
|
|
||||||
|
# Verify binaries exist
|
||||||
|
for bin in pm-web pm-worker; do
|
||||||
|
[[ -f "${PROJECT_ROOT}/target/release/${bin}" ]] || error "${bin} not found in target/release/"
|
||||||
|
done
|
||||||
|
info "Rust binaries built successfully."
|
||||||
|
|
||||||
|
# Strip debug symbols for smaller package
|
||||||
|
for bin in pm-web pm-worker; do
|
||||||
|
strip "${PROJECT_ROOT}/target/release/${bin}" 2>/dev/null || warn "strip failed for ${bin} (may already be stripped)"
|
||||||
|
done
|
||||||
|
info "Binaries stripped."
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2. Build frontend
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
info "Step 2/5: Building frontend..."
|
||||||
|
cd "${PROJECT_ROOT}/frontend"
|
||||||
|
|
||||||
|
if [[ ! -d "node_modules" ]]; then
|
||||||
|
info "Installing frontend dependencies..."
|
||||||
|
npm ci --production 2>&1 | tail -3
|
||||||
|
fi
|
||||||
|
|
||||||
|
npm run build 2>&1 | tail -5
|
||||||
|
[[ -d "${PROJECT_ROOT}/frontend/dist" ]] || error "Frontend build failed: dist/ not found"
|
||||||
|
info "Frontend built successfully."
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 3. Assemble package directory structure
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
info "Step 3/5: Assembling package structure..."
|
||||||
|
rm -rf "${BUILD_DIR}"
|
||||||
|
mkdir -p "${BUILD_DIR}/DEBIAN"
|
||||||
|
mkdir -p "${BUILD_DIR}/usr/local/bin"
|
||||||
|
mkdir -p "${BUILD_DIR}/usr/share/patch-manager/frontend"
|
||||||
|
mkdir -p "${BUILD_DIR}/usr/share/patch-manager/migrations"
|
||||||
|
mkdir -p "${BUILD_DIR}/lib/systemd/system"
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
cp "${PROJECT_ROOT}/target/release/pm-web" "${BUILD_DIR}/usr/local/bin/pm-web"
|
||||||
|
cp "${PROJECT_ROOT}/target/release/pm-worker" "${BUILD_DIR}/usr/local/bin/pm-worker"
|
||||||
|
cp "${PROJECT_ROOT}/scripts/backup.sh" "${BUILD_DIR}/usr/local/bin/backup.sh"
|
||||||
|
chmod 755 "${BUILD_DIR}/usr/local/bin/pm-web"
|
||||||
|
chmod 755 "${BUILD_DIR}/usr/local/bin/pm-worker"
|
||||||
|
chmod 700 "${BUILD_DIR}/usr/local/bin/backup.sh"
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
cp -r "${PROJECT_ROOT}/frontend/dist/"* "${BUILD_DIR}/usr/share/patch-manager/frontend/"
|
||||||
|
|
||||||
|
# Config example
|
||||||
|
cp "${PROJECT_ROOT}/config/config.example.toml" "${BUILD_DIR}/usr/share/patch-manager/config.example.toml"
|
||||||
|
|
||||||
|
# Migrations
|
||||||
|
cp "${PROJECT_ROOT}/migrations/"*.sql "${BUILD_DIR}/usr/share/patch-manager/migrations/"
|
||||||
|
|
||||||
|
# Systemd units
|
||||||
|
cp "${PROJECT_ROOT}/systemd/patch-manager-web.service" "${BUILD_DIR}/lib/systemd/system/"
|
||||||
|
cp "${PROJECT_ROOT}/systemd/patch-manager-worker.service" "${BUILD_DIR}/lib/systemd/system/"
|
||||||
|
cp "${PROJECT_ROOT}/systemd/patch-manager.target" "${BUILD_DIR}/lib/systemd/system/"
|
||||||
|
|
||||||
|
# DEBIAN control files
|
||||||
|
cp "${PROJECT_ROOT}/debian/control" "${BUILD_DIR}/DEBIAN/control"
|
||||||
|
cp "${PROJECT_ROOT}/debian/postinst" "${BUILD_DIR}/DEBIAN/postinst"
|
||||||
|
cp "${PROJECT_ROOT}/debian/prerm" "${BUILD_DIR}/DEBIAN/prerm"
|
||||||
|
cp "${PROJECT_ROOT}/debian/postrm" "${BUILD_DIR}/DEBIAN/postrm"
|
||||||
|
chmod 755 "${BUILD_DIR}/DEBIAN/postinst" "${BUILD_DIR}/DEBIAN/prerm" "${BUILD_DIR}/DEBIAN/postrm"
|
||||||
|
|
||||||
|
# Calculate installed size (in KB)
|
||||||
|
INSTALLED_SIZE=$(du -sk "${BUILD_DIR}" | cut -f1)
|
||||||
|
sed -i "s/^Installed-Size: .*/Installed-Size: ${INSTALLED_SIZE}/" "${BUILD_DIR}/DEBIAN/control"
|
||||||
|
|
||||||
|
info "Package structure assembled (${INSTALLED_SIZE} KB)."
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 4. Build .deb package
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
info "Step 4/5: Building .deb package..."
|
||||||
|
dpkg-deb --build "${BUILD_DIR}" "${PROJECT_ROOT}/${DEB_NAME}"
|
||||||
|
info ".deb package created: ${DEB_NAME}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 5. Verify and summarize
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
info "Step 5/5: Verifying package..."
|
||||||
|
dpkg-deb --info "${PROJECT_ROOT}/${DEB_NAME}"
|
||||||
|
echo
|
||||||
|
dpkg-deb --contents "${PROJECT_ROOT}/${DEB_NAME}" | head -20
|
||||||
|
echo
|
||||||
|
|
||||||
|
PKG_SIZE=$(du -h "${PROJECT_ROOT}/${DEB_NAME}" | cut -f1)
|
||||||
|
|
||||||
|
info "=== Package Build Complete ==="
|
||||||
|
info "Package: ${DEB_NAME}"
|
||||||
|
info "Size: ${PKG_SIZE}"
|
||||||
|
echo
|
||||||
|
echo -e "${CYAN}Installation instructions:${NC}"
|
||||||
|
echo " 1. Copy ${DEB_NAME} to the target Ubuntu 24.04 host"
|
||||||
|
echo " 2. Install: sudo dpkg -i ${DEB_NAME}"
|
||||||
|
echo " 3. Or with auto-deps: sudo apt install ./${DEB_NAME}"
|
||||||
|
echo " 4. Configure database URL in /etc/patch-manager/config.toml"
|
||||||
|
echo " 5. Start: systemctl enable --now patch-manager.target"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Cleanup build directory
|
||||||
|
rm -rf "${BUILD_DIR}"
|
||||||
|
info "Build directory cleaned up."
|
||||||
Reference in New Issue
Block a user