[relay] Align the UBI image with the shared UBI pattern

Main now ships UBI variants of the client, combined server and proxy that
share one license collector and one image layout, and the Red Hat
certification workflow expects every certified image to carry both amd64
and arm64. The relay variant predated that, kept its own copy of the
license script, built amd64 only, and ran as UID 65532 on the privileged
default port :443, so it would not start under OpenShift or rootless Podman.

Use release_files/collect-licenses.sh and build amd64 and arm64 like the
other UBI images. Run as 1000:0 with a group-0 writable /var/lib/netbird
for Let's Encrypt data, and default the listener to :8443 so an arbitrary
non-root UID can bind it; the relay's Let's Encrypt flow uses TLS-ALPN on
that same listener, so no separate challenge port is needed.
This commit is contained in:
jnfrati
2026-10-09 12:14:20 +02:00
parent 60896afb9e
commit 62bebb6cbb
3 changed files with 20 additions and 86 deletions
+2 -2
View File
@@ -462,15 +462,15 @@ dockers_v2:
dockerfile: relay/Dockerfile.ubi
platforms:
- linux/amd64
- linux/arm64
build_args:
VERSION: "{{ .Version }}"
RELEASE: "{{ .Timestamp }}"
hooks:
pre:
- cmd: 'sh relay/collect-licenses.sh "{{ .ContextDir }}/licenses"'
- cmd: 'sh release_files/collect-licenses.sh -l relay/LICENSE "{{ .ContextDir }}/licenses" ./relay amd64 arm64'
env:
- GOOS=linux
- GOARCH=amd64
- CGO_ENABLED=0
labels:
"org.opencontainers.image.created": "{{.Date}}"
+18 -8
View File
@@ -9,15 +9,25 @@ LABEL name="netbird-relay" \
vendor="NetBird GmbH" \
version="${VERSION}" \
release="${RELEASE}" \
summary="NetBird Relay server" \
description="NetBird Relay carries traffic when a direct peer connection is unavailable."
summary="NetBird Relay" \
description="NetBird Relay carries traffic between peers when a direct connection is unavailable."
COPY --chmod=0555 ${TARGETPLATFORM}/netbird-relay /go/bin/netbird-relay
COPY licenses/AGPL-3.0.txt licenses/BSD-3-Clause.txt licenses/Go-LICENSE licenses/Go-PATENTS /licenses/
COPY licenses/third_party/ /licenses/third_party/
RUN chmod -R a+rX /licenses
COPY licenses/ /licenses/
# Only the data directory shares the root group for arbitrary non-root UIDs.
# Runtime-created Let's Encrypt keys retain the application's restrictive modes.
RUN mkdir -p /var/lib/netbird && \
chown 1000:0 /var/lib/netbird && \
chmod 0770 /var/lib/netbird && \
chmod -R a+rX /licenses
USER 65532
STOPSIGNAL SIGTERM
ENTRYPOINT [ "/go/bin/netbird-relay" ]
USER 1000:0
ENV HOME=/var/lib/netbird
ENV NB_LOG_FILE=console
# Unprivileged port: runtimes such as OpenShift and Podman keep the kernel
# default that reserves ports below 1024 for root. 8443/udp carries QUIC and
# 9000 is the health probe.
ENV NB_LISTEN_ADDRESS=":8443"
EXPOSE 8443 8443/udp
STOPSIGNAL SIGTERM
ENTRYPOINT ["/go/bin/netbird-relay"]
-76
View File
@@ -1,76 +0,0 @@
#!/bin/sh
set -eu
if [ "$#" -ne 1 ]; then
printf '%s\n' "usage: $0 OUTPUT_DIRECTORY" >&2
exit 2
fi
repo_root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
output_name=$(basename "$1")
case "$output_name" in
"" | . | .. | /)
printf '%s\n' "OUTPUT_DIRECTORY must name a directory" >&2
exit 2
;;
esac
output_parent=$(CDPATH= cd -- "$(dirname "$1")" && pwd)
output="$output_parent/$output_name"
modules=$(mktemp "${TMPDIR:-/tmp}/netbird-relay-licenses.modules.XXXXXX")
sorted_modules=$(mktemp "${TMPDIR:-/tmp}/netbird-relay-licenses.sorted.XXXXXX")
trap 'rm -f "$modules" "$sorted_modules"' EXIT HUP INT TERM
if [ -e "$output" ] || [ -L "$output" ]; then
printf 'output directory already exists: %s\n' "$output" >&2
exit 1
fi
mkdir "$output"
mkdir "$output/third_party"
cp "$repo_root/relay/LICENSE" "$output/AGPL-3.0.txt"
cp "$repo_root/LICENSE" "$output/BSD-3-Clause.txt"
cd "$repo_root"
GOOS=${GOOS:-linux} GOARCH=${GOARCH:-amd64} CGO_ENABLED=${CGO_ENABLED:-0} \
go list -deps -f '{{with .Module}}{{if .Replace}}{{.Replace.Path}}{{"\t"}}{{.Replace.Version}}{{"\t"}}{{.Replace.Dir}}{{else}}{{.Path}}{{"\t"}}{{.Version}}{{"\t"}}{{.Dir}}{{end}}{{end}}' ./relay >"$modules"
LC_ALL=C sort -u "$modules" >"$sorted_modules"
goroot=$(go env GOROOT)
for term in LICENSE PATENTS; do
if [ ! -f "$goroot/$term" ]; then
printf 'missing Go standard-library term: %s\n' "$goroot/$term" >&2
exit 1
fi
cp "$goroot/$term" "$output/Go-$term"
done
while IFS=' ' read -r module version module_dir; do
[ -n "$module" ] || continue
[ "$module" = "github.com/netbirdio/netbird" ] && continue
if [ -z "$version" ] || [ ! -d "$module_dir" ]; then
printf 'cannot collect terms for module %s at version %s\n' "$module" "$version" >&2
exit 1
fi
destination="$output/third_party/$module/$version"
mkdir -p "$destination"
printf 'module: %s\nversion: %s\n' "$module" "$version" >"$destination/MODULE"
found=false
for term in \
"$module_dir"/LICENSE* "$module_dir"/License* "$module_dir"/license* \
"$module_dir"/LICENCE* "$module_dir"/Licence* "$module_dir"/licence* \
"$module_dir"/COPYING* "$module_dir"/Copying* "$module_dir"/copying* \
"$module_dir"/NOTICE* "$module_dir"/Notice* "$module_dir"/notice* \
"$module_dir"/PATENTS* "$module_dir"/Patents* "$module_dir"/patents*; do
[ -f "$term" ] || continue
cp "$term" "$destination/"
found=true
done
if [ "$found" = false ]; then
printf 'no root license terms found for module %s at %s\n' "$module" "$module_dir" >&2
exit 1
fi
done <"$sorted_modules"