Skip to content

TLS Setup

AKKO supports four TLS modes, controlled by global.tls.mode in values.yaml.

Quick Reference

Mode Certificate Source Air-Gapped Complexity
cloudflare-proxy Cloudflare edge (automatic) No Low
cert-manager Let's Encrypt via DNS-01 Yes (swap solver) Medium
self-signed Helm-generated (dev only) Yes None
disabled No TLS N/A None

Cloudflare terminates TLS at the edge. Zero certificate management on the cluster.

Setup (5 minutes)

  1. Cloudflare DNS: Add A record pointing to your server IP (e.g., 159.195.77.208). Enable the orange cloud (Proxy ON) for each record.

  2. SSL/TLS mode: In Cloudflare dashboard, go to SSL/TLS > Overview and set mode to Full (Strict).

  3. Origin Certificate (recommended for Full Strict):

    • Go to SSL/TLS > Origin Server > Create Certificate.
    • Hostnames: *.akko-ai.com, akko-ai.com.
    • Validity: 15 years (Cloudflare origin certs are free).
    • Download the certificate and private key.
    • Create the Kubernetes secret:
      kubectl create secret tls akko-tls \
        --cert=origin-cert.pem \
        --key=origin-key.pem \
        -n akko
      
  4. Helm values:

    global:
      tls:
        mode: "cloudflare-proxy"
        secretName: akko-tls
        skipVerify: false
    

  5. Cloudflare security settings (recommended):

    • Always Use HTTPS: ON
    • Minimum TLS Version: 1.2
    • HSTS: Enable with max-age=31536000; includeSubDomains
    • Automatic HTTPS Rewrites: ON

Pros & Cons

  • Pros: Zero maintenance, DDoS protection, CDN caching, WAF available.
  • Cons: Requires Cloudflare, not air-gapped, traffic routes through third party.

cert-manager provisions a wildcard Let's Encrypt certificate via DNS-01 challenge. Fully portable: swap the DNS solver for any provider (Cloudflare, Route53, Azure DNS, Google Cloud DNS).

Prerequisites

Install cert-manager CRDs in the cluster:

helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager --create-namespace \
  --version v1.17.2 \
  --set crds.enabled=true

Cloudflare API Token

Create a scoped API token in Cloudflare:

  1. Go to My Profile > API Tokens > Create Token.
  2. Use template Edit zone DNS.
  3. Permissions: Zone:DNS:Edit + Zone:Zone:Read.
  4. Zone resources: Include specific zone akko-ai.com.
  5. Save the token.

Helm values

global:
  tls:
    mode: "cert-manager"
    secretName: akko-tls
    skipVerify: false

akko-cert-manager:
  enabled: true
  acme:
    environment: "production"  # Use "staging" for testing
    email: "admin@akko-ai.com"
  dns01:
    provider: "cloudflare"
    cloudflare:
      apiToken: ""  # Set via --set or values-dev-secrets.yaml

Verification

# Check certificate status
kubectl get certificate akko-wildcard-cert -n akko

# Check certificate details
kubectl describe certificate akko-wildcard-cert -n akko

# Check cert-manager logs
kubectl logs -n cert-manager deploy/cert-manager

# Verify the secret was created
kubectl get secret akko-tls -n akko

The certificate auto-renews 30 days before expiry. No manual intervention needed.

Air-Gapped Deployment

For air-gapped environments, replace the ACME issuer with a CA issuer:

# Use a private CA instead of Let's Encrypt
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: akko-private-ca
spec:
  ca:
    secretName: akko-ca-keypair  # Your private CA cert+key

Self-Signed (Development)

Default mode for k3d/local development. Traefik uses the akko-tls secret containing a self-signed certificate.

global:
  tls:
    mode: "self-signed"
    skipVerify: true  # Required for self-signed

Browsers will show a certificate warning. This is expected in development.


Switching Modes

To switch from self-signed (dev) to Cloudflare proxy (production):

# 1. Create the origin certificate secret
kubectl create secret tls akko-tls \
  --cert=origin-cert.pem --key=origin-key.pem -n akko

# 2. Upgrade with new TLS mode
helm upgrade akko helm/akko/ -n akko \
  -f values-dev.yaml -f values-domain.yaml -f values-dev-secrets.yaml \
  --set global.tls.mode=cloudflare-proxy \
  --set global.tls.skipVerify=false