init: added the base files by ai and debugged by hand
it's great but currently it has a basic error which is go nil pointer dereference WIP
This commit is contained in:
126
docs/design.md
Normal file
126
docs/design.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user