All Posts

How to Troubleshoot a Website That Is Down

Posted by Rick on November 10th, 2026
Man troubleshooting a website that is offline

When a website goes down, it is tempting to SSH into the server and start restarting things. That can occasionally fix the immediate problem, but it can also destroy useful evidence and leave you with no idea what actually failed.

A better approach is to work through the request in order. Check whether the domain resolves, whether the server can be reached, whether the web server responds, whether PHP or another application runtime is healthy, and whether the application can reach its database and other dependencies.

This guide provides a practical troubleshooting process you can work through when a website is unavailable, returning errors or taking too long to respond.

Start by confirming what "down" actually means

Before changing anything, load the site and note exactly what happens.

There is an important difference between:

  • The browser saying the domain cannot be found
  • A connection timing out
  • A connection being refused
  • An SSL certificate warning
  • An Nginx error page
  • A 403 Forbidden
  • A 404 Not Found
  • A 500 Internal Server Error
  • A 502 Bad Gateway
  • A 504 Gateway Timeout
  • A page that loads but is extremely slow

Each points towards a different part of the stack.

From your own computer, use curl to see the HTTP response:

curl -I https://example.com

A successful response might look like:

HTTP/2 200
content-type: text/html; charset=UTF-8

curl -I requests the response headers without downloading the normal response body, which makes it useful for quickly checking a URL.

To print only the HTTP status code:

curl -sS -o /dev/null -w "%{http_code}\n" https://example.com

For more information about the connection itself:

curl -v https://example.com

Verbose output can show DNS resolution, the IP address being contacted, TLS negotiation and the HTTP response.

A useful first-pass guide is:

Symptom Start by checking
Domain cannot be found DNS
Connection timed out Network, firewall, server availability
Connection refused Web server, listening ports, firewall
SSL warning Certificate and DNS
403 Web server configuration and permissions
404 Document root, server block or application routes
500 Application and PHP logs
502 PHP-FPM or another upstream service
504 Slow or unavailable upstream service
Very slow response Server resources, database, application

This narrows the investigation immediately.

1. Check whether DNS is resolving correctly

If the domain itself cannot be resolved, there is little point investigating PHP or MySQL yet.

Check the domain:

dig +short example.com

You might see:

203.0.113.10

Check IPv6 as well:

dig +short AAAA example.com

Compare the result with the server's actual public IP address.

A common problem is an old DNS record pointing to a previous server after a migration.

You should also check the www hostname separately if the website uses it:

dig +short www.example.com

Do not assume that because example.com is correct, www.example.com is also correct.

Watch for broken IPv6 records

A particularly confusing issue occurs when the A record is correct but the domain also has an incorrect AAAA record.

Some visitors may connect over IPv4 and see the website normally while others attempt IPv6 and fail.

If you are not actually serving the website over IPv6, remove an obsolete AAAA record rather than leaving it pointing elsewhere.

DNS changes may take time

If records were changed recently, different resolvers may still have the previous value cached.

You can query specific DNS resolvers:

dig @1.1.1.1 example.com
dig @8.8.8.8 example.com

If DNS points to the correct server, move on.

2. Check whether the server can be reached

An IP address resolving correctly does not prove that the server is accessible.

Try connecting to HTTPS:

curl -v https://example.com

If you receive something similar to:

Connection timed out

the request may not be reaching the web server at all.

Possible causes include:

  • The server is powered off
  • The server has lost network connectivity
  • A cloud provider firewall is blocking traffic
  • The server firewall is blocking ports 80 or 443
  • Nginx or Apache is not listening
  • The server is overloaded and unable to respond
  • The IP address is wrong

If you can SSH into the server, check whether anything is listening on ports 80 and 443:

sudo ss -lntp | grep -E ':(80|443)\b'

You would normally expect to see Nginx, Apache or another web server listening.

For example:

LISTEN 0 511 0.0.0.0:80
LISTEN 0 511 0.0.0.0:443

If nothing is listening, investigate the web server next.

If the service is listening locally but external connections still time out, investigate firewall and network rules.

3. Check Nginx or Apache

For Nginx:

sudo systemctl status nginx

You want to see:

Active: active (running)

If Nginx has stopped, do not immediately restart it. Look at why it stopped.

Check recent service logs:

sudo journalctl -u nginx -n 100 --no-pager

Then test the configuration:

sudo nginx -t

A valid configuration should produce something similar to:

syntax is ok
test is successful

If the configuration test fails, fix the reported problem before restarting or reloading Nginx.

For Apache on Ubuntu or Debian:

sudo systemctl status apache2
sudo apachectl configtest

On many RHEL-family systems:

sudo systemctl status httpd
sudo apachectl configtest

Has the web server crashed or failed after a configuration change?

Check recent events:

sudo journalctl -u nginx --since "1 hour ago"

If the outage started shortly after someone changed a site configuration, SSL setting or PHP version, that recent change should be high on your list of suspects.

Configuration errors are especially likely after:

  • Adding a new website
  • Changing a domain
  • Moving a document root
  • Enabling SSL
  • Changing PHP versions
  • Editing redirects
  • Changing proxy settings

Do not restart a service repeatedly without finding out why it is failing.

4. Test the website from inside the server

Testing locally helps separate a web server problem from an external network or DNS problem.

For a basic HTTP site:

curl -I http://127.0.0.1

However, a server hosting multiple websites may use the hostname to decide which site to serve.

Specify it explicitly:

curl -I \
  -H "Host: example.com" \
  http://127.0.0.1

If the site redirects immediately to HTTPS, you can test HTTPS against localhost while still supplying the correct hostname:

curl -kI \
  --resolve example.com:443:127.0.0.1 \
  https://example.com

If the website works locally but not externally, the application and web server are probably functioning.

Concentrate instead on:

  • DNS
  • Server firewall rules
  • Cloud provider firewalls
  • Load balancers
  • Reverse proxies
  • CDN configuration
  • Network connectivity

This test can save a lot of time.

5. Check the HTTP error you are actually receiving

If the server responds, the status code provides useful direction.

403 Forbidden

A 403 normally means the server received the request but will not serve the requested resource.

Check:

  • File and directory permissions
  • Website ownership
  • Nginx or Apache access rules
  • The configured document root
  • Whether the web server can traverse parent directories
  • Whether an index file exists
  • SELinux or AppArmor where applicable

Inspect the path:

namei -l /var/www/example.com/public/index.php

This shows the permissions on every directory between / and the target file.

404 Not Found

A 404 does not necessarily mean the application file is missing.

Check:

  • The server_name
  • The configured document root
  • Whether the request is reaching the correct virtual host
  • Application routing
  • Nginx try_files configuration
  • Whether the latest deployment contains the expected files

For Nginx, print the active configuration:

sudo nginx -T

Search for the domain:

sudo nginx -T 2>/dev/null \
  | grep -n "server_name.*example.com"

500 Internal Server Error

A 500 usually means the web server reached the application but something failed while processing the request.

For PHP applications, check:

  • Application logs
  • PHP-FPM logs
  • Missing environment variables
  • File permissions
  • Database connectivity
  • Missing PHP extensions
  • Failed deployments
  • Broken application caches
  • Recent dependency changes

For Laravel, for example, application errors are commonly written beneath:

storage/logs/

The exact location depends on the application.

502 Bad Gateway

With Nginx and PHP, a 502 frequently means Nginx could not communicate successfully with PHP-FPM.

Common causes include:

  • PHP-FPM is stopped
  • Nginx points to the wrong PHP socket
  • The PHP version changed
  • Socket permissions are incorrect
  • PHP-FPM workers have failed or become exhausted

We cover this in detail in our 502 Bad Gateway troubleshooting guide.

504 Gateway Timeout

A 504 means the web server or proxy waited for an upstream service and did not receive a response in time.

With a PHP application, possible causes include:

  • A very slow PHP request
  • A slow database query
  • An external API that is not responding
  • PHP-FPM worker exhaustion
  • A long-running import or report
  • Locks or deadlocks
  • Insufficient server resources

Increasing the Nginx timeout may make the error disappear, but do not assume the timeout itself is the problem.

Find out what the application was waiting for first.

6. Check the web server logs

Logs are often the fastest way to stop guessing.

Nginx commonly writes to:

/var/log/nginx/access.log
/var/log/nginx/error.log

Show the latest errors:

sudo tail -n 100 /var/log/nginx/error.log

Follow new errors while making another request:

sudo tail -f /var/log/nginx/error.log

Nginx supports separate access and error logs, and the configured locations can be changed per server or location block.

If you are not sure where a website writes its logs:

sudo nginx -T 2>/dev/null \
  | grep -E 'access_log|error_log'

Useful messages might include:

connect() to unix:/run/php/php8.4-fpm.sock failed
Permission denied
No such file or directory
upstream timed out
rewrite or internal redirection cycle

Those messages are far more useful than the generic error shown in a browser.

ServerAuth's Log Viewer provides access to common logs including Nginx, Apache, PHP, Redis and SSH through the web interface, which can save you from finding and tailing each log manually when investigating a server.

7. Check PHP-FPM

If Nginx is healthy but a PHP website is failing, check PHP-FPM.

The service name depends on the installed PHP version.

For PHP 8.4 on Ubuntu, for example:

sudo systemctl status php8.4-fpm

Check its recent logs:

sudo journalctl \
  -u php8.4-fpm \
  -n 100 \
  --no-pager

If PHP-FPM is stopped, investigate the logs before restarting it.

A configuration error, missing extension, exhausted resource or failed upgrade may explain why it stopped.

Check which PHP socket Nginx expects

Search the Nginx configuration:

sudo nginx -T 2>/dev/null \
  | grep fastcgi_pass

You might find:

fastcgi_pass unix:/run/php/php8.4-fpm.sock;

Check whether that socket exists:

ls -la /run/php/

If Nginx expects:

/run/php/php8.3-fpm.sock

but the server now runs PHP 8.4, you have probably found the problem.

This often occurs after changing or removing a PHP version.

ServerAuth can manage different PHP versions on a per-site basis, so if the website is managed through ServerAuth it is also worth checking that the expected PHP version is assigned to the site.

8. Check the application logs

Once Nginx and PHP-FPM are working, move further into the application.

Frameworks usually have their own logs.

For Laravel:

tail -n 100 \
  /var/www/example.com/storage/logs/laravel.log

Your application may use a different location or send logs to another service.

Look for errors around the time the outage began.

Useful clues include:

  • Database connection failures
  • Missing environment variables
  • Permission errors
  • Missing files
  • PHP exceptions
  • Exhausted memory
  • External API failures
  • Cache or Redis failures
  • Failed dependency loading

Avoid reading a thousand old log entries from the top of a file.

Start with the latest entries:

tail -n 100 application.log

or follow it while reproducing the problem:

tail -f application.log

If a specific request triggers the problem, reproduce that request while watching the logs.

9. Check the database

A website can be online at the web-server level while remaining unusable because its database is unavailable.

For MySQL:

sudo systemctl status mysql

On some systems the service may be named:

sudo systemctl status mariadb

Check recent MySQL logs through systemd:

sudo journalctl \
  -u mysql \
  -n 100 \
  --no-pager

Useful application errors include:

Connection refused
Access denied for user
Too many connections
Unknown database

These point towards different issues.

Connection refused

The database service may be stopped or the application may be using the wrong host or port.

Access denied

Check:

  • Username
  • Password
  • Database hostname
  • MySQL user host restrictions
  • Grants

Too many connections

Find the configured limit:

mysql -NBe "SHOW VARIABLES LIKE 'max_connections';"

Check current connections:

mysql -NBe "SHOW STATUS LIKE 'Threads_connected';"

Do not simply raise max_connections without understanding why connections have accumulated.

A badly behaving application can consume a much larger amount of server memory if you allow it to open hundreds of additional database connections.

ServerAuth provides web-based management for MySQL databases and users, including remote MySQL access, which can make checking the expected database and user configuration easier.

10. Check disk space

A full disk can cause surprisingly varied failures.

Check filesystem usage:

df -h

You might find:

Filesystem      Size  Used Avail Use%
/dev/vda1        50G   50G     0 100%

When a filesystem reaches 100%, you may see:

  • MySQL refusing writes
  • PHP sessions failing
  • Logs stopping
  • Deployments failing
  • Cache writes failing
  • Queue workers crashing
  • Applications returning 500 errors

Also check inode usage:

df -i

A server can have free disk space but still be unable to create new files if all available inodes have been consumed.

Find large top-level directories:

sudo du -xhd1 /var \
  | sort -h

Then continue into the largest one.

Common causes include:

  • Application logs
  • Old releases
  • Database logs
  • Backups stored locally
  • Uploaded media
  • Docker images
  • Temporary files

Do not begin deleting unfamiliar files simply because they are large.

Find out what created them and whether the service still requires them.

ServerAuth monitors disk usage alongside load and memory, which can help identify a disk that has been steadily filling before it reaches the point where applications begin failing.

11. Check memory and load

If everything is technically running but the website is extremely slow or timing out, check the server itself.

View memory:

free -h

Check load:

uptime

Inspect active processes:

top

or, if installed:

htop

To find processes using the most memory:

ps aux \
  --sort=-%mem \
  | head -20

For CPU usage:

ps aux \
  --sort=-%cpu \
  | head -20

High resource usage may come from:

  • PHP-FPM
  • MySQL
  • Queue workers
  • A backup process
  • Image processing
  • Imports
  • Search indexing
  • A compromised process
  • Unexpected traffic

Check for out-of-memory kills

Linux may terminate processes when the system becomes critically short of memory.

Search the kernel log:

sudo journalctl -k \
  | grep -Ei 'out of memory|oom|killed process'

If PHP-FPM, MySQL or another important service was killed by the OOM killer, restarting that service only treats the immediate symptom.

You still need to find out why the server exhausted its memory.

ServerAuth stores server monitoring data for metrics including memory and system load, so the historical graphs can help distinguish a sudden spike from a problem that has been growing over time.

12. Check SSL certificates

If the website works over HTTP but fails over HTTPS, investigate TLS.

A quick check is:

curl -Iv https://example.com

You can inspect the certificate directly using OpenSSL:

openssl s_client \
  -connect example.com:443 \
  -servername example.com \
  </dev/null 2>/dev/null \
  | openssl x509 \
    -noout \
    -subject \
    -issuer \
    -dates

Check:

  • The certificate has not expired
  • The hostname is covered by the certificate
  • The correct certificate is being served
  • The certificate chain is complete
  • DNS points to the server containing that certificate
  • Nginx is listening on port 443

An expired certificate usually produces a browser security warning rather than a conventional HTTP error.

If a certificate renewal recently failed, check your Let's Encrypt or ACME client logs and confirm that ports 80 and 443 are accessible as required by the selected validation method.

13. Check the firewall

If the website works locally on the server but cannot be reached externally, firewall rules are a likely candidate.

On Ubuntu with UFW:

sudo ufw status verbose

You would normally expect public web traffic to be allowed on:

80/tcp
443/tcp

Do not assume the server firewall is the only one involved.

Cloud providers may also have:

  • Network firewalls
  • Security groups
  • Access control lists
  • Load balancer rules

A provider-level firewall can block a request before it ever reaches Linux.

If you use ServerAuth's Firewall Manager, you can review and manage port access from the control panel, including restricting SSH access and centrally managing firewall rules.

14. Check whether anything changed

When a previously healthy website suddenly fails, ask what happened immediately before the outage.

Check:

  • Was there a deployment?
  • Did PHP get upgraded?
  • Were packages updated?
  • Was the server rebooted?
  • Did DNS change?
  • Was an SSL certificate renewed?
  • Did someone edit Nginx?
  • Was a database password changed?
  • Did disk usage suddenly increase?
  • Was a firewall rule added?
  • Did an external API change or fail?

Check server uptime:

uptime

See the last boot:

who -b

Inspect recent package changes on Ubuntu:

grep -E ' install | upgrade | remove ' \
  /var/log/dpkg.log \
  | tail -50

If the problem began immediately after a deployment, compare the failed release with the previous one before making unrelated server changes.

The timing of a failure is often one of your strongest clues.

15. Do not forget background processes

Some websites appear online while important functionality has stopped.

For example:

  • Emails are no longer being sent
  • Orders are not being processed
  • Imports have stopped
  • Webhooks remain queued
  • Scheduled tasks are not running

Check queue workers and Supervisor:

sudo supervisorctl status

For a systemd-managed worker:

sudo systemctl status example-worker

Check cron where scheduled work is involved:

crontab -l

or for another user:

sudo crontab -u deploy -l

A failed queue worker may not make the homepage unavailable, but it can still represent a serious application outage.

ServerAuth can manage both cron jobs and Supervisor daemons through its web interface, so these are worth checking alongside the site itself when investigating applications that rely on background tasks.

A practical troubleshooting order

When the cause is not immediately obvious, work through the stack in this order:

Step Check Useful command
1 DNS dig +short example.com
2 HTTP response curl -I https://example.com
3 Listening ports ss -lntp
4 Web server systemctl status nginx
5 Nginx configuration nginx -t
6 Local website response curl -I -H "Host: example.com" http://127.0.0.1
7 Web server logs tail -n 100 /var/log/nginx/error.log
8 PHP-FPM systemctl status php8.4-fpm
9 Application logs tail -n 100 application.log
10 Database systemctl status mysql
11 Disk df -h and df -i
12 Memory and load free -h and uptime
13 Firewall ufw status verbose
14 Recent changes Deployments, updates and configuration changes

You will rarely need every step.

The purpose of the sequence is to prove each layer works before moving to the next one.

If DNS is wrong, PHP-FPM is irrelevant. If Nginx works locally but the website cannot be reached from the internet, your Laravel logs are unlikely to contain the answer.

Avoid making the outage harder to diagnose

A few habits make production incidents considerably more difficult than they need to be.

Restarting everything immediately

Restarting Nginx, PHP and MySQL may temporarily restore the website, but it can also remove useful evidence about which service failed.

Check status and logs first.

Changing several things at once

If you change permissions, restart PHP, alter Nginx and clear every application cache at the same time, you will not know which change fixed the issue.

Make one justified change, then test again.

Clearing logs

Do not delete the evidence you need to investigate the outage.

If disk space is critical, rotate or archive logs carefully rather than blindly deleting everything beneath /var/log.

Increasing limits without understanding the cause

Raising PHP workers, database connections, memory limits or timeouts may delay the next failure while making its eventual impact larger.

Work out what exhausted the original limit first.

Assuming the latest error is the root cause

One failing component often creates errors elsewhere.

For example, a full disk might cause MySQL to fail. PHP then reports database errors, and Nginx eventually returns a 500 or 502.

The browser shows the final symptom, not necessarily the original problem.

Make the next outage easier to investigate

The best time to improve your troubleshooting setup is while the website is healthy.

Make sure you know:

  • Where Nginx or Apache logs are stored
  • Where application logs are stored
  • Which PHP-FPM service and pool the site uses
  • Which user the application runs as
  • Which database it connects to
  • Which queue workers should be running
  • Which cron jobs are important
  • What normal memory, load and disk usage look like
  • Where backups are stored
  • How to roll back a deployment

Monitoring is particularly useful because it gives you information from before the outage.

If a server normally uses 40% of its memory and suddenly reaches 100% just before PHP-FPM is killed, that history is much more useful than looking at memory usage after the service has restarted.

ServerAuth brings server monitoring, logs, website management, MySQL, cron jobs and Supervisor processes into the same web interface. That gives you several of the places you would normally check during an incident without needing separate SSH commands for each one.

Work from the outside in

A website depends on several layers working together:

Domain
  ↓
DNS
  ↓
Network and firewall
  ↓
Nginx or Apache
  ↓
PHP-FPM or application server
  ↓
Application
  ↓
Database, cache and other services

Troubleshooting becomes much easier when you work through those layers in order.

Start with the exact symptom. Confirm DNS. Check whether the server responds. Test the web server locally. Read the logs. Only then move into PHP, the application, database and server resources.

Most importantly, avoid changing things simply because they might help. Every check should either confirm a part of the stack is working or move you closer to the component that is failing.

That approach gives you a much better chance of fixing the immediate outage while also understanding what needs to change to stop it happening again.

Server Management & Security doesn't have to be a full time job.

ServerAuth provides a whole host of management tools, from controlling who can access your server, to managing your website deployments. And with an ever-growing suite of tools you'll always be one step ahead!

Server Management Software Screenshot
ServerAuth
Server Management & SSH Security Software
 on X (Twitter)
Copyright © Peakstone Ltd
Registered in England & Wales No. 13996293
All Rights Reserved.
Solutions
Resources
Support
Customers
ServerAuth
The Legal Bits