---
title: "Host WordPress on a VPS: Nginx, PHP 8.3 and MariaDB | StreetHosting"
description: "Install WordPress on an Ubuntu VPS with Nginx, PHP FPM 8.3, MariaDB, HTTPS via Certbot, correct permissions, OPcache, page cache and optional Redis."
url: "https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx"
type: "page"
language: "en-US"
---

VPS · 9 min · Intermediate

Published on Sep 28, 2026 · Updated on Sep 28, 2026

# WordPress from scratch on a VPS with Nginx, PHP FPM and MariaDB

Installing WordPress by hand, with no control panel, gives you full control over performance and security. The path is short: Nginx, PHP FPM and MariaDB on Ubuntu 24.04, a dedicated database, HTTPS and two layers of cache.

By [Equipe StreetHosting](https://streethosting.com.br/en/autores#equipe-streethosting) · StreetHosting infrastructure and support team

[Linux administration](https://streethosting.com.br/en/guides/topics/linux) [Databases](https://streethosting.com.br/en/guides/topics/databases) [Network, DNS and domains](https://streethosting.com.br/en/guides/topics/networking) [Deploying and running apps](https://streethosting.com.br/en/guides/topics/deploy)

Summarize with:

[](https://chat.openai.com/?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "ChatGPT") [](https://claude.ai/new?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Claude") [](https://www.google.com/search?udm=50&aep=11&q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Google AI Mode") [](https://x.com/i/grok?text=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Grok") [](https://www.perplexity.ai/search/new?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Perplexity")

Share:

[](https://x.com/intent/tweet?text=Host%20WordPress%20on%20a%20VPS%3A%20Nginx%2C%20PHP%208.3%20and%20MariaDB&url=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx "Share on X") [](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx "Share on Facebook") [](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx "Share on LinkedIn") [](https://wa.me/?text=Host%20WordPress%20on%20a%20VPS%3A%20Nginx%2C%20PHP%208.3%20and%20MariaDB%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fhost-wordpress-on-vps-nginx "Share on WhatsApp")

For agents: Copy as Markdown [.md](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx.md)

In this guide 8 sections

* [The stack you will build](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#pilha)
* [Nginx, PHP FPM 8.3 and extensions](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#instalar-pacotes)
* [The MariaDB database](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#banco)
* [Files, configuration and salts](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#arquivos-configuracao)
* [Server block and permissions](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#server-block)
* [HTTPS with Certbot and the installer](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#https)
* [OPcache, page cache and Redis](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#otimizacoes)
* [Which VPS to use](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#qual-vps)

Quick answer

To **host WordPress on a VPS**, install Nginx, PHP FPM 8.3 with the extensions WordPress requires and MariaDB, create a dedicated database and user, download WordPress, fill in the configuration with the credentials and fresh salts, point an Nginx server block at the folder and issue HTTPS with Certbot. Then enable OPcache and page cache; Redis as object cache is optional.

## The stack you will build[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#pilha)

Everything here runs on Ubuntu 24.04 LTS, which ships PHP 8.3 and MariaDB 10.11 in the official repositories. Both versions are within what WordPress recommends today: PHP 8.3 or higher and MariaDB 10.11 or higher. On Ubuntu 22.04 the default PHP is 8.1 and MariaDB is 10.6, both below the recommendation; prefer installing on a fresh VPS with 24.04.

| Component        | Version on Ubuntu 24.04 | Role                                                                   |
| ---------------- | ----------------------- | ---------------------------------------------------------------------- |
| Nginx            | 1.24                    | Accepts connections, serves static files and passes PHP requests along |
| PHP FPM          | 8.3                     | Runs WordPress in processes that stay resident in memory               |
| MariaDB          | 10.11                   | Stores posts, users, orders and settings                               |
| Certbot          | Nginx plugin            | Issues and renews the Let's Encrypt certificate                        |
| Redis (optional) | 7.x                     | Object cache for repeated database queries                             |

Before you start, check three things: the domain already [points to the VPS IP through DNS](https://streethosting.com.br/en/guides/vps/point-domain-to-vps), you log in over SSH with a sudo user, and the UFW firewall allows SSH. If the plan is to bring over a site that already exists, the installation is the same and copying the data follows the guide on [migrating WordPress to a VPS](https://streethosting.com.br/en/guides/vps/migrate-wordpress-to-vps).

## Nginx, PHP FPM 8.3 and extensions[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#instalar-pacotes)

One command installs the whole stack with the extensions WordPress requires or recommends:

`sudo apt update sudo apt install -y nginx mariadb-server php8.3-fpm php8.3-mysql \ php8.3-curl php8.3-xml php8.3-mbstring php8.3-intl php8.3-zip \ php8.3-gd php8.3-opcache php-imagick sudo ufw allow 'Nginx Full'`

* **mysql:** provides mysqli, the one extension without which WordPress will not even start.
* **curl, xml, mbstring, intl and zip:** API calls and updates, parsing XML and feeds, accented text, locale formatting and installing plugins from a zip file.
* **gd and imagick:** generate thumbnails for uploaded images. Imagick preserves quality better and handles more formats.
* **opcache:** keeps compiled PHP in memory. It is the cheapest performance gain on the list.

Extensions like exif, fileinfo and openssl already ship in the common PHP package. Next, create a file with the limits WordPress usually needs for media uploads and larger plugins:

`# /etc/php/8.3/fpm/conf.d/99-wordpress.ini upload_max_filesize = 64M post_max_size = 64M memory_limit = 256M`

Apply it with `sudo systemctl reload php8.3-fpm`. Your own files in `conf.d` survive package updates, unlike edits to the original `php.ini`.

## The MariaDB database[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#banco)

Run `sudo mariadb-secure-installation` and accept removing anonymous users, the test database and remote root login. Then create the database and a user that can only see that database:

`sudo mariadb CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'wp_usuario'@'localhost' IDENTIFIED BY 'SENHA_FORTE_AQUI'; GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_usuario'@'localhost'; FLUSH PRIVILEGES; EXIT;`

Generate the password with `openssl rand -base64 24`. The user only exists for local connections, so port 3306 stays closed in the firewall: WordPress and the database talk through the socket on the same machine. More database security details are in [installing MariaDB or MySQL on an Ubuntu VPS](https://streethosting.com.br/en/guides/vps/install-mariadb-mysql-ubuntu-vps).

The default MariaDB buffer pool is 128 MB. If the database grows past that, raise it in a file of your own, such as `/etc/mysql/mariadb.conf.d/99-wordpress.cnf`, with the `[mysqld]` section and the line `innodb_buffer_pool_size = 512M`, then restart the service. Queries served from memory never touch the disk.

## Files, configuration and salts[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#arquivos-configuracao)

Download the current release straight from wordpress.org and copy it into the site folder:

`cd /tmp curl -LO https://wordpress.org/latest.tar.gz tar -xzf latest.tar.gz sudo mkdir -p /var/www/seu-dominio.com.br sudo cp -a wordpress/. /var/www/seu-dominio.com.br/ cd /var/www/seu-dominio.com.br sudo cp wp-config-sample.php wp-config.php sudo nano wp-config.php`

In `wp-config.php`, fill in the database details and add two protections above the line that says to stop editing:

`define( 'DB_NAME', 'wordpress' ); define( 'DB_USER', 'wp_usuario' ); define( 'DB_PASSWORD', 'SENHA_FORTE_AQUI' ); define( 'DB_HOST', 'localhost' ); define( 'DISALLOW_FILE_EDIT', true ); define( 'WP_POST_REVISIONS', 20 );`

The first disables the theme and plugin code editor inside the dashboard, which is the first place an attacker holding an administrator password uses to plant a backdoor. The second caps the revisions kept per post, which keeps the database from ballooning.

Now the salts. They are the keys that sign login cookies, and the sample file ships with the text `put your unique phrase here` on the eight lines from `AUTH_KEY` to `NONCE_SALT`. Generate a unique set with `curl -s https://api.wordpress.org/secret-key/1.1/salt/` and replace the eight lines with the output. Rotating the salts later invalidates every open session, which is exactly what you want after suspecting a password leak.

## Server block and permissions[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#server-block)

PHP FPM runs as `www-data`, and the simplest way for WordPress to update itself and its plugins is for that user to own the files, with the configuration file closed off to everyone else:

`sudo chown -R www-data:www-data /var/www/seu-dominio.com.br sudo find /var/www/seu-dominio.com.br -type d -exec chmod 755 {} + sudo find /var/www/seu-dominio.com.br -type f -exec chmod 644 {} + sudo chmod 640 /var/www/seu-dominio.com.br/wp-config.php`

The cost of this model is that a vulnerable plugin can modify site files. For several sites on the same VPS, give each one its own user and its own PHP FPM pool, as shown in the guide on [several sites on the same VPS with Nginx](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps), so a breach does not spread from one site to another. Create the server block at `/etc/nginx/sites-available/seu-dominio.com.br`:

`server { listen 80; server_name seu-dominio.com.br www.seu-dominio.com.br; root /var/www/seu-dominio.com.br; index index.php; client_max_body_size 64M; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location = /xmlrpc.php { deny all; } location ~ /\.(?!well-known) { deny all; } location ~* \.(css|js|jpg|jpeg|png|gif|webp|avif|svg|ico|woff2)$ { expires 30d; access_log off; } }`

The `try_files` directive makes permalinks work without .htaccess, the deny blocks hide dotfiles and xmlrpc.php, and the last block lets the browser keep images, CSS and JavaScript for 30 days. Enable it and test before reloading:

`sudo ln -s /etc/nginx/sites-available/seu-dominio.com.br /etc/nginx/sites-enabled/ sudo rm /etc/nginx/sites-enabled/default sudo nginx -t && sudo systemctl reload nginx`

## HTTPS with Certbot and the installer[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#https)

Issue the certificate before opening the installer. That way WordPress stores the site address with https from the first minute and you never have to fix URLs in the database later.

`sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d seu-dominio.com.br -d www.seu-dominio.com.br sudo certbot renew --dry-run`

Certbot adds the port 443 block to the server block and sets up the HTTP to HTTPS redirect; if it asks, choose to redirect. Renewal is handled by a systemd timer. Renewal details, multiple domains and security headers are covered in [SSL certificate with Let's Encrypt and Nginx](https://streethosting.com.br/en/guides/vps/lets-encrypt-ssl-certificate-vps).

Open `https://seu-dominio.com.br` in the browser and finish the installer: language, site title, administrator user and password.

* Administrator user with a real name, never admin
* Long password generated by the installer itself or by a password manager
* Administrator email that someone actually reads
* Permalinks set to post name, under Settings
* Automatic plugin updates turned on for the plugins you trust

## OPcache, page cache and Redis[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#otimizacoes)

### OPcache and PHP processes[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#opcache)

Add the OPcache settings to the same `99-wordpress.ini` and reload PHP FPM:

`opcache.enable = 1 opcache.memory_consumption = 192 opcache.interned_strings_buffer = 16 opcache.max_accelerated_files = 20000 opcache.validate_timestamps = 1 opcache.revalidate_freq = 60`

With revalidation every 60 seconds, a plugin update can take up to a minute to show up; reload PHP FPM if you need it right away. The default pool ships with `pm.max_children = 5`, low for any site with real traffic. Find out how much each process uses:

`ps -o rss= -C php-fpm8.3 | awk '{s+=$1; n++} END {print s/n/1024 " MB por processo"}'`

Divide the RAM left over for PHP, after subtracting the system and the database, by that figure, and use the result as the ceiling for `pm.max_children` in `/etc/php/8.3/fpm/pool.d/www.conf`. The vCPU count limits how many processes actually work at the same time; the RAM ceiling keeps a spike from pushing the VPS into swap.

### Page cache in Nginx[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#cache-pagina)

With FastCGI cache, Nginx stores the generated HTML and serves the next visit without calling PHP or the database. Create the cache zone:

`# /etc/nginx/conf.d/wordpress-cache.conf fastcgi_cache_path /var/cache/nginx/wordpress levels=1:2 keys_zone=WORDPRESS:64m inactive=60m max_size=1g; fastcgi_cache_key "$scheme$request_method$host$request_uri";`

Certbot turned the original server block into the port 443 block. In it, before the location blocks, define when to skip the cache, and replace the PHP block with this version with caching enabled:

`set $sem_cache 0; if ($request_method = POST) { set $sem_cache 1; } if ($query_string != "") { set $sem_cache 1; } if ($request_uri ~* "/wp-admin/|/wp-login.php|/carrinho/|/finalizar-compra/|/minha-conta/") { set $sem_cache 1; } if ($http_cookie ~* "wordpress_logged_in|wp-postpass|comment_author|woocommerce_items_in_cart") { set $sem_cache 1; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; fastcgi_cache WORDPRESS; fastcgi_cache_valid 200 301 302 10m; fastcgi_cache_bypass $sem_cache; fastcgi_no_cache $sem_cache; add_header X-Cache $upstream_cache_status; }`

Test with `curl -sI https://seu-dominio.com.br | grep -i x-cache` twice: the first response comes back as MISS and the second as HIT. Logged-in users, cart and checkout never enter the cache; adjust the store paths if your WooCommerce uses different URLs.

This cache is not cleared on its own when you publish or edit a post: the old page can show up for up to 10 minutes. Accept that window, shorten the validity or install a purge plugin that supports FastCGI cache. If you would rather not touch Nginx, a cache plugin that generates static HTML gives a similar gain.

### Redis as object cache (optional)[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#redis)

The object cache keeps database query results between requests. It does not speed up pages already served from the page cache, but it makes a difference in everything dynamic: dashboard, logged-in users, store. Install it with `sudo apt install -y redis-server php-redis`, reload PHP FPM, install the Redis Object Cache plugin and enable it under Settings. Password, max memory and eviction policy settings are in [installing Redis on an Ubuntu VPS](https://streethosting.com.br/en/guides/vps/install-redis-ubuntu-vps).

## Which VPS to use[](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#qual-vps)

This full stack, with Nginx, PHP FPM, MariaDB and Redis, gets comfortable from 4 GB of RAM. A small blog with caching runs on 2 GB, with a few PHP processes and swap as a safety net. In the [Xeon VPS](https://streethosting.com.br/en/vps/xeon) line, the tiers that come up most for WordPress are:

* **3 vCPU, 4 GB and 40 GB NVMe for R$ 43.00:** an active blog or a company site with page cache.
* **6 vCPU, 8 GB and 80 GB NVMe for R$ 77.00:** a small WooCommerce store or a few sites on the same VPS.
* **9 vCPU, 16 GB and 160 GB NVMe for R$ 145.00:** a store with a large catalog, many logged-in users or a database already past a few gigabytes.

The Xeon line delivers more vCPU for the money, which suits PHP FPM, since it serves several pages in parallel, and comes with Anti-DDoS Enterprise, NVMe and an average latency of 20 ms in Brazil from São Paulo. When the bottleneck is the response time of pages that cannot be cached, such as checkout and the dashboard, the Ryzen 9 9950X VPS with clocks up to 5.7 GHz responds faster; the 4 vCPU and 8 GB DDR5 plan costs R$ 114.00. The full visits-per-plan math, covering both lines, is in [how to choose a VPS for WordPress](https://streethosting.com.br/en/guides/vps/choose-vps-for-wordpress).

In this guide

* [The stack you will build](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#pilha)
* [Nginx, PHP FPM 8.3 and extensions](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#instalar-pacotes)
* [The MariaDB database](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#banco)
* [Files, configuration and salts](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#arquivos-configuracao)
* [Server block and permissions](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#server-block)
* [HTTPS with Certbot and the installer](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#https)
* [OPcache, page cache and Redis](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#otimizacoes)
* [Which VPS to use](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx#qual-vps)

## Frequently asked questions

Do I need a hosting control panel to run WordPress on a VPS?

No. Nginx, PHP FPM and MariaDB installed from the terminal are enough, and more memory is left for the site. A control panel helps anyone managing dozens of client sites, but it adds resource usage and, in many cases, a license cost.

Which PHP version should I use with WordPress?

WordPress recommends PHP 8.3 or higher, which is the default version on Ubuntu 24.04. Before switching the version on an existing site, test the theme and plugins on a copy, because older plugins may not be compatible.

Nginx or Apache for WordPress?

Both work. Nginx with PHP FPM uses less memory per connection and serves static files more efficiently, which is why it became the standard on a VPS. The practical difference is that Nginx ignores .htaccess: rules from security and redirect plugins have to go into the server block.

How do I make WordPress faster on a VPS?

Enable OPcache, use page cache in Nginx or through a plugin, match the number of PHP FPM processes to the available RAM and keep the database on NVMe. Redis as object cache helps sites with many logged-in users and WooCommerce stores.

Is it safe to block xmlrpc.php?

For most sites, yes, and it closes a common entry point for brute-force attacks. The file is used by the WordPress mobile app, by remote publishing and by some integration plugins. If you use any of those, allow the file and protect the login with Fail2ban or rate limiting.

Next step

See Xeon VPS

Xeon VPS for steady workloads, automation and long-running projects.

[See Xeon VPS](https://streethosting.com.br/en/vps/xeon)

[See VPS plans Root VPS in Brazil with NVMe and Anti-DDoS.](https://streethosting.com.br/en/vps) [See Ryzen VPS Ryzen 9 9950X VPS in São Paulo with root access, NVMe and gamer Anti-DDoS.](https://streethosting.com.br/en/vps/ryzen)

## Related guides

[VPS Beginner VPS for WordPress: how to pick RAM, CPU and disk Sizing a VPS for WordPress means adding up the memory of PHP, the database and the system, working out how many pages miss the cache and leaving room for uploads to grow. Here is the math and a table of visits per plan. 10 min Read guide](https://streethosting.com.br/en/guides/vps/choose-vps-for-wordpress) [VPS Intermediate How to install WordPress with Docker Compose on a VPS With Docker Compose, WordPress and its database come up with a single command and the data lives in volumes that survive any update. See the full file, the HTTPS proxy and the backup routine. 9 min Read guide](https://streethosting.com.br/en/guides/vps/install-wordpress-docker-vps) [VPS Intermediate How to migrate a WordPress site to a VPS without losing traffic Moving WordPress to a VPS can improve performance and control, but you need the right order of steps to avoid downtime. Here is a simple, safe process. 2 min Read guide](https://streethosting.com.br/en/guides/vps/migrate-wordpress-to-vps)

[← Back to the Guide Center](https://streethosting.com.br/en/guides)
