Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions images/dhcpd-dns-pxe/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
FROM alpine:3.20
MAINTAINER Rich Braun "docker@instantlinux.net"
FROM alpine:3.23
ARG BUILD_DATE
ARG VCS_REF
LABEL org.label-schema.build-date=$BUILD_DATE \
LABEL org.opencontainers.image.authors="Rich Braun docker@instantlinux.net" \
org.label-schema.build-date=$BUILD_DATE \
org.label-schema.license=Apache-2.0 \
org.label-schema.name=dhcpd-dns-pxe \
org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.vcs-url=https://github.com/instantlinux/docker-tools
ARG DHCP_VERSION=4.4.3_p1-r4
ARG DNSMASQ_VERSION=2.90-r3
ARG KEA_VERSION=3.0.2-r0
ARG DNSMASQ_VERSION=2.91-r0

ENV DHCP_BOOT=pxelinux.0 \
ENV DB_HOST=db00 \
DB_NAME=kea \
DB_USER=kea \
DB_SECRETNAME=kea-db-password \
DB_INITIALIZE=yes \
DHCP_BOOT=pxelinux.0 \
DHCP_ENABLE=yes \
DHCP_LEASE_PATH=/var/lib/misc \
DHCP_LEASE_TIME=3600 \
DHCP_NETBIOS_NAME_SERVERS="" \
DHCP_RANGE="" \
DHCP_SUBNET1=192.168.1.0 \
DHCP_SUBNET1_POOL="" \
DNS_ENABLE=yes \
DNS_SERVER="" \
DNS_UPSTREAM=8.8.8.8 \
Expand All @@ -34,11 +38,12 @@ ENV DHCP_BOOT=pxelinux.0 \
TFTP_SERVER=self \
TZ=UTC

RUN apk add --no-cache --update dhcp=$DHCP_VERSION dnsmasq=$DNSMASQ_VERSION && \
mkdir -m 755 /run/dhcp && chown dhcp /run/dhcp
RUN apk add --no-cache --update kea=$KEA_VERSION dnsmasq=$DNSMASQ_VERSION \
kea-admin kea-hook-mysql mariadb-client && \
mkdir -m 755 /run/kea && chown kea /run/kea

EXPOSE 53/udp 67/udp 69/udp
VOLUME $DHCP_LEASE_PATH $TFTP_ROOT /etc/dhcpd.d/local /etc/dnsmasq.d/local
EXPOSE 53/udp 67/udp 69/udp 8000/tcp
VOLUME $TFTP_ROOT /etc/dhcpd.d/local /etc/dnsmasq.d/local
COPY entrypoint.sh /usr/local/bin/
COPY src/*.j2 /root/
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
36 changes: 24 additions & 12 deletions images/dhcpd-dns-pxe/README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
## dhcpd-dns-pxe
[![](https://img.shields.io/docker/v/instantlinux/dhcpd-dns-pxe?sort=date)](https://hub.docker.com/r/instantlinux/dhcpd-dns-pxe/tags "Version badge") [![](https://img.shields.io/docker/image-size/instantlinux/dhcpd-dns-pxe?sort=date)](https://github.com/instantlinux/docker-tools/tree/main/images/dhcpd-dns-pxe "Image badge") ![](https://img.shields.io/badge/platform-amd64%20arm64%20arm%2Fv6%20arm%2Fv7-blue "Platform badge") [![](https://img.shields.io/badge/dockerfile-latest-blue)](https://gitlab.com/instantlinux/docker-tools/-/blob/main/images/dhcpd-dns-pxe/Dockerfile "dockerfile")

Serve DNS and DHCP from one or more small Alpine Linux container(s). This
supplies DNS and tftp (for network PXE booting) using dnsmasq, and
DHCP using your choice of the original ISC dhcpd or the newer
dnsmasq. Any of the three services can be enabled or disabled.
Serve DNS and DHCP from one or more small Alpine Linux container(s). This supplies DNS and tftp (for network PXE booting) using dnsmasq, and DHCP using your choice of kea or dnsmasq. Any of the three services can be enabled or disabled. ISC dhcpd is deprecated by its maintainers, and replaced here with kea in January 2026 starting with tag `3.0.2-r0-2.91-r0`. Look at the subnet and reservation definitions for breaking changes.

### Usage

In kubernetes.yaml / docker-compose.yml, set the environment variables for your environment.

Mount these under /etc:

* /etc/dhcpd.d/local/reserve-<net>.conf: Add any hardware MAC addresses for which you want static IP assignments (see [dhcpd man page](https://linux.die.net/man/5/dhcpd.conf))
* /etc/dhcpd.d/local/ranges: Optional non-overlapping range definitions as noted below
* /etc/kea.d/local/reserve-<net>.conf: Add any hardware MAC addresses for which you want static IP assignments (see [dhcpd man page](https://linux.die.net/man/5/dhcpd.conf))
* /etc/dnsmasq.d/local/hosts: Add entries you want added dnsmasq's DNS service (see [syntax](https://linux.die.net/man/5/hosts))

Mount your PXE boot images and client definitions under /tftpboot/pxelinux.
Mount your PXE boot images and client definitions under /tftpboot/pxelinux. Kea stores reservations on a mariadb/mysql database: generate a secret for database access, and create an empty database `kea` with a user `kea`@`%`:
```
CREATE DATABASE kea;
GRANT USAGE ON *.* TO `kea`@`%` IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON `kea`.* TO `kea`@`%`;
```

See the kubernetes.yaml provided here. If you're using Swarm, see the docker-compose.yml file provided here in the source directory; this needs to run on host network with kernel capability CAP_NET_ADMIN, so it will not currently run in Docker Swarm. (You can run a single instance of this via _docker run_ or _docker-compose_.) This repo has complete instructions for
See the kubernetes.yaml provided here. If you're using Swarm, see the docker-compose.yml file provided here in the source directory. This repo has complete instructions for
[building a kubernetes cluster](https://github.com/instantlinux/docker-tools/blob/main/k8s/README.md) where you can launch with [helm](https://github.com/instantlinux/docker-tools/tree/main/images/dhcpd-dns-pxe/helm), or [kubernetes.yaml](https://github.com/instantlinux/docker-tools/blob/main/images/dhcpd-dns-pxe/kubernetes.yaml) using _make_ and customizing [Makefile.vars](https://github.com/instantlinux/docker-tools/blob/main/k8s/Makefile.vars) after cloning this repo:
~~~
git clone https://github.com/instantlinux/docker-tools.git
cd docker-tools/k8s
make dhcpd-dns-pxe
~~~

You can build a failsafe cluster of DHCP servers under kubernetes using the kubernetes.yaml definition here. Define a ConfigMap with non-overlapping range definitions such as "192.168.1.32 192.168.1.63", "192.16.1.64 192.168.1.95", "192.168.1.96 192.168.1.127" for a set of 3 replicas. If a replica goes down, the others will continue to assign addresses. They won't conflict thanks to the way DHCP protocol works; a client will use the first address offered and ignore any additional offers from the server pool. If a blank range is specified, the dhcp server will offer only reserved MAC/IP assignments.
You can build a failsafe cluster of DHCP servers under kubernetes using the helm chart included here. Define a ConfigMap with your reservations defined as shown in kea documentation, and hosts defined as in the dnsmasq documentation. If a replica goes down, the others will continue to assign addresses. They won't conflict thanks to the way DHCP protocol works; a client will use the first address offered and ignore any additional offers from the server pool. Subsequent requests will be checked against the reservations database.

Verified to work with a single subnet and with the limited set of DHCP/DNS options supported in environment vars defined here. Additional options as defined in the [dnsmasq man page](https://linux.die.net/man/8/dnsmasq) can be specified as any .conf file under /etc/dnsmasq.d/local volume mount, and for dhcpd as any .conf file under /etc/dhcpd.d/local.

I don't use the DHCP feature of dnsmasq; its software configuration
is hugely different from ISC and much more difficult to customize if
is hugely different from ISC/kea and much more difficult to customize if
you've been using ISC all along. If you've been using dnsmasq all
along, simply set variable DHCP_ENABLE=no and volume-mount your configuration as /etc/dnsmasq.d/local/dhcpd-options.conf; dnsmasq will serve
DHCP on port 67 if you have any such options specified.
Expand All @@ -42,18 +43,24 @@ These variables can be passed to the image from kubernetes.yaml or docker-compos

Variable | Default | Description |
-------- | ------- | ----------- |
DB_HOST | db00 | database host for kea
DB_INITIALIZE | yes | set to no after initial setup
DB_NAME | kea | db schema
DB_SECRETNAME | kea-db-password | name of k8s secret
DB_USER | kea | db username
DHCP_BOOT | pxelinux.0 | PXE-boot filename
DHCP_ENABLE | yes | enable dhcp server
DHCP_LEASE_PATH | /var/lib/misc | don't change this
DHCP_LEASE_TIME | 3600 | default lease time
DHCP_NETBIOS_NAME_SERVERS | | netBIOS name servers
DHCP_RANGE | | dynamic IP pool, e.g. "192.168.1.101 192.168.1.150"
DHCP_SUBNET1 | 192.168.1.0/24 | subnet
DHCP_SUBNET1_POOL | | dynamic IP pool, e.g. "192.168.1.101 - 192.168.1.150"
DNS_ENABLE | yes | enable dns server
DNS_SERVER | | list of (other) DNS servers to send dhcp clients
DNS_UPSTREAM | 8.8.8.8 | upstream DNS server for queries (e.g. your ISP)
DOMAIN | example.com | your domain name
IP_FORWARDING | false | enable clients' IP forwarding
LISTEN_ADDRESS | | bind to IP address
LISTEN_ADDRESS | | bind dnsmasq to IP address
MAX_LEASE_TIME | 14400 | maximum lease time
NTP_SERVER | 0.pool.ntp.org,1.pool.ntp.org |
PORT_DNSMASQ_DNS | 53 | port number for DNS
Expand All @@ -63,6 +70,11 @@ SUBNET1_NETMASK | 255.255.255.0 | network mask
TFTP_ENABLE | yes | enable tftp server
TFTP_ROOT | /tftpboot/pxelinux | don't change this

### Secrets
| Secret | Description |
| ------ | ----------- |
| kea-db-password | database password |

### Contributing

If you want to make improvements to this image, see [CONTRIBUTING](https://github.com/instantlinux/docker-tools/blob/main/CONTRIBUTING.md).
Expand Down
10 changes: 5 additions & 5 deletions images/dhcpd-dns-pxe/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ services:
image: ${REGISTRY_URI:-instantlinux}/dhcpd-dns-pxe:latest
restart: always
environment:
DB_HOST: ${DB_HOST:-db00}
DHCP_NETBIOS_NAME_SERVERS: ${DHCP_NETBIOS_NAME_SERVERS}
DHCP_RANGE: ${DHCP_RANGE}
DHCP_SUBNET1: ${DHCP_SUBNET1:-192.168.1.0}
DHCP_SUBNET1: ${DHCP_SUBNET1:-192.168.1.0/24}
DHCP_SUBNET1_POOL: ${DHCP_SUBNET1_POOL}
DOMAIN: ${DOMAIN:-example.com}
DNS_SERVER: ${DNS_SERVERS:-8.8.8.8}
DNS_UPSTREAM: ${DNS_UPSTREAM:-8.8.8.8}
Expand All @@ -20,14 +21,13 @@ services:
- ${PORT_DNSMASQ_DNS:-53}:53/udp
- 67:67/udp
- 69:69/udp
- 8000:8000/tcp
volumes:
- ${SHARE_PATH}/dhcpd-dns-pxe/pxelinux:/tftpboot/pxelinux:ro
- ${ADMIN_PATH}/dhcpd-dns-pxe/etc/dhcpd.d:/etc/dhcpd.d/local:ro
- ${ADMIN_PATH}/dhcpd-dns-pxe/etc/kea.d:/etc/dhcpd.d/local:ro
- ${ADMIN_PATH}/dhcpd-dns-pxe/etc/dnsmasq.d:/etc/dnsmasq.d/local:ro
- leases:/var/lib/misc
network_mode: host
cap_add:
- NET_ADMIN

volumes:
leases:
50 changes: 27 additions & 23 deletions images/dhcpd-dns-pxe/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
#! /bin/sh -e

# created 27 sep 2017 by richb
# Populates dhcpd.conf and defaults in /etc/dhcpd.d & /etc/dnsmasq.d
# Starts dhcpd (optionally) and dnsmasq
# Populates kea.conf and defaults in /etc/kea.d & /etc/dnsmasq.d
# Starts kea dhcpd (optionally) and dnsmasq

DHCP_USER=dhcp
DHCP_USER=kea

if [ "$DHCP_ENABLE" == yes ]; then
if [ ! -z "$NETBIOS_NAME_SERVERS" ]; then
NETBIOS_OPTION="option netbios-name-servers $DHCP_NETBIOS_NAME_SERVERS;"
NETBIOS_OPTION="{\"space\": \"dhcp4\", \"name\": \"netbios-name-servers\", \"code\": 44, \"data\": \"$DHCP_NETBIOS_NAME_SERVERS\"},"
fi
if [ ! -z "$DHCP_RANGE" ]; then
RANGE_OPTION="range $DHCP_RANGE;"
elif [ "$(ls -A /etc/dhcpd.d/ranges)" ]; then
RANGE=$(cat /etc/dhcpd.d/ranges/$POD_NAME)
[ -z "$RANGE" ] || RANGE_OPTION="range $RANGE;"
if [ ! -z "$DHCP_SUBNET1_POOL" ]; then
POOL_OPTION="\"pools\": [{\"pool\": \"$DHCP_SUBNET1_POOL\"}],"
fi
if [ "$TFTP_SERVER" == self ]; then
TFTP_SERVER=$(ifconfig $SUBNET1_INTERFACE | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}')
fi
for file in /etc/dhcpd.conf /etc/dhcpd.d/default.conf /etc/dhcpd.d/subnet.conf /etc/dhcpd.d/apc-rpdu.conf; do
[ -d /etc/kea.d ] || mkdir -m 750 /etc/kea.d
chgrp kea /etc/kea.d
for file in /etc/kea/kea.conf /etc/kea.d/local.conf /etc/kea.d/subnet.conf /etc/kea.d/apc-rpdu.conf; do
if [ ! -e $file ]; then
sed -e "s:{{ DHCP_BOOT }}:$DHCP_BOOT:" \
sed -e "s:{{ DB_HOST }}:$DB_HOST:" \
-e "s:{{ DB_NAME }}:$DB_NAME:" \
-e "s:{{ DB_USER }}:$DB_USER:" \
-e "s:{{ DHCP_BOOT }}:$DHCP_BOOT:" \
-e "s:{{ DHCP_LEASE_TIME }}:$DHCP_LEASE_TIME:" \
-e "s:{{ DHCP_NETBIOS_NAME_SERVERS }}:$DHCP_NETBIOS_NAME_SERVERS:" \
-e "s:{{ DHCP_RANGE }}:$DHCP_RANGE:" \
Expand All @@ -31,29 +33,31 @@ if [ "$DHCP_ENABLE" == yes ]; then
-e "s:{{ DOMAIN }}:$DOMAIN:" \
-e "s:{{ IP_FORWARDING }}:$IP_FORWARDING:" \
-e "s:{{ MAX_LEASE_TIME }}:$MAX_LEASE_TIME:" \
-e "s:{{ NETBIOS_OPTION }}:$NETBIOS_OPTION:" \
-e "s+{{ NETBIOS_OPTION }}+$NETBIOS_OPTION+" \
-e "s:{{ NTP_SERVER }}:$NTP_SERVER:" \
-e "s:{{ RANGE_OPTION }}:$RANGE_OPTION:" \
-e "s+{{ POOL_OPTION }}+$POOL_OPTION+" \
-e "s:{{ SUBNET1_GATEWAY }}:$SUBNET1_GATEWAY:" \
-e "s:{{ SUBNET1_INTERFACE }}:$SUBNET1_INTERFACE:" \
-e "s:{{ SUBNET1_NETMASK }}:$SUBNET1_NETMASK:" \
-e "s:{{ TFTP_ENABLE }}:$TFTP_ENABLE:" \
-e "s:{{ TFTP_SERVER }}:$TFTP_SERVER:" \
-e "s:{{ TZ }}:$TZ:" \
/root/$(basename $file).j2 > $file
fi
done
for file in /etc/dhcpd.d/*.conf /etc/dhcpd.d/local/*.conf; do
if ! grep -q "$file" /etc/dhcpd.conf; then
echo "include \"$file\";" >>/etc/dhcpd.conf
if [ ! -e /run/secrets/$DB_SECRETNAME ]; then
echo kea-db-password secret is not set, proceeding without database
else
DB_PASS=`cat /run/secrets/$DB_SECRETNAME`
sed -i -e "s:{{ DB_PASS }}:$DB_PASS:" /etc/kea/kea.conf
if [ "$DB_INITIALIZE" == yes ]; then
SCHEMA_EXISTS=$(mariadb -s -N -h $DB_HOST -D $DB_NAME -u $DB_USER \
-p"$DB_PASS" -e "SHOW TABLES LIKE 'schema_version';")
[ -z "$SCHEMA_EXISTS" ] && kea-admin db-init mysql -h $DB_HOST \
-n $DB_NAME -u $DB_USER -p "$DB_PASS"
fi
done
if [ ! -z "$LISTEN_ADDRESS" ]; then
LISTEN_FLAG="-s $LISTEN_ADDRESS"
fi
touch $DHCP_LEASE_PATH/dhcpd.leases
chown $DHCP_USER $DHCP_LEASE_PATH/dhcpd.leases
dhcpd -d -cf /etc/dhcpd.conf -lf $DHCP_LEASE_PATH/dhcpd.leases \
-user $DHCP_USER -group daemon $LISTEN_FLAG $SUBNET1_INTERFACE &
kea-dhcp4 -c /etc/kea/kea.conf &
fi

if [ "$TFTP_ENABLE" == yes ]; then
Expand Down
4 changes: 2 additions & 2 deletions images/dhcpd-dns-pxe/helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ sources:
- https://source.isc.org/git/dhcp.git
- http://thekelleys.org.uk/gitweb/?p=dnsmasq.git
type: application
version: 0.1.12
appVersion: "4.4.3_p1-r4-2.90-r3"
version: 0.2.1
appVersion: "3.0.2-r0-2.91-r0"
dependencies:
- name: chartlib
version: 0.1.8
Expand Down
48 changes: 22 additions & 26 deletions images/dhcpd-dns-pxe/helm/values.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Default values for dhcpd-dns-pxe.
dhcpPoolRanges:
dhcpd-dns-pxe-0: 192.168.1.8 192.168.1.15
dhcpd-dns-pxe-1: 192.168.1.16 192.168.1.31
dhcpd-dns-pxe-2: ""

statefulset:
deployment:
env:
db_initialize: yes
db_host: db00
db_name: kea
db_user: kea
dhcp_netbios_name_servers: 192.168.1.50,192.168.1.60
dhcp_subnet1: 192.168.1.0
dhcp_subnet1_pool: 192.168.1.8 - 192.168.1.31
domain: example.com
dns_server: 192.168.1.40,192.168.1.45
dns_upstream: 8.8.8.8
Expand All @@ -22,10 +22,15 @@ statefulset:
fieldRef:
fieldPath: metadata.name
hostNetwork: true
securityContext:
capabilities:
add: [ NET_ADMIN ]
replicas: 3
containerPorts:
- containerPort: 67
protocol: UDP
- containerPort: 68
protocol: UDP
- containerPort: 8000
nodeSelector:
service.dhcpd-dns-pxe: allow
replicas: 2
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
Expand All @@ -40,33 +45,24 @@ volumeMounts:
name: share
readOnly: true
subPath: dhcpd-dns-pxe/pxelinux
- mountPath: /etc/dhcpd.d/ranges
name: ranges
- mountPath: /etc/dhcpd.d/local/reservations.conf
- mountPath: /etc/kea.d/local/reservations.conf
name: config
subPath: reservations
- mountPath: /etc/dnsmasq.d/local/hosts
name: config
subPath: hosts
- mountPath: /var/lib/misc
name: leases
- mountPath: /run/secrets/kea-db-password
name: kea-db-password
subPath: kea-db-password
volumes:
- name: config
configMap:
name: dhcpd-dns-pxe
- name: ranges
configMap:
name: dhcpd-dns-pxe-ranges
- name: kea-db-password
secret:
secretName: kea-db-password
- name: share
hostPath: { path: /var/lib/docker/k8s-volumes/share }
volumeClaimTemplates:
- metadata:
name: leases
spec:
accessModes: [ ReadWriteOnce ]
resources:
requests:
storage: 500Mi

image:
repository: instantlinux/dhcpd-dns-pxe
Expand Down
2 changes: 1 addition & 1 deletion images/dhcpd-dns-pxe/hooks/add_tags
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
VER1=$(grep "ARG DHCP_VERSION" Dockerfile | cut -d= -f 2)
VER1=$(grep "ARG KEA_VERSION" Dockerfile | cut -d= -f 2)
VER2=$(grep "ARG DNSMASQ_VERSION" Dockerfile | cut -d= -f 2)
echo "--tag $DOCKER_REPO:$VER1-$VER2"
2 changes: 1 addition & 1 deletion images/dhcpd-dns-pxe/hooks/post_push
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
VER1=$(grep "ARG DHCP_VERSION" Dockerfile | cut -d= -f 2)
VER1=$(grep "ARG KEA_VERSION" Dockerfile | cut -d= -f 2)
VER2=$(grep "ARG DNSMASQ_VERSION" Dockerfile | cut -d= -f 2)
docker tag $IMAGE_NAME $DOCKER_REPO:$VER1-$VER2
docker push $DOCKER_REPO:$VER1-$VER2
Loading
Loading