← Field Manual
BRIEF · 00803 ArchitectDigitalNetwork & Hardware· 36 min read· updated 2026-05-30

pfSense on Bare Metal: The Wall Nothing Crosses

Install, harden, and operate a pfSense CE firewall on a Protectli Vault. The reference build, end to end.

§ BRIEFING

TL;DR

Install pfSense CE on a Protectli Vault, harden it correctly on day one, segment the network into TRUSTED / IOT / GUEST VLANs, run Unbound as a recursive DNSSEC-validating resolver with pfBlockerNG-devel block-lists, and put Suricata in IPS mode on WAN. Auto-backup the config off-box. Verify every layer before you call it done.

What you'll be able to do

  • pfSense CE 2.7.x installed on ZFS with interfaces correctly assigned.
  • Default-deny WAN, sane LAN rules, and an anti-lockout safety net you understand.
  • Three working VLANs with rule-enforced isolation between them.
  • Recursive DNS with DNSSEC validation and DNSBL block-lists active.
  • Suricata IPS in inline mode on WAN, with the ET Open ruleset and a tuning workflow.
  • Encrypted off-box config backups, both automatic and manual.
  • A verification pass that proves the build works rather than assumes it.

Prerequisites

  • ·A Protectli Vault (VP2420 or better) with RAM and SSD installed, see the Protectli Vault guide.
  • ·A managed switch and a separate Wi-Fi access point capable of VLAN-tagged SSIDs.
  • ·Basic networking literacy: you know what a /24 is and what NAT does.
  • ·A laptop with a terminal and the ability to write an OS image to USB.

Threat model

Opportunistic internet adversaries, compromised IoT devices on your LAN, ISP-side DNS tampering, and the operator's own mistakes (misconfigured port-forwards, stale firmware). This is a household and small-lab build, not an enterprise SOC. It is honest about what an IPS catches, what a DNSBL catches, and what they don't.

A firewall is not an appliance. An appliance is a thing you plug in and forget. A firewall is a managed system that sits on the edge of your network and rewrites the rules of what is possible, for you, for your guests, for every infected device that will eventually find its way onto your LAN. Treating it like a router with extra checkboxes is how people end up with a $400 box doing the job of a $40 one.

pfSense is the reference open-source firewall on x86. It has twenty years of FreeBSD lineage, the most documented package ecosystem in its category (Suricata, pfBlockerNG-devel, HAProxy, ACME, WireGuard, OpenVPN, FRR for routing), and the operational maturity of software that runs in actual production networks rather than on tutorial blogs. It is also the OS Netgate sponsors and ships on their appliances, so the development cadence is funded rather than vibes.

This guide installs pfSense CE on a Protectli Vault, hardens it the way a competent operator would on day one, configures the rules and segmentation a real household needs, and gets you to the point where the firewall stops being a project and starts being infrastructure. Plan a Saturday.

The firewall isn't done when it's installed. It's done when you've forgotten what's special about it.

By the end of this build you will have: pfSense CE 2.7.x on ZFS, interfaces assigned and labelled, default-deny on WAN, sane LAN rules, three VLANs (TRUSTED, IOT, GUEST) with proper isolation, Unbound resolving recursively with DNSSEC, pfBlockerNG-devel blocking the obvious garbage, Suricata in IPS mode on WAN with the ET Open ruleset, automated config backups going off-box, and a verification pass that proves each of those works rather than just claims to.

§ 01

pfSense CE vs. pfSense Plus, pick correctly.

Netgate ships two editions of pfSense and the naming has confused operators for years. The difference matters before you download anything.

AspectpfSense CE (Community Edition)pfSense Plus
LicenseApache 2.0, fully open sourceProprietary, source-available for some components
CostFree on any hardware, foreverFree on Netgate appliances; paid subscription on third-party hardware
Release cadenceSlower; CE 2.7.x is the current stable lineFaster; Plus 24.x ships features first
FeaturesAll the essentials; no ZFS boot env GUI, no built-in WireGuard kernel module (uses port)Earlier WireGuard kernel, ZFS boot envs in GUI, some QoS extras
Right pick on a Protectli VaultYes, this is what we installNo, you'd be paying a subscription for a Netgate feature set on non-Netgate hardware
On a Protectli, pfSense CE is the correct choice. Plus is correct on a Netgate SG appliance. Don't mix them up.

§ 02

Pre-flight: the parts on your desk before you begin.

  • Protectli Vault (VP2420 or better)

    ref ↗

    The firewall hardware itself

    See the Protectli Vault guide for model selection. This guide assumes a VP2420 with 8 GB RAM and a 120 GB SATA SSD.

  • 8 GB DDR4 SO-DIMM (Crucial CT8G4SFRA32A)

    RAM, not included in barebones

    8 GB is comfortable for CE + Suricata + pfBlockerNG. Don't bother with 4 GB.

  • 120 GB SATA SSD (Crucial MX500 or similar)

    Boot + logs

    Anything ≥ 60 GB works. ZFS likes headroom. Avoid the cheapest no-name drives.

  • USB 3.0 stick, ≥ 2 GB

    Installer media (one-time use)

    Any cheap stick. You will write the pfSense image to it and forget about it after install.

  • USB-C cable (data) for console

    Serial console access

    The VP24xx/VP46xx/VP66xx expose serial console over the front USB-C port. A standard USB-C-to-USB-A or USB-C-to-USB-C data cable works.

  • Two ethernet cables (different colours)

    WAN and LAN

    Cat 6 or better. Use distinct colours so you never plug WAN into LAN by mistake.

  • A laptop with terminal and Etcher (or dd)

    Imaging + console host

    Mac, Linux, or Windows. You'll write the installer USB and open the serial console from this machine.

§ 03

Download and verify the installer.

You are about to install the OS that decides which packets enter your house. Verify the image. This takes ninety seconds and is the difference between running pfSense and running someone's repackaged pfSense.

  1. STEP 01

    Download from the official Netgate mirror only.

    Get the installer from atxfiles.netgate.com (the official mirror linked from pfsense.org/download). Pick architecture AMD64, installer type USB Memstick Installer, console type VGA (the Vault has VGA/HDMI; serial still works at boot). The filename will look like pfSense-CE-memstick-2.7.2-RELEASE-amd64.img.gz.

  2. STEP 02

    Verify the SHA-256.

    Netgate publishes the hash on the download page. Compare it against what you actually downloaded. If they don't match, do not proceed, re-download, and if it still doesn't match, your network path is compromised.

    verify
    # Compute
    shasum -a 256 pfSense-CE-memstick-2.7.2-RELEASE-amd64.img.gz
    
    # Expected output should match the SHA-256 shown next to the file on
    # https://www.pfsense.org/download/, character for character.
    macOS / Linux. Replace the expected hash with the one from the download page.
  3. STEP 03

    Decompress and write to USB.

    On macOS or Linux, use dd with care, wrong device name overwrites your laptop. balenaEtcher is the safer GUI alternative and works on all three platforms.

    write-usb
    gunzip pfSense-CE-memstick-2.7.2-RELEASE-amd64.img.gz
    
    # macOS: identify the disk (look for the USB stick by size)
    diskutil list
    
    # Unmount (do NOT eject)
    diskutil unmountDisk /dev/disk4   # replace with YOUR disk number
    
    # Write
    sudo dd if=pfSense-CE-memstick-2.7.2-RELEASE-amd64.img \
           of=/dev/rdisk4 bs=1m status=progress
    
    # Linux equivalent:
    # sudo dd if=pfSense-...img of=/dev/sdX bs=4M status=progress oflag=sync
    Identify the USB first. Wrong target = destroyed disk.

§ 04

BIOS prep on the Vault.

Plug in the installer USB, a monitor (or a serial cable), the keyboard, and the power. Tap DEL on boot to enter AMI BIOS. Make four changes.

  1. STEP 01

    Disable Secure Boot.

    Under Security → Secure Boot, set it to Disabled. FreeBSD's loader does not participate in Secure Boot and pfSense will not install with it on.

  2. STEP 02

    Confirm AES-NI is enabled.

    Under Advanced → CPU Configuration, confirm AES-NI shows as enabled (it's on by default on every supported Vault CPU). Suricata and IPsec depend on it for any reasonable throughput.

  3. STEP 03

    Set the boot order, USB first.

    Under Boot, move the USB stick above the SSD. You'll undo this after install.

  4. STEP 04

    (Optional) Enable serial console redirection.

    Under Advanced → Serial Port Console Redirection, set BIOS redirection to 115200, 8N1, VT100+. You don't need this for install, just useful if you ever lock yourself out of the web UI and have to console in.

§ 05

Install pfSense.

  1. STEP 01

    Boot the installer, accept the defaults until the disk picker.

    Accept the copyright, pick Install, choose your keymap. At the partition prompt, choose Auto (ZFS), then stripe, 1 disk. ZFS gives you checksumming, snapshot-based rollbacks, and proper crash consistency. There is no good reason to use UFS in 2026.

  2. STEP 02

    Let it install. Reboot. Pull the USB.

    Install takes 3–5 minutes on a Vault SSD. When prompted to reboot, choose No to manual shell, just reboot, pull the USB the moment the screen goes dark, and let the box come up on its own disk.

  3. STEP 03

    Assign interfaces by physical port.

    On first boot pfSense will ask whether to set up VLANs (say n for now, we'll do them properly from the web UI) and then ask you to assign WAN, LAN, and any OPT interfaces to physical NICs. The Vault NICs will appear as igc0, igc1, igc2, igc3 (i225/i226 Intel NICs use the igc driver). Convention: igc0 = WAN, igc1 = LAN.

    auto-detect
    # At the console:
    #   "Should VLANs be set up now [y|n]?"  → n
    #   "Enter the WAN interface name or 'a' for auto-detection:"  → a
    # Then unplug and replug the cable in the port you want as WAN.
    # pfSense sees the link drop and tells you which interface it was.
    If you can't tell which port is which, use the auto-detect helper.
  4. STEP 04

    Set the LAN IP to something you can route to.

    Default is 192.168.1.1/24 with DHCP serving .100–.245. Fine if it doesn't collide with your current network. If it does, pick a unique RFC1918 range now, moving it later means re-IPing every client.

§ 06

First-boot hardening from the web UI.

Plug a laptop into the LAN port. You'll get a DHCP lease. Browse to https://192.168.1.1 (accept the self-signed cert, we'll replace it). Default credentials are admin / pfsense. The setup wizard will run.

§ CHECKLIST, Setup wizard, every step

post-wizard
# System → Advanced → Admin Access
- Protocol: HTTPS (default)
- WebGUI redirect: CHECKED
- Anti-lockout rule: leave ENABLED on LAN (do not disable until you have console muscle memory)
- Login Protection, Threshold: 10, Blocktime: 1800

# System → Advanced → Networking
- Disable hardware checksum offload: UNCHECKED (Intel igc handles it correctly)
- Disable hardware TCP segmentation offload: UNCHECKED

# System → General Setup
- DNS Server Override: UNCHECKED (we control DNS, not the ISP)
Three more clicks before you do anything else.

§ 07

Firewall rules that match how people actually live.

The textbook answer is "default-deny outbound, allowlist every protocol". In a household, that ends with someone unable to print at 11 PM and a firewall flipped back to "allow LAN to any". Be honest about the threshold of effort you'll maintain.

The realistic baseline:

  • · WAN: default-deny inbound (already the default). Block bogons. Block private networks. No port-forwards yet.
  • · LAN (trusted): allow LAN to any. Above that rule, block LAN to other RFC1918 subnets (IoT, GUEST) so trusted devices don't accidentally route into them.
  • · IoT VLAN: default-deny. Allow only DNS to the firewall, NTP to the firewall, and HTTPS to the internet. Block IoT to all RFC1918 above the allow rules.
  • · GUEST VLAN: allow internet, block all RFC1918, rate-limit per-host if you care.

§ 08

VLANs and segmentation.

VLANs only work end-to-end. The firewall tags them; the switch carries the tags on a trunk port; the access point binds each SSID to a VLAN ID. If any link in that chain is an unmanaged switch, your "isolated" IoT VLAN is a fiction.

vlan-plan
Interface assignments after VLAN setup:
  igc0 (WAN)          , public IP from ISP
  igc1 (LAN parent)   , trunk to managed switch, carries VLANs below
    └─ VLAN 10 (TRUSTED), 10.10.10.0/24  laptops, phones, work
    └─ VLAN 20 (IOT)    , 10.10.20.0/24  cameras, bulbs, vacuum, TV
    └─ VLAN 30 (GUEST)  , 10.10.30.0/24  guest Wi-Fi, isolated
    └─ VLAN 99 (MGMT)   , 10.10.99.0/24  switch + AP admin only

Rule order on each VLAN:
  1. Anti-lockout (auto, LAN only)
  2. Block VLAN_NET → other RFC1918   (kills lateral movement)
  3. Allow VLAN_NET → firewall:53     (DNS to Unbound)
  4. Allow VLAN_NET → firewall:123    (NTP)
  5. Allow VLAN_NET → any (or restricted for IOT)
A sane four-segment household plan.
  1. STEP 01

    Create the VLAN interfaces in pfSense.

    Interfaces → Assignments → VLANs → Add. Parent interface is igc1, VLAN tag is the ID you chose (10, 20, 30, 99). Repeat for each.

  2. STEP 02

    Assign and enable each VLAN as an OPT interface.

    Interfaces → Assignments → add each VLAN as a new interface (OPT1, OPT2, OPT3, OPT4). Rename them (IOT, GUEST, MGMT) and enable them. Static IPv4, /24, the firewall holds .1.

  3. STEP 03

    Enable DHCP server on each VLAN.

    Services → DHCP Server → [VLAN tab]. Reasonable pool (e.g. .100–.245). Point DNS at the firewall's VLAN IP, not at upstream resolvers.

  4. STEP 04

    Configure the trunk on your switch and tag your AP SSIDs.

    On the managed switch, set the port to the firewall as a trunk carrying VLANs 10/20/30/99 (PVID untagged depends on your switch, UniFi and Mikrotik both make this straightforward). On the access point, bind TRUSTED SSID to VLAN 10, GUEST to VLAN 30, IoT SSID to VLAN 20.

§ 09

DNS: resolve recursively, block the obvious.

pfSense ships Unbound as the DNS resolver. By default it runs in resolver mode with forwarding disabled, which means it asks the root servers directly, no Google, no Cloudflare, no ISP in the path. This is correct. Validate it stays this way.

unbound-settings
General Settings:
  - Enable DNS Resolver: CHECKED
  - Listen Port: 53
  - Network Interfaces: ALL (or explicitly LAN + every VLAN)
  - Outgoing Interfaces: WAN
  - System Domain Local Zone Type: Transparent
  - DNSSEC: CHECKED
  - DNS Query Forwarding: UNCHECKED  (this is the important one)
  - DHCP Registration: CHECKED       (lets you ssh by hostname.lan)
  - Static DHCP: CHECKED
Services → DNS Resolver → General Settings
  1. STEP 01

    Install pfBlockerNG-devel.

    System → Package Manager → Available Packages. Install pfBlockerNG-devel (not the classic pfBlockerNG , it's abandoned). Run the wizard; it will set sane defaults.

  2. STEP 02

    Add the obvious block-lists, nothing exotic.

    Under Firewall → pfBlockerNG → DNSBL → DNSBL Groups, enable: EasyList, EasyPrivacy, StevenBlack unified hosts, OISD Big. That's enough. People who add twelve lists end up with broken Slack and turn the whole thing off in a month.

  3. STEP 03

    Save, force-reload, and verify a known-bad domain.

    From a LAN client: dig doubleclick.net @firewall_ip. Expect a response of 0.0.0.0 or the pfBlocker-VIP, that confirms DNSBL is doing its job.

§ 10

IDS/IPS with Suricata, and the honest CPU cost.

Suricata in IPS mode inspects every packet against signature rules and drops what matches. This is heavy work. A VP2410 will struggle with the full ET Open ruleset on a gigabit link. A VP2420 handles it comfortably. A VP4630 yawns.

  1. STEP 01

    Install Suricata.

    System → Package Manager → Available Packages → Suricata. Install. Reboot if it asks.

  2. STEP 02

    Configure on WAN only, IPS mode, inline.

    Under Services → Suricata → Interfaces → Add: pick WAN, enable, set Block Offendersand IPS Mode = Inline. Inline mode requires Netmap-capable NICs, the Intel igc on VP24xx/VP46xx supports this; older Realtek-based gear does not.

  3. STEP 03

    Enable the ET Open ruleset and let it download.

    Services → Suricata → Global Settings → enable ET Open Emerging Threats. Save. Run an initial update, this takes 5–10 minutes. Schedule automatic updates daily at a quiet hour.

  4. STEP 04

    Tune for false positives over the first week.

    Suricata will false-positive on legitimate traffic (Microsoft Office telemetry, some game servers, Netflix CDN occasionally). Watch Services → Suricata → Alerts daily for the first week and suppress rules that fire on traffic you recognise. Do not just disable categories, disable specific SIDs.

§ 11

Backups and monitoring.

A firewall without a config backup is a one-disk-failure away from a Saturday rebuilding rules from memory. Two layers: automatic encrypted backup to Netgate's free service, and a manual pull to your own offline storage.

  1. STEP 01

    Enable AutoConfigBackup.

    Services → AutoConfigBackup. Sign in with a free Netgate account, set an encryption passphrase you store in your password manager, and enable it. Pushes an encrypted XML to Netgate every time you make a change.

  2. STEP 02

    Periodically pull the config XML off-box yourself.

    Diagnostics → Backup & Restore → Download configuration. Check the encryption box, set a strong passphrase, save the file to your password manager's secure attachments or an encrypted backup drive. Do this monthly and after every significant change.

  3. STEP 03

    Send logs to a local syslog collector.

    Status → System Logs → Settings → enable remote logging to your private server (the Raspberry Pi from the previous guide is fine). Send firewall, Suricata, and DHCP logs. The firewall's local log buffer is too small for forensics; centralised logs are cheap insurance.

§ 12

Verification: confirm every layer holds.

§ CHECKLIST, End-of-install verification

from-trusted-vlan
# Confirm DNSSEC validation is on
dig dnssec-failed.org   # expect: SERVFAIL
dig internetsociety.org # expect: NOERROR with AD flag

# Confirm DNSBL
dig doubleclick.net @192.168.1.1   # expect: 0.0.0.0 or pfBlocker VIP

# Confirm lateral isolation: try to reach an IoT host
ping 10.10.20.50    # expect: no response (or 'Destination Host Unreachable')

# Confirm WAN is sealed from cellular (do this from your phone hotspot, not LAN)
nmap -Pn -p- <your WAN IP>
Run from a laptop on the TRUSTED VLAN.

§ 13

What this build does NOT do.

✓ PROTECTS AGAINST

  • +Unsolicited inbound traffic from the public internet (default-deny WAN, no UPnP).
  • +Lateral movement between TRUSTED, IOT, and GUEST segments (rule-enforced).
  • +Outbound connections to known-malicious domains (DNSBL via pfBlockerNG-devel).
  • +DNS hijacking by the ISP or by upstream resolvers (Unbound recursive + DNSSEC).
  • +A meaningful percentage of known network-layer exploit attempts (Suricata IPS with ET Open).
  • +Config loss from disk failure (encrypted off-box backups, twice over).

✗ DOES NOT PROTECT AGAINST

  • Inspect TLS-encrypted payloads, IDS sees metadata and SNI, not content. That's a feature, not a bug.
  • Protect endpoints that visit the wrong link in a phishing email, the firewall sees the connection, not the click.
  • Replace endpoint AV/EDR. The firewall is one layer; the laptop's OS is another.
  • Stop a determined insider with admin credentials, a household firewall is not a SOC.
  • Auto-tune itself. Suricata false-positives, DNSBL false-positives, and rule drift all require attention.
  • Survive an out-of-date OS. pfSense 2.6.0 in 2026 is the attack surface, not the defence.

The firewall is now infrastructure. The next moves expand what it lets you do safely.

§ REFERENCES

  1. [01]Netgate, pfSense documentation
  2. [02]pfSense CE, download
  3. [03]pfBlockerNG-devel, active fork
  4. [04]Suricata, IDS/IPS documentation
  5. [05]Emerging Threats, ET Open ruleset
  6. [06]Unbound, recursive DNS resolver
  7. [07]FreeBSD Handbook, for the OS underneath

↳ last updated · 2026-05-30

Field notes for education. Private engagements: Greyshrine.

§ 00, BOOTING FIELD MANUAL
● LINK · NEGOTIATING
JTA //

JUSTIN · THE · ARCHITECT

> establishing secure channel…

HANDSHAKE004%READY
● STATUS: HANDSHAKE
LAT 00.000 · LON 00.000