Skip to content

jumanjihouse/docker-hooktftp

Repository files navigation

hooktftp in a container

This source is used to build an image for hooktftp.

Project URL: https://github.com/jumanjihouse/docker-hooktftp
Registry: https://registry.hub.docker.com/u/jumanjiman/hooktftp/

    Docker Registry  Circle CI

The primary artifact is a docker image with the hooktftp binary and a default, minimal configuration.
The runtime image contains only:

  • a static binary,
  • a default config file,
  • /etc/nsswitch.conf so golang net resolver uses /etc/hosts,
  • CA certificates, and
  • /etc/passwd to provide an unprivileged user.

The container runs as an unprivileged user via the technique described in this Medium post.

The goal is to provide a compromise between a single, monolithic tftpd image that contains all the things and a flexible tftpd image that contains just enough to combine with custom-built data containers or volumes an organization needs to bootstrap their infrastructure.

Table of Contents

Build integrity and docker tags

An unattended test harness runs the build script and acceptance tests. If all tests pass on master branch in the unattended test harness, circleci pushes the built image to the Docker hub.

The CI scripts apply two tags before pushing to docker hub:

  • jumanjiman/hooktftp:latest: latest successful build on master branch
  • jumanjiman/hooktftp:<date>T<time>-<git-hash>: a particular build on master branch

Therefore you can docker pull a specific tag if you don't want latest.

How-to

Fetch an already-built image

The runtime image is published as jumanjiman/hooktftp.

docker pull jumanjiman/hooktftp

View image labels

Each built image has labels that generally follow http://label-schema.org/

We add a label, ci-build-url, that is not currently part of the schema. This extra label provides a permanent link to the CI build for the image.

View the ci-build-url label on a built image:

docker inspect \
  -f '{{ index .Config.Labels "io.github.jumanjiman.ci-build-url" }}' \
  jumanjiman/hooktftp

Query all the labels inside a built image:

docker inspect jumanjiman/hooktftp | jq -M '.[].Config.Labels'

List files in the image

The image contains the typical syslinux, efi, and pxelinux files from syslinux at /tftpboot/. However, the image is built from scratch, so the image does not have typical shell utilities. List the files with:

ci/build
docker-compose run --rm list_files_in_tftpboot

Load NetFilter modules

Add helpers to track connections:

sudo modprobe nf_conntrack_tftp
sudo modprobe nf_nat_tftp

Configure and run

The container reads the config file /etc/hooktftp/hooktftp.yml inside the container. You can use the default config provided inside the image or provide your own at runtime.

The published image contains just enough files to provide a base tftpd to PXE-boot your hosts to a simple menu. The simple menu and pxelinux.cfg/default only allow to skip PXE. Therefore you probably want to override the built-in menu.

Run a container with your own pxelinux.cfg files:

docker run -d -p 69:69/udp \
  -v /path/to/your/pxelinux.cfg:/tftpboot/pxelinux.cfg:ro \
  jumanjiman/hooktftp

Run a container with default config and your data:

docker run -d -p 69:69/udp \
  -v /path/to/your/files:/tftpboot:ro \
  jumanjiman/hooktftp

Run a container with your own config and your own data:

docker run -d -p 69:69/udp \
  -v /path/to/your/files:/tftpboot:ro \
  -v /path/to/your/config/dir:/etc/hooktftp:ro \
  jumanjiman/hooktftp

Use multiple volumes to add site-local boot files and menus in addition to the built-in syslinux files:

docker run -d -p 69:69/udp \
  -v /path/to/your/pxelinux.cfg:/tftpboot/pxelinux.cfg:ro \
  -v /path/to/your/bootfiles:/tftpboot/site:ro \
  jumanjiman/hooktftp

You can add entries to /etc/hosts via docker run --add-host or via the docker-compose extra_hosts option.

docker run -d -p 69:69/udp \
  -v /path/to/your/pxelinux.cfg:/tftpboot/pxelinux.cfg:ro \
  -v /path/to/your/bootfiles:/tftpboot/site:ro \
  --add-host some-host.example.com:10.0.0.1 \
  jumanjiman/hooktftp

Use systemd for automatic startup

Review and potentially modify the sample systemd unit file at systemd/hooktftp.service, then run:

sudo cp systemd/hooktftp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl start hooktftp
sudo systemctl enable hooktftp

Build

The build script(s) produce multiple artifacts:

Image Tag Size Purpose
hooktftp-runtime 8 MB run hooktftp as a service
tftp 6 MB test the runtime container

On a docker host, run:

ci/build

Test

⚠️ We use BATS for the test harness.

On a docker host, run:

ci/test

You can also test via the docker remote API if you have configured a remote docker host:

export DOCKER_HOST=tcp://<remote_ip>:<port>
ci/build
ci/test

Output from ci/test resembles:

===> Run file checks.
[forbid-binary] Forbid binaries..........................................(no files to check)Skipped
[git-check] Check for conflict markers and core.whitespace errors............................Passed
[git-dirty] Check if the git tree is dirty...................................................Passed
[shellcheck] Test shell scripts with shellcheck..............................................Passed
[yamllint] yamllint..........................................................................Passed
[check-added-large-files] Check for added large files........................................Passed
[check-case-conflict] Check for case conflicts...............................................Passed
[check-executables-have-shebangs] Check that executables have shebangs.......................Passed
[check-json] Check JSON..................................................(no files to check)Skipped
[check-merge-conflict] Check for merge conflicts.............................................Passed
[check-xml] Check Xml....................................................(no files to check)Skipped
[check-yaml] Check Yaml......................................................................Passed
[detect-private-key] Detect Private Key......................................................Passed
[forbid-crlf] CRLF end-lines checker.........................................................Passed
[forbid-tabs] No-tabs checker................................................................Passed

===> Clean up from previous test runs.
[RUN] docker_rm tftp
[RUN] docker_rm tftpd
[RUN] docker_rm downloads
[RUN] docker_rm fixtures

===> Create data container in which to download test files.
[RUN] docker create --name downloads -v /home/user base_image true
19d787a81fa8cc3d68fdd97f0d7fa85d2d3f95fadcd144e52f47aafda74fb763
[RUN] docker run --rm --volumes-from downloads base_image chown -R 1000:1000 /home/user

===> Create data container for fixtures.
[RUN] docker create --name fixtures hooktftp-fixtures true
35887d1b1761350b9dda5dac398822d91d9e7375cd29ef2b88feb3e7b97d7d41

===> Start hooktftp server.
[RUN] docker run -d -p 69:69/udp --volumes-from fixtures --name tftpd hooktftp-runtime
28cd162ee8edbe314354ec09d5bbd65bb40350d977d41d9544f6d1482a98f144
Server is up at 172.17.0.3

===> Run BATS tests.
1..11
ok 1 hooktftp drops privileges
ok 2 downloads site/menu from fixtures
ok 3 downloads pxelinux.0
ok 4 does not download a non-existent-file
ok 5 downloads pxelinux.cfg/default
ok 6 downloads pxelinux.cfg/F1.msg
ok 7 hooktftp server log is meaningful
ok 8 file command is available
ok 9 scanelf command is available
ok 10 hooktftp binary is stripped
ok 11 hooktftp binary is statically compiled
ci/test OK

Publish to a private registry

You can push the built image to a private docker registry:

docker tag hooktftp-runtime registry_id/your_id/hooktftp
docker push registry_id/your_id/hooktftp

Contribute

See CONTRIBUTING.md in this repo.

License

See LICENSE in this repo.

About

Build, test, and deploy a container to run the hooktftp server

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published