## 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 ...`)