Last active
January 22, 2026 16:45
-
-
Save Palatis/d8947cb416be61355cfcc4981a4b0ad8 to your computer and use it in GitHub Desktop.
OpenWrt podman use br-lan
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [engine] | |
| hooks_dir = [ | |
| "/etc/containers/oci/hooks.d/", | |
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "version": "1.0.0", | |
| "hook": { | |
| "path": "/root/bin/podman-lan-bridge-hook.sh" | |
| }, | |
| "when": { | |
| "annotations": { | |
| "io.podman.annotations.lan-bridge": "true" | |
| } | |
| }, | |
| "stages": [ "prestart", "poststart", "poststop" ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| LOG="/dev/null" | |
| #LOG="/tmp/podman-hook.log" | |
| PIDFILE_DIR="/var/run/podman/dhcp" | |
| echo "=== Hook called at $(date) ===" >> "$LOG" | |
| # Read all input | |
| input=$(cat) | |
| echo "Stdin: $input" >> "$LOG" | |
| CONTAINER_ID=$(echo "$input" | sed -n 's/.*"id":"\([^"]*\)".*/\1/p') | |
| CONTAINER_PID=$(echo "$input" | sed -n 's/.*"pid":\([0-9]*\).*/\1/p') | |
| STATUS=$(echo "$input" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p') | |
| echo "Container ID: $CONTAINER_ID" >> "$LOG" | |
| echo "Container PID: $CONTAINER_PID" >> "$LOG" | |
| echo "Status: $STATUS" >> "$LOG" | |
| DHCP4_PIDFILE="$PIDFILE_DIR/$CONTAINER_ID.udhcpc.pid" | |
| DHCP6_PIDFILE="$PIDFILE_DIR/$CONTAINER_ID.odhcp6c.pid" | |
| # Determine stage based on status | |
| if [ "$STATUS" = "created" ] && [ -n "$CONTAINER_PID" ]; then | |
| STAGE="prestart" | |
| elif [ "$STATUS" = "running" ]; then | |
| STAGE="poststart" | |
| elif [ "$STATUS" = "stopped" ]; then | |
| STAGE="poststop" | |
| else | |
| echo "Unknown stage, exiting" >> "$LOG" | |
| exit 0 | |
| fi | |
| echo "Stage: $STAGE" >> "$LOG" | |
| case "$STAGE" in | |
| prestart) | |
| mkdir -p $PIDFILE_DIR | |
| # IPv6 | |
| nsenter -t "$CONTAINER_PID" -a sysctl -w net.ipv6.conf.all.accept_ra=2 >> "$LOG" 2>&1 | |
| nsenter -t "$CONTAINER_PID" -a sysctl -w net.ipv6.conf.default.accept_ra=2 >> "$LOG" 2>&1 | |
| nsenter -t "$CONTAINER_PID" -a sysctl -w net.ipv6.conf.eth0.accept_ra=2 >> "$LOG" 2>&1 | |
| nsenter -t "$CONTAINER_PID" -a sysctl -w net.ipv6.conf.eth0.autoconf=1 >> "$LOG" 2>&1 | |
| ;; | |
| poststart) | |
| # Hostname | |
| CONTAINER_HOSTNAME=$(nsenter -t $CONTAINER_PID -u cat /proc/sys/kernel/hostname) | |
| [ -z "$CONTAINER_HOSTNAME" ] && CONTAINER_HOSTNAME="ctr-${CONTAINER_ID:0:10}" | |
| echo "Container Hostname: $CONTAINER_HOSTNAME" >> "$LOG" | |
| # IPv4 | |
| nsenter -t $CONTAINER_PID -m umount /etc/resolv.conf >> "$LOG" | |
| nsenter -t $CONTAINER_PID -a udhcpc -f -R -S -i eth0 -x hostname:$CONTAINER_HOSTNAME 2>&1 >> "$LOG" & | |
| UDHCPC_PID=$! | |
| echo "$UDHCPC_PID" > "$DHCP4_PIDFILE" | |
| echo "udhcpc pid: ${UDHCPC_PID}" >> "$LOG" | |
| # IPv6 | |
| DUID="00048e3c${CONTAINER_ID:0:26}" | |
| nsenter -t "$CONTAINER_PID" -n -u odhcp6c -s /root/bin/dhcpv6.simple.script -c "$DUID" -t120 eth0 2>&1 >> "$LOG" & | |
| ODHCP6C_PID=$! | |
| echo "$ODHCP6C_PID" > "$DHCP6_PIDFILE" | |
| echo "odhcp6c pid: ${ODHCP6C_PID}" >> "$LOG" | |
| ;; | |
| poststop) | |
| echo "Stopping DHCP client..." >> "$LOG" | |
| # kill IPv4 udhcpc | |
| [ -f "$DHCP4_PIDFILE" ] && kill $(cat "$DHCP4_PIDFILE") 2>/dev/null | |
| rm -f "$DHCP4_PIDFILE" | |
| # kill IPv6 odhcpc6 | |
| [ -f "$DHCP6_PIDFILE" ] && kill $(cat "$DHCP6_PIDFILE") 2>/dev/null | |
| rm -f "$DHCP6_PIDFILE" | |
| echo "Cleanup complete" >> "$LOG" | |
| ;; | |
| esac | |
| echo "=== Hook finished ===" >> "$LOG" | |
| exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # Minimal odhcp6c script for container (IPv6 only) | |
| # Works with RA_ADDRESSES / ADDRESSES | |
| IF="$1" | |
| ACTION="$2" | |
| case "$ACTION" in | |
| ra-updated|add|bound) | |
| # assign addresses from ADDRESSES | |
| for addr in $ADDRESSES; do | |
| ip_addr=$(echo "$addr" | cut -d',' -f1) | |
| [ -n "$ip_addr" ] && ip -6 addr add "$ip_addr" dev "$IF" | |
| done | |
| # set default routes from RA_ROUTES | |
| for route in $RA_ROUTES; do | |
| dst=$(echo "$route" | cut -d',' -f1) | |
| gw=$(echo "$route" | cut -d',' -f2) | |
| [ -n "$dst" ] && [ -n "$gw" ] && ip -6 route add "$dst" via "$gw" dev "$IF" || true | |
| done | |
| # update resolv.conf from RDNSS | |
| if [ -n "$RDNSS" ]; then | |
| echo > /etc/resolv.conf | |
| for dns in $RDNSS; do | |
| echo "nameserver $dns" >> /etc/resolv.conf | |
| done | |
| fi | |
| ;; | |
| del|debound) | |
| # remove assigned addresses | |
| for addr in $ADDRESSES; do | |
| ip_addr=$(echo "$addr" | cut -d',' -f1) | |
| [ -n "$ip_addr" ] && ip -6 addr del "$ip_addr" dev "$IF" | |
| done | |
| ;; | |
| esac | |
| exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # podman network create --disable-dns -d bridge --ipv6 --interface-name br-lan --help --ipam-driver dhcp br-lan | |
| # podman inspect br-lan | |
| [ | |
| { | |
| "name": "br-lan", | |
| "id": "...", | |
| "driver": "bridge", | |
| "network_interface": "br-lan", | |
| "created": "2026-01-20T20:37:44.707081309+08:00", | |
| "ipv6_enabled": true, | |
| "internal": false, | |
| "dns_enabled": false, | |
| "ipam_options": { | |
| "driver": "dhcp" | |
| } | |
| } | |
| ] | |
| # podman run -d --name samba --network=br-lan \ | |
| --annotation io.podman.annotations.lan-bridge=true \ | |
| -h samba \ | |
| --mac-address "11:22:33:44:55:66" \ | |
| ghcr.io/servercontainers/samba:smbd-wsdd2-latest |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Issues
podman inspectto obtain the hostname, as it might be more reliable. however can't use that in a hook script because inside hooks the container is in a limbo state andpodman inspectjust hang forever (kill -9to stop it).poststartphase. it's not available duringprestart, the command just retrieve router's hostname instead container's hostname duringprestart.podman exec $CONTAINER_ID udhcpc, container don't have the permission to modify network settings.loggerso things logs into syslog, but dunno why a simplelogger hellodoesn't write anything tologread.