Skip to content

Commit 76053dc

Browse files
Add Containerfile for Podman/Docker
This adds a simple Containerfile to run Tang within a Fedora-based container. In this PR, the image is not published anywhere, but it is built and tested. Also updates the README to remove the dead link to the external image. Progress on #107.
1 parent 97cffa4 commit 76053dc

17 files changed

+235
-21
lines changed

.github/workflows/build.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,44 @@ jobs:
7171
env:
7272
DISTRO: ${{matrix.os}}
7373

74+
build-podman:
75+
runs-on: ubuntu-24.04
76+
env:
77+
DISTRO: ubuntu:noble
78+
steps:
79+
- uses: actions/checkout@v4
80+
81+
- name: Show OS information
82+
run: cat /etc/os-release 2>/dev/null || \
83+
echo /etc/os-release not available
84+
85+
- name: Install build dependencies
86+
run: sudo --preserve-env bash .github/workflows/install-dependencies
87+
88+
- name: Build tang
89+
run: |
90+
mkdir -p build && cd build
91+
export ninja=$(command -v ninja)
92+
[ -z "${ninja}" ] && export ninja=$(command -v ninja-build)
93+
meson setup .. || cat meson-logs/meson-log.txt >&2
94+
${ninja}
95+
export podman=$(command -v podman)
96+
[ -n "${podman}" ] && ${podman} build -t tangd ..
97+
98+
- name: Run tests
99+
run: |
100+
cd build
101+
if ! meson test ; then
102+
cat meson-logs/testlog.txt >&2
103+
exit -1
104+
fi
105+
106+
- name: Show full test logs
107+
run: |
108+
if [ -r build/meson-logs/testlog.txt ]; then
109+
cat build/meson-logs/testlog.txt >&2
110+
else
111+
echo "No test log available" >&2
112+
fi
113+
74114
# vim:set ts=2 sw=2 et:

.github/workflows/install-dependencies

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ubuntu:focal)
66
apt clean
77
apt update
88
apt -y install gcc pkg-config libjose-dev jose libhttp-parser-dev \
9-
systemd gcovr curl socat iproute2 asciidoc git python3-pip ninja-build
9+
systemd gcovr curl socat iproute2 asciidoc git python3-pip ninja-build
1010
apt remove -y meson
1111
pip3 install --upgrade meson
1212
;;
@@ -16,15 +16,15 @@ debian:*|ubuntu:*)
1616
apt clean
1717
apt update
1818
apt -y install gcc meson pkg-config libjose-dev jose libhttp-parser-dev \
19-
systemd gcovr curl socat iproute2 asciidoc git
19+
systemd gcovr curl socat iproute2 asciidoc git podman
2020
;;
2121

2222
*fedora:*)
2323
echo 'max_parallel_downloads=10' >> /etc/dnf/dnf.conf
2424
dnf -y clean all
2525
dnf -y --setopt=deltarpm=0 update
2626
dnf -y install gcc meson pkgconfig libjose-devel jose llhttp-devel \
27-
systemd gcovr curl socat iproute asciidoc git
27+
systemd gcovr curl socat iproute asciidoc git podman
2828
;;
2929

3030
centos:7)
@@ -33,7 +33,7 @@ centos:7)
3333
yum install -y yum-utils epel-release
3434
yum config-manager -y --set-enabled PowerTools \
3535
|| yum config-manager -y --set-enabled powertools || :
36-
yum -y install meson socat iproute asciidoc git
36+
yum -y install meson socat iproute asciidoc git podman
3737
yum-builddep -y tang
3838
;;
3939

@@ -43,7 +43,7 @@ centos:7)
4343
dnf install -y dnf-plugins-core epel-release
4444
dnf config-manager -y --set-enabled powertools \
4545
|| dnf config-manager -y --set-enabled crb || :
46-
dnf -y install meson socat iproute git
46+
dnf -y install meson socat iproute git podman
4747
dnf builddep -y tang --allowerasing --skip-broken --nobest
4848
;;
4949
esac

Containerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM quay.io/fedora/fedora:latest AS build
2+
RUN dnf -y --setopt=deltarpm=0 update && \
3+
dnf -y install gcc pkgconfig meson libjose-devel jose llhttp-devel
4+
RUN mkdir -p /build/in /build/out
5+
COPY . /build/in/
6+
WORKDIR /build/out
7+
RUN meson setup ../in && ninja-build
8+
9+
FROM quay.io/fedora/fedora:latest AS runtime
10+
RUN dnf -y install jose llhttp
11+
COPY src/tang-show-keys /bin/
12+
COPY --from=build /build/out/src/tangd /build/out/src/tangd-rotate-keys /build/out/src/tangd-keygen /bin/
13+
14+
VOLUME [ "/jwkdir" ]
15+
EXPOSE 9090
16+
17+
CMD [ "/bin/tangd", "-l", "-p", "9090", "/jwkdir" ]

README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,22 @@ and start the server:
124124
# service tangd enable
125125
# service tangd start
126126

127-
#### Docker Container
127+
#### Docker/Podman Container
128128

129-
Tang is also available as a [Docker
130-
Container](https://gitlab.com/AdrianKoshka/tang-docker-container/).
129+
Tang can also be built as a Docker or Podman image using the included
130+
Containerfile.
131131

132-
Care should be taken to ensure that, when deploying in a container cluster,
133-
that the Tang keys are not stored on the same physical medium that you wish to
134-
protect.
132+
When deploying in a container cluster, care should be taken to ensure that the
133+
Tang keys are not stored on the same physical medium that you wish to protect.
134+
135+
By default, this container starts in listen mode on port 9090 of all addresses
136+
within the container, with the key directory set to the container's `/jwkdir`.
137+
This path should be bound to a key storage location on the container host.
138+
139+
Note that socket activation is **not supported** for Tang Podman containers, as
140+
Tang uses inetd-style socket activation (`Accept=yes`) rather than systemd-style
141+
socket activation (`Accept=no`), and Podman quadlets do not support inetd-style
142+
socket activation due to containers/podman#22874 (among other reasons).
135143

136144
### Building and Installing from Source
137145

tests/adv

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ adv_second_phase () {
7575
test "$(tang-show-keys $PORT $ENDPOINT)" = "$(jose jwk thp -a "${THP_DEFAULT_HASH}" -i $TMP/db/sig.jwk)"
7676

7777
# Check that new keys will be created if none exist.
78-
rm -rf "${TMP}/db" && mkdir -p "${TMP}/db"
78+
# Use find to delete the contents here because deleting the directory
79+
# breaks the container-volume link in Podman tests, which is a problem.
80+
find "${TMP}/db" -mindepth 1 -depth -delete
7981
fetch "${ENDPOINT}"/adv
8082

8183
# Now let's make sure the new keys were named using our default thumbprint

tests/adv-podman

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/sh -ex
2+
# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3+
#
4+
# Copyright (c) 2026 Marissa Lyndon <mari@reya.zone>
5+
#
6+
# This program is free software: you can redistribute it and/or modify
7+
# it under the terms of the GNU General Public License as published by
8+
# the Free Software Foundation, either version 3 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# This program is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
#
19+
20+
. adv
21+
22+
sanity_check_podman
23+
24+
adv_startup
25+
26+
export PORT=$(random_port)
27+
export CONTAINER=$(start_podman_server "${PORT}")
28+
wait_for_port "${PORT}"
29+
30+
adv_second_phase

tests/adv-podman-endpoint

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/sh -ex
2+
#
3+
# Copyright (c) 2026 Marissa Lyndon <mari@reya.zone>
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
#
18+
19+
. adv
20+
21+
sanity_check_podman
22+
23+
adv_startup
24+
25+
export PORT=$(random_port)
26+
export ENDPOINT="/api/dee-hms"
27+
export CONTAINER=$(start_podman_server_endpoint "${PORT}" "${ENDPOINT}")
28+
wait_for_port "${PORT}"
29+
30+
adv_second_phase

tests/adv-socat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
. adv
2222

23-
sanity_check
23+
sanity_check_socat
2424

2525
adv_startup
2626

tests/adv-socat-endpoint

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
. adv
2121

22-
sanity_check
22+
sanity_check_socat
2323

2424
adv_startup
2525

tests/helpers

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,22 @@ start_standalone_server_endpoint() {
8383
${VALGRIND} tangd -p ${1} -l ${TMP}/db -e ${2} &
8484
}
8585

86+
start_podman_server() {
87+
"${PODMAN}" run -d -p "${1}":9090 -v "${TMP}"/db:/jwkdir localhost/tangd
88+
}
89+
90+
start_podman_server_endpoint() {
91+
"${PODMAN}" run -d -p "${1}":9090 -v "${TMP}"/db:/jwkdir localhost/tangd /bin/tangd -p 9090 -l -e "${2}" /jwkdir
92+
}
93+
8694
on_exit() {
8795
if [ "${PID}" ]; then
8896
kill "${PID}" || true
8997
wait "${PID}" || true
9098
fi
99+
if [ -n "${PODMAN}" ] && [ -n "${CONTAINER}" ]; then
100+
"${PODMAN}" stop --time 1 "${CONTAINER}"
101+
fi
91102
[ -d "${TMP}" ] && rm -rf "${TMP}"
92103
}
93104

@@ -114,11 +125,18 @@ validate_exc() {
114125
--use deriveKey 2>/dev/null
115126
}
116127

117-
sanity_check() {
128+
sanity_check_socat() {
118129
# Skip test if socat is not available.
119130
[ -n "${SOCAT}" ] || exit 77
120131
}
121132

133+
sanity_check_podman() {
134+
# Skip test if podman is not available or the image does not exist.
135+
if [ -z "${PODMAN}" ] || ! podman image exists localhost/tangd; then
136+
exit 77
137+
fi
138+
}
139+
122140
die() {
123141
echo "${1}" >&2
124142
exit 1

0 commit comments

Comments
 (0)