[Unit] Description=Hound Antivirus daemon Documentation=https://houndav.com/docs After=network.target # The gate is only useful while the filesystem it watches is mounted. RequiresMountsFor=/var/lib/hound [Service] Type=exec ExecStart=/usr/bin/houndd Restart=on-failure RestartSec=2s # ── Privilege ──────────────────────────────────────────────────────── # # houndd reduces its own capabilities at startup (see crates/houndd/src/ # caps.rs). This bounding set is the second half of that: it protects the # machine if the binary is ever replaced by one that does not, and it # means the daemon never *holds* the rest even momentarily. # # It cannot be narrower. fanotify needs SYS_ADMIN; scanning arbitrary # files needs DAC_READ_SEARCH; quarantining out of a directory owned by # someone else needs DAC_OVERRIDE; stripping the execute bit off a file # we do not own needs FOWNER. CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER AmbientCapabilities=CAP_SYS_ADMIN CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER NoNewPrivileges=yes # ── Filesystem ─────────────────────────────────────────────────────── # # ProtectSystem=strict would be the obvious choice and is WRONG here: it # remounts everything read-only, and quarantine has to remove a threat # from wherever it landed. ProtectHome is off for the same reason — most # of what we quarantine is under /home. ProtectSystem=false ProtectHome=false ReadWritePaths=/var/lib/hound /var/log/hound StateDirectory=hound LogsDirectory=hound RuntimeDirectory=hound PrivateTmp=no # ── Everything else we can shut off ────────────────────────────────── ProtectKernelTunables=yes ProtectKernelModules=yes ProtectKernelLogs=yes ProtectControlGroups=yes ProtectClock=yes ProtectHostname=yes ProtectProc=invisible RestrictNamespaces=yes RestrictRealtime=yes RestrictSUIDSGID=yes LockPersonality=yes MemoryDenyWriteExecute=yes RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallFilter=~@clock @cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @swap UMask=0077 # ── Resources ──────────────────────────────────────────────────────── # A scanner that eats the machine is its own denial of service. MemoryMax=1G TasksMax=64 LimitNOFILE=65536 OOMScoreAdjust=-500 [Install] WantedBy=multi-user.target