How to manage applications

See also: Application

This document shows how to manage applications with Juju.


Deploy an application

To deploy an application from a charm on Charmhub / your local filesystem, use the deploy command followed by the name of the charm / the path to the local .charm file that delivers the application and, optionally, a custom application name:

juju deploy <charm | path/to/charm> <custom application name>

Example: Deploy MySQL from Charmhub using the `mysql` charm
juju deploy mysql

Example: Deploy an application from a local charm
juju deploy ./mini_ubuntu-20.04-amd64.charm

Example: Deploy an application from a local charm with a resource

If your charm’s metadata.yaml specifies a resource, you must also explicitly pass the resource. For example:

juju deploy ./demo-api-charm_ubuntu-22.04-amd64.charm --resource \

Depending on the cloud substrate that your controller is running on, the above command will allocate a machine (physical, virtual, LXD container) or a Kubernetes pod and then proceed to deploy and configure the application.

Depending on your use case, you may alternatively opt to provision a set of machines in advance via the juju add-machine command.

In this case, when running the above juju deploy command, Juju will detect that the model contains machines with no applications assigned to them and automatically deploy the application to one of those machines instead of spinning up a new machine.

The command also allows you to add another argument to specify a custom name (alias) for your deployed application. You can also take advantage of the rich set of flags to specify a charm channel or revision, a machine base (e.g., , a machine constraint (e.g., availability zone), the number of application units you want (clusterised, a space binding, a placement directive (e.g., to depoy to a LXD container), a specific storage instance, a specific machine, etc., and even to trust the application with the current credential – in case the application requires access to the backing cloud in order to fulfil its purpose (e.g., storage-related tasks).

See more: juju deploy

View details about an application

To view more information about a deployed application, run the show-application command followed by the application name or alias:

juju show-application <application name or alias >

By specifying various flags you can also specify a model, or an output format or file.

See more: juju show-application

Manage an application’s public availability over the network

Expose an application. By default, once an application is deployed, it is only reachable by other applications in the same Juju model. However, if the particular deployment use case requires for the application to be reachable by Internet traffic (e.g. a web server, Wordpress installation etc.), Juju needs to tweak the backing cloud’s firewall rules to allow Internet traffic to reach the application. This is done with the juju expose command.

After running a juju expose command, any ports opened by the application’s charmed operator will become accessible by any public or private IP address.

Assuming the wordpress application has been deployed (and a relation has been made to the deployed database mariadb), the following command can be used to expose the application outside the Juju model:

juju expose wordpress

When running juju status, its output will not only indicate whether an application is exposed or not, but also the public address that can be used to access each exposed application:

App        Version  Status  Scale  Charm      Rev  Exposed  Message
mariadb    10.1.36  active      1  mariadb      7  no       
wordpress           active      1  wordpress    5  yes      exposed

Unit          Workload  Agent  Machine  Public address  Ports   Message
mariadb/0*    active    idle   1           ready
wordpress/0*  active    idle   0  80/tcp

The command also has flags that allow you to expose just specific endpoints of the application, or to make the application available to only specific CIDRs or spaces. For example:

juju expose percona-cluster --endpoints db-admin --to-cidrs

See more: juju expose

Inspect exposure.

To view details of how the application has been exposed, run the show-application command. Sample session:

$ juju show-application percona-cluster
  exposed: true
      - ::/0

See more: juju show-application

Unexpose an application. The juju unexpose command can be used to undo the firewall changes and once again only allow the application to be accessed by applications in the same Juju model:

juju unexpose wordpress

You can again choose to unexpose just certain endpoints of the application. For example, running juju unexpose percona-cluster --endpoints db-admin will block access to any port ranges opened for the db-admin endpoint but still allow access to ports opened for all other endpoints:

juju unexpose percona-cluster --endpoints db-admin

See more: juju unexpose

Trust an application with a credential

Some applications may require access to the backing cloud in order to fulfil their purpose (e.g., storage-related tasks). In such cases, the remote credential associated with the current model would need to be shared with the application. When the Juju administrator allows this to occur the application is said to be trusted. An application can be trusted during deployment or after deployment.

Trust an application during deployment. To trust an application during deployment, run the deploy command with the --trust flag. E.g., below we trust

juju deploy --trust ...

See more: juju deploy --trust

Trust an application after deployment. To trust an application after deployment, use the trust command:

juju trust <application>

By specifying various flags, you can also use this command to remove trust from an application, or to give an application deployed on a Kubernetes model access to the full Kubernetes cluster, etc.

See more: juju trust

Configure an application

See also: Application configuration

Most charms ship with a sensible default configuration out of the box. However, for some use cases, it may be desirable or necessary to override the default application configuration options.

Get values. The way to view the existing configuration for an application depends on whether the application has been deployed or not.

  • To view the configuration options of an application that you have not yet deployed,

  • To view the configuration values for a deployed application, run the config command followed by the name of the application. For example:

juju config mediawiki

Expand to view a sample output
application: mediawiki
charm: mediawiki
    description: Admin users to create, user:pass
    is_default: true
    type: string
    value: ""
    description: turn on debugging features of mediawiki
    is_default: true
    type: boolean
    value: false
    description: URL to fetch logo from
    is_default: true
    type: string
    value: ""
    description: The name, or Title of the Wiki
    is_default: true
    type: string
    value: Please set name of wiki
    description: The server url to set "$wgServer". Useful for reverse proxies
    is_default: true
    type: string
    value: ""
    description: skin for the Wiki
    is_default: true
    type: string
    value: vector
    description: If we should put '/mediawiki' suffix on the url
    is_default: true
    type: boolean
    value: true

See more: juju config

Set values. You can set configuration values for an application during deployment or later.

juju deploy mediawiki --config name='my media wiki'

To pass multiple values, you can repeat the flag or store the values into a config file and pass that as an argument.

See more: juju deploy -- config

juju config mediawiki name='Juju Wiki'  skin=monoblock

By exploring various options you can also use this command to pass the pairs from a YAML file or to reset the keys to their default values.

See more: juju config

Manage machine constraints for an application

See also: Constraint

Set values. You can set machine constraint values for an application during deployment or later.

  • To set machine constraints for an application during deployment, run the deploy command with the --constraints flag followed by the relevant key-value pair or a quotes-enclosed list of key-value pairs. For example, to deploy MySQL on a machine that has at least 6 GiB of memory and 2 CPUs:
juju deploy mysql --constraints "mem=6G cores=2"

Expand to see more examples

Assuming a LXD cloud, to deploy PostgreSQL with a specific amount of CPUs and memory, you can use a combination of the instance-type and mem constraints, as below – instance-type=c5.large maps to 2 CPUs and 4 GiB, but mem overrides the latter, such that the result is a machine with 2 CPUs and 3.5 GiB of memory.

juju deploy postgresql --constraints "instance-type=c5.large mem=3.5G"

To deploy Zookeeper to a new LXD container (on a new machine) limited to 5 GiB of memory and 2 CPUs, execute:

juju deploy zookeeper --constraints "mem=5G cores=2" --to lxd

To deploy two units of Redis across two AWS availability zones, run:

juju deploy redis -n 2 --constraints zones=us-east-1a,us-east-1d

See more: juju deploy --constraints

If you want to use the image-id constraint with juju deploy:
You must also use the --base flag of the command. The base specified via --base will be used to determine the charm revision deployed on the machine created with the image-id constraint.

See more: juju deploy --base

  • To set machine constraints for an application after deployment, run the set-constraints command followed by the desired ("-enclosed list of) key-value pair(s), as below. This will affect any future units you may add to the application.
juju set-constraints mariadb cores=2

Pro tip: To reset a constraint key to its default value, run the command with the value part empty (e.g., juju deploy apache2 --constraints mem= ).

See more: juju set-constraints

Get values. To view an application’s current constraints, use the constraints command:

juju constraints mariadb

See more: juju constraints

Scale an application

The capability of a service to adjust its resource footprint to a level appropriate for fulfilling client demands placed upon it is known as scalability. Scaling vertically affects the resources of existing machines (memory, CPU, disk space) whereas scaling horizontally, in Juju, involves the number of application units available.

Units are not always synonymous with machines however. Multiple units can be placed onto a single machine (co-location) and still be considered horizontal scaling if sufficient resources are present on the machine.

This page will describe how rudimentary scaling works with Juju as well as mention some less common situations.

Scaling up

In the context of Juju, scaling up means increasing the number of application units and always involves the add-unit command. The exception is for a Kubernetes-backed cloud where the scale-application command is used.

Closely resembling scaling up is the addition of a machine devoid of a unit. This is accomplished via the add-machine command:

juju add-machine

A machine provisioned via the add-machine command that does not yet house an application unit will, by default, be used for any subsequent application deployment (via the deploy command).

Scaling up behind a load balancer

In many cases simply adding more units will not make an application scale properly. A load balancer or proxy is often required.

Below is an example of deploying a load balanced MediaWiki application by placing the HAProxy application in front of it:

juju deploy mediawiki
juju deploy mysql
juju deploy haproxy
juju integrate mediawiki:db mysql
juju integrate mediawiki haproxy
juju expose haproxy

When a relation is made between MediaWiki and HAProxy, the latter will be configured to load balance requests to the MediaWiki application. This means that client requests should go to the HAProxy instance. To get the proxy’s IP address run the following:

juju status haproxy

You can now scale up the MediaWiki application behind the proxy as you see fit. To add five more units (with each running in its own machine):

juju add-unit -n 5 mediawiki

Scaling up within a Kubernetes model

To scale a Kubernetes application up or down, run the scale-application command followed by the name of the application and the desired – higher or lower – number of units. For example, below we scale mediawiki to 3 units:

juju scale-application mediawiki 3

Scaling up using a charm with built-in scaling

Some charms have scaling built-in where scaling up really is as simple as adding more units.

An example of this is the WordPress charm:

juju deploy mysql
juju deploy wordpress
juju integrate mysql wordpress
juju expose wordpress

To scale, just add more units:

juju add-unit wordpress

This will cause a new unit (and machine) to be spawned and configured to work alongside the existing one.

By default, add-unit will add a single unit. To request multiple units the -n option is needed. For example, to further scale up our current application by adding 100 units of MySQL one would run:

juju add-unit -n 100 mysql

Scaling up through co-location

Like the deploy command, it is possible to co-locate multiple applications on a single machine. This is done via the --to option.

For example, to add a unit of MySQL to the machine with an ID of ‘23’:

juju add-unit mysql --to 23

To add a unit of the same application to existing LXC container ‘3’ residing on host machine ‘24’:

juju add-unit mysql --to 24/lxc/3

Not all applications will happily co-exist (usually due to conflicting configuration files). It is therefore generally safer to place units on dedicated machines or containers.

Here we add a unit of MySQL to a new LXC container on host machine 25:

juju add-unit mysql --to lxc:25

Scaling up by specifying new constraints

It is possible to scale out an application by adding a unit with different hardware requirements (constraints) than those set with the initial deployment. The default behaviour is for new units to use the same, if any, constraints.

This is done by indirectly creating a machine with a constraint and then adding the unit to it. For example, to add a unit with 16 GiB of memory to the MySQL application if the initial deployment was only, say, 4 GiB:

juju add-machine --constraints mem=16G
juju machines
juju add-unit mysql --to 3

Above, it is presumed that juju machines informed us that the new machine was assigned an ID of ‘3’.

Read the Using constraints page for details on constraints.

Scaling down

In the context of Juju, scaling down means decreasing the number of application units and always involves the remove-unit command. The exception is for a Kubernetes-backed cloud where the scale-application command is used.

Closely resembling scaling down is the direct removal of a machine. This is therefore also covered here and is accomplished via the remove-machine command.

To scale down the MediaWiki application by removing a specific unit:

juju remove-unit mediawiki/1

Note that if this is the only unit running on the underlying machine, the machine will also be removed.

A machine cannot be manually removed if any of the following is true:

  • it houses a unit
  • it is being used as the only controller
  • it is hosting Juju-managed containers (KVM guests or LXD containers)

For example, to remove a machine with ID of ‘6’:

juju remove-machine 6

For more information on removing applications and machines, see the Removing things page.

Scaling down within a Kubernetes model

To scale down while in a Kubernetes model the total number of desired units for the application is simply stated. Here we want a total of two units:

juju scale-application mediawiki 2

Charm Implementation

When developing charms using the Operator Framework, scaling is handled via relation events - specifically through peer relations. For more information see:

Change space bindings for an application

To change space bindings for a deployed application, run the bind command followed by the name of the application followed by the name of a default space and/or key-value pairs consisting of specific application endpoints and the space you want to bind them to.

For example, to update the default binding for the application and automatically update all existing endpoint bindings that were referencing the old default, pass the name of the new default space:

juju bind <application> <new default space>

Or, to bind individual endpoints to a space, pass key-value pairs of specific application endpoints and the specific space you want to bind them to:

juju bind <application> endpoint-1=space-1 endpoint-2=space-2

Finally, to both update the default space and individual endpoints in one go, pass both:

juju bind <application> new-default endpoint-1=space-1

See more: juju bind

Upgrade an application

See also: Upgrading things, Application, Juju SDK | Channel, Juju SDK | Upgrading a charm

To upgrade an application, you need to upgrade the channel of its deployed charm.

This always involves the refresh command, but the exact way to use it differs a little bit depending on whether you are dealing with a Charmhub charm or rather a local charm.


Upgrade a Charmhub charm

See also: juju status, juju info, juju refresh

Run status to find the current channel.

Run info followed by the charm name to find out all the available channels.

Finally, run refresh followed by the charm name and the channel option to change the charm to the desired channel.

Upgrade a local charm

See also: juju refresh

To upgrade a local charm, run the refresh command followed by the name of the charm and the local path to the charm:

juju refresh juju-test --path ./path/to/juju-test

The command offers many other options, for example, the possibility to replace a charm completely with another charm by using the --switch option followed by a different path (a process known as ‘crossgrading’). (Note: --path and --switch are mutually exclusive. Use --switch if you want to replace your existing charm with a completely new charm.)

Remove an application

See also: Removing things reference


Remove an application

An application can be removed with:

juju remove-application <application-name>

For example:

juju remove-application apache2

This will remove all of the application’s units. All associated machines will also be removed providing they are not hosting containers or another application’s units.

If persistent storage is in use by the application it will be detached and left in the model. However, the --destroy-storage option can be used to instruct Juju to destroy the storage once detached.

Removing an application which has relations with another application will terminate that relation. This may adversely affect the other application. See section Removing relations below for how to selectively remove relations.

As a last resort, use the --force option (in v.2.6.1).

Manage application integrations

See: How to manage integrations

Remove a charm or a charm bundle

A charmed operator is the means by which an application is installed. There is therefore no method to remove a charm. Removal should be done at either the unit or application level.

A bundle is not a logical entity that can be removed. Once a bundle is deployed, applications can evolve in numerous ways that are not tracked and associated with the original bundle. For complex deployments, the recommendation is to deploy on a per-model basis so the removal of a complex deployment becomes equivalent to the removal of a model.

Remove an application offer

An application offer (for a cross model relation) is removed with:

juju remove-offer <offer url>

For example:

juju remove-offer hosted-mysql

The attempt will fail if a relation has already been made to the offer. To override this behaviour the --force option is required, in which case the relation is also removed.

Note that if the offer does not reside in the current model then the full URL must be used:

juju remove-offer prod.model/hosted-mysql

Contributors: @nvinuesa

Last updated 21 hours ago.