> - firewall? […] Wherever I looked, people said "it's complicated." After a lot of tinkering and learning I finally got a setup that was pretty safe. (I think.)
I felt this way about pf when I first got PF going around 2011 for my home router/firewall box. Not saying this is the same for you or anyone else, but my issue was that I was approaching it from the point of view of “I want to configure a home firewall router with PF” instead of “I want to learn the fundamentals of what a firewall does”.
It took me a few more years to get well-versed in all that stuff: the structure of packets, what NAT actually means (what addresses are being translated, why, and where), what's going on in the state table, how to debug when things aren't doing what I expect, etc. Once I did it became much more straightforward to express in my `pf.conf` what I want to do, but you're right that doesn't really help new users.
> Lots of pain and hard to find friendly, best practice starter templates.
FreeBSD does include this, however! It's just implemented using IPFW instead of PF. Check out `firewall_type` key in `rc.conf`: https://cgit.freebsd.org/src/tree/libexec/rc/rc.conf?id=edad...
For a very simple NAT gateway, one could set `firewall_type=simple` and then `firewall_simple_(iif|inet|oif|onet)(_ipv6)?` to configure the ISP-side and internal-side interface names and IPv4 and IPv6 network ranges for each.
For a very easy single-machine firewall, one could set `firewall_type=client` or `firewall_type=workstation` if you want to host anything. For the latter, `firewall_myservices` and `firewall_allowservices` control what ports are enabled and who (other networks/IPs) have access to them
For more details and to see exactly what each option actually does, check out `/etc/rc.firewall` where this is all implemented: https://cgit.freebsd.org/src/tree/libexec/rc/rc.firewall?id=...