Skip to content

Caddy HTTPS#2129

Open
Pythoniasm wants to merge 1 commit intogetumbrel:masterfrom
Pythoniasm:pr-caddy-https
Open

Caddy HTTPS#2129
Pythoniasm wants to merge 1 commit intogetumbrel:masterfrom
Pythoniasm:pr-caddy-https

Conversation

@Pythoniasm
Copy link
Copy Markdown

@Pythoniasm Pythoniasm commented May 2, 2026

Caddy HTTPS Proxy Integration for Umbrel

Summary

This merge request adds HTTPS support to Umbrel using Caddy as a reverse proxy server. The implementation enables secure, encrypted connections to all self-hosted apps on the local network, protecting against man-in-the-middle attacks even in untrusted local network environments.

Problem Statement

Umbrel currently serves all apps over unencrypted HTTP, which is vulnerable to:

  • Man-in-the-middle (MITM) attacks on untrusted local networks
  • Credential theft through network sniffing
  • Session hijacking via cookie interception
  • Data exposure of sensitive information transferred between client and server

This is particularly concerning for users on:

  • Public or semi-trusted networks (apartments, co-working spaces, offices)
  • Networks with compromised routers
  • Environments where network-level security cannot be guaranteed

Solution

Integrate Caddy reverse proxy to provide:

  1. Automatic HTTPS with self-signed certificates
  2. Dynamic app routing - apps automatically registered as they start/stop
  3. HTTP to HTTPS redirect - seamless upgrade for all connections
  4. Security headers - HSTS, X-Frame-Options, and other protections
  5. Zero configuration - works out of the box with sensible defaults

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Local Network Clients                     │
│              (https://umbrel.local or IP)                    │
└────────────────────────────────┬────────────────────────────┘
                                 │
                    ┌────────────▼────────────┐
                    │   Caddy Reverse Proxy   │
                    │  (Single Instance)      │
                    │  - Self-signed SSL      │
                    │  - Auto TLS termination │
                    │  - Dynamic routing      │
                    └────────────┬────────────┘
                                 │
              ┌──────────────────┼──────────────────┐
              │                  │                  │
    ┌─────────▼────────┐ ┌──────▼───────┐ ┌───────▼──────┐
    │  App 1 Proxy     │ │  App 2 Proxy │ │  App N Proxy │
    │  (app-proxy:4000)│ │(app-proxy:4001)│ │(app-proxy:400N)│
    └─────────┬────────┘ └──────┬───────┘ └───────┬──────┘
              │                 │                 │
    ┌─────────▼────────┐ ┌──────▼───────┐ ┌───────▼──────┐
    │   App Container  │ │ App Container│ │ App Container│
    └──────────────────┘ └──────────────┘ └──────────────┘

Changes

New Files

Core Module

  • packages/umbreld/source/modules/caddy/index.ts - Main Caddy module
  • packages/umbreld/source/modules/caddy/schema.ts - Settings schema with Zod validation
  • packages/umbreld/source/modules/caddy/config-builder.ts - Caddyfile and JSON config generation
  • packages/umbreld/source/modules/caddy/README.md - Comprehensive documentation

Container

  • containers/caddy/Dockerfile - Caddy container build
  • containers/caddy/Caddyfile.template - Base Caddyfile template

Docker Compose

  • packages/umbreld/source/modules/apps/legacy-compat/docker-compose.caddy.yml - Caddy service definition

Tests

  • packages/umbreld/source/modules/caddy/config-builder.test.ts - Unit tests for config generation
  • containers/caddy/test/docker-compose.yml - Integration test setup
  • containers/caddy/test/Caddyfile.test - Test Caddyfile
  • containers/caddy/test/test.sh - Test runner script

Modified Files

Core Integration

  • packages/umbreld/source/index.ts - Initialize Caddy module on startup
  • packages/umbreld/source/modules/apps/app.ts - Add lifecycle hooks for app registration
  • packages/umbreld/source/modules/apps/legacy-compat/app-environment.ts - Add Caddy environment variables
  • packages/umbreld/source/modules/apps/legacy-compat/docker-compose.app_proxy.yml - Enable PROXY_TRUST_UPSTREAM

Features

Automatic Certificate Generation

  • Self-signed certificates generated on first enable
  • Valid for 10 years with SHA-256 fingerprint
  • Stored in ${UMBREL_DATA_DIR}/caddy/certs/
  • Supports custom certificate paths

Dynamic App Routing

  • Apps automatically registered when started
  • Routes automatically removed when stopped
  • Path-based routing: https://umbrel.local/{app-id}/*
  • No manual configuration required

Security Headers

All responses include:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

Configuration Options

Setting Default Description
enabled false Enable/disable HTTPS proxy
domain umbrel.local Domain name for certificate
httpPort 80 HTTP port for redirects
httpsPort 443 HTTPS port for secure access
forceHttps true Force HTTP → HTTPS redirect

Usage

Enable via API

// Enable Caddy
await umbreld.caddy.setEnabled(true)

// Configure domain
await umbreld.caddy.updateSettings({
  domain: 'myserver.local'
})

// Get certificate fingerprint
const fingerprint = await umbreld.caddy.getCertificateFingerprint()
console.log('SHA256:', fingerprint)

Access Apps

Once enabled, all apps are accessible via HTTPS:

https://umbrel.local/mempool/
https://umbrel.local/nextcloud/
https://umbrel.local/bitcoind/

Testing

Unit Tests

cd packages/umbreld
npm test -- modules/caddy

Integration Tests

cd containers/caddy/test
./test.sh

The integration test:

  1. Generates test certificates
  2. Starts Caddy with test apps
  3. Verifies HTTP → HTTPS redirect
  4. Tests app routing
  5. Validates security headers
  6. Displays certificate information

Backward Compatibility

  • Disabled by default - No impact on existing installations
  • Non-breaking - Existing HTTP access continues to work
  • Opt-in - Users must explicitly enable HTTPS
  • Reversible - Can be disabled without data loss

Security Considerations

Self-Signed Certificates

  • Provides encryption against MITM attacks
  • Browser warnings on first access (expected behavior)
  • Certificate fingerprint available for manual verification
  • Users can trust certificate in OS/browser to eliminate warnings

Network Security

  • All client-to-server traffic encrypted
  • Internal Docker network traffic remains unencrypted (trusted)
  • HSTS prevents protocol downgrade attacks
  • Security headers protect against common web vulnerabilities

Future Enhancements

  • Let's Encrypt support with DNS challenge
  • Local CA mode for trusted certificates
  • Subdomain routing (myapp.umbrel.local)
  • Certificate management UI
  • Access logging and analytics

Performance

  • Caddy written in Go - minimal overhead
  • HTTP/2 support automatic with HTTPS
  • Connection pooling to backend proxies
  • No noticeable performance impact in testing

Migration Path

For New Installations

  1. Umbrel installs with Caddy module included
  2. User enables HTTPS via settings (future UI)
  3. Certificates auto-generated
  4. All apps immediately accessible via HTTPS

For Existing Installations

  1. Update to version with Caddy module
  2. Module starts but remains disabled
  3. User enables HTTPS when ready
  4. Existing sessions unaffected
  5. New connections use HTTPS

Known Limitations

  1. Browser Warnings: Self-signed certificates trigger browser warnings (by design)
  2. Per-Device Trust: Each device must separately trust the certificate
  3. No Mobile Deep Linking: Apps accessed via browser only (future: custom URL scheme)
  4. Port Conflicts: Ports 80/443 must be available (configurable)

Future Work

Short-term

  • UI integration for enable/disable
  • Certificate export/download
  • Certificate fingerprint display in UI
  • Setup wizard for first-time enable

Medium-term

  • Let's Encrypt support (public DNS required)
  • Local CA generation and trust distribution
  • Subdomain routing support
  • WebSocket connection optimization

Long-term

  • mDNS/Bonjour integration for discovery
  • Rate limiting and DDoS protection
  • Access logging and analytics dashboard
  • Multi-domain certificate support

Testing Performed

✅ TypeScript compilation - No errors
✅ Module initialization - Successful
✅ Certificate generation - Working
✅ App registration/unregistration - Working
✅ HTTP to HTTPS redirect - Working
✅ Security headers - Present
✅ Dynamic config reload - Working
✅ Container lifecycle - Clean start/stop

Documentation

  • Module README: packages/umbreld/source/modules/caddy/README.md
  • Inline code comments throughout
  • Test examples in containers/caddy/test/
  • API documentation in code (JSDoc compatible)

Dependencies

  • Caddy 2.7.6 - Modern, efficient reverse proxy
  • OpenSSL - Certificate generation (already present in umbrelOS)
  • No new NPM packages - Uses existing Umbrel dependencies

License

Part of the Umbrel project. Same license as main repository.


Checklist

  • Code follows Umbrel style guidelines
  • TypeScript compilation passes
  • Module integrates with existing architecture
  • Backward compatible (disabled by default)
  • Documentation provided
  • Tests included
  • Security considerations addressed
  • No breaking changes
  • Performance impact minimal

Related Issues

This addresses the need for HTTPS support on untrusted local networks, protecting against MITM attacks and credential theft.

Questions?

See packages/umbreld/source/modules/caddy/README.md for detailed usage instructions and troubleshooting guide.

@Pythoniasm Pythoniasm changed the title Caddy HTTPS App Caddy HTTPS May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant