Privacy by architecture
Personal data and sensitive services remain on systems I administer. Private applications use private access paths instead of being exposed simply because they are convenient to reach.
A production-inspired environment for containerized services, private networking, virtualization, observability, automation, resilient storage, and on-demand GPU compute.
A sanitized view of the environment I design and operate daily. Exact addressing, credentials, internal naming and security-sensitive implementation details are omitted.
Public and private ingress, segmented service networks, persistent data, observability and on-demand compute.
Swipe sideways to explore the diagram.
A sanitized model, not a network map. Components are grouped by role; counts, addresses and exact wiring are omitted.
Security is designed as several independent boundaries rather than one perimeter. Each layer assumes the one outside it might fail. Mark a layer as compromised to see what still stands between a request and the data.
All layers intact. Select any layer to assume it has failed.
Illustrates the principles I apply. It is not a reproduction of my firewall, proxy or overlay configuration.
I self-host where it gives me meaningful control over privacy, exposure, data and operations.
Personal data and sensitive services remain on systems I administer. Private applications use private access paths instead of being exposed simply because they are convenient to reach.
I control deployment, updates, storage, service lifecycle and migration. The infrastructure remains understandable and portable instead of depending on one hosted product.
Public ingress is deliberate. Administrative interfaces, internal databases and infrastructure tooling do not need the same exposure model as public web services.
Container networks separate routine application services. Virtual machines provide a stronger boundary when I am testing security tools, untrusted workloads or isolated AI environments.
Application state, redundancy and backups are treated as separate concerns so services can be rebuilt without treating a running container as permanent infrastructure.
Metrics, health checks and history make changes measurable. I want to know what changed and when instead of relying on memory or manual inspection.
I use containers as the default application runtime and virtual machines when I want a stronger security or experimentation boundary.
Long-running services fit naturally into Docker: small isolated processes, repeatable Compose definitions, explicit networks and persistent data kept outside the container lifecycle.
KVM/libvirt gives me a separate kernel and operating environment when isolation matters more than efficiency. That makes VMs useful for security testing and experiments I do not want sharing the normal application environment.
Metrics are collected continuously, kept as history, and visualized, so questions about the system are answered with data instead of by logging in and looking around.
Linux host, containers
Node Exporter for the host, cAdvisor for per-container usage
Scrapes on an interval and stores time series
Dashboards and historical trends
History is the useful part. When something feels slow, I can check whether memory, disk or a single container changed, and when.
RAID keeps services available when a disk fails. It does not protect against deletion, corruption or mistakes, because it faithfully mirrors those too. The storage design treats the two as separate layers.
| Failure | Volumes | RAID | Backups |
|---|---|---|---|
| Container recreated | Covers | n/a | n/a |
| One disk fails | No | Covers | Restore |
| File deleted by mistake | No | Mirrors it | Covers |
| Bad update corrupts data | No | Mirrors it | Covers |
| Controller or host lost | No | No | If off-host |
| Ransomware | No | No | If isolated |
Storage and backup details are intentionally summarized here. Disk layout, schedules, destinations and recovery procedures are not published.
My server stays online for storage, networking, automation and web services. GPU inference is handled by my workstation only when I need it, keeping model traffic local without running a high-power GPU system around the clock.
Orchestration, storage and application interfaces.
Local model inference and GPU-heavy workloads.
Prompts and model traffic stay on infrastructure I control.
The always-on server handles services; the workstation provides GPU acceleration when a workload actually needs it.
High-power hardware does not need to remain active just to keep the rest of the self-hosted environment online.
It started on a $20 used desktop and grew one problem at a time.
A 2011 office PC upgraded to 32 GB of RAM and a few terabytes of disk. First Compose stacks, first reverse proxy, first self-hosted password manager.
A VPN for administration, then Prometheus and Grafana once guessing about resource usage stopped being good enough.
Moved to a PowerEdge T330 with a Xeon, more memory and a hardware RAID controller.
A coordinated encrypted overlay for private access, and KVM for workloads that need a harder boundary.
Local inference runs on a separate GPU workstation when high-compute workloads need it.
Storage redundancy and backup strategy are treated as separate operational layers.
Connected by how they interact here. Select one to jump to where it shows up.