Interesting, was this using the openWRT packages? I ask because Postfix didn't look to be updated compared to Exim packages.
I will admit, had no idea setting up email server would be so tricky. So far I've got about 2 pages of A4 notes and when it started to dawn on me that mistakes will lead to big problems, thats when I started looking at trying to add Crowdsec.
Speaking of Crowdsec. I managed to use the 22.03.2 OpenWRT SDK and compile Crowdsec 1.4.3 (x86_64).
For what its worth, it does work with the cs-firewall-bouncer 0.0.21 that we've installed from openWRT 21.02.3 onto 22.03.2
But I could not repeat the same trick in terms of SDK compiling of cs-firewall-bouncer 0.0.24-rc1. It doesnt show up in make menuconfig and simply editing the .config and Makefiles doesnt get an ipk.
Going to park that one for a bit and come back to it given 1.4.3 is working with 0.0.21 anyway.
EDIT:
Just to confirm, I changed /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
from set-only true to false
nftables:
ipv4:
enabled: true
set-only: false
table: crowdsec
chain: crowdsec-chain
ipv6:
enabled: true
set-only: false
table: crowdsec6
chain: crowdsec6-chain
EDIT2:
On reboot, unfortunately the nftables are not populated with the IP bans. And cat /var/log/crowdsec-firewall-bouncer.log reports error "auth with api key failed" which apparently is due to bouncer starting before crowdsec (this happened on 1.3.0 too) . So I added "sleep 2" to /etc/firewall.cs (see below). A bit bodgy......but works 
Errors
time="15-12-2022 22:37:00" level=info msg="backend type : nftables"
time="15-12-2022 22:37:00" level=info msg="nftables initiated"
time="15-12-2022 22:37:00" level=info msg="Processing new and deleted decisions . . ."
time="15-12-2022 22:37:00" level=error msg="auth-api: auth with api key failed return nil response, error: dial tcp [::1]:8080: connect: connection refused"
time="15-12-2022 22:37:00" level=fatal msg="Get \"http://localhost:8080/v1/decisions/stream?startup=true\": dial tcp [::1]:8080: connect: connection refused"
time="15-12-2022 22:37:02" level=info msg="backend type : nftables"
time="15-12-2022 22:37:02" level=info msg="nftables initiated"
time="15-12-2022 22:37:02" level=info msg="Processing new and deleted decisions . . ."
time="15-12-2022 22:37:02" level=error msg="auth-api: auth with api key failed return nil response, error: dial tcp [::1]:8080: connect: connection refused"
time="15-12-2022 22:37:02" level=fatal msg="Get \"http://localhost:8080/v1/decisions/stream?startup=true\": dial tcp [::1]:8080: connect: connection refused"
Weirdly on re-boot, there are repeats of the same rules. I did read earlier in this thread someone else had same issue, solved by the modified /etc/firewall.cs with rule deletions; more bodges 
Duplicate rules showing:
nft list table crowdsec
table ip crowdsec {
set crowdsec-blacklists {
type ipv4_addr
flags timeout
}
chain crowdsec-chain {
type filter hook input priority filter; policy accept;
ip saddr @crowdsec-blacklists drop
ip saddr @crowdsec-blacklists drop
ip saddr @crowdsec-blacklists drop
ip saddr @crowdsec-blacklists drop
}
}
My /etc/firewall.cs now looks like this
#!/bin/sh
#/etc/init.d/crowdsec enabled && /etc/init.d/crowdsec restart
#/etc/init.d/crowdsec-firewall-bouncer enabled && /etc/init.d/crowdsec-firewall-bouncer restart
#nft delete chain ip crowdsec crowdsec-chain
#nft delete chain ip6 crowdsec6 crowdsec6-chain
#nft add chain ip crowdsec crowdsec-chain '{ type filter hook forward priority 4; policy accept; }'
#nft add rule ip crowdsec crowdsec-chain iifname { usb0, eth4 } ct state new ip saddr @crowdsec-blacklists log prefix \"crowdsec: \" counter drop
#nft add chain ip6 crowdsec6 crowdsec6-chain '{ type filter hook forward priority 4; policy accept; }'
#nft add rule ip6 crowdsec6 crowdsec6-chain iifname { usb0, eth4 } ct state new ip6 saddr @crowdsec6-blacklists log prefix \"crowdsec: \" counter drop
#service crowdsec reload
sleep 2
service crowdsec-firewall-bouncer reload
sleep 2
nft delete rule crowdsec crowdsec-chain handle 6
nft delete rule crowdsec crowdsec-chain handle 5
nft delete rule crowdsec crowdsec-chain handle 4
nft delete rule ip6 crowdsec6 crowdsec6-chain handle 6
nft delete rule ip6 crowdsec6 crowdsec6-chain handle 5
nft delete rule ip6 crowdsec6 crowdsec6-chain handle 4
exit 0
So now on bootup
cat /var/log/crowdsec-firewall-bouncer.log shows
time="15-12-2022 23:08:25" level=info msg="backend type : nftables"
time="15-12-2022 23:08:25" level=info msg="nftables initiated"
time="15-12-2022 23:08:25" level=info msg="Processing new and deleted decisions . . ."
time="15-12-2022 23:09:38" level=info msg="'1352' decisions deleted"
time="15-12-2022 23:09:39" level=info msg="'26261' decisions added"
And nft list table crowdsec has data + no duplicate rule.
223.197.145.33 timeout 2d17h15m55s140ms expires 2d17h1s10ms, 223.197.151.55 timeout 4d18h15m55s130ms expires 4d18h1s200ms,
223.197.153.135 timeout 4d10h22m9s130ms expires 4d10h6m15s140ms, 223.197.175.91 timeout 5d12h15m55s120ms expires 5d12h1s490ms,
223.197.186.7 timeout 5d3h15m55s130ms expires 5d3h1s280ms, 223.197.188.206 timeout 5d12h15m55s130ms expires 5d12h1s410ms,
223.197.208.186 timeout 4d19h22m9s130ms expires 4d19h6m15s230ms, 223.197.220.67 timeout 6d10h22m9s120ms expires 6d10h6m15s710ms,
223.240.83.206 timeout 5d12h15m55s130ms expires 5d12h1s460ms, 223.240.96.1 timeout 5d12h15m55s130ms expires 5d12h1s470ms,
223.241.222.151 timeout 13h22m9s140ms expires 13h6m14s870ms, 223.245.0.5 timeout 5d12h15m55s120ms expires 5d12h1s460ms }
}
chain crowdsec-chain {
type filter hook input priority filter; policy accept;
ip saddr @crowdsec-blacklists drop
}
}
root@OpenWrt:~#