<a id="harden-your-deployment"></a>

# Harden your Juju deployment

See also: [Juju security](https://documentation.ubuntu.com/juju/4.0/explanation/juju-security.md#juju-security)

Juju ships with sensible security defaults. However, security doesn’t stop there.

## Harden the cloud

Use a private cloud.

See more: [List of supported clouds](https://documentation.ubuntu.com/juju/4.0/reference/cloud/list-of-supported-clouds.md#list-of-supported-clouds)

If you want to go one step further, take your cloud (and the entire deployment) offline.

See more: [Set up your Juju deployment - offline](https://documentation.ubuntu.com/juju/4.0/howto/manage-your-juju-deployment/set-up-your-juju-deployment-offline.md#take-your-deployment-offline)

## Harden the client and the agent binaries

The `juju` CLI client can be installed from a strictly confined snap. The strict confinement means the client cannot do malicious things. The snap means the client updates by itself. All in all, you don’t need to take any action.

The Juju agent binaries come in the same package as the `juju` CLI client. However, when you deploy them (e.g., to bootstrap a controller or deploy an application), they’re no longer in a snap, so snap advantages no longer apply. Also, the Juju controller agent needs root access. Juju unit agents typically need root access too, except if the charm next to which they are deployed is rootless. Rootless charms are currently supported only for Kubernetes charms. (For more on rootless charms see [Harden the applications](#harden-the-applications)). To protect the agents, you must protect the cloud resource (machine or container) they’re deployed on.

See more: [Snapcraft | Snap confinement](https://snapcraft.io/docs/snap-confinement), [How to manage the juju CLI client](https://documentation.ubuntu.com/juju/4.0/howto/manage-juju.md#manage-juju), [Release notes](https://documentation.ubuntu.com/juju/4.0/releasenotes.md#releasenotes)

## Harden the controller(s)

In a typical Juju workflow you allow your client to read your locally stored cloud credentials, then copy them to the controller, so that the controller can use them to authenticate with the cloud. However, for some clouds, Juju now supports a workflow where  neither your nor your controller know your credentials directly – you can just supply an instance profile (AWS) or a managed identity (Azure). One way to harden your controller is to take advantage of this workflow.

See more: [Bootstrap a controller](https://documentation.ubuntu.com/juju/4.0/howto/manage-controllers.md#bootstrap-a-controller), [Amazon EC2](https://documentation.ubuntu.com/juju/4.0/reference/cloud/list-of-supported-clouds/amazon-ec2.md#cloud-ec2), [Microsoft Azure](https://documentation.ubuntu.com/juju/4.0/reference/cloud/list-of-supported-clouds/microsoft-azure.md#cloud-azure)

Like all the cloud resources provisioned through Juju, the cloud resources (machines or containers) that a controller is deployed on run the latest Ubuntu LTS.  This Ubuntu is *not* CIS- and DISA-STIG-compliant (see more: [Ubuntu | The Ubuntu Security Guide](https://ubuntu.com/security/certifications/docs/usg)). However, it is behind a firewall, inside a VPC, with only the following three ports opened – as well as hardened (through security groups) – by default:

- (always:) `17070`, to allow access from clients and agents;
- (in high-availability scenarios): mongo
- (In high-availability scenarios): `controller-api-port`, which can be turned off (see [api-port](https://documentation.ubuntu.com/juju/4.0/reference/configuration/list-of-controller-configuration-keys.md#controller-config-api-port)).

When a controller deploys a charm, all the traffic between the controller and the resulting application unit agent(s) is [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security)-encrypted (each agent starts out with a CA certificate from the controller and, when they connect to the controller, they get another certificate that is then signed by the preshared CA certificate). In addition to that, every unit agent authenticates itself with the controller using a password.

See more: [Wikipedia | TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security)

## Harden the user(s)

When you bootstrap a controller into a cloud, you automatically become a user with controller admin access. Make sure to change your password, and choose a strong password.

Also, when you create other users (whether human or for an application), take advantage of Juju’s granular access levels to grant access to clouds, controllers, models, or application offers only as needed. Disable or remove any users that are no longer needed.

See more: [User](https://documentation.ubuntu.com/juju/4.0/reference/user.md#user), [User access levels](https://documentation.ubuntu.com/juju/4.0/reference/user.md#user-access-levels), [How to manage users](https://documentation.ubuntu.com/juju/4.0/howto/manage-users.md#manage-users)

## Harden the model(s)

Within a single controller, living on a particular cloud, you can have multiple users. Each user can have their own models (i.e., workspaces or namespaces). Each model can be associated with a different credential for a different cloud. Juju thus supports multi-tenancy.

You can also restrict user access to a model and also restrict the commands that any user can perform on a given model.

See more: [How to manage models](https://documentation.ubuntu.com/juju/4.0/howto/manage-models.md#manage-models)

<a id="harden-the-applications"></a>

## Harden the applications

When you deploy (an) application(s) from a charm or a bundle, choose the charm / bundle carefully:

- Choose charms / bundles that show up in the Charmhub search – that means they’ve passed formal review – and which have frequent releases – that means they’re actively maintained.
- Choose charms that don’t require deployment with `--trust` (i.e., access to the cloud credentials). If not possible, make sure to audit those charms.
- *Starting with Juju 3.6.0, for Kubernetes charms:* Choose charms whose `charmcraft.yaml > containers > uid` and `gid` are not 0 (do not require root access). If not possible, make sure to audit those charms. See more: [Charmcraft | File `charmcraft.yaml` > `containers`](https://documentation.ubuntu.com/charmcraft/stable/reference/files/charmcraft-yaml-file/#containers).
- *Starting with Juju 3.6.0, for Kubernetes charms:* Choose charms whose `charmcraft.yaml > charm-user` field is set to `non-root`. If not possible, make sure to audit those charms. See more: [Charmcraft | File `charmcraft.yaml` > `charm-user`](https://documentation.ubuntu.com/charmcraft/stable/reference/files/charmcraft-yaml-file/#charm-user).
- Choose charms that support secrets (see more:  [Secret](https://documentation.ubuntu.com/juju/4.0/reference/secret.md#secret)).

(Like all the cloud resources provisioned through Juju,) the cloud resource(s) (machines or containers) that an application is deployed on by default run the latest Ubuntu LTS.  This Ubuntu is *not* CIS- and DISA-STIG-compliant (see more: [Ubuntu | The Ubuntu Security Guide](https://ubuntu.com/security/certifications/docs/usg)). However, it is by default behind a firewall, inside a VPC. Just make sure to expose application or application offer endpoints only as needed.

Keep an application’s charm up to date.

See more: [How to manage charms or bundles](https://documentation.ubuntu.com/juju/4.0/howto/manage-charms.md#manage-charms),  [How to manage applications](https://documentation.ubuntu.com/juju/4.0/howto/manage-applications.md#manage-applications)

## Audit and observe

Juju generates agent logs that can help administrators perform auditing for troubleshooting, security maintenance, or compliance.

See more: [Log](https://documentation.ubuntu.com/juju/4.0/reference/log.md#log)

You can also easily collect metrics about or generally monitor and observe your deployment by deploying and integrating with the Canonical Observability Stack.

See more: [Collect metrics about a controller](https://documentation.ubuntu.com/juju/4.0/howto/manage-controllers.md#collect-metrics-about-a-controller) (the same recipe – integration with the [Canonical Observability Stack](https://charmhub.io/topics/canonical-observability-stack) bundle – can be used to observe applications other than the controller)
