## Why replace nginx with freenginx?
In early 2024, nginx’s core developer forked nginx into **freenginx** to preserve fully community-driven, non-corporate development.
Freenginx:
* Follows the same configuration language and architecture as nginx
* Tracks bug fixes and features from modern nginx releases
* Is distributed under a 2-clause BSD-style license and aims to remain fully “free” in both senses
On **FreeBSD**, freenginx is available as a regular port/package: **www/freenginx**, with the package name `freenginx`.
This post walks through **migrating an existing nginx install to freenginx** on a FreeBSD 13.5/14.x system (the current Handbook targets those releases).
* * *
## Overview of the migration
At a high level, we’ll:
1. Inspect and back up your existing nginx configuration
2. Remove the nginx package
3. Install freenginx (via `pkg` or ports)
4. Copy and adapt configuration to freenginx’s paths
5. Enable and start the freenginx service
6. Test and verify everything
7. Optionally, clean up and harden the new setup
* * *
## Prerequisites
I’ll assume:
* You’re running **FreeBSD 13.5 or 14.x** (RELEASE or newer).
* You have **root** or sudo access.
* nginx is installed via **pkg/ports**, not from custom source.
* You’re somewhat familiar with the FreeBSD Handbook’s package/ports chapter.
All commands below run as `root` (or `doas`/`sudo` equivalent).
* * *
## Step 1 – Inspect your current nginx setup
First, confirm how nginx is installed:
```sh
pkg info | grep -i nginx
```
You might see something like:
* `nginx-1.24.x`
* or flavored packages such as `nginx-lite`, `nginx-full`, `nginx-naxsi`, etc.
Check where your configs and web root live (defaults):
* Config directory (pkg/ports installs):
* `/usr/local/etc/nginx/`
* Main config: `/usr/local/etc/nginx/nginx.conf`
* Log directory:
* `/var/log/nginx/`
* Default document root (often):
* `/usr/local/www/nginx/` (or custom, depending on your config)
Also note your rc settings:
```sh
grep nginx /etc/rc.conf /etc/rc.conf.local 2>/dev/null
```
You’ll probably see:
```sh
nginx_enable="YES"
```
Keep this in mind; we’ll reuse the same service name.
* * *
## Step 2 – Back up your current nginx configuration
Before touching packages, **back everything up**.
```sh
mkdir -p /root/nginx-backup
cp -a /usr/local/etc/nginx /root/nginx-backup/etc-nginx-$(date +%Y%m%d-%H%M)
cp -a /var/www /root/nginx-backup/var-www-$(date +%Y%m%d-%H%M) 2>/dev/null || true
```
If your web root is somewhere else (e.g. `/usr/local/www/yourapp`), back that up too:
```sh
cp -a /usr/local/www /root/nginx-backup/usr-local-www-$(date +%Y%m%d-%H%M)
```
If you’re on ZFS, consider creating a snapshot as well, e.g.:
```sh
zfs snapshot poolname/dataset@before-freenginx
```
* * *
## Step 3 – Plan the cut-over (downtime vs. seamless)
For a simple single server, you can usually just:
1. Stop nginx
2. Uninstall nginx package
3. Install freenginx
4. Start freenginx
If this box is in a load-balanced cluster, you’d drain it from the balancer first, do the migration on one node, verify, then repeat on others.
For this post, we’ll assume **brief downtime is OK**.
* * *
## Step 4 – Stop nginx cleanly
Stop nginx and make sure it’s really gone:
```sh
service nginx stop
ps auxw | grep nginx
```
If any stray worker/master processes remain, kill them:
```sh
pkill nginx || true
```
Make sure ports 80/443 are clear:
```sh
sockstat -4 -l | egrep '(:80|:443)' || echo "HTTP(S) ports are free."
```
* * *
## Step 5 – Remove nginx package
Using `pkg` (as described in the Handbook’s package management section), uninstall nginx.
```sh
pkg delete nginx nginx-lite nginx-full nginx-devel nginx-naxsi
```
You won’t necessarily have all of those; pkg will just skip ones that aren’t installed.
> **Note:**
> This removes the binaries, but keeps your config files in `/usr/local/etc/nginx` (you already backed them up anyway).
* * *
## Step 6 – Install freenginx on FreeBSD
Freenginx is available from the **FreeBSD Ports Collection** as `www/freenginx` and can be installed via either ports or packages.
### Option A – Install via pkg (recommended for most)
```sh
pkg update
pkg install freenginx
```
From the port’s metadata, you can see this is equivalent to installing `www/freenginx`, and it pulls in required libraries such as `devel/pcre2`.
### Option B – Install from ports (for custom module sets)
If you want to tweak the large set of options (e.g. HTTP/2, HTTP/3, various third-party modules), use ports.
```sh
cd /usr/ports/www/freenginx
make config # choose your modules & options
make install clean
```
The options dialog exposes things like:
* Core features: `HTTP`, `STREAM`, `MAIL`
* SSL and HTTP/2/HTTP/3 (`HTTP_SSL`, `HTTPV2`, `HTTPV3`)
* Many third-party modules (brotli, lua, naxsi, modsecurity3, etc.)
* * *
## Step 7 – Understand freenginx’s layout on FreeBSD
After installation, check the file list (from the port metadata):
Key points:
* **Binary**:
* `/usr/local/sbin/nginx`
* **Service script**:
* **Configuration directory** (important difference):
* `/usr/local/etc/freenginx/`
* **Default document root** (from the port):
* `www/freenginx-dist` (under `/usr/local/www`), symlinked as `/usr/local/www/freenginx` for convenience.
* **Logs**:
* Same log directories as nginx: `/var/log/nginx/` etc.
Sample configs are installed as:
```text
/usr/local/etc/freenginx/nginx.conf-dist → /usr/local/etc/freenginx/nginx.conf
/usr/local/etc/freenginx/mime.types-dist → /usr/local/etc/freenginx/mime.types
…
```
rc script name is still **`nginx`**, so you’ll use:
```sh
service nginx start
service nginx stop
service nginx reload
```
So the **service name and binary are “nginx”**, but the config lives in an **`freenginx`** directory. That’s the main thing to remember.
* * *
## Step 8 – Migrate nginx configuration to freenginx
Now copy your previous nginx configs into the freenginx directory.
* `include /usr/local/etc/nginx/conf.d/*.conf;`
should become:
* `include /usr/local/etc/freenginx/conf.d/*.conf;`
2. Double-check SSL key/cert paths, upstream sockets, etc., but these usually aren’t nginx/freenginx-specific.
If you used `conf.d`\-style includes or extra files, check paths inside `nginx.conf`:You can adjust this manually with `vi` or use `sed`:
```sh
sed -i '' 's#/usr/local/etc/nginx#/usr/local/etc/freenginx#g' /usr/local/etc/freenginx/nginx.conf
sed -i '' 's#/usr/local/etc/nginx#/usr/local/etc/freenginx#g' /usr/local/etc/freenginx/*.conf
```
Ensure the main config is what you expect:
```sh
ls -l /usr/local/etc/freenginx/nginx.conf
```
Copy your old nginx config over:
```sh
cp -a /usr/local/etc/nginx/* /usr/local/etc/freenginx/
```
If freenginx already created default configs, back those up:
```sh
cd /usr/local/etc
mkdir -p freenginx.default
cp -a freenginx/* freenginx.default/ 2>/dev/null || true
```
* * *
## Step 9 – Keep or update rc.conf
Because the rc script name stays `nginx`, your existing rc.conf entry is still correct:
```sh
nginx_enable="YES"
```
If it’s missing, add it:
```sh
sysrc nginx_enable=YES
```
This ensures freenginx will start at boot, just as nginx did – using the standard FreeBSD rc system described in the Handbook.
* * *
## Step 10 – Test the freenginx configuration
Before starting the service, test the config with the freenginx binary:
```sh
/usr/local/sbin/nginx -t -c /usr/local/etc/freenginx/nginx.conf
```
If the port installed freenginx so that `nginx` picks up the correct default config directory, you can usually just do:
```sh
nginx -t
```
Look for:
```text
nginx: the configuration file /usr/local/etc/freenginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/freenginx/nginx.conf test is successful
```
If you see errors:
* Check for leftover `/usr/local/etc/nginx` paths
* Check for modules you had loaded via `load_module` that may not be present in your freenginx build; either enable them at `make config` time (ports) or remove those `load_module` lines.
* * *
## Step 11 – Start freenginx
If `nginx -t` passes, start the service:
```sh
service nginx start
```
Verify it’s running:
```sh
service nginx status
ps auxw | grep nginx
sockstat -4 -l | egrep '(:80|:443)'
```
Test from the same machine:
```sh
curl -v http://127.0.0.1/
curl -vk https://127.0.0.1/ # if using TLS
```
And from a client machine (using your actual hostname):
```sh
curl -v https://your-domain.example
```
You should see the same content you served with nginx, because freenginx is using the same configuration.
* * *
## Step 12 – Check logs and modules
Inspect error logs for any surprises:
```sh
tail -n 50 /var/log/nginx/error.log
```
Things to look for:
* Unknown directives → often mean a missing module or syntax change
* Permission errors → maybe freenginx runs as a different user (usually still `www` on FreeBSD)
If you deliberately want newer features (HTTP/3, certain third-party modules), double-check which options your freenginx port was built with (`make config` or look at the FreshPorts options list).
* * *
## Step 13 – Optional cleanup and hardening
Once you’re confident everything works:
1. Consider enabling additional security headers, stronger TLS config, etc., just as you would on nginx proper.
Run a package and vulnerability audit regularly (per the Handbook):
```sh
pkg audit -F
pkg upgrade
```
Ensure permissions are tight:
```sh
chown -R root:wheel /usr/local/etc/freenginx
chmod -R o-rwx /usr/local/etc/freenginx
chown -R www:www /usr/local/www # if www user should own content
```
Remove the old nginx config directory if you no longer need it (you still have your backup):
```sh
rm -rf /usr/local/etc/nginx
```
* * *
## Step 14 – Rolling back to nginx (if needed)
If you hit some obscure module issue or bug and want to roll back:
Test and start:
```sh
nginx -t
service nginx start
```
Restore the old config:
```sh
mkdir -p /usr/local/etc/nginx
cp -a /root/nginx-backup/etc-nginx-/* /usr/local/etc/nginx/
```
Reinstall nginx:
```sh
pkg install nginx
```
Remove freenginx:
```sh
pkg delete freenginx
```
Stop freenginx:
```sh
service nginx stop
```
* * *
## Closing thoughts
On FreeBSD, swapping nginx for freenginx is mostly about:
* **Package substitution** (`nginx` → `freenginx`)
* **Config directory change** (`/usr/local/etc/nginx` → `/usr/local/etc/freenginx`)
* **Keeping the same rc service name** (`service nginx ...`)