wordpress-nginx is a config kit, not a plugin, and it replaces your whole Nginx directory
Nginx server configurations for WordPress
At a glance
- What is it?
- SpinupWP's wordpress-nginx collects the Nginx server configurations used in its guide for installing WordPress on Ubuntu 24.04, as four example site files covering single site, subdirectory multisite, subdomain multisite and FastCGI caching. Adopting it means backing up /etc/nginx and copying the kit in, then picking a PHP upstream per server block.
- Who is it for?
- wordpress-nginx is worth taking if you run WordPress on your own Ubuntu server with Nginx and you want a known-good set of server blocks with caching, file exclusions and security defaults already written, rather than assembling one from fragments. It is the wrong tool if your Nginx setup is shared with other applications, if you cannot replace /etc/nginx wholesale, or if you want per site PHP versions without also running the extra php-fpm services.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly DIGITAL Command Language, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Four example sites, assembled from published best practices
This repository is a config kit rather than an application. It holds the Nginx configurations used in the SpinupWP guide to install WordPress on Ubuntu 24.04, and it says plainly that it contains best practices from various sources, naming the WordPress Developer Resources page on Nginx and the H5BP server configuration collection as the places the guidance came from.
The useful part is that the examples are named after the situations they cover, and there are four of them:
* multisite-subdirectory.com, a WordPress multisite install using subdirectories * multisite-subdomain.com, a WordPress multisite install using subdomains * single-site.com, a WordPress single site install * single-site-with-caching.com, a WordPress single site install with FastCGI caching
Each is a file in the sites-available directory, which means they are complete server blocks you can copy and adjust rather than snippets you have to stitch together. That distinction is the reason this kind of repository is useful at all: the difficult part of a WordPress Nginx setup is not any single directive, it is the combination of PHP location blocks, static asset caching, upload path handling and the WordPress rewrite rules, and having one file that already agrees with itself saves a lot of trial and error.
The licensing is BSD-3-Clause, which permits reuse and modification with the notice retained, including commercial use.
Adopting the kit means replacing /etc/nginx wholesale
The usage instructions are explicit about the shape of the change. You can use the sample configurations as reference or directly by replacing your existing nginx directory, and the steps below describe the replace-in-place route.
Start by moving the existing configuration out of the way:
`sudo mv /etc/nginx /etc/nginx.backup`Then copy the kit into place and symlink the default file from sites-available into sites-enabled, which sets up a catch-all server block:
`sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default`Copy one of the examples to your own domain name:
`sudo cp /etc/nginx/sites-available/single-site.com /etc/nginx/sites-available/yourdomain.com`Edit the copy, paying attention to the server name and the paths, then enable it the same way as the default:
`sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/yourdomain.com`Before reloading, test the configuration, and only restart if it passes:
`sudo nginx -t``sudo systemctl reload nginx.service`That last pair is the safe habit. A reload rather than a restart keeps existing connections alive, and the test command is what stops a typo in a server name from taking the whole web server down.
The catch-all default block answers unknown domains with 444
One line in the usage section deserves more attention than it gets. Symlinking the default file from sites-available to sites-enabled sets up a catch-all server block, and the stated purpose is that unrecognised domains return a 444 response.
444 is an nginx status code with no response body at all. The connection is closed without a status line, which is useful for two reasons. It does not tell a scanner that a web server is running, since there is no error page and no server header, and it does not serve the default landing page of whatever happens to be on port 80 for an unrelated domain.
For a shared host or a machine where several domains point at the same IP, that is the difference between a stray request landing on someone's site and the request going nowhere. It is also why the kit asks you to symlink the default file before you enable your own site: without it, a request for a domain that has no server block will be served by whatever the first default server block is.
The order of operations in the usage section therefore matters. The catch-all goes in first, then your site, and only then the configuration is tested and reloaded.
PHP version selection happens through upstream names, not per site services
The php-fpm pool configuration lives in global/php-pool.conf and defaults to PHP 8.3. If you want the default pool to run a different PHP version, you modify that file. Additional PHP version upstream definitions can be added to the upstreams directory, and a PHP 8.4 sample is provided there.
The mechanism is a named upstream. The example configuration for single-site.com passes PHP requests like this:
fastcgi_pass $upstreamThe $upstream variable points at whatever the default pool defines, so switching the site to the 8.4 service is a one line change:
fastcgi_pass php84as long as the php8.4-fpm service is actually running.
That is the useful part of the design. Because the upstream is a name rather than a socket path or a port, different server blocks can execute different PHP versions at the same time, so one site can stay on the default pool while another runs on 8.4. Sites that must stay on one version for compatibility reasons and sites that want the newest runtime can coexist in the same Nginx instance.
The trade-off is that the extra PHP services are your responsibility. The kit gives you the upstream definitions and the naming convention, but it does not install or start a second php-fpm service, and a server block pointing at an upstream whose service is down will fail at request time rather than at configuration test time.
conf.d, global, sites-available and sites-enabled follow the Debian layout
The kit's structure is based on the conventions used by a default Nginx install on Debian, which is what makes it drop-in rather than a parallel arrangement you have to learn:
.
βββ conf.d
βββ global
βββ server
βββ sites-available
βββ sites-enabledconf.d holds configurations for additional modules. global holds the configurations that sit inside the http block, and global/server holds those that sit inside the server block. Within global/server, the defaults.conf file should be included on the majority of sites and contains sensible defaults for caching, file exclusions and security, with additional .conf files includable on a per-site basis.
sites-available holds the configurations for individual sites, the virtual hosts. sites-enabled holds symlinks into sites-available, and only the symlinked sites are loaded. That last rule is the mechanism that makes enabling and disabling a site a single ln or rm operation with no config editing, and it is the same model as Apache's sites-available and sites-enabled pair.
At the repository root there is an nginx.conf, a dhparam directory for Diffie-Hellman parameters, and the upstreams folder where the PHP version definitions live. The default branch is develop, there are no GitHub releases, and the last push was on 2026-10-16, so this is a configuration set that changes without a version history to track.
Each site is expected to own its cache, logs and public directories
The configs assume a particular on-disk layout for a site, and it is worth checking against your own before copying a config:
.
βββ yourdomain1.com
βββ cache
βββ logs
βββ public
βββ yourdomain2.com
βββ cache
βββ logs
βββ publicThree directories per site, with cache and logs inside the site root rather than in a shared location. That arrangement is what lets the FastCGI caching variant work, since each site needs somewhere to store its own cache, and it keeps log files separable per domain, which is the difference between reading one site's errors and reading all of them.
For a single site installation the paths in the example files will point at the WordPress directory you actually used, so this is the part you have to edit rather than accept. The instructions say to pay close attention to the server name and paths when you edit the copy, which is the shortest possible warning about the two things that will be wrong.
One practical note for anyone running this in production: the dhparam directory at the root of the kit is for the Diffie-Hellman parameters used to negotiate the key exchange, and generating a fresh set rather than shipping a shared one is the usual advice. The kit provides the place for that file, and the generation step is on you.
Editorial conclusion
wordpress-nginx is worth taking if you run WordPress on your own Ubuntu server with Nginx and you want a known-good set of server blocks with caching, file exclusions and security defaults already written, rather than assembling one from fragments. It is the wrong tool if your Nginx setup is shared with other applications, if you cannot replace /etc/nginx wholesale, or if you want per site PHP versions without also running the extra php-fpm services. Verify first that sudo nginx -t passes after you symlink your site, that the catch-all default block is in place so unknown domains return 444, and that the php-fpm pool you point $upstream at is actually running on the machine.
Frequently asked questions
How do I install the wordpress-nginx configs on my server?
Back up the existing directory with sudo mv /etc/nginx /etc/nginx.backup, copy the kit into /etc/nginx, symlink the default file into sites-enabled, copy one of the example sites to your domain name, edit it, symlink it into sites-enabled, then run sudo nginx -t and reload with sudo systemctl reload nginx.service.
Which example configurations are included in the wordpress-nginx kit?
Four: single-site.com for a single WordPress site, single-site-with-caching.com for the same with FastCGI caching, multisite-subdirectory.com for a multisite install using subdirectories, and multisite-subdomain.com for a multisite install using subdomains.
How do I run a different PHP version for one site?
Add an upstream definition in the upstreams folder, a PHP 8.4 sample is provided, then change that site's fastcgi_pass from $upstream to the upstream name such as php84. The corresponding php-fpm service has to be running on the machine.
What does the default server block in wordpress-nginx do?
Symlinking the default file from sites-available to sites-enabled sets up a catch-all server block, so unrecognised domains return a 444 response with no body rather than being served by some other site.
Which PHP version does the php-fpm pool default to?
The pool configuration in global/php-pool.conf defaults to PHP 8.3, and it is that file you modify if you want the default pool to run a different version.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/spinupwp-wordpress-nginx)Was this useful?