Skip to content

Commit

Permalink
First Release (#1)
Browse files Browse the repository at this point in the history
* first version

* correction on login

* added variable

* add args

* test

* correction

* test

* test2

* test3

* test4

* test5

* test6

* test7

* test7

* test8

* correct user creation for alpine

* test user and group

* correct

* test

* test

* test

* test

* test

* test

* test

* last test

* test

* fix version

* bugfix

* entrypoint test

* testing

* added mkdir

* corrections

* removed user

* test cron

* test

* bugfix

* test su-exec

* test sudo

* apk upd and upgr

* added sudo

* sudo veresion

* test

* test2

* test4

* test sudoers

* last mods

* healthcheck

* new healthcehck

* bugfix

* test hc

* final version for testing

* moved credentials to env

* cron modified

* test23456

* test clean ci

* test21345543

* updated script

* crond log level

* test

* test

* removed root use

* permission problem

* boh

* debug

* add chown

* added CMD

* test

* bug

* bug

* test

* test

* test

* test libcap

* test supercronic

* bug

* bug

* test quoting

* test env arch

* test env

* test

* printenv

* test arg

* test

* test arg su env

* ...

* ,

* found

* final?

* test entrypoint

* tee -a

* maybe final

* test doas

* bug

* aorrect

* bus doas

* bus conf doas

* change base dir

* moved pip

* live anda archive folders

* test update pip3 packages

* rollback pip update

* permissions

* permissions

* maybe ready for release

* added license

* readme update

* Update README.md

* bug toml
  • Loading branch information
gianmarco-mameli authored Mar 8, 2024
1 parent bf3cf79 commit 9e2649d
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.*
*.yml
*.tmpl
*.md
*.hcl
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Dev stuff
.trunk
.vscode
53 changes: 53 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
variables:
IMAGE_NAME: docker-certbot-dns-ionos
VERSION: "2024.1.8"
CERTBOT_VERSION: v2.9.0
REGISTRY_IMAGE: ${HARBOR_HOST}/${HARBOR_PROJECT}/${IMAGE_NAME}
REGISTRY_IMAGE_PUBLIC: $DOCKERHUB_USER/$IMAGE_NAME
BUILDER_IMAGE: "${IMAGE_NAME}-builder-$CI_CONCURRENT_ID"

image: docker:$DOCKER_VERSION

stages:
- linting
- build

before_script:
- echo ${HARBOR_PASSWORD} | docker login -u ${HARBOR_USERNAME} --password-stdin ${HARBOR_HOST}
- echo ${DOCKERHUB_PASSWORD} | docker login -u ${DOCKERHUB_USER} --password-stdin
- docker run --privileged --rm tonistiigi/binfmt --install all >/dev/null
- docker buildx create --use --bootstrap --name ${BUILDER_IMAGE} --config=buildkitd.toml

after_script:
- docker buildx stop ${BUILDER_IMAGE}
- docker buildx rm ${BUILDER_IMAGE}

buildkit_toml:
stage: .pre
image: alpine
before_script: [] # to exclude default before_script
after_script: [] # to exclude default after_script
script:
- apk add envsubst
- envsubst < buildkitd.toml.tmpl > buildkitd.toml
artifacts:
paths:
- buildkitd.toml

.hadolint:
stage: linting
image: registry.gitlab.com/pipeline-components/hadolint:latest
script:
- hadolint Dockerfile
rules:
- changes:
- Dockerfile*

build_publish:
stage: build
script:
- docker buildx bake --push --file docker-bake.hcl --progress plain
rules:
- changes:
- Dockerfile*
- docker-bake.hcl
73 changes: 73 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
ARG CERTBOT_VERSION
FROM certbot/certbot:${CERTBOT_VERSION}

LABEL org.opencontainers.image.authors="gnammyx@gmail.com"
LABEL org.opencontainers.image.url="https://hub.docker.com/r/gmmserv/docker-certbot-dns-ionos"
LABEL org.opencontainers.image.source="https://github.com/gianmarco-mameli/docker-certbot-dns-ionos"
LABEL org.opencontainers.image.base.name="certbot/certbot:${CERTBOT_VERSION}"
LABEL org.opencontainers.image.version="${VERSION}"

# arch and version envs
ARG TARGETPLATFORM
ARG VERSION

ENV IONOS_VERSION=${VERSION}
ENV TARGETPLATFORM=${TARGETPLATFORM}

# user envs
ENV USERNAME=certbot
ENV USER_UID=1000
ENV USER_GID="${USER_UID}"

# certbot envs
ENV CERTBOT_BASE_DIR="/certbot"
ENV CERTBOT_CONFIG_DIR="${CERTBOT_BASE_DIR}/etc/letsencrypt"
ENV CERTBOT_LIVE_DIR="${CERTBOT_CONFIG_DIR}/live"
ENV CERTBOT_ARCHIVE_DIR="${CERTBOT_CONFIG_DIR}/archive"
ENV CERTBOT_LOGS_DIR="${CERTBOT_BASE_DIR}/var/log/letsencrypt"
ENV CERTBOT_WORK_DIR="${CERTBOT_BASE_DIR}/var/lib/letsencrypt"

# update image, create user and set some permissions
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN apk update --no-cache \
&& apk upgrade --no-cache \
&& apk add --no-cache doas==6.8.2-r4 \
&& mkdir -p "${CERTBOT_BASE_DIR}" \
&& addgroup -g "${USER_GID}" -S "${USERNAME}" \
&& adduser -u "${USER_UID}" -S "${USERNAME}" -G "${USERNAME}" -h "${CERTBOT_BASE_DIR}" \
&& chown -R "${USERNAME}":"${USERNAME}" "${CERTBOT_BASE_DIR}" \
&& echo "permit nopass keepenv ${USERNAME} as root cmd /certbot_permissions.sh" | tee -a "/etc/doas.d/doas.conf" \
&& doas -C "/etc/doas.d/doas.conf"

# install supercronic
ENV SUPERCRONIC_BASE_URL="https://github.com/aptible/supercronic/releases/download/v0.2.29"
RUN wget -q "${SUPERCRONIC_BASE_URL}/supercronic-linux-$(echo "${TARGETPLATFORM}" | \
cut -d '/' -f 2)" -O /usr/local/bin/supercronic \
&& chmod +x /usr/local/bin/supercronic

# install plugin
RUN pip install --no-cache-dir "certbot-dns-ionos==${VERSION}"

# copy anda config scripts
COPY entrypoint.sh /entrypoint.sh
COPY certbot_script.sh /certbot_script.sh
COPY certbot_permissions.sh /certbot_permissions.sh

RUN chmod 555 /*.sh

USER ${USERNAME}

# create dirs
WORKDIR "${CERTBOT_BASE_DIR}"
RUN mkdir -p "${CERTBOT_LIVE_DIR}" \
"${CERTBOT_ARCHIVE_DIR}" \
"${CERTBOT_LOGS_DIR}" \
"${CERTBOT_WORK_DIR}" \
/tmp/crontabs \
&& touch "/tmp/crontabs/${USERNAME}"

HEALTHCHECK CMD ["pgrep","-f","certbot_entry.sh"]

# ENTRYPOINT ["tail", "-f", "/dev/null"] # for testing purposes
ENTRYPOINT ["/entrypoint.sh"]
CMD ["/usr/local/bin/supercronic", "/tmp/crontabs/certbot"]
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Gianmarco Mameli

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
122 changes: 121 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,122 @@
# docker-certbot-dns-ionos
Docker build for certbot-dns-ionos plugin from https://github.com/helgeerbe/certbot-dns-ionos project

![Contributors](https://img.shields.io/github/contributors/gianmarco-mameli/docker-certbot-dns-ionos?style=plastic) ![Forks](https://img.shields.io/github/forks/gianmarco-mameli/docker-certbot-dns-ionos?style=plastic) ![Stargazers](https://img.shields.io/github/stars/gianmarco-mameli/docker-certbot-dns-ionos?style=plastic) ![Issues](https://img.shields.io/github/issues/gianmarco-mameli/docker-certbot-dns-ionos?style=plastic) ![License](https://img.shields.io/github/license/gianmarco-mameli/docker-certbot-dns-ionos?style=plastic)

I created a Docker image for certbot-dns-ionos plugin from <https://github.com/helgeerbe/certbot-dns-ionos> project

The image is based on certbot original image with the addition of the plugin and include some variations to run all the scripts as non root user, set some permissions and schedule the certificate update with 'supercronic'.
The only script that run with highest privileges is for settings some folder permission and it's limited by "doas" command.

You need mapping of the following internal folders, that certbot uses as base dirs.

```ini
- /certbot # base folder
- /certbot/etc/letsencrypt/live # generated certificates folder
- /certbot/etc/letsencrypt/.secrets # path containing Ionos credential file
```

Create the file containing the credentials for the ionos api login, you can specify the path via env variable (change the volume accordingly).
Make sure you created the API key on [Ionos control panel](https://developer.hosting.ionos.it/keys)

This is the template to use (also available in the repository ionos.ini.tmpl or in the original [project repo](https://github.com/helgeerbe/certbot-dns-ionos#credentials))

```ini
# Instructions: <https://github.com/helgeerbe/certbot-dns-ionos>
# Replace with your values
dns_ionos_prefix = # ionos api prefix
dns_ionos_secret = # ionos api secret
dns_ionos_endpoint = # ionos api endpoint, ex. <https://api.hosting.ionos.com>
```

Finally need the following environment variables to make it work

```ini
IONOS_CREDENTIALS=/certbot/etc/letsencrypt/.secrets/ionos.ini # the path of the credential file ionos.ini
IONOS_CRONTAB=0 13 * * * # the supercronic schedule, in crontab format
IONOS_DOMAINS=test.ionos.io,test2.ionos.io # the domains to use on certificate renew, multiple entry comma separated
IONOS_PROPAGATION=300 # the seconds to wait for ionos dns propagation
IONOS_EMAIL=test@test.com # your ionos account email
```

## Usage

The image is available on Dockerhub <https://hub.docker.com/r/gmmserv/docker-certbot-dns-ionos>

For a fast run from command line with the following example make sure:

- you created all dirs to mount as volume
- you created the 'ionos.ini' file with correct credentials under ~/certbot/etc/letsencrypt/.secrets
- create a .env file, for simplicity, with all the envs needed

```shell
docker run -v ~/certbot:/certbot
-v ~/certbot/etc/letsencrypt/live:/certbot/etc/letsencrypt/live
-v ~/certbot/etc/letsencrypt/.secrets:/certbot/etc/letsencrypt/.secrets
--env-file .env
gmmserv/docker-certbot-dns-ionos:2024.1.8
```

The repo contains also a docker-compose file for example service

## Build

If you want to build the image with your mods or customization you can find on the repo the Dockerfile used and a docker-bake.hcl file for multi architectures with buildx. Also there's a Gitlab pipeline that I use to build the images pushed to Dockerhub and a personal Harbor Registry

Make sure to pass the following args

```ini
VERSION = # version of the image (I'm using the version of the Ionos certbot plugin)
CERTBOT_VERSION = # version of the certbot image used as base
```

Example of a simple build with "docker build"

```shell
docker build
--build-arg VERSION=2024.1.8
--build-arg CERTBOT_VERSION=v2.9.0
-t docker-certbot-dns-ionos:2024.1.8 .
```

Example of a multi architecture build with "docker buildx", you need to first create a builder using the binfmt image. Have a look at the docker-bake.hcl file for other parameters
My file iso configured to build 4 platforms, 'linux/amd64','linux/arm64','linux/arm/v7','linux/arm/v6'

```shell
export IMAGE_NAME=docker-certbot-dns-ionos
export VERSION=2024.1.8
export CERTBOT_VERSION=v2.9.0
export REGISTRY_IMAGE="${HARBOR_HOST}/${HARBOR_PROJECT}/${IMAGE_NAME}"
export REGISTRY_IMAGE_PUBLIC="${DOCKERHUB_USER}/${IMAGE_NAME}"
export BUILDER_IMAGE="${IMAGE_NAME}-builder"
docker run --privileged --rm tonistiigi/binfmt --install all
docker buildx create --use --bootstrap --name ${BUILDER_IMAGE} --config=buildkitd.toml
docker buildx bake --push --file docker-bake.hcl --progress plain
```

If you want to build with Gitlab, like me, have a look at the .gitlab-ci.yml, and set variables needed by the runner to execute. Pay particular attention to the 'buildkitd.toml.tmpl' file, you need to configure and rename to toml, for using custom signed CA Certificates for private registries. You can omit that file for pushing to dockerhub, also make sure to comment the "buildkit_toml" job on the pipeline.

## Customization

This project is written keeping in mind my necessities so I reccomend you to check all the sources before use it or launch it

## Issues, bugs, requests, collaboration

Feel free to open issues or pull requests if you find bugs or feature lack

## Next steps

- enable/disable supercronic if needed, for use with external scheduler

Any idea is welcome :)

### Tools and links

- [certbot](https://github.com/certbot/certbot)
- [certbot-dns-ionos](https://github.com/helgeerbe/certbot-dns-ionos)
- [supercronic](https://github.com/aptible/supercronic)
- [doas](https://github.com/Duncaen/OpenDoas)

### Support

<a href="https://www.buymeacoffee.com/app/gianmarcomameli"> <img src="https://cdn.simpleicons.org/buymeacoffee" alt="buymeacoffe" height="32" /></a>
<a href="https://ko-fi.com/gianmarcomameli"> <img src="https://cdn.simpleicons.org/kofi" alt="kofi" height="32"/></a>
6 changes: 6 additions & 0 deletions buildkitd.toml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[registry."$CI_REGISTRY"]
ca=["$CA_PATH"]
[registry."$PRIVATE_REGISTRY"]
ca=["$CA_PATH"]
[registry."$HARBOR_HOST"]
ca=["$CA_PATH"]
6 changes: 6 additions & 0 deletions certbot_permissions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

# Set some permissions at startup
chown -R "${USERNAME}":"${USERNAME}" "${CERTBOT_BASE_DIR}"
chmod 755 "${CERTBOT_LIVE_DIR}"
chmod 755 "${CERTBOT_ARCHIVE_DIR}"
27 changes: 27 additions & 0 deletions certbot_script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh

# Check that IONOS_DOMAINS are populated
if env | grep -w IONOS_DOMAINS >/dev/null; then
DOMAINS=$(echo "${IONOS_DOMAINS}" | tr "," " ")
for domain in ${DOMAINS}; do
DOMAINS_ARGS=${DOMAINS_ARGS}" -d ${domain}"
done
else
echo "IONOS_DOMAINS env not set"
exit 10
fi

# Start certbot
/usr/local/bin/certbot certonly \
--config-dir "${CERTBOT_CONFIG_DIR}" \
--logs-dir "${CERTBOT_LOGS_DIR}" \
--work-dir "${CERTBOT_WORK_DIR}" \
--authenticator dns-ionos \
--dns-ionos-credentials "${IONOS_CREDENTIALS}" \
--dns-ionos-propagation-seconds "${IONOS_PROPAGATION}" \
--non-interactive \
--expand \
--agree-tos \
--email "${IONOS_EMAIL}" \
--rsa-key-size 4096 ${DOMAINS_ARGS}
# --server "${IONOS_SERVER}" \
25 changes: 25 additions & 0 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
variable "VERSION" {
default = ""
}

variable "CERTBOT_VERSION" {
default = ""
}

variable "REGISTRY_IMAGE" {
default = ""
}

variable "REGISTRY_IMAGE_PUBLIC" {
default = ""
}

target "default" {
dockerfile = "Dockerfile"
args = {
VERSION = "${VERSION}"
CERTBOT_VERSION = "${CERTBOT_VERSION}"
}
platforms = ["linux/amd64","linux/arm64","linux/arm/v7","linux/arm/v6"]
tags = ["${REGISTRY_IMAGE}:${VERSION}","${REGISTRY_IMAGE_PUBLIC}:${VERSION}"]
}
15 changes: 15 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: "3.8"
services:
certbot_ionos:
image: gmmserv/docker-certbot-dns-ionos:2024.1.8
volumes:
- "~/certbot:/certbot"
- "~/certbot/etc/letsencrypt/live:/certbot/etc/letsencrypt/live"
- "~/certbot/etc/letsencrypt/.secrets:/certbot/etc/letsencrypt/.secrets"
environment:
- TZ=Europe/Rome
- IONOS_CREDENTIALS=/certbot/etc/letsencrypt/.secrets/ionos.ini
- IONOS_CRONTAB=0 13 * * *
- IONOS_DOMAINS=test.ionos.io
- IONOS_PROPAGATION=300
- IONOS_EMAIL=test@test.com
14 changes: 14 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

# Set permissions
doas /certbot_permissions.sh

# Configure supercronic schedules
echo "${IONOS_CRONTAB} /certbot_script.sh" | tee -a "/tmp/crontabs/certbot" >/dev/null

# Some startup log
echo time=\""$(date -Is || true)"\"' level=info msg='\""docker-certbot-dns-ionos v${IONOS_VERSION} started"\"
echo time=\""$(date -Is || true)"\"' level=info msg='\""Starting $*"\"

#Start supercronic from image CMD
"$@"
5 changes: 5 additions & 0 deletions ionos.ini.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Instructions: https://github.com/helgeerbe/certbot-dns-ionos
# Replace with your values
dns_ionos_prefix = # ionos api prefix
dns_ionos_secret = # ionos api secret
dns_ionos_endpoint = # ionos api endpoint, ex. https://api.hosting.ionos.com

0 comments on commit 9e2649d

Please sign in to comment.