Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/.custom_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ liveness
manpages
misconfiguration
mitigations
OAuth
pathops
Parca
protobuf
Expand Down Expand Up @@ -53,6 +54,7 @@ uniter
untyped
unpatched
uv
Valkey
VM
websockets
Wordpress
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/charm-maturity.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Submit any newly-proposed public interfaces for review, to ensure that:
- Interface names and structure are consistent with the charming ecosystem.
- Tests cover integration with the applications consuming or providing the relations.

See more: [Charmlibs documentation](https://canonical.com/juju/docs/charmlibs/)
See more: [](#set-up-production-integrations), [Charmlibs documentation](https://canonical.com/juju/docs/charmlibs/)

### The charm respects the Juju proxy options

Expand Down
5 changes: 5 additions & 0 deletions docs/howto/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ To make your charm deployable from Charmhub, publish your charm.

- {doc}`Publish your charm on Charmhub <publish-your-charm-on-charmhub>`

Set up production integrations for your charm so that it can fit into the Juju ecosystem, integrating with other applications.
Comment thread
tromai marked this conversation as resolved.
Resolved

- {doc}`Set up production integrations <set-up-production-integrations>`

Once your charm is ready for wide production use, your next goal should be to get it publicly listed on Charmhub, so that it is visible in searches.

- {doc}`Make your charm discoverable <make-your-charm-discoverable>`
Expand Down Expand Up @@ -157,6 +161,7 @@ Secure your charm <secure-your-charm>
:hidden:

Publish your charm on Charmhub <publish-your-charm-on-charmhub>
Set up production integrations <set-up-production-integrations>
Comment thread
tromai marked this conversation as resolved.
Resolved
Make your charm discoverable <make-your-charm-discoverable>
```

Expand Down
106 changes: 106 additions & 0 deletions docs/howto/set-up-production-integrations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
myst:
html_meta:
description: Guidance for integrating your charm with common services, including ingress, observability, databases, TLS, object storage, and identity.
Comment thread
tromai marked this conversation as resolved.
Resolved
---

(set-up-production-integrations)=
# How to set up production integrations

See first: {ref}`charm-maturity`.
Comment thread
tromai marked this conversation as resolved.
Resolved

A production-ready charm should fit into the Juju ecosystem, integrating with other applications. Therefore, it needs to be compatible with other charms. This guide summarises the integrations that production charms most often support.
Comment thread
tromai marked this conversation as resolved.
Resolved

These integrations are not mandatory for your charm to work. You need to decide which ones to use based on your charm's workload.

```{tip}
If your charm uses a Charmcraft 12-factor app extension, many integrations are set up for you. Check {external+charmcraft:ref}`Charmcraft | Manage relations for a 12-factor app charm <integrate-12-factor-charms>` for more information. To add custom integrations to a 12-factor app charm, follow [Add a custom integration to a 12-factor app charm](https://canonical.com/juju/docs/12-factor/latest/how-to/add-custom-relation/) instead of this page.
Comment thread
tromai marked this conversation as resolved.
Resolved
```

(set-up-production-integrations-best-practices)=
## Best practices

Juju integrates endpoints that use the same interface name. You should use existing interface names for any integration that your charm supports. To browse the available interface names and their supporting libraries, see {external+charmlibs:ref}`Charmlibs | Interface libraries <charm-libs-interface>` and the {external+charmlibs:ref}`interface specifications <reference-interfaces>`.
Comment thread
tromai marked this conversation as resolved.
Resolved
Comment thread
tromai marked this conversation as resolved.
Resolved

Writing integration tests is the best way to validate that your charm can integrate well with others. See {ref}`How to manage relations | Write integration tests <manage-relations-integration-tests>`.
Comment thread
tromai marked this conversation as resolved.
Resolved

If no existing interface fits your workload, you can design a new one. See {ref}`manage-interfaces`.
Comment thread
tromai marked this conversation as resolved.
Resolved

(set-up-production-integrations-ingress)=
## Ingress

Integrate your charm with an ingress provider when your workload serves HTTP or HTTPS, and users or applications outside the model need to reach it. Your charm declares a `requires` endpoint that uses the `ingress` interface, and consumes the ingress data from the provider.
Comment thread
tromai marked this conversation as resolved.
Resolved

Some providers:

* [Traefik](https://charmhub.io/traefik-k8s), [NGINX Ingress Integrator](https://charmhub.io/nginx-ingress-integrator), and [Istio Ingress](https://charmhub.io/istio-ingress-k8s) on Kubernetes.
Comment thread
tromai marked this conversation as resolved.
Resolved
* [Ingress Configurator](https://charmhub.io/ingress-configurator) on machines. It translates `ingress` to the `haproxy-route` interface of the [HAProxy](https://charmhub.io/haproxy) charm.

In most cases, your charm can use the [ingress library](https://github.com/canonical/traefik-k8s-operator/blob/main/lib/charms/traefik_k8s/v2/ingress.py). You can use alternative libraries, as long as they fulfil the {external+charmlibs:ref}`ingress v2 interface specification <interfaces-ingress-v2>`.
Comment thread
tromai marked this conversation as resolved.
Resolved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use alternative libraries

Is this speculative or is there evidence that people do (or want to) do this? If there's no clear evidence, I'd say drop it in favour of pushing people towards typical solutions:

Suggested change
In most cases, your charm can use the [ingress library](https://github.com/canonical/traefik-k8s-operator/blob/main/lib/charms/traefik_k8s/v2/ingress.py). You can use alternative libraries, as long as they fulfil the {external+charmlibs:ref}`ingress v2 interface specification <interfaces-ingress-v2>`.
In most cases, your charm can use the [ingress library](https://github.com/canonical/traefik-k8s-operator/blob/main/lib/charms/traefik_k8s/v2/ingress.py).

@tromai tromai Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence was introduced at the beginning because I wanted to introduce about interface specification, so a charm can stay production-ready even if they use an alternative library. In other sections, I also mention interface specification in the same manner.

I previously had an example of istio-ingress-route, but this interface library relies on a different interface, and we decided to drop it.

I agree with you, I think we should suggest the typical solution. Advanced users could explore the specification from the charmlibs documentation. I will remove this sentence.

EDIT: may be I can keep it, and change it to

See also {external+charmlibs:ref}`ingress v2 interface specification <interfaces-ingress-v2>`


See more: [Jenkins](https://github.com/canonical/jenkins-k8s-operator/blob/main/src/charm.py).
Comment thread
tromai marked this conversation as resolved.
Resolved

(set-up-production-integrations-observability)=
## Observability

Integrate your charm with the [Canonical Observability Stack (COS)](https://documentation.ubuntu.com/observability/) to provide metrics, logs, alerts, and dashboards for your workload in production. Most charms with a workload need it. A charm that doesn't run a workload, such as an integrator charm, might not.
Comment thread
tromai marked this conversation as resolved.
Resolved

To integrate your charm with COS:

* On Kubernetes, your charm integrates with each COS component over its own interface. Declare a `provides` endpoint for each of `prometheus_scrape` (Prometheus) and `grafana_dashboard` (Grafana), and a `requires` endpoint for `loki_push_api` (Loki). See {ref}`Observe your charm with COS Lite tutorial <observe-your-charm-with-cos-lite>`. To trace your charm code and send the trace data to COS, see {ref}`trace-your-charm`.
Comment thread
tromai marked this conversation as resolved.
Resolved
* On machines, your charm declares a single `provides` endpoint that uses the `cos_agent` interface. Use the [`cos_agent` charm library](https://charmhub.io/grafana-agent/libraries/cos_agent) to implement it. The [OpenTelemetry Collector](https://charmhub.io/opentelemetry-collector) subordinate charm forwards everything to COS. See more: [COS | Instrument machine charms](https://documentation.ubuntu.com/observability/latest/how-to/integrate/instrument-machine-charms/).

See more: [Hydra](https://github.com/canonical/hydra-operator/blob/main/src/charm.py), [Valkey](https://github.com/canonical/valkey-operator/blob/9/edge/src/events/observability.py).
Comment thread
tromai marked this conversation as resolved.
Resolved

(set-up-production-integrations-databases)=
## Databases

Charms often need to connect to a database. Your charm declares a `requires` endpoint that uses the interface for your database. Each database technology has its own interface:

| Database | Interface | Provider charms |
|:--|:--|:--|
| PostgreSQL | `postgresql_client` | [`postgresql`](https://charmhub.io/postgresql), [`postgresql-k8s`](https://charmhub.io/postgresql-k8s) |
| MySQL | `mysql_client` | [`mysql`](https://charmhub.io/mysql), [`mysql-k8s`](https://charmhub.io/mysql-k8s) |
| MongoDB | `mongodb_client` | [`mongodb`](https://charmhub.io/mongodb), [`mongodb-k8s`](https://charmhub.io/mongodb-k8s) |

The [`dpcharmlibs-interfaces`](https://github.com/canonical/data-platform-charmlibs/blob/main/interfaces/README.md) library covers all of these interfaces. New charms should use this library. Some existing charms still use the older `data_platform_libs.v0.data_interfaces` charm library.
Comment thread
tromai marked this conversation as resolved.
Resolved

See more: [MediaWiki](https://github.com/canonical/mediawiki-k8s-operator/blob/main/src/relations/valkey.py) uses `dpcharmlibs-interfaces` for its Valkey relation (interface `valkey_client`). [Discourse](https://github.com/canonical/discourse-k8s-operator/blob/main/src/database.py) requires `postgresql_client` and [MediaWiki](https://github.com/canonical/mediawiki-k8s-operator/blob/main/src/relations/database.py) requires `mysql_client`, but both still use the older v0 library for these.
Comment thread
tromai marked this conversation as resolved.
Resolved

(set-up-production-integrations-tls)=
## TLS certificates

Integrate your charm with a certificate provider when your workload needs TLS certificates, for example to serve or query from HTTPS endpoints. Your charm declares a `requires` endpoint that uses the `tls-certificates` interface and receives certificates from the provider.

Some providers:

* [Self Signed Certificates](https://charmhub.io/self-signed-certificates)
* [Lego](https://charmhub.io/lego)
* [Manual TLS Certificates](https://charmhub.io/manual-tls-certificates)
* [Vault](https://charmhub.io/vault-k8s)

New charms should use the {external+charmlibs:ref}`charmlibs-interfaces-tls-certificates <charmlibs-interfaces-tls-certificates>` library. See also the {external+charmlibs:ref}`tls-certificates v1 interface specification <interfaces-tls-certificates-v1>`. Some existing charms still use the older `charms.tls_certificates_interface` charm library.
Comment thread
tromai marked this conversation as resolved.
Resolved
Comment thread
tromai marked this conversation as resolved.
Resolved
Comment thread
tromai marked this conversation as resolved.
Resolved

See more: [NGINX Ingress Integrator](https://github.com/canonical/nginx-ingress-integrator-operator/blob/main/src/charm.py), [Landscape](https://github.com/canonical/landscape-charm/blob/main/src/charm.py).
Comment thread
tromai marked this conversation as resolved.
Resolved

(set-up-production-integrations-object-storage)=
## Object storage

Integrate your charm with an object storage provider when your workload needs S3-compatible storage. Your charm declares a `requires` endpoint that uses the `s3` interface, and receives the endpoint, bucket, and credentials from the provider.

The main provider is [S3 Integrator](https://github.com/canonical/object-storage-integrator/blob/main/s3/README.md), which you configure with the details of an S3-compatible service. Its documentation explains how to set it up and which charm library to use.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other sections name the library, and the README and charmlibs listing both recommend object-storage-charmlib, so maybe this should too?

@tromai tromai Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank for pointing it out. I agree. I updated the provider Charmhub link, consistent with other sections and showed the object-storage-charmlib library name explicitly.


See more: [MLflow](https://github.com/canonical/mlflow-operator/blob/main/src/charm.py), [Valkey](https://github.com/canonical/valkey-operator/blob/9/edge/src/events/backup.py).
Comment thread
tromai marked this conversation as resolved.
Resolved

(set-up-production-integrations-identity)=
## Identity

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tonyandrewmeyer I might need some help with this section. This is a new topic for me, and I tried my best to match their documentation with the structure of this page.

Is Canonical Identity the one to go for if someone want to setup production-grade identity solution for their charm ? And whether I select the right one provider charms in the table 😓 .

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think Canonical Identity is the right place to send people. As far as I can tell it covers two stacks: the Identity Platform (Hydra, Kratos, GLAuth) and Authentik. The providers you have are right (I checked the hydra, authentik-server, authentik-ldap-outpost and saml-integrator endpoints on Charmhub). I'd add glauth-k8s for ldap, since that's the Identity Platform's LDAP provider. Their Choosing an identity solution page might be a useful link too. It's worth getting someone from the Identity team to look over this section, though, since I'm not an expert here either.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the response and help!

I'd add glauth-k8s for ldap ...

I agree, I have added glauth-k8s for ldap and the Choosing an identity solution page.

I also contacted the Identity team (Alessandro), and am now waiting for their response.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(from Identity team): Overall lgtm, except that IMO it is a little misleading listing the saml-integrator in there. The charm does not really provide saml functionality, it simply simply allows the user to provide saml configurations. All the other charms actually provide the functionality.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nsklikas Thank you for the review. I included saml-integrator here because this charm provides the saml endpoint, similar to other charms.

I agree that it can be confusing listing together with other charms that provide functionality. I will add a small sentence to clarify.


Use the [Canonical Identity Stack](https://canonical-identity.readthedocs-hosted.com/) for identity and access management of your charm. To compare the available solutions, see [Choosing an identity solution](https://canonical-identity.readthedocs-hosted.com/choosing-an-identity-solution/). Your charm declares a `requires` endpoint that uses the interface for the protocol that your workload supports:

| Protocol | Interface | Provider charms | Library |
|:--|:--|:--|:--|
| OAuth 2.0 and OpenID Connect (OIDC) | `oauth` | [`hydra`](https://canonical-identity.readthedocs-hosted.com/identity-platform/how-to/onboard-an-application-with-charmed-hydra/), [`authentik-server`](https://canonical-identity.readthedocs-hosted.com/authentik/how-to/protect-oidc-applications/) | {external+charmlibs:ref}`charmlibs-interfaces-oauth <charmlibs-interfaces-oauth>` |
Comment thread
tromai marked this conversation as resolved.
Resolved
| LDAP | `ldap` | [`glauth-k8s`](https://canonical-identity.readthedocs-hosted.com/identity-platform/tutorial/charms/glauth/), [`authentik-ldap-outpost`](https://canonical-identity.readthedocs-hosted.com/authentik/how-to/protect-ldap-applications/) | {external+charmlibs:ref}`charmlibs-interfaces-ldap <charmlibs-interfaces-ldap>` |
Comment thread
tromai marked this conversation as resolved.
Resolved
| SAML | `saml` | [`saml-integrator`](https://charmhub.io/saml-integrator) | [`saml` charm library](https://charmhub.io/saml-integrator/libraries/saml) |
Comment thread
tromai marked this conversation as resolved.
Resolved

See more: [SSSD](https://github.com/canonical/sssd-operator/blob/main/src/integrations/ldap.py) uses the LDAP library, and [Discourse](https://github.com/canonical/discourse-k8s-operator/blob/main/src/charm.py) uses the SAML library.
Comment thread
tromai marked this conversation as resolved.
Resolved
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ For a hands-on introduction to charm development with Ops, try our tutorials:
* - **Design & best practices**
- [Holistic vs delta charms](explanation/holistic-vs-delta-charms) • [Follow best practices](#follow-best-practices) • [Trace your charm](howto/trace-your-charm)
* - **Publishing**
- [Publish your charm on Charmhub](howto/publish-your-charm-on-charmhub) • [Make your charm discoverable](howto/make-your-charm-discoverable)
- [Publish your charm on Charmhub](howto/publish-your-charm-on-charmhub) • [Set up production integrations](howto/set-up-production-integrations) • [Make your charm discoverable](howto/make-your-charm-discoverable)
```

## How this documentation is organised
Expand Down
Loading