Go framework extension¶
The go-framework extension includes configuration options customised for a Go
application. This document describes all the keys that a user may interact with.
Tip
If you’d like to see the full contents contributed by this extension, see How to manage extensions.
Runtime user and writable directory¶
The charm-user field controls the user that runs the charm’s hook code.
Setting it to non-root runs the charm without root privileges or access
to sudo.
Running as a non-root user follows the principle of least privilege and limits the impact of a compromised charm. The charm can modify only files and directories permitted by the configured ownership and filesystem permissions. Configure the workload user and writable directories separately.
Learn more about charm-user in the
Charmcraft configuration reference.
The charmcraft.yaml file that charmcraft init generates doesn’t set
charm-user, so Juju
runs the charm as the root user by default.
The charmcraft.yaml file that charmcraft init generates sets
charm-user: non-root. The matching rock provides /app-data outside
/app as an application data directory writable by the _daemon_ user.
charmcraft.yaml > config > options¶
You can use the predefined options (run charmcraft expand-extensions for details)
but also add your own, as needed.
The predefined configuration options for the go-framework are listed below.
The secret key options listed apply to Ubuntu 24.04 LTS. For Ubuntu 26.04 LTS,
see Secrets.
app-port: Port in which the application should listen. The ingress will be configured using this port. The environment variable passed to the app is
APP_PORT. Default value is 8080.app-secret-key: Long secret you can use for sessions, CSRF or any other thing where you need a random secret shared by all units. The environment variable passed to the app is
APP_SECRET_KEY. The default value is random.app-secret-key-id: A secret you can use for sessions, CSRF or any other thing where you need a random secret shared by all units. The secret should contain a single key,
value, which maps to the actual application secret key. Use the secret ID to configure this option, as described in Secrets.metrics-port: Port where the prometheus metrics will be scraped. The environment variable passed to the app is
APP_METRICS_PORT. Default value is 8080.metrics-path: Path where the prometheus metrics will be scraped. The environment variable passed to the app is
APP_METRICS_PATH. Default value is/metrics.
Note
On Ubuntu 26.04 LTS, the app-port, metrics-port, and metrics-path options
are not generated. Set port, metrics-port, and metrics-path in the
paas-config.yaml file instead.
In case you want to add extra configuration options, any option you define will be used
to generate environment variables; a user-defined option config-option-name will
generate an environment variable named APP_CONFIG_OPTION_NAME where the option name
is converted to upper case and dashes are converted to underscores.
In either case, you will be able to set it in the usual way by running juju config
<application> <option>=<value>. For example, if you define an option called token,
as below, this will generate a APP_TOKEN environment variable, and a user of your
charm can set it by running juju config <application> token=<token>.
config:
options:
token:
description: The token for the service.
type: string
In addition to this, you can set the configuration option to be
mandatory by setting the optional key to false. This will
block the charm and stop services until the configuration is supplied. For example,
if your application needs an api-token to function correctly you can set
optional, as shown below. This will block the charm and stop the
services until the api-token configuration is supplied.
config:
options:
api-token:
description: The token necessary for the service to run.
type: string
optional: false
Note
A configuration with optional: false can’t also have a default key.
If it has both, the charm will fail to pack.
Relations¶
Your charm already has the following peers, provides, and requires
relations, as they were automatically supplied by the Go extension:
peers:
secret-storage:
interface: secret-storage
provides:
metrics-endpoint:
interface: prometheus_scrape
grafana-dashboard:
interface: grafana_dashboard
requires:
logging:
interface: loki_push_api
ingress:
interface: ingress
limit: 1
peers:
peers:
interface: peers
provides:
metrics-endpoint:
interface: prometheus_scrape
grafana-dashboard:
interface: grafana_dashboard
requires:
logging:
interface: loki_push_api
ingress:
interface: ingress
limit: 1
In addition to these relations, in each provides and requires
block you may specify further relations, to integrate with
the following charms:
Relation |
Endpoint definition |
|---|---|
Ingress Gateway API integrator and Traefik |
Already available in the charm |
MySQL machine and Kubernetes charm |
requires:
mysql:
interface: mysql_client
optional: True
limit: 1
|
PostgreSQL machine and Kubernetes charm |
requires:
postgresql:
interface: postgresql_client
optional: True
limit: 1
|
MongoDB charm |
requires:
mongodb:
interface: mongodb_client
optional: True
limit: 1
|
Already available in the charm |
|
Redis charm (not generated on Ubuntu 26.04 LTS) |
requires:
redis:
interface: redis
optional: True
limit: 1
|
Valkey charm |
requires:
valkey:
interface: valkey_client
optional: True
limit: 1
|
SAML charm |
requires:
saml:
interface: saml
optional: True
limit: 1
|
S3 charm |
requires:
s3:
interface: s3
optional: True
limit: 1
|
RabbitMQ machine and Kubernetes charm |
requires:
rabbitmq:
interface: rabbitmq
optional: True
limit: 1
|
Tempo charm |
requires:
tracing:
interface: tracing
optional: True
limit: 1
|
SMTP charm |
requires:
smtp:
interface: smtp
optional: True
limit: 1
|
OpenFGA charm |
requires:
openfga:
interface: openfga
optional: True
limit: 1
|
Hydra charm |
The requires:
oauth-endpoint-name:
interface: oauth
optional: True
limit: 1
The relation will create two configuration options,
|
Squid Forward Proxy charm |
requires:
http-proxy:
interface: http_proxy
optional: True
limit: 1
|
Note
The key optional with value False means that the charm will
get blocked and stop the services if the integration is not provided.
Note
Ubuntu 26.04 LTS generates only the Valkey relation, not the Redis relation. See Extensions for the full list of contract differences by base. The Valkey integration doesn’t support TLS.
To add one of these relations, e.g., PostgreSQL, in the
project file, include the appropriate requires block and
integrate with juju integrate <go charm> postgresql as usual.
Environment variables¶
Each relation adds its own environment variables to your Go app. Some are required, meaning they must be set for the relation to function.
The environment variable APP_BASE_URL provides the ingress URL
for an Ingress relation or the Kubernetes service URL if there is no
Ingress relation.
Relation |
Environment variables |
|---|---|
PostgreSQL |
|
MySQL |
|
MongoDB |
|
Redis (Ubuntu 22.04 LTS and 24.04 LTS only) |
|
Valkey |
|
SAML |
|
S3 |
|
RabbitMQ |
|
Tracing |
|
SMTP |
|
OpenFGA |
|
OpenID Connect |
|
HTTP Proxy |
|
HTTP Proxy¶
Proxy settings can be sourced either from the model configurations or from the
http-proxy relation. When the http-proxy relation is present, its
values take precedence over those defined in the model configuration. Charms
built using the Go extension automatically expose the Juju proxy
settings to the workload as the environment variables HTTP_PROXY,
HTTPS_PROXY and NO_PROXY, as well as their lowercase equivalents. The
HTTP_PROXY and HTTPS_PROXY values
are obtained from the relation, whereas the NO_PROXY value is obtained from
the model configuration. For example, if the relation is absent, the
juju-http-proxy environment variable will be exposed as HTTP_PROXY to
the Go service.
Worker and Scheduler Services¶
Extra services defined in the file
rockcraft.yaml
with names ending in -worker or -scheduler will be passed the same environment
variables as the main application. If there is more than one unit in the application,
the services with the name ending in -worker will run in all units. The services
with name ending in -scheduler will only run in one of the units of the application.
Observability¶
12-Factor charms are designed to be easily observable using the Canonical Observability Stack.
You can easily integrate your charm with Loki, Prometheus and Grafana using Juju.
juju integrate go-k8s grafana
juju integrate go-k8s loki
juju integrate go-k8s prometheus
After integration, you will be able to observe your workload using Grafana dashboards.
In addition to that you can also trace your workload code using Tempo.
To learn about how to deploy Tempo you can read the documentation here.
OpenTelemetry will automatically read the environment variables and configure the OpenTelemetry SDK to use them. See the OpenTelemetry documentation for further information about tracing.
Regarding the migrate.sh file¶
If your app depends on a database it is common to run a database migration script before
app startup which, for example, creates or modifies tables. This can be done by
including the migrate.sh script in the root of your project. It will be executed
with the same environment variables and context as the Go app.
If the migration script fails, the app won’t be started and the app charm will go into blocked state. The migration script will be run on every unit and it is assumed that it is idempotent (can be run multiple times) and that it can be run on multiple units at the same time without causing issues. This can be achieved by, for example, locking any tables during the migration.
If you prefer you can also use different tooling for migration, for example golang-migrate or goose .
Secrets¶
Juju secrets can be passed as environment variables to your Go application. The secret
ID has to be passed to the application as a config option in the project file of type
secret. This config option has to be populated with the secret ID, in the format
secret:<secret ID>.
The environment variable name passed to the application will be:
APP_<config option name>_<key inside the secret>
The <config option name> and <key inside the secret> keywords in the environment
variable name will have the hyphens replaced by underscores and all the letters
capitalised.
See more: Juju | Secret
The extension automatically adds the secret-typed app-secret-key-id
configuration option. The secret must contain a single key value, which
holds the actual Go app secret key and is exposed as the APP_SECRET_KEY
environment variable. If this configuration option is not set,
APP_SECRET_KEY is automatically assigned a random value.
The extension automatically adds the secret-typed app-secret-key
configuration option. The secret must contain a single key value, which
holds the actual Go app secret key and is exposed as the APP_SECRET_KEY
environment variable. If this configuration option is not set,
APP_SECRET_KEY is automatically assigned a random value.
Rotating the generated secret key¶
The extension adds the rotate-secret-key action to the charm. When the secret key
option isn’t set, run the action on the leader unit to generate a new random key:
juju run <LEADER_UNIT> rotate-secret-key
The action fails on units that aren’t the leader. Rotating the key invalidates any sessions signed with the previous key. The action doesn’t change a key that you set through the secret key option. To rotate that key, update its value instead.
Grafana dashboard graphs¶
If the Go app is connected to the Canonical Observability Stack (COS), the Grafana dashboard Go Operator displays the following default graphs:
Go version: Running Go version.
Number of bytes obtained from system
Average of GC call time: Average time spent in garbage collection
Rate of GC calls: Number of garbage collections per second
Number of goroutines that currently exist