CompTIA Linux+ Labs

Master intermediate Linux administration with hands-on labs aligned to CompTIA Linux+ (XK0-006) exam objectives. Package management, firewall security, scripting, and automation.

These Labs Cover All Major Linux Certifications

LPI Linux Essentials CompTIA Linux+ (XK0-006) LPIC-1 (101 & 102) LPIC-2 (201 & 202) LPIC-3 (300 / 303 / 305 / 306)
RHCSA (EX200) RHCE (EX294) RHCA LFCS LFCE LFCA CKA CKAD CKS

CompTIA Linux+ Labs - Module 2

Intermediate Linux administration: package management, services, firewall hardening, shell scripting, and cron automation.

Lab 4: Package Management & Service Control
Intermediate / Terminal + GUI
Scenario: Deploy a Web & Database Stack
Your team lead has asked you to set up a new development server by installing Nginx (web server) and MariaDB (database) using APT package management. You must update the package list, install packages, start and enable services, verify they are running correctly, review logs, and then clean up the database server after testing.

Learning Objectives:

CompTIA Linux+ XK0-006 - Domain 1 & 2
  • Package Management: Use apt to update, install, query, and remove packages
  • Service Control: Manage services with systemctl (start, stop, enable, status)
  • Log Analysis: Use journalctl to review service logs
  • Dependency Mgmt: Understand package dependencies and autoremove

📋 Step-by-Step Instructions

  1. Step 1: Update Package Lists & Check Available Upgrades
    🎯 Goal: Refresh repository metadata and see what's upgradable

    📝 What is apt update?
    APT (Advanced Package Tool) downloads package lists from repositories configured in /etc/apt/sources.list. This does NOT install anything — it only updates the local index so APT knows what versions are available.

    💻 Update the package index:
    sudo apt update

    💻 List upgradable packages:
    apt list --upgradable

    🔍 What to look for:
    • Packages in the "upgradable" list have newer versions available
    • The repository URL shows where the package comes from
    • Running apt update regularly prevents stale installs
    💡 Tip: Always run sudo apt update before installing anything. Stale package lists can cause version conflicts!
    📖 Hint: Check the Package Manager GUI tab — it shows installed packages in real-time as you add them.
  2. Step 2: Install Nginx and MariaDB Server
    🎯 Goal: Install both the web server and database server packages

    📝 What does -y do?
    The -y flag automatically answers "yes" to the confirmation prompt. Without it, APT asks you to confirm before downloading and installing. In scripts, always use -y for unattended installs.

    💻 Install Nginx web server:
    sudo apt install -y nginx

    💻 Install MariaDB database server:
    sudo apt install -y mariadb-server

    💻 Verify Nginx is installed:
    dpkg -l | grep nginx
    💡 Tip: dpkg -l lists ALL installed packages. Pipe it through grep to find specific ones. The ii prefix means "installed".
    ⚠️ Exam Note: Know the difference: apt handles repos and dependencies, dpkg handles individual .deb files. apt calls dpkg under the hood.
  3. Step 3: Start and Enable Nginx
    🎯 Goal: Start the Nginx service and ensure it starts automatically on boot

    📝 start vs enable:
    start — runs the service now (this session only)
    enable — tells systemd to start it automatically on boot
    • You need BOTH for a service that should always be running


    💻 Start Nginx now:
    sudo systemctl start nginx

    💻 Enable Nginx on boot:
    sudo systemctl enable nginx

    💻 Check status:
    sudo systemctl status nginx

    💻 Verify web server responds:
    curl http://localhost
    💡 Tip: Watch the Service Monitor tab — service states update live! Green = running, red = stopped.
    📖 Hint: curl http://localhost sends an HTTP request to the local web server. If Nginx is running, you'll see the default welcome page HTML.
  4. Step 4: Start MariaDB and Review Logs
    🎯 Goal: Start MariaDB and use journalctl to review service logs

    📝 What is journalctl?
    journalctl reads systemd journal logs. Use -u to filter by service (unit). --no-pager prevents pagination, and -n 10 limits to last 10 entries.

    💻 Start and enable MariaDB:
    sudo systemctl start mariadb
    sudo systemctl enable mariadb

    💻 View Nginx logs (last 10 entries):
    sudo journalctl -u nginx --no-pager -n 10
    💡 Exam Tip: journalctl -u <service> is the go-to for troubleshooting any systemd service. Add -f to follow logs in real-time!
  5. Step 5: List Running Services
    🎯 Goal: See all currently running services on the system

    💻 List running services:
    sudo systemctl list-units --type=service --state=running

    🔍 What to look for:
    • Both nginx.service and mariadb.service should appear
    • The "ACTIVE" column should show "active" and SUB column "running"
    • This is how you audit what's running on a production server
    💡 Tip: Use --state=running to filter only active services. Without it, you see ALL units including stopped ones.
  6. Step 6: Stop and Remove MariaDB (Cleanup)
    🎯 Goal: Practice removing packages and cleaning dependencies

    📝 Why autoremove?
    When you install a package, it may pull in dependencies. Removing the package doesn't remove dependencies. apt autoremove cleans up orphaned dependencies that are no longer needed.

    💻 Stop MariaDB:
    sudo systemctl stop mariadb

    💻 Remove MariaDB:
    sudo apt remove -y mariadb-server

    💻 Clean up orphaned dependencies:
    sudo apt autoremove -y
    ⚠️ Warning: apt remove keeps config files. Use apt purge to remove configs too. In production, verify before removing!
    🎓 Checkpoint: You can now install, manage, troubleshoot, and remove packages and services — a core competency for Linux+ Domain 1 & 2!

Linux Terminal

Terminal
Package Manager
Service Monitor
Activity Log
sysadmin@devserver:~$
Installed Packages
apt2.6.1
bash5.2.15
coreutils9.1
systemd252
openssh-server9.2
Package Statistics
Total Installed5
Upgradable3
RepositoryDebian 12 (bookworm)
Last UpdatedNever
Service Status
ServiceStateBoot
sshdrunningenabled
cronrunningenabled
nginxstoppeddisabled
mariadbstoppeddisabled
System Resources
CPU Usage18%
Memory2.1 GB / 4 GB
Recent Activity
[--:--:--]Lab session started. Ready for commands.
Progress: 0/6 tasks completed
Score: 0/100
🎉 After Completing All Steps:

1. Click "Validate Configuration" to see which tasks are complete and which remain.
2. Check the Package Manager and Service Monitor tabs for live dashboards.
💡 Tip: Check the Activity Log tab to review all commands you ran with timestamps!
Lab 5: Firewall Configuration & Security Hardening
Intermediate / Terminal + GUI
Scenario: Harden the Development Server
A recent security audit flagged your development server as having an open firewall and insecure SSH configuration. You need to configure UFW (Uncomplicated Firewall) to restrict incoming traffic, block insecure services like Telnet, harden SSH by disabling root login, and verify the server's security posture using network analysis tools.

Learning Objectives:

CompTIA Linux+ XK0-006 - Domain 3
  • Firewall Management: Configure UFW rules to allow/deny traffic
  • SSH Hardening: Disable root login and verify SSH security
  • Network Analysis: Use ss and iptables to audit open ports
  • Security Auditing: Review login history and firewall status

📋 Step-by-Step Instructions

  1. Step 1: Audit Current Firewall & Network State
    🎯 Goal: Understand the current firewall posture before making changes

    📝 What is UFW?
    UFW (Uncomplicated Firewall) is a user-friendly frontend for iptables. It simplifies firewall management with intuitive commands. iptables is the low-level kernel-level firewall.

    💻 Check UFW status:
    sudo ufw status verbose

    💻 View raw iptables rules:
    sudo iptables -L -n

    🔍 What to look for:
    • UFW status: inactive means NO firewall is protecting you
    • iptables shows ACCEPT all by default — everything is allowed in
    • This is a major security risk on any public-facing server
    💡 Tip: An inactive firewall means ANY network traffic can reach your server. Always enable a firewall before exposing a server to a network!
    📖 Hint: Check the Firewall Dashboard tab to see rules appear as you add them.
  2. Step 2: Set Default Policies and Enable UFW
    🎯 Goal: Configure default deny-incoming / allow-outgoing policy, then activate

    📝 Why deny incoming?
    The principle of "default deny" means block everything, then explicitly allow only what's needed. This is the gold standard for firewall security — whitelisting, not blacklisting.

    💻 Set default deny incoming:
    sudo ufw default deny incoming

    💻 Set default allow outgoing:
    sudo ufw default allow outgoing

    💻 Enable the firewall:
    sudo ufw enable
    ⚠️ Caution: Enabling UFW without allowing SSH (port 22) first can lock you out of a remote server! Always add SSH rule before enabling on remote machines.
    💡 Tip: In this lab environment, it's safe. On a real remote server, run sudo ufw allow 22/tcp BEFORE sudo ufw enable!
  3. Step 3: Allow Essential Services (SSH, HTTP, HTTPS)
    🎯 Goal: Open only the ports needed for SSH and web traffic

    📝 Port numbers to know:
    • Port 22 = SSH (secure remote login)
    • Port 80 = HTTP (unencrypted web)
    • Port 443 = HTTPS (encrypted web)


    💻 Allow SSH access:
    sudo ufw allow 22/tcp

    💻 Allow HTTP:
    sudo ufw allow 80/tcp

    💻 Allow HTTPS:
    sudo ufw allow 443/tcp
    💡 Exam Tip: You can also use service names: ufw allow ssh, ufw allow http. But specifying port/protocol is more explicit and recommended on exams.
  4. Step 4: Harden SSH Configuration
    🎯 Goal: Disable root SSH login to prevent brute-force attacks

    📝 Why disable root login?
    Root is a known username. Attackers try to brute-force root@server first. Disabling root login forces attackers to guess BOTH username and password, making attacks exponentially harder.

    💻 Check current SSH config:
    cat /etc/ssh/sshd_config | grep PermitRootLogin

    💻 Disable root login:
    sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

    💻 Restart SSH to apply changes:
    sudo systemctl restart sshd
    💡 Tip: sed -i edits files in-place. The s/old/new/ syntax replaces the first occurrence of "old" with "new". Watch the Security Dashboard for the change!
    📖 Hint: After restarting sshd, the Security Dashboard will update to show root login is disabled.
  5. Step 5: Block Insecure Services and Verify Rules
    🎯 Goal: Block Telnet (insecure) and verify all firewall rules

    💻 View numbered rules:
    sudo ufw status numbered

    💻 Check open ports:
    ss -tuln

    💻 Block Telnet (port 23):
    sudo ufw deny 23/tcp
    💡 Tip: Telnet (port 23) sends passwords in plain text — it should NEVER be allowed on a production system. Always use SSH (port 22) instead!
  6. Step 6: Final Security Audit
    🎯 Goal: Perform a final review of firewall status and login history

    💻 Full firewall status:
    sudo ufw status verbose

    💻 Review login history:
    sudo lastlog

    🔍 What to verify:
    • Default incoming: DENY (not allow)
    • SSH (22), HTTP (80), HTTPS (443) are ALLOW
    • Telnet (23) is DENY
    • Root SSH login is disabled
    🎓 Checkpoint: Your server is now hardened: firewall enabled, only essential ports open, Telnet blocked, root SSH disabled. These are real-world best practices for Linux+ Domain 3 (Security)!

Linux Terminal

Terminal
Firewall Dashboard
Security Dashboard
Activity Log
sysadmin@devserver:~$
UFW Firewall Status
StatusInactive
Default IncomingALLOW (insecure)
Default OutgoingALLOW
Firewall Rules
#ToActionFrom
No rules configured — firewall inactive
Port Summary
Open PortsAll (no firewall)
Blocked PortsNone
SSH Security
Root LoginEnabled (insecure)
SSH Port22
ProtocolSSHv2
Security Score
OverallLow
Firewall inactive, root login enabled, no port restrictions
Last Login Attempts
rootNever logged in
sysadminActive now
Recent Activity
[--:--:--]Lab session started. Ready for commands.
Progress: 0/6 tasks completed
Score: 0/100
🎉 After Completing All Steps:

1. Click "Validate Configuration" to check firewall rules and SSH hardening status.
2. Check the Firewall Dashboard and Security Dashboard tabs for live security posture.
💡 Tip: The Security Score updates dynamically as you harden the server!
Lab 6: Shell Scripting & Cron Automation
Intermediate / Terminal + GUI
Scenario: Automate Backup & Monitoring
Your operations team needs automated daily backups and system monitoring. You will write a backup shell script that creates timestamped compressed archives, write a monitoring script that checks disk usage and alerts on thresholds, make both scripts executable, test them, and schedule them with cron for unattended execution.

Learning Objectives:

CompTIA Linux+ XK0-006 - Domain 4
  • Shell Scripting: Create and execute Bash scripts with variables and commands
  • File Permissions: Use chmod to make scripts executable
  • Cron Scheduling: Schedule automated tasks with crontab
  • Automation: Combine scripts + cron for unattended operations

📋 Step-by-Step Instructions

  1. Step 1: Create the Backup Script File
    🎯 Goal: Create a new script file and make it executable

    📝 What is a shell script?
    A shell script is a text file containing a series of commands. When executed, the shell reads and runs each command in order. The .sh extension is a convention — Linux uses permissions, not extensions, to determine executability.

    💻 Create the script file:
    touch backup.sh

    💻 Make it executable:
    chmod +x backup.sh

    💻 Verify permissions:
    ls -la backup.sh
    💡 Tip: After chmod +x, you'll see -rwxr-xr-x — the x means execute permission is set. Without it, you'd get "Permission denied"!
    📖 Hint: Check the Script Editor tab to see scripts being built in real-time.
  2. Step 2: Write the Backup Script
    🎯 Goal: Add the shebang line and backup commands to the script

    📝 What is a shebang (#!)?
    The #!/bin/bash line (called shebang) tells the system which interpreter to use. Without it, the default shell runs the script. Always include it for portability.

    💻 Add shebang line:
    echo '#!/bin/bash' > backup.sh

    💻 Add backup command:
    echo 'tar -czvf /tmp/backup-$(date +%Y%m%d).tar.gz /home' >> backup.sh

    💻 Add completion message:
    echo 'echo "Backup completed at $(date)"' >> backup.sh

    💻 Verify script contents:
    cat backup.sh
    💡 Tip: > overwrites the file, >> appends to it. Use > for the first line and >> for subsequent lines!
    ⚠️ Caution: Don't confuse > (overwrite) with >> (append). Using > when you mean >> will erase your script!
  3. Step 3: Test the Backup Script
    🎯 Goal: Run the script and verify it creates the backup archive

    📝 Running scripts:
    You can run a script with bash script.sh or ./script.sh (if executable). Using bash directly doesn't require +x permission — it explicitly calls the interpreter.

    💻 Execute the backup script:
    bash backup.sh

    💻 Verify the backup was created:
    ls -lh /tmp/backup*.tar.gz
    💡 Tip: The wildcard * matches any characters. /tmp/backup*.tar.gz finds all backup archives regardless of the date suffix.
  4. Step 4: Create a Monitoring Script
    🎯 Goal: Write a script that checks disk usage and logs a warning

    💻 Create monitoring script:
    echo '#!/bin/bash' > monitor.sh

    💻 Add disk check command:
    echo 'df -h / | tail -1 | awk "{print \"Disk usage: \" \$5}"' >> monitor.sh

    💻 Add log line:
    echo 'echo "Health check completed at $(date)" >> /tmp/monitor.log' >> monitor.sh

    💻 Make executable and run:
    chmod +x monitor.sh
    bash monitor.sh
    💡 Tip: awk is a powerful text processor. {print $5} prints the 5th column (the "Use%" column from df output).
  5. Step 5: Schedule Scripts with Cron
    🎯 Goal: Use crontab to schedule automated execution

    📝 Cron syntax:
    * * * * * = minute hour day-of-month month day-of-week
    Example: 0 2 * * * = every day at 2:00 AM
    Example: */5 * * * * = every 5 minutes


    💻 Add backup cron job (daily at 2 AM):
    echo '0 2 * * * /home/sysadmin/backup.sh' | crontab -

    💻 Verify crontab:
    crontab -l
    💡 Exam Tip: Memorize cron fields: minute(0-59) hour(0-23) day(1-31) month(1-12) weekday(0-7). Use crontab -e to edit interactively, crontab -l to list.
    📖 Hint: Check the Cron Manager tab to see scheduled jobs appear with schedule breakdowns.
  6. Step 6: Verify Cron Service is Running
    🎯 Goal: Confirm the cron daemon is active and will execute your jobs

    💻 Check cron service status:
    systemctl status cron

    🔍 What to verify:
    • Active: active (running) — cron daemon is operational
    • If stopped, your scheduled jobs won't execute
    • The cron daemon checks crontabs every minute
    🎓 Checkpoint: You can now write shell scripts, make them executable, test them, and schedule them with cron. This is Linux automation — Linux+ Domain 4 (Automation, Orchestration & Scripting)!

Linux Terminal

Terminal
Script Editor
Cron Manager
Activity Log
sysadmin@devserver:~$
backup.sh
# Script not yet created
monitor.sh
# Script not yet created
Files
No scripts created yet
Cron Jobs
ScheduleCommand
No cron jobs configured
Cron Service
StatusRunning
Next CheckEvery 60s
Total Jobs0
Recent Activity
[--:--:--]Lab session started. Ready for commands.
Progress: 0/6 tasks completed
Score: 0/100
🎉 After Completing All Steps:

1. Click "Validate Configuration" to see your completion status and remaining items.
2. Check the Script Editor tab to see your scripts and the Cron Manager for scheduled jobs.
💡 Tip: The Activity Log shows every command with timestamps for review!