From 8f4f43209db4453d16b8736d0df76564b408c5a9 Mon Sep 17 00:00:00 2001 From: ElevenNotes Date: Sun, 3 Aug 2025 03:18:01 +0200 Subject: [PATCH] refactor: add payload and distroless defaults --- arch.dockerfile | 243 +++++++++++++++++++++++++++--------------------- key.txt | 192 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+), 107 deletions(-) create mode 100644 key.txt diff --git a/arch.dockerfile b/arch.dockerfile index 7461ee5..5f74120 100644 --- a/arch.dockerfile +++ b/arch.dockerfile @@ -1,40 +1,70 @@ -ARG APP_UID=1000 -ARG APP_GID=1000 +# ╔═════════════════════════════════════════════════════╗ +# ║ SETUP ║ +# ╚═════════════════════════════════════════════════════╝ +# GLOBAL + ARG APP_UID=1000 \ + APP_GID=1000 \ + APP_VERSION=0 \ + BUILD_NGINX_CONFIGURATION=light \ + BUILD_DEPENDENCY_OPENSSL_VERSION=3.5.1 \ + BUILD_DEPENDENCY_ZLIB_VERSION=1.3.1 \ + BUILD_DEPENDENCY_ZLIB_SHA256=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 \ + BUILD_DEPENDENCY_PCRE2_VERSION=10.45 \ + BUILD_DEPENDENCY_HEADERS_MORE_VERSION=0.39 \ + BUILD_DEPENDENCY_QUICKJS_VERSION= \ + BUILD_DEPENDENCY_NJS_VERSION=0.8.10 \ + BUILD_NGINX_PREFIX=/etc/nginx -# :: Util - FROM 11notes/util AS util + ARG BUILD_ROOT=/nginx-${APP_VERSION} \ + BUILD_DEPENDENCY_OPENSSL_ROOT=/openssl-${BUILD_DEPENDENCY_OPENSSL_VERSION} \ + BUILD_DEPENDENCY_ZLIB_ROOT=/zlib-${BUILD_DEPENDENCY_ZLIB_VERSION} \ + BUILD_DEPENDENCY_PCRE2_ROOT=/pcre2-${BUILD_DEPENDENCY_PCRE2_VERSION} \ + BUILD_DEPENDENCY_HEADERS_MORE_ROOT=/headers-more-nginx-module-${BUILD_DEPENDENCY_HEADERS_MORE_VERSION} \ + BUILD_DEPENDENCY_BROTLI_ROOT=/ngx_brotli \ + BUILD_DEPENDENCY_NJS_ROOT=/njs-${BUILD_DEPENDENCY_NJS_VERSION} \ + BUILD_DEPENDENCY_QUICKJS_ROOT=/quickjs${BUILD_DEPENDENCY_QUICKJS_VERSION} \ + BUILD_BIN=${BUILD_ROOT}/objs/nginx -# :: Build / nginx +# :: FOREIGN IMAGES + FROM 11notes/distroless AS distroless + FROM 11notes/distroless:curl AS distroless-curl + FROM 11notes/util:bin AS util-bin + +# ╔═════════════════════════════════════════════════════╗ +# ║ BUILD ║ +# ╚═════════════════════════════════════════════════════╝ +# :: NGINX FROM alpine AS build - ARG TARGETARCH - ARG TARGETPLATFORM - ARG TARGETVARIANT - ARG APP_ROOT - ARG APP_VERSION - ARG APP_NGINX_CONFIGURATION - ENV BUILD_ROOT=/nginx-${APP_VERSION} - ENV BUILD_BIN=${BUILD_ROOT}/objs/nginx - ENV NGINX_PREFIX=/etc/nginx - ENV BUILD_DEPENDENCY_OPENSSL_VERSION=3.5.0 - ENV BUILD_DEPENDENCY_OPENSSL_ROOT=/openssl-${BUILD_DEPENDENCY_OPENSSL_VERSION} - ENV BUILD_DEPENDENCY_ZLIB_VERSION=1.3.1 - ENV BUILD_DEPENDENCY_ZLIB_ROOT=/zlib-${BUILD_DEPENDENCY_ZLIB_VERSION} - ENV BUILD_DEPENDENCY_PCRE2_VERSION=10.45 - ENV BUILD_DEPENDENCY_PCRE2_ROOT=/pcre2-${BUILD_DEPENDENCY_PCRE2_VERSION} - ENV BUILD_DEPENDENCY_HEADERS_MORE_VERSION=0.38 - ENV BUILD_DEPENDENCY_HEADERS_MORE_ROOT=/headers-more-nginx-module-${BUILD_DEPENDENCY_HEADERS_MORE_VERSION} - ENV BUILD_DEPENDENCY_BROTLI_ROOT=/ngx_brotli - ENV BUILD_DEPENDENCY_NJS_VERSION=0.8.10 - ENV BUILD_DEPENDENCY_NJS_ROOT=/njs-${BUILD_DEPENDENCY_NJS_VERSION} - ENV BUILD_DEPENDENCY_QUICKJS_VERSION= - ENV BUILD_DEPENDENCY_QUICKJS_ROOT=/quickjs${BUILD_DEPENDENCY_QUICKJS_VERSION} + COPY --from=util-bin / / + COPY ./key.txt / - USER root - - COPY --from=util /usr/local/bin/ /usr/local/bin + ARG APP_UID \ + APP_GID \ + APP_VERSION \ + APP_ROOT \ + BUILD_DEPENDENCY_OPENSSL_VERSION \ + BUILD_DEPENDENCY_ZLIB_VERSION \ + BUILD_DEPENDENCY_ZLIB_SHA256 \ + BUILD_DEPENDENCY_PCRE2_VERSION \ + BUILD_DEPENDENCY_HEADERS_MORE_VERSION \ + BUILD_DEPENDENCY_QUICKJS_VERSION \ + BUILD_DEPENDENCY_NJS_VERSION \ + BUILD_NGINX_PREFIX \ + BUILD_NGINX_CONFIGURATION \ + BUILD_ROOT \ + BUILD_DEPENDENCY_OPENSSL_ROOT \ + BUILD_DEPENDENCY_ZLIB_ROOT \ + BUILD_DEPENDENCY_PCRE2_ROOT \ + BUILD_DEPENDENCY_HEADERS_MORE_ROOT \ + BUILD_DEPENDENCY_BROTLI_ROOT \ + BUILD_DEPENDENCY_NJS_ROOT \ + BUILD_DEPENDENCY_QUICKJS_ROOT \ + BUILD_BIN RUN set -ex; \ apk --update --no-cache add \ + gpg \ + gpg-agent \ cmake \ autoconf \ automake \ @@ -67,60 +97,63 @@ ARG APP_GID=1000 brotli-dev \ libgd \ tar \ - xz \ - upx; + pv \ + jq \ + xz; + + RUN set -ex; \ + gpg --import /key.txt; RUN set -ex; \ cd /; \ - curl -SL https://nginx.org/download/nginx-${APP_VERSION}.tar.gz | tar -zxC /; \ - curl -SL https://zlib.net/fossils/zlib-${BUILD_DEPENDENCY_ZLIB_VERSION}.tar.gz | tar -zxC /; \ - curl -SL https://github.com/PCRE2Project/pcre2/releases/download/pcre2-${BUILD_DEPENDENCY_PCRE2_VERSION}/pcre2-${BUILD_DEPENDENCY_PCRE2_VERSION}.tar.gz | tar -zxC /; \ - curl -SL https://github.com/openresty/headers-more-nginx-module/archive/v${BUILD_DEPENDENCY_HEADERS_MORE_VERSION}.tar.gz | tar -zxC /; + eleven asset gpg-asc https://nginx.org/download/nginx-${APP_VERSION}.tar.gz https://nginx.org/download/nginx-${APP_VERSION}.tar.gz.asc; \ + eleven asset sha256 https://zlib.net/zlib-${BUILD_DEPENDENCY_ZLIB_VERSION}.tar.gz ${BUILD_DEPENDENCY_ZLIB_SHA256}; \ + eleven github asset PCRE2Project/pcre2 pcre2-${BUILD_DEPENDENCY_PCRE2_VERSION} pcre2-${BUILD_DEPENDENCY_PCRE2_VERSION}.tar.gz; \ + eleven github asset openresty/headers-more-nginx-module v${BUILD_DEPENDENCY_HEADERS_MORE_VERSION} v${BUILD_DEPENDENCY_HEADERS_MORE_VERSION}.tar.gz; RUN set -ex; \ #build OpenSSL - case "${APP_NGINX_CONFIGURATION}" in \ + case "${BUILD_NGINX_CONFIGURATION}" in \ "full") \ cd /; \ - curl -SL https://github.com/openssl/openssl/releases/download/openssl-${BUILD_DEPENDENCY_OPENSSL_VERSION}/openssl-${BUILD_DEPENDENCY_OPENSSL_VERSION}.tar.gz | tar -zxC /; \ + eleven github asset openssl/openssl openssl-${BUILD_DEPENDENCY_OPENSSL_VERSION} openssl-${BUILD_DEPENDENCY_OPENSSL_VERSION}.tar.gz; \ ;; \ esac; RUN set -ex; \ # build brotli cd /; \ - git clone --recurse-submodules -j8 https://github.com/google/ngx_brotli; \ + eleven git clone google/ngx_brotli.git; \ mkdir -p ${BUILD_DEPENDENCY_BROTLI_ROOT}/deps/brotli/out; \ cd ${BUILD_DEPENDENCY_BROTLI_ROOT}/deps/brotli/out; \ - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS="-Ofast -march=native -mtune=native -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="-Ofast -march=native -mtune=native -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_INSTALL_PREFIX=./installed ..; \ - cmake --build . --config Release --target brotlienc; + cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS="-Ofast -march=native -mtune=native -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="-Ofast -march=native -mtune=native -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_INSTALL_PREFIX=./installed .. 2>&1 > /dev/null; \ + cmake --build . --config Release --target brotlienc 2>&1 > /dev/null; RUN set -ex; \ #build QuickJS - case "${APP_NGINX_CONFIGURATION}" in \ + case "${BUILD_NGINX_CONFIGURATION}" in \ "full") \ cd /; \ - git clone https://github.com/bellard/quickjs; \ - curl -SL https://github.com/nginx/njs/archive/refs/tags/${BUILD_DEPENDENCY_NJS_VERSION}.tar.gz | tar -zxC /; \ + eleven github asset nginx/njs ${BUILD_DEPENDENCY_NJS_VERSION} ${BUILD_DEPENDENCY_NJS_VERSION}.tar.gz; \ cd ${BUILD_DEPENDENCY_QUICKJS_ROOT}; \ - CFLAGS='-fPIC -static -static-libgcc' make libquickjs.a; \ + CFLAGS='-fPIC -static -static-libgcc' make libquickjs.a 2>&1 > /dev/null; \ ;; \ esac; RUN set -ex; \ #build XLST - case "${APP_NGINX_CONFIGURATION}" in \ + case "${BUILD_NGINX_CONFIGURATION}" in \ "full") \ cd /; \ - curl -SL https://download.gnome.org/sources/libxml2/2.14/libxml2-2.14.1.tar.xz | tar -xJC /; \ - curl -SL https://download.gnome.org/sources/libxslt/1.1/libxslt-1.1.43.tar.xz | tar -xJC /; \ + eleven asset sha256-sum https://download.gnome.org/sources/libxml2/2.14/libxml2-2.14.1.tar.xz https://download.gnome.org/sources/libxml2/2.14/libxml2-2.14.1.sha256sum; \ + eleven asset sha256-sum https://download.gnome.org/sources/libxslt/1.1/libxslt-1.1.43.tar.xz https://download.gnome.org/sources/libxslt/1.1/libxslt-1.1.43.sha256sum; \ cd /libxml2-2.14.1; \ ./configure \ --prefix="/usr" \ --disable-shared \ --enable-static \ --without-python; \ - make -s -j $(nproc); \ + make -s -j $(nproc) 2>&1 > /dev/null; \ make install; \ cd /libxslt-1.1.43; \ ./configure \ @@ -128,13 +161,13 @@ ARG APP_GID=1000 --disable-shared \ --enable-static \ --without-python; \ - make -s -j $(nproc); \ + make -s -j $(nproc) 2>&1 > /dev/null; \ make install; \ ;; \ esac; RUN set -ex; \ - case "${APP_NGINX_CONFIGURATION}" in \ + case "${BUILD_NGINX_CONFIGURATION}" in \ "light") \ cd ${BUILD_ROOT}; \ ./configure \ @@ -142,10 +175,10 @@ ARG APP_GID=1000 --with-pcre=${BUILD_DEPENDENCY_PCRE2_ROOT} \ --add-module=${BUILD_DEPENDENCY_HEADERS_MORE_ROOT} \ --add-module=${BUILD_DEPENDENCY_BROTLI_ROOT} \ - --prefix=${NGINX_PREFIX} \ + --prefix=${BUILD_NGINX_PREFIX} \ --sbin-path=${BUILD_BIN} \ --modules-path=${APP_ROOT}/lib/modules \ - --conf-path=${NGINX_PREFIX}/nginx.conf \ + --conf-path=${BUILD_NGINX_PREFIX}/nginx.conf \ --error-log-path=${APP_ROOT}/log/error.log \ --http-log-path=${APP_ROOT}/log/access.log \ --pid-path=${APP_ROOT}/run/nginx.pid \ @@ -197,10 +230,10 @@ ARG APP_GID=1000 --add-module=${BUILD_DEPENDENCY_BROTLI_ROOT} \ --add-module=${BUILD_DEPENDENCY_NJS_ROOT}/nginx \ --with-openssl=${BUILD_DEPENDENCY_OPENSSL_ROOT} \ - --prefix=${NGINX_PREFIX} \ + --prefix=${BUILD_NGINX_PREFIX} \ --sbin-path=${BUILD_BIN} \ --modules-path=${APP_ROOT}/lib/modules \ - --conf-path=${NGINX_PREFIX}/nginx.conf \ + --conf-path=${BUILD_NGINX_PREFIX}/nginx.conf \ --error-log-path=${APP_ROOT}/log/error.log \ --http-log-path=${APP_ROOT}/log/access.log \ --pid-path=${APP_ROOT}/run/nginx.pid \ @@ -246,72 +279,68 @@ ARG APP_GID=1000 RUN set -ex; \ cd ${BUILD_ROOT}; \ - make -s -j $(nproc); \ - eleven checkStatic ${BUILD_BIN}; + make -s -j $(nproc); RUN set -ex; \ - mkdir -p /distroless/usr/local/bin; \ - mkdir -p /distroless${NGINX_PREFIX}; \ - cp -R ${BUILD_ROOT}/conf/* /distroless${NGINX_PREFIX}; \ - rm /distroless${NGINX_PREFIX}/nginx.conf; \ - eleven strip ${BUILD_BIN}; \ - cp ${BUILD_BIN} /distroless/usr/local/bin; - - COPY ./rootfs/etc /distroless/etc - -# :: Distroless / nginx - FROM scratch AS distroless-nginx - COPY --from=build /distroless/ / - - -# :: Build / file system - FROM alpine AS fs - ARG APP_ROOT - USER root + eleven distroless ${BUILD_BIN}; RUN set -ex; \ - mkdir -p ${APP_ROOT}/etc; \ - mkdir -p ${APP_ROOT}/var; \ - mkdir -p ${APP_ROOT}/run; \ - mkdir -p ${APP_ROOT}/lib/modules; \ - mkdir -p ${APP_ROOT}/cache; \ - mkdir -p ${APP_ROOT}/log; \ - ln -sf /dev/stdout ${APP_ROOT}/log/access.log; \ - ln -sf /dev/stderr ${APP_ROOT}/log/error.log; + mkdir -p /distroless${BUILD_NGINX_PREFIX}; \ + cp -R ${BUILD_ROOT}/conf/* /distroless${BUILD_NGINX_PREFIX}; \ + rm /distroless${BUILD_NGINX_PREFIX}/nginx.conf; - COPY ./rootfs/nginx ${APP_ROOT} + COPY ./rootfs/etc/nginx/ /distroless${BUILD_NGINX_PREFIX} -# :: Distroless / file system - FROM scratch AS distroless-fs + RUN set -ex; \ + ls -lah /distroless${BUILD_NGINX_PREFIX}; \ + cat /distroless${BUILD_NGINX_PREFIX}/nginx.conf; + +# :: FILE-SYSTEM + FROM alpine AS file-system ARG APP_ROOT - COPY --from=fs ${APP_ROOT} /${APP_ROOT} + COPY ./rootfs/nginx /distroless${APP_ROOT} + + RUN set -ex; \ + mkdir -p /distroless${APP_ROOT}/etc; \ + mkdir -p /distroless${APP_ROOT}/var; \ + mkdir -p /distroless${APP_ROOT}/run; \ + mkdir -p /distroless${APP_ROOT}/lib/modules; \ + mkdir -p /distroless${APP_ROOT}/cache; \ + mkdir -p /distroless${APP_ROOT}/log; \ + ln -sf /dev/stdout /distroless${APP_ROOT}/log/access.log; \ + ln -sf /dev/stderr /distroless${APP_ROOT}/log/error.log; -# :: Header - FROM 11notes/distroless AS distroless - FROM 11notes/distroless:curl AS distroless-curl +# ╔═════════════════════════════════════════════════════╗ +# ║ IMAGE ║ +# ╚═════════════════════════════════════════════════════╝ + # :: HEADER FROM scratch - # :: arguments - ARG TARGETARCH - ARG APP_IMAGE - ARG APP_NAME - ARG APP_VERSION - ARG APP_ROOT - ARG APP_UID - ARG APP_GID + # :: default arguments + ARG TARGETPLATFORM \ + TARGETOS \ + TARGETARCH \ + TARGETVARIANT \ + APP_IMAGE \ + APP_NAME \ + APP_VERSION \ + APP_ROOT \ + APP_UID \ + APP_GID \ + APP_NO_CACHE - # :: environment - ENV APP_IMAGE=${APP_IMAGE} - ENV APP_NAME=${APP_NAME} - ENV APP_VERSION=${APP_VERSION} - ENV APP_ROOT=${APP_ROOT} + # :: default environment + ENV APP_IMAGE=${APP_IMAGE} \ + APP_NAME=${APP_NAME} \ + APP_VERSION=${APP_VERSION} \ + APP_ROOT=${APP_ROOT} # :: multi-stage - COPY --from=distroless --chown=${APP_UID}:${APP_GID} / / - COPY --from=distroless-fs --chown=${APP_UID}:${APP_GID} / / - COPY --from=distroless-curl --chown=${APP_UID}:${APP_GID} / / - COPY --from=distroless-nginx --chown=${APP_UID}:${APP_GID} / / + COPY --from=distroless / / + COPY --from=distroless-curl / / + COPY --from=build /distroless/ / + COPY --from=file-system --chown=${APP_UID}:${APP_GID} /distroless/ / # :: Volumes VOLUME ["${APP_ROOT}/etc", "${APP_ROOT}/var"] diff --git a/key.txt b/key.txt new file mode 100644 index 0000000..656d40c --- /dev/null +++ b/key.txt @@ -0,0 +1,192 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +vcV0wl+DODz9hw== +=oWlI +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +ozw9yNdOZmnk2Prj7+mBuchbT3BJOQ== +=AgHy +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGZXO1wBEADEm061e/MGo2f7rpSqokI59in/egWbeQE26vwxB7vPu4e7j+cU +Vg3AezwCbf3nVRAE9DpJ+yuB0KVkM/0QszjOEEBuehZYJrUiwMyiY6jAk8xtqjpV +PsOMyZrypoJhwzg/sYNadUPw4UoHJ/xq4wNA2ZG9Xf0l8M3shYJPmKWLz/eefa5V +Ef/toQ7a55l0aJ7XyACTU6dv4bkHHqomDImK2C94s+KyCxaFyz6NgFz25V/j66Am +gB1m6UGGsvP4qYXW+KTsLz9XDvJeLLHWNcqQoyUO5Vs5C3hGozL7kEkyK/1qHcou +XXkeGN365z93ZeK+VdBZKJtsCswPk2wdDBByU9lAUNHYcLHf6S8fwCACeIqJ6LaY +MKmZUN2gR/boTyMERHEA8XnWXTDp7EsSNIc+LkU5AT8yesANcczH5k/XOI4hltJC +piEsSgg9V7FvO4eA2iQWGv/Y4nlUfw3lbRuRFvd7oqVQKlX4iIs++kVCCegBvtNA +1naxPbvTqrC4THvBSSZpOW/y/6XibAr/scCNNW1mEhwm5SPBHq9Sv35p6xKDTcgQ +8o3KLM8tKKt6kokAqlrXk9Nq6LYrZKwg5a9crFF7nCL2xgxZy1OJQVcPuhhZy5WT +WReE5RJdlF5VGRT9nMJ3B4Vlp5luQnMUFYXTAKQd6Cogbb99J4MjDttAlwARAQAB +tCtuZ2lueCBzaWduaW5nIGtleSA8c2lnbmluZy1rZXktM0BuZ2lueC5jb20+iQIi +BBMBCgAWBQJmVztcCRC83NijjYiiswIbAwIZAQAA9FMQAJ/e8F1egZGbRIV6qU/Q +bJD3EsKZZlitQSVXbBpxqDlkD+uzSFATGjiLGvJoTzfpJpJjI7FwrtO74lRkjCl9 +wQUNJ+wm2Kod6rEEQc6lWkDsgxpjqAAGVS0lmMf+VPBGQ+kc8S3ZdCOWEeq7nThZ +/xWR+UuQQcz1vCKmEgwTrr5MJVcqDg4wiH1Z4lRVfjTezf9IWk+xeE3mV8h7Ltbr +N5ZvOkiw88JLrbQsurxx+lYEaGIZyIk3huiDE/KpsMdw9KXUfoDcBqWc7oDjqKL+ +QEaq7TW6VetKyJaakP6Do+Opx0BtS3eH86PEZqtULEw9WifC86GtRr50iTXWBTfI +MFZo4AwigHXvZ5WrJvLfldY+scoU1rPMouYlZJ9W+6YHLjf/jpr4W1w6LKKXX3ah +h4VLtlOmrOLA21E7RQ0PwoE6nT7DAm1DsMFCXy7lyp3u5IXGahnJddWCb0Px3RTm +PZgOt+YAGJDsP46ngl5LxhilMK5f5R8v5n1lJ/XzFcXCEN4i/d8A1jx9DQx4CJN1 +wp/WZzJ6GjnCqMCdOBlQ2eNmhR+q1bAI79kSv86ahaM/aS1FvHMz8ppzwkRhv5jY +eR9aRlAwaCPOjbWhYJt/xveOWmxCdg5ta+Pj5g+41wHZyNf9aqR314aKwsxo2AYH +uUe+PgpsHbe1sQTkb/W1OfSCiQEzBBABCAAdFiEEcziXMGntP0Q/TTffpk/VsXrb +OagFAmZXO+kACgkQpk/VsXrbOajGgwf8CAXJwSIhGOWFSgV6vpvZPChTsgteZxhT +8NrJJLxL8X34Rw5YctSli4akkchTonm5RRp/SlvI2fPe0o6q2ymF4BASPJ/oSI3p +Gs/jwctHz8hwaVN0xQ4SBXgquIFWrLRNOjCxEV/vMRJRzuF9jrrdv3vxZEugETI+ +rnoEZu2Z2ZlMj7PPeiScf8dFXax67+Xi5S2KJCaXm1QGAJvttHrwsbBAIE9CVUg4 +UmXwADQ6HkOKjY+QS5AP8Ak1dg8/oadgyMqB4GrcE44KUpo4YafP37XnwXfQNKpk +Rb0bO9Qm9lM/LhPulBY8WIPkmrFCVhGTE6K5ZvI59R4nECHHx24/LYkBMwQQAQgA +HRYhBFc7/Ws9j7xkEHmmq6v1vYJ72b9iBQJmVzzzAAoJEKv1vYJ72b9iPPIIAJ5k +hTz2d7CaJefHzoraogKSIeBnA3OR+nDgdDl9Mp8i2WLGu9YYhIrPU0iSVw8jqa8t +GIjCw4/bS9HN8oub2Ip802xDLugCz1Yz6CXjCXN2rlNPsdBV8IIKNHOv93qMvnZS +DwyBUAvAs4XzF7zbYgfZ30B0gRI0g0+Nt44oDOn3PfO/kNUJyBVPT9m7l3JUHuZT +FPOD8a0oJPvW+iYlSkmPELBvgehsX7MVLoeQ5qtS1KkuWr+y1wqD5kxqabMPcfdU +jAr4ssXs/pSsYJVyS4CuUWkY4FiCJm4KtU+XPDs1RCTzMkW6HHgSebocTZzLETYw +XsDx80qd21UAdGc116qJAjMEEAEIAB0WIQTWeGzjA9mpAimY3GzIRk1UmvdcCgUC +ZldKYgAKCRDIRk1UmvdcCoG/D/9qLmHYOGnsmedUbgtLmuBJOuA6oqnaWxYI45eV ++vaAaI2+QfRoJTrjklTXv29Pi4LTzN5YBySSIkv/z9ry5Xsz5yroNY9Xb6JdrqOt +fLa/U0wddNuJbmIom4gUPXGInhHUBbP6mNz+s6e2ukBEWvb2XIsGe5v291QXMohQ +/PT8zTIwNYaw2zVF6Sa/0spA9/9XA5BdUcrtl7xPgYL7pLVmKYGJlCf5TOaWfLDJ +mIMeeUznVK9vK+vT+YqUPfFyIqO7dvio/+MRFjePoD6csT4UBT009ugy8vrYg2YR +K9uaRxP3laz9b6xdUM648ycUQLoI4fLhyKAHwPU9/Q+4rOFdrL72ZGVKzv1XOB0H +VXf0/E4JmJBydM7AyXHNxIPDtNFydosGn6VZsEvSPZdQSCsCeBs9UuBWgwFb1XBB +61XiHGnheb3U3ZRkajS1ZNdxfohHrBzHnd8tbDkv5Rq+XoUmDauoeM0VcN15hl4a +M/JzkeOrHuJicn3mg+HRHxQSCl3D37bVQT7O36n7cff22GykT7XQUBBxMlhKzygD +SgdQUtSEt0eu7AXIvr6yl0kobgZQS3wzUIaY0JEuv2ahtEXXjoPzCVWB2OHIpPbu +D58cpyyEVqr+ZecaI4HlaO9lVShf+K0rf/6DC12rC2gNzzv/fCIinDiqiMsPTfEM +fduRSYkBswQQAQgAHRYhBBPIKmO2A1dhVuMKTqDqmBtmsNlnBQJmV1HlAAoJEKDq +mBtmsNlnhI4L/0MHtfCZ2nuKTF/BkxJ7oB3Uule0tWiFj5SU97GjcVj1LgawGY7Y ++zoyEd6Twpl6H/+QkZBB55Bf8+cTzRbDzH1Og0fSORu0pGC0uxWdYu1sTLeTnn93 +mesXAvevHFNbsPchIWwsVJopTdzMWuAQS5hMMMtNb/14ZfnBadzhjvaJeH3DlZVK +0cGFp0qfbMfjr9yRJzQ1IkiXsS4G4uKg9T+KRsPr4+JalurWJgLnBXZGetNNjjUa +UCV1KZY/iWCAlZjkZ5z7yBRj5nUWLb5AVouEQPEDbn+i/0uEjukC+G6EMq2mgbrh +m0bFHbHAYBaf9EH0eP799HpoAx2aziDB5igAC516i3BnqxINI9mXHh92tU/H797I +oYZvpBsAHDWDHj6O74jwk5lXF5Qwri8gjA8aTudmuQX3uX4h0/FyGGQJW4/wWecH +/1fMuvHHyRtOSsJsheDwcSjrw5WlsyNjvSIbBPV2fIx60W2haVMUVX6CrxAeq44F +UYda9m8fOnaIew== +=TEOn +-----END PGP PUBLIC KEY BLOCK-----