Secret Sender è uno di quei progetti che nascono da un’esigenza quotidiana. Niente teoria, niente grandi piani: solo il bisogno concreto di mandare un’informazione sensibile come una password, un token, una chiave sapendo che, una volta letta, sparisce per sempre. Nessun log, nessun “vediamo dopo”, nessuna copia in giro.

Da lì ho costruito qualcosa che facesse esattamente quello, senza fronzoli: cifratura, link unico, autodistruzione dopo la lettura. Stop. Tutto gira dentro un container, senza database persistenti e senza servizi terzi. Lo accendi, lo usi, lo spegni.

  • FastAPI per il backend: moderno, veloce e scritto come piace a me
  • Redis per la parte temporanea: tiene i segreti in memoria e li fa sparire da solo
  • HTMX per dare movimento all’interfaccia, ma senza buttarmi dentro un framework JS completo

Un’architettura semplice (come dovrebbe essere)

Il flusso è diretto e pulito: l’utente scrive un messaggio o allega un file. Il server lo cifra, lo mette in Redis con una scadenza, e genera un link univoco. Quando il destinatario apre quel link, il sistema recupera il dato, lo decifra e lo mostra una sola volta. Poi lo elimina. Fine della storia.

Perché FastAPI

Avrei potuto usare Flask o Django, ma cercavo qualcosa di più snello e moderno. FastAPI mi ha convinto subito: asincrono, tipizzato e con una sintassi che non sembra del 2005.

Con async/await gestisco in modo pulito upload, cifratura e chiamate a Redis. Il risultato è un’app veloce anche su una VPS economica o dentro un container con risorse limitate.

La validazione con Pydantic poi è una di quelle cose che ti fanno chiedere come hai fatto a vivere senza:

class SecretCreate(BaseModel):
    content: str
    password: Optional[str]
    ttl: int = Field(ge=60, le=86400)

Ogni campo è controllato, e l’API si autodocumenta da sola. Meno errori, meno bug, meno tempo perso.

Perché Redis

Redis è nato per fare esattamente quello che mi serviva: tenere qualcosa in memoria, e cancellarlo dopo un po’. Non serviva un database relazionale, non volevo persistenza. Volevo qualcosa che fosse veloce e volatile.

Quando salvo un secret, uso SETEX per impostare il valore con scadenza. Quando viene letto, uso GETDEL per leggerlo e cancellarlo in un colpo solo:

secret = await redis.getdel(secret_id)
if not secret:
    raise HTTPException(status_code=404, detail="Secret not found or already viewed")

Niente race condition: lettura singola garantita.

HTMX: un front-end che non rompe le scatole

Non volevo mettermi a scrivere JavaScript per gestire due form e un risultato. React o Vue sarebbero stati come sparare con un cannone a una zanzara. Con HTMX faccio tutto con HTML pulito, e il browser fa il resto.

<form hx-post="/send" hx-target="#result" hx-swap="innerHTML">
    <textarea name="secret"></textarea>
    <button type="submit">Invia</button>
</form>

<div id="result"></div>

Il server risponde con un frammento HTML e HTMX lo inietta nella pagina, senza ricaricare tutto.

  • Niente build tool
  • Rendering server-side → più sicurezza
  • HTML leggibile anche senza JS

Il progetto sotto il cofano

app/
├── main.py
├── db.py
├── crypto.py
├── routers/
│   ├── secrets.py
│   ├── view.py
│   └── about.py
├── schemas.py
├── templates/
└── static/

Dentro crypto.py gestisco la parte più delicata: la cifratura con AES-GCM e la derivazione delle chiavi con Scrypt. Ogni secret ha un salt diverso, così anche se due messaggi sono identici, i risultati non lo sono.

Containerizzazione e deploy

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app/ .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Un Dockerfile minimale, un container per l’app e uno per Redis. Li fai partire con docker compose up -d e sei operativo.

E poi?

  • Aggiungere cifratura client-side con WebCrypto
  • Limitare i tentativi e aggiungere rate limiting
  • Gestire file più grandi con streaming cifrato
  • Aggiungere log anonimi e audit di sicurezza

Conclusione

Secret Sender è un progetto piccolo ma concreto. Nasce dal bisogno di avere qualcosa di utile e sicuro, non dall’idea di reinventare l’ennesimo servizio cloud.

Ogni componente ha un ruolo chiaro: FastAPI gestisce la logica, Redis fa da memoria volatile, HTMX tiene il front-end semplice e pulito. Insieme formano qualcosa che fa quello che promette, e basta.