https://github.com/fialkaapp/fialka-mailbox
📬 Self-hosted store-and-forward relay for Fialka over Tor. AES-256-GCM, zero server-side decryption, no metadata, Raspberry Pi ready.
https://github.com/fialkaapp/fialka-mailbox
aes-256-gcm cryptography e2e-encryption end-to-end-encryption kotlin mailbox messenger onion-service post-quantum privacy raspberry-pi relay security self-hosted server store-and-forward tor zero-metadata
Last synced: 2 months ago
JSON representation
📬 Self-hosted store-and-forward relay for Fialka over Tor. AES-256-GCM, zero server-side decryption, no metadata, Raspberry Pi ready.
- Host: GitHub
- URL: https://github.com/fialkaapp/fialka-mailbox
- Owner: FialkaApp
- License: gpl-3.0
- Created: 2026-04-07T18:04:37.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-08T01:08:36.000Z (2 months ago)
- Last Synced: 2026-04-08T01:25:31.859Z (2 months ago)
- Topics: aes-256-gcm, cryptography, e2e-encryption, end-to-end-encryption, kotlin, mailbox, messenger, onion-service, post-quantum, privacy, raspberry-pi, relay, security, self-hosted, server, store-and-forward, tor, zero-metadata
- Language: Go
- Homepage: https://fialka.app
- Size: 112 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# fialka-mailbox
> **[English version below](#english)**
---
## Français
Serveur relay auto-hébergé, privacy-first, pour l'écosystème [Fialka](https://fialka.app).
### Ce que c'est
**fialka-mailbox** est un relais store-and-forward **aveugle** : il stocke et transfère des blobs chiffrés sans jamais en voir le contenu. Les messages sont chiffrés par l'application Fialka (PQXDH + Double Ratchet) avant dépôt — le serveur ne voit que du bruit.
- Exposé via **Tor hidden service v3 (.onion)** — aucune IP exposée
- Protocole TCP binaire au lieu de HTTP — surface d'attaque minimale
- Membership contrôlé (liste blanche Ed25519 — pas de relay public ouvert)
- Clé .onion protégée : **passphrase** (argon2id + AES-256-GCM) ou **TPM 2.0** (systemd-creds)
- Binaire statique unique — déployable sur RPi, VPS, Docker
### Installation rapide (Linux / RPi)
```bash
curl -fsSL https://raw.githubusercontent.com/FialkaApp/fialka-mailbox/main/deploy/install.sh | sudo bash
```
L'installeur détecte automatiquement si un **TPM 2.0** est disponible et propose :
1. **TPM 2.0** — clé liée au hardware, redémarrage automatique
2. **Passphrase** — argon2id + AES-256-GCM, saisie à chaque démarrage *(recommandé sans TPM)*
3. **Plaintext** — legacy, non recommandé
### Installation manuelle
```bash
# Cloner
git clone https://github.com/FialkaApp/fialka-mailbox.git
cd fialka-mailbox
# Compiler (Go 1.23+)
go build -o fialka .
# Setup interactif
sudo ./fialka setup
# Démarrer
sudo ./fialka start
```
### Docker
```bash
docker compose up -d
```
La clé .onion est persistée dans le volume `mailbox-data`.
### Commandes
| Commande | Description |
|---|---|
| `fialka setup` | Wizard de configuration interactif (TUI) |
| `fialka start` | Démarrer le daemon relay |
| `fialka stop` | ArrĂŞter le daemon |
| `fialka restart` | Redémarrer le daemon |
| `fialka status` | Statut + adresse .onion |
| `fialka config` | Édition interactive de la configuration |
| `fialka logs` | Logs en temps réel |
| `fialka mailbox` | Gestion membres et invitations |
| `fialka uninstall` | Désinstallation propre |
### Configuration
Fichier : `/etc/fialka-mailbox/config.toml`
```toml
[server]
listen = "127.0.0.1:7333" # Port TCP interne (Tor gère l'exposition)
[tor]
enabled = true
tor_binary = "" # Auto-détecté
data_dir = "" # Défaut: ~/.config/fialka-mailbox/tor
key_protection = "passphrase" # "plaintext" | "passphrase" | "tpm"
cred_name = "onion-key" # Nom du credential systemd (mode tpm)
[storage]
db_path = "mailbox.db"
[limits]
max_message_size = 65536 # 64 Ko par message
max_messages_per_recipient = 100
message_ttl_hours = 168 # 7 jours
max_storage_mb = 500
[security]
rate_limit_deposits = 60 # Dépôts max par IP par minute
require_auth_fetch = true # Auth Ed25519 obligatoire pour la récupération
```
### Protocole
Le serveur utilise un protocole **TCP binaire** (pas HTTP), format :
```
[4 octets : type] [4 octets : longueur payload] [payload]
```
| Type | Code | Description |
|---|---|---|
| DEPOSIT | 0x01 | Dépôt d'un blob chiffré |
| FETCH | 0x02 | Récupération des messages (auth Ed25519) |
| DELETE | 0x03 | Acquittement / suppression |
| FETCH_RESP | 0x04 | Réponse avec les blobs |
| ACK | 0x05 | Accusé de réception |
| ERROR | 0x06 | Erreur protocolaire |
| INVITE_USE | 0x07 | Utilisation d'un token d'invitation |
| MEMBER_LIST | 0x08 | Liste des membres |
**Auth FETCH** : challenge-response Ed25519.
Le serveur ne connaît que `base64(raw 32B pubkey)` — jamais la clé privée, jamais le contenu.
### Membership
```bash
# Générer une invitation (usage unique, 24h)
fialka mailbox invite --max-uses 1 --expires 24h
# Lister les membres
fialka mailbox list
# Révoquer un membre
fialka mailbox revoke
```
### Sécurité — Modèle de menace
**Ce que fialka-mailbox protège :**
- Contenu des messages (chiffrement E2E par Fialka — le serveur voit des blobs opaques)
- Identité des correspondants (seul le hash SHA-256 de la pubkey est stocké)
- Clé .onion au repos en modes passphrase et TPM
**Ce que fialka-mailbox ne protège PAS :**
- Métadonnées de timing (moment du dépôt/récupération)
- Analyse de trafic réseau (Tor atténue mais n'élimine pas)
- Compromission du serveur en cours d'exécution
- Saisie légale du serveur (les blobs chiffrés restent inutilisables pour l'attaquant)
### Stack technique
| Composant | Librairie |
|---|---|
| CLI | `cobra` |
| Wizard setup | `bubbletea` + `huh` |
| Protocole TCP | stdlib `net` |
| Base de données | `modernc/sqlite` (pure Go) |
| Tor | control port (`ADD_ONION ED25519-V3`) |
| Config | `viper` (TOML) |
| Logs | `zerolog` |
| Crypto clé | `golang.org/x/crypto` (argon2id + AES-256-GCM) |
| TTY passphrase | `golang.org/x/term` |
### Licence
GPL-3.0 — voir [LICENSE](LICENSE)
---
## English
Self-hosted, privacy-first message relay for the [Fialka](https://fialka.app) ecosystem.
### What it is
**fialka-mailbox** is a **blind** store-and-forward relay: it stores and forwards encrypted blobs without ever seeing their content. Messages are encrypted by the Fialka app (PQXDH + Double Ratchet) before deposit — the server only sees opaque ciphertext.
- Exposed via **Tor hidden service v3 (.onion)** — no IP address exposed
- Binary TCP protocol instead of HTTP — minimal attack surface
- Controlled membership (Ed25519 allowlist — no open relay)
- .onion key protection: **passphrase** (argon2id + AES-256-GCM) or **TPM 2.0** (systemd-creds)
- Single static binary — deployable on RPi, VPS, Docker
### Quick install (Linux / RPi)
```bash
curl -fsSL https://raw.githubusercontent.com/FialkaApp/fialka-mailbox/main/deploy/install.sh | sudo bash
```
The installer automatically detects if a **TPM 2.0** is available and offers:
1. **TPM 2.0** — hardware-bound key, automatic restart
2. **Passphrase** — argon2id + AES-256-GCM, prompted on every start *(recommended without TPM)*
3. **Plaintext** — legacy, not recommended
### Manual install
```bash
git clone https://github.com/FialkaApp/fialka-mailbox.git
cd fialka-mailbox
# Build (requires Go 1.23+)
go build -o fialka .
# Interactive setup
sudo ./fialka setup
# Start
sudo ./fialka start
```
### Docker
```bash
docker compose up -d
```
The .onion key is persisted in the `mailbox-data` volume.
### Commands
| Command | Description |
|---|---|
| `fialka setup` | Interactive configuration wizard (TUI) |
| `fialka start` | Start the relay daemon |
| `fialka stop` | Stop the daemon |
| `fialka restart` | Restart the daemon |
| `fialka status` | Status + .onion address |
| `fialka config` | Interactive configuration editor |
| `fialka logs` | Tail live logs |
| `fialka mailbox` | Manage members and invitations |
| `fialka uninstall` | Clean uninstall |
### Configuration
File: `/etc/fialka-mailbox/config.toml`
```toml
[server]
listen = "127.0.0.1:7333" # Internal TCP port (Tor handles exposure)
[tor]
enabled = true
tor_binary = "" # Auto-detected
data_dir = "" # Default: ~/.config/fialka-mailbox/tor
key_protection = "passphrase" # "plaintext" | "passphrase" | "tpm"
cred_name = "onion-key" # systemd credential name (tpm mode)
[storage]
db_path = "mailbox.db"
[limits]
max_message_size = 65536 # 64 KB per message
max_messages_per_recipient = 100
message_ttl_hours = 168 # 7 days
max_storage_mb = 500
[security]
rate_limit_deposits = 60 # Max deposits per IP per minute
require_auth_fetch = true # Ed25519 auth required to fetch messages
```
### Protocol
The server uses a **binary TCP protocol** (not HTTP), with the frame format:
```
[4 bytes: type] [4 bytes: payload length] [payload]
```
| Type | Code | Description |
|---|---|---|
| DEPOSIT | 0x01 | Deposit an encrypted blob |
| FETCH | 0x02 | Retrieve messages (Ed25519 auth) |
| DELETE | 0x03 | Acknowledge receipt / delete |
| FETCH_RESP | 0x04 | Response with blobs |
| ACK | 0x05 | Acknowledgement |
| ERROR | 0x06 | Protocol error |
| INVITE_USE | 0x07 | Use an invitation token |
| MEMBER_LIST | 0x08 | List members |
**FETCH auth**: Ed25519 challenge-response.
The server only stores `base64(raw 32B pubkey)` — never the private key, never the content.
### Membership
```bash
# Generate an invitation (single-use, 24h)
fialka mailbox invite --max-uses 1 --expires 24h
# List members
fialka mailbox list
# Revoke a member
fialka mailbox revoke
```
### Security — Threat model
**What fialka-mailbox protects:**
- Message content (E2E encrypted by Fialka — the server sees opaque blobs)
- Correspondent identities (only SHA-256 hash of pubkey is stored)
- .onion key at rest in passphrase and TPM modes
**What fialka-mailbox does NOT protect:**
- Timing metadata (when messages are deposited/retrieved)
- Network traffic analysis (Tor mitigates but does not eliminate)
- A compromised running server
- Legal seizure of the server (encrypted blobs remain useless to an attacker)
### Tech stack
| Component | Library |
|---|---|
| CLI | `cobra` |
| Setup wizard | `bubbletea` + `huh` |
| TCP protocol | stdlib `net` |
| Database | `modernc/sqlite` (pure Go) |
| Tor | control port (`ADD_ONION ED25519-V3`) |
| Config | `viper` (TOML) |
| Logging | `zerolog` |
| Key crypto | `golang.org/x/crypto` (argon2id + AES-256-GCM) |
| TTY passphrase | `golang.org/x/term` |
### License
GPL-3.0 — see [LICENSE](LICENSE)