From 5f3c516f7ba7bdaf590d123163b884e586f4dbc2 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Thu, 29 Jan 2026 14:26:02 +0100 Subject: [PATCH] init --- README.md | 83 +++++++++ break_server.sh | 455 ++++++++++++++++++++++++++++++++++++++++++++++++ setup.sh | 442 ++++++++++++++++++++++++++++++++++++++++++++++ solutions.md | 271 ++++++++++++++++++++++++++++ tasks.md | 149 ++++++++++++++++ verify.sh | 90 ++++++++++ 6 files changed, 1490 insertions(+) create mode 100644 README.md create mode 100755 break_server.sh create mode 100755 setup.sh create mode 100644 solutions.md create mode 100644 tasks.md create mode 100755 verify.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..6668bc2 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# Practice Exam - Setup Instructions + +## Overview + +This practice exam simulates a real-world server troubleshooting scenario with 5 problems to diagnose and fix within 45 minutes. + +## Requirements + +- Ubuntu Server (20.04 or 22.04 recommended) +- Root/sudo access +- Internet connection (for package installation) + +## Quick Start + +### 1. Initial Setup + +Run the setup script to install and configure all services: + +```bash +sudo ./setup.sh +``` + +This will install and configure: +- Nginx with 3 websites (company.local, shop.local, api.local) +- PHP-FPM for the API +- MySQL database with test data +- Docker with a simple web application +- UFW firewall + +### 2. Start the Exam + +Run the break server script and select option 6: + +```bash +sudo ./break_server.sh +``` + +Select: `6) START EXAM (All 5 problems - 45 minutes)` + +### 3. Check Your Progress + +At any time, run the verification script: + +```bash +./verify.sh +``` + +### 4. Reset (If Needed) + +To reset all problems and start over: + +```bash +sudo ./break_server.sh +# Select: 8) RESET all problems +``` + +## Files + +| File | Description | +|------|-------------| +| `setup.sh` | Initial server setup script | +| `break_server.sh` | Interactive menu to break/reset services | +| `verify.sh` | Check your progress on all tasks | +| `tasks.md` | Exam task descriptions | +| `solutions.md` | Detailed solutions (don't peek!) | + +## Tasks Overview + +1. **company.local** - Website not loading (Web Server Config) +2. **shop.local** - 403 Forbidden error (File Permissions) +3. **api.local:8080** - 502 Bad Gateway (Service Management) +4. **localhost:8888** - Connection timeout (Firewall) +5. **MySQL** - Connection refused (Database Admin) + +## Tips + +- Work systematically through each problem +- Check service status first (`systemctl status`) +- Read error logs (`journalctl`, `/var/log/`) +- Test configurations before reloading (`nginx -t`) +- Verify each fix before moving on + +Good luck! diff --git a/break_server.sh b/break_server.sh new file mode 100755 index 0000000..769a2a1 --- /dev/null +++ b/break_server.sh @@ -0,0 +1,455 @@ +#!/bin/bash + +# ============================================================ +# PRACTICE EXAM - BREAK SERVER SCRIPT +# Betriebssysteme und Netzwerke - 45 Minute Practice Test +# ============================================================ +# This script intentionally introduces problems for students +# to diagnose and fix during the practice exam +# ============================================================ + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +MAGENTA='\033[0;35m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${BLUE}[*]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[✓]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[✗]${NC} $1" +} + +print_break() { + echo -e "${MAGENTA}[BREAK]${NC} $1" +} + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + print_error "This script must be run as root (use sudo)" + exit 1 +fi + +# Detect PHP version +PHP_VERSION=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;" 2>/dev/null || echo "8.3") + +# ============================================================ +# PROBLEM 1: Nginx Configuration Error (company.local) +# Category: Web Server Configuration +# ============================================================ +break_nginx_config() { + print_break "Breaking company.local (Nginx config error)..." + + # Introduce a syntax error - remove semicolon + cat > /etc/nginx/sites-available/company.local << 'EOF' +server { + listen 80; + server_name company.local; + + root /var/www/company; + index index.html + + location / { + try_files $uri $uri/ =404; + } + + error_log /var/log/nginx/company_error.log; + access_log /var/log/nginx/company_access.log; +} +EOF + + # Try to reload nginx (will fail silently) + nginx -t > /dev/null 2>&1 || true + systemctl reload nginx 2>/dev/null || systemctl restart nginx 2>/dev/null || true + + print_success "Problem 1 active: company.local has a configuration error" +} + +# ============================================================ +# PROBLEM 2: File Permissions (shop.local) +# Category: File System Permissions +# ============================================================ +break_file_permissions() { + print_break "Breaking shop.local (wrong file permissions)..." + + # Remove all permissions from the website directory + chmod 000 /var/www/shop/index.html + + print_success "Problem 2 active: shop.local has permission issues" +} + +# ============================================================ +# PROBLEM 3: PHP-FPM Service Stopped (api.local) +# Category: Service Management (systemd) +# ============================================================ +break_php_service() { + print_break "Breaking api.local (PHP-FPM service stopped)..." + + # Stop and disable PHP-FPM + systemctl stop php${PHP_VERSION}-fpm + systemctl disable php${PHP_VERSION}-fpm 2>/dev/null + + print_success "Problem 3 active: API returns 502 Bad Gateway (PHP-FPM stopped)" +} + +# ============================================================ +# PROBLEM 4: Firewall Blocking Docker App +# Category: Firewall (UFW) +# ============================================================ +break_firewall() { + print_break "Breaking Docker app access (firewall block)..." + + # Block port 8888 + ufw delete allow 8888/tcp > /dev/null 2>&1 + ufw deny 8888/tcp > /dev/null 2>&1 + + print_success "Problem 4 active: Docker app unreachable (port blocked)" +} + +# ============================================================ +# PROBLEM 5: MySQL User Configuration +# Category: Database Administration +# ============================================================ +break_mysql_user() { + print_break "Breaking MySQL database access..." + + # Drop the working user and create one bound to wrong IP + mysql -e "DROP USER IF EXISTS 'webuser'@'localhost';" + mysql -e "CREATE USER 'webuser'@'10.0.0.1' IDENTIFIED BY 'WebPass123!';" + mysql -e "GRANT ALL PRIVILEGES ON practicedb.* TO 'webuser'@'10.0.0.1';" + mysql -e "FLUSH PRIVILEGES;" + + print_success "Problem 5 active: MySQL connection refused (wrong host binding)" +} + +# ============================================================ +# RESET FUNCTIONS +# ============================================================ +reset_nginx_config() { + print_status "Resetting company.local configuration..." + + cat > /etc/nginx/sites-available/company.local << 'EOF' +server { + listen 80; + server_name company.local; + + root /var/www/company; + index index.html; + + location / { + try_files $uri $uri/ =404; + } + + error_log /var/log/nginx/company_error.log; + access_log /var/log/nginx/company_access.log; +} +EOF + + nginx -t > /dev/null 2>&1 && systemctl reload nginx + print_success "company.local restored" +} + +reset_file_permissions() { + print_status "Resetting shop.local permissions..." + + chmod 644 /var/www/shop/index.html + chown www-data:www-data /var/www/shop/index.html + + print_success "shop.local permissions restored" +} + +reset_php_service() { + print_status "Resetting PHP-FPM service..." + + systemctl enable php${PHP_VERSION}-fpm + systemctl start php${PHP_VERSION}-fpm + + print_success "PHP-FPM service restored" +} + +reset_firewall() { + print_status "Resetting firewall rules..." + + ufw delete deny 8888/tcp > /dev/null 2>&1 + ufw allow 8888/tcp > /dev/null 2>&1 + + print_success "Firewall rules restored" +} + +reset_mysql_user() { + print_status "Resetting MySQL user..." + + mysql -e "DROP USER IF EXISTS 'webuser'@'10.0.0.1';" + mysql -e "DROP USER IF EXISTS 'webuser'@'localhost';" + mysql -e "CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'WebPass123!';" + mysql -e "GRANT ALL PRIVILEGES ON practicedb.* TO 'webuser'@'localhost';" + mysql -e "FLUSH PRIVILEGES;" + + print_success "MySQL user restored" +} + +reset_all() { + echo "" + print_status "Resetting all problems..." + echo "" + + reset_nginx_config + reset_file_permissions + reset_php_service + reset_firewall + reset_mysql_user + + # Restart services + systemctl restart nginx + + echo "" + print_success "All problems have been reset!" + echo "" +} + +# ============================================================ +# START EXAM (ALL PROBLEMS) +# ============================================================ +start_exam() { + echo "" + echo -e "${RED}============================================================${NC}" + echo -e "${RED} STARTING PRACTICE EXAM - 45 MINUTES${NC}" + echo -e "${RED}============================================================${NC}" + echo "" + + print_warning "Introducing 5 problems to the server..." + echo "" + + break_nginx_config + break_file_permissions + break_php_service + break_firewall + break_mysql_user + + # Restart nginx to apply changes + systemctl restart nginx 2>/dev/null || true + + echo "" + echo -e "${RED}============================================================${NC}" + echo "" + print_warning "EXAM STARTED! You have 45 minutes to fix all issues." + echo "" + echo "The following services should be working when you're done:" + echo "" + echo " Task 1: http://company.local - Company Portal" + echo " Task 2: http://shop.local - Online Shop" + echo " Task 3: http://api.local:8080 - REST API" + echo " Task 4: http://localhost:8888 - Docker App" + echo " Task 5: mysql -u webuser -p'WebPass123!' practicedb" + echo "" + echo "Use './verify.sh' to check your progress" + echo "" + echo -e "${RED}============================================================${NC}" + echo "" +} + +# ============================================================ +# VERIFICATION +# ============================================================ +verify_all() { + echo "" + echo "============================================================" + echo " VERIFICATION RESULTS" + echo "============================================================" + echo "" + + PASSED=0 + FAILED=0 + + # Test company.local + echo -n "Task 1 - company.local: " + if curl -s -o /dev/null -w "%{http_code}" http://company.local 2>/dev/null | grep -q "200"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) + else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) + fi + + # Test shop.local + echo -n "Task 2 - shop.local: " + if curl -s http://shop.local 2>/dev/null | grep -q "Online Shop"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) + else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) + fi + + # Test API + echo -n "Task 3 - api.local:8080: " + if curl -s http://api.local:8080 2>/dev/null | grep -q "success"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) + else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) + fi + + # Test Docker app + echo -n "Task 4 - Docker app :8888: " + if curl -s http://localhost:8888 2>/dev/null | grep -q "Docker"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) + else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) + fi + + # Test MySQL + echo -n "Task 5 - MySQL connection: " + if mysql -u webuser -p'WebPass123!' practicedb -e "SELECT 1;" > /dev/null 2>&1; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) + else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) + fi + + echo "" + echo "============================================================" + echo "" + echo -e "Results: ${GREEN}${PASSED} PASSED${NC} | ${RED}${FAILED} FAILED${NC}" + echo "" + + if [ $FAILED -eq 0 ]; then + echo -e "${GREEN}Congratulations! All tasks completed successfully!${NC}" + else + echo -e "${YELLOW}Keep working - ${FAILED} task(s) still need to be fixed.${NC}" + fi + echo "" + echo "============================================================" +} + +# ============================================================ +# MAIN MENU +# ============================================================ +show_menu() { + clear + echo "" + echo -e "${CYAN}============================================================${NC}" + echo -e "${CYAN} PRACTICE EXAM - BREAK SERVER MENU${NC}" + echo -e "${CYAN} Betriebssysteme und Netzwerke${NC}" + echo -e "${CYAN}============================================================${NC}" + echo "" + echo " INDIVIDUAL PROBLEMS:" + echo "" + echo " 1) Break company.local (Nginx config error)" + echo " 2) Break shop.local (File permissions)" + echo " 3) Break api.local (PHP-FPM service)" + echo " 4) Break Docker app (Firewall block)" + echo " 5) Break MySQL (User configuration)" + echo "" + echo " EXAM MODE:" + echo "" + echo " 6) START EXAM (All 5 problems - 45 minutes)" + echo "" + echo " UTILITIES:" + echo "" + echo " 7) Verify all services" + echo " 8) RESET all problems" + echo " 9) Reset specific problem" + echo "" + echo " 0) Exit" + echo "" + echo -e "${CYAN}============================================================${NC}" + echo "" +} + +show_reset_menu() { + echo "" + echo " SELECT PROBLEM TO RESET:" + echo "" + echo " 1) Reset company.local" + echo " 2) Reset shop.local" + echo " 3) Reset api.local (PHP-FPM)" + echo " 4) Reset Docker app (Firewall)" + echo " 5) Reset MySQL user" + echo " 6) Back to main menu" + echo "" +} + +# ============================================================ +# MAIN LOOP +# ============================================================ +while true; do + show_menu + read -p " Select option: " choice + + case $choice in + 1) + break_nginx_config + systemctl restart nginx 2>/dev/null || true + read -p "Press Enter to continue..." + ;; + 2) + break_file_permissions + read -p "Press Enter to continue..." + ;; + 3) + break_php_service + read -p "Press Enter to continue..." + ;; + 4) + break_firewall + read -p "Press Enter to continue..." + ;; + 5) + break_mysql_user + read -p "Press Enter to continue..." + ;; + 6) + start_exam + read -p "Press Enter to continue..." + ;; + 7) + verify_all + read -p "Press Enter to continue..." + ;; + 8) + reset_all + read -p "Press Enter to continue..." + ;; + 9) + show_reset_menu + read -p " Select problem to reset: " reset_choice + case $reset_choice in + 1) reset_nginx_config ;; + 2) reset_file_permissions ;; + 3) reset_php_service ;; + 4) reset_firewall ;; + 5) reset_mysql_user ;; + 6) continue ;; + *) print_error "Invalid option" ;; + esac + read -p "Press Enter to continue..." + ;; + 0) + echo "" + print_status "Goodbye!" + exit 0 + ;; + *) + print_error "Invalid option" + read -p "Press Enter to continue..." + ;; + esac +done diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..f90a71c --- /dev/null +++ b/setup.sh @@ -0,0 +1,442 @@ +#!/bin/bash + +# ============================================================ +# PRACTICE EXAM SETUP SCRIPT +# Betriebssysteme und Netzwerke - 45 Minute Practice Test +# ============================================================ +# This script sets up a server environment with multiple services +# for students to practice system administration troubleshooting +# ============================================================ + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${BLUE}[*]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[✓]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[✗]${NC} $1" +} + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + print_error "This script must be run as root (use sudo)" + exit 1 +fi + +echo "" +echo "============================================================" +echo " PRACTICE EXAM ENVIRONMENT SETUP" +echo " Betriebssysteme und Netzwerke" +echo "============================================================" +echo "" + +# ============================================================ +# STEP 1: Install required packages +# ============================================================ +print_status "Updating package lists..." +apt-get update -qq + +print_status "Installing required packages..." +apt-get install -y -qq nginx mysql-server php-fpm php-mysql docker.io docker-compose ufw curl > /dev/null 2>&1 +print_success "Packages installed" + +# ============================================================ +# STEP 2: Configure Nginx - Website 1 (company.local) +# ============================================================ +print_status "Setting up company.local website..." + +# Create website directory +mkdir -p /var/www/company +cat > /var/www/company/index.html << 'EOF' + + + + + Company Portal + + + +
+

Company Portal

+

Status: Online

+

Welcome to the internal company portal.

+
+ + +EOF + +# Set correct permissions +chown -R www-data:www-data /var/www/company +chmod -R 755 /var/www/company + +# Create Nginx config +cat > /etc/nginx/sites-available/company.local << 'EOF' +server { + listen 80; + server_name company.local; + + root /var/www/company; + index index.html; + + location / { + try_files $uri $uri/ =404; + } + + error_log /var/log/nginx/company_error.log; + access_log /var/log/nginx/company_access.log; +} +EOF + +# Enable site +ln -sf /etc/nginx/sites-available/company.local /etc/nginx/sites-enabled/ +print_success "company.local configured" + +# ============================================================ +# STEP 3: Configure Nginx - Website 2 (shop.local) +# ============================================================ +print_status "Setting up shop.local website..." + +# Create website directory +mkdir -p /var/www/shop +cat > /var/www/shop/index.html << 'EOF' + + + + + Online Shop + + + +
+

Online Shop

+

Status: Online

+

Browse our products and enjoy shopping!

+
+ + +EOF + +# Set correct permissions +chown -R www-data:www-data /var/www/shop +chmod -R 755 /var/www/shop + +# Create Nginx config +cat > /etc/nginx/sites-available/shop.local << 'EOF' +server { + listen 80; + server_name shop.local www.shop.local; + + root /var/www/shop; + index index.html; + + location / { + try_files $uri $uri/ =404; + } + + error_log /var/log/nginx/shop_error.log; + access_log /var/log/nginx/shop_access.log; +} +EOF + +# Enable site +ln -sf /etc/nginx/sites-available/shop.local /etc/nginx/sites-enabled/ +print_success "shop.local configured" + +# ============================================================ +# STEP 4: Configure PHP-FPM API (api.local:8080) +# ============================================================ +print_status "Setting up PHP API on api.local..." + +# Create API directory +mkdir -p /var/www/api +cat > /var/www/api/index.php << 'EOF' + 'success', + 'message' => 'API is running', + 'timestamp' => date('Y-m-d H:i:s'), + 'server' => 'Practice Exam Server', + 'endpoints' => [ + '/health' => 'Health check', + '/info' => 'Server information' + ] +]; + +echo json_encode($response, JSON_PRETTY_PRINT); +?> +EOF + +cat > /var/www/api/health.php << 'EOF' + 'healthy', 'uptime' => shell_exec('uptime -p')]); +?> +EOF + +# Set permissions +chown -R www-data:www-data /var/www/api +chmod -R 755 /var/www/api + +# Detect PHP-FPM version +PHP_VERSION=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;") + +# Create API Nginx config +cat > /etc/nginx/sites-available/api.local << EOF +server { + listen 8080; + server_name api.local; + + root /var/www/api; + index index.php; + + location / { + try_files \$uri \$uri/ =404; + } + + location ~ \.php\$ { + include snippets/fastcgi-php.conf; + fastcgi_pass unix:/var/run/php/php${PHP_VERSION}-fpm.sock; + } + + error_log /var/log/nginx/api_error.log; + access_log /var/log/nginx/api_access.log; +} +EOF + +# Enable site +ln -sf /etc/nginx/sites-available/api.local /etc/nginx/sites-enabled/ +print_success "api.local configured on port 8080" + +# ============================================================ +# STEP 5: Configure MySQL Database +# ============================================================ +print_status "Setting up MySQL database..." + +# Start MySQL if not running +systemctl start mysql +systemctl enable mysql + +# Create database and user +mysql -e "CREATE DATABASE IF NOT EXISTS practicedb;" +mysql -e "CREATE USER IF NOT EXISTS 'webuser'@'localhost' IDENTIFIED BY 'WebPass123!';" +mysql -e "GRANT ALL PRIVILEGES ON practicedb.* TO 'webuser'@'localhost';" +mysql -e "FLUSH PRIVILEGES;" + +# Create test table with data +mysql practicedb << 'EOF' +CREATE TABLE IF NOT EXISTS products ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100) NOT NULL, + price DECIMAL(10,2) NOT NULL, + stock INT DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +INSERT IGNORE INTO products (id, name, price, stock) VALUES +(1, 'Laptop', 999.99, 50), +(2, 'Mouse', 29.99, 200), +(3, 'Keyboard', 79.99, 150), +(4, 'Monitor', 299.99, 75); +EOF + +print_success "MySQL database 'practicedb' configured" + +# ============================================================ +# STEP 6: Configure Docker Application +# ============================================================ +print_status "Setting up Docker application..." + +# Start and enable Docker +systemctl start docker +systemctl enable docker + +# Create Docker app directory +mkdir -p /opt/docker-app +cat > /opt/docker-app/docker-compose.yml << 'EOF' +version: '3' +services: + webapp: + image: nginx:alpine + container_name: practice-webapp + ports: + - "8888:80" + volumes: + - ./html:/usr/share/nginx/html:ro + restart: unless-stopped +EOF + +# Create simple HTML for Docker app +mkdir -p /opt/docker-app/html +cat > /opt/docker-app/html/index.html << 'EOF' + + + + Docker App + + + +
+

Docker Application

+

Running in a container on port 8888

+
+ + +EOF + +# Start Docker container +cd /opt/docker-app +docker-compose up -d +print_success "Docker application started on port 8888" + +# ============================================================ +# STEP 7: Configure Firewall (UFW) +# ============================================================ +print_status "Configuring firewall..." + +# Reset UFW to defaults +ufw --force reset > /dev/null 2>&1 + +# Set default policies +ufw default deny incoming > /dev/null 2>&1 +ufw default allow outgoing > /dev/null 2>&1 + +# Allow required ports +ufw allow 22/tcp > /dev/null 2>&1 # SSH +ufw allow 80/tcp > /dev/null 2>&1 # HTTP +ufw allow 8080/tcp > /dev/null 2>&1 # API +ufw allow 8888/tcp > /dev/null 2>&1 # Docker app +ufw allow 3306/tcp > /dev/null 2>&1 # MySQL (local) + +# Enable firewall +ufw --force enable > /dev/null 2>&1 +print_success "Firewall configured" + +# ============================================================ +# STEP 8: Configure /etc/hosts +# ============================================================ +print_status "Configuring DNS entries in /etc/hosts..." + +# Remove old entries if they exist +sed -i '/company\.local/d' /etc/hosts +sed -i '/shop\.local/d' /etc/hosts +sed -i '/api\.local/d' /etc/hosts + +# Add new entries +echo "127.0.0.1 company.local" >> /etc/hosts +echo "127.0.0.1 shop.local" >> /etc/hosts +echo "127.0.0.1 www.shop.local" >> /etc/hosts +echo "127.0.0.1 api.local" >> /etc/hosts + +print_success "/etc/hosts configured" + +# ============================================================ +# STEP 9: Start and enable services +# ============================================================ +print_status "Starting all services..." + +# Enable and start PHP-FPM +systemctl enable php${PHP_VERSION}-fpm +systemctl start php${PHP_VERSION}-fpm + +# Test and reload Nginx +nginx -t > /dev/null 2>&1 +systemctl enable nginx +systemctl restart nginx + +print_success "All services started" + +# ============================================================ +# FINAL: Verification +# ============================================================ +echo "" +echo "============================================================" +echo " SETUP COMPLETE" +echo "============================================================" +echo "" +print_status "Verifying services..." +echo "" + +# Test each service +echo "Testing services:" +echo "" + +# Test company.local +if curl -s -o /dev/null -w "%{http_code}" http://company.local 2>/dev/null | grep -q "200"; then + print_success "company.local → OK (HTTP 200)" +else + print_error "company.local → FAILED" +fi + +# Test shop.local +if curl -s -o /dev/null -w "%{http_code}" http://shop.local 2>/dev/null | grep -q "200"; then + print_success "shop.local → OK (HTTP 200)" +else + print_error "shop.local → FAILED" +fi + +# Test API +if curl -s http://api.local:8080 2>/dev/null | grep -q "success"; then + print_success "api.local:8080 → OK (JSON response)" +else + print_error "api.local:8080 → FAILED" +fi + +# Test Docker app +if curl -s -o /dev/null -w "%{http_code}" http://localhost:8888 2>/dev/null | grep -q "200"; then + print_success "Docker app :8888 → OK (HTTP 200)" +else + print_error "Docker app :8888 → FAILED" +fi + +# Test MySQL +if mysql -u webuser -p'WebPass123!' practicedb -e "SELECT 1;" > /dev/null 2>&1; then + print_success "MySQL database → OK (Connection successful)" +else + print_error "MySQL database → FAILED" +fi + +echo "" +echo "============================================================" +echo "Server is ready for the practice exam!" +echo "" +echo "Available services:" +echo " - http://company.local (Company Portal)" +echo " - http://shop.local (Online Shop)" +echo " - http://api.local:8080 (REST API)" +echo " - http://localhost:8888 (Docker App)" +echo " - MySQL: webuser@localhost (Database)" +echo "" +echo "Run 'sudo ./break_server.sh' to start the exam" +echo "============================================================" diff --git a/solutions.md b/solutions.md new file mode 100644 index 0000000..f174d6c --- /dev/null +++ b/solutions.md @@ -0,0 +1,271 @@ +# Practice Exam Solutions + +## Task 1: Company Portal Unreachable + +### Diagnosis + +```bash +# Check nginx status +sudo systemctl status nginx + +# Test nginx configuration +sudo nginx -t +# Output: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/company.local:8 + +# View the config file +cat /etc/nginx/sites-available/company.local +``` + +### Problem +The nginx configuration file for company.local has a **missing semicolon** after `index index.html`. + +### Solution + +```bash +# Edit the configuration file +sudo nano /etc/nginx/sites-available/company.local + +# Find this line: + index index.html + +# Change to (add semicolon): + index index.html; + +# Test configuration +sudo nginx -t +# Output: nginx: configuration file /etc/nginx/nginx.conf syntax is ok + +# Reload nginx +sudo systemctl reload nginx +``` + +### Verification +```bash +curl http://company.local +# Should return HTML with "Company Portal" +``` + +--- + +## Task 2: Online Shop Shows 403 Forbidden + +### Diagnosis + +```bash +# Check nginx error log +sudo tail /var/log/nginx/shop_error.log +# Output: open() "/var/www/shop/index.html" failed (13: Permission denied) + +# Check file permissions +ls -la /var/www/shop/ +# Output: ---------- 1 www-data www-data ... index.html +# (No permissions at all!) +``` + +### Problem +The index.html file has **wrong permissions** (chmod 000 - no read/write/execute for anyone). + +### Solution + +```bash +# Fix the file permissions +sudo chmod 644 /var/www/shop/index.html + +# Verify permissions (should show -rw-r--r--) +ls -la /var/www/shop/index.html +``` + +### Verification +```bash +curl http://shop.local +# Should return HTML with "Online Shop" +``` + +--- + +## Task 3: API Returns 502 Bad Gateway + +### Diagnosis + +```bash +# Check nginx error log for API +sudo tail /var/log/nginx/api_error.log +# Output: connect() to unix:/var/run/php/php8.x-fpm.sock failed (2: No such file or directory) + +# Check PHP-FPM status +sudo systemctl status php*-fpm +# Output: Active: inactive (dead) +``` + +### Problem +The **PHP-FPM service is stopped and disabled**. Nginx cannot forward PHP requests. + +### Solution + +```bash +# Find the PHP-FPM version +php -v +# or: ls /etc/php/ + +# Start PHP-FPM (replace 8.3 with your version if different) +sudo systemctl start php8.3-fpm + +# Enable to start on boot +sudo systemctl enable php8.3-fpm + +# Verify it's running +sudo systemctl status php8.3-fpm +# Should show: Active: active (running) +``` + +### Verification +```bash +curl http://api.local:8080 +# Should return JSON with "status": "success" +``` + +--- + +## Task 4: Docker Application Unreachable + +### Diagnosis + +```bash +# Check if Docker container is running +sudo docker ps +# Output: practice-webapp is running (HEALTHY) + +# Check if port is listening +sudo ss -tulnp | grep 8888 +# Output: Shows docker-proxy listening on 8888 + +# Check firewall status +sudo ufw status +# Output: 8888/tcp DENY Anywhere +``` + +### Problem +The **firewall (UFW) is blocking port 8888**. The Docker container is running correctly, but connections are denied. + +### Solution + +```bash +# Remove the deny rule +sudo ufw delete deny 8888/tcp + +# Allow port 8888 +sudo ufw allow 8888/tcp + +# Verify firewall rules +sudo ufw status +# Should show: 8888/tcp ALLOW Anywhere +``` + +### Verification +```bash +curl http://localhost:8888 +# Should return HTML with "Docker Application" +``` + +--- + +## Task 5: Database Connection Refused + +### Diagnosis + +```bash +# Try to connect with the user +mysql -u webuser -p'WebPass123!' practicedb +# Output: ERROR 1045 (28000): Access denied for user 'webuser'@'localhost' + +# Check which users exist (as root) +sudo mysql -e "SELECT user, host FROM mysql.user WHERE user='webuser';" +# Output: webuser | 10.0.0.1 +# (User is bound to wrong IP, not localhost!) +``` + +### Problem +The MySQL user `webuser` is bound to **wrong host IP** (10.0.0.1 instead of localhost). + +### Solution + +```bash +# Connect as root +sudo mysql + +# Create user for localhost (or recreate) +DROP USER IF EXISTS 'webuser'@'10.0.0.1'; +CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'WebPass123!'; +GRANT ALL PRIVILEGES ON practicedb.* TO 'webuser'@'localhost'; +FLUSH PRIVILEGES; +EXIT; +``` + +Or as a one-liner: +```bash +sudo mysql -e "DROP USER IF EXISTS 'webuser'@'10.0.0.1'; CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'WebPass123!'; GRANT ALL PRIVILEGES ON practicedb.* TO 'webuser'@'localhost'; FLUSH PRIVILEGES;" +``` + +### Verification +```bash +mysql -u webuser -p'WebPass123!' practicedb -e "SELECT * FROM products;" +# Should show table with products (Laptop, Mouse, Keyboard, Monitor) +``` + +--- + +## Quick Reference: Problem Summary + +| Task | Service | Problem | Key Fix | +|------|---------|---------|---------| +| 1 | company.local | Missing semicolon in nginx config | Add `;` after `index index.html` | +| 2 | shop.local | Wrong file permissions (000) | `chmod 644 /var/www/shop/index.html` | +| 3 | api.local | PHP-FPM service stopped | `systemctl start php*-fpm` | +| 4 | localhost:8888 | Firewall blocking port | `ufw allow 8888/tcp` | +| 5 | MySQL | User bound to wrong host | Create user for `'webuser'@'localhost'` | + +--- + +## Diagnostic Approach + +For each problem, follow this systematic approach: + +1. **Check the symptom** - What error do you see? + - Connection refused → Service not running or firewall + - 403 Forbidden → Permissions issue + - 502 Bad Gateway → Backend service (PHP-FPM) down + - Connection timeout → Firewall blocking + +2. **Check service status** - Is the service running? + ```bash + systemctl status nginx + systemctl status php*-fpm + docker ps + ``` + +3. **Check logs** - What do the logs say? + ```bash + journalctl -u nginx + tail /var/log/nginx/error.log + ``` + +4. **Check configuration** - Is the config valid? + ```bash + nginx -t + cat /etc/nginx/sites-available/... + ``` + +5. **Check permissions** - Can the service read the files? + ```bash + ls -la /var/www/... + ``` + +6. **Check network** - Is the port accessible? + ```bash + ss -tulnp + ufw status + ``` + +--- + +*Practice Exam Solutions - Betriebssysteme und Netzwerke* diff --git a/tasks.md b/tasks.md new file mode 100644 index 0000000..18a5a37 --- /dev/null +++ b/tasks.md @@ -0,0 +1,149 @@ +# Practice Exam - Betriebssysteme und Netzwerke + +## Exam Information + +- **Duration:** 45 minutes +- **Tasks:** 5 problems to diagnose and fix +- **Allowed:** 1x A4 cheat sheet (front and back) + +--- + +## Scenario + +You are a system administrator for a company. Multiple services on the server have stopped working after a colleague made some changes. Your task is to diagnose and fix all issues. + +--- + +## Task 1: Company Portal Unreachable + +**Service:** http://company.local + +**Problem:** The company portal website is not loading. Users report seeing an error page or the page won't load at all. + +**Expected Result:** The website should display "Company Portal" with "Status: Online" + +**Test Command:** +```bash +curl http://company.local +``` + +**Category:** Web Server Configuration + +--- + +## Task 2: Online Shop Shows 403 Forbidden + +**Service:** http://shop.local + +**Problem:** The online shop returns a "403 Forbidden" error when accessed. + +**Expected Result:** The website should display "Online Shop" with "Status: Online" + +**Test Command:** +```bash +curl http://shop.local +``` + +**Category:** File System Permissions + +--- + +## Task 3: API Returns 502 Bad Gateway + +**Service:** http://api.local:8080 + +**Problem:** The REST API returns a "502 Bad Gateway" error instead of JSON data. + +**Expected Result:** The API should return a JSON response with `"status": "success"` + +**Test Command:** +```bash +curl http://api.local:8080 +``` + +**Category:** Service Management (systemd) + +--- + +## Task 4: Docker Application Unreachable + +**Service:** http://localhost:8888 + +**Problem:** The Docker web application running on port 8888 is not accessible. The connection times out. + +**Expected Result:** The page should display "Docker Application" running in a container. + +**Test Command:** +```bash +curl http://localhost:8888 +``` + +**Hint:** The Docker container itself is running correctly. + +**Category:** Firewall (UFW) + +--- + +## Task 5: Database Connection Refused + +**Service:** MySQL Database + +**Problem:** The web application cannot connect to the MySQL database. Connection attempts with the `webuser` account are being refused. + +**Credentials:** +- Username: `webuser` +- Password: `WebPass123!` +- Database: `practicedb` + +**Expected Result:** Should be able to connect and query the database. + +**Test Command:** +```bash +mysql -u webuser -p'WebPass123!' practicedb -e "SELECT * FROM products;" +``` + +**Category:** Database Administration + +--- + +## Verification + +Run the verification script to check your progress: + +```bash +sudo ./break_server.sh +# Then select option 7) Verify all services +``` + +Or test each service manually with the curl commands above. + +--- + +## Diagnostic Commands Reference + +| Tool | Purpose | +|------|---------| +| `systemctl status ` | Check service status | +| `systemctl start/restart ` | Start or restart service | +| `nginx -t` | Test nginx configuration | +| `journalctl -u ` | View service logs | +| `ufw status` | Check firewall rules | +| `ss -tulnp` | Show listening ports | +| `ls -la ` | Check file permissions | +| `docker ps` | List running containers | +| `cat /var/log/nginx/error.log` | View nginx error logs | + +--- + +## Good Luck! + +Remember to work systematically: +1. Identify the symptom +2. Check service status +3. Review configuration/logs +4. Apply the fix +5. Verify the solution + +--- + +*Practice Exam - Betriebssysteme und Netzwerke* diff --git a/verify.sh b/verify.sh new file mode 100755 index 0000000..75f8fb5 --- /dev/null +++ b/verify.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +# ============================================================ +# PRACTICE EXAM - VERIFICATION SCRIPT +# Run this to check your progress +# ============================================================ + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo "" +echo "============================================================" +echo " PRACTICE EXAM - VERIFICATION" +echo "============================================================" +echo "" + +PASSED=0 +FAILED=0 + +# Task 1: company.local +echo -n "Task 1 - company.local (Nginx Config): " +if curl -s http://company.local 2>/dev/null | grep -q "Company Portal"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) +else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) +fi + +# Task 2: shop.local +echo -n "Task 2 - shop.local (Permissions): " +if curl -s http://shop.local 2>/dev/null | grep -q "Online Shop"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) +else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) +fi + +# Task 3: api.local +echo -n "Task 3 - api.local:8080 (PHP-FPM): " +if curl -s http://api.local:8080 2>/dev/null | grep -q "success"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) +else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) +fi + +# Task 4: Docker app +echo -n "Task 4 - Docker App :8888 (Firewall): " +if curl -s --connect-timeout 3 http://localhost:8888 2>/dev/null | grep -q "Docker"; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) +else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) +fi + +# Task 5: MySQL +echo -n "Task 5 - MySQL Database (User): " +if mysql -u webuser -p'WebPass123!' practicedb -e "SELECT 1;" > /dev/null 2>&1; then + echo -e "${GREEN}PASS${NC}" + ((PASSED++)) +else + echo -e "${RED}FAIL${NC}" + ((FAILED++)) +fi + +echo "" +echo "============================================================" +echo "" +echo -e "Score: ${GREEN}${PASSED}/5 PASSED${NC} | ${RED}${FAILED}/5 FAILED${NC}" +echo "" + +if [ $FAILED -eq 0 ]; then + echo -e "${GREEN}============================================${NC}" + echo -e "${GREEN} CONGRATULATIONS! All tasks completed! ${NC}" + echo -e "${GREEN}============================================${NC}" +elif [ $PASSED -ge 3 ]; then + echo -e "${YELLOW}Good progress! Keep going - ${FAILED} task(s) remaining.${NC}" +else + echo -e "${YELLOW}${FAILED} task(s) still need to be fixed.${NC}" +fi + +echo "" +echo "============================================================"