Caddy Integration
OnTree seamlessly integrates with Caddy to provide automatic HTTPS certificates and easy domain management for your applications. This allows you to expose your apps securely at custom domains like https://app.yourdomain.com
.
How It Works
OnTree uses Caddy's Admin API to dynamically configure reverse proxy routes:
- You request a subdomain for your app
- OnTree configures Caddy with the routing rules
- Caddy obtains HTTPS certificates automatically
- Your app becomes accessible at the custom domain
Setting Up Integration
Prerequisites
Before using domain features:
- Caddy installed with admin API enabled
- Domain configured (public or Tailscale)
- DNS pointed to your server
- Ports 80 & 443 accessible
Quick Setup
- Install Caddy (see Domain Setup)
- Configure domains in OnTree:
PUBLIC_BASE_DOMAIN=example.com treeos
- Verify integration - Check app detail pages for Domain & Access section
Using Domain Management
Exposing an App
- Navigate to your app in OnTree
- Find Domain & Access section
- Enter subdomain (e.g.,
chat
,wiki
,cloud
) - Click "Expose App"
OnTree will:
- Configure Caddy reverse proxy
- Set up HTTPS automatically
- Make app available immediately
Subdomain Guidelines
Choose subdomains wisely:
- Descriptive:
photos
notapp1
- Short:
wiki
notmy-personal-wikipedia
- Valid: Lowercase letters, numbers, hyphens
- Unique: Each subdomain used once
Managing Exposed Apps
For exposed apps, you can:
- View URLs - See all access methods
- Check status - Verify subdomain availability
- Unexpose - Remove public access
- Change subdomain - Unexpose and re-expose
Domain Types
Public Domains
For internet-accessible applications:
public_base_domain = "example.com"
Features:
- Accessible from anywhere
- Automatic Let's Encrypt certificates
- Perfect for public services
Tailscale Domains
For private, secure access:
tailscale_base_domain = "machine.tail-scale.ts.net"
Features:
- Only accessible within Tailnet
- Built-in authentication
- Ideal for internal tools
Using Both
Configure both for flexibility:
public_base_domain = "example.com"
tailscale_base_domain = "machine.tail-scale.ts.net"
Choose per-app whether to use public or private domain.
Advanced Configuration
Custom Headers
Add security headers via Caddy:
app.example.com {
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
}
Path-Based Routing
Expose apps at paths instead of subdomains:
example.com/app1 -> localhost:3001
example.com/app2 -> localhost:3002
(Configuration coming soon)
Wildcard Certificates
Caddy automatically handles wildcard certificates:
- Single certificate for
*.example.com
- Covers all subdomains
- Automatic renewal
Security Features
Automatic HTTPS
All exposed apps get:
- SSL/TLS encryption - Data in transit protected
- HTTP → HTTPS redirect - Force secure connections
- Modern cipher suites - Strong encryption
- Certificate renewal - Automatic before expiry
Access Control
Implement access restrictions:
Basic Authentication
app.example.com {
basicauth {
admin $2a$14$Zkx19XV...
}
reverse_proxy localhost:3000
}
IP Whitelisting
app.example.com {
@allowed {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
handle @allowed {
reverse_proxy localhost:3000
}
respond "Access denied" 403
}
Rate Limiting
Protect against abuse:
app.example.com {
rate_limit {
zone dynamic 100r/m
}
reverse_proxy localhost:3000
}
Troubleshooting
Common Issues
"Caddy is not available"
-
Check Caddy is running:
systemctl status caddy
-
Verify admin API:
curl http://localhost:2019/config/
-
Check firewall allows localhost:2019
Certificate Errors
-
Check DNS propagation:
dig subdomain.example.com
-
Verify ports 80/443 are open:
sudo ufw status
-
Check Caddy logs:
journalctl -u caddy -f
Subdomain Not Working
- Verify DNS wildcard record exists
- Check subdomain doesn't conflict
- Test direct access to app port
- Review OnTree logs for errors
Debug Mode
Enable detailed logging:
# OnTree config
debug = true
caddy_debug = true
Check logs for:
- Caddy API requests
- Response details
- Configuration sent
Best Practices
Domain Organization
Structure your subdomains:
- By function:
api
,admin
,public
- By environment:
dev-
,staging-
,prod-
- By project:
project1-
,project2-
Security Hardening
- Use strong subdomains - Avoid common names
- Enable monitoring - Watch for unusual traffic
- Regular updates - Keep Caddy current
- Backup configurations - Save Caddy config
Performance
Optimize for speed:
- Enable HTTP/2 - Caddy does this automatically
- Configure compression - Reduce bandwidth
- Set cache headers - Improve load times
- Use CDN - For static assets
Integration Examples
WordPress with Custom Domain
- Deploy WordPress from template
- Expose at
blog.example.com
- Update WordPress settings:
- WordPress Address:
https://blog.example.com
- Site Address:
https://blog.example.com
- WordPress Address:
Nextcloud with Tailscale
- Deploy Nextcloud
- Expose on Tailscale domain
- Access securely from anywhere via Tailnet
- No public internet exposure
Development Environment
- Deploy code-server
- Expose at
dev.example.com
- Add basic auth for security
- Access VS Code from any browser
Future Enhancements
Planned Caddy integration features:
- Load balancing - Multiple container backends
- Health checks - Automatic failover
- WebSocket support - For real-time apps
- Custom middleware - Extended functionality
- Multi-domain - Different domains per app
- Certificate management UI - View/manage certs
The Caddy integration transforms OnTree from a local container manager into a full-featured hosting platform with enterprise-grade security and convenience.