When a site is down, slow, or showing errors: narrow down which layer is broken, then look in the right place. Apache with PHP-FPM, databases on Amazon RDS. Amazon Linux 1 and Ubuntu 24.04 side by side.
READ-ONLY only looks; safeCHANGES THINGS be carefulON YOUR MAC in Terminal on your MacON THE SERVER after logging inAmazon Linux 1Ubuntu 24.04 where they differ
Start here
#1The method
Before typing anything, answer three questions. They usually point straight at the layer that's broken.
1. What changed?
An update (yours or automatic), a config edit, a Moodle upgrade or plugin, a new certificate, a busy day like exams. Most problems start right after a change. (history.log on Ubuntu, yum history on Amazon Linux 1, and your own history show what changed.)
2. When did it start?
The time lets you find the first error in the logs, which is usually the real cause. Later errors are often just side effects.
3. Who's affected?
The most useful question. See the diagram below.
Who's affected tells you where to look
GOLDEN RULELook before you change. Everything in sections 2–7 is read-only. Restarting things first can wipe out the clue (a full log, a stuck process) that tells you what actually went wrong.
Load averages for the last 1, 5, and 15 minutes. Compare with the number of CPUs (nproc). Much higher than that = overloaded; then run top to see what's busy.
4. Is a disk full?
df -h
Look at Use%. 100% on the main disk or the moodledata disk breaks sessions, uploads, and caching. Details: df, du.
5. Is memory running out?
Amazon Linux 1
free -m (sizes in MB; works on every version, while -h may not)
Ubuntu 24.04
free -h
Watch available (on Amazon Linux 1, the free number on the -/+ buffers/cache line). Very low = out of memory; Linux may be killing PHP processes. See free.
6. Are Apache and PHP-FPM running?
Amazon Linux 1
sudo service httpd status
PHP-FPM: find the service names first (section 5), then sudo service NAME status for each.
Ubuntu 24.04
systemctl status apache2
Anything failed, including PHP-FPM: systemctl --failed
7. What's the latest error?
Amazon Linux 1
sudo tail -n 30 /var/log/httpd/error_log
Ubuntu 24.04
sudo tail -n 30 /var/log/apache2/error.log
The main Apache error log. Sites with their own log files are covered in section 4. Read the times: errors from when the problem started matter; old ones may not.
BY NOWYou usually know whether it's one site or the whole server, and whether something obvious is full, stopped, or overloaded. Next, match what you're seeing in section 3.
How many requests got each status code, most common first. Hundreds of 5xx codes = a real server-side problem, not a one-off. (Use the site's own access log if it has one.)
Apache messages worth knowing
AH01079: failed to make connection to backend
Apache can't reach PHP-FPM. Check PHP-FPM (§5). Behind most 503s.
AH01067: Failed to read FastCGI header
PHP-FPM crashed mid-request. Behind most 502s. PHP-FPM log (§5).
The timeout specified has expired
PHP took too long. Behind most 504s.
server reached MaxRequestWorkers setting
Apache itself is at its limit of simultaneous visitors. Tuning belongs on the Apache sheet.
Permission denied on a file path
Apache can't read a file. Check ownership with ls -l.
With several PHP versions on one server, each version runs as its own PHP-FPM service with its own log. So first find which version the broken site uses, then check that one.
1. Which PHP-FPM services does this server have?
Amazon Linux 1
ls /etc/init.d/ | grep -i fpm
Ubuntu 24.04
systemctl list-units--type=service | grep -i fpm
One name per PHP version, for example php-fpm-7.3 or php8.1-fpm. The exact names depend on how PHP was installed, which is why you look them up instead of guessing.
Each line: the site's settings file, then the PHP-FPM "socket" it sends PHP work to. The version is in the socket's name. Here, the school site uses PHP 8.1.
What this searches for
The line in each site's Apache settings that hands PHP work to PHP-FPM.
grep -rn-E
Search every file in the folder and the folders inside it (-r), show line numbers (-n), and let | mean "or" (-E).
proxy:unix
The usual way: through a socket file, like php8.1-fpm.sock. The version is in its name.
fcgi://
The other way: by address and port, like fcgi://127.0.0.1:9000. (FastCGI is the "language" Apache and PHP-FPM speak.)
Got a port number instead of a socket name?
A port like 9000 doesn't say which PHP version it is. Find the PHP-FPM settings file that listens on it:
Replace 9000 with the port from step 2. The file's folder name shows the version, here 7.3. 2>/dev/null just hides "can't read" noise from unrelated files.
3. Is that version running?
Amazon Linux 1
sudo service NAME status using the name from step 1
Ubuntu 24.04
systemctl status php8.1-fpm using the name from step 1
is running / active (running) = up. Stopped or failed = that's why its sites give 503 errors.
4. Find its log
sudo find /var/log -iname '*fpm*'
Lists every PHP-FPM log on the server; pick the one for the version from step 2. On Ubuntu it's usually /var/log/php8.1-fpm.log. Then read the end of it: sudo tail -n 30 PATH.
PHP messages worth knowing
server reached pm.max_children setting
All PHP workers are busy, so new visitors wait, causing slowness and 504s. A sign of too many visitors for the settings, or slow pages tying workers up. Tuning belongs on the PHP-FPM sheet.
Allowed memory size of … bytes exhausted
One request needed more memory than PHP allows (memory_limit). Common with big course restores or reports.
Maximum execution time of … seconds exceeded
A request ran longer than PHP allows (max_execution_time).
child … exited on signal 9 or 11
A PHP worker was killed: 9 often means out of memory (§2 step 5); 11 is a crash, often from a PHP extension.
PHP Parse error: syntax error
A typo in a PHP file, often config.php after an edit. Names the file and line.
Use the version from step 2. Shows the limits from the command-line settings. PHP-FPM uses its own settings file, which is usually the same but can differ; the PHP-FPM sheet covers where each lives.
⚠ RESTARTING PHP-FPMCHANGES THINGSIf a PHP-FPM service is stopped or stuck, restarting it is usually the fix to get sites back. But read its log first (step 4), so you know why it happened. Restart only that version: Amazon Linux 1 sudo service NAME restart; Ubuntu sudo systemctl restart php8.1-fpm. It interrupts that version's sites for a second or two.
The databases live on Amazon RDS, a separate machine. So the questions are: can this server reach it, does it let the site in, and is RDS itself healthy?
Put the site's dbhost in place of the example. 3306 is the MySQL/MariaDB port. Works on both systems; nothing to install.
OPEN = the network path is fine; the problem is login or RDS itself (steps 3, 4).
BLOCKED after 5 seconds = can't reach it: RDS is down or rebooting, or the RDS security group doesn't allow this server.
Name or service not known = a typo in dbhost, or the RDS instance was renamed or deleted.
3. Can the site's user log in? (needs a database client)
mysql -h mydb.abc123xyz.us-east-1.rds.amazonaws.com -u school_user -p school -e "SELECT 1;"
Asks for the password (from config.php's dbpass line; nothing shows as you type). SELECT 1 only asks the database to answer "1", so it changes nothing.
A small table with 1 = login works.
Access denied for user = wrong user name or password, or that user isn't allowed from this server.
Too many connections = RDS has hit its connection limit (step 4).
mysql: command not found = no client installed. Skip to step 4.
4. Check RDS itself, in the AWS console
RDS › Databases › pick the instance:
Status
Should say Available. Rebooting, Modifying, Storage-full, or Maintenance explains a lot.
Monitoring › CPU utilization
Pinned near 100% = the database is the bottleneck (slow pages, 504s).
Monitoring › Database connections
A sudden jump, or flat at a ceiling = connection limit.
Monitoring › Free storage space
Near zero = writes fail; Moodle errors on almost everything.
Logs & events › Recent events
Reboots, failovers, maintenance, and storage warnings, with times. Compare with when the problem started.
MOODLE NOTEIf several sites share one RDS instance, one site's heavy report or course restore can slow all of them. If every site using that RDS is slow at once, look at RDS first; if only one is, look at that site.
For "can't be reached" and certificate warnings. Run these on your Mac, since the question is what visitors see.
1. Does the name point anywhere?
dig +short school.example.com
One or more addresses = the name works. Nothing = the DNS record is missing or wrong.
Your Mac may remember an old answer. Ask a public service instead: dig +short school.example.com @1.1.1.1. If that works but yours doesn't, it's just your Mac's memory (it clears on its own within minutes).
The address should match the server's Elastic IP in the EC2 console (or end in cloudfront.net / elb.amazonaws.com if it's behind one).
2. Is the server answering on the web port?
nc -zv-G 5 school.example.com 443
succeeded! = something is listening on 443 (HTTPS). The network is fine; look at Apache (§4).
Operation timed out = blocked or down: the server is stopped, or its security group doesn't allow port 443.
Connection refused = the server is up, but Apache isn't running (§2 step 6).
3. When does the certificate expire, and which names does it cover?
Replace the address in both places. notAfter is the expiry date; in the past = that's your warning.
subjectCN= is the main name on the certificate. A different name = the browser warns it doesn't match.
Where the certificate lives decides the fix
On CloudFront or a load balancer (from AWS Certificate Manager)
AWS renews it automatically, as long as its DNS validation record still exists. Check Certificate Manager in the console for its status.
On the server itself (for example Let's Encrypt)
Renewed by a tool on the server, usually certbot. sudo certbot certificates lists them and their expiry dates.
EVERY SITE AT ONCE?If every server seems unreachable at the same moment, check your own internet and VPN first, then the AWS Health Dashboard. It's rarely all your servers at once.
When the server, PHP, and database look fine, but the site misbehaves. Run Moodle's command-line scripts from inside the site's Moodle folder, as the web server user, with the PHP version that site uses (§5).
Which PHP command runs that version?
ls /usr/bin/php*/usr/bin/php /usr/bin/php7.3 /usr/bin/php8.1
Use the one matching the site, like php8.1, in the commands below. (Names vary with how PHP was installed.) The web server user is apache on Amazon Linux 1, www-data on Ubuntu; the examples use Ubuntu.
Quick checks (read-only)
php8.1 -l config.php
Typo in config.php? No syntax errors detected = fine.
grep dataroot config.php
Where moodledata is. Then ls -ld on that path: owner should be apache / www-data.
ls DATAROOT/climaintenance.html
If this file exists, the site is in maintenance mode (shows 503 to visitors). Replace DATAROOT with the path.
ps aux | grep cron.php
Is Moodle's cron running right now? One that started hours ago is probably stuck.
Site administration › Notifications
In the browser: warns if cron hasn't run recently, and of pending upgrades.
Site administration › Reports › Logs
In the browser: what users were doing when it broke.
Purge caches (fixes many odd display problems)
sudo -uwww-data php8.1 admin/cli/purge_caches.php
Safe; Moodle rebuilds them. The next few page loads are slower.
Shows visitors a "site under maintenance" page while you work. Remember to disable it; a forgotten maintenance mode looks exactly like an outage.
RECENT CHANGE?A new or updated plugin is a common cause. Site administration › Plugins › Plugins overview can show recently changed plugins; compare with when the problem started.
Five minutes now saves an hour next time. Keep a short note for each problem, in one place you can search, like a notes app or 1Password Secure Notes.
Template: copy these headings into your note
Date / time noticed:
Site(s) and server:
What users saw: (e.g. 504 on course pages)
Who was affected: (one page / one site / whole server / everything)
What changed just before:
What I checked: (and what each showed)
The cause:
The fix:
To stop it happening again:
TIPPaste the actual error lines from the logs into the note. Next time, searching your notes for part of an error message will find the fix.