diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ee67e27..31f466c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: test: # The type of runner that the job will run on - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -31,8 +31,6 @@ jobs: - name: Start apt proxy run: | - # Hiding the read-only token base64 to avoid github disabling it... - echo OWMyMGVhYzk4N2NhYWQxYmI3MzhmNTZkODNmOGMwOGJjZjlhNDc4YQo= | base64 -d | docker login ghcr.io -u dubo-dubon-duponey --password-stdin docker run --rm -d --expose 443 --expose 80 --pull always \ --name apt-front \ --read-only \ @@ -47,12 +45,13 @@ jobs: --env ADDITIONAL_DOMAINS=*.debian.org \ --volume "$GITHUB_WORKSPACE/cache/certs":/certs \ --volume "$GITHUB_WORKSPACE/cache/apt":/data \ - ghcr.io/dubo-dubon-duponey/aptutil:bullseye-2021-08-01 + docker.io/dubodubonduponey/aptutil:bullseye-2021-08-01 - name: test run: | # Set the path and install the tools - BIN_LOCATION="$GITHUB_WORKSPACE/cache/bin" source ./hack/helpers/install-tools.sh + export PATH="$GITHUB_WORKSPACE/cache/bin:$PATH" + ./hack/helpers/install-tools.sh # Start buildkit bkaddr="$(./hack/helpers/start-buildkit.sh 2>/dev/null)" # Sanity check diff --git a/.gitignore b/.gitignore index 10b083a..507266e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /.idea */cache/* cache +*trace.json +xxx-* diff --git a/DEVELOP.md b/DEVELOP.md index a9b5344..73dfe5a 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -10,11 +10,11 @@ ### The what -This image is built using: `ghcr.io/dubo-dubon-duponey/base:builder-bullseye-2021-09-01` +This image is built using: `docker.io/dubodubonduponey/base:builder-bullseye-2022-12-01` -The runtime part is based on: `ghcr.io/dubo-dubon-duponey/base:runtime-bullseye-2021-09-01` +The runtime part is based on: `docker.io/dubodubonduponey/base:runtime-bullseye-2022-12-01` -Both these images are built upon: `ghcr.io/dubo-dubon-duponey/debian:bullseye-2021-09-01` +Both these images are built upon: `docker.io/dubodubonduponey/debian:bullseye-2022-12-01` You can find out more here: diff --git a/Dockerfile b/Dockerfile index 819d6f3..8612f6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -ARG FROM_REGISTRY=ghcr.io/dubo-dubon-duponey +ARG FROM_REGISTRY=docker.io/dubodubonduponey -ARG FROM_IMAGE_BUILDER=base:builder-bullseye-2021-09-01@sha256:12be2a6d0a64b59b1fc44f9b420761ad92efe8188177171163b15148b312481a -ARG FROM_IMAGE_AUDITOR=base:auditor-bullseye-2021-09-01@sha256:28d5eddcbbee12bc671733793c8ea8302d7d79eb8ab9ba0581deeacabd307cf5 -ARG FROM_IMAGE_RUNTIME=base:runtime-bullseye-2021-09-01@sha256:bbd3439247ea1aa91b048e77c8b546369138f910b5083de697f0d36ac21c1a8c -ARG FROM_IMAGE_TOOLS=tools:linux-bullseye-2021-09-01@sha256:e5535efb771ca60d2a371cd2ca2eb1a7d6b7b13cc5c4d27d48613df1a041431d +ARG FROM_IMAGE_BUILDER=base:builder-bookworm-2023-09-05 +ARG FROM_IMAGE_AUDITOR=base:auditor-bookworm-2023-09-05 +ARG FROM_IMAGE_RUNTIME=base:runtime-bookworm-2023-09-05 +ARG FROM_IMAGE_TOOLS=tools:linux-bookworm-2023-09-05 FROM $FROM_REGISTRY/$FROM_IMAGE_TOOLS AS builder-tools @@ -13,15 +13,15 @@ FROM $FROM_REGISTRY/$FROM_IMAGE_TOOLS FROM --platform=$BUILDPLATFORM $FROM_REGISTRY/$FROM_IMAGE_BUILDER AS fetcher-lego ARG GIT_REPO=github.com/go-acme/lego -ARG GIT_VERSION=v4.4.0 -ARG GIT_COMMIT=7c24212e8a1df8547ca6edb6cf630cff60e62f46 +ARG GIT_VERSION=v4.15.0 +ARG GIT_COMMIT=46fe435c2c2e447ae48df712eca8278bbca8986e ENV WITH_BUILD_SOURCE="./cmd/lego" ENV WITH_BUILD_OUTPUT="lego" ENV CGO_ENABLED=1 -RUN git clone --recurse-submodules git://"$GIT_REPO" .; git checkout "$GIT_COMMIT" +RUN git clone --recurse-submodules https://"$GIT_REPO" .; git checkout "$GIT_COMMIT" RUN --mount=type=secret,id=CA \ --mount=type=secret,id=NETRC \ [[ "${GOFLAGS:-}" == *-mod=vendor* ]] || go mod download @@ -40,9 +40,6 @@ ENV GOARCH=$TARGETARCH ENV CGO_CFLAGS="${CFLAGS:-} ${ENABLE_PIE:+-fPIE}" ENV GOFLAGS="-trimpath ${ENABLE_PIE:+-buildmode=pie} ${GOFLAGS:-}" -# Important cases being handled: -# - cannot compile statically with PIE but on amd64 and arm64 -# - cannot compile fully statically with NETCGO RUN export GOARM="$(printf "%s" "$TARGETVARIANT" | tr -d v)"; \ [ "${CGO_ENABLED:-}" != 1 ] || { \ eval "$(dpkg-architecture -A "$(echo "$TARGETARCH$TARGETVARIANT" | sed -e "s/^armv6$/armel/" -e "s/^armv7$/armhf/" -e "s/^ppc64le$/ppc64el/" -e "s/^386$/i386/")")"; \ @@ -68,8 +65,8 @@ RUN export GOARM="$(printf "%s" "$TARGETVARIANT" | tr -d v)"; \ FROM --platform=$BUILDPLATFORM $FROM_REGISTRY/$FROM_IMAGE_BUILDER AS fetcher-coredns ARG GIT_REPO=github.com/coredns/coredns -ARG GIT_VERSION=v1.8.4 -ARG GIT_COMMIT=053c4d5ca1772517746a854e87ffa971249df14b +ARG GIT_VERSION=v1.11.1 +ARG GIT_COMMIT=ae2bbc29be1aaae0b3ded5d188968a6c97bb3144 ENV WITH_BUILD_SOURCE=./coredns.go ENV WITH_BUILD_OUTPUT=coredns @@ -77,14 +74,15 @@ ENV WITH_LDFLAGS="-X $GIT_REPO/coremain.GitCommit=$GIT_COMMIT" ENV CGO_ENABLED=1 -RUN git clone --recurse-submodules git://"$GIT_REPO" .; git checkout "$GIT_COMMIT" +RUN git clone --recurse-submodules https://"$GIT_REPO" .; git checkout "$GIT_COMMIT" RUN --mount=type=secret,id=CA \ --mount=type=secret,id=NETRC \ [[ "${GOFLAGS:-}" == *-mod=vendor* ]] || go mod download; \ printf "mdns:github.com/openshift/coredns-mdns\n" >> plugin.cfg; \ printf "unbound:github.com/coredns/unbound\n" >> plugin.cfg; \ go generate coredns.go; \ - go mod tidy + go mod tidy -compat=1.17 + # XXX how to pin that? # hadolint ignore=DL3009 @@ -96,11 +94,11 @@ RUN --mount=type=secret,uid=100,id=CA \ --mount=type=secret,id=APT_SOURCES \ --mount=type=secret,id=APT_CONFIG \ apt-get update -qq; \ - for architecture in armel armhf arm64 ppc64el i386 s390x amd64; do \ + for architecture in arm64 amd64; do \ apt-get install -qq --no-install-recommends \ - libunbound-dev:"$architecture"=1.13.1-1 \ - nettle-dev:"$architecture"=3.7.3-1 \ - libevent-dev:"$architecture"=2.1.12-stable-1; \ + libunbound-dev:"$architecture"=1.17.1-2 \ + nettle-dev:"$architecture"=3.8.1-2 \ + libevent-dev:"$architecture"=2.1.12-stable-8; \ done ########################## @@ -117,9 +115,6 @@ ENV GOARCH=$TARGETARCH ENV CGO_CFLAGS="${CFLAGS:-} ${ENABLE_PIE:+-fPIE}" ENV GOFLAGS="-trimpath ${ENABLE_PIE:+-buildmode=pie} ${GOFLAGS:-}" -# Important cases being handled: -# - cannot compile statically with PIE but on amd64 and arm64 -# - cannot compile fully statically with NETCGO RUN export GOARM="$(printf "%s" "$TARGETVARIANT" | tr -d v)"; \ [ "${CGO_ENABLED:-}" != 1 ] || { \ eval "$(dpkg-architecture -A "$(echo "$TARGETARCH$TARGETVARIANT" | sed -e "s/^armv6$/armel/" -e "s/^armv7$/armhf/" -e "s/^ppc64le$/ppc64el/" -e "s/^386$/i386/")")"; \ @@ -142,10 +137,15 @@ RUN export GOARM="$(printf "%s" "$TARGETVARIANT" | tr -d v)"; \ RUN mkdir -p /dist/boot/lib; \ eval "$(dpkg-architecture -A "$(echo "$TARGETARCH$TARGETVARIANT" | sed -e "s/^armv6$/armel/" -e "s/^armv7$/armhf/" -e "s/^ppc64le$/ppc64el/" -e "s/^386$/i386/")")"; \ cp /usr/lib/"$DEB_TARGET_MULTIARCH"/libunbound.so.8 /dist/boot/lib; \ - cp /lib/"$DEB_TARGET_MULTIARCH"/libpthread.so.0 /dist/boot/lib; \ - cp /lib/"$DEB_TARGET_MULTIARCH"/libc.so.6 /dist/boot/lib; \ cp /usr/lib/"$DEB_TARGET_MULTIARCH"/libevent-2.1.so.7 /dist/boot/lib + +# XXX whether or not we want these in depends on how slick we want the future runtime +# cp /lib/"$DEB_TARGET_MULTIARCH"/libpthread.so.0 /dist/boot/lib; \ +# cp /lib/"$DEB_TARGET_MULTIARCH"/libc.so.6 /dist/boot/lib; \ + + + # go get github.com/coredns/unbound; \ ####################### @@ -158,6 +158,22 @@ COPY --from=builder-coredns /dist /dist COPY --from=builder-tools /boot/bin/dns-health /dist/boot/bin +RUN cp /dist/boot/bin/coredns /dist/boot/bin/coredns_no_cap +RUN cp /dist/boot/bin/coredns /dist/boot/bin/coredns_cap+origin +RUN setcap 'cap_net_bind_service+ep' /dist/boot/bin/coredns_cap+origin +# hadolint ignore=SC2016 +RUN patchelf --set-rpath '$ORIGIN/../lib' /dist/boot/bin/coredns_cap+origin +# hadolint ignore=SC2016 +RUN patchelf --set-rpath '$ORIGIN/../lib' /dist/boot/bin/coredns_no_cap + +# XXX https://mail.openjdk.java.net/pipermail/distro-pkg-dev/2010-May/009112.html +# no $ORIGIN rpath expansion with caps +RUN patchelf --set-rpath '/boot/lib' /dist/boot/bin/coredns +RUN patchelf --set-rpath '/boot/lib' /dist/boot/lib/* +RUN patchelf --set-rpath '/boot/lib' /dist/boot/bin/lego + +RUN setcap 'cap_net_bind_service+ep' /dist/boot/bin/coredns + RUN chmod 555 /dist/boot/bin/*; \ epoch="$(date --date "$BUILD_CREATED" +%s)"; \ find /dist/boot -newermt "@$epoch" -exec touch --no-dereference --date="@$epoch" '{}' +; @@ -170,32 +186,37 @@ FROM $FROM_REGISTRY/$FROM_IMAGE_RUNTIME # Get relevant bits from builder COPY --from=builder --chown=$BUILD_UID:root /dist / -ENV DOMAIN="" -ENV EMAIL="dubo-dubon-duponey@farcloser.world" -ENV UPSTREAM_SERVER_1="" -ENV UPSTREAM_SERVER_2="" -ENV UPSTREAM_NAME="" -ENV STAGING="" - -ENV DNS_PORT=1053 -ENV TLS_PORT=1853 -ENV HTTPS_PORT=1443 -ENV GRPC_PORT=5553 +ENV DNS_OVER_TLS_ENABLED=false +ENV DNS_OVER_TLS_DOMAIN="" +ENV DNS_OVER_TLS_PORT=853 +ENV DNS_OVER_TLS_LEGO_PORT=443 +ENV DNS_OVER_TLS_LEGO_EMAIL="dubo-dubon-duponey@farcloser.world" +ENV DNS_OVER_TLS_LE_USE_STAGING=false + +ENV DNS_FORWARD_ENABLED=true +ENV DNS_FORWARD_UPSTREAM_NAME="cloudflare-dns.com" +ENV DNS_FORWARD_UPSTREAM_IP_1="tls://1.1.1.1" +ENV DNS_FORWARD_UPSTREAM_IP_2="tls://1.0.0.1" + +ENV DNS_PORT=53 +ENV DNS_OVER_GRPC_PORT=553 +ENV DNS_STUFF_MDNS=false + ENV METRICS_PORT=9253 # NOTE: this will not be updated at runtime and will always EXPOSE default values # Either way, EXPOSE does not do anything, except function as a documentation helper EXPOSE $DNS_PORT/udp -EXPOSE $TLS_PORT/tcp -EXPOSE $HTTPS_PORT/tcp -EXPOSE $GRPC_PORT/tcp +EXPOSE $DNS_OVER_TLS_PORT/tcp +EXPOSE $DNS_OVER_TLS_LEGO_PORT/tcp +EXPOSE $DNS_OVER_GRPC_PORT/tcp EXPOSE $METRICS_PORT/tcp # Lego just needs /certs to work VOLUME /certs ENV HEALTHCHECK_URL="127.0.0.1:$DNS_PORT" -ENV HEALTHCHECK_QUESTION=healthcheck-dns.farcloser.world +ENV HEALTHCHECK_QUESTION=dns.autonomous.healthcheck.farcloser.world ENV HEALTHCHECK_TYPE=udp HEALTHCHECK --interval=120s --timeout=30s --start-period=10s --retries=1 CMD dns-health || exit 1 diff --git a/README.md b/README.md index 9998f08..d5547f2 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,34 @@ # What -Docker image for CoreDNS, with sample configuration for various "DNS over TLS" scenarios. +Easy to use CoreDNS container with reasonable defaults. This is based on [CoreDNS](https://coredns.io/), and [Let's Encrypt](https://letsencrypt.org/) (via [Lego](https://github.com/go-acme/lego)). This is useful in the following scenarios: - 1. you want to encrypt all your laptop DNS traffic (forwarded to Cloudflare, Quad9, Google, or any other DoT public resolver) - 1. you want to run your own DNS/DoT recursive service - 1. anything else you can do with CoreDNS +1. you want to run a *local* DNS server on your LAN (or your laptop) that will forward requests with encryption to an upstream resolver + ( like Cloudflare, Quad9, Google, or any other DoT public resolver) +1. you want to run your own DNS over TLS (recursive) service +1. other stuff + +Before running this publicly on the internet, you should think twice though, and make sure you understand the implications. ## Image features -* multi-architecture: +* multi-architecture (publishing): * [x] linux/amd64 - * [x] linux/386 * [x] linux/arm64 + +* multi-architecture (not publishing anymore) + * [x] linux/386 * [x] linux/arm/v7 * [x] linux/arm/v6 * [x] linux/ppc64le * [x] linux/s390x +* * hardened: * [x] image runs read-only - * [x] image runs with no capabilities (unless you want it on a privileged port) + * [x] image runs with no capabilities but NET_BIND_SERVICE, which you could remove if you use unprivileged ports * [x] process runs as a non-root user, disabled login, no shell * lightweight * [x] based on our slim [Debian Bullseye](https://github.com/dubo-dubon-duponey/docker-debian) @@ -35,8 +41,7 @@ This is useful in the following scenarios: ## Run -You can run either a forwarding server (that will send requests to an upstream), or a recursive one -(only available on AMD64 in the provided image - or ARM64 if you rebuild the image on an ARM64 node). +You can run either a forwarding server (that will send requests to an upstream), or a recursive one. Then you can either expose a traditional DNS server, a TLS server, or both. @@ -48,14 +53,15 @@ Examples: ```bash docker run -d \ - --env "UPSTREAM_NAME=cloudflare-dns.com" - --env "UPSTREAM_SERVER_1=tls://1.1.1.1" - --env "UPSTREAM_SERVER_2=tls://1.0.0.1" + --env "DNS_FORWARD_UPSTREAM_NAME=cloudflare-dns.com" \ + --env "DNS_FORWARD_UPSTREAM_IP_1=tls://1.1.1.1" \ + --env "DNS_FORWARD_UPSTREAM_IP_2=tls://1.0.0.1" \ --net bridge \ - --publish 53:1053/udp \ + --publish 53:53/udp \ --cap-drop ALL \ + --cap-add NET_BIND_SERVICE \ --read-only \ - ghcr.io/dubo-dubon-duponey/dns + docker.io/dubodubonduponey/dns ``` ### TLS server, forwarding @@ -64,42 +70,49 @@ docker run -d \ ```bash docker run -d \ - --env "DOMAIN=dev-null.farcloser.world" - --env "EMAIL=dubo-dubon-duponey@farcloser.world" - --env "UPSTREAM_NAME=cloudflare-dns.com" - --env "UPSTREAM_SERVER_1=tls://1.1.1.1" - --env "UPSTREAM_SERVER_2=tls://1.0.0.1" + --env "DNS_FORWARD_UPSTREAM_NAME=cloudflare-dns.com" \ + --env "DNS_FORWARD_UPSTREAM_IP_1=tls://1.1.1.1" \ + --env "DNS_FORWARD_UPSTREAM_IP_2=tls://1.0.0.1" \ + --env "DNS_OVER_TLS_ENABLED=true" \ + --env "DNS_OVER_TLS_DOMAIN=dev-null.farcloser.world" \ + --env "DNS_OVER_TLS_LEGO_EMAIL=dubo-dubon-duponey@farcloser.world" \ --net bridge \ - --publish 443:1443/tcp \ - --publish 853:1853/tcp \ + --publish 443:443/tcp \ + --publish 853:853/tcp \ --cap-drop ALL \ + --cap-add NET_BIND_SERVICE \ --read-only \ - ghcr.io/dubo-dubon-duponey/dns + docker.io/dubodubonduponey/dns ``` -### Traditional DNS server, recursive +### Recursive DNS server ```bash docker run -d \ + --env "DNS_FORWARD_ENABLED=false" \ --net bridge \ - --publish 53:1053/udp \ + --publish 53:53/udp \ --cap-drop ALL \ + --cap-add NET_BIND_SERVICE \ --read-only \ - ghcr.io/dubo-dubon-duponey/dns + docker.io/dubodubonduponey/dns ``` ### TLS server, recursive ```bash docker run -d \ - --env "DOMAIN=dev-null.farcloser.world" - --env "EMAIL=dubo-dubon-duponey@farcloser.world" + --env "DNS_FORWARD_ENABLED=false" \ + --env "DNS_OVER_TLS_ENABLED=true" \ + --env "DNS_OVER_TLS_DOMAIN=dev-null.farcloser.world" \ + --env "DNS_OVER_TLS_LEGO_EMAIL=dubo-dubon-duponey@farcloser.world" --net bridge \ - --publish 443:1443/tcp \ - --publish 853:1853/tcp \ + --publish 443:443/tcp \ + --publish 853:853/tcp \ --cap-drop ALL \ + --cap-add NET_BIND_SERVICE \ --read-only \ - ghcr.io/dubo-dubon-duponey/dns + docker.io/dubodubonduponey/dns ``` For TLS, you do need to expose port 443 publicly from your docker host so that LetsEncrypt can issue your certificate, @@ -113,77 +126,59 @@ If you want to customize your CoreDNS config, mount a volume into `/config` on t (and customize one of the files to your needs). ```bash -chown -R 1000:nogroup "[host_path_for_config]" +chown -R 2000:nogroup "[host_path_for_config]" docker run -d \ --volume [host_path_for_config]:/config:ro \ - --net bridge \ - --publish 53:1053/udp \ - --publish 443:1443/tcp \ - --publish 853:1853/tcp \ - --cap-drop ALL \ - --read-only \ - ghcr.io/dubo-dubon-duponey/dns + ... ``` ### Networking -If you want to use another networking mode but `bridge` (and run the service on privileged ports), you have to run the container as `root`, grant the appropriate `cap` and set the ports: +You can control the various ports used by the service if you wish to: ```bash docker run -d \ - --env DOMAIN=something.mydomain.com \ - --env EMAIL=me@mydomain.com \ - --net host \ --env DNS_PORT=53 \ - --env TLS_PORT=853 \ - --env HTTPS_PORT=443 \ - --cap-add CAP_NET_BIND_SERVICE \ - --user root \ - --cap-drop ALL \ - --read-only \ - ghcr.io/dubo-dubon-duponey/dns + --env DNS_OVER_TLS_PORT=853 \ + --env DNS_OVER_TLS_LEGO_PORT=443 \ + ... ``` ### Configuration reference The default setup use CoreDNS config files in `/config` that sets-up different scenarios based on the value of environment variables. -The `/certs` folder is used to store LetsEncrypt certificates (it's a volume by default, which you may want to mount), in case you configure a TLS server (through using the DOMAIN variable). +The `/certs` folder is used to store LetsEncrypt certificates (it's a volume by default, which you may want to mount), in case you configure a DNS-over-TLS server. #### Runtime You may specify the following environment variables at runtime: - * DOMAIN (eg: `something.mydomain.com`) controls the domain name of your server if you want a TLS server - * EMAIL (eg: `me@mydomain.com`) controls the email used to issue your server certificate - * STAGING controls whether you want to use LetsEncrypt staging environment (useful when debugging so not to burn your quota) - * UPSTREAM_NAME (eg: `cloudflare-dns.com`) controls the server name of the (TLS) upstream if you want a forwarding server - * UPSTREAM_SERVER_1 and UPSTREAM_SERVER_2 (eg: `tls://1.1.1.1`) controls the upstream forward addresses +For DoT: + * DNS_OVER_TLS_ENABLED: enable the DoT service + * DNS_OVER_TLS_DOMAIN (eg: `something.mydomain.com`) controls the domain name of your server + * DNS_OVER_TLS_LEGO_PORT: port that lego will use to listen on for LetsEncrypt response + * DNS_OVER_TLS_LEGO_EMAIL (eg: `me@mydomain.com`) controls the email used to issue your server certificate + * DNS_OVER_TLS_LE_USE_STAGING controls whether you want to use LetsEncrypt staging environment (useful when debugging so not to burn your quota) -You can also tweak the following for control over which internal ports are being used (useful if intend to run with host/macvlan, see above) +For forwarding: + * DNS_FORWARD_ENABLED: enable (default) or disable forwarding mode + * DNS_FORWARD_UPSTREAM_NAME: if you forward to a DoT server, the domain name of that service + * DNS_FORWARD_UPSTREAM_IP_1: the ip of the upstream + * DNS_FORWARD_UPSTREAM_IP_2: the backup ip of the upstream - * DNS_PORT (default to 1053) - * HTTPS_PORT (default to 1443) - * TLS_PORT (default to 1853) - * GRPC_PORT (default to 5553) - * METRICS_PORT (default to 9253) +You can also tweak the following: -Of course using any privileged port for these requires CAP_NET_BIND_SERVICE and a root user. + * DNS_PORT (default to 53) + * DNS_OVER_GRPC_PORT (default to 553) + * DNS_STUFF_MDNS: convenient little trick to respond for certain mDNS queries over traditional DNS + * METRICS_PORT for Prometheuse (default to 9253) -Note that these environment variables are used solely in the default configuration files. -If you are rolling your own, it's up to you to use them or not. +Of course using any privileged port for these requires CAP_NET_BIND_SERVICE. Finally, any additional arguments provided when running the image will get fed to the `coredns` binary. -### Unbound and recursive server - -Unbound support requires CGO, which requires the target platform to be the same as the build platform. - -Our images are built on linux/amd64. - -If you want to run on arm64, you have to rebuild it yourself on an arm64 node. - ### Prometheus The default configuration files expose a Prometheus metrics endpoint on port 9253. diff --git a/context/runtime/boot/entrypoint.sh b/context/runtime/boot/entrypoint.sh index dafb371..b5e3f1f 100755 --- a/context/runtime/boot/entrypoint.sh +++ b/context/runtime/boot/entrypoint.sh @@ -1,60 +1,86 @@ #!/usr/bin/env bash set -o errexit -o errtrace -o functrace -o nounset -o pipefail -DOMAIN="${DOMAIN:-}" -EMAIL="${EMAIL:-}" -HTTPS_PORT="${HTTPS_PORT:-}" -STAGING="${STAGING:-}" -UPSTREAM_NAME="${UPSTREAM_NAME:-}" - -# Ensure the certs folder is writable -[ -w /certs ] || { - printf >&2 "/certs is not writable. Check your mount permissions.\n" - exit 1 -} +root="$(cd "$(dirname "${BASH_SOURCE[0]:-$PWD}")" 2>/dev/null 1>&2 && pwd)" +readonly root +# shellcheck source=/dev/null +source "$root/helpers.sh" + +helpers::dir::writable /certs + +# DNS over tls settings +DNS_OVER_TLS_ENABLED="${DNS_OVER_TLS_ENABLED:-}" +DNS_OVER_TLS_DOMAIN="${DNS_OVER_TLS_DOMAIN:-}" +DNS_OVER_TLS_PORT="${DNS_OVER_TLS_PORT:-}" +DNS_OVER_TLS_LEGO_PORT="${DNS_OVER_TLS_LEGO_PORT:-}" +DNS_OVER_TLS_LEGO_EMAIL="${DNS_OVER_TLS_LEGO_EMAIL:-}" +DNS_OVER_TLS_LE_USE_STAGING="${DNS_OVER_TLS_LE_USE_STAGING:-}" + +# Forward settings +DNS_FORWARD_ENABLED="${DNS_FORWARD_ENABLED:-}" +DNS_FORWARD_UPSTREAM_NAME="${DNS_FORWARD_UPSTREAM_NAME:-}" +DNS_FORWARD_UPSTREAM_IP_1="${DNS_FORWARD_UPSTREAM_IP_1:-}" +DNS_FORWARD_UPSTREAM_IP_2="${DNS_FORWARD_UPSTREAM_IP_2:-}" + +# Other DNS settings +DNS_PORT="${DNS_PORT:-}" +DNS_OVER_GRPC_PORT="${DNS_OVER_GRPC_PORT:-}" +DNS_STUFF_MDNS="${DNS_STUFF_MDNS:-}" + +# Metrics settings +METRICS_PORT="${METRICS_PORT:-}" certs::renew(){ local domain="$1" local email="$2" - local staging="$3" + local port="$3" + local staging="$4" local command="renew --days=45" - [ ! "$staging" ] || staging="--server=https://acme-staging-v02.api.letsencrypt.org/directory" + [ "$staging" != true ] \ + && staging= \ + || staging="--server=https://acme-staging-v02.api.letsencrypt.org/directory" [ -e "/certs/certificates/$domain.key" ] || command="run" printf >&2 "Running command: %s" "lego --domains=\"$domain\" \ --accept-tos --email=\"$email\" --path=/certs --tls $staging --pem \ - --tls.port=:${HTTPS_PORT} \ + --tls.port=:$port \ ${command}" lego --domains="$domain" \ - --accept-tos --email="$email" --path=/certs --tls ${staging} --pem \ - --tls.port=:${HTTPS_PORT} \ + --accept-tos \ + --email="$email" \ + --path=/certs \ + --tls $staging --pem \ + --tls.port=:"$port" \ ${command} } loop(){ while true; do - certs::renew "$1" "$2" "$3" + sleep 86400 + certs::renew "$@" # signal coredns to reload config - technically happens once a day, which is not optimal, but fine kill -s SIGUSR1 1 - sleep 86400 done } +no_tls=-no # If we have a domain, get certificates for that, and the appropriate config -if [ "$DOMAIN" ]; then - # Initial registration - certs::renew "$DOMAIN" "$EMAIL" "$STAGING" +if [ "$DNS_OVER_TLS_ENABLED" == true ]; then + no_tls= + + # Initial registration, blocking + certs::renew "$DNS_OVER_TLS_DOMAIN" "$DNS_OVER_TLS_LEGO_EMAIL" "$DNS_OVER_TLS_PORT" "$DNS_OVER_TLS_LE_USE_STAGING" # Now run in the background to renew 45 days before expiration - loop "$DOMAIN" "$EMAIL" "$STAGING" & + loop "$DNS_OVER_TLS_DOMAIN" "$DNS_OVER_TLS_LEGO_EMAIL" "$DNS_OVER_TLS_PORT" "$DNS_OVER_TLS_LE_USE_STAGING" & fi # Choose config based on environment values -[ "$DOMAIN" ] && no_tls= || no_tls=-no -[ "$UPSTREAM_NAME" ] && mode=forward || mode=recursive +[ "$DNS_FORWARD_ENABLED" == true ] && mode=forward || mode=recursive +[ "$DNS_STUFF_MDNS" == true ] && mod=-mdns || mod= # Get coredns started -exec coredns -conf /config/coredns${no_tls}-tls-${mode}.conf "$@" +exec coredns -conf /config/coredns${no_tls}-tls-${mode}${mod}.conf "$@" diff --git a/context/runtime/boot/helpers.sh b/context/runtime/boot/helpers.sh new file mode 100644 index 0000000..ceb987e --- /dev/null +++ b/context/runtime/boot/helpers.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -o errexit -o errtrace -o functrace -o nounset -o pipefail + +helpers::dir::writable(){ + local path="$1" + local create="${2:-}" + # shellcheck disable=SC2015 + ( [ ! "$create" ] || mkdir -p "$path" 2>/dev/null ) && [ -w "$path" ] && [ -d "$path" ] || { + printf >&2 "%s does not exist, is not writable, or cannot be created. Check your mount permissions.\n" "$path" + exit 1 + } +} diff --git a/context/runtime/config/coredns-no-tls-forward-mdns.conf b/context/runtime/config/coredns-no-tls-forward-mdns.conf new file mode 100644 index 0000000..e5624ce --- /dev/null +++ b/context/runtime/config/coredns-no-tls-forward-mdns.conf @@ -0,0 +1,30 @@ +# experimental: suck up mdns names in +local { + mdns local 1 +} + +# Classic DNS on 53, forwarding to an upstream +.:{$DNS_PORT} { + hosts { + fallthrough + } + + prometheus :{$METRICS_PORT} + + forward . {$DNS_FORWARD_UPSTREAM_IP_1} {$DNS_FORWARD_UPSTREAM_IP_2} { + tls_servername {$DNS_FORWARD_UPSTREAM_NAME} + health_check 5s + } + + cache 3600 + + log + errors + + reload +} + +# GRPC healthcheck endpoint +grpc://.:{$DNS_OVER_GRPC_PORT} { + whoami +} diff --git a/context/runtime/config/coredns-no-tls-forward.conf b/context/runtime/config/coredns-no-tls-forward.conf index 34bb744..f9de036 100644 --- a/context/runtime/config/coredns-no-tls-forward.conf +++ b/context/runtime/config/coredns-no-tls-forward.conf @@ -6,8 +6,8 @@ prometheus :{$METRICS_PORT} - forward . {$UPSTREAM_SERVER_1} {$UPSTREAM_SERVER_2} { - tls_servername {$UPSTREAM_NAME} + forward . {$DNS_FORWARD_UPSTREAM_IP_1} {$DNS_FORWARD_UPSTREAM_IP_2} { + tls_servername {$DNS_FORWARD_UPSTREAM_NAME} health_check 5s } @@ -19,11 +19,7 @@ reload } -#duboduboduponey.me { -# mdns duboduboduponey.me -#} - # GRPC healthcheck endpoint -grpc://.:{$GRPC_PORT} { +grpc://.:{$DNS_OVER_GRPC_PORT} { whoami } diff --git a/context/runtime/config/coredns-no-tls-recursive.conf b/context/runtime/config/coredns-no-tls-recursive.conf index aa2ad17..c0f39de 100644 --- a/context/runtime/config/coredns-no-tls-recursive.conf +++ b/context/runtime/config/coredns-no-tls-recursive.conf @@ -17,6 +17,6 @@ } # GRPC healthcheck endpoint -grpc://.:{$GRPC_PORT} { +grpc://.:{$DNS_OVER_GRPC_PORT} { whoami } diff --git a/context/runtime/config/coredns-tls-forward.conf b/context/runtime/config/coredns-tls-forward.conf index 9bf4f33..462f5b0 100644 --- a/context/runtime/config/coredns-tls-forward.conf +++ b/context/runtime/config/coredns-tls-forward.conf @@ -6,8 +6,8 @@ prometheus :{$METRICS_PORT} - forward . {$UPSTREAM_SERVER_1} {$UPSTREAM_SERVER_2} { - tls_servername {$UPSTREAM_NAME} + forward . {$DNS_FORWARD_UPSTREAM_IP_1} {$DNS_FORWARD_UPSTREAM_IP_2} { + tls_servername {$DNS_FORWARD_UPSTREAM_NAME} health_check 5s } @@ -20,7 +20,7 @@ } # DoT on 853, forwarding to an upstream -tls://.:{$TLS_PORT} { +tls://.:{$DNS_OVER_TLS_PORT} { tls /certs/certificates/{$DOMAIN}.crt /certs/certificates/{$DOMAIN}.key /certs/certificates/{$DOMAIN}.issuer.crt hosts { @@ -29,8 +29,8 @@ tls://.:{$TLS_PORT} { prometheus :{$METRICS_PORT} - forward . {$UPSTREAM_SERVER_1} {$UPSTREAM_SERVER_2} { - tls_servername {$UPSTREAM_NAME} + forward . {$DNS_FORWARD_UPSTREAM_IP_1} {$DNS_FORWARD_UPSTREAM_IP_2} { + tls_servername {$DNS_FORWARD_UPSTREAM_NAME} health_check 5s } @@ -43,6 +43,6 @@ tls://.:{$TLS_PORT} { } # GRPC healthcheck endpoint -grpc://.:{$GRPC_PORT} { +grpc://.:{$DNS_OVER_GRPC_PORT} { whoami } diff --git a/context/runtime/config/coredns-tls-recursive.conf b/context/runtime/config/coredns-tls-recursive.conf index d3ee180..4d029fc 100644 --- a/context/runtime/config/coredns-tls-recursive.conf +++ b/context/runtime/config/coredns-tls-recursive.conf @@ -17,8 +17,8 @@ } # DoT on 853, forwarding to an upstream -tls://.:{$TLS_PORT} { - tls /certs/certificates/{$DOMAIN}.crt /certs/certificates/{$DOMAIN}.key /certs/certificates/{$DOMAIN}.issuer.crt +tls://.:{$DNS_OVER_TLS_PORT} { + tls /certs/certificates/{$DNS_OVER_TLS_DOMAIN}.crt /certs/certificates/{$DNS_OVER_TLS_DOMAIN}.key /certs/certificates/{$DNS_OVER_TLS_DOMAIN}.issuer.crt hosts { fallthrough @@ -37,6 +37,6 @@ tls://.:{$TLS_PORT} { } # GRPC healthcheck endpoint -grpc://.:{$GRPC_PORT} { +grpc://.:{$DNS_OVER_GRPC_PORT} { whoami } diff --git a/context/runtime/config/todo.conf b/context/runtime/config/todo.conf new file mode 100644 index 0000000..9c31649 --- /dev/null +++ b/context/runtime/config/todo.conf @@ -0,0 +1,24 @@ +# Not an active config, just a list of future, useful, in-tree plugins: + +# https://coredns.io/plugins/dnssec/ +dnssec [ZONES... ] { + key file KEY... + cache_capacity CAPACITY +} + +# https://coredns.io/plugins/health/ +health [ADDRESS] { + lameduck DURATION +} + +# https://coredns.io/plugins/pprof/ +pprof [ADDRESS] { + block [RATE] +} + +# https://coredns.io/plugins/trace/ +trace [ENDPOINT-TYPE] [ENDPOINT] { + every AMOUNT + service NAME + client_server +} diff --git a/cue.mod/pkg/duponey.cloud/buildkit/buildctl/buildctl.cue b/cue.mod/pkg/duponey.cloud/buildkit/buildctl/buildctl.cue index 2cb902b..7a74ef0 100644 --- a/cue.mod/pkg/duponey.cloud/buildkit/buildctl/buildctl.cue +++ b/cue.mod/pkg/duponey.cloud/buildkit/buildctl/buildctl.cue @@ -72,6 +72,7 @@ import ( ["--local", "dockerfile=\(dockerfile)"] + ["--frontend", frontend] + + ["--trace", "buildctl.trace.json"] + ["--opt", "filename=\(filename)"] + ["--local", "context=\(context)"] + diff --git a/cue.mod/pkg/duponey.cloud/buildkit/types/platform.cue b/cue.mod/pkg/duponey.cloud/buildkit/types/platform.cue index 579ccf1..1d4d2dd 100644 --- a/cue.mod/pkg/duponey.cloud/buildkit/types/platform.cue +++ b/cue.mod/pkg/duponey.cloud/buildkit/types/platform.cue @@ -6,7 +6,7 @@ import ( #Platforms: { // XXX for whatever reason, this HAS TO BE DONE THIS WAY and not as below - [...=~ "^(?:\(#AMD64)|\(#ARM64)|\(#V7)|\(#V6)|\(#PPC64LE)|\(#S390X)|\(#I386)|\(#RISCV64))$"] // | *[] + [...=~ "^(?:\(#AMD64)|\(#ARM64)|\(#V7)|\(#V6)|\(#V5)|\(#PPC64LE)|\(#MIPS64LE)|\(#S390X)|\(#I386)|\(#RISCV64))$"] // | *[] // XXX might not work - other circumstances have demonstrated this is broken as fuck // [...#AMD64 | #ARM64 | #V7 | #V6 | #PPC64LE | #S390X | #I386 | #RISCV64] | *[] @@ -14,7 +14,9 @@ import ( #ARM64: "linux/arm64" #V7: "linux/arm/v7" #V6: "linux/arm/v6" + #V5: "linux/arm/v5" #PPC64LE: "linux/ppc64le" + #MIPS64LE: "linux/mips64le" #S390X: "linux/s390x" #I386: "linux/386" #RISCV64: "linux/riscv64" diff --git a/hack/helpers/install-tools.sh b/hack/helpers/install-tools.sh index 8376c82..8be862c 100755 --- a/hack/helpers/install-tools.sh +++ b/hack/helpers/install-tools.sh @@ -6,7 +6,7 @@ export DATE=2021-08-01 export BIN_LOCATION="${BIN_LOCATION:-$HOME/bin}" export PATH="$BIN_LOCATION:$PATH" -readonly IMAGE_TOOLS="${IMAGE_TOOLS:-ghcr.io/dubo-dubon-duponey/tools:$(uname -s | grep -q Darwin && printf "macos" || printf "linux-dev")-$SUITE-$DATE}" +readonly IMAGE_TOOLS="${IMAGE_TOOLS:-dubodubonduponey/tools:$(uname -s | grep -q Darwin && printf "macos" || printf "linux-dev")-$SUITE-$DATE}" export SHELLCHECK_VERSION=0.7.2 export HADOLINT_VERSION=2.7.0 diff --git a/hack/helpers/start-buildkit.sh b/hack/helpers/start-buildkit.sh index fc75009..80702fa 100755 --- a/hack/helpers/start-buildkit.sh +++ b/hack/helpers/start-buildkit.sh @@ -4,7 +4,7 @@ set -o errexit -o errtrace -o functrace -o nounset -o pipefail export SUITE=bullseye export DATE=2021-08-01 -readonly IMAGE_BLDKT="${IMAGE_BLDKT:-ghcr.io/dubo-dubon-duponey/buildkit:$SUITE-$DATE}" +readonly IMAGE_BLDKT="${IMAGE_BLDKT:-docker.io/dubodubonduponey/buildkit:$SUITE-$DATE}" setup::buildkit() { [ "$(docker container inspect -f '{{.State.Running}}' dbdbdp-buildkit 2>/dev/null)" == "true" ] || { diff --git a/hack/lint.sh b/hack/lint.sh index 07f00e2..e39dd2d 100755 --- a/hack/lint.sh +++ b/hack/lint.sh @@ -24,7 +24,4 @@ if ! hadolint "${hadolint_ignore[@]}" "$root"/*Dockerfile*; then exit 1 fi -if ! shellcheck "$root"/**/*.sh; then - printf >&2 "Failed shellchecking\n" - exit 1 -fi +find "$root" -iname "*.sh" -not -path "*debuerreotype*" -not -path "*cache*" -exec shellcheck {} \; diff --git a/hack/recipe.cue b/hack/recipe.cue index 75f78a9..6b728d3 100644 --- a/hack/recipe.cue +++ b/hack/recipe.cue @@ -11,7 +11,7 @@ cakes: { recipe: { input: { from: { - registry: * "ghcr.io/dubo-dubon-duponey" | string + registry: * "docker.io/dubodubonduponey" | string } } @@ -19,11 +19,11 @@ cakes: { platforms: types.#Platforms | * [ types.#Platforms.#AMD64, types.#Platforms.#ARM64, - types.#Platforms.#I386, types.#Platforms.#V7, - types.#Platforms.#V6, - types.#Platforms.#S390X, - types.#Platforms.#PPC64LE, + // types.#Platforms.#I386, + // types.#Platforms.#V6, + // types.#Platforms.#S390X, + // types.#Platforms.#PPC64LE, ] } @@ -43,8 +43,8 @@ cakes: { } injectors: { - suite: * "bullseye" | =~ "^(?:jessie|stretch|buster|bullseye|sid)$" @tag(suite, type=string) - date: * "2021-09-01" | =~ "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" @tag(date, type=string) + suite: * "bullseye" | =~ "^(?:bullseye|bookworm|trixie|sid)$" @tag(suite, type=string) + date: * "2022-12-01" | =~ "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" @tag(date, type=string) platforms: string @tag(platforms, type=string) registry: * "registry.local" | string @tag(registry, type=string) } diff --git a/hack/test.sh b/hack/test.sh index e918581..ac1a5a1 100755 --- a/hack/test.sh +++ b/hack/test.sh @@ -8,9 +8,9 @@ root="$(cd "$(dirname "${BASH_SOURCE[0]:-$PWD}")" 2>/dev/null 1>&2 && pwd)/../" # XXX Currently reduced to a single architecture to avoid using all disk space until we figure out our space efficiency problem (likely the fat builder image getting duplicated over and over) # Solution would probably be to do like buildkit and fetch with a lightweight go image while build mount from the previous stage instead of inheriting - annoying but probably the only way if ! "$root/hack/build.sh" \ - --inject registry="ghcr.io/dubo-dubon-duponey" \ + --inject registry="docker.io/dubodubonduponey" \ --inject progress=plain \ - --inject date=2021-09-01 \ + --inject date=2022-12-01 \ --inject suite=bullseye \ --inject platforms=linux/arm64 \ "image" "$@"; then