How to manage applications
See also: Application
This document shows how to manage applications with Juju.
- Deploy an application
- View details about an application
- Manage an application’s public availability over the network
- Trust an application with a credential
- Configure an application
- Manage machine constraints for an application
- Scale an application
- Change space bindings for an application
- Upgrade an application
- Remove 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 directory of the charm that delivers the application and, optionally, a custom application name:
juju deploy <charm | <path/to/charm directory> <custom application name>
Example: Deploy MySQL from Charmhub using the `mysql` charm
juju deploy mysql
Example: Deploy an application from a local machine charm
juju deploy ./mini_ubuntu-20.04-amd64.charm
Example: Deploy an application from a local Kubernetes charm
To deploy an application from a local Kubernetes charm, you must also specify a resource.
juju deploy ./demo-api-charm_ubuntu-22.04-amd64.charm --resource \ demo-server-image=ghcr.io/beliaev-maksim/api_demo_server:0.0.9
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).
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 also: Control application network ingress
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.
Since Juju 2.9, operators can explicitly specify the list of CIDRs and/or spaces that should be able to access the ports opened by the application. See Controlling application expose settings via the Juju CLI to learn more about this feature.
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
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 220.127.116.11 ready wordpress/0* active idle 0 18.104.22.168 80/tcp
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
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 ...
juju deploy --trust
Trust an application after deployment. To trust an application after deployment, use the
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 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 at deployment time. Juju provides tools to help manage these options and respond to changes over the lifetime of the application. These options apply to the entire application, as opposed to only a specific unit or relation. The configuration can be done at deployment time or post-deployment.
- Discover application configuration options
- Configure an application during deployment
- Configure an application post deployment
Each charm will have its own set of options and possible values. You can discover these in several ways:
- by running the
- by viewing the charm on Charmhub
- by examining the
config.yamlfile in the charm itself
Configuration values can be set at deployment time using the following methods:
- by using a yaml-formatted file
- by passing options/values directly on the command line
- a combination of the above
All these methods use the
For example, upon investigation we discover that the Mediawiki charm allows us to set values for the
name of the wiki and the
skin to use. We can put these inside a configuration file.
mediawiki: name: Juju Wiki skin: monobook
Assuming the file is called
myconfig.yaml, the application can be deployed and configured in this way:
juju deploy --config myconfig.yaml mediawiki
If the configuration file cannot be read or contains syntax errors or invalid options, an error message will be printed to this effect. However, the application will still be deployed.
To pass the options directly:
juju deploy --config name='Juju Wiki' --config skin='monobook'
A combination can also be used. If a duplication arises, the last-mentioned value gets used. For instance, below, the wiki will be assigned the name of ‘Juju Wiki’:
juju deploy --config name='Juju Wookie' --config myconfig.yaml
It is possible to set or change the configuration of an application which is already deployed.
Before you set any of these options, you may want to check what current options are already set. For example:
juju config mediawiki
Should return something like this:
application: mediawiki charm: mediawiki settings: admins: description: Admin users to create, user:pass is_default: true type: string value: "" debug: description: turn on debugging features of mediawiki is_default: true type: boolean value: false logo: description: URL to fetch logo from is_default: true type: string value: "" name: description: The name, or Title of the Wiki is_default: true type: string value: Please set name of wiki server_address: description: The server url to set "$wgServer". Useful for reverse proxies is_default: true type: string value: "" skin: description: skin for the Wiki is_default: true type: string value: vector use_suffix: description: If we should put '/mediawiki' suffix on the url is_default: true type: boolean value: true
You can set the options in a very similar way. Simply add space-separated key=value pairs as arguments:
juju config mediawiki skin=monoblock name='Juju Wiki'
It is also possible to set options from a YAML file:
juju config mediawiki --file path/to/myconfig.yaml
Setting an option back to its default value is achieved with the
--reset option. Here, the argument is a comma-separated list of the option names in question:
juju config mediawiki --reset admins,name
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
deploycommand with the
--constraintsflag 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
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
juju deploy --constraints
If you want to use the
image-id constraint with
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
juju deploy --base
- To set machine constraints for an application after deployment, run the
set-constraintscommand 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= ).
Get values. To view an application’s current constraints, use the
juju constraints mariadb
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.
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
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
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.
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 up while in a Kubernetes model the total number of desired units for the application is simply stated. Here we want a total of three 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 up by adding an extra unit one can simply do:
juju add-unit wordpress
This will cause a new unit (and machine) to be spawned and configured to work alongside the existing one.
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
deploy command, it is possible to co-locate multiple applications on a single machine. This is done via the
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.
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
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
When developing charms using the Operator Framework, scaling is handled via relation events - specifically through peer relations. For more information see:
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
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.
status to find the current channel.
info followed by the charm name to find out all the available channels.
refresh followed by the charm name and the
channel option to change the charm to the desired channel.
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:
--switch are mutually exclusive. Use
--switch if you want to replace your existing charm with a completely new charm.)
See also: Removing things reference
An application can be removed with:
juju remove-application <application-name>
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
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.
An application offer (for a cross model relation) is removed with:
juju remove-offer <offer url>
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
Last updated a month ago.