My first WordPress installation on Nginx was a disaster. Coming from years of Apache experience, I
assumed the configuration would be similar—just different syntax. Three hours later, I had a site
that loaded the homepage but returned 404 errors for every other page. Permalinks weren’t working
because Nginx doesn’t read .htaccess files, and I hadn’t configured the equivalent rewrite rules.

Installing WordPress on Nginx requires understanding how Nginx differs fundamentally from Apache.
It’s not just different syntax for the same concepts—it’s a different architectural approach. But
once you understand those differences, Nginx offers superior performance, especially for
high-traffic sites. The configuration is actually cleaner and more maintainable once you know what
you’re doing.

This guide walks through every step of installing WordPress on Nginx, from server preparation through
security hardening. You’ll understand not just what to configure, but why each configuration
matters.

Understanding the LEMP Stack

WordPress on Nginx runs on what’s called a LEMP stack: Linux, Nginx (pronounced “Engine-X,” hence the
E), MySQL/MariaDB, and PHP. Each component plays a specific role in serving WordPress pages.

How Nginx Differs from Apache

The fundamental difference lies in how each handles requests. Apache uses a process-based or
thread-based model where each connection ties up a worker. Nginx uses an event-driven, asynchronous
model where a single worker can handle thousands of connections simultaneously.

For WordPress, this translates to Nginx being more efficient at handling concurrent connections.
During traffic spikes, Nginx maintains responsiveness while Apache might struggle with connection
limits.

The configuration difference that trips up most WordPress users: Apache reads .htaccess files in each
directory, applying rules dynamically. WordPress’s pretty permalinks rely on .htaccess rules that
redirect requests to index.php. Nginx doesn’t read .htaccess files at all—you must configure these
rules directly in server configuration files.

PHP Processing: The FPM Difference

Apache commonly runs PHP through mod_php, which embeds the PHP interpreter directly in Apache
workers. Nginx can’t do this—it needs PHP-FPM (FastCGI Process Manager), which runs PHP as a
separate service.

This separation actually offers advantages. PHP-FPM maintains its own pool of workers, configurable
independently from the web server. You can restart PHP without touching Nginx. You can tune PHP
worker counts and memory limits without affecting how Nginx handles static files.

The communication happens through either a Unix socket (faster, local only) or TCP port (allows
remote PHP processing). For WordPress on a single server, Unix sockets are the standard choice.

Server Preparation

Before installing WordPress, prepare the server environment with all necessary components properly
configured.

Starting Fresh

Begin with a fully updated system. Outdated packages introduce security vulnerabilities and
compatibility issues that cause mysterious problems later.

Update package lists with sudo apt update, then upgrade existing packages with sudo apt upgrade -y.
This ensures you’re working with current, patched software.

Install essential tools you’ll need throughout the setup: curl for downloading files, wget as an
alternative, unzip for extracting archives, and nano or your preferred text editor for configuration
files.

Installing Nginx

On Ubuntu/Debian, install Nginx from the default repositories with sudo apt install nginx -y. This
provides a stable, well-tested version.

Enable Nginx to start on boot with sudo systemctl enable nginx, then start the service with sudo
systemctl start nginx. Verify it’s running with sudo systemctl status nginx.

Test by visiting your server’s IP address in a browser. You should see the default Nginx welcome
page. If you can’t access it, check your firewall—UFW users need to allow port 80 with sudo ufw
allow ‘Nginx HTTP’.

Installing PHP-FPM

Install PHP and necessary extensions. WordPress requires several PHP extensions for full
functionality. A typical installation command for PHP 8.3 includes the core php8.3-fpm package plus
extensions for MySQL, curl, GD image processing, mbstring multibyte support, XML processing, ZIP
handling, internationalization (intl), and ImageMagick.

Verify PHP installed correctly with php -v. Check PHP-FPM is running with sudo systemctl status
php8.3-fpm (adjusting version as needed). Note the socket path—typically /run/php/php8.3-fpm.sock—as
you’ll need this when configuring Nginx.

Installing MariaDB

MariaDB is a fully compatible MySQL replacement with improved performance. Install with sudo apt
install mariadb-server -y, then enable and start the service.

Run the security hardening script with sudo mysql_secure_installation. Set a strong root password,
remove anonymous users, disallow remote root login, and remove the test database. These are basic
security steps that should never be skipped.

Configuring the Database

Create a dedicated database and user for WordPress. Never use the root account for application
database access—a compromised WordPress installation shouldn’t provide full database server access.

Creating the WordPress Database

Access MariaDB with sudo mysql -u root -p and enter your root password. Create a database with a
meaningful name and proper character set: CREATE DATABASE wordpress_db CHARACTER SET utf8mb4 COLLATE
utf8mb4_unicode_ci.

The utf8mb4 character set is essential for modern WordPress—it supports full Unicode including emoji.
The unicode_ci collation provides proper sorting for international characters.

Create a dedicated user with a strong, unique password: CREATE USER ‘wp_user’@’localhost’ IDENTIFIED
BY ‘your_secure_password_here’. Grant only necessary privileges on the WordPress database: GRANT ALL
PRIVILEGES ON wordpress_db.* TO ‘wp_user’@’localhost’. Apply changes with FLUSH PRIVILEGES and exit.

Store these credentials securely—you’ll need them during WordPress configuration. Consider using a
password manager rather than simple text notes.

Configuring Nginx for WordPress

Nginx configuration is where the Apache-mindset trip-up happens most. The server block configuration
must explicitly handle everything that .htaccess would handle automatically in Apache.

Creating the Server Block

Nginx organizes site configurations in /etc/nginx/sites-available/ with enabled sites symlinked from
/etc/nginx/sites-enabled/. Create a new configuration file for your WordPress site.

The basic structure includes a server block that specifies: which port to listen on (80 for HTTP, 443
for HTTPS), your server name (domain), the document root where WordPress files live, and the index
file (index.php for WordPress).

The Essential Directives

The most critical directive for WordPress is try_files. This tells Nginx what to do when a requested
file doesn’t exist. For WordPress pretty permalinks, the directive should be: try_files $uri $uri/
/index.php?$args;

This checks if the requested URI exists as a file, then as a directory, and finally falls back to
index.php with the original request arguments. This is exactly what the .htaccess rewrite rules
accomplish in Apache.

PHP processing requires a location block matching .php files. This block should pass requests to
PHP-FPM via the Unix socket, include FastCGI parameters, and specify the script filename to execute.

The fastcgi_pass directive needs the correct socket path from your PHP-FPM installation. Setting
fastcgi_param SCRIPT_FILENAME to $document_root$fastcgi_script_name ensures PHP knows which file to
execute.

Security Location Blocks

Add location blocks that deny access to sensitive files. Block access to hidden files (starting with
.) to prevent .git, .htaccess, and similar files from being exposed. Block direct PHP execution in
the uploads directory—if an attacker uploads a malicious PHP file, it shouldn’t be executable. Block
access to wp-config.php from the web.

Enabling and Testing

Create a symbolic link from sites-available to sites-enabled to activate your configuration. Before
reloading Nginx, always test the configuration with sudo nginx -t. This catches syntax errors that
would prevent Nginx from starting.

If the test passes, reload Nginx with sudo systemctl reload nginx. This applies the new configuration
without dropping existing connections.

Installing WordPress

With the server environment configured, download and install WordPress itself.

Downloading WordPress

Navigate to your web root (typically /var/www/) and download the latest WordPress directly from
wordpress.org using wget. Extract the archive, which creates a “wordpress” directory, then rename it
to match your intended site folder.

Working with official WordPress downloads ensures you have authentic, unmodified code. Never download
WordPress from third-party sources.

Setting Correct Permissions

File permissions are critical for security and functionality. WordPress needs write access to upload
files, install plugins, and update itself—but overly permissive permissions expose security
vulnerabilities.

Set ownership to the web server user (www-data on Ubuntu/Debian) so WordPress can write files. Set
directory permissions to 755 (owner can read/write/execute, others can read/execute) and file
permissions to 644 (owner can read/write, others can read).

After WordPress installation completes, tighten wp-config.php permissions to 640—WordPress rarely
needs to write to this file, and protecting database credentials is essential.

Running the Web Installer

Visit your domain in a browser to start the WordPress installation wizard. Select your language, then
enter the database credentials you created earlier: database name, username, password, host
(localhost for local connections), and table prefix.

Consider changing the table prefix from the default wp_ to something unique. While not a major
security measure, it does add mild obscurity against automated attacks targeting default table
names.

Complete the site information screen with your site title, admin username (never use “admin”), a
strong password, and your email address. Proceed through installation, then log into your new
WordPress dashboard.

Post-Installation Configuration

A fresh WordPress installation needs additional configuration for security and proper operation.

Setting Permalinks

Navigate to Settings > Permalinks in WordPress admin. Select “Post name” for clean, SEO-friendly
URLs. Save changes.

Verify permalinks work by creating a test post and visiting its URL. If you get 404 errors, the Nginx
try_files directive isn’t configured correctly. Review your server block configuration.

Security Headers in Nginx

Add HTTP security headers to your Nginx configuration for protection against common attacks.
X-Frame-Options SAMEORIGIN prevents clickjacking by blocking external sites from framing your pages.
X-Content-Type-Options nosniff prevents MIME-type confusion attacks. Referrer-Policy controls what
information is sent in the Referer header.

After adding headers, test the configuration and reload Nginx. Verify headers are present by checking
browser developer tools on your site.

Protecting Sensitive Files

In your Nginx configuration, add location blocks that deny direct access to WordPress files that
shouldn’t be publicly accessible. Block direct access to PHP files in wp-includes and
wp-content/uploads directories. These files should only be accessed through WordPress, not directly.

SSL/TLS Configuration

Modern sites require HTTPS. Let’s Encrypt provides free certificates with straightforward
installation.

Installing Certbot

Certbot automates Let’s Encrypt certificate issuance and renewal. Install it with sudo apt install
certbot python3-certbot-nginx -y. The nginx plugin handles certificate installation and
configuration automatically.

Run sudo certbot –nginx and follow the prompts. Select your domain, agree to terms, and choose
whether to redirect HTTP to HTTPS (recommended). Certbot modifies your Nginx configuration to add
SSL settings.

Verify automatic renewal works with sudo certbot renew –dry-run. Certbot installs a systemd timer
that handles renewal automatically, but testing confirms everything is configured correctly.

Updating WordPress Settings

After enabling HTTPS, update WordPress settings to use HTTPS URLs. In Settings > General, change both
WordPress Address and Site Address to https://. This ensures WordPress generates HTTPS links
throughout the site.

Common Issues and Solutions

Even careful installations encounter problems. These are the issues I see most frequently.

502 Bad Gateway

This error means Nginx couldn’t communicate with PHP-FPM. Either the PHP-FPM service isn’t running,
or the socket path in your Nginx configuration is wrong.

Check PHP-FPM status with sudo systemctl status php8.3-fpm. If it’s not running, start it. If it is
running, verify the socket path matches what’s in your Nginx configuration. The socket path depends
on your PHP version—check /run/php/ for actual socket files.

404 Errors Except Homepage

This is the classic permalinks problem. Nginx isn’t falling back to index.php for requests that don’t
match existing files. Verify your server block includes try_files $uri $uri/ /index.php?$args; in
the main location block.

Cannot Upload Files or Install Plugins

WordPress can’t write to necessary directories. Check ownership of wp-content with ls -la. The
directory and its contents should be owned by www-data. Fix with sudo chown -R www-data:www-data
/path/to/wordpress/wp-content.

Database Connection Errors

Verify credentials in wp-config.php exactly match what you created in MariaDB. Test the connection
manually with mysql -u wp_user -p wordpress_db—if this fails, the credentials are wrong or the user
doesn’t have proper permissions.

Verification Checklist

Before considering installation complete, verify each component works correctly.

Test permalinks by creating a post and viewing it. Test media uploads by uploading an image. Test
plugin installation by installing any plugin from the repository. Test theme installation by
switching to a different theme. Test user registration by creating a test user account.

Check Nginx error logs (/var/log/nginx/error.log) for any warnings or errors that might indicate
configuration issues not yet causing visible problems.

Conclusion

Installing WordPress on Nginx requires understanding the architectural differences from Apache,
particularly around PHP processing and URL rewriting. Once properly configured, Nginx provides
excellent performance for WordPress sites with clear, maintainable configuration files.

The key differences to remember: PHP runs through FPM as a separate service, permalinks require
explicit try_files configuration, and security settings must be configured in server blocks rather
than .htaccess files.

With this foundation, your WordPress installation is ready for content creation, plugin installation,
and further performance optimization.