
Dito is an advanced, highly extensible reverse proxy server written in Go. It features a robust plugin-based architecture, custom certificate handling for backend connections, dynamic configuration reloading, and more. Plugins can manage their own dependencies and provide custom middleware functionality.
The official project repository is available on GitHub.
Features
- Layer 7 Reverse Proxy: Handles HTTP and HTTPS requests efficiently.
- WebSockets Support: Proxy WebSocket connections with ease.
- Dynamic Configuration Reloading: Update configurations without restarting the server.
- Extensible Plugin System: Enhance Dito with custom Go plugins for authentication, caching, rate limiting, request/response transformation, custom logging and more.
- Plugin Security: Plugins are signed with Ed25519 keys and verified at startup.
- Custom TLS Certificate Management: Support for mTLS and custom certificates for backend connections.
- Header Manipulation: Add or remove HTTP headers as needed.
- Advanced Logging: Asynchronous logging with customizable verbosity and performance optimizations.
- Custom Transport Configuration: Fine-tune HTTP transport settings per location or globally.
- Response Body Size Limits: Control maximum response body sizes globally and per location with proper error handling.
- Response Buffering Control: Enable or disable response buffering per location for optimal performance.
- Prometheus Metrics: Monitor performance and behavior with detailed metrics.
Project Structure
dito/
├── cmd/ # Entry points (main application & plugin-signer)
├── app/ # Core application logic
├── config/ # Configuration loader & hot-reload
├── handlers/ # Request routing & proxy handlers
├── middlewares/ # Built-in middlewares (plugins can add more)
├── plugin/ # Plugin loading, signing, and verification
├── plugins/ # Plugin implementations
├── transport/ # HTTP transport configuration
├── websocket/ # WebSocket proxy support
├── writer/ # Response writers and buffering
├── metrics/ # Prometheus metrics
├── logging/ # Structured logging
├── deployments/ # Deployment configurations
│ ├── kubernetes/ # Basic Kubernetes deployments
│ ├── openshift/ # OpenShift production deployments
│ └── docker/ # Docker Compose for development
├── configs/ # Configuration files and templates
│ └── templates/ # Configuration templates
├── scripts/ # Deployment and utility scripts
├── bin/ # Built binaries and runtime files
├── plugins/ # Example and community plugins
├── transport/ # HTTP transport customization
├── websockets/ # WebSocket support
├── writer/ # Custom response writers
├── logging/ # Logging utilities
└── metrics/ # Prometheus metrics collection
Installation
Ensure you have Go 1.21+ and make
installed.
Quick Start
# Clone repo
git clone https://github.com/andrearaponi/dito.git && cd dito
# One-command setup & start
make quick-start
This will build binaries, generate keys, sign plugins, update configuration and start the server.
Step-by-Step
# 1. Clone repo
git clone https://github.com/andrearaponi/dito.git && cd dito
# 2. Setup (build, keys, plugins, config)
make setup
# 3. Start server
make run
Makefile Commands
Category | Command | Description |
---|---|---|
Quick | quick-start | Clean, setup everything and start |
setup | Full development setup (build, keys, plugins, config) | |
setup-prod | Full production setup (persistent keys, prod config) | |
run | Start the Dito server | |
fix-config | Quick command to fix configuration after setup | |
Build | build | Build Dito binary only |
build-plugins | Build all plugins | |
build-plugin-signer | Build plugin-signer tool | |
Security | generate-keys | Generate Ed25519 key pair for development |
generate-prod-keys | Generate persistent Ed25519 key pair for production | |
sign-plugins | Sign all plugins with development keys | |
sign-plugins-prod | Sign all plugins with production keys | |
update-config | Update bin/config.yaml with development key paths/hashes | |
update-prod-config | Update bin/config-prod.yaml with production key paths/hashes | |
update-k8s-config | Create configs/config-prod-k8s.yaml for Kubernetes deployment | |
OpenShift | deploy-ocp | Complete OpenShift production deployment |
deploy-ocp-dev | Quick development deployment to OpenShift | |
status-ocp | Check OpenShift deployment status | |
logs-ocp | View OpenShift deployment logs | |
clean-ocp | Clean up OpenShift resources | |
Debug | debug-config | Debug configuration issues |
help | Show all commands | |
Cleanup | clean | Remove build artifacts |
clean-plugins | Clean plugin binaries only | |
Development | test | Run tests |
vet | Run go vet | |
fmt | Format code | |
sonar | Run SonarQube analysis |
Manual Installation
- Build Dito
go build -o bin/dito ./cmd/dito/main.go
- Build plugin-signer
cd cmd/plugin-signer && go build -o ../../bin/plugin-signer . && cd ../..
- Generate keys
./bin/plugin-signer generate-keys
- Build plugins
find plugins -mindepth 1 -maxdepth 1 -type d -exec sh -c 'cd "$1" && go build -buildmode=plugin -o "$(basename "$1").so"' sh {} \;
- Sign plugins
find plugins -name "*.so" -exec ./bin/plugin-signer sign {} \;
- Update configuration
Ensure
public_key_path
andpublic_key_hash
inconfig.yaml
are correct. - Run Dito
./bin/dito
Usage
Start the server with the default configuration:
make run
Or directly:
./bin/dito -f /path/to/custom-config.yaml -enable-profiler
Configuration File
- Template:
cmd/config.yaml
- Runtime:
bin/config.yaml
Example configuration:
port: '8081'
hot_reload: true
metrics:
enabled: true
path: "/metrics"
logging:
enabled: true
verbose: false
level: "info"
plugins:
directory: "./plugins"
public_key_path: "./ed25519_public.key"
public_key_hash: "<SHA256_HASH>"
transport:
http:
idle_conn_timeout: 90s
max_idle_conns: 1000
max_idle_conns_per_host: 200
max_conns_per_host: 0
tls_handshake_timeout: 2s
response_header_timeout: 2s
expect_continue_timeout: 500ms
disable_compression: false
dial_timeout: 2s
keep_alive: 30s
force_http2: true
locations:
- path: "^/test-ws$"
target_url: "wss://echo.websocket.org"
enable_websocket: true
replace_path: true
- path: "^/dito$"
target_url: "https://httpbin.org/get"
replace_path: true
transport:
http:
disable_compression: true
additional_headers:
X-Custom: "true"
excluded_headers:
- Cookie
middlewares:
- hello-plugin
Response Limits
Dito allows configuring maximum response body sizes globally and per location.
Global Limits
response_limits:
max_response_body_size: 100000 # 100KB default limit
Per-Location Limits
locations:
- path: "^/api/small"
target_url: "https://api.example.com"
max_response_body_size: 1024
disable_response_buffering: false
- path: "^/api/large"
target_url: "https://api.example.com"
max_response_body_size: 52428800
disable_response_buffering: true
Features
- Automatic 413 status code when limits are exceeded
- JSON error responses with details
- Early detection using
Content-Length
- Works with buffered and streaming responses
- Logging when limits are exceeded
- Limits can be updated via hot reload
Error Format
{
"error": {
"code": 413,
"message": "Response body size exceeds limit",
"details": {
"limit_bytes": 90,
"path": "/api/endpoint"
}
}
}
Buffering Control
false
(default): responses buffered in memorytrue
: responses streamed directly to the client
Plugin System
Dito uses Go plugins (.so
files). Each plugin should be placed in its own subdirectory under plugins/
and typically contains the compiled plugin (<name>.so
), a signature file and an optional config.yaml
.
Signing & Verification
Plugin signing is mandatory and uses Ed25519 keys.
- Generate key pair
./bin/plugin-signer generate-keys -privateKey ed25519_private.key -publicKey ed25519_public.key
- Compute public key hash
shasum -a 256 ed25519_public.key | awk '{print $1}'
- Update
config.yaml
with thepublic_key_path
and computed hash. - Sign plugin
./bin/plugin-signer sign -plugin path/to/plugin.so -privateKey path/to/ed25519_private.key
Troubleshooting
public key integrity validation failed
: regenerate the hash and update the configuration.failed to read public key
: verify the path and file permissions.plugin signature verification failed
: re-sign with the correct key pair.
Custom Transport Configuration
Customize how Dito connects to backend services.
- Timeouts and Connection Limits: adjust to match backend behavior.
- TLS Settings: manage handshake timeouts and enforce HTTP/2 if needed.
- Custom Certificates: specify client certificates for mTLS backends.
WebSocket Support
Add enable_websocket: true
to a location to proxy WebSocket connections.
locations:
- path: "^/test-ws$"
target_url: "wss://echo.websocket.org"
enable_websocket: true
replace_path: true
Upcoming Enhancements
Future versions will provide enhanced TLS control, improved error handling and detailed metrics for WebSocket traffic.
TLS/SSL
Support for mTLS is built in. Specify cert_file
, key_file
and ca_file
to secure backend connections.
Metrics
Dito exposes Prometheus metrics to monitor performance and behaviour.
Available Metrics
http_requests_total
– total number of HTTP requests processedhttp_request_duration_seconds
– duration histogramactive_connections
– number of active connectionsdata_transferred_bytes_total
– bytes transferred- Standard Go runtime and promhttp metrics
Configuration
Enable metrics in config.yaml
:
metrics:
enabled: true
path: "/metrics"
Reporting Issues
- Go Version – include the output of
go version
. - Error Details – provide the error message, steps to reproduce and any logs.
- Configuration File – attach the
config.yaml
used when the issue occurred.
Contributing
- Fork the repository.
- Create your branch:
git checkout -b feature/AmazingFeature
. - Commit your changes.
- Push to the branch.
- Open a pull request.
Containerization & OpenShift Deployment
Dito is containerized and optimized for OpenShift.
Quick Deployment
chmod +x scripts/deploy-ocp.sh
./scripts/deploy-ocp.sh
Custom namespace and version:
./scripts/deploy-ocp.sh -n my-dito -v latest
Other options include force key regeneration (-f
), configuration only (-c
) or deploy only (-d
).
Manual Deployment Steps
1. Build and Push Container Image
./docker-build.sh
2. Generate Production Keys
make generate-prod-keys
3. Create OpenShift Resources
oc new-project dito
oc create secret generic dito-keys \
--from-file=ed25519_public.key=bin/ed25519_public_prod.key \
--from-file=ed25519_private.key=bin/ed25519_private_prod.key
HASH=$(shasum -a 256 bin/ed25519_public_prod.key | awk '{print $1}')
sed "s/PLACEHOLDER_HASH_TO_BE_REPLACED/$HASH/" configs/templates/application.yaml > configs/config-prod-k8s.yaml
oc create configmap dito-config \
--from-file=config.yaml=configs/config-prod-k8s.yaml
4. Deploy Application
oc apply -f deployments/openshift/production-deployment.yaml
Deployment Models
File | Use Case | Features |
---|---|---|
deployments/kubernetes/basic-deployment.yaml | Basic deployment | Simple setup |
deployments/openshift/production-deployment.yaml | Production deployment | Plugin signing, proper secrets, health checks |
Security Features
Container Security
- Non-root execution (user ID 1001)
- Read-only root filesystem
- Dropped capabilities
- OpenShift security contexts
Key Management
- External key generation
- Runtime plugin signing
- Secure secret mounting
- Proper file permissions
Configuration Management
Dito supports template-based configs, environment-specific configs and hot reload via ConfigMaps. See configs/README.md
for details.
License
This project is licensed under the Apache License 2.0. See the LICENSE file for details.