Network & Security

Cloudillo’s network layer uses Rustls with the AWS-LC-RS cryptographic provider for TLS, automatic certificate management via ACME, and runs a dual-server architecture.

TLS architecture

Cloudillo uses Rustls for TLS termination, configured with HTTP/2 (preferred) and HTTP/1.1 via ALPN negotiation.

SNI-based certificate resolution

A custom CertResolver serves the correct certificate for each domain using SNI (Server Name Indication). This is essential for multi-tenant hosting where many users share a single server.

The resolver maintains an in-memory RwLock<HashMap<domain, CertifiedKey>> cache, prepopulated on startup from the database. On a TLS handshake:

  1. Check in-memory cache (fast path, read lock)
  2. On cache miss, load from database on a blocking worker thread
  3. Parse PEM certificate and private key, insert into cache
  4. Return certificate for TLS handshake

Each tenant gets entries for both its canonical domain (cl-o.{id_tag}) and any custom domain.

Certificate management

Cloudillo uses instant-acme to automatically provision and renew TLS certificates from Let’s Encrypt using the HTTP-01 challenge method.

Dual-server setup

  • HTTPS server (primary): Handles all application traffic with TLS via Rustls and the SNI-based certificate resolver
  • HTTP server (optional): Serves ACME HTTP-01 challenge responses at /.well-known/acme-challenge/{token} and redirects everything else to HTTPS

Certificate renewal

A scheduled CertRenewalTask checks all certificates periodically. Certificates expiring within 30 days are automatically renewed. The renewal uses exponential backoff (1s initial, 1.5x factor, 90s timeout) for resilience.

Certificates are stored via the AuthAdapter trait, which provides create_cert, read_cert, delete_cert, and list_domains methods.

Cryptography

Algorithms

Purpose Algorithm Details
Action token signing ES384 (P-384) Federated action tokens between instances
Access tokens HS256 (HMAC-SHA256) Session JWTs, symmetric secret per instance
Web Push (VAPID) ES256 (P-256) Push notification subscription keys
Password hashing bcrypt (cost 10) Per-password random salt
Content hashing SHA256 File IDs, content addressing, deduplication
TLS TLS 1.2/1.3 Rustls defaults, modern cipher suites

Key management

Profile signing keys use the P-384 elliptic curve (ES384). Keys are identified by date-based key IDs (format: YYMMDD) and stored in PKCS#8 PEM format. Each tenant has its own signing key pair:

  • Public key: Published for other instances to verify action tokens
  • Private key: Used to sign outgoing action tokens

A key failure cache (default size: 100 entries) prevents repeated fetch attempts for unreachable remote keys during federation.

Security policies

Memory safety

Cloudillo enforces unsafe_code = "forbid" as a workspace-wide lint, along with strict clippy rules (unwrap_used = "deny", expect_used = "deny", panic = "deny").

CORS

API endpoints use a permissive CORS policy (CorsLayer::very_permissive()). This is intentional: Cloudillo apps run in sandboxed iframes served from the /apps/ directory and need cross-origin access to the API.

Request size limits

File upload size is configurable per tenant via the file.max_file_size_mb setting (default: 50 MiB).

See also