TLS encryption in COS¶
Both COS and COS Lite, have 2 sections of the deployment (internal and external) which can implement TLS communication.
The combination of these 2 configurations provides our products with 4 modes of operation:
Both
externalandinternalTLS communication, i.e.full TLS encryptionOnly
externalTLS communicationOnly
internalTLS communication (default)Neither
externalnorinternalTLS communication, i.e.unencrypted

Full TLS encryption implementation details¶
The recommended deployment for COS implements full TLS encryption, which requires an external certificates provider offer URL (cross-model relation) and has the following semantics:
The external CA provides a certificate for Traefik’s external URL.
Within the COS model, workloads communicate via K8s FQDN URLs, except (on a case-by-case basis) when they have ingress relations
COS charms generate CSRs with the K8s FQDN as the SAN DNS and the internal CA signs.
All COS charms trust the internal CA by installing the CA certificate in the charm and workload containers, using the
update-ca-certificatestool.Traefik establishes a secure connection with its proxied apps by trusting the local CA.
COS Lite with full TLS encryption is described in the diagram below. The diagram is limited to prometheus and alertmanager for brevity and clarity.
Note
This TLS diagram is relevant for COS as well, if prometheus is replaced with Mimir.
%%{init: { "theme": "dark" } }%%
flowchart TB
subgraph COS [cos-model]
traefik[traefik]
prometheus[prometheus]
alertmanager[alertmanager]
localca[local-ca]
end
subgraph CAModel [ca-model]
direction TB
cert-provider[certificates provider]
end
subgraph ObserveModel [observable-model]
grafana[grafana-agent]
end
grafana -->|"remote_write<br>(example.com)"| prometheus
prometheus -->|"self-monitoring<br>(am-0.cluster.local)"| alertmanager
cert-provider -->|"tls_certificates<br>(example.com)"| traefik
traefik -->|"ingress-per-unit<br>(prom-0.cluster.local)"| prometheus
traefik -->|"ingress-per-app<br>(am-*.cluster.local)"| alertmanager
prometheus -->|"tls_certificates<br>(prom-0.cluster.local)"| localca
alertmanager -->|"tls_certificates<br>(am-0.cluster.local)"| localca
localca -->|"certificate_transfer<br>(local_ca)"| traefik
cert-provider -->|"certificate_transfer<br>(external_ca)"| grafana
classDef Charm stroke:white,stroke-width:1px,color:white,rx:8px,ry:8px
class traefik,prometheus,alertmanager,localca,grafana,cert-provider Charm
As with any TLS configuration, keep in mind best practices such as frequent certificate rotation. See this guide for an example of monitoring certificates.
Warning
currently there is a known issue due to which some COS relations are limited to in-cluster relations only.
Deployment¶
Using the following Terraform root module, you can control external and internal TLS.
To enable internal TLS, set the internal_tls value to true. To enable external TLS, supply the external_certificates_offer_url value with a certificates provider’s Juju offer URL, from the ssc module in this example. The combination of these settings enables full encryption.
Note
If you are using COS Lite, create a cos-lite module with the cos-lite source: “git::https://github.com/canonical/observability-stack//terraform/cos-lite”
The COS Lite bundle is now deprecated in favor of Terraform modules.
# Note: The deployment order matters since the 'traefik:certificates' integration depends on 'module.ssc'
# 'terraform apply -target module.ssc'
# 'terraform apply'
module "ssc" {
source = "git::https://github.com/canonical/self-signed-certificates-operator//terraform"
model = "external-ca"
}
module "cos" {
# Use the right source value depending on whether you are using cos or cos-lite
source = "git::https://github.com/canonical/observability-stack//terraform/cos"
model = "cos"
channel = "1/stable"
internal_tls = true # Set to 'false' to disable TLS between in-model applications
external_certificates_offer_url = module.ssc.offers.certificates.url # Set to 'null' to communicate with Traefik via HTTP, i.e. 'external_tls'
}