Setting up server-side XSLT on NGINX and Ubuntu

Moving to server-side XSLT is easier and harder than I expected

21 Oct 2025 - This is no longer strictly true. I ended up moving everything to an org mode-based workflow in October 2025 for a variety of reasons. I'm leaving this here for posterity

This site is built with XML and XSLT For the last couple of years, I used client-side processing because it literally took no additional configuration on my end other than telling nginx what an XML file is. I decided that it was time to change this.

Note: I'm using Ubuntu for this for reasons that don't warrant going into here, but the same steps should also work for Debian

Install the server module

Install the libnginx-mod-http-xslt-filter module by typing apt install libnginx-mod-http-xslt-filter as root or via su. It might already be installed (it was on mine).

Near the top of your nginx.conf file, add the following line to activate the module

/etc/nginx.conf
include /etc/nginx/modules-enabled/50-mod-http-xslt-filter.conf;

Restart nginx and, if there are no errors, it's time to configure your /etc/nginx/sites-available/sitename.example.

Configuring your site

If your site is like mine, then this part gets tedious.

In /etc/nginx/sites-available/sitename.example (replace sitename.example with whatever your site name is), find the location directive for the root of your site. Add the following:

xslt_stylesheet /var/somefolder/path-to.xsl;

Where /var/somefolder is the real full path to the XSLT file on your server. Restart nginx and marvel at how nothing looks right because nginx is now applying one XSL to everything. That's probably not what we want (it's definitly not what <em>I</em> want. To fix this, we need to add lots more location directives for every different XSLT file that we want to use. And since I sprinkled them everywhere, I need <em>lots</em> of location directives. They all look something like this.

sites-available/example.com

        location /cookiefaq.xml {
                xslt_stylesheet /path/to/webroot/cookiefaq.xsl;
        }
        location /books {
                xslt_stylesheet /path/to/webroot/books/books.xsl;
        }
        location /inventory/amiibo.xml {
                xslt_stylesheet /path/to/webroot/inventory/amiibo.xsl;
        }

Obviously /path/to/webroot should reflect your actual system path the XSLT files live in.

Restart nginx again. If you have no errors, then, congratulations! Everything looks identical! Which may seem like a huge waste of time and energy, but now people who are using web browsers with scripting turned off (or if scripting isn't available) can see the site (more-or-less) as intended.

This article's fake tags are

  • XML and XSLT
  • Server-side
  • howdid

This article was posted on 17 Jul 2023 and I haven't looked at it since.