# Design Decisions ## Why Go? - Single binary — no external dependencies. - Small memory footprint — ~10 MB for a typical deployment. - Fast startup — < 1 second. - Simple to compile and distribute. ## Why not NGINX auth_basic? NGINX's auth_basic is simpler but doesn't support: - IP whitelisting (you'd need the geo module or a third-party module). - Temporary whitelisting (requires config reload). - API-based management. Our auth-gate service fills these gaps while keeping the architecture simple. ## Why not Authelia? Authelia is a full-featured self-hosted auth portal with: - SSO integration - 2FA - MFA - LDAP - OIDC But for our use case: - It's heavier (requires Postgres, Redis, etc.). - It doesn't support temporary whitelisting out of the box. - It requires a login portal. We wanted something simpler. ## Why not Authentik? Authentik is a full-featured identity provider with: - SSO - MFA - OIDC - LDAP - SCIM But it's too heavy for our use case. We just need IP whitelisting + Basic Auth. ## Why not Pomerium? Pomerium is a zero-trust proxy with: - OIDC - MFA - IP-based access control - Policy engine But it's overkill for our use case. We just need IP whitelisting + Basic Auth. ## Why not oauth2-proxy? oauth2-proxy is a reverse proxy with: - OIDC - SSO - MFA But it's designed for OIDC, not for IP whitelisting. ## Why not a custom script? A shell script would work but: - No type safety. - No built-in HTTP server (need to use Python/Node). - No standard library (need to install packages). - No built-in JSON encoding/decoding. Go's standard library is sufficient for our needs. ## Why in-memory temporary whitelist? For a handful of IPs (dozens at most), an in-memory map is: - Simple to implement. - Fast (O(1) lookup). - No external dependencies. If you need persistence across restarts, add a disk-backed store later. ## Why a background cleanup goroutine? Checking expiry on every request adds latency (two map lookups per request). The cleanup goroutine is a one-time cost that keeps the hot path fast. ## Why a file watcher? The permanent whitelist file is the source of truth for permanent whitelisted IPs. We poll the file every 30 seconds (configurable) and reload the in-memory store if the file has changed. ## Why poll instead of inotify? Polling is simpler and works inside Docker containers where inotify may not be available (no host filesystem access). ## Why not use a database? For our use case (a handful of IPs), a database is overkill. We chose an in-memory map + periodic cleanup. ## Why not use Redis? For our use case, Redis is overkill. We chose an in-memory map + periodic cleanup. ## Why not use SQLite? For our use case, SQLite is overkill. We chose an in-memory map + periodic cleanup. ## Why not use a key-value store? For our use case, a key-value store is overkill. We chose an in-memory map + periodic cleanup.