Monday 7th July 2025
I have been working on how to host multiple websites for a while. This post will describe all the prerequisites that has to be in order on the pfSense firewall before I can start implementing my first Wordpress platform, or any other platform in that regard.
Some of these prerequisites are already covered in other articles so i will link to those articles when relevant.
Design
Explanation:
The topology shows an RP = Reverse Proxy setup with two webservices on different virtual machines, to demonstrate that the solution can scale.
Depending on the port number (80 or 443) and domain name visited, the firewall will forward to correct backend.
Maybe not so clear but the lighter colored icons and lines represent ACME-Challenge traffic flows while the darker colors represents HTTPS traffic flow.
Only ACME-Challenges needs to be open on port 80. All other HTTP traffic can be redirected to HTTPS.
DNS resolution for the backend servers are important because SSL verification is enabled for the HTTPS backends.
Summary
For a website to reached securely to the internet, these are the necessary configuration steps needed, not including underlying network and server infrastructure:
Verify DNS servers under General Setup
Configure a Dynamic DNS Entry
Configure an A or AAAA record in DNS Resolver
Request Let’s Encrypt certificate for the webserver with the ACME tool
One frontend for the SSL connection
One frontend for the ACME-Challenge (if you don’t run your own PKI infrastructure)
Configuration
Verify DNS Server settings
Go to System > General Setup and verify that DNS are correctly setup. I’m using public DNS servers at the moment:
Also notice that “DNS Resolution Behaviour” is set to “Use local DNS first then fall back to remote DNS”.
Dynamic DNS
I have already covered this topic so I only show a screenshot of the relevant entries that I have configured under Services > Dynamic DNS:
Note: sometimes it may take a while until the entries turn green. Wait an hour, then try “save and force update”. If it doesn’t work withing 24 hours, you probably have a problem with the upstream DNS server.
Configure A/AAAA records in DNS Resolver
Note: You could also use the bind9 package but I could not make it work, not even with this guide.
pfSense can be used as a DNS resolver (Unbound) for clients and can forward requests for public records. However, I’m only using this service for the firewall itself to know where the public services are located1. This is needed when TLS/SSL is enabled on the servers. Otherwise clients visitng the websites will get “SSL validation failed” warnings.
In Services > DNS Forwarder, make sure that this feature is turned off.
In Services > DNS Resolver > General Settings, following settings are configured:
General DNS Resolver Options
Listen port: blank (53 is default)
Enable SSL/TLS Service: No
SSL/TLS Certificate: can be self-signed or any certificate. It doesn’t matter if you only use it for local DNS lookups
SSL/TLS Listen Port: blank (853 is default)
Network Interfaces: Localhost (incoming DNS resolution requests)
Outgoing Network Interfaces: WAN (outgoing DNS resolution requests)
The remaining settings are at default values
Host Overrides
Under General DNS Resolver options are “Host Overrides”. These are for configuring static DNS entries that should be resolved by the firewall, and not be forwarded. One example:
Host: pub
Domain: bastuklubben.online
IP Address: 2001:DB8:1234:9001::1
What it basically does is adding host entries in the /etc/hosts
file. I actually tried that first, but it didn’t have any effect on HAProxy, and the entries disappeared after an update.
Advanced Settings and ACLs
These settings are not needed to be changed as long as you only use the service for local lookups.
Request Let’s Encrypt certificate for the webserver with the ACME tool
Only the base domains (i.e. bastuklubben.online) are needed. These certificates are used by HAProxy later to forward to correct backend.
Configuration of ACME certificates tool is already covered in another article so I will only include an overview of the certificate entries that I have made for this setup.
Under Services > Acme Certificates > Account Keys:
Under Services > Acme Certificates > Certificates:
HAProxy Configration
HAProxy configuration is covered under the same article as ACME certificates above.
Backend Configuration
Go to Services > HAProxy > Backend
HTTP Backend
I give one example for one of the domains. The configured settings are:
Name: pub.bastuklubben.online-HTTP
Server list:
Mode: Active
Name: SAUNA-VM1
Forwardto: Address+Port
Address: pub.bastuklubben.online
Port: 10080
No SSL checks, encryption, weight or actions defined
Health check: none
No other settings are changed.
HTTPS Backend
The HTTPS Backend is configured in similar fashion, but with SSL enabled:
Name: pub.bastuklubben.online-HTTPS
Server list:
Mode: Active
Name: SAUNA-VM1
Forwardto: Address+Port
Address: pub.bastuklubben.online
Port: 10443
Encryption: Yes
SSL Check: Yes
Health check: none
Frontend Configuration
The Frontends are used to server multiple domains to forward to correct backend. Therefore only two frontend entries are needed.
Frontend is configured to handle the ACME-Challenge to servers. All other incoming HTTP traffic will be redirected to HTTPS.
HTTP Frontend
Under “Edit HAProxy Frontend” Options:
Name: HTTP-FE
Status: Active
External Address:
Listen Address: WAN IPv4. Port: 80. SSL Offloading: No
Listen Address: WAN IPv6. Port: 80. SSL Offloading: No
Type: http / https (offloading)
Under “Default backend, access control lists and actions” Options:
ACL Entries:
ACL Entry for ACME Challenge:
Name: acme-challenge
Expression: patch-starts-with:
CS: No
Not: No
Value: /.well-known/acme-challenge/
ACL Entry for HTTPS redirect looks similar but matches any path not starting with “acme”:
Name: not-acme-challenge
Expression: patch-starts-with:
CS: No
Not: Yes
Value: /.well-known/acme-challenge/
Then there are ACL entries for the HTTP Backends:
Name: pub.bastuklubben.online
Expression: host matches
CS: No
Not: No
Value: pub.bastuklubben.online
Actions:
Action: http-request-redirect
Parameters: rule: scheme https
Condition ACL Names: not-acme-challenge
Action: Use Backend
Paremeters: Use Backend
Backend: pub.bastuklubben.online-HTTP
Conditions ACL Names: acme-challenge pub.bastuklubben.online*
Note: specifying multiple ACL entries combines them into a logical AND statement.
HTTPS Frontend
HTTPS Frontend is forwarding client traffic to the SSL enabled backend.
Settings under “Edit HAProxy Frontend”:
Name: HTTPS-FE
Status: Active
External Address:
Listen Address: WAN IPv4. Port: 443. SSL Offloading: Yes
Listen Address: WAN IPv6. Port: 443. SSL Offloading: Yes
Type: http / https (offloading)
Settings under “Default backend, access control lists and actions”:
Access Control Lists:
ACL entries for the HTTPS Backends:
Name: bastuklubben.online
Expression: host matches
CS: No
Not: No
Value: bastuklubben.online
Actions:
Action: Use Backend
Paremeters: Use Backend
Backend: pub.bastuklubben.online-HTTPS
Conditions ACL Names: bastuklubben.online
Under “SSL Offloading”:
Certificate: any certificate. Check “Add ACL for certificate SANs”
Additional Certificates:
add certificates for the domains created earlier.
Check “Add ACL for certificate SANs”
Note: HAProxy will present correct certificate to the client based on the information inside the SNI=Server Name Indication.
HAProxy Configuration Summary
Under Backends you can verify that they are bound to correct frontend:
Now everything is in order to host a wordpress site. That will be covered in the next part.
Special Mentions
Thank you “_mbx_” for your instructions on how to configure HAProxy to handle ACME Challenges.
I’m planning to use a dedicated DNS server for clients later.