LFCA 118 ๐ง Real-World Scenario โ Deploying a Simple Web Server
The previous two chapters covered troubleshooting as a method and as a catalog of common scenarios. This chapter applies both. Deploying a web server is one of the first real tasks a new system administrator performs, and it exercises nearly every competency the LFCA exam tests: package management, service management, network configuration, file permissions, and verification. The process is straightforward, but the details matter. A missing firewall rule or an incorrect file permission will produce a server that appears to work on localhost but fails for every remote client.
This chapter walks through a complete deployment of a web server on a Linux system. You will install a web server package, manage it with systemd, configure it to serve a simple site, verify that it is listening on the correct ports, adjust firewall settings, and confirm the deployment from both local and remote perspectives. The goal is not just to follow steps but to understand why each step exists and what verification looks like at each stage.
By the end, you will have a repeatable deployment procedure and the knowledge to diagnose the most common failures when something does not work as expected.
Key point: A web server deployment is not complete until it has been verified from outside the local machine. A service that responds to curl localhost but fails to curl from another host is not a working web serverโit is a working service behind a misconfigured firewall.
Why this scenario matters
The practical foundation. Deploying a web server is one of the most common tasks in entry-level system administration. Whether the server runs Apache, Nginx, or a Python HTTP server, the workflow is the same: install the package, manage the service, configure the content directory, open the firewall, and verify. Learning this workflow once means you can repeat it for any web server on any distribution.
The integration test. A web server deployment touches every layer of the system. Package management ensures the software is installed. systemd ensures it starts and stays running. File permissions ensure the server process can read the content it serves. Network configuration ensures clients can reach the server. Firewall rules ensure traffic is not blocked. A failure in any one of these layers produces the same symptomโthe browser cannot connectโbut requires a different diagnostic path. This is why deployment and troubleshooting are inseparable skills.
The LFCA domain coverage. The LFCA exam covers system administration fundamentals, including system management tasks, networking, and troubleshooting . Deploying a web server exercises all three. The exam expects candidates to know the commands for installing packages (apt install, dnf install), managing services (systemctl start, systemctl enable), checking listening ports (ss -tuln), and reading logs (journalctl -u) . This chapter brings those commands together in a coherent workflow.
The verification discipline. The most common deployment mistake is stopping when the service starts. A service that reports “active (running)” is not necessarily serving content. A web server that listens on port 80 is not necessarily reachable from outside the host. Verification is not optional; it is the step that confirms the deployment succeeded. This chapter treats verification as a first-class part of the process, not an afterthought.
a. Installing the web server package
The first step is installing the web server software. The command depends on the distribution and the package manager. On Debian and Ubuntu systems, apt is the package manager. On RHEL, Fedora, and their derivatives, dnf (or yum on older systems) is used.
# Debian/Ubuntu
sudo apt update
sudo apt install nginx -y
# RHEL/Fedora/AlmaLinux
sudo dnf install nginx -y
The apt update command refreshes the package index, ensuring you install the latest available version . The -y flag automatically answers “yes” to the installation prompt, which is useful in scripts but should be used with awarenessโyou are confirming that you want to install the package and its dependencies.
After installation, the web server is installed but not necessarily running. On Debian and Ubuntu, the nginx package starts the service automatically after installation . On RHEL-based systems, the service may be installed but not started. This is why the next step is always to check the service status, not to assume it is running.
A note on Apache versus Nginx: both are web servers, and the deployment workflow is nearly identical. The commands in this chapter use Nginx because it is lightweight and common in cloud environments, but the principles apply equally to Apache. On Debian/Ubuntu, Apache’s service name is apache2; on RHEL, it is httpd. The package name for Apache on Debian/Ubuntu is apache2, and the configuration directory is /etc/apache2/ .
b. Managing the service with systemd
Once the package is installed, the next step is ensuring the service is running and configured to start at boot. The systemctl command manages systemd services.
# Check status
sudo systemctl status nginx
# Start the service
sudo systemctl start nginx
# Enable start at boot
sudo systemctl enable nginx
The systemctl status command is the first diagnostic tool for any service . The output tells you whether the service is active, inactive, or failed, and it displays the most recent log entries. If the service is failed, the last log lines often contain the reason.
The systemctl enable command creates a symbolic link that causes the service to start automatically when the system boots . Without this, the service would need to be started manually after every rebootโa recipe for forgotten deployments and late-night emergencies.
After starting or enabling the service, verify that it is listening on the expected port. Port 80 is the standard HTTP port. The ss command shows listening sockets.
sudo ss -tulpn | grep :80
The -t flag shows TCP sockets, -u shows UDP, -l shows listening sockets only, -p shows the process using the socket, and -n shows numeric port numbers . If Nginx is listening on port 80, the output shows nginx as the process name. If nothing is listening on port 80, the service is either not running or not configured correctly.
c. Configuring content and firewall rules
With the service running and listening on port 80, the next step is serving content and ensuring it is reachable from outside the host. The default Nginx installation includes a sample page at /var/www/html/index.nginx-debian.html or /usr/share/nginx/html/index.html, depending on the distribution . This page confirms that the server works, but it is not a real deployment.
To serve your own content, create a file in the web root directory.
sudo mkdir -p /var/www/html/mysite
echo "<h1>Hello from my web server</h1>" | sudo tee /var/www/html/mysite/index.html
The file permissions matter. The web server process runs as a specific user (typically www-data on Debian/Ubuntu or nginx on RHEL). The content directory and its files must be readable by that user. A common mistake is creating files as root with restrictive permissions that the web server cannot read. The ls -la command verifies permissions.
ls -la /var/www/html/mysite/
If the web server user cannot read the files, the server returns a 403 Forbidden error. The fix is to ensure the files are world-readable or owned by the web server user.
The firewall is the final barrier between the web server and the outside world. On systems using ufw (common on Ubuntu), the command to allow HTTP traffic is:
sudo ufw allow 80/tcp
sudo ufw reload
On systems using firewalld (common on RHEL and Fedora), the command is:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
The --permanent flag ensures the rule survives a reboot; without it, the rule is temporary and disappears after the next restart . The --reload command applies the change without restarting the firewall service entirely.
Verification from outside the host is the final step. On the server itself, curl localhost confirms that the web server responds locally. From another machine on the network, curl http://server-ip confirms that the network path, firewall rules, and web server are all working together.
Complete Example Session
# ============================================
# PART 1: SYSTEM UPDATE AND PACKAGE INSTALLATION
# ============================================
sudo apt update
sudo apt install nginx -y
# ============================================
# PART 2: SERVICE STATUS AND MANAGEMENT
# ============================================
sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# ============================================
# PART 3: VERIFY LISTENING PORT
# ============================================
sudo ss -tulpn | grep :80
# ============================================
# PART 4: CREATE CONTENT DIRECTORY
# ============================================
sudo mkdir -p /var/www/html/mysite
echo "<h1>Hello from my web server</h1>" | sudo tee /var/www/html/mysite/index.html
# ============================================
# PART 5: VERIFY FILE PERMISSIONS
# ============================================
ls -la /var/www/html/mysite/
# Ensure world-readable or owned by www-data
# ============================================
# PART 6: CONFIGURE FIREWALL (UFW)
# ============================================
sudo ufw allow 80/tcp
sudo ufw reload
sudo ufw status verbose
# ============================================
# PART 7: VERIFY FROM LOCALHOST
# ============================================
curl -I http://localhost
curl http://localhost/mysite/
# ============================================
# PART 8: VERIFY FROM REMOTE HOST
# ============================================
# On another machine:
curl -I http://server-ip
curl http://server-ip/mysite/
# ============================================
# PART 9: CHECK LOGS FOR ERRORS
# ============================================
sudo journalctl -u nginx -n 20 --no-pager
sudo tail -20 /var/log/nginx/error.log
# ============================================
# PART 10: VERIFICATION CHECKLIST
# ============================================
# Service active? sudo systemctl status nginx
# Listening on :80? sudo ss -tulpn | grep :80
# Content readable? sudo -u www-data cat /var/www/html/mysite/index.html
# Firewall open? sudo ufw status | grep 80
# Local access works? curl http://localhost/mysite/
# Remote access works? curl http://server-ip/mysite/
The ten parts covered the complete deployment workflow: package installation, service management, port verification, content creation, permission checking, firewall configuration, local verification, remote verification, log inspection, and a final verification checklist.
Quick Reference
Deployment Commands by Distribution
| Task | Debian/Ubuntu | RHEL/Fedora |
|---|---|---|
| Install Nginx | apt install nginx | dnf install nginx |
| Install Apache | apt install apache2 | dnf install httpd |
| Service name (Nginx) | nginx | nginx |
| Service name (Apache) | apache2 | httpd |
| Firewall tool | ufw | firewalld |
| Config directory | /etc/nginx/ | /etc/nginx/ |
| Apache config | /etc/apache2/ | /etc/httpd/ |
| Web root | /var/www/html/ | /usr/share/nginx/html/ |
Verification Commands
| Check | Command | Expected Output |
|---|---|---|
| Service status | systemctl status nginx | active (running) |
| Listening ports | ss -tulpn | grep :80 | nginx on 0.0.0.0:80 |
| Local HTTP | curl -I localhost | HTTP/1.1 200 OK |
| Remote HTTP | curl -I server-ip | HTTP/1.1 200 OK |
| Firewall (UFW) | ufw status | 80/tcp ALLOW |
| Firewall (firewalld) | firewall-cmd --list-all | http in services |
Common Failure Symptoms
| Symptom | Likely Cause | Diagnostic Command |
|---|---|---|
| Connection refused | Service not running | systemctl status nginx |
| Connection timed out | Firewall blocking | ufw status or firewall-cmd --list-all |
| 403 Forbidden | File permissions | ls -la /var/www/html/ |
| 404 Not Found | Wrong document root | grep root /etc/nginx/sites-enabled/ |
| Works locally, fails remotely | Firewall or binding | ss -tulpn | grep :80 |
Best Practices
โ Do This:
# Update package index before installing
sudo apt update && sudo apt install nginx -y # โ
# Enable service at boot
sudo systemctl enable nginx # โ
# Verify listening port after starting
sudo ss -tulpn | grep :80 # โ
# Check file permissions for web content
ls -la /var/www/html/ # โ
# Test from localhost first, then remote
curl -I localhost && curl -I server-ip # โ
# Read logs when something fails
sudo journalctl -u nginx -n 50 --no-pager # โ
โ Don’t Do This:
# Assume the service is running after install
# (check status) # โ
# Forget to open the firewall
# (service works locally, fails remotely) # โ
# Create content with restrictive permissions
sudo chmod 700 /var/www/html/mysite # โ
# Stop at localhost verification
curl localhost # โ (test remotely)
# Ignore logs when troubleshooting
# (journalctl and error.log contain answers) # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Remote access fails, local works | Firewall blocking port 80 | Open port with ufw allow 80/tcp |
| 403 Forbidden error | Web server user cannot read files | chmod 644 or change ownership |
| Service not running after reboot | Service not enabled | systemctl enable nginx |
| Port 80 already in use | Another web server running | ss -tulpn | grep :80 then stop conflict |
| Config changes not applied | Service not reloaded | systemctl reload nginx |
| SELinux blocking access | Context not set for custom directory | semanage fcontext -a -t httpd_sys_content_t |
Real-World Examples
1. Verify Service is Active
systemctl is-active nginx
# Output: active
2. Check Listening Ports
ss -tulpn | grep -E ':80|:443'
3. Test HTTP Response
curl -I http://localhost
# HTTP/1.1 200 OK
4. Check Firewall Rules
sudo ufw status numbered
5. View Access Logs
sudo tail -f /var/log/nginx/access.log
6. Reload After Config Change
sudo nginx -t && sudo systemctl reload nginx
7. Check Web Server User
ps aux | grep nginx | grep -v grep
8. Test File Readability
sudo -u www-data cat /var/www/html/mysite/index.html
9. Verify Remote Access
curl -v http://192.168.1.100/mysite/
10. Check for Port Conflicts
sudo lsof -i :80
Visual
Deployment Workflow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WEB SERVER DEPLOYMENT WORKFLOW โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 1. INSTALL โ apt install nginx โ
โ โ PACKAGE โ dnf install nginx โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 2. MANAGE โ systemctl start nginx โ
โ โ SERVICE โ systemctl enable nginx โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 3. VERIFY โ ss -tulpn | grep :80 โ
โ โ PORT โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 4. CONFIGURE โ Create content, check permissions โ
โ โ CONTENT โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 5. OPEN โ ufw allow 80/tcp โ
โ โ FIREWALL โ firewall-cmd --add-service=http โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ 6. VERIFY โ Local: curl localhost โ
โ โ ACCESS โ Remote: curl server-ip โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Verification Layers
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VERIFICATION LAYERS (INSIDE OUT) โ
โ โ
โ Layer 1: Service โ
โ systemctl status nginx โ
โ โ Is the process running? โ
โ โ
โ Layer 2: Socket โ
โ ss -tulpn | grep :80 โ
โ โ Is it listening on the right port? โ
โ โ
โ Layer 3: Local HTTP โ
โ curl localhost โ
โ โ Does it respond locally? โ
โ โ
โ Layer 4: Firewall โ
โ ufw status | grep 80 โ
โ โ Is the port open externally? โ
โ โ
โ Layer 5: Remote HTTP โ
โ curl server-ip โ
โ โ Does it respond from another host? โ
โ โ
โ Each layer must pass before the next is meaningful. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Troubleshooting Decision Tree
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WEB SERVER NOT ACCESSIBLE โ WHERE IS THE PROBLEM? โ
โ โ
โ Can you curl localhost? โ
โ โ โ
โ โโโ NO โโโถ Service not running โ
โ โ systemctl status nginx โ
โ โ journalctl -u nginx โ
โ โ โ
โ โโโ YES โ
โ โ โ
โ โผ โ
โ Is it listening on :80? โ
โ โ โ
โ โโโ NO โโโถ Config issue โ
โ โ Check nginx.conf, sites-enabled/ โ
โ โ โ
โ โโโ YES โ
โ โ โ
โ โผ โ
โ Can you curl from remote host? โ
โ โ โ
โ โโโ NO โโโถ Firewall blocking โ
โ โ ufw status / firewall-cmd --list-all โ
โ โ โ
โ โโโ YES โโโถ Deployment successful โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
File Permission Check
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WEB CONTENT PERMISSIONS โ
โ โ
โ Web server runs as: www-data (Debian) or nginx (RHEL) โ
โ โ
โ Content must be readable by that user. โ
โ โ
โ Correct: โ
โ -rw-r--r-- 1 root root index.html โ
โ (world-readable) โ
โ โ
โ Or: โ
โ -rw-r--r-- 1 www-data www-data index.html โ
โ (owned by web server user) โ
โ โ
โ Incorrect: โ
โ -rw------- 1 root root index.html โ
โ (403 Forbidden error) โ
โ โ
โ Check with: ls -la /var/www/html/ โ
โ Test with: sudo -u www-data cat /var/www/html/index.html โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Install command (Debian) | sudo apt install nginx -y |
| Install command (RHEL) | sudo dnf install nginx -y |
| Start service | sudo systemctl start nginx |
| Enable at boot | sudo systemctl enable nginx |
| Check port | sudo ss -tulpn | grep :80 |
| Firewall (UFW) | sudo ufw allow 80/tcp |
| Firewall (firewalld) | sudo firewall-cmd --add-service=http |
| Local verify | curl -I http://localhost |
| Remote verify | curl -I http://server-ip |
| Logs | journalctl -u nginx |
| Config test | sudo nginx -t |
Key takeaways:
- Deployment is a layered process. Install the package, manage the service, configure the content, open the firewall, and verify. Each layer depends on the previous one.
systemctl statusis the first diagnostic command. It tells you whether the service is active, failed, or inactive, and it shows the most recent log entries.ss -tulpn | grep :80confirms the service is listening. A running service that is not listening on the expected port is not serving traffic.- Firewall configuration is separate from service configuration. A service can be perfectly configured and still unreachable because the firewall blocks the port.
- File permissions matter for web content. The web server user must be able to read the files it serves. A 403 Forbidden error almost always indicates a permission problem.
- Verification must be done from outside the host.
curl localhostconfirms local functionality.curl server-ipfrom another machine confirms the full deployment. journalctl -u nginxis the first troubleshooting step. When the service fails or behaves unexpectedly, the journal contains the answer.
Remember: Deploying a web server is a complete exercise in system administration. It touches package management, service management, file permissions, networking, and security. The deployment is not finished when the service starts; it is finished when a remote client receives content. This verification disciplineโtesting from the outside, not just the insideโis the difference between a deployment that appears to work and one that actually works. The LFCA exam tests this reasoning: given a symptom, which layer of the deployment is failing, and which command confirms it? Master the workflow, and the diagnostic path becomes obvious.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!