Security
Naylence provides a progressive security model that lets you start simple and add layers as your requirements grow. You can move from no security to enterprise-grade zero-trust by changing security profiles and setting the appropriate environment variables.
The Security Model, in Order
- Gated (
gated): OAuth2/OIDC admission + basic identity via token claims. - Overlay (
overlay): adds cryptographic envelope signing (tamper-evidence) using public keys. - Advanced (
strict-overlay/ advanced): upgrades identity to X.509/SPIFFE and enables end-to-end confidentiality.
Security Philosophy
Security in Naylence is built around three core principles:
- Progressive enhancement: Start with the simplest model that meets your needs, add more when required
- Configuration over code: Security profiles are configured via environment variables, not code changes
- Defense in depth: Multiple layers work together (admission, identity, encryption)
TLS and Transport Security
Naylence does not provide TLS itself. TLS termination is handled by your deployment infrastructure.
Naylence expects TLS to be established using well-known deployment patterns—typically by running fabric nodes behind reverse proxies that handle TLS termination. In our security examples, we use Caddy as the reverse proxy, but you’re free to choose whatever fits your infrastructure (nginx, Traefik, cloud load balancers, etc.).
TLS vs End-to-End Encryption
| Layer | Scope | What It Protects |
|---|---|---|
| TLS | Single hop | Connection between client and reverse proxy (or between proxies) |
| E2E Encryption | Entire fabric | Message confidentiality across all hops, from sender to recipient |
TLS protects data in transit between two endpoints, but in a distributed fabric messages may traverse multiple nodes (sentinels, intermediaries). The end-to-end encryption provided by the Advanced Security layer is complementary to TLS:
- TLS: Encrypts each individual connection (hop-by-hop)
- Sealed/Channel encryption: Encrypts the message payload so only the intended recipient can decrypt it, regardless of how many nodes it passes through
This means even if an intermediate node is compromised, or if TLS terminates at a proxy, the message content remains confidential.
Recommended Setup
┌─────────────────┐ TLS ┌──────────────────┐
│ Browser/Agent │ ◀────────────▶ │ Reverse Proxy │
└─────────────────┘ │ (Caddy/nginx) │
└────────┬─────────┘
│ internal
▼
┌──────────────────┐
│ Sentinel/Node │
└──────────────────┘For production deployments:
- Always use TLS for external connections (handled by your proxy)
- Add E2E encryption (
sealedorchannel) when you need message confidentiality across the fabric - Use internal networks or mTLS between proxies and nodes for additional defense in depth
Security Profiles at a Glance
| Profile | Admission | Identity | E2E Encryption | License |
|---|---|---|---|---|
| Gated | OAuth2 tokens | JWT claims | None | OSS |
| Overlay | OAuth2 tokens | Public keys | None | OSS |
| Advanced | Welcome service | X.509/SPIFFE | sealed/channel | BSL |
What Each Layer Provides
Admission Control
How a node is authorized to join the fabric:
| Profile | Mechanism | How It Works |
|---|---|---|
open | None | Any node can connect (dev/testing only) |
gated | OAuth2 | Bearer token validated before fabric access |
welcome | Federated admission | Welcome service issues placement + attach tickets |
Identity
How nodes prove who they are:
| Profile | Mechanism | What You Get |
|---|---|---|
gated | JWT claims | Identity from OAuth2 token (no cryptographic binding) |
overlay | Public keys | Raw key exchange during attach (EdDSA) |
strict-overlay | X.509/SPIFFE | Cryptographic workload identity with path binding |
Encryption
How messages are protected:
| Level | What’s Protected | How |
|---|---|---|
| TLS | Transport | Caddy/reverse proxy terminates TLS |
| Envelope signing | Message integrity | EdDSA signatures on each envelope |
| Sealed encryption | Message confidentiality | Per-message ChaCha20-Poly1305 |
| Channel encryption | Session confidentiality | Persistent encrypted channel |
Choosing the Right Profile
Start Here: Do You Need Admission Control?
Do you need to control who can connect?
│
├─ No → Use `open` profile (dev/testing only)
│
└─ Yes → Do you need message integrity beyond TLS?
│
├─ No → Use `gated` profile (OAuth2 admission)
│
└─ Yes → Do you need cryptographic node identity?
│
├─ No → Use `overlay` profile (public key signing)
│
└─ Yes → Use `strict-overlay` profile (X.509/SPIFFE)Quick Decision Matrix
| Requirement | Recommended Profile |
|---|---|
| Development/testing | open |
| Simple authentication | gated |
| Message tamper-evidence | overlay |
| Enterprise zero-trust | strict-overlay |
Configuration
All security behavior is controlled via environment variables:
# Security profile (how nodes communicate)
FAME_SECURITY_PROFILE=overlay
# Admission profile (how nodes join)
FAME_ADMISSION_PROFILE=direct
# Encryption level (for strict-overlay)
FAME_DEFAULT_ENCRYPTION_LEVEL=channel # or: sealed, plaintextCommon Environment Variables
| Variable | Values | Description |
|---|---|---|
FAME_SECURITY_PROFILE | open, gated, overlay, strict-overlay | Security mode |
FAME_ADMISSION_PROFILE | none, direct, welcome | How nodes join |
FAME_DEFAULT_ENCRYPTION_LEVEL | plaintext, channel, sealed | Encryption mode |
FAME_ADMISSION_TOKEN_URL | URL | OAuth2 token endpoint |
FAME_ADMISSION_CLIENT_ID | String | OAuth2 client ID |
FAME_ADMISSION_CLIENT_SECRET | String | OAuth2 client secret |
Next Steps
Explore each security section in detail:
- Gated Security — OAuth2/OIDC admission control
- Overlay Security — Envelope signing with public keys
- Advanced Security — X.509/SPIFFE with end-to-end encryption
- Secure Load Balancing — Channel encryption with sticky routing
Complete runnable examples are available in both naylence-examples-ts and naylence-examples-python
under the examples/security/ directory.