Logo

Install Nginx and PHP-FPM on a VPS

Install Nginx and PHP-FPM on a VPS

This step by step guide installs and configures Nginx with PHP-FPM to host PHP apps (WordPress, Laravel, Symfony, and more), including basic hardening, virtual hosts, and optional HTTPS via Let's Encrypt.

Prerequisites

  • SSH access to the server with root or sudo privileges
  • A domain name pointing to the server IP for HTTPS
  • Debian 12 or Ubuntu 22.04 or later

1) Update the system and install Nginx

sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx
sudo systemctl enable --now nginx
sudo systemctl status nginx --no-pager

If UFW is enabled, allow Nginx.

sudo ufw allow "Nginx Full"
sudo ufw status

2) Install PHP 8.2 and PHP-FPM with common extensions

sudo apt install -y php8.2-fpm php8.2-cli php8.2-mysql php8.2-curl php8.2-xml php8.2-gd php8.2-zip php8.2-mbstring php8.2-intl
sudo systemctl enable --now php8.2-fpm
sudo systemctl status php8.2-fpm --no-pager

Performance and security tip, verify the following in your PHP configuration.

sudo cp /etc/php/8.2/fpm/php.ini /etc/php/8.2/fpm/php.ini.bak
sudo sed -i 's/^\s*;*\s*cgi.fix_pathinfo\s*=.*/cgi.fix_pathinfo=0/' /etc/php/8.2/fpm/php.ini
sudo systemctl reload php8.2-fpm

3) Prepare the site directory and a test file

Replace example.com with your domain.

sudo mkdir -p /var/www/example.com/public
sudo chown -R www-data:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 750 {} \;
sudo find /var/www/example.com -type f -exec chmod 640 {} \;
cat <<'PHP' | sudo tee /var/www/example.com/public/index.php >/dev/null
<?php phpinfo();
PHP

4) Create an Nginx server block for PHP-FPM

Create the server block.

sudo tee /etc/nginx/sites-available/example.com >/dev/null <<'NGINX'
server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.php index.html;

    # Basic app routing
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP handling via PHP-FPM socket on Debian 12
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

    # Static files with light caching
    location ~* \.(?:css|js|jpg|jpeg|gif|png|svg|ico|webp)$ {
        try_files $uri =404;
        expires 7d;
        access_log off;
    }
}
NGINX

Enable the site and test the syntax.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t
sudo systemctl reload nginx

5) Verify PHP is rendered

From your browser, open http://example.com. You should see the PHP info page. Then remove the test file.

sudo rm -f /var/www/example.com/public/index.php

Install Certbot and the Nginx plugin, then request the certificates.

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

Check automatic renewal.

sudo systemctl status certbot.timer --no-pager
sudo certbot renew --dry-run

7) Basic hardening

  • Disable script execution in your application upload directories
  • Limit upload sizes in PHP and Nginx as needed
  • Enable Fail2ban and watch Nginx and PHP-FPM logs
sudo apt install -y fail2ban
sudo journalctl -u nginx -u php8.2-fpm -f

8) Quick troubleshooting

502 Bad Gateway after deploying PHP.

sudo systemctl status php8.2-fpm --no-pager
sudo tail -n 100 /var/log/nginx/error.log
sudo tail -n 100 /var/log/php8.2-fpm.log

PHP-FPM socket errors due to version or path mismatch.

ls -l /run/php/
# Adjust fastcgi_pass accordingly, for example unix:/run/php/php8.3-fpm.sock

Blank page or PHP downloading.

sudo nginx -t && sudo systemctl reload nginx
grep -R "fastcgi_pass" -n /etc/nginx

RHEL, AlmaLinux, or Rocky in brief

sudo dnf install -y nginx php-fpm php-cli php-mysqlnd php-gd php-zip php-xml php-mbstring php-intl
sudo systemctl enable --now nginx php-fpm
# In /etc/php-fpm.d/www.conf enable socket listening:
# listen = /run/php-fpm/www.sock
# Then in Nginx:
# fastcgi_pass unix:/run/php-fpm/www.sock;
sudo systemctl reload nginx php-fpm

Summary

  • Nginx installed and started
  • PHP-FPM 8.2 with key extensions up and running
  • Nginx server block wired to PHP-FPM via socket and tested
  • Optional HTTPS via Certbot
  • Handy hardening tips and quick troubleshooting

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members