mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 16:11:29 +00:00
a49eae8155
why-certctl.md said March 1, CHART_SUMMARY.md said March 28. The LICENSE file is authoritative: Change Date is March 14, 2033. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
462 lines
12 KiB
Markdown
462 lines
12 KiB
Markdown
# Certctl Helm Chart - Complete Summary
|
|
|
|
## Overview
|
|
|
|
A production-ready Helm chart for deploying certctl (self-hosted certificate lifecycle management platform) on Kubernetes. The chart provides:
|
|
|
|
- High availability support with multi-replica deployments
|
|
- Persistent PostgreSQL database with automatic schema migration
|
|
- DaemonSet or Deployment-based agent deployment
|
|
- Comprehensive security contexts and RBAC
|
|
- Multiple deployment scenarios (dev, prod, HA, external DB)
|
|
- Full documentation and examples
|
|
|
|
## Chart Metadata
|
|
|
|
- **Name**: certctl
|
|
- **Chart Version**: 0.1.0
|
|
- **App Version**: 2.1.0
|
|
- **Type**: application
|
|
- **License**: BSL-1.1 (converts to Apache 2.0 in 2033)
|
|
|
|
## File Structure
|
|
|
|
```
|
|
deploy/helm/
|
|
├── README.md # Main Helm chart documentation
|
|
├── DEPLOYMENT_GUIDE.md # Step-by-step deployment guide
|
|
├── CHART_SUMMARY.md # This file
|
|
│
|
|
├── certctl/
|
|
│ ├── Chart.yaml # Chart metadata
|
|
│ ├── values.yaml # Default configuration values
|
|
│ ├── .helmignore # Files to ignore when building chart
|
|
│ │
|
|
│ └── templates/
|
|
│ ├── _helpers.tpl # Helm template helper functions
|
|
│ ├── NOTES.txt # Post-deployment notes
|
|
│ │
|
|
│ ├── server-deployment.yaml # Certctl API server deployment
|
|
│ ├── server-service.yaml # Server Kubernetes service
|
|
│ ├── server-configmap.yaml # Server configuration
|
|
│ ├── server-secret.yaml # Server secrets (API key, DB password, etc)
|
|
│ │
|
|
│ ├── postgres-statefulset.yaml # PostgreSQL database statefulset
|
|
│ ├── postgres-service.yaml # PostgreSQL headless service
|
|
│ ├── postgres-secret.yaml # Database credentials secret
|
|
│ │
|
|
│ ├── agent-daemonset.yaml # Certctl agent daemonset/deployment
|
|
│ ├── agent-configmap.yaml # Agent configuration
|
|
│ │
|
|
│ ├── ingress.yaml # Optional ingress resource
|
|
│ └── serviceaccount.yaml # ServiceAccount and RBAC
|
|
│
|
|
└── examples/
|
|
├── values-dev.yaml # Development/testing configuration
|
|
├── values-prod-ha.yaml # Production HA configuration
|
|
├── values-external-db.yaml # External PostgreSQL (RDS, Cloud SQL)
|
|
└── values-acme-dns01.yaml # ACME with DNS-01 (Let's Encrypt)
|
|
```
|
|
|
|
## Key Components
|
|
|
|
### 1. Server Deployment
|
|
|
|
**File**: `templates/server-deployment.yaml`
|
|
|
|
- Manages certctl API server instances
|
|
- Configurable replicas (default: 1)
|
|
- Health checks (liveness & readiness probes)
|
|
- Security context: non-root user, read-only filesystem
|
|
- Resource limits (default: 500m CPU, 512Mi memory)
|
|
- Automatic restart on failure
|
|
|
|
**Values**:
|
|
```yaml
|
|
server:
|
|
replicas: 1
|
|
port: 8443
|
|
auth:
|
|
type: api-key
|
|
apiKey: "REQUIRED"
|
|
resources:
|
|
requests: {cpu: 100m, memory: 128Mi}
|
|
limits: {cpu: 500m, memory: 512Mi}
|
|
```
|
|
|
|
### 2. PostgreSQL StatefulSet
|
|
|
|
**File**: `templates/postgres-statefulset.yaml`
|
|
|
|
- Persistent database storage
|
|
- Automatic schema migrations on startup
|
|
- Single replica (can be extended with external HA tools)
|
|
- Health checks via pg_isready
|
|
- Configurable storage size and class
|
|
- Security context: non-root user (UID 999)
|
|
|
|
**Values**:
|
|
```yaml
|
|
postgresql:
|
|
enabled: true
|
|
storage:
|
|
size: 10Gi
|
|
storageClass: "" # Use default
|
|
auth:
|
|
database: certctl
|
|
username: certctl
|
|
password: "REQUIRED"
|
|
```
|
|
|
|
### 3. Agent DaemonSet/Deployment
|
|
|
|
**File**: `templates/agent-daemonset.yaml`
|
|
|
|
- DaemonSet mode: one agent per Kubernetes node
|
|
- Deployment mode: custom number of agent replicas
|
|
- Local key storage with secure permissions (0600)
|
|
- Health checks and automatic restart
|
|
- Optional certificate discovery from filesystem
|
|
|
|
**Values**:
|
|
```yaml
|
|
agent:
|
|
enabled: true
|
|
kind: DaemonSet # or Deployment
|
|
replicas: 1 # for Deployment only
|
|
keyDir: /var/lib/certctl/keys
|
|
discoveryDirs: "/etc/ssl/certs" # optional
|
|
```
|
|
|
|
### 4. Ingress (Optional)
|
|
|
|
**File**: `templates/ingress.yaml`
|
|
|
|
- Optional HTTPS ingress
|
|
- cert-manager integration for automatic TLS
|
|
- Multiple host support
|
|
- Path-based routing
|
|
|
|
**Values**:
|
|
```yaml
|
|
ingress:
|
|
enabled: false
|
|
className: nginx
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
hosts:
|
|
- host: certctl.example.com
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
```
|
|
|
|
### 5. ConfigMaps and Secrets
|
|
|
|
**Files**:
|
|
- `server-configmap.yaml` - Non-secret server configuration
|
|
- `server-secret.yaml` - API key, database URL, SMTP password
|
|
- `postgres-secret.yaml` - Database credentials
|
|
- `agent-configmap.yaml` - Agent configuration
|
|
|
|
All secrets are base64-encoded and stored in Kubernetes Secrets.
|
|
|
|
### 6. ServiceAccount and RBAC
|
|
|
|
**File**: `templates/serviceaccount.yaml`
|
|
|
|
- Optional ServiceAccount creation
|
|
- Optional RBAC (ClusterRole, ClusterRoleBinding)
|
|
- Namespace-scoped by default
|
|
|
|
## Deployment Scenarios
|
|
|
|
### Development Setup
|
|
|
|
Use `examples/values-dev.yaml`:
|
|
|
|
```bash
|
|
helm install certctl certctl/ \
|
|
--values examples/values-dev.yaml \
|
|
--set server.auth.apiKey="dev-key" \
|
|
--set postgresql.auth.password="dev-password"
|
|
```
|
|
|
|
**Features**:
|
|
- Single server replica
|
|
- Demo auth (no API key required)
|
|
- Small database (5Gi)
|
|
- LoadBalancer service for easy access
|
|
- Debug logging level
|
|
|
|
### Production HA Setup
|
|
|
|
Use `examples/values-prod-ha.yaml`:
|
|
|
|
```bash
|
|
helm install certctl certctl/ \
|
|
--values examples/values-prod-ha.yaml \
|
|
--set server.auth.apiKey="$(openssl rand -base64 32)" \
|
|
--set postgresql.auth.password="$(openssl rand -base64 32)"
|
|
```
|
|
|
|
**Features**:
|
|
- 3 server replicas with pod anti-affinity
|
|
- Large database storage (100Gi)
|
|
- Pod disruption budgets
|
|
- Prometheus monitoring enabled
|
|
- Production resource limits
|
|
|
|
### External PostgreSQL
|
|
|
|
Use `examples/values-external-db.yaml`:
|
|
|
|
```bash
|
|
helm install certctl certctl/ \
|
|
--values examples/values-external-db.yaml \
|
|
--set postgresql.enabled=false \
|
|
--set 'server.env.CERTCTL_DATABASE_URL=postgres://...'
|
|
```
|
|
|
|
**Use cases**:
|
|
- AWS RDS
|
|
- Google Cloud SQL
|
|
- Azure Database for PostgreSQL
|
|
- External self-managed PostgreSQL
|
|
|
|
### ACME with DNS-01
|
|
|
|
Use `examples/values-acme-dns01.yaml`:
|
|
|
|
```bash
|
|
helm install certctl certctl/ \
|
|
--values examples/values-acme-dns01.yaml
|
|
```
|
|
|
|
**Enables**:
|
|
- Automatic certificate issuance from Let's Encrypt
|
|
- DNS-01 challenge (wildcard support)
|
|
- Custom DNS provider scripts
|
|
|
|
## Configuration Options
|
|
|
|
### Server Configuration
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `server.replicas` | 1 | Number of server replicas |
|
|
| `server.port` | 8443 | Server port |
|
|
| `server.auth.type` | api-key | Authentication type |
|
|
| `server.auth.apiKey` | "" | API key (REQUIRED) |
|
|
| `server.logging.level` | info | Log level |
|
|
| `server.logging.format` | json | Log format |
|
|
|
|
### PostgreSQL Configuration
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `postgresql.enabled` | true | Enable internal PostgreSQL |
|
|
| `postgresql.storage.size` | 10Gi | Database storage size |
|
|
| `postgresql.storage.storageClass` | "" | Storage class name |
|
|
| `postgresql.auth.password` | "" | Database password (REQUIRED) |
|
|
|
|
### Agent Configuration
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `agent.enabled` | true | Deploy agents |
|
|
| `agent.kind` | DaemonSet | DaemonSet or Deployment |
|
|
| `agent.replicas` | 1 | Replicas (Deployment only) |
|
|
| `agent.keyDir` | /var/lib/certctl/keys | Key storage directory |
|
|
|
|
### Issuer Configuration
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `server.issuer.local.enabled` | true | Enable Local CA |
|
|
| `server.issuer.acme.enabled` | false | Enable ACME |
|
|
| `server.issuer.acme.directoryURL` | "" | ACME directory URL |
|
|
| `server.issuer.acme.email` | "" | ACME email |
|
|
| `server.issuer.acme.challengeType` | http-01 | Challenge type |
|
|
|
|
See `values.yaml` for complete configuration options.
|
|
|
|
## Helm Template Functions
|
|
|
|
Defined in `templates/_helpers.tpl`:
|
|
|
|
| Function | Purpose |
|
|
|----------|---------|
|
|
| `certctl.name` | Chart name |
|
|
| `certctl.fullname` | Full release name |
|
|
| `certctl.chart` | Chart name and version |
|
|
| `certctl.labels` | Common labels |
|
|
| `certctl.selectorLabels` | Selector labels |
|
|
| `certctl.serverSelectorLabels` | Server selector labels |
|
|
| `certctl.agentSelectorLabels` | Agent selector labels |
|
|
| `certctl.postgresSelectorLabels` | PostgreSQL selector labels |
|
|
| `certctl.serviceAccountName` | ServiceAccount name |
|
|
| `certctl.serverImage` | Server image URI |
|
|
| `certctl.agentImage` | Agent image URI |
|
|
| `certctl.postgresImage` | PostgreSQL image URI |
|
|
| `certctl.databaseURL` | Database connection string |
|
|
| `certctl.serverURL` | Server URL for agents |
|
|
|
|
## Security Features
|
|
|
|
### Pod Security
|
|
|
|
- Non-root users (UID 1000 for app, UID 999 for PostgreSQL)
|
|
- Read-only root filesystems
|
|
- No privilege escalation
|
|
- Dropped capabilities (ALL)
|
|
- Resource limits to prevent DoS
|
|
|
|
### Secrets Management
|
|
|
|
- All sensitive data in Kubernetes Secrets
|
|
- Base64 encoded at rest
|
|
- Can be integrated with:
|
|
- sealed-secrets
|
|
- external-secrets
|
|
- Vault
|
|
- AWS Secrets Manager
|
|
|
|
### RBAC
|
|
|
|
- ServiceAccount per release
|
|
- Optional ClusterRole/ClusterRoleBinding
|
|
- Extensible for custom permissions
|
|
|
|
### Network Security
|
|
|
|
- Support for Kubernetes NetworkPolicies
|
|
- Service-to-service communication via internal DNS
|
|
- Optional Ingress with TLS
|
|
|
|
## Monitoring and Observability
|
|
|
|
### Health Checks
|
|
|
|
- Liveness probes (detect dead containers)
|
|
- Readiness probes (detect not-ready services)
|
|
- HTTP endpoints: `/health`, `/readyz`
|
|
|
|
### Logging
|
|
|
|
- Structured JSON logging
|
|
- Request ID propagation
|
|
- Configurable log levels (debug, info, warn, error)
|
|
|
|
### Metrics
|
|
|
|
- Prometheus metrics endpoint: `/api/v1/metrics/prometheus`
|
|
- Optional ServiceMonitor for Prometheus Operator
|
|
- Built-in metrics:
|
|
- Certificate counts by status
|
|
- Agent counts and status
|
|
- Job completion/failure rates
|
|
- Server uptime
|
|
|
|
## Installation Quick Reference
|
|
|
|
```bash
|
|
# Development
|
|
helm install certctl certctl/ \
|
|
--set server.auth.apiKey=dev \
|
|
--set postgresql.auth.password=dev
|
|
|
|
# Production HA
|
|
helm install certctl certctl/ \
|
|
--values examples/values-prod-ha.yaml \
|
|
--set server.auth.apiKey="$(openssl rand -base64 32)" \
|
|
--set postgresql.auth.password="$(openssl rand -base64 32)"
|
|
|
|
# External database
|
|
helm install certctl certctl/ \
|
|
--values examples/values-external-db.yaml \
|
|
--set postgresql.enabled=false \
|
|
--set 'server.env.CERTCTL_DATABASE_URL=postgres://...'
|
|
|
|
# ACME with Let's Encrypt
|
|
helm install certctl certctl/ \
|
|
--set server.issuer.acme.enabled=true \
|
|
--set server.issuer.acme.directoryURL=https://acme-v02.api.letsencrypt.org/directory
|
|
|
|
# Check status
|
|
kubectl get pods -l app.kubernetes.io/instance=certctl
|
|
kubectl logs -l app.kubernetes.io/component=server -f
|
|
|
|
# Upgrade
|
|
helm upgrade certctl certctl/ -f new-values.yaml
|
|
|
|
# Uninstall
|
|
helm uninstall certctl
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Use Secrets Management
|
|
|
|
```bash
|
|
# Use sealed-secrets
|
|
kubectl create secret generic certctl-secrets \
|
|
--from-literal=api-key="$(openssl rand -base64 32)" \
|
|
--dry-run=client -o yaml | kubeseal -f - | kubectl apply -f -
|
|
```
|
|
|
|
### 2. Configure Resource Limits
|
|
|
|
Match limits to your cluster capacity:
|
|
|
|
```yaml
|
|
server:
|
|
resources:
|
|
requests: {cpu: 250m, memory: 256Mi}
|
|
limits: {cpu: 1000m, memory: 512Mi}
|
|
```
|
|
|
|
### 3. Enable HA for Production
|
|
|
|
```yaml
|
|
server:
|
|
replicas: 3
|
|
podAntiAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution: [...]
|
|
```
|
|
|
|
### 4. Use Persistent Storage
|
|
|
|
```yaml
|
|
postgresql:
|
|
storage:
|
|
size: 100Gi
|
|
storageClass: fast-ssd
|
|
```
|
|
|
|
### 5. Enable Monitoring
|
|
|
|
```yaml
|
|
monitoring:
|
|
enabled: true
|
|
serviceMonitor:
|
|
enabled: true
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- **README.md** - Complete Helm chart documentation
|
|
- **DEPLOYMENT_GUIDE.md** - Step-by-step deployment instructions
|
|
- **values.yaml** - Commented configuration reference
|
|
|
|
## Support
|
|
|
|
For issues, questions, or contributions:
|
|
- GitHub: https://github.com/shankar0123/certctl
|
|
- Documentation: https://github.com/shankar0123/certctl/tree/main/docs
|
|
|
|
## License
|
|
|
|
BSL-1.1 (Business Source License)
|
|
Converts to Apache 2.0 on March 14, 2033
|