Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Seal — Chat peer-to-peer crittografata end-to-end. Niente casella di posta. Nessun account da recuperare. Nessuno ascolta — nemmeno noi. | Kitploit
Strumenti/GitHubGitHub/emn4tor/seal
Strumenti di Crittografia/DecrittografiaCrittografiaPrivacy
GitHubemn4tor/seal

Seal

Chat peer-to-peer crittografata end-to-end. Niente casella di posta. Nessun account da recuperare. Nessuno ascolta — nemmeno noi.

Vedi Repository
9113 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Logo di Seal

Seal

Chat peer-to-peer, cifrata end-to-end.
Niente inbox. Nessun account da recuperare. Nessuno ascolta — nemmeno noi.

github.com/Emn4tor/Seal

Rust: 1.97+ Tauri: 2.11.5 React: 19.2 Platforms: macOS, Linux, Windows Encryption: Olm / Megolm Server-side message storage: none

GitHub stars GitHub forks GitHub issues GitHub last commit GitHub repo size

Contributors Total commits

I messaggi viaggiano direttamente tra i peer tramite libp2p e vengono cifrati con i protocolli Olm/Megolm in stile Signal (via vodozemac) prima ancora di lasciare il tuo dispositivo. L'unico server coinvolto è una piccola directory che aiuta i peer a trovare l'indirizzo attuale degli altri. Non vede mai il contenuto dei messaggi e può essere eliminata con un solo comando.

Consulta docs/THREAT_MODEL.md e docs/SECURITY.md per sapere cosa è realmente protetto e come.

Contenuti

  • Schermate
  • Funzionalità
  • Come funziona
  • Struttura del progetto
  • 1. Prerequisiti
  • 2. Compilazione
  • 3. Esecuzione in modalità di sviluppo
  • 4. Test
  • 5. Configurazione del backend (directory server)
  • 6. Utilizzo dell'app

Schermate

Prima esecuzione — scegli un nome; non c'è altro da configurare.

Schermata di primo avvio di Seal: una spiegazione del modello di cifratura accanto a un modulo per il nome visualizzato, con un'opzione di avvio al login



Conversazioni — la barra dei gruppi, l'elenco dei contatti e un pannello di chat cifrata end-to-end.

Una conversazione diretta in Seal, con la barra dei gruppi, l'elenco dei contatti e il pannello di chat cifrata end-to-end



Impostazioni — sensibilità del microfono, push-to-talk, avvio al login, raggiungibilità di rete.

Pannello impostazioni di Seal: sensibilità del microfono, push-to-talk, avvio al login e raggiungibilità di rete

Funzionalità

  • Cifratura end-to-end, sempre — ogni messaggio viene sigillato con Olm (1:1) o Megolm (gruppi) prima ancora di lasciare il tuo dispositivo, usando lo schema in stile Double Ratchet di vodozemac: ogni messaggio ha la propria chiave.
  • Niente inbox, mai — i messaggi viaggiano su una connessione peer-to-peer diretta (libp2p: QUIC/TCP + Noise, con relay e hole-punching per i NAT). Se il destinatario è offline, il messaggio resta in attesa in locale e riprova: non viene mai accodato sull'infrastruttura di altri.
  • Una directory, non un database — l'unico server coinvolto (crates/directory-server) associa un ID utente a un indirizzo di rete corrente e nient'altro. È strutturalmente incapace di leggere il contenuto dei messaggi: il suo Cargo.toml non dipende nemmeno dai crate che saprebbero come farlo.
  • Più account, un solo dispositivo — identità completamente separate (chiavi, contatti, messaggi) tra cui puoi passare senza riavviare.
  • Gruppi con modifiche reali dei membri — canali di testo e voce per gruppo; rimuovere qualcuno ruota la chiave del gruppo così non può leggere nulla inviato in seguito.
  • Voce integrata — push-to-talk con una scorciatoia di sistema (funziona da qualsiasi app, non solo da Seal), sensibilità del microfono regolabile e un voice changer opzionale.
  • Allegati senza metadati — i dati EXIF (posizione GPS, informazioni su fotocamera/dispositivo) vengono rimossi dalle immagini prima dell'invio, attivo per impostazione predefinita.
  • Un vero pulsante di emergenza — Impostazioni → Dati e privacy elimina istantaneamente e irreversibilmente ogni chiave, contatto e messaggio su questo dispositivo, senza alcun effetto su chiunque tu abbia contattato.
  • Avvio al login, se lo desideri — attivo per impostazione predefinita, a un interruttore di distanza nelle Impostazioni.
  • Un'unica codebase, tre piattaforme — finestre native su macOS, Windows e Linux, tramite Tauri.

Come funziona

In questa app esistono due tipi di identità, e sono tenuti volutamente separati:

  • La tua identità di chat è una coppia di chiavi Ed25519/Curve25519 generata localmente da vodozemac la prima volta che apri l'app (identity::Identity). Il tuo "user ID" pubblico è semplicemente l'impronta di quella chiave (wire_proto::user_id_from_ed25519). Non può essere emesso o revocato da alcun server, perché nessun server è coinvolto nella sua creazione.
  • La tua identità di rete è una coppia di chiavi libp2p separata (PeerId), usata solo per il livello di trasporto. Può cambiare tra un riavvio e l'altro senza influire affatto sulla tua identità di chat; le due sono legate solo da un record di presenza che firmi tu stesso.

Trovare qualcuno e parlarci davvero sono due passaggi diversi:``` ┌────────────────────────┐ │ directory server │ │ (axum + one SQLite │ │ file: users, │ │ presence, group │ │ rosters. Never │ │ message content.) │ └─────────┬───────────────┘ 1. "where is bob │ 2. "here's my current right now?" │ address" (signed, │ expires in minutes) ┌─────────┴───────────────┐ ▼ ▼ ┌───────┐ 3. direct libp2p ┌───────┐ │ alice │◄──── connection ────►│ bob │ └───────┘ (Noise + Olm/ └───────┘ Megolm encrypted)

root@kitploit:~
1. Alice cerca Bob nella directory tramite il suo ID utente. Questo restituisce
   le sue chiavi pubbliche e il suo ultimo indirizzo di rete annunciato. È tutto
   ciò che la directory contiene: chiavi pubbliche, nomi di visualizzazione,
   liste di appartenenza ai gruppi e annunci di indirizzo di breve durata
   (`crates/directory-server`).
2. Alice contatta Bob direttamente tramite libp2p (QUIC o TCP+Noise, con relay +
   hole-punching per i peer dietro NAT; vedi `crates/net`). La directory è
   completamente fuori gioco da qui in poi.
3. Il messaggio vero e proprio è cifrato con **Olm** per una chat 1:1, o
   **Megolm** per un gruppo (`crates/crypto-session`), uno schema in stile Double-Ratchet
   in cui ogni messaggio ha la propria chiave, prima di essere messo su
   quella connessione libp2p. Non esiste una casella di posta lato server: se Bob è offline,
   il messaggio attende in locale e viene ritentato, non viene memorizzato su infrastruttura
   di nessun altro.

Tutto quanto sopra è orchestrato dall'`AppService` di `crates/core`, che è
ciò che il backend Rust dell'app Tauri (`apps/desktop/src-tauri`) richiama effettivamente;
la UI non comunica mai direttamente con la rete.

## Struttura del progetto```
crates/
  wire-proto        shared signed-request types for the directory API
  identity          vodozemac identity, OS-keychain key management
  storage           local encrypted store (contacts, messages, groups)
  net               libp2p transport + directory HTTP client
  crypto-session    Olm (1:1) / Megolm (group) session management
  core              orchestrates the above into `AppService` / `ChatNode`
  directory-server  the one server component (axum + SQLite)
apps/desktop         the Tauri + React app
scripts/             build + backend-deployment scripts (§2, §5)

1. Prerequisiti

Hai bisogno di Rust e Node.js su ogni piattaforma, oltre a una toolchain specifica per piattaforma di cui Tauri ha bisogno per creare una finestra nativa. storage e directory-server compilano anche SQLite dal sorgente in bundle, il che richiede un semplice compilatore C (non è richiesta OpenSSL né alcuna altra libreria crittografica nativa in questo progetto).

Comune a tutte le piattaforme:

  • Rust (canale stabile; installa tramite rustup, non tramite il gestore pacchetti del tuo sistema operativo)
  • Node.js 20+ e npm
macOS```sh xcode-select --install ``` Tutto qui. Gli Xcode Command Line Tools forniscono sia il compilatore C che i framework necessari al backend macOS di Tauri (basato su WKWebView).
Linux

Installa un compilatore C, pkg-config, e i pacchetti di sviluppo WebKitGTK/AppIndicator a cui il backend Linux di Tauri si collega.

Debian/Ubuntu:```sh sudo apt update sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev pkg-config

root@kitploit:~
Fedora:```sh
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file \
  libappindicator-gtk3-devel librsvg2-devel pkgconf-pkg-config
sudo dnf group install "C Development Tools and Libraries"

Architettura:```sh sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl
appmenu-gtk-module libappindicator-gtk3 librsvg pkgconf

root@kitploit:~
(I nomi dei pacchetti cambiano tra le release di Tauri: se una build fallisce cercando un
file `.pc` mancante, controlla i
[prerequisiti Tauri Linux attuali](https://v2.tauri.app/start/prerequisites/)
per la tua distribuzione.)

</details>

<details>
<summary><strong>Windows</strong></summary>

1. Installa il **Microsoft C++ Build Tools** (Visual Studio Installer →
   carico di lavoro "Sviluppo desktop con C++"), necessario sia per la shell
   nativa di Tauri sia per compilare il SQLite incluso.
2. Installa il toolchain Rust **MSVC**: `rustup default stable-msvc`.
3. **WebView2**: già presente su Windows 11 e sulla maggior parte delle installazioni
   Windows 10 aggiornate; in caso contrario, la build di Tauri ti chiederà di installare
   il runtime Evergreen.

</details>

---

## 2. Build

Dalla radice del repository:```sh
# Rust workspace (backend crates + the directory server)
cargo build --workspace --release

# Frontend + the actual desktop app bundle (installer/.app/.exe)
cd apps/desktop
npm install
npm run tauri build
Scarica lo strumento

npm run tauri build produce un installer nativo per piattaforma in target/release/bundle/ nella root del repository (questo è un workspace Cargo, quindi tutte le crate, inclusa l'app Tauri, condividono un'unica directory target/ di livello superiore). La cross-compilazione (es. creare l'installer Windows da macOS) non è configurata: compila su ciascuna piattaforma di destinazione, oppure usa il workflow GitHub Actions di Tauri se vuoi release compilate tramite CI.

Oppure usa gli script

scripts/ contiene uno script di build per ogni piattaforma/output, ognuno eseguibile in modo indipendente e verificato per produrre effettivamente un artefatto funzionante:

ScriptProduce
scripts/build-mac-dmg.shInstaller macOS .dmg
scripts/build-mac-app.shBundle macOS .app grezzo, senza installer
scripts/build-linux.shLinux .AppImage + .deb
scripts/build-windows.ps1Windows .msi + .exe (NSIS)

Ognuno si limita a incapsulare npm run tauri build --bundles <...> con i flag giusti e il controllo della piattaforma; esegui tu stesso il comando grezzo se vuoi una diversa combinazione di bundle (npx tauri build --help da apps/desktop).

scripts/release.sh vX.Y.Z incrementa la versione ovunque sia necessario e crea il tag del commit — vedi docs/RELEASING.md. Viene eseguito su macOS e Linux; non esegue commit né push.

Integrare la propria rete "Seal"

La schermata di scelta del server (§3) mostra sempre tre opzioni: Seal (la tua rete ufficiale), Server personalizzato e un piccolo collegamento Server di test locale in fondo. "Seal" è disabilitato (grigio, con "Non ancora configurato in questa build") finché non integrerai un URL al momento della build:```sh SEAL_DEFAULT_DIRECTORY_URL=https://directory.example.com npm run tauri build

root@kitploit:~
Una volta che hai configurato il tuo server (§5) e hai un dominio reale puntato ad esso, imposta questo e ricompila: ogni copia che distribuisci da quel momento in poi mostra "Seal" come un'opzione reale e selezionabile usando quell'URL, senza toccare nessun altro codice. Lascialo non impostato per le build ordinarie/dev: non c'è un server ufficiale ospitato da questo repository, quindi "Seal" rimane disabilitato e gli utenti ripiegano su un server personalizzato o su quello locale, invece che l'app punti silenziosamente a un dominio segnaposto che in realtà non esegue nulla.

---

## 3. Eseguirlo in modalità dev```sh
cd apps/desktop
npm install
npm run tauri dev

Questo avvia il server di sviluppo Vite, compila il backend Rust in modalità debug e apre una finestra nativa con hot-reload sul frontend. La prima compilazione compila l'intero albero delle dipendenze e richiede alcuni minuti; le esecuzioni successive sono veloci.

Scelta del server (primo avvio)

Al primo avvio, Seal chiede quale server di directory usare, in questo ordine:

  • Seal: la rete ufficiale, se questa build ne ha una incorporata (vedi §2). Disabilitata finché non ce l'ha; questo repository non viene distribuito puntando a un dominio segnaposto.
  • Server personalizzato: quello di chiunque, incluso il tuo (§5).
  • Server di test locale: un piccolo collegamento volutamente de-enfatizzato in fondo. Avvia il server embedded dell'app (si lega a 127.0.0.1:47100/47101, dati nella directory app-data del tuo sistema operativo), adatto per provare Seal o testare istanze su una sola macchina, non per una vera implementazione. Se una seconda istanza trova quelle porte già occupate, riutilizza semplicemente il server della prima istanza invece di avviarne un altro, ed è questo che permette a due istanze sulla stessa macchina di trovarsi. È questa la scelta automatica se "Seal" non è configurato e non scegli nient'altro.

La scelta viene salvata (server.json accanto agli altri dati locali dell'app) e riutilizzata silenziosamente a ogni avvio successivo; puoi modificarla da Impostazioni → Server di directory, e la modifica ha effetto al successivo avvio dell'app invece di tentare di hot-swap di una connessione attiva. Per l'uso scriptato/di sviluppo, una variabile d'ambiente salta completamente il prompt:```sh P2P_CHAT_DIRECTORY_URL=https://directory.example.com npm run tauri dev

root@kitploit:~
### Esecuzione di due istanze localmente (per testare realmente la messaggistica)

Ogni istanza ha bisogno della propria identità. Seal supporta più account
nativamente (Impostazioni → Account su questo dispositivo), ma per due *processi
separati* sulla stessa macchina, `P2P_CHAT_PROFILE` è il percorso più rapido: crea
automaticamente (la prima volta) o riprende automaticamente (ogni volta successiva) un account
con quel nome, in modo non interattivo, saltando del tutto il selettore account:```sh
# terminal 1
P2P_CHAT_PROFILE=alice npm run tauri dev

# terminal 2
P2P_CHAT_PROFILE=bob npm run tauri dev

La scelta del server (server.json) e l'elenco degli account (accounts.json) sono entrambi condivisi tra i processi su una singola macchina, non per profilo. La prima istanza che avvii sceglie il server, e ogni profilo successivo (incluso bob qui) lo riutilizza silenziosamente. Entrambe le finestre finiscono sullo stesso server di directory integrato, quindi potete aggiungervi come contatti tramite ID e scambiarvi messaggi.

Il dev server di Vite richiede una porta reale e fissa a cui la webview di Tauri possa puntare, il che normalmente significa che può essere eseguito un solo npm run tauri dev alla volta: il secondo troverebbe la porta 1420 già occupata e fallirebbe subito. npm run tauri è in realtà un piccolo wrapper (apps/desktop/scripts/tauri.mjs) che sceglie la porta libera successiva (1421, 1422, …) per ogni istanza dopo la prima e la collega automaticamente, quindi eseguire i due comandi sopra in due terminali funziona e basta; non devi fare nulla di diverso. Cambia comportamento solo per dev — npm run tauri build e tutto il resto passano direttamente alla CLI reale.

Testare con una build reale (non in modalità dev)```sh

./scripts/run-two-mac-instances.sh # profiles: alice, bob ./scripts/run-two-mac-instances.sh carol dave

root@kitploit:~
Stessa idea di sopra, ma avvia l'app effettivamente compilata (l'output di `build-mac-app.sh` / `build-mac-dmg.sh`, oppure una copia installata in `/Applications`) due volte con diversi `P2P_CHAT_PROFILE` invece di `npm run tauri dev`, più vicino a quello che esegue un utente reale. Stampa i PID e come fermare entrambi.

### Debug

- **Log Rust**: imposta `RUST_LOG` prima di avviare, ad es. `RUST_LOG=debug npm run tauri dev` (oppure `RUST_LOG=p2p_core=debug,net=debug` per restringere il campo). I campi registrati sono limitati ai metadati (ID di peer/gruppo/utente, tipi di errore); vedi [`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/HEAD/docs/SECURITY.md) per capire perché è sicuro lasciarli dettagliati.
- **Frontend**: la finestra di sviluppo è una vera webview; fare clic con il tasto destro → Ispeziona elemento (oppure aprire gli strumenti di sviluppo) funziona come in un normale browser.
- **Crate del backend in isolamento**: ogni crate ha la propria suite di test che puoi eseguire e iterare senza toccare affatto l'interfaccia; vedi §4.
- **Un server directory autonomo**, invece di quello integrato: vedi §5.

---

## 4. Test```sh
# everything
cargo test --workspace

# one crate, e.g. the full backend-to-backend flow a Tauri command would trigger
cargo test -p p2p-core --test app_service

# lint + format check (what CI runs)
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings

# dependency vulnerability scan
cargo install cargo-audit --locked   # once
cargo audit

# frontend type-check + build
cd apps/desktop && npm run build

5. Configurazione del backend (directory server)

Riepilogo di cosa si tratta realmente, dato che è facile immaginare qualcosa di più complesso: un processo axum, un file SQLite, tre tipi di record (chiavi pubbliche, annunci di presenza a breve durata, roster di gruppo), tutte le scritture firmate dalla chiave di identità del chiamante. Non è mai nel percorso di un messaggio. Vedere docs/THREAT_MODEL.md per capire perché questo è vero strutturalmente, e non solo per policy: il Cargo.toml di directory-server non dipende nemmeno dalle crate che sanno leggere il contenuto dei messaggi.

Percorso più rapido: lo script di setup```sh

sudo ./scripts/setup-backend.sh

root@kitploit:~
Interattivo, solo Linux + systemd (vedi l'intestazione dello script per il motivo). Chiede su quale famiglia di distribuzioni ti trovi (Debian/Ubuntu, Fedora/RHEL/Rocky/Alma, Arch/Manjaro, o openSUSE, precompilata con un'ipotesi da `/etc/os-release`, quindi di solito basta un tasto per confermare) e installa i prerequisiti di build di quella distribuzione con una funzione dedicata per famiglia, offre di installare Rust tramite `rustup` se manca, compila il binario di release, crea un utente di sistema dedicato, genera un token di amministrazione, chiede se vuoi che configuri un dominio con HTTPS automatico tramite [Caddy](https://caddyserver.com) (installando Caddy stesso, per distribuzione, ripiegando sul binario statico ufficiale di Caddy se il pacchetto della distribuzione non è disponibile), oppure di limitarsi ad ascoltare su loopback/HTTP semplice se preferisci gestirne tu il front-end, poi scrive e abilita il servizio systemd. Sicuro da rieseguire.
Tutto ciò che segue è quello che lo script fa effettivamente, se preferisci farlo a mano o capirlo prima di eseguirlo.

### macOS: un rapido server di test LAN```sh
./scripts/run-mac-test-server.sh

Non per hosting reale: serve per testare l'app su due dispositivi nella stessa rete (ad es. il tuo Mac + un'altra macchina, o due persone sullo stesso Wi-Fi) senza configurare un dominio, TLS o systemd (che su macOS comunque non esiste). Compila il binario di release, genera un token admin (riusato nelle esecuzioni successive), vincola l'API pubblica a tutte le interfacce e stampa l'URL da usare: l'indirizzo IP LAN reale del tuo Mac (via ipconfig getifaddr), non solo 127.0.0.1, così anche gli altri dispositivi possono raggiungerlo. La porta admin resta in ascolto solo su loopback. Viene eseguito in primo piano; Ctrl-C lo interrompe. I dati risiedono in ~/.seal-test-server.

Esecuzione locale rapida```sh

DIRECTORY_DB_PATH=/var/lib/seal-directory/directory.sqlite3
DIRECTORY_PUBLIC_ADDR=0.0.0.0:8080
DIRECTORY_ADMIN_ADDR=127.0.0.1:8090
DIRECTORY_ADMIN_TOKEN=$(openssl rand -hex 32)
cargo run --release -p directory-server --bin directory-server

root@kitploit:~
| Variable | Required | Meaning |
|---|---|---|
| `DIRECTORY_DB_PATH` | no (predefinito `directory.sqlite3`, cwd) | Dove risiede il singolo file SQLite. La directory padre deve esistere. |
| `DIRECTORY_PUBLIC_ADDR` | no (predefinito `0.0.0.0:8080`) | L'API rendezvous a cui le app si rivolgono. Va bene esporla pubblicamente. |
| `DIRECTORY_ADMIN_ADDR` | no (predefinito `127.0.0.1:8090`) | L'endpoint di purge. Tienilo fuori da Internet pubblico; vedi sotto. |
| `DIRECTORY_ADMIN_TOKEN` | **sì** | Token Bearer per l'API di amministrazione. Il processo rifiuta di avviarsi senza uno. Generane uno con `openssl rand -hex 32` o simile; non riutilizzarlo altrove. |

Il processo registra nei log gli indirizzi su cui è in ascolto all'avvio e avvisa chiaramente se
`DIRECTORY_ADMIN_ADDR` non è in loopback.

### Puntare l'app al server

Tre modi, nell'ordine in cui normalmente li useresti:

1. **Schermata di primo avvio**: scegli "Server personalizzato" e inserisci l'URL. Vedi §3.
2. **Impostazioni → Server di directory**: puoi cambiarlo in seguito; ha effetto al prossimo
   riavvio.
3. **`P2P_CHAT_DIRECTORY_URL`**, impostata prima dell'avvio: salta interamente
   la richiesta e sovrascrive qualunque valore salvato, utile per esecuzioni di sviluppo/script:   ```sh
   P2P_CHAT_DIRECTORY_URL=https://directory.example.com npm run tauri dev

Chiunque voglia trovarsi deve puntare alla stessa istanza di directory; è così che si cercano a vicenda.

Eseguirlo come un vero servizio (systemd)

Mostra l'unità systemd + note```ini # /etc/systemd/system/seal-directory.service [Unit] Description=Seal directory server After=network.target

[Service] Type=simple User=seal-directory Group=seal-directory Environment=DIRECTORY_DB_PATH=/var/lib/seal-directory/directory.sqlite3 Environment=DIRECTORY_PUBLIC_ADDR=127.0.0.1:8080 Environment=DIRECTORY_ADMIN_ADDR=127.0.0.1:8090 EnvironmentFile=/etc/seal-directory/admin-token.env ; DIRECTORY_ADMIN_TOKEN=... ExecStart=/usr/local/bin/directory-server Restart=on-failure

Sandboxing: this process needs almost nothing

ProtectSystem=strict ProtectHome=true PrivateTmp=true NoNewPrivileges=true ReadWritePaths=/var/lib/seal-directory

[Install] WantedBy=multi-user.target

root@kitploit:~
Note:

- `DIRECTORY_PUBLIC_ADDR` è volutamente associato a **loopback**; metti un
  reverse proxy davanti per TLS (vedi sotto) invece di esporre axum direttamente
  a internet.
- Crea prima l'utente/gruppo di sistema `seal-directory` e
  `/var/lib/seal-directory` (`useradd --system --no-create-home
  seal-directory && install -d -o seal-directory -g seal-directory
  /var/lib/seal-directory`), poi copia il binario `directory-server` compilato
  (da `target/release/`) in `/usr/local/bin/`.
- Metti il token admin in un `EnvironmentFile` leggibile solo da root, non direttamente
  nel file unit (i file unit sono spesso leggibili da tutti).

</details>

### TLS tramite un reverse proxy

<details>
<summary>Mostra la configurazione di Caddy / nginx</summary>

[Caddy](https://caddyserver.com) ti offre HTTPS automatico con il minimo
di configurazione:```
# /etc/caddy/Caddyfile
directory.example.com {
    reverse_proxy 127.0.0.1:8080
}

caddy run (o systemctl enable --now caddy) gestisce l'emissione e il rinnovo dei certificati autonomamente. Se preferisci usare nginx, termina la TLS lì e usa proxy_pass http://127.0.0.1:8080;, poiché l'app ha bisogno solo di HTTP semplice dal punto di vista del proxy.

Per quanto riguarda il firewall: solo la porta pubblica deve essere raggiungibile dall'esterno (8080 negli esempi precedenti, con la 443 come front-end tramite il proxy). La porta di amministrazione non dovrebbe mai essere raggiungibile dall'esterno; raggiungila tramite port-forwarding SSH (ssh -L 8090:127.0.0.1:8090 your-server) quando devi eseguire una pulizia da remoto.

Come eseguire la pulizia```sh

cargo run --release -p directory-server --bin directory-admin --
--admin-url http://127.0.0.1:8090 --token "$DIRECTORY_ADMIN_TOKEN" purge

root@kitploit:~
Questo elimina il file SQLite e ricrea uno schema vuoto: nessuna istruzione `DELETE`,
nessuno stato parziale. È sicuro eseguirlo senza avvisare prima nessuno:
ogni record in esso è una cache di dati che ciascun client possiede già localmente
(la propria registrazione, presenza e qualsiasi elenco di gruppo di cui è membro),
quindi i client lo ripopolano entro pochi istanti dalla loro azione successiva.
Non esiste deliberatamente alcuna policy di backup per questo database; vedi
[`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/HEAD/docs/SECURITY.md) per capire perché mantenerne una minerebbe
l'intero scopo.

---

## 6. Usare l'app

1. **Primo avvio, prima domanda**: quale server di directory usare (§3).
   Il predefinito è ciò che è incorporato nella build in esecuzione (un server
   di test locale, a meno che chi l'ha creata non ne abbia configurato uno ufficiale); scegli
   "Server personalizzato" per puntare a uno ospitato da te o da qualcuno di cui ti fidi.
2. **Scegli un nome visualizzato.** Questo genera una coppia di chiavi private sul tuo
   dispositivo (niente da ricordare, e nulla di recuperabile se perso: è
   intenzionale) e ti guida attraverso una breve spiegazione in-app di come la
   crittografia funziona davvero. Puoi rivederla in qualsiasi momento dalle Impostazioni. Ogni successivo
   avvio torna direttamente all'app senza alcun prompt; questo accade solo una volta per
   account. Aggiungi altri account (identità completamente separate) da Impostazioni →
   Account su questo dispositivo e passa dall'uno all'altro senza riavviare.
3. **Aggiungi qualcuno**: clicca su **+** accanto a "Direct messages" e inserisci il suo
   ID (trovato nelle *sue* Impostazioni → La mia identità). Non c'è una directory da
   consultare, per scelta progettuale; ti connetti allo stesso modo in cui condivideresti un numero di telefono.
4. **Scrivi loro**: scegli il loro nome dall'elenco e digita. Il primo
   messaggio a qualcuno stabilisce automaticamente una sessione crittografata.
5. **Crea un gruppo**: clicca su **+** nella barra delle icone, dagli un nome, poi invita
   le persone tramite ID allo stesso modo. Rimuovere qualcuno ruota la chiave del gruppo così
   non possono leggere nulla inviato in seguito.
6. **Elimina tutto**: Impostazioni → Dati e privacy. Questa azione è immediata,
   solo locale e irreversibile: distrugge le tue chiavi, i contatti e la
   cronologia su *questo dispositivo* e non ha alcun effetto su nessuno con cui hai parlato.