Skip to content

Build and Install from Source

duggytuxy edited this page Sep 20, 2026 · 1 revision

Build and Install from Source

Status: Version-specific Documentation baseline: v4.10.0

Build the latest fetched main with build_packages.sh, then install one locally generated package on a test host. This procedure was reviewed against commit 8fc22a6bae4adfcf62d80e90da6387f2aa6db1c7 on 2026-09-20. The v4.10.0 candidate is still undergoing qualification. A successful local build does not make its revision a qualified public release.

For stable packages, use the deployment tutorial and public releases.

1. Build host and outputs

Use a dedicated Linux x86_64 build machine or VM and an ordinary user account. Ubuntu 24.04 is the package workflow's reference build host. The script also accepts Debian/Ubuntu and RHEL/Fedora-family hosts with the required tools. Alpine is an installation target, not an accepted build host for this script. ARM, macOS and Windows are outside this procedure.

The default build always generates all three packages:

Installation target Architecture Output for this baseline
Debian/Ubuntu amd64 syswarden_4.10.0_amd64.deb
RHEL/Fedora family x86_64 syswarden-4.10.0-1.x86_64.rpm
Alpine/OpenRC x86_64 syswarden_4.10.0_x86_64.apk

Allow several GB of free disk space, including in /tmp, and sufficient RAM for Go compilation. Time and peak memory depend on the machine. The script uses fresh private Go caches, downloads locked modules and removes its temporary workspace on exit. Building is not an offline operation.

The builder does not install SysWarden on the build host. Installing a standard package on a running target can invoke the installation pipeline, including dependencies, SSH configuration, firewall policy, hardening, integrations, services and scheduled jobs. Use a disposable target first.

2. Install build prerequisites

Run only the block matching the build host, using its approved distribution repositories. Resolve unavailable dependencies before proceeding.

Debian/Ubuntu:

sudo apt-get update
sudo apt-get install -y \
  bash git python3 ca-certificates curl ruby ruby-dev build-essential \
  binutils file rpm rpm2cpio cpio tar gzip xz-utils zip unzip \
  coreutils findutils diffutils grep sed gawk util-linux

RHEL/Fedora family:

sudo dnf install -y \
  bash git python3 ca-certificates curl ruby ruby-devel rubygems gcc make \
  binutils file rpm rpm-build cpio tar gzip xz zip unzip \
  coreutils findutils diffutils grep sed gawk util-linux

The v4.10.0 builder requires exactly Go 1.26.6 for linux/amd64, FPM 1.17.0 and nFPM 2.47.0. Install Go from the official downloads following the Go installation instructions. Select go1.26.6.linux-amd64.tar.gz, verify its SHA-256 against the official listing and extract into a fresh directory. Do not overlay an existing Go installation. Put that installation's bin directory first in PATH.

GOTOOLCHAIN=local go version

The required output is go version go1.26.6 linux/amd64. The builder refuses to download a missing Go toolchain implicitly. A newer compiler does not satisfy this pin.

Install FPM and nFPM under your user account, outside the source checkout. Keep this shell open for subsequent steps:

set -euo pipefail
SW_BUILD_TOOLS="${HOME}/.local/share/syswarden-build-tools"
mkdir -p "${SW_BUILD_TOOLS}/bin" "${SW_BUILD_TOOLS}/gems"
export GEM_HOME="${SW_BUILD_TOOLS}/gems"
export GEM_PATH="${GEM_HOME}"
export PATH="${SW_BUILD_TOOLS}/bin:${GEM_HOME}/bin:${PATH}"
gem install --no-document fpm -v 1.17.0
GOTOOLCHAIN=local GOWORK=off GOFLAGS='' GOENV=off \
  GOBIN="${SW_BUILD_TOOLS}/bin" \
  go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.47.0 # Version-specific tool pin.
fpm --version
go version -m "$(command -v nfpm)"

FPM must report 1.17.0. nFPM metadata must contain module github.com/goreleaser/nfpm/v2 at version 2.47.0 (with a v prefix in Go metadata). The builder requires its executable to be a regular file, not a symlink. These methods are documented by FPM and nFPM; SysWarden pins the versions.

3. Fetch and freeze a clean source revision

Start from a fresh clone in a parent directory of your choice. Keep notes, tool installations and logs outside it. Preserve any existing working tree; do not discard changes or run git clean to satisfy the builder.

git clone https://github.com/duggytuxy/syswarden.git syswarden-source-build
cd syswarden-source-build
git fetch origin main
SW_SOURCE_SHA="$(git rev-parse --verify 'origin/main^{commit}')"
git switch --detach "${SW_SOURCE_SHA}"
git status --short
printf 'Source commit: %s\n' "${SW_SOURCE_SHA}"
./scripts/versioning.sh inspect --repo .

git status --short must print nothing. Record the full commit and reported version. This selects the latest main fetched at that moment, then freezes it even if main changes during the build. A source ZIP without Git metadata cannot replace this clone.

To reproduce the reviewed revision instead, select it before building:

SW_SOURCE_SHA=8fc22a6bae4adfcf62d80e90da6387f2aa6db1c7
git switch --detach "${SW_SOURCE_SHA}"
./scripts/versioning.sh inspect --repo .

This revision reports v4.10.0. Later revisions may declare another version or require other tools; read their builder before using these instructions. Do not edit the changelog, version files or dependency manifests to force a package name. A commit ID identifies content; it does not prove release status.

4. Build the standard packages

From the clean repository root, as the same ordinary user:

set -euo pipefail
SW_SOURCE_VERSION="$(./scripts/versioning.sh inspect --repo .)"
SW_PACKAGE_VERSION="${SW_SOURCE_VERSION#v}"
SW_BUILD_LOG="$(mktemp "${TMPDIR:-/tmp}/syswarden-build-log.XXXXXXXX")"
bash ./build_packages.sh 2>&1 | tee "${SW_BUILD_LOG}"
git status --short
printf 'Build log: %s\n' "${SW_BUILD_LOG}"

pipefail prevents tee from hiding a failed build. Continue only after exit status zero, the final [SUCCESS] message and an unchanged clean checkout. Do not build with sudo. dist and dist/packages must be real directories owned by the build user and group; the script secures them with mode 0700.

The script materializes the exact commit, builds the CLI, core and TUI, checks binary provenance and packaging contracts, then writes packages and SHA256SUMS.txt into dist/packages. It uses AMD64 level v1 and CGO_ENABLED=0; APK has separate static binaries.

The optional --rhel-package-owned-profile flag selects a different RPM integration model and filename, syswarden-4.10.0-1.rhelpo.x86_64.rpm. DEB and APK remain standard. Both RPM variants share the package name syswarden and cannot coexist. For that variant, follow the exact revision's profile reference, whose activation and removal differ from the standard RPM steps below.

5. Verify and retain the build

(
  cd dist/packages
  sha256sum --check --strict SHA256SUMS.txt
)
git rev-parse HEAD

Every listed package must pass. Save the commit, tool versions, log, packages and checksum manifest together outside the clone before another build. Rebuilding the same source version can replace the same filenames; the version alone cannot distinguish two source commits.

Checksums detect changed bytes relative to your retained manifest. They are not publisher signatures. This script does not create an official signed release, signed tag, signed update manifest or protected qualification bundle. Local packages do not inherit official SysWarden package signatures.

Transfer packages over an authenticated channel such as SSH with a verified host key, retaining the expected hash independently on the build machine. Recheck that hash on the target. If transferring only one package, verify its specific filename and digest rather than treating missing manifest entries as successful verification.

6. Prepare the target and recovery path

Before a fresh installation or upgrade:

  1. Confirm the target distribution and x86_64 architecture match the package.
  2. Keep a verified console and a second operator SSH session open.
  3. Take and test a complete pre-installation VM or volume snapshot. For an existing installation, retain configuration, lists, trust material, package identity and firewall state as private recovery data.
  4. Review package hooks and effective SSH, firewall, HA and feed settings. Preserve operator access in both host and provider firewalls.
  5. Use approved repositories for runtime dependencies. Do not stop an existing firewall frontend merely to make installation proceed.

The default keep backend preserves firewall service ownership but can still commit nftables policy and reconcile bounded rules for one already active supported UFW or firewalld frontend. It does not imply unchanged firewall rules. An HA cluster or historical migration needs its own version-specific recovery and coordination plan; this generic procedure does not establish compatibility.

7. Install one matching standard package

Run only the block for your target from the directory holding the verified package. Replace 4.10.0 only when your recorded source version differs.

Debian/Ubuntu:

SW_PACKAGE_VERSION=4.10.0
sudo apt-get update
sudo apt-get install "./syswarden_${SW_PACKAGE_VERSION}_amd64.deb"

RHEL/Fedora family:

SW_PACKAGE_VERSION=4.10.0
sudo dnf install "./syswarden-${SW_PACKAGE_VERSION}-1.x86_64.rpm"

If local policy rejects your unsigned RPM, stop and use a package signed with an accepted organizational key or the official signed release route. Do not globally disable signature checking.

Alpine/OpenRC:

SW_PACKAGE_VERSION=4.10.0
sudo apk add --no-cache cronie cronie-openrc
sudo apk add --allow-untrusted "./syswarden_${SW_PACKAGE_VERSION}_x86_64.apk"

Here --allow-untrusted applies to the explicitly named unsigned package you built and independently hash-checked. It does not authenticate origin and must not be used to accept unverified downloaded packages.

Alpine automatic activation requires the exact supported Cronie/OpenRC state. If the package reports payload-only installation, retain its output and follow its emitted fail-fast, two-phase activation instructions after the transaction completes. Do not substitute a manual syswarden install or shortened scheduler commands. A committed APK payload alone does not prove activation.

An offline systemd image transaction can also defer activation. Follow its emitted instructions after booting the real target. Package-manager success alone does not establish runtime readiness.

8. Check the installed system

After the normal activation path on a running target:

sudo syswarden
sudo syswarden config validate --path /etc/syswarden/config
sudo syswarden audit

The first command prints the CLI version. Configuration validation is read-only. Review audit findings, package logs, SSH access and firewall state. The audit is an operational diagnostic, not release qualification or a compliance certificate.

On systemd targets:

sudo systemctl status syswarden-core.service syswarden-firewall.service --no-pager
sudo journalctl -u syswarden-core.service -u syswarden-firewall.service -n 80 --no-pager

On Alpine after the emitted activation procedure:

sudo rc-service syswarden-core status
sudo rc-service syswarden-firewall status

Logs can contain private configuration or event data; redact them before sharing. Check package identity with dpkg-query -W syswarden, rpm -q syswarden or apk info -v syswarden. For binary provenance, run go version -m on a retained copy of each installed binary under /opt/syswarden/bin. Its vcs.revision must match the recorded commit and vcs.modified must be false.

9. Refresh, troubleshoot or recover

For a later commit, repeat the clean-clone, frozen-revision and build procedure. syswarden update consumes the signed release channel, not arbitrary main source builds.

An unchanged package version may be considered already installed. After checking the replacement file and recovery snapshot, use APT's --reinstall or DNF's reinstall with the exact local filename. On Alpine, first verify local-file replacement behavior for the installed apk-tools version on a disposable target. Never change source versioning just to force installation.

Failure Next step
Missing or wrong tool version Restore the exact pins and check PATH; retain builder checks.
Dirty checkout or inherited Git redirection Use a fresh clean clone in a normal shell; preserve existing work.
Unsafe output ownership or paths Use a fresh clone owned by the build user; avoid symlinked output and root builds.
Download, memory or disk failure Check approved network access and resources, then rerun the same commit.
Partial output after failure Retain the log; do not install partial or stale artifacts.
Configuration, scheduler or service failure Keep recovery access and resolve the exact failure before activation.
Lost access or failed migration Use the verified console and restore the complete pre-installation snapshot.

Package removal or an in-place downgrade does not restore the previous OS, configuration and firewall state. Retain the snapshot until acceptance and recovery checks are complete.

Source references