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
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)
|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>
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:
limits.cpuconfig key also requires that CPU pinning is not used.
limits.memoryconfig key must be set to an absolute value, not a percentage.
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
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
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
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
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.
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
restricted is set to
false, changing a
restricted.* sub-key is
effectively a no-op.
'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.
restricted.* keys to
allow is effectively equivalent to setting
restricted itself to