Valkyrian Labs logo

Install

Install forti-hole with Homebrew or APT, or build it from source, and prepare the forti profile it uses to reach the FortiGate.

Install

forti-hole is one executable, forti-hole. libcurl is its only runtime dependency; the forti command engine is compiled in. Install it with Homebrew or APT, or build it from source.

Prerequisites

You needWhy
A FortiGate on FortiOS 7.2.1 or later (7.4.4 or later recommended)Push-mode feeds arrived in 7.2.1; from 7.4.4 the device reports its domain-entry limit, which forti-hole budgets against
A forti profile for itforti-hole reaches the FortiGate through the forti engine with the profile, API key and certificate that forti configure (from forti-cli) stores in the forti home (~/.forti)
An API administrator allowed to write system external-resource and dnsfilter profileThe feeds and DNS filter profiles forti-hole manages. attach also needs write access to firewall policies

A FortiGuard web-filtering subscription is not required: forti-hole's feeds are remote categories on the device itself. Its DNS filter profiles set error-allow, so a lapsed subscription never stops name resolution.

Install the package

1brew install valkyrianlabs/tap/forti-cli valkyrianlabs/tap/forti-hole

Recent Homebrew versions ask you to trust a third-party tap first (brew trust valkyrianlabs/tap). forti-cli provides forti configure; forti-hole does not need it at run time.

The example configuration and the launchd template are in $(brew --prefix)/share/forti-hole/. brew services start forti-hole runs a sync every 12 hours (Scheduling).

Create the forti profile

1forti configure

forti configure asks for the FortiGate's address, the API key and, if your API user has a trusted-host certificate, the client certificate (forti cert create makes one). It stores the key in the macOS Keychain or a 0600 file, bound to that device, and sets the profile's mode:

Modeforti-hole's writes
read-only (the default)Refused: plan and compile work, sync exits 7
guardedWait for your approval of each plan: forti approve <id>, then forti-hole sync again
autonomousApplied directly; every safeguard still applies

An unattended timer needs autonomous. Check the profile with forti discover capabilities.

Next

Quick start: from an empty FortiGate to verified feeds.