Homelab Architecture — AWS

Immich self-host · K3s on 2 EC2 nodes · ~$20/mo · Cloudflare edge · cross-region S3 durability
HTTPS :443
Cloudflare Tunnel · outbound-only
media upload
CRR · logical airgap · delete-marker OFF
WAL archive · pg_basebackup + pg_dump (cross-region)
Session Manager
no SSH · inbound closed
cloud-init → bootstrap secrets (SSM)
Internet / Edge
Visitor
browser / phone
Cloudflare
Cloudflare Edge (Hub)
TLS · WAF · DDoS
Operator
Operator
SSM only · no SSH
Reach every node through
AWS Systems Manager —
Security Groups keep all
inbound ports closed.
AWS · us-east-1 · VPC (no NAT · no bastion)
Public subnet — us-east-1a
EC2
Stateful Control Plane
On-Demand t4g.medium
K3s server + etcdcluster control plane
cloudflaredzero-trust ingress
Traefik Ingresshost-header routing
immich-serverAPI + background jobs
PostgreSQLstateful · PITR
Valkeyin-memory cache
stateful tier — PostgreSQL & Valkey never run on Spot
EC2 Spot
Stateless Spot Worker
Spot t4g.small
immich-machine-learningstateless ML
ML model cacheephemeral EBS
cloud-initauto-join on replace
Spot replaceable — auto-rejoins & re-downloads ML cache
VPC Endpoint
S3 Gateway
VPC Endpoint
free · AWS backbone
No Inbound Ports Open — All Ingress via Cloudflare Tunnel
S3 primary
S3 primary (us-east-1)
versioning on
AWS Systems Manager
Session Manager
Session Manager
no SSH · inbound closed
Parameter Store
Parameter Store
bootstrapping &
node-registration secrets
us-east-2 · cross-region
S3 backup
S3 backup
logical airgap
delete-marker replication OFF
/database/wal/ — 7-day lifecycle
/database/base/ — 30-day lifecycle
WAL + base + dump enable PITR
ingress / media durability (CRR · WAL) operator access (SSM)