How to manage users

See also: User

Juju has an internal user framework that allows for the sharing of controllers and models. To achieve this, a Juju user can be created, disabled, and have rights granted and revoked. Users remote to the system that created a controller can use their own Juju client to log in to the controller and manage the environment based on the rights conferred. Multiple users can be accommodated by the same Juju client.


Create a user

There are two ways to create a user in Juju:


See also: juju bootstrap

To add a user implicitly, bootstrap a controller into a cloud.

# Bootstrap a controller into a cloud:
$ juju bootstrap localhost localhost-controller

As you can verify using juju whoami and juju show-user, this creates a user with the username admin and controller-level superuser access.

Expand to view details
# Print current login details:
$ juju whoami
Controller:  localhost-controller
Model:       default
User:        admin

# View details for user `admin`:
$ juju show-user admin
user-name: admin
display-name: admin
access: superuser
date-created: 8 minutes ago
last-connection: just now

If you try to log out via logout, you will also notice that this user lacks a password. Set one using change-user-password.

Expand to view details
# Try to log out:
$ juju logout
ERROR preventing account loss

It appears that you have not changed the password for
your account. If this is the case, change the password
first before logging out, so that you can log in again
afterwards. To change your password, run the command
"juju change-user-password".

If you are sure you want to log out, and it is safe to
clear the credentials from the client, then you can run
this command again with the "--force" option.

# Set a password:
$ juju change-user-password admin
new password: ******
type new password again: ******
Your password has been changed.

To create users with other usernames and roles, use the explicit method.


See also: juju add-user

To add a user explicitly, use the add-user command:

# Add a user named `alex`:
$ juju add-user alex
User "alex" added
Please send this command to alex:
    juju register MFUTBGFsZXgwFRMTMTAuMTM2LjEzNi4xOToxNzA3MAQghBj6RLW5VgmCSWsAesRm5unETluNu1-FczN9oVfNGuYTFGxvY2FsaG9zdC1jb250cm9sbGVy

"alex" has not been granted access to any models. You can use "juju grant" to grant access.

As the output prompt indicates, at this point you can also grant the user more access, if you want. Or you can skip this for now and get back to it later.

Then, send the provided command to the intended user.

On their end, they must run the provided code in a terminal. This will prompt them to set a password (to be stored on the controller) and also choose a name for the controller that they have been given access to (the prompt suggests the original name, below, localhost-controller, but the user can also choose a different name, provided it is unique in the context of the juju client).

$ juju register MFUTBGFsZXgwFRMTMTAuMTM2LjEzNi4xOToxNzA3MAQghBj6RLW5VgmCSWsAesRm5unETluNu1-FczN9oVfNGuYTFGxvY2FsaG9zdC1jb250cm9sbGVy
Enter a new password: ********
Confirm password: ********
Enter a name for this controller [localhost-controller]: localhost-controller
Initial password successfully set for alex.

Welcome, alex. You are now logged into "localhost-controller".

There are no models available. You can add models with
"juju add-model", or you can ask an administrator or owner
of a model to grant access to that model with "juju grant".

Controller registration (and any other Juju operations that involves communication between a client and a controller) necessitates the client be able to contact the controller over the network on TCP port 17070. In particular, if using a LXD-based cloud, network routes need to be in place (i.e. to contact the controller LXD container the client traffic must be routed through the LXD host).

As you can verify on your end, the user thus created has login access only though, as suggested in the output above, you can grant them more privileges via juju grant.

Expand to view details
$ juju show-user alex
user-name: alex
access: login
date-created: 15 minutes ago
last-connection: 2 minutes ago

Logins and logouts

A user who has just registered a controller is automatically logged in to that controller.

A user can log out at any time:

juju logout

To log in to a controller, the administrator needs to specify both the user and the controller:

juju login -u mat -c lxd-bionic-1

The following is a quick way to determine the current user (as well as the current controller and model):

juju whoami

Example output:

Controller:  lxd-bionic-1
Model:       <no-current-model>
User:        mat

See Controller logins for more information.

Disabling and re-enabling users

To immediately sever a user’s communication with their controller the disable-user command is employed. To re-establish communication the enable-user command is used.

To disable the user ‘mike’:

juju disable-user mike

To re-enable:

juju enable-user mike

Disabled users are suppressed in the output to the users command unless the --all option is used, whereby the output will show “disabled”:

Controller: cstack

Name    Display name  Access     Date created    Last connection
admin*  admin         superuser  2018-12-12      just now
mike                  login      17 minutes ago  never connected (disabled)

Changing user passwords

A user is prompted to set a password when registering a controller. This password can subsequently be changed either by the user himself or by a controller admin. For the user, it is simply a matter of running:

juju change-user-password

The admin user supplies the name of the user whose password is to be changed:

juju change-user-password mike

Then simply follow the prompts to enter and confirm a new password.

Re-generating a lost registration string

If the original registering token fails to work or is lost a new token can be generated by a controller admin. This is done through the use of the --reset option in conjunction with the change-user-password command. For example, to generate a new token for ‘jon’:

juju change-user-password jon --reset

The previous token will be invalidated, and the user should register with the new token.

Managing models in a multi-user context

In this section we go over the various ways models can be managed in a multi-user context. Subtopics include:

  • Providing model ownership during model creation
  • Model access
  • Controller access
  • Cloud access (v.2.6.0)

Providing model ownership during model creation

The model creator becomes, by default, the model owner. However, the creation process does allow for owner designation. To add model ‘staging’ and designate user ‘neo’ as the owner:

juju add-model --owner=neo staging

See the Adding a model page for the basics on adding models.

Model access

A controller admin uses the grant command to give a user ‘read’, ‘write’, or ‘admin’ access to a model:

  • read: A user can view the state of a model (e.g. models, machines, and status)
  • write: In addition to ‘read’ abilities, a user can modify/configure models (e.g. model-config and model-defaults).
  • admin: In addition to ‘write’ abilities, a user can perform model upgrades (upgrade-model) and connect to machines via juju ssh. Makes the user an effective model owner. See Machine authentication for how to connect to machines.

Here we give ‘bob’ write access to model ‘genesis’:

juju grant bob write genesis

Current model access for a user can be viewed by specifying the user with the models command. Here we inspect the access enjoyed by user ‘mat’:

juju models --user mat

Sample output:

Controller: lxd-bionic-1

Model            Cloud/Region         Status     Access  Last connection
admin/euphoric*  localhost/localhost  available  read    never connected

Notice how the model name is prepended with the remote user’s name, which is the ‘owner’ of the model.

Access can be viewed on a per-model basis by using the show-model command. Here we query model ‘mara’:

juju show-model mara

Partial output:

      display-name: admin
      access: admin
      last-connection: never connected
      access: write
      last-connection: never connected
      access: admin
      last-connection: never connected

Controller access

A controller actually refers to a special kind of model that acts as the nucleus for each cloud environment. In addition to the three levels of model access, three further levels of access can be applied to a controller:

  • login: the standard access level, enabling a user to log in to a controller.
  • superuser: makes a user an effective controller administrator.

The command syntax for controller access is the same as for model access, only without the need to specify a model. As usual, with no controller specified via the -c option, the current controller is the assumed target.

Here we give ‘jim’ the ‘add-model’ permission:

juju grant jim add-model

Current controller access for all users registered to a controller can be viewed with the users command. Example output:

Controller: azure-1

Name    Display name  Access     Date created  Last connection
admin*  admin         superuser  2018-12-14    just now
bob                   login      1 hour ago    50 minutes ago
jim                   add-model  2018-12-14    58 minutes ago

In addition, a controller admin can use the show-user command to get controller access on a per-user basis, in addition to other information on the user.

Cloud access

Since v.2.6.0, models from more than one cloud can be managed by a controller. The controller will naturally manage the cloud that hosts the controller itself but afterwards other clouds can be added. With such a design it is natural to want to manage user access on a per-cloud basis. This is done with the grant-cloud and revoke-cloud commands.

Revoking access

The revoke command is used by a controller administrator to demote a user’s access to the next lowest level. That is, if a user has ‘write’ access to a model and ‘read’ is revoked then both ‘read’ and ‘write’ are removed. This works similarly for controller access. If a user has ‘superuser’ access and ‘add-model’ is revoked then both ‘add-model’ and ‘superuser’ are removed.

If user ‘bob’ has ‘write’ access to model ‘gotcha’, use the following to remove all access to this model:

juju revoke bob read gotcha

Confirm this action with juju models --user bob.

If user ‘jim’ has ‘superuser’ access to controller ‘waves’, use the following to leave the user with just ‘login’ access:

juju revoke -c waves jim add-model

Confirm this action with juju show-user --user jim.

As usual, if a controller is not specified (-c) the default controller is the currently active one.

I would love to request a permission level of status in addition to the current read, write, and admin permissions. A status level permission would be able to see the status of the cluster without being able to read the configuration of the state of the model. This would be beneficial in environments I’d wish a user to see the relations of the charms and the status of the applications without having to be able to see configuration data which could contain secrets/keys private to those applications. If the user can SEE the config, in many cases they can also access the underlying applications and change them. If there was a status only permission, juju could manage that API. I’m not familiar with the UAC on the juju api – so i’d be happy with some kinda of admin managed permissions of groups/users and permissions to certain APIs.

Link to Bug


The last couple of links (Multi-user basic setup, Multi-user external setup) are broken. They point to [1] and [2].