Projects
Self-directed infrastructure projects, built and running in a personal multi-node homelab.
Linux Home Server & Network Infrastructure
A Dell XPS 13 running Ubuntu Server serves as the always-on NAS and services host for the
homelab, currently running seventeen Docker containers behind a Caddy reverse proxy that
provisions and renews its own Let's Encrypt TLS certificates through the Tailscale daemon.
The entire environment is reachable only across a Tailscale zero-trust mesh with no port
forwarding, so no service is exposed to the public internet, and AdGuard Home runs as the
mesh DNS resolver for network-wide ad and telemetry filtering. Administration is
deliberately split across three tools rather than consolidated into one: CasaOS for
container deployment, Cockpit for system-level and encrypted-drive management, and
Portainer for direct Docker engine control.
Data protection follows a 3-2-1 model that pairs local volume mounts with cross-device
Syncthing replication and AES-256 encrypted cloud backup through Rclone, monitored by SMART
health checks and a Bash alerting layer that pushes any failure to a phone. The security
baseline is key-only SSH hardened against upstream config drift, a default-deny UFW policy,
and Fail2Ban. One representative problem from building it: a backup sweep left pointed at a
stale path with no mount-state guard would, on its next run, have read the missing source as
authoritative and deleted the matching cloud backup to match. Catching that before it ran,
and extending a mount guard across every external-drive sweep so an absent drive becomes a
logged no-op instead of a destructive event, is the kind of silent-failure auditing that
keeps a backup system from quietly destroying the data it exists to protect.
Tech Stack: Ubuntu Server, Docker, CasaOS, Cockpit,
Portainer, Caddy, Tailscale, AdGuard Home, Rclone, Syncthing, UFW, Fail2Ban, Bash
Virtualization & VM Infrastructure
A KVM/QEMU hypervisor managed through virt-manager runs a small fleet of purpose-built
virtual machines on a private NAT network. virt-manager was chosen over the more common
alternatives for specific reasons: GNOME Boxes produced unfixable SPICE display scaling
bugs, and VirtualBox requires recompiling its kernel modules against Fedora's rolling
kernel, which breaks periodically. The fleet includes a headless RHEL system built
specifically for RHCSA preparation, installed with no GUI to match the exam environment and
with the root account enabled to rehearse GRUB-based password recovery, a near-certain exam
task; a Kali environment for graduate cybersecurity coursework; and a sandboxed
malware-analysis VM disguised as a generic accounting workstation to defeat malware that
suppresses its behavior when it detects security tooling.
Installing Docker on the same host broke internet access for the virtual machines, and
fixing it required understanding why. Three independent nftables tables, belonging to
firewalld, libvirt, and Docker, each register rules at the same kernel forwarding hook and
evaluate traffic separately, so a packet that one table permits another can still drop, and
correcting a single layer does nothing for the others. Restoring VM return traffic took two
separate changes: an inter-zone policy for firewalld's own table, and a direct rule for the
packet-filter table that Docker owns, where a Docker version change had left VM traffic with
no matching accept rule. The permissive rule is safe because the machines sit behind NAT on a
private subnet with no port forwarding, so nothing external can initiate a connection
regardless of what the rule allows.
Tech Stack: KVM/QEMU, virt-manager, libvirt, firewalld,
nftables, RHEL, Kali, Lubuntu, UEFI/Q35
Encrypted Storage Architecture
Three external drives are encrypted with LUKS2 and unlock automatically at boot from
keyfiles stored on the already-encrypted root partition, registered in crypttab and mounted
through fstab, with passphrases retained separately in a password manager for recovery.
Devices are always identified by their LUKS UUID rather than by drive letter, since USB
device letters reshuffle on every replug and only the UUID is a stable reference.
The most demanding problem in this area was a hard boot failure on the root volume itself.
The machine dropped into an initramfs recovery shell across every boot entry with no
passphrase prompt at all, and the generic error text pointed at a missing disk. The disk was
fine: kernel logs showed the drive and all of its partitions detected within a second. The
missing passphrase prompt was the real clue, because it meant the initramfs had never been
given an unlock step for the root volume, which placed the fault in the crypttab-to-initramfs
chain rather than in hardware. Four hardware and firmware theories were ruled out in sequence
before the actual cause surfaced: the root volume's encryption entry had gone missing from
crypttab entirely. Recovery was manual from the shell, followed by restoring the entry and
rebuilding the initramfs, using the disappearance of one specific warning as the signal that
the rebuild had actually taken rather than trusting that the command had merely exited
cleanly.
Tech Stack: LUKS2, cryptsetup, crypttab, fstab,
systemd-cryptsetup, initramfs, LVM
Linux Endpoint Administration & Automation
A Fedora Linux laptop serves as the primary workstation and is administered with the same
rigor as the server. Bringing it to a stable state required kernel-level work: one GRUB
parameter (amdgpu.sg_display=0) proved strictly necessary to stop the RDNA 3.5 GPU from
crashing its scheduler and hard-locking the machine, a fix reasoned out from kernel behavior
rather than found in documentation. Routine maintenance runs unattended through user-level
systemd timers, among them a download-sorting daemon, a self-correcting DNS blocklist
updater, and an Rclone cloud backup scheduled deliberately against the server's window so the
two never compete for upstream bandwidth or API quota.
Running local AI inference on the workstation raised a concrete security question, because
the model server has to bind broadly enough for a containerized frontend to reach it, which
would otherwise expose its API on any public Wi-Fi the laptop joins. The answer was firewalld
zone isolation: the port is removed from the public zone and bound only to the Tailscale and
container-loopback zones, so the API answers mesh peers and the local container while staying
invisible everywhere else. A separate break-glass container stack keeps the same tooling
available offline during outages or travel. Malware scanning is intentionally not run on the
laptop but consolidated onto the always-on server, since the workstation's working set
already replicates into the server's scan scope and a machine that is frequently closed
mid-scan is not a dependable host for a twelve-hour job.
Tech Stack: Fedora Linux, systemd (services, timers,
drop-ins), firewalld, GRUB, Bash, Rclone, Docker, Ollama
Version Control & Deployment Infrastructure
A version-controlled Obsidian knowledge base is the source for this portfolio and syncs
across devices over a Syncthing mesh, with one machine acting as a receive-only anchor that
commits changes to a private GitHub repository on a scheduled cron job, from which the site
builds and deploys to Vercel automatically on every push. The instructive failure here was an
overnight build that broke against a commit history nobody had touched. A loose version range
in the project's dependencies let a patch-level upstream update pull in on its own, which
wiped Vercel's build cache and exposed a latent image-path bug the cache had been masking.
Pinning dependencies to exact versions moved cache invalidation onto a controlled schedule
rather than leaving it to fire whenever an upstream maintainer ships a patch, which is a
production-reliability decision rather than a development convenience.
Tech Stack: Git, GitHub, Vercel, Astro, Markdown, Obsidian,
Syncthing, cron, DNS