Overview
This site is a small, production-style deployment on Oracle Cloud Infrastructure. Two web servers share the work behind a load balancer, keep no files that matter on their own disks, and hold no cloud credentials. Each request follows the path below; the server that answered yours is highlighted.
- Your browser HTTPS for every page; plain HTTP is redirected
- OCI Load Balancer Terminates TLS with a self-renewing Let's Encrypt certificate, balances traffic, health-checks every server
- KirkStrongWebServer3 Served this page, fault domain 1 VM.Standard.E2.1.Micro KirkStrongWebServer4 Fault domain 3 VM.Standard.E2.1.Micro
- OCI Object Storage Résumé, photos, page content and releases, shared by every server
Infrastructure
The web servers are VM.Standard.E2.1.Micro instances running Oracle Linux Server 8.10. Each is in a different fault domain, so a single hardware failure can't take the site down. They sit in a private subnet with no public IP addresses; the load balancer in the public subnet is the only way in from the internet. The whole environment, from the servers to the load balancer and storage, runs within Oracle's Always Free tier.
Outbound traffic is split by purpose: a NAT gateway for operating system and package updates, and a service gateway for Object Storage, so content traffic never leaves Oracle's network. Security lists allow web traffic to the servers only from the load balancer's subnet.
Security
- No stored credentials. The servers reach Oracle Cloud with Instance Principals. A dynamic group identifies them, and IAM policies limit them to this site's single bucket and to installing certificates on its load balancer.
- Encrypted everywhere. Every page is served over HTTPS with a Let's Encrypt certificate that renews itself and is installed on the load balancer automatically. Plain HTTP redirects to HTTPS, and HSTS tells browsers to insist on it.
- Protected administration. The admin area uses a hashed password, one-hour sessions, CSRF protection and sign-in rate limiting.
- Hardened pages. Every response carries a strict Content Security Policy and related security headers, and edited text is sanitized before it's shown.
- Private photos. Uploaded photos are re-encoded with all metadata removed, including GPS location.
Application and deployment
On each server, Apache httpd sits in front of a Python Flask application running under Gunicorn as a hardened systemd service. Content is read from Object Storage and briefly cached, so an update made from the admin page on either server appears on both within seconds.
New versions are published to Object Storage as release packages. Each server pulls the release using its own identity and installs it, one server at a time, while the load balancer's health check keeps traffic on whichever server is ready.