Linux — Level by Level›06 · Checkpoint: a day on a server

Lesson 06 of 19 · Level 1 — Beginner: everyday commands

Checkpoint: a day on a server

Put Level 1 to work on a server that has been broken on purpose: a web server that won't start, a page that returns 403, logs a developer can't read, and a disk to tidy. Solve each from the symptoms.

Beginner
Key wordscheckpointnginx -t403 Forbiddengroup accessss -ltnpdujournalctl

The situation

You're on call. A colleague hands you a server with three complaints and a warning:

  1. "The website is down."
  2. "When it was up, it said 403 Forbidden."
  3. "Dev can't read the app logs in /var/log/myapp."
  4. "Also, check what's using the most space in /var/log."

It's like being the new caretaker of a school on day one: the front door is jammed, a classroom is locked, a teacher can't get into the staff room, and a cupboard is overflowing. You don't guess. You check each one, find the real reason, and fix only that.

Set up the broken server

Use a disposable Ubuntu VM (not a machine you care about). Save this as checkpoint-setup.sh and run it with sudo bash checkpoint-setup.sh:

#!/usr/bin/env bash
# Breaks a fresh Ubuntu VM on purpose, for the Linux Level 1 checkpoint.
set -euo pipefail
apt-get update -qq && apt-get install -y -qq nginx > /dev/null

# 3) app logs readable only by the 'applog' group
groupadd -f applog
mkdir -p /var/log/myapp
for i in 1 2 3; do echo "$(date) INFO request ok" >> /var/log/myapp/app.log; done
echo "$(date) ERROR database connection refused" >> /var/log/myapp/app.log
chown root:applog /var/log/myapp /var/log/myapp/app.log
chmod 750 /var/log/myapp
chmod 640 /var/log/myapp/app.log

# 2) a page the web server can't read
echo '<h1>Checkpoint</h1>' > /var/www/html/index.html
chmod 600 /var/www/html/index.html

# 1) a missing semicolon in the nginx config
sed -i 's/listen 80 default_server;/listen 80 default_server/' /etc/nginx/sites-available/default
systemctl restart nginx || true
echo "Server broken on purpose. Good luck!"

Also create a developer account to test with: sudo adduser dev.

Now stop reading and try each problem yourself. Solutions follow.

Problem 1: the website is down

Your turn

Find out whether nginx is running, why not, and fix it.

Solution
$ systemctl status nginx
× nginx.service - A high performance web server and a reverse proxy server
     Active: failed (Result: exit-code) since …
$ sudo nginx -t
nginx: [emerg] invalid parameter "listen" in /etc/nginx/sites-enabled/default:23
nginx: configuration file /etc/nginx/nginx.conf test failed

The line before the reported one is missing its ;, so nginx read the next listen as a parameter. (Line numbers may differ slightly.) Open the file with sudo nano /etc/nginx/sites-available/default, add the semicolon back to listen 80 default_server, then:

$ sudo nginx -t && sudo systemctl restart nginx
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ systemctl is-active nginx
active

Habit: always run the config test before restarting a service.

Problem 2: 403 Forbidden

Your turn

curl -I http://localhost now answers, but with a 403. Why, and what's the smallest correct fix?

Solution
$ curl -I http://localhost
HTTP/1.1 403 Forbidden
$ sudo tail -3 /var/log/nginx/error.log
… open() "/var/www/html/index.html" failed (13: Permission denied) …
$ ls -l /var/www/html/index.html
-rw------- 1 root root 20 Sep 27 10:02 /var/www/html/index.html
$ ps -o user= -C nginx | sort | uniq -c
      1 root
      2 www-data

The workers run as www-data, but only root can read the file. Make it world-readable (web pages are public anyway):

$ sudo chmod 644 /var/www/html/index.html
$ curl -s http://localhost
<h1>Checkpoint</h1>

Error code 13 is EACCES (permission denied). The error log told you exactly which file.

Problem 3: dev can't read the app logs

Your turn

sudo -u dev cat /var/log/myapp/app.log fails. Give dev read access without loosening permissions for everyone.

Solution
$ ls -ld /var/log/myapp /var/log/myapp/app.log
drwxr-x--- 2 root applog 4096 … /var/log/myapp
-rw-r----- 1 root applog  246 … /var/log/myapp/app.log
$ sudo usermod -aG applog dev

The directory and file are group-readable by applog, so adding dev to that group is the least-privilege fix. Dev must log in again for the new group to apply. Then:

$ sudo -iu dev
$ grep ERROR /var/log/myapp/app.log
… ERROR database connection refused

Problem 4: what's using the space?

Your turn

List the five largest items under /var/log, and confirm which process is listening on port 80.

Solution
$ sudo du -ah /var/log | sort -rh | head -5
$ sudo ss -ltnp | grep ':80 '
LISTEN 0  511  0.0.0.0:80  0.0.0.0:*  users:(("nginx",pid=2231,fd=6),("nginx",pid=2230,fd=6))

Don't delete logs by hand while a service writes to them. Use the log rotation (logrotate) or journalctl --vacuum-size= for the journal (lesson 07).

Going deeper: write it up

For each problem, write three lines: symptom → evidence → fix. This is the start of a proper incident habit (see SRE & Production Incident Response), and it's exactly what interviewers ask for: "tell me about a time something was broken."

You've finished Linux Level 1

You can navigate, read and search, manage permissions, processes, services and packages, and fix common problems from evidence. Level 2 is troubleshooting in depth: systemd and the journal, disks, host networking, performance and SSH.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.