Skip to content

en.Installation Docker OCI

Jens Maus edited this page Oct 5, 2026 · 8 revisions

OpenCCU can be run as a Docker/OCI container on existing amd64 or arm64 (aarch64) systems. The container provides almost all functionality of a "normal" OpenCCU system; certain features – such as the network setup or the WebUI-based update mechanism – are intentionally disabled, however, since these tasks are typically performed on the host system rather than inside the container.

As with a regular OpenCCU installation, compatible Homematic radio modules are required. However, the corresponding kernel drivers for radio modules such as RPI-RF-MOD, HM-MOD-RPI-PCB, HmIP-RFUSB as well as for the HB-RF-USB / HB-RF-USB-2 and HB-RF-ETH adapters must be installed on the host, not inside the container; the container then uses these already loaded drivers. The drivers can be installed either via the install-docker.sh script or manually. In both cases, the kernel modules provided by @alexreinert via piVCCU are installed on the host.

Important

Known limitations

To enable OpenCCU to communicate with an HmIP-HAP or HmIPW-DRAP, the following guide uses a macvlan Docker network. This requires two static IP addresses – <IP-ADDRESS> and <AUX-ADDRESS> – from your local network that are outside the DHCP range of your router. <IP-ADDRESS> is assigned to the container and <AUX-ADDRESS> to the Docker host so that host and container can reach each other.


Requirements

  • A Debian-based amd64 or arm64 host system (e.g. Debian, Ubuntu, Raspberry Pi OS 64-bit, Armbian). 32-bit systems are no longer supported since OpenCCU 3.87.6.20260313.
  • A current version of the pivccu-modules-dkms kernel modules (at least 1.0.88). Older versions cause the Homematic IP service in the container not to start or an HmIP-RFUSB-TK not to be detected.
  • A supported radio module.

Install and prepare Docker on the host:

  1. Install Docker:
    sudo sh -c "wget -qO - https://get.docker.com | bash -"
  2. Add your user to the docker group so that it can run Docker commands:
    sudo usermod -aG docker $USER
    exec su -l $USER
  3. Verify Docker works with the hello-world example:
    docker run hello-world

Afterwards, the host is ready to run Docker containers.


Installation

To set up all requirements and start the OpenCCU container, you can either use the install-docker.sh script or proceed manually with docker pull, docker load or Docker Compose.

Placeholders used – replace them with the values of your environment:

  • <IP-ADDRESS> – the static IP address (e.g. 192.168.178.4) of the container; outside the DHCP range.
  • <AUX-ADDRESS> – an auxiliary static IP address (e.g. 192.168.178.3) for the host, so that host and container can communicate in the same subnet; also outside the DHCP range and not the host's main IP.
  • <INTERFACE> – the primary network interface of the host (e.g. eth0).
  • <SUBNET> – the subnet of the local network (e.g. 192.168.178.0/24).
  • <GATEWAY> – the IP address of the default gateway (e.g. 192.168.178.1).

Automatic Installation

For the simplest possible setup (or with little Linux/Docker experience), the installation script is recommended:

  1. Run:

    wget -qO - https://openccu.de/install-docker.sh | bash -

    If the script requests elevated privileges, run it again with sudo:

    sudo sh -c "wget -qO - https://openccu.de/install-docker.sh | bash -"

    During the installation, the script may ask for the following values:

    • <IP-ADDRESS> – IP address of the container (static, outside DHCP)
    • <AUX-ADDRESS> – auxiliary IP address of the host (static, outside DHCP)
    • <INTERFACE>, <SUBNET>, <GATEWAY> – detected automatically, but can be adjusted
  2. Start the container:

    docker start -i ccu

    Note: Without -i, the container starts in the background.

The script can be run again at any time to check the Docker setup, to adapt to changes in OpenCCU or to update OpenCCU. Further settings of the script are described in the appendix.

Manual Installation

For full control (or when using tools such as Docker Compose), proceed as follows.

Host Dependencies

Install the following dependencies on the Docker host so that the OpenCCU container can access the Homematic radio hardware correctly:

  1. Install pivccu-modules-dkms (drivers for RPI-RF-MOD, HM-MOD-RPI-PCB, HmIP-RFUSB as well as HB-RF-USB(-2)/HB-RF-ETH):

    sudo apt install wget ca-certificates build-essential bison flex libssl-dev gpg
    wget -qO - https://apt.pivccu.de/piVCCU/public.key | sudo gpg --dearmor -o /usr/share/keyrings/pivccu-archive-keyring.gpg
    sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/pivccu-archive-keyring.gpg] https://apt.pivccu.de/piVCCU stable main" >/etc/apt/sources.list.d/pivccu.list'
    sudo apt update
    sudo apt install pivccu-modules-dkms

    Compiling the modules requires the kernel headers of the running kernel, e.g. linux-headers-rpi-v8 on Raspberry Pi OS (64-bit) or linux-headers-$(uname -r) on Debian/Ubuntu.

  2. GPIO radio module (RPI-RF-MOD / HM-MOD-RPI-PCB) – not required for HB-RF-USB, HB-RF-USB-2, HB-RF-ETH or HmIP-RFUSB:

    • Armbian: Install the device tree overlays:
      sudo apt install pivccu-devicetree-armbian
    • Raspberry Pi OS:
      1. Install the device tree overlays:
        sudo apt install pivccu-modules-raspberrypi
      2. Free the serial interface for the radio module (not on the Raspberry Pi 5): On the Raspberry Pi 3/4, the onboard Bluetooth occupies the serial interface (ttyAMA0) that the radio module requires on GPIO 14/15.
        • Variant A (recommended, matches the configuration of OpenCCU itself): Move Bluetooth to the mini UART; Bluetooth remains usable with limitations.
          sudo bash -c 'cat <<EOT >>/boot/firmware/config.txt
          enable_uart=1
          dtoverlay=miniuart-bt
          EOT'
        • Variant B (if Bluetooth is not needed or problems occur): Disable Bluetooth completely.
          sudo bash -c 'cat <<EOT >>/boot/firmware/config.txt
          dtoverlay=disable-bt
          EOT'
          sudo systemctl disable hciuart
      3. Disable the serial console:
        sudo sed -i /boot/firmware/cmdline.txt -e "s/console=\(serial0\|ttyAMA0\),[0-9]\+ //"
        sudo systemctl stop serial-getty@ttyAMA0.service && sudo systemctl disable serial-getty@ttyAMA0.service && sudo systemctl mask serial-getty@ttyAMA0.service
      Note: On older Raspberry Pi OS versions, the files config.txt and cmdline.txt are located directly under /boot/.
  3. HmIP-RFUSB – ensure that no conflicting udev rule is present:

    sudo rm -f /etc/udev/rules.d/10-hmiprfusb.rules
  4. Create udev rules for Homematic devices:

    sudo bash -c 'cat <<EOF >/etc/udev/rules.d/99-Homematic.rules
    ATTRS{idVendor}=="1b1f", ATTRS{idProduct}=="c020", ENV{ID_MM_DEVICE_IGNORE}="1"
    ATTRS{idVendor}=="1b1f", ATTRS{idProduct}=="c00f", ENV{ID_MM_DEVICE_IGNORE}="1"
    ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6f70", ENV{ID_MM_DEVICE_IGNORE}="1"
    ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8c07", ENV{ID_MM_DEVICE_IGNORE}="1"
    EOF'
  5. Load eq3_char_loop at boot:

    sudo sh -c 'echo eq3_char_loop >/etc/modules-load.d/eq3_char_loop.conf'
  6. Start/load the kernel modules now:

    sudo service pivccu-dkms start
    sudo modprobe eq3_char_loop

    Note: If modprobe eq3_char_loop fails, install or update the kernel headers (see step 1) and recompile the modules:

    sudo apt install --reinstall pivccu-modules-dkms
  7. Create a macvlan network named ccu (not needed when using Docker Compose, see below):

    docker network create -d macvlan \
                          --opt parent=<INTERFACE> \
                          --subnet <SUBNET> \
                          --gateway <GATEWAY> \
                          ccu
  8. Set up a "shim" link so that the host can reach the container (macvlan isolates host and containers by default):

    sudo ip link add ccu-shim link <INTERFACE> type macvlan mode bridge
    sudo ip addr add <AUX-ADDRESS> dev ccu-shim
    sudo ip link set ccu-shim up
    sudo ip route add <IP-ADDRESS> dev ccu-shim protocol static

    These ip commands are not persistent; they must be run on every boot or added to a boot-time script.

    Example for Debian/Ubuntu with ifupdown – create the file /etc/network/if-up.d/99-ccu-shim-network:

    #!/bin/sh
    if [ "$IFACE" = "<INTERFACE>" ]; then
      if ! ip link show ccu-shim >/dev/null 2>&1; then
        ip link add ccu-shim link <INTERFACE> type macvlan mode bridge
        ip addr add <AUX-ADDRESS> dev ccu-shim
        ip link set ccu-shim up
        ip route add <IP-ADDRESS> dev ccu-shim protocol static
      fi
    fi

    Then:

    sudo chmod a+rx /etc/network/if-up.d/99-ccu-shim-network

    Example for systems with NetworkManager (e.g. Raspberry Pi OS):

    sudo nmcli connection add type macvlan con-name ccu-shim ifname ccu-shim mode bridge dev <INTERFACE>
    sudo nmcli connection modify ccu-shim ipv4.addresses "<AUX-ADDRESS>"
    sudo nmcli connection modify ccu-shim ipv4.method manual
    sudo nmcli connection modify ccu-shim +ipv4.routes "<IP-ADDRESS>"
    sudo nmcli connection modify ccu-shim connection.autoconnect yes
    sudo nmcli connection up ccu-shim

    To verify that the settings have been stored correctly:

    nmcli device status
    ip route show

Container Setup / Startup

The container can be set up via docker pull, docker load or Docker Compose (or via the install-docker.sh script). Replace all <…> placeholders accordingly.

Using docker pull
  1. Pull the latest image:
    docker pull ghcr.io/openccu/openccu:latest
  2. Create the container:
    docker create --name ccu \
                  --read-only \
                  --volume ccu_data:/usr/local:rw \
                  --volume /lib/modules:/lib/modules:ro \
                  --volume /run/udev/control:/run/udev/control \
                  --privileged --restart always --stop-timeout 30 \
                  --network ccu --ip <IP-ADDRESS> --hostname ccu \
                  ghcr.io/openccu/openccu:latest
  3. Start it:
    docker start -i ccu
    Note: Without -i, the container starts in the background.
Using docker load
  1. Download the latest OpenCCU Docker/OCI image (on arm64 hosts, use oci_arm64 instead of oci_amd64):
    wget https://github.com/OpenCCU/OpenCCU/releases/download/3.XX.XX.YYYYMMDD/OpenCCU-3.XX.XX.YYYYMMDD-oci_amd64.tgz
  2. Load it into Docker:
    docker load < OpenCCU-3.XX.XX.YYYYMMDD-oci_amd64.tgz
  3. Create the container:
    docker create --name ccu \
                  --read-only \
                  --volume ccu_data:/usr/local:rw \
                  --volume /lib/modules:/lib/modules:ro \
                  --volume /run/udev/control:/run/udev/control \
                  --privileged --restart always --stop-timeout 30 \
                  --network ccu --ip <IP-ADDRESS> --hostname ccu \
                  ghcr.io/openccu/openccu:amd64-3.XX.XX.YYYYMMDD
  4. Start it:
    docker start -i ccu
    Note: Without -i, the container starts in the background.
Using Docker Compose
  1. Add the following to your docker-compose.yml:
    services:
      openccu:
        image: ghcr.io/openccu/openccu:latest
        container_name: ccu
        hostname: ccu
        read_only: true
        privileged: true
        restart: unless-stopped
        stop_grace_period: 30s
        volumes:
          - ccu_data:/usr/local:rw
          - /lib/modules:/lib/modules:ro
          - /run/udev/control:/run/udev/control
        networks:
          ccu:
            ipv4_address: <IP-ADDRESS>
    volumes:
      ccu_data:
    networks:
      ccu:
        name: ccu
        driver: macvlan
        driver_opts:
          parent: <INTERFACE>
        ipam:
          config:
            - subnet: <SUBNET>
              gateway: <GATEWAY>
  2. Start via Compose:
    docker compose up -d

Potential Container Startup Errors

  1. ERROR: could not insert 'eq3_char_loop': Exec format error The required kernel modules could not be compiled for the host kernel. Remedy:

    sudo apt remove --purge linux-headers-*
    sudo rm -rf /usr/src/linux-headers-*
    sudo apt autoremove && sudo apt autoclean
    sudo apt install linux-headers-generic
    sudo apt install --reinstall pivccu-modules-dkms

    (On Raspberry Pi OS, install the linux-headers-rpi-v8 package instead of linux-headers-generic.)

  2. Homematic IP service does not start or HmIP-RFUSB-TK is not detected The kernel modules on the host are too old. Update pivccu-modules-dkms to at least version 1.0.88:

    sudo apt update && sudo apt install --only-upgrade pivccu-modules-dkms
  3. Slow or unreliable radio communication Make sure the container gets enough CPU time to process radio messages in time. For this purpose, add e.g. --cap-add=SYS_NICE as well as CPU settings to docker create, or in Compose:

    openccu:
      # ...
      cap_add:
        - SYS_NICE
      cpu_shares: 4096  # 4x more CPU cycles during peaks
      deploy:
        update_config:
          order: stop-first
        resources:
          reservations:
            cpus: '0.6'
            memory: 256M
  4. (Partly obsolete) cpu.rt_runtime_us == 0 errors in docker logs ccu The host kernel was compiled with CONFIG_RT_GROUP_SCHED and the Docker daemon lacks sufficient real-time runtime.

    • Set the Docker daemon option in /etc/docker/daemon.json:

      {
        "cpu-rt-runtime": 950000
      }

      Then restart Docker: sudo systemctl restart docker.

    • Depending on the installation method, additionally:

      • install-docker.sh: not required in recent versions.
      • docker pull / docker load: add when creating the container:
        --cpu-rt-runtime 950000 --ulimit rtprio=99
      • Docker Compose (docker-compose.yml):
        cpu_rt_runtime: 950000
        ulimits:
          rtprio: 99

Container Usage

WebUI access

Point your browser to the IP address of the container:

http://<IP-ADDRESS>/

Afterwards, the first steps after installation help with the further setup.

Shell access

Either enable SSH in the WebUI, or:

docker exec -it ccu /bin/sh

Updating to newer versions

Updates are performed from the host (the usual Docker way) using the same method as for the installation – i.e. by running install-docker.sh again, via docker pull and recreating the container, or via Docker Compose (docker compose pull && docker compose up -d). The configuration in the ccu_data volume is preserved.


Uninstallation

To remove the entire OpenCCU container setup (including networks and configurations on the host), run the installation script with the uninstall parameter:

wget -qO - https://openccu.de/install-docker.sh | sudo bash -s uninstall

This removes containers, networks and related configuration files. After a reboot, only the data volume (ccu_data) should remain, which can be deleted with docker volume rm ccu_data if desired.


Appendix

Additional install-docker.sh settings

The defaults of the script can be adjusted via environment variables:

  • CCU_DATA_VOLUME Name of the Docker volume for persistent CCU data (can also point to a mounted NAS, a cluster file system, etc.). Default: ccu_data

  • CCU_OCI_REPO Container image repository to use. Default: ghcr.io/openccu/openccu

  • CCU_OCI_TAG Container image tag. Default: latest

  • CCU_CONTAINER_NAME Name of the container instance (also used as --hostname). Default: ccu

  • CCU_CONTAINER_IP Static IP address of the container (e.g. 192.168.178.4), outside the DHCP range. Default: (empty; prompted interactively)

  • CCU_CONTAINER_IP_AUX Auxiliary IP address of the host (e.g. 192.168.178.3), in the same subnet, outside the DHCP range. Default: (empty; prompted interactively)

  • CCU_NETWORK_NAME Name of the Docker macvlan network. Default: ccu

  • CCU_NETWORK_INTERFACE Network interface of the host (e.g. eth0, ensXX). Default: (auto-detected or prompted)

  • CCU_NETWORK_SUBNET Subnet (e.g. 192.168.178.0/24). Default: (auto-detected or prompted)

  • CCU_NETWORK_GATEWAY IP address of the gateway (e.g. 192.168.178.1). Default: (auto-detected or prompted)

  • CCU_DOCKER_RUN_OPTIONS Additional options for docker run. Default: (empty)

  • CCU_DOCKER_PULL_OPTIONS Additional options for docker pull. Default: (empty)

  • CCU_DOCKER_PULL_REFRESH Whether to refresh the image via docker pull. Default: true

  • CCU_DOCKER_STOP_TIMEOUT Time (in seconds) allowed for the container to stop before Docker kills it. Default: 30

Clone this wiki locally