How to Replace Nginx with Freenginx on FreeBSD: A Complete Step-by-Step Guide

Learn how to replace Nginx with Freenginx on FreeBSD in a smooth, step-by-step migration. This guide walks you through installation, config transfer, testing, and optimization so you can upgrade your web server with confidence and zero headaches.

How to Replace Nginx with Freenginx on FreeBSD: A Complete Step-by-Step Guide

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:

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:

grep nginx /etc/rc.conf /etc/rc.conf.local 2>/dev/null

You’ll probably see:

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.

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:

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.:

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:

service nginx stop
ps auxw | grep nginx

If any stray worker/master processes remain, kill them:

pkill nginx || true

Make sure ports 80/443 are clear:

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.

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.

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.

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:

/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:

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;
  1. 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:

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:

ls -l /usr/local/etc/freenginx/nginx.conf

Copy your old nginx config over:

cp -a /usr/local/etc/nginx/* /usr/local/etc/freenginx/

If freenginx already created default configs, back those up:

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:

nginx_enable="YES"

If it’s missing, add it:

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:

/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:

nginx -t

Look for:

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:

service nginx start

Verify it’s running:

service nginx status
ps auxw | grep nginx
sockstat -4 -l | egrep '(:80|:443)'

Test from the same machine:

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):

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:

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):

pkg audit -F
pkg upgrade

Ensure permissions are tight:

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):

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:

nginx -t
service nginx start

Restore the old config:

mkdir -p /usr/local/etc/nginx
cp -a /root/nginx-backup/etc-nginx-<timestamp>/* /usr/local/etc/nginx/

Reinstall nginx:

pkg install nginx

Remove freenginx:

pkg delete freenginx

Stop freenginx:

service nginx stop

Closing thoughts

On FreeBSD, swapping nginx for freenginx is mostly about:

  • Package substitution (nginxfreenginx)
  • Config directory change (/usr/local/etc/nginx/usr/local/etc/freenginx)
  • Keeping the same rc service name (service nginx ...)