nginx PHP-FPM config: example and generator
Run a PHP site (WordPress, Laravel or plain PHP) on nginx with PHP-FPM.
nginx does not run PHP itself. It passes .php files to PHP-FPM, a separate service that runs the code and returns the page. Fill in your domain, site folder and PHP version below to get a ready config for Ubuntu or Debian, then follow the steps to turn it on.
Create your config file
Type your own values. The file below updates as you type, and nothing you type leaves your browser.
server {
listen 80;
server_name example.com;
root /var/www/mysite;
index index.php index.html;
client_max_body_size 10m;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}How this setup works
Step-by-step setup
- Install the software on Ubuntu or Debian: sudo apt install nginx php-fpm.
- Put your site in /var/www/mysite.
- Save the config above as /etc/nginx/conf.d/mysite.conf.
- Check the socket exists: ls /run/php/php8.3-fpm.sock. If it does not, change the PHP version above.
- Test it: sudo nginx -t, then apply it: sudo systemctl reload nginx.
What the important lines mean
- root is the folder nginx serves files from: /var/www/mysite.
- try_files sends unknown addresses to index.php, which WordPress and Laravel need for pretty links.
- fastcgi_pass hands PHP files to PHP-FPM through the socket php8.3-fpm.sock.
- location ~ /\.ht blocks access to Apache .htaccess and .htpasswd files.
Common errors and how to fix them
- 502 Bad Gateway
- nginx cannot reach PHP-FPM. Check it is running with sudo systemctl status php8.3-fpm and that the socket path matches your PHP version.
- File not found.
- nginx reached PHP-FPM but the file does not exist. Check that root is /var/www/mysite and that the file is inside it.
- The browser downloads the .php file
- The PHP location block is not being used. Check the config was saved in /etc/nginx/conf.d and that you reloaded nginx.
- 403 Forbidden
- nginx cannot read the folder or there is no index file. Check that the folder and its parents are readable by the nginx user (www-data on Ubuntu).
Frequently asked questions
- What is the difference between a socket and port 9000 for PHP-FPM?
- Both reach PHP-FPM. A Unix socket such as /run/php/php8.3-fpm.sock works only on the same machine and is what Ubuntu and Debian packages use by default. A TCP address such as 127.0.0.1:9000 is used when PHP-FPM listens on a port, for example in some Docker setups.
- How do I find my PHP version?
- Run php -v in a terminal. Use the first two numbers, such as 8.3, in the PHP version field.
- Does this work for WordPress and Laravel?
- The try_files line is the part those need for pretty links. For Laravel, set the site folder to the project's public folder.
Free tools that help
- Common ports listSearch a list of common TCP and UDP port numbers: SSH 22, HTTP 80, HTTPS 443, MySQL 3306, PostgreSQL 5432 and more, with dev server ports.
- chmod calculatorTick read, write and execute for owner, group and others to get the chmod number, symbolic form and command. Or type 755 and see what it means.
Fix a problem with this setup
- nginx 502 Bad GatewayFix nginx 502 Bad Gateway with Node, PHP-FPM or any proxy: read the error log, check the app is running and the port or socket matches.
- nginx 403 ForbiddenFix nginx 403 Forbidden: check the folder permissions, the index file, the root path and SELinux.
- XAMPP Apache not startingWhy Apache stops right after starting in XAMPP, and how to change its port or free port 80.
More server configs
- Caddyfile reverse proxySend visitors to an app on port 3000 and get HTTPS certificates automatically.
- crontab examplesRun a script every minute, hour, day or week.
- systemd service fileRun your app in the background and start it automatically at boot.
- Apache virtual hostHost a website from a folder with Apache, with or without .htaccess.
- logrotate configKeep log files from filling your disk: rotate, compress and delete old logs on a schedule.
- fail2ban jail.localBan addresses that keep failing to log in. Choose ban time, retries and which services to protect.