Project configuration

LXD supports projects as a way to split your LXD server. Each project holds its own set of instances and may also have its own images and profiles.

What a project contains is defined through the features configuration keys. When a feature is disabled, the project inherits from the default project.

By default all new projects get the entire feature set, on upgrade, existing projects do not get new features enabled.

The key/value configuration is namespaced with the following namespaces currently supported:

  • features (What part of the project featureset is in use)
  • limits (Resource limits applied on containers and VMs belonging to the project)
  • user (free form key/value for user metadata)
Key Type Condition Default Description
features.images boolean - true Separate set of images and image aliases for the project
features.profiles boolean - true Separate set of profiles for the project
features.storage.volumes boolean - true Separate set of storage volumes for the project
limits.containers integer - - Maximum number of containers that can be created in the project
limits.virtual-machines integer - - Maximum number of VMs that can be created in the project
limits.cpu integer - - Maximum value for the sum of individual "limits.cpu" configs set on the instances of the project
limits.memory integer - - Maximum value for the sum of individual "limits.memory" configs set on the instances of the project
limits.processes integer - - Maximum value for the sum of individual "limits.processes" configs set on the instances of the project
restricted boolean - true Block access to security-sensitive features
restricted.containers.nesting string - block Prevents setting security.nesting=true.
restricted.containers.privilege string - unpriviliged If "unpriviliged", prevents setting security.privileged=true. If "isolated", prevents setting security.privileged=true and also security.idmap.isolated=true. If "allow", no restriction apply.
restricted.containers.lowlevel string - block Prevents use of low-level container options like raw.lxc, raw.idmap, volatile, etc.
restricted.virtual-machines.lowlevel string - block Prevents use of low-level virtual-machine options like raw.qemu, volatile, etc.
restricted.devices.disk string - managed If "block" prevent use of disk devices except the root one. If "managed" allow use of disk devices only if "pool=" is set. If "allow", no restrictions apply.
restricted.devices.gpu string - block Prevents use of devices of type "gpu"
restricted.devices.usb string - block Prevents use of devices of type "usb"
restricted.devices.nic string - managed If "block" prevent use of all network devices. If "managed" allow use of network devices only if "network=" is set. If "allow", no restrictions apply.
restricted.devices.infiniband string - block Prevents use of devices of type "infiniband"
restricted.devices.unix-char string - block Prevents use of devices of type "unix-char"
restricted.devices.unix-block string - block Prevents use of devices of type "unix-block"
restricted.devices.unix-hotplug string - block Prevents use of devices of type "unix-hotplug"

Those keys can be set using the lxc tool with:

lxc project set <project> <key> <value>

Project limits

Note that to be able to set one of the limits.* config keys, all instances in the project must have that same config key defined, either directly or via a profile.

In addition to that:

  • The limits.cpu config key also requires that CPU pinning is not used.
  • The limits.memory config key must be set to an absolute value, not a percentage.

The limits.* config keys defined on a project act as a hard upper bound for the aggregate value of the individual limits.* config keys defined on the project's instances, either directly or via profiles.

For example, setting the project's limits.memory config key to 50GB means that the sum of the individual values of all limits.memory config keys defined on the project's instances will be kept under 50GB. Trying to create or modify an instance assigning it a limits.memory value that would make the total sum exceed 50GB, will result in an error.

Similarly, setting the project's limits.cpu config key to 100, means that the sum of individual limits.cpu values will be kept below 100.

Project restrictions

If the restricted config key is set to true, then the instances of the project won't be able to access security-sensitive features, such as container nesting, raw LXC configuration, etc.

The exact set of features that the restricted config key blocks may grow across LXD releases, as more features are added that are considered security-sensitive.

Using the various restricted.* sub-keys, it's possible to pick individual features which would be normally blocked by restricted and white-list them, so they can be used by instances of the project.

For example:

lxc project set <project> restricted=true
lxc project set <project> restricted.containers.nesting=allow

will block all security-sensitive features except container nesting.

Each security-sensitive feature has an associated restricted.* project config sub-key whose default value needs to be explicitly changed if you want for that feature to be white-listed and allow it in the project.

Note that changing the value of a specific restricted.* config key has an effect only if the top-level restricted key itself is currently set to true. If restricted is set to false, changing a restricted.* sub-key is effectively a no-op.

Most 'restricted.* config keys are binary switches that can be set to either block (the default) or allow. However some of them support other values for more fine-grained control.

Setting all restricted.* keys to allow is effectively equivalent to setting restricted itself to false.