#!/usr/bin/env bash # # Build a .deb for Ubuntu / Debian / Linux Mint. # # Deliberately hand-rolled rather than cargo-deb: the package needs a # postinst that creates the vault with the right mode, a conffile that # survives upgrades, and a unit that is enabled but whose gate stays off # until the operator turns it on. That is easier to read as a script than # as a pile of metadata, and it is the thing most likely to need auditing. set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" VERSION="$(grep -m1 '^version' "$ROOT/Cargo.toml" | cut -d'"' -f2)" ARCH="$(dpkg --print-architecture)" OUT="${OUT:-$ROOT/dist}" STAGE="$(mktemp -d)" trap 'rm -rf "$STAGE"' EXIT # mktemp -d creates 0700, and dpkg applies the staging root's mode to "/". # Installing this package would chmod / to 0700 and break the machine. chmod 0755 "$STAGE" echo "building hound ${VERSION} (${ARCH})" ( cd "$ROOT" && cargo build --release -p houndd -p hound ) install -Dm755 "$ROOT/target/release/houndd" "$STAGE/usr/bin/houndd" install -Dm755 "$ROOT/target/release/hound" "$STAGE/usr/bin/hound" install -Dm644 "$ROOT/packaging/systemd/houndd.service" \ "$STAGE/lib/systemd/system/houndd.service" install -Dm644 "$ROOT/crates/houndd/rules/hound-builtin.yar" \ "$STAGE/usr/share/hound/rules/hound-builtin.yar" install -Dm644 "$ROOT/README.md" "$STAGE/usr/share/doc/hound/README.md" # Launcher icon: the white mark on a periwinkle tile (app-*.png), not the # bare brand mark. The tray ladder is a different family and ships with # the GUI, because tray glyphs must stay transparent to sit on any panel. for size in 16 22 24 32 48 64 128 256 512; do src="$ROOT/assets/icons/app-${size}.png" [ -f "$src" ] && install -Dm644 "$src" \ "$STAGE/usr/share/icons/hicolor/${size}x${size}/apps/hound.png" done install -Dm644 "$ROOT/assets/icons/hound-app.svg" \ "$STAGE/usr/share/icons/hicolor/scalable/apps/hound.svg" install -Dm644 /dev/stdin "$STAGE/usr/share/applications/hound.desktop" <<'DESKTOP' [Desktop Entry] Type=Application Name=Hound Antivirus GenericName=Antivirus Comment=Endpoint and supply-chain protection for Linux Exec=hound Icon=hound Categories=System;Security;Utility; Keywords=antivirus;malware;security;scan;supply chain; Terminal=true DESKTOP mkdir -p "$STAGE/DEBIAN" cat > "$STAGE/DEBIAN/control" < Depends: libc6 (>= 2.34) Recommends: clamav-daemon Homepage: https://houndav.com Description: Hound Antivirus for Linux Endpoint and supply-chain protection built for the distributions people actually run. Scanning is yara-x in process; real-time protection uses fanotify, so a binary can be refused at execve rather than reported after it has already run. . The execution gate is installed switched OFF. It needs CAP_SYS_ADMIN and covers the whole root filesystem, so turning it on is the operator's decision: hound settings set exec_gate true CONTROL cat > "$STAGE/DEBIAN/conffiles" <<'CONFFILES' /etc/hound/hound.toml CONFFILES install -Dm644 /dev/stdin "$STAGE/etc/hound/hound.toml" <<'CONF' # Hound Antivirus configuration. # # Live settings are managed through `hound settings` and stored per user; # this file holds the machine-wide defaults the daemon starts from. # Deny execution until a verdict is returned. Needs CAP_SYS_ADMIN. # Off by default: it covers the whole root filesystem, and that is the # operator's call to make rather than the installer's. exec_gate = false # Mounts the gate covers. Empty means the root filesystem. exec_gate_paths = [] # Never held for a verdict. exclude_paths = ["/proc", "/sys", "/dev", "/run", "/var/lib/docker"] # Files larger than this are allowed through unread. max_file_size_mb = 100 # "quarantine" or "alert". on_detect = "quarantine" CONF cat > "$STAGE/DEBIAN/postinst" <<'POSTINST' #!/bin/sh set -e case "$1" in configure) # The vault holds live malware: root-only, and on a filesystem where # nothing in it can be executed even by accident. mkdir -p /var/lib/hound/vault /var/lib/hound/rules /var/log/hound chmod 0700 /var/lib/hound/vault chmod 0755 /var/lib/hound /var/lib/hound/rules chmod 0750 /var/log/hound # Seed the built-in rules where the daemon looks for packs, so an # offline install still detects something. if [ -f /usr/share/hound/rules/hound-builtin.yar ]; then cp -n /usr/share/hound/rules/hound-builtin.yar /var/lib/hound/rules/ || true fi if [ -d /run/systemd/system ]; then systemctl daemon-reload || true systemctl enable houndd.service || true systemctl restart houndd.service || true fi echo "" echo "Hound is installed and scanning on demand." echo "" echo " hound status what the daemon sees" echo " hound scan ~/Downloads scan a directory" echo "" echo "Real-time execution blocking is OFF until you turn it on:" echo "" echo " sudo hound settings set exec_gate true" echo "" ;; esac exit 0 POSTINST cat > "$STAGE/DEBIAN/prerm" <<'PRERM' #!/bin/sh set -e case "$1" in remove|deconfigure) if [ -d /run/systemd/system ]; then systemctl stop houndd.service || true systemctl disable houndd.service || true fi ;; esac exit 0 PRERM cat > "$STAGE/DEBIAN/postrm" <<'POSTRM' #!/bin/sh set -e case "$1" in purge) # The vault is deliberately NOT removed on `remove`, only on `purge`, # and even then only after saying so: it may be the sole copy of # evidence somebody still needs. echo "Removing the Hound quarantine vault at /var/lib/hound/vault" rm -rf /var/lib/hound /var/log/hound ;; esac if [ -d /run/systemd/system ]; then systemctl daemon-reload || true fi exit 0 POSTRM chmod 0755 "$STAGE/DEBIAN/postinst" "$STAGE/DEBIAN/prerm" "$STAGE/DEBIAN/postrm" mkdir -p "$OUT" DEB="$OUT/hound_${VERSION}_${ARCH}.deb" fakeroot dpkg-deb --build --root-owner-group "$STAGE" "$DEB" >/dev/null echo "built $DEB" dpkg-deb -I "$DEB" | sed 's/^/ /'