This example demonstrates how to run an A2A server with TLS encryption, providing secure HTTPS communication between client and server using self-signed certificates.
- What This Example Shows
- Directory Structure
- Quick Start
- TLS Configuration
- Certificate Generation
- Troubleshooting
- Next Steps
- A2A server configured with TLS/SSL encryption
- Self-signed certificate generation for development
- HTTPS communication between client and server
- Docker Compose orchestration with TLS setup
- Secure task submission and response handling
tls-example/
├── server/
│ ├── main.go # TLS-enabled A2A server
│ ├── config/
│ │ └── config.go # Server configuration
│ └── go.mod # Server dependencies
├── client/
│ ├── main.go # TLS-aware A2A client
│ ├── config/
│ │ └── config.go # Client configuration
│ └── go.mod # Client dependencies
├── certs/
│ └── generate-certs.sh # Self-signed certificate generation script
├── docker-compose.yaml # TLS orchestration with cert generation
└── README.md
Note: Uses ../Dockerfile.server and ../Dockerfile.client for containers
- Navigate to the example directory:
cd examples/tls-example- Run the complete TLS setup:
docker-compose up --buildThis will:
-
Generate self-signed certificates (if they don't exist)
-
Start the TLS-enabled A2A server on port 8443 (HTTPS)
-
Run the client to test secure communication
-
Demonstrate encrypted message exchange
-
View the logs to see TLS communication:
# In another terminal
docker-compose logs -f tls-server
docker-compose logs -f tls-clientIf you want to generate certificates manually:
cd certs
chmod +x generate-certs.sh
./generate-certs.shcd certs
./generate-certs.shcd server
export A2A_SERVER_TLS_ENABLE=true
export A2A_SERVER_TLS_CERT_PATH=../certs/server.crt
export A2A_SERVER_TLS_KEY_PATH=../certs/server.key
export A2A_SERVER_PORT=8443
go run main.gocd client
export A2A_SERVER_URL=https://localhost:8443
export A2A_SKIP_TLS_VERIFY=true
go run main.goThe server supports the following TLS-related environment variables:
| Environment Variable | Description | Default |
|---|---|---|
A2A_SERVER_TLS_ENABLE |
Enable TLS/HTTPS | true |
A2A_SERVER_TLS_CERT_PATH |
Path to TLS certificate file | /certs/server.crt |
A2A_SERVER_TLS_KEY_PATH |
Path to TLS private key file | /certs/server.key |
A2A_SERVER_PORT |
HTTPS server port | 8443 |
The client supports these TLS-related environment variables:
| Environment Variable | Description | Default |
|---|---|---|
A2A_SERVER_URL |
HTTPS server URL | https://localhost:8443 |
A2A_SKIP_TLS_VERIFY |
Skip TLS certificate verification | true (for self-signed) |
A2A_TIMEOUT |
Request timeout | 30s |
The generate-certs.sh script creates:
ca.crt- Root Certificate Authority certificateca.key- Root CA private keyserver.crt- Server certificate (signed by CA)server.key- Server private key
- Validity: 365 days (1 year)
- Key Size: 4096-bit RSA
- Hash Algorithm: SHA-256
- Subject Alternative Names:
localhost*.localhostservertls-server127.0.0.1::1
- Do not use in production environments
- The client skips TLS verification by default (
A2A_SKIP_TLS_VERIFY=true) - For production, use certificates from a trusted Certificate Authority
- Store private keys securely and never commit them to version control
The server configures TLS through the ADK server configuration:
ServerConfig: serverConfig.ServerConfig{
Port: "8443",
TLSEnabled: true,
TLSCertFile: "/certs/server.crt",
TLSKeyFile: "/certs/server.key",
},Key features:
- Certificate validation before startup
- HTTPS endpoint on port 8443
- TLS-aware health checks
- Secure task processing
The client creates an HTTP client configured for TLS:
httpClient := &http.Client{
Timeout: cfg.Timeout,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: cfg.SkipTLSVerify,
},
},
}Key features:
- HTTPS communication with the server
- Configurable TLS verification (skip for self-signed certs)
- Timeout handling for secure requests
- Certificate error handling
# Test with curl (skip certificate verification)
curl -k https://localhost:8443/health
# Test with certificate verification
curl --cacert certs/ca.crt https://localhost:8443/health# Get agent information over HTTPS
curl -k https://localhost:8443/agent-card# Submit a task securely
curl -k -X POST https://localhost:8443/tasks \
-H "Content-Type: application/json" \
-d '{
"message": {
"role": "user",
"parts": [{"type": "text", "text": "Hello secure server!"}]
}
}'For production deployments:
# Use Let's Encrypt or commercial CA certificates
A2A_SERVER_TLS_CERT_FILE=/etc/ssl/certs/server.crt
A2A_SERVER_TLS_KEY_FILE=/etc/ssl/private/server.key# Client should verify certificates in production
A2A_SKIP_TLS_VERIFY=false- Store certificates in secure locations
- Use proper file permissions (600 for keys, 644 for certificates)
- Consider using certificate management tools
- Implement certificate rotation
- Use firewalls to restrict access
- Consider mutual TLS (mTLS) for enhanced security
- Implement proper logging and monitoring
# Verify certificate validity
openssl x509 -in certs/server.crt -text -noout
# Check certificate chain
openssl verify -CAfile certs/ca.crt certs/server.crt
# Test TLS connection
openssl s_client -connect localhost:8443 -servername localhost# Test server connectivity
nc -zv localhost 8443
# Check if TLS is working
curl -k -v https://localhost:8443/health# Check certificate generation
docker-compose logs cert-generator
# Check server startup
docker-compose logs tls-server
# Restart with fresh certificates
docker-compose down -v
docker-compose up --build- Explore the
minimalexample for basic A2A concepts - Check the
ai-poweredexample for AI integration - Learn about streaming with the
streamingexample - Review production deployment patterns in the main documentation
# List tasks and debug the A2A server (note: uses --skip-tls-verify for self-signed certs)
docker compose run --rm a2a-debugger tasks listminimal/- Basic A2A server/client setupai-powered/- AI integration patternsstreaming/- Real-time communicationdefault-handlers/- Built-in task handlers