Networks

Not supported:

External Networks

Mark a network as external: true to attach services to a pre-existing Incus network. incus-compose will never create or delete an external network.

networks:
  shared:
    external: true

Set name: when the Incus network is not called what the compose file calls it. A bare value is an Incus network name, taken literally — use it for a bridge you manage yourself:

networks:
  shared:
    external: true
    name: alpha:dns # the "dns" network of the "alpha" compose project

The reference goes through the same naming rules the owning project used, so it keeps resolving after a rename to a hash — alpha:dns becomes alpha-dns, and a pair long enough to exceed the interface limit becomes the same ic- hash on both sides. Only the project that declares the network creates it; everyone else is external: true.

Name resolution — incus-compose probes the following candidates in order and uses the first one that exists in Incus:

  1. name: value — literal, only when it names no project
  2. name: value — resolved ({project}-{network}, or its hash)
  3. Compose network name — raw
  4. Compose network name — sanitized

If none of the candidates match an existing network, up fails with a not-found error.

Since: v1.2.0

Automatic DHCP Ranges

When a managed bridge network is created, incus-compose automatically configures DHCP ranges if they are not already set:

IPv4 - The first quarter of the address block is reserved for static assignment. The DHCP range starts at that boundary:

Subnet Static range DHCP range
/24 .1-.63 .64-.254
/16 .0.0-.63.255 .64.0-.255.254
/28 .1-.3 .4-.14

IPv6 - The first 256 addresses (::0-::ff) are reserved for static; DHCP runs from ::100 to ::ffff. Stateful DHCPv6 (ipv6.dhcp.stateful) is enabled automatically.

Setting ipv4.dhcp.ranges or ipv6.dhcp.ranges in x-incus disables auto-calculation for that protocol. Existing networks (already present in Incus when up runs) are never modified.

Static IP Assignment

A service can be assigned a fixed IP on a specific network using the standard Compose ipv4_address / ipv6_address fields on the per-service network attachment:

:::warning An address without a netmask (e.g. 10.100.0.2 instead of 10.100.0.2/24) is invalid and fails silently. :::

services:
  db:
    image: docker.io/postgres:16-alpine
    networks:
      backend:

  web:
    image: docker.io/nginx:alpine
    depends_on:
      db: service_healthy
    networks:
      backend:
      frontend:
        ipv4_address: 10.100.0.2/24
        ipv6_address: fd42:abc::2/64

networks:
  frontend:
    x-incus:
      ipv4.address: "10.0.0.1/24"
      ipv6.address: "fd42:abc::1/64"

  backend:
    internal: true

The address is set as ipv4.address / ipv6.address on the Incus NIC device. The bridge's built-in DHCP server reserves it so the instance always receives that address on the network.

The address must fall within the static zone (first quarter of the block) to avoid conflicts with DHCP-assigned addresses.

Setting internal: true on a network disables its gateway by setting ipv4.gateway and ipv6.gateway to none. This requires Incus 7.3 or later (or the 7.0.2 LTS point release). Override this per-service with x-incus-compose.internal: false.

internal: true since: v1.1.0

Network Aliases

The standard Compose aliases field on a service's network attachment registers extra DNS names for that instance:

services:
  db:
    image: docker.io/postgres:16-alpine
    container_name: my-db
    networks:
      default:
        aliases:
          - db.mydomain.lan

Each alias becomes a cname=<alias>,<instance> record in the network's raw.dnsmasq, resolving straight to the instance, with no DHCP lease to wait for, unlike the IP-based service-name records described in DNS Resolution. Aliases on networks shared by multiple projects (external: true / name:) coexist without clobbering each other's records, the same way service-name records do.

:::warning Because a CNAME alias can only point at one target, aliases is for single-instance services. Declaring it on a service with more than one replica registers the same alias against every replica's instance name, which dnsmasq does not support (an alias must be unique) and produces undefined DNS behavior. Use the service name, which does round-robin, for scaled services instead. :::

Since: v1.1.0