Random Musings

O for a muse of fire, that would ascend the brightest heaven of invention!


Extending OCI container networks with Hooks

Sunday, 29 Jun 2025 Tags: containersfreebsd

Following on from the previous post, after storage, we want networking. FreeBSD provides a rich set of networking facilities, both in the base system, and in the ports collection. But Podman containers are not aware of these, and relies on a shared bridge, and epairs, to allow mediated access to the host’s network stack, supervised by the host firewall.

For this example, let’s create a wireguard interface on the host, and pass it through to the container, so that the container can use it directly, without needing to go via the bridge.

Create the Wireguard interface

Create the Podman Hook

We will create a Podman Hook to delegate an interface into the container, and to remove it when the container stops. This is very similar to the ZFS Hook we created in the previous post. It’s not wireguard-specific, so it can be used for any interface that you want to pass through.

  • add the hook metadata /usr/local/etc/containers/hooks.d/net.json:
{
  "version": "1.0.0",
  "hook": {
    "path": "/usr/local/etc/containers/hooks.d/net.sh"
  },
  "when": {
    "annotations": {
      "^net.interface$": ".+"
    }
  },
  "stages": ["createRuntime", "poststop"]
}
  • add /usr/local/etc/containers/hooks.d/net.sh:
#!/bin/sh -e
set -o pipefail
INPUT=$(  cat - )
ID=$(     echo $INPUT | jq -r .id || exit 1)
STATUS=$( echo $INPUT | jq -r .status || exit 1)
IFACE=$(  echo $INPUT | jq -r '.annotations."net.interface"')

# if we are in created state, we can proceed
if [ "$STATUS" == "created" ]; then
  ifconfig ${IFACE} vnet ${ID}
fi
  • mark the script executable:
# chmod +x /usr/local/etc/containers/hooks.d/*.sh