Skip to content
Français
Conteneurs & Orchestration medium

Multi-tenant private cloud with Incus: projects, quotas and peering

15 min de lecture

Read this page in French

incus logo

An Incus cluster does not have to serve a single team: it can host several isolated tenants, each with its own instances, its own VPC, its own quotas and its own access. All of it rests on projects, the equivalent of accounts on a public cloud. This guide shows how to create a tenant, give it quotas that are genuinely enforced, issue it a credential confined to its perimeter, and peer two OVN VPCs across tenants. It ends with an honest assessment of what is not there yet. Advanced audience, private cloud oriented.

What you will learn

  • Use a project as an isolated tenant.
  • Set quotas and check that they really block.
  • Issue a scoped credential (the equivalent of an access key) and revoke it.
  • Peer two VPCs belonging to different tenants.

Prerequisites

  • A working OVN network: see OVN in Incus.
  • An existing uplink (named UPLINK here).

The project is the tenant

A project isolates its instances, networks, profiles and volumes. You enable features.networks so that it carries its own VPC:

Fenêtre de terminal
incus project create tenant-b -c features.networks=true

Each tenant then creates its own OVN network, its instances and its ACLs, without seeing those of the others.

Setting quotas, and checking that they hold

Quotas bound what a tenant consumes. You set them on the project:

Fenêtre de terminal
incus project set tenant-b \
limits.cpu=4 limits.memory=8GiB limits.instances=5 \
restricted=true restricted.networks.uplinks=UPLINK

A quota is only worth something if it is enforced. You verify that by exceeding it on purpose. With limits.instances=2, the third instance is refused:

Fenêtre de terminal
incus launch images:debian/13 c3 --network vpc-b --storage ceph-rbd --project tenant-b
Error: Failed instance creation: Reached maximum number of instances in project "tenant-b"

The message leaves no room for doubt: Incus quotas really do block.

Issuing a scoped credential

Each user receives their own certificate, restricted to their project. The operator issues a token (the equivalent of an access key):

Fenêtre de terminal
incus config trust add alice --projects tenant-b --restricted
Client alice certificate add token:
eyJjbGllbnRfbmFtZSI6ImFsaWNlIi...

The user adds that token to their own configuration, which generates their certificate, automatically confined:

Fenêtre de terminal
incus remote add mycloud eyJjbGll... # in the user's own config
incus project list mycloud: # they only see tenant-b

They see nothing of the other tenants, and listing the default project comes back empty. To cut access off, you revoke the certificate the way you would disable a key:

Fenêtre de terminal
incus config trust remove <fingerprint>

Peering two VPCs across tenants

By default, two OVN VPCs belonging to different tenants are isolated: they cannot see each other. To connect them, you create a peering, which has to be established on both sides (a mutual relationship):

Fenêtre de terminal
incus network peer create vpc0 to-tenantb tenant-b/vpc-b --project default
incus network peer create vpc-b to-default default/vpc0 --project tenant-b

Once both halves are in place, the state moves to CREATED and traffic routes directly between the two VPCs, without going back through the uplink. One notable point: ACLs stay enforced across the peering. A tenant can reach another tenant's web tier (if allowed), but not its database if an ACL blocks it. That is the behaviour of VPC Peering combined with Security Groups.

What is not there yet (let us be honest)

This model covers the essentials of a private cloud operated by the infrastructure team. Two limits are worth knowing:

  • No fine-grained per-resource RBAC without an extra building block: trust certificates grant access at project level, not "read only on this network". Fine granularity does exist, through OpenFGA, which the Incus documentation describes as a first-class authorization method (authorization.openfga.* options, with the model generated by Incus). The cost is therefore not availability but operations: you have to run your own OpenFGA server and explicitly route the relevant clients to it, otherwise enabling it changes nothing.
  • No self-service portal: the user does not manage their resources from a console of their own the way they would on a public cloud. Everything is driven through the CLI and the API (often via Terraform). The multi-tenant portal remains a layer to build on top.

For a company private cloud driven by IaC, this is enough. For a self-service public cloud, that layer is missing.

Key points

  • A project equals an isolated tenant; features.networks gives it its own VPC.
  • Quotas (limits.*) are enforced: going over the limit is refused.
  • A scoped credential (config trust add --projects --restricted) confines the user to their project; revoking it cuts access.
  • Peering connects two VPCs (mutually), and ACLs stay enforced across it.
  • Fine-grained RBAC needs an OpenFGA server of your own; the self-service portal is still missing entirely.

Next steps

Is this site useful to you?

Fewer than 1% of readers support this site.

I maintain more than 700 free guides, with no ads and no tracking. Any support, even a symbolic one, helps cover hosting and keeps these resources free. Thank you for the help.

The form does not show? Open Ko-fi in a new tab.

Subscribe and follow my DevSecOps work on LinkedIn