ibnbattuta Server

Linux Nginx SELinux Flask Gunicorn Git

What It Is

This is the server you're reading this on. A Oracle Linux 9 VM on Oracle Cloud running a fully hardened deployment stack: Nginx reverse-proxying to Gunicorn over a Unix socket, serving a Flask app, with HTTPS via Let's Encrypt, SELinux in enforcing mode, and a self-hosted Git deployment pipeline with automated rollback. Every layer — SSH, firewall, permissions, sudo policies, rate limiting, security headers — was configured by hand, not with Ansible or a tutorial's copy-paste commands.

Why I Built It

I wanted to understand infrastructure the way I understand code: by building it myself and knowing why every decision was made. The project doubles as a learning journal — the blog posts on this site document each step, the mistakes, and the concepts behind them.

What's In It

Multi-user permission model with least-privilege separation: an admin, a deployer, an app runner (nologin), a git-shell-only push user, and nginx. A shared web group with setgid ties them together without over-granting access.

Dual-layer firewall (OCI security list + firewalld), fail2ban on a custom SSH port, and a CSP that starts at script-src 'self'.

Zero-downtime deploys via a post-receive Git hook that backs up, rsyncs, regenerates the RSS feed, installs dependencies, then runs four validation layers (import check, service health, HTTP 200, smoke test) before committing — with automatic rollback on failure.

Monitoring via a Python script checking services, disk, memory, CPU, SSL expiry, and SSH attacks every 5 minutes, with alerts through ntfy.sh. External coverage from UptimeRobot hitting a real blog route, plus a dead man's switch via healthchecks.io.

The full story is in the blog — start with the infrastructure post and read forward.

Status

Active and evolving. Next up: expanding into a portfolio site, containerization with Podman, pipeline hardening, and eventually a real domain.