Portfolio / Projects / SysAdmin Lab

SysAdmin Lab

A real, self-managed Linux homelab — not a simulation

Status Ongoing
Goal LPIC-1 (101 & 102) hands-on practice
Environment UTM (Apple Hypervisor) — Debian 13 ARM64

Objectives

Build and run a real Linux server infrastructure from a bare VM, not a guided tutorial
Apply LPIC-1 (101 + 102) course material to real, working services
Practice troubleshooting on real incidents as they happen, including recovery from a failed boot
Document every command, config and decision for future reference

Practice Scenarios

Firewall & Network Security 🛡️
Built a persistent iptables firewall with a default-DROP policy on INPUT, explicit rules for loopback, established connections and SSH, plus localhost-only access for internal services.
$ iptables -P INPUT DROP
$ iptables -A INPUT -i lo -j ACCEPT
$ iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT
$ netfilter-persistent save
✓ Rules survive reboot
iptables netfilter-persistent DROP vs REJECT network security
SSH Hardening & fail2ban 🔐
Switched SSH to key-only authentication, then configured fail2ban and verified it live — simulated a brute-force attempt and watched the IP get banned, then unbanned it manually.
$ ssh-copy-id lpic1
$ sed -i "s/PasswordAuthentication yes/no/" sshd_config
$ systemctl restart sshd
$ fail2ban-client status sshd
Currently banned: 1 IP: 192.168.x.x
$ fail2ban-client set sshd unbanip 192.168.x.x
SSH key auth sshd_config fail2ban brute-force defense
Nginx Reverse Proxy — 5+ Apps 🌐
Configured Nginx as a reverse proxy routing to five self-built Flask apps and a containerized Node/React app, each on its own internal port, with HTTPS and per-app rate/size limits.
$ nginx -t
nginx: configuration file test is successful
$ cat /etc/nginx/sites-available/default
location /convert/ { proxy_pass http://127.0.0.1:5001/; }
location /shiatsu/ { proxy_pass http://127.0.0.1:8080/; }
$ systemctl reload nginx
Nginx reverse proxy HTTPS/self-signed certs proxy_pass
Docker Deployment (Full Stack) 🐳
Installed Docker CE from the official repository and deployed a full React + Node/Express + MySQL application with Docker Compose, debugging real build and networking issues along the way.
$ docker compose up -d
✓ frontend Up 0.0.0.0:8080
✓ backend Up 0.0.0.0:3000
✓ db Up (healthy)
$ docker compose logs backend --tail 20
$ docker compose exec db mysqldump -u root -p shiatsu | gzip > backup.sql.gz
Docker Docker Compose container networking mysqldump
Kernel Boot Failure & Recovery ⚠️
A kernel update left the VM unreachable after reboot. Diagnosed and recovered via a forced shutdown from the hypervisor, then fixed the GRUB configuration — including its submenu indexing syntax.
$ ssh lpic1
ssh: connect to host ... Host is down
# forced power-cycle from the hypervisor console
$ grep GRUB_DEFAULT /etc/default/grub
GRUB_DEFAULT="1>3" # submenu > entry syntax
$ update-grub && reboot
GRUB kernel management boot recovery incident response
Automated Backups (Bash + Anacron) ⏱
Wrote Bash scripts to back up application code and a live MySQL database, with log-based rotation, scheduled via anacron to survive a machine that is not always powered on.
$ cat backup_shiatsu_db.sh
mysqldump ... | gzip > "$BACKUP_DIR/$FILE"
ls -1t *.sql.gz | tail -n +15 | xargs rm -f
$ cat /etc/anacrontab
1 10 backup_shiatsu_db /home/luca/backup_shiatsu_db.sh
Bash scripting anacron mysqldump backup rotation
Permissions Deep Dive: SUID, SGID, ACL 👤
Reproduced SUID/SGID/sticky-bit behaviour hands-on (why passwd can write to /etc/shadow), then used ACLs to grant one specific user access without touching the owner or group.
$ chmod 1777 shared_dir/ # sticky bit
$ ls -l /usr/bin/passwd
-rwsr-xr-x root root # SUID
$ setfacl -m u:collab:rwx file.txt
$ getfacl file.txt
chmod SUID/SGID sticky bit ACL (setfacl/getfacl)

LPIC-1 Progress

System Architecture 90%
Linux Installation & Pkg 90%
GNU & Unix Commands 95%
Devices & Filesystems 75%
Shell & Scripting 90%
Administrative Tasks 90%
Networking Fundamentals 90%
Security 90%