How to Fix Common Nginx Web Server Errors
Nginx is a very popular web server these days. This article will show you some common errors when running an Nginx web server and possible solutions. This is not a complete list. If you still can’t fix the error after trying the advised solutions, please check your Nginx server logs under /var/log/nginx/
directory and search on Google to debug the problem.
Unable to connect/Refused to Connect
If you see the following error when trying to access your website:
Firefox can’t establish a connection to the server at www.example.com
or
www.example.com refused to connect
or
The site can't be reached, www.example.com unexpectedly closed the connection.
It could be that
- Nginx isn’t running. You can check Nginx status with
sudo systemctl status nginx
. Start Nginx withsudo systemctl start nginx
. If Nginx fails to start, runsudo nginx -t
to find if there is anything wrong with your configuration file. And check the journal (sudo journalctl -eu nginx
) to find out why it fails to start. - Firewall blocking ports 80 and 443. If you use the UFW firewall on Debian/Ubuntu, run
sudo ufw allow 80,443/tcp
to open TCP ports 80 and 443. If you use Firewalld on RHEL/CentOS/Rocky Linux/AlmaLinux, runsudo firewall-cmd --permanent --add-service={http,https}
, thensudo systemctl reload firewalld
to open TCP ports 80 and 443. - Fail2ban. If your server uses fail2ban to block malicious requests, it could be that fail2ban banned your IP address. Run
sudo journalctl -eu fail2ban
to check if your IP address is banned. You can add your IP address to the fail2banignoreip
list, so it won’t be banned again. - Nginx isn’t listening on the right network interface. For example, Nginx isn’t listening on the server’s public IP address.
If systemctl status nginx
shows Nginx is running, but sudo ss -lnpt | grep nginx
shows Nginx is not listening on TCP port 80/443, it could be that you deleted the following lines in the /etc/nginx/nginx.conf
file.
include /etc/nginx/conf.d/*;
So Nginx doesn’t use the virtual host files in /etc/nginx/conf.d/
directory. Add this line back.
The Connection Has Timed Out
This could mean that your server is offline, or Nginx isn’t working properly. I once had an out-of-memory problem, which caused Nginx to fail to spawn the worker processes. If you can see the following error message in /var/log/nginx/error.log
file, your server is short of memory.
fork() failed while spawning "worker process" (12: Cannot allocate memory)
404 Not Found
404 not found means Nginx can’t find the resources your web browser asks for. The reason could be:
- The web root directory doesn’t exist on your server. In Nginx, the web roor directory is configured using the
root
directive, like this:root /usr/share/nginx/linuxbabe.com/;
. Make sure your website files (HTML, CSS, JavaScript, PHP) are stored in the correct directory. - PHP-FPM isn’t running. You can check PHP-FPM status with
sudo systemctl status php7.4-fpm
(Debian/Ubuntu) orsudo systemctl status php-fpm
. - You forgot to include the
try_files $uri /index.php$is_args$args;
directive in your Nginx server config file. This directive is needed to process PHP code. - Your server has no free disk space. Try to free up some disk space. You can use the
ncdu
utility (sudo apt install ncdu
orsudo dnf install ncdu
) to find out which directories are taking up huge amount of disk space.
403 Forbidden
This error means that you are not allowed to access the request resources. Possible scenario includes:
- The website administrator blocks public access to the requested resources with an IP whitelist or other methods.
- The website could be using a web application firewall like ModSecurity, which detected an intrusion attack, so it blocked the request.
Some web applications may show a different error message when 403 forbidden happens. It might tell you that “secure connection failed”, while the cause is the same.
500 Internal Server Error
This means there is some error in the web application. It could be that
- The database server is down. Check MySQL/MariaDB status with
sudo systemctl status mysql
. Start it withsudo systemctl start mysql
. Runsudo journalctl -eu mysql
to find out why it fails to start. MySQL/MariaDB process could be killed due to out-of-memory issue. - You didn’t configure Nginx to use PHP-FPM, so Nginx doesn’t know how to execute PHP code.
- If your web application has a built-in cache, you can try flushing the app cache to fix this error.
- Your web application may produce its own error log. Check this log file to debug this error.
- Your web application may have a debugging mode. Turn it on and you will see more detailed error messages on the web page. For example, you can turn on debugging mode in the Modoboa mail server hosting platform by setting
DEBUG = True
in the/srv/modoboa/instance/instance/settings.py
file. - PHP-FPM could be overloaded. Check your PHP-FPM log (such as
/var/log/php7.4-fpm.log
). If you can find the[pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)
warning message, you need to allocate more resources to PHP-FPM. - Sometimes reloading PHP-FPM (
sudo systemctl reload php7.4-fpm
) can fix the error. - It also might be that you didn’t install the database module for PHP, so PHP can’t connect to the database. For MySQL/MariaDB, install it with
sudo apt install php7.4-mysql
. For PostgreSQL, install it withsudo apt install php7.4-pgsql
.
Nginx Shows the default page
If you try to set up an Nginx virtual host and when you type the domain name in your web browser, the default Nginx page shows up, it might be
- Your Nginx virtual host file doesn’t have the
server_name
directive. - You didn’t use a real domain name for the
server_name
directive in your Nginx virtual host. - You forgot to reload Nginx.
- You can try deleting the default virtual host file in Nginx (
sudo rm /etc/nginx/sites-enabled/default
).
The page isn’t redirecting properly
Firefox displays this error as The page isn’t redirecting properly
. Google Chrome shows this error as www.example.com redirected you too many times
.
This means you have configured Nginx redirection too many times. For example, you may have added an unnecessary return 301
directive in the https
server block to redirect HTTP to HTTPS connection.
If you have set up a page cache such as Nginx FastCGI cache, you need to clear your server page cache.
504 Gateway time-out
This means the upstream like PHP-FPM/MySQL/MariaDB isn’t able to process the request fast enough. You can try restarting PHP-FPM to fix the error temporarily, but it’s better to start tuning PHP-FPM/MySQL/MariaDB for faster performance.
Optimize MySQL/MariaDB Performance
Here is the InnoDB configuration in my /etc/mysql/mariadb.conf.d/50-server.cnf
file. This is a very simple performance tunning.
innodb_buffer_pool_size = 1024M innodb_buffer_pool_dump_at_shutdown = ON innodb_buffer_pool_load_at_startup = ON innodb_log_file_size = 512M innodb_log_buffer_size = 8M #Improving disk I/O performance innodb_file_per_table = 1 innodb_open_files = 400 innodb_io_capacity = 400 innodb_flush_method = O_DIRECT innodb_read_io_threads = 64 innodb_write_io_threads = 64 innodb_buffer_pool_instances = 3
Where:
- The InnoDB buffer pool size needs to be at least half of your RAM. ( For VPS with small amount of RAM, I recommend setting the buffer pool size to a smaller value, like 400M, or your VPS would run out of RAM.)
- InnoDB log file size needs to be 25% of the buffer pool size.
- Set the read IO threads and write IO thread to the maximum (64) and
- Make MariaDB use 3 instances of InnoDB buffer pool. The number of instances needs to be the same number of CPU cores on your system.
After saving the changes, restart MariaDB.
sudo systemctl restart mariadb
Recommended reading: MySQL/MariaDB Database Performance Monitoring with Percona on Ubuntu Server
Find Out Which PHP Script Caused 504 Error
You can check the web server access log to see if there are any bad requests. For example, some folks might find the following lines in the Nextcloud access log file (/var/log/nginx/nextcloud.access
).
"GET /apps/richdocumentscode/proxy.php?req=/hosting/capabilities HTTP/1.1" 499 0 "-" "Nextcloud Server Crawler" "GET /apps/richdocumentscode/proxy.php?req=/hosting/capabilities HTTP/1.1" 499 0 "-" "Nextcloud Server Crawler" "GET /apps/richdocumentscode/proxy.php?req=/hosting/capabilities HTTP/1.1" 499 0 "-" "Nextcloud Server Crawler"
Notice the HTTP status code 499, which means the HTTP client quit the connection before the server gives back an answer. Successful HTTP code should be 2xx
or 3xx
. If you can find HTTP code 4xx
, it means there’s a problem with this HTTP request. In this example, the Nextcloud richdocumentscode
app isn’t working.
Increase Timeout Settings
You can also set a longer timeout value in Nginx to reduce the chance of gateway timeout. Edit your Nginx virtual host file and add the following lines in the server {...}
block.
proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600;
If you use Nginx with PHP-FPM, then set the fastcgi_read_timeout to a bigger value like 300 seconds. Default is 60 seconds.
location ~ \.php$ { try_files $uri /index.php$is_args$args; include snippets/fastcgi-php.conf; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_read_timeout 300; }
Then reload Nginx.
sudo systemctl reload nginx
PHP-FPM also has a max execution time for each script. Edit the php.ini
file.
sudo nano /etc/php/7.4/fpm/php.ini
You can increase the value to 300 seconds.
max_execution_time = 300
Then restart PHP-FPM
sudo systemctl restart php7.4-fpm
Memory Size Exhausted
If you see the following line in your Nginx error log, it means PHP reached the 128MB memory limit.
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 57134520 bytes)
You can edit the php.ini
file (/etc/php/7.4/fpm/php.ini
) and increase the PHP memory limit.
memory_limit = 512M
Then restart PHP7.4-FPM.
sudo systemctl restart php7.4-fpm
If the error still exists, it’s likely there’s bad PHP code in your web application that eats lots of RAM.
PR_END_OF_FILE_ERROR
- You configured Nginx to rediect HTTP request to HTTPS, but there’s no server block in Nginx serving HTTPS request.
- Maybe Nginx isn’t running?
- Sometimes, the main Nginx binary is running, but a worker process can fail and exit due to various reasons. Check the Nginx error log (
/var/log/nginx/error.log
) to debug.
PHP-FPM Upstream Time Out
Some folks can find the following error in Nginx error log file ( under /var/log/nginx/
).
[error] 7553#7553: *2234677 upstream timed out (110: Connection timed out) while reading response header from upstream
Possible solutions:
- Restart PHP-FPM.
- Upgrade RAM.
- Optimize database performance. Because PHP-FPM needs to fetch data from the database, if the database is slow to process requests, PHP-FPM will time out.
502 Bad Gateway
This error could be caused by:
- PHP-FPM isn’t running. Check its status:
sudo systemctl status php7.4-fpm
. - PHP-FPM is running, but Nginx isn’t able to connect to PHP-FPM (Resource temporarily unavailable), see how to fix this error below.
- PHP-FPM is running, but Nginx doesn’t have permission to connect to PHP-FPM socket (Permission denied). It might be that Nginx is running as nginx user, but the socket file
/run/php/php7.4-fpm.sock
is owned by thewww-data
user. You should configure Nginx to run as thewww-data
user.
Resource temporarily unavailable
Some folks can find the following error in Nginx error log file ( under /var/log/nginx/
).
connect() to unix:/run/php/php7.4-fpm.sock failed (11: Resource temporarily unavailable)
This usually means your website has lots of visitors and PHP-FPM is unable to process the huge amounts of requests. You can adjust the number of PHP-FPM child process, so it can process more requests.
Edit your PHP-FPM www.conf
file. (The file path varies depending on your Linux distribution.)
sudo nano /etc/php/7.4/fpm/pool.d/www.conf
The default child process config is as follows:
pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3
The above configuration means
- PHP-FPM dynamically create child processes. No fixed number of child processes.
- It creates at most 5 child processes.
- Start 2 child processes when PHP-FPM starts.
- There’s at least 1 idle process.
- There’s at most 3 idle processes.
The defaults are based on a server without much resources, like a server with only 1GB RAM. If you have a high traffic website, you probably want to increase the number of child processes, so it can serve more requests. (Make sure you have enough RAM to run more child processes.)
pm = dynamic pm.max_children = 20 pm.start_servers = 8 pm.min_spare_servers = 4 pm.max_spare_servers = 12
Save and close the file. Then we also increase the PHP memory limit.
sudo nano /etc/php/7.4/fpm/php.ini
Find the following line.
memory_limit = 128M
By default, a script can use at most 128M memory. It’s recommended to set this number to at lest 512M.
memory_limit = 512M
Save and close the file. Restart PHP-FPM. (You might need to change the version number.)
sudo systemctl restart php7.4-fpm
To monitor the health of PHP-FPM, you can enable the status page. Find the following line in the PHP-FPM www.conf
file.
;pm.status_path = /status
Remove the semicolon to enable PHP-FPM status page. Then restart PHP-FPM.
sudo systemctl restart php7.4-fpm
Then edit your Nginx virtual host file. Add the following lines. The allow
and deny
directives are used to restrict access. Only the whitelisted IP addresses can access the status page.
location ~ ^/(status|ping)$ {
allow 127.0.0.1;
allow your_other_IP_Address;
deny all;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
Save and close the file. Then test Nginx configurations.
sudo nginx -t
If the test is successful, reload Nginx for the changes to take effect.
sudo systemctl reload nginx
Sample PHP-FPM status page.
The PHP-FPM www.conf
file gives you a good explanation of what each parameter means.
If PHP-FPM is very busy and unable to serve a request immediately, it will queue this request. By default, there can be at most 511 pending requests, determined by the listen.backlog
parameter.
listen.backlog = 511
If you see the following value on the PHP-FPM status page, it means there has never been a request put in the queue, i.e. your PHP-FPM can process requests quickly.
listen queue: 0 max listen queue: 0
If there are 511
pending requests in the queue, it means your PHP-FPM is very busy, so you should increase the number of child processes.
You may also need to change the Linux kernel net.core.somaxconn
setting, which defines max number of connections allowed to a socket file on Linux, such as the PHP-FPM Unix socket file. By default, its value is 128
before kernel 5.4 and 4096
starting with kernel 5.4.
linuxbabe@ubuntu:~$ sysctl net.core.somaxconn net.core.somaxconn = 128
If you run a high traffic website, you can use a big value. Edit /etc/sysctl.conf
file.
sudo nano /etc/sysctl.conf
Add the following two lines.
net.core.somaxconn = 20000 net.core.netdev_max_backlog = 65535
Save and close the file. Then apply the settings.
sudo sysctl -p
Note: If your server has enough RAM, you can allocate a fixed number of child processes for PHP-FPM like below. In my experience, this fixed the 500 internal error for a Joomla + Virtuemart website.
pm = static pm.max_children = 50
Two Virtual Host files For the Same Website
If you run sudo nginx -t
and see the following warning.
nginx: [warn] conflicting server name "example.com" on [::]:443, ignored nginx: [warn] conflicting server name "example.com" on 0.0.0.0:443, ignored
It means there are two virtual host files that contain the same server_name
configuration. Don’t create two virtual host files for one website.
PHP-FPM Connection reset by peer
Nginx error log file shows the following message.
recv() failed (104: Connection reset by peer) while reading response header from upstream
This may be caused by a restart of PHP-FPM. If it’s retarted manually by yourself, then you can ignore this error.
Nginx Socket Leaks
If you find the following error message in the /var/log/nginx/error.log
file, your Nginx has a socket leaks problem.
2021/09/28 13:27:41 [alert] 321#321: *120606 open socket #16 left in connection 163 2021/09/28 13:27:41 [alert] 321#321: *120629 open socket #34 left in connection 188 2021/09/28 13:27:41 [alert] 321#321: *120622 open socket #9 left in connection 213 2021/09/28 13:27:41 [alert] 321#321: *120628 open socket #25 left in connection 217 2021/09/28 13:27:41 [alert] 321#321: *120605 open socket #15 left in connection 244 2021/09/28 13:27:41 [alert] 321#321: *120614 open socket #41 left in connection 245 2021/09/28 13:27:41 [alert] 321#321: *120631 open socket #24 left in connection 255 2021/09/28 13:27:41 [alert] 321#321: *120616 open socket #23 left in connection 258 2021/09/28 13:27:41 [alert] 321#321: *120615 open socket #42 left in connection 269 2021/09/28 13:27:41 [alert] 321#321: aborting
You can restart the OS to solve this problem. If it doesn’t work, you need to compile a debug version of Nginx, which will show you debug info in the log.
invalid PID number “” in “/run/nginx.pid”
You need to restart your web server.
sudo pkill nginx sudo systemctl restart nginx
Cloudflare Errors
Here are some common errors and solutions if your website runs behind Cloudflare CDN (Content Delivery Network).
521 Web Server is Down
- Nginx isn’t running.
- You didn’t open TCP ports 80 and 443 in the firewall.
- You changed the server IP address, but forgot to update DNS record in Cloudflare.
The page isn’t redirecting properly
If your SSL setting on the SSL/TLS app is set to Flexible
, but your origin server is configured to redirect HTTP requests to HTTPS, Your Nginx server sends reponse back to Cloudflare in encrypted connection. Since Cloudflare is expecting HTTP traffic, it keeps resending the same request, resulting in a redirect loop. In this case, you need to use the Full (strict)
SSL/TLS option in your Cloudflare settings.
Wrapping Up
I hope this article helped you to fix common Nginx web server errors. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks 🙂
You may want to check out:
I found a tutorial about Nginx and apache webserver on your blog but I can’t find the caddy web server if you can make a tutorial about caddy it can help me to learn about the detail of the caddy webserver. thank you
This is helpful, thanks for sharing this.
its help at least for me, a lot..tqvm.