#!/usr/bin/env bash # # Build the Hound AppImage. # # What an AppImage can and cannot be, for this product: # # An AppImage is unprivileged by design — no install, no root, no # systemd. The execution gate needs CAP_SYS_ADMIN and a filesystem-wide # fanotify mark, so it is simply not available here, and pretending # otherwise would be worse than saying so. # # What IS available is everything that does not need privilege: # on-demand scanning, the quarantine vault under the user's own data # directory, rootkit heuristics, supply-chain checks and the CLI. That # makes this the "try it without installing anything" build, and the # AppRun below says exactly that when the gate is asked for. # # Needs appimagetool on PATH (or at $APPIMAGETOOL). set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" VERSION="$(grep -m1 '^version' "$ROOT/Cargo.toml" | cut -d'"' -f2)" OUT="${OUT:-$ROOT/dist}" TOOL="${APPIMAGETOOL:-$(command -v appimagetool || true)}" APPDIR="$(mktemp -d)/Hound.AppDir" trap 'rm -rf "$(dirname "$APPDIR")"' EXIT if [ -z "$TOOL" ]; then echo "appimagetool not found. Set APPIMAGETOOL=/path/to/appimagetool" >&2 exit 2 fi echo "building Hound AppImage ${VERSION}" ( cd "$ROOT" && cargo build --release -p houndd -p hound ) mkdir -p "$APPDIR" chmod 0755 "$APPDIR" install -Dm755 "$ROOT/target/release/hound" "$APPDIR/usr/bin/hound" install -Dm755 "$ROOT/target/release/houndd" "$APPDIR/usr/bin/houndd" install -Dm644 "$ROOT/crates/houndd/rules/hound-builtin.yar" \ "$APPDIR/usr/share/hound/rules/hound-builtin.yar" # The launcher icon is the white mark on periwinkle, sized optically. install -Dm644 "$ROOT/assets/icons/app-256.png" "$APPDIR/hound.png" 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" \ "$APPDIR/usr/share/icons/hicolor/${size}x${size}/apps/hound.png" done install -Dm644 "$ROOT/assets/icons/hound-app.svg" \ "$APPDIR/usr/share/icons/hicolor/scalable/apps/hound.svg" cat > "$APPDIR/hound.desktop" <<'DESKTOP' [Desktop Entry] Type=Application Name=Hound Antivirus Comment=Endpoint and supply-chain protection for Linux Exec=hound Icon=hound Categories=System;Security; Terminal=true DESKTOP cat > "$APPDIR/AppRun" <<'APPRUN' #!/bin/sh # # Portable-mode launcher. # # Everything lives under the user's own directories, so the AppImage # leaves nothing behind on the system and needs no privilege. The one # thing it cannot do is gate execution — see below. set -e HERE="$(dirname "$(readlink -f "$0")")" export PATH="$HERE/usr/bin:$PATH" # Rules ship inside the bundle; point the daemon at them read-only. export HOUNDD_RULES_DIR="${HOUNDD_RULES_DIR:-$HERE/usr/share/hound/rules}" # Keep state in the user's own dirs rather than /var/lib. export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" export HOUNDD_SOCK="${HOUNDD_SOCK:-${XDG_RUNTIME_DIR:-/tmp}/houndd.sock}" mkdir -p "$XDG_DATA_HOME/hound" "$XDG_CONFIG_HOME/hound" # A Unix socket path cannot exceed sun_path (108 bytes on Linux), and # XDG_RUNTIME_DIR is not always short. Fall back rather than failing with # an error most people cannot act on. if [ "${#HOUNDD_SOCK}" -ge 100 ]; then HOUNDD_SOCK="/tmp/houndd-$(id -u).sock" export HOUNDD_SOCK fi # Start a private daemon if one is not already answering. if ! "$HERE/usr/bin/hound" status >/dev/null 2>&1; then "$HERE/usr/bin/houndd" >"${XDG_DATA_HOME}/hound/appimage.log" 2>&1 & # Wait for the socket rather than sleeping a fixed amount. i=0 while [ ! -S "$HOUNDD_SOCK" ] && [ $i -lt 50 ]; do i=$((i + 1)) sleep 0.1 done fi case "${1:-}" in settings) case "${2:-} ${3:-}" in "set exec_gate") cat >&2 <<'MSG' The execution gate is not available in the AppImage. Blocking a program at execve needs CAP_SYS_ADMIN and a filesystem-wide fanotify mark, which an unprivileged, uninstalled bundle cannot have. Everything else works here: on-demand scanning, quarantine, rootkit checks and supply-chain checks. For real-time protection, install the package: sudo apt install ./hound_*.deb sudo hound settings exec-gate on MSG exit 2 ;; esac ;; esac exec "$HERE/usr/bin/hound" "$@" APPRUN chmod 0755 "$APPDIR/AppRun" mkdir -p "$OUT" ARCH=x86_64 "$TOOL" --no-appstream "$APPDIR" "$OUT/Hound-${VERSION}-x86_64.AppImage" 2>&1 \ | grep -vE "^(WARNING|Warning)" || true echo "built $OUT/Hound-${VERSION}-x86_64.AppImage"