Architecture
Flux is built on a Hexagonal Architecture (also known as Ports and Adapters) pattern. This ensures a strict separation between the core logic (Forms, Validations), the driving adapters (HTTP Server, SSH Interface), and the driven adapters (Database, SMTP, Captcha Providers).
The Tech Stack
Flux leverages a modern Go ecosystem to deliver a lightweight, single-binary experience without external dependencies.
- Language: Go (Golang) 1.25+
- TUI Framework: Bubble Tea & Huh
- SSH Server: Wish
- HTML Rendering: Templ
- Database: SQLite via GORM
Single Binary Structure
Unlike traditional web apps that require a separate database server, queue worker, and admin dashboard, Flux runs everything in a single process.
When you start Flux, it launches two concurrent servers:
HTTP Server (
:8080)- Role: Public Interface.
- Function: Serves the HTML forms to users and handles submissions via standard POST or HTMX.
- Access: It has read-only access to form definitions and write-only access for collecting submissions.
SSH Server (
:2222)- Role: Management Controller.
- Function: Serves the TUI (Text User Interface) over SSH. This is where you create forms, view logs, and configure secrets.
- Access: Full CRUD (Create, Read, Update, Delete) capabilities.
Security Model
Security is the primary design constraint of Flux. We minimize the blast radius using strong encryption and strict access controls.
1. Encryption at Rest
Flux uses AES-GCM (Advanced Encryption Standard in Galois/Counter Mode) to encrypt sensitive configuration data before it is written to the SQLite database.
- Encrypted: SMTP Passwords, Captcha Secret Keys, Webhook URLs.
- Plaintext: Form titles, field labels, CSS configs (data necessary for public rendering).
2. The RAM-Only Master Key
Flux never stores your decryption key on the disk. This prevents an attacker who steals your database file from accessing your third-party credentials.
- Setup: On the first run, you define a Master Password.
- Derivation: Flux uses Argon2id (a memory-hard password hashing algorithm) to derive a 32-byte encryption key from your password.
- Operation: This key is held in RAM only.
- Lockdown: If the server reboots or crashes, the RAM is cleared. The database automatically enters a "Sealed" state until you manually unlock it via SSH.
3. Database Isolation
We use SQLite with Write-Ahead Logging (WAL) enabled.
- Concurrency: WAL mode allows the HTTP server and SSH server to access the data simultaneously without locking issues.
- Portability: Your entire state lives in
flux.db.
4. CORS Protection (Cross-Origin Resource Sharing)
To prevent malicious sites from embedding your forms or spamming your API, Flux enforces strict CORS policies.
- Configuration: For each form, you can define a list of Authorized Domains (e.g.,
https://mysite.com). - Enforcement: If a request originates from an unauthorized domain (e.g.,
https://evil-site.com), Flux blocks the request immediately with a generic error, protecting your inbox from cross-site attacks.
5. SSH Access Control (Authorized Keys)
By default, Flux accepts SSH connections from any client (Development Mode). This is convenient for testing but insecure for production.
You can lock down the management interface by providing a standard authorized_keys file.
How to secure your instance:
- Generate/Find your Public Key:
On your local machine, run:cat ~/.ssh/id_ed25519.pub - Register it with Flux:
Run this command on the server where Flux is installed (inside the Flux directory):
# Replace contents with your actual public key if not running locally
cat ~/.ssh/id_ed25519.pub > data/authorized_keys
- Restart Flux.
Result: Flux will now reject any connection attempt that does not provide the matching private key with Permission denied (publickey).