Browse Source

add hooks for lego certificate renewal + self-signed certificate generation when in dev mode

main
Nicolas Massé 2 weeks ago
parent
commit
eff4d8be98
  1. 3
      cookbooks/lego/Makefile
  2. 2
      cookbooks/lego/config/examples/config.env
  3. 19
      cookbooks/lego/config/examples/lego-dev.sh
  4. 18
      cookbooks/lego/config/process-hooks.sh
  5. 0
      cookbooks/lego/config/renew-hook/flag-as-renewed.sh
  6. 7
      cookbooks/lego/dropins/lego-renew.container.d/lego-dev.conf
  7. 7
      cookbooks/lego/dropins/lego-run.container.d/lego-dev.conf
  8. 5
      cookbooks/lego/hooks.mk
  9. 12
      cookbooks/lego/lego-renew-hooks.service
  10. 2
      cookbooks/lego/lego-renew.container
  11. 12
      cookbooks/quay/config/quay_load_tls_certs.sh
  12. 6
      cookbooks/quay/other/lego/quay.sh
  13. 9
      cookbooks/quay/quay-app.container
  14. 15
      cookbooks/quay/quay-init-certificate.service
  15. 17
      cookbooks/quay/quay-load-renewed-certificate.service
  16. 4
      cookbooks/quay/quay.target
  17. 6
      cookbooks/vsftpd/other/lego/vsftpd.sh
  18. 17
      cookbooks/vsftpd/vsftpd-load-renewed-certificate.service

3
cookbooks/lego/Makefile

@ -9,3 +9,6 @@ PROJECT_GID = 10000
# Include common Makefile # Include common Makefile
include ../../scripts/common.mk include ../../scripts/common.mk
TARGET_FILES += $(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d
$(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d:
install -m 0700 -o root -g root -D -d $@

2
cookbooks/lego/config/examples/config.env

@ -1,3 +1,3 @@
LEGO_GLOBAL_ARGS=-a -m nicolas.masse@itix.fr -d changeme.example.tld --http LEGO_GLOBAL_ARGS=-a -m nicolas.masse@itix.fr -d changeme.example.tld --http
LEGO_RUN_ARGS= LEGO_RUN_ARGS=
LEGO_RENEW_ARGS=--days 30 --renew-hook=/etc/lego/hooks/flag-as-renewed.sh LEGO_RENEW_ARGS=--days 30 --renew-hook=/etc/lego/renew-hook/flag-as-renewed.sh

19
cookbooks/lego/config/examples/lego-dev.sh

@ -0,0 +1,19 @@
#!/bin/bash
set -Eeuo pipefail
# In development mode, it is not possible to get a certificate from Let's Encrypt, so we just create a self-signed certificate for localhost, so that other services can still use it.
mkdir -p /var/lib/quadlets/lego/certificates
if [ -f /var/lib/quadlets/lego/certificates/localhost.crt ] && [ -f /var/lib/quadlets/lego/certificates/localhost.key ]; then
renewal="yes"
else
renewal="no"
fi
echo "Generating self-signed certificate for localhost..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /var/lib/quadlets/lego/certificates/localhost.key -out /var/lib/quadlets/lego/certificates/localhost.crt -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"
if [[ "$renewal" == "yes" ]]; then
echo "Flagging certificate as renewed..."
touch /var/lib/quadlets/lego/certificates/localhost.renewed
fi

18
cookbooks/lego/config/process-hooks.sh

@ -0,0 +1,18 @@
#!/bin/bash
set -Eeuo pipefail
for hook in /etc/quadlets/lego/renew-hooks.d/*.sh; do
if [[ -x "$hook" ]]; then
echo "Running renew hook: $hook"
if ! "$hook"; then
echo "Error: Renew hook failed: $hook" >&2
fi
else
echo "Skipping non-executable hook: $hook"
fi
done
rm -f /var/lib/quadlets/lego/certificates/*.renewed
exit 0

0
cookbooks/lego/config/hooks/flag-as-renewed.sh → cookbooks/lego/config/renew-hook/flag-as-renewed.sh

7
cookbooks/lego/dropins/lego-renew.container.d/lego-dev.conf

@ -0,0 +1,7 @@
[Container]
# When in development mode, it is not possible to renew a certificate from Let's Encrypt, so we just skip the entrypoint.
Entrypoint=/bin/true
[Service]
# And we update the self-signed certificate and flag it as renewed.
ExecStartPost=/etc/quadlets/lego/lego-dev.sh

7
cookbooks/lego/dropins/lego-run.container.d/lego-dev.conf

@ -0,0 +1,7 @@
[Container]
# When in development mode, it is not possible to get a certificate from Let's Encrypt, so we just skip the entrypoint.
Entrypoint=/bin/true
[Service]
# And we create a self-signed certificate for localhost, so that other services can still use it.
ExecStartPost=/etc/quadlets/lego/lego-dev.sh

5
cookbooks/lego/hooks.mk

@ -0,0 +1,5 @@
# Lego renewal hooks
TARGET_LEGO_FILES = $(patsubst other/lego/%.sh, $(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d/%.sh, $(wildcard other/lego/*.sh))
TARGET_EXAMPLE_FILES += $(TARGET_LEGO_FILES)
$(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d/%.sh: other/lego/%.sh
install -D -m 0755 -o root -g root $< $@

12
cookbooks/lego/lego-renew-hooks.service

@ -0,0 +1,12 @@
[Unit]
Description=Process Lego certificate renewal hooks
# Lego touches .renewed files when renewed certificates are available
ConditionPathExistsGlob=/var/lib/quadlets/lego/certificates/*.renewed
After=lego-renew.service
[Service]
Type=oneshot
ExecStart=/etc/quadlets/lego/process-hooks.sh
[Install]
WantedBy=lego-renew.service

2
cookbooks/lego/lego-renew.container

@ -27,7 +27,7 @@ EnvironmentFile=/etc/quadlets/lego/config.env
# Volume mounts # Volume mounts
Volume=/var/lib/quadlets/lego:/.lego:z Volume=/var/lib/quadlets/lego:/.lego:z
Volume=/etc/quadlets/lego/hooks:/etc/lego/hooks:ro Volume=/etc/quadlets/lego/renew-hook:/etc/lego/renew-hook:ro
# Be safe, set the umask to 0077 so that private keys are not world-readable # Be safe, set the umask to 0077 so that private keys are not world-readable
PodmanArgs=--umask=0077 PodmanArgs=--umask=0077

12
cookbooks/quay/config/quay_load_tls_certs.sh

@ -2,13 +2,5 @@
set -Eeuo pipefail set -Eeuo pipefail
if ls /var/lib/quadlets/lego/certificates/*.crt &> /dev/null; then install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.crt | head -1) /run/quadlets/quay/tls/ssl.cert
echo "Lego-issued certificates found, loading them for Quay..." install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.key | head -1) /run/quadlets/quay/tls/ssl.key
install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.crt | head -1) /etc/quadlets/quay/app/ssl.cert
install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.key | head -1) /etc/quadlets/quay/app/ssl.key
elif [ ! -f /etc/quadlets/quay/app/ssl.cert ] && [ ! -f /etc/quadlets/quay/app/ssl.key ]; then
echo "No Lego-issued certificates found, generating self-signed certificates for Quay..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/quadlets/quay/app/ssl.key -out /etc/quadlets/quay/app/ssl.cert -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"
chown 10026:10000 /etc/quadlets/quay/app/ssl.{key,cert}
chmod 0600 /etc/quadlets/quay/app/ssl.{key,cert}
fi

6
cookbooks/quay/other/lego/quay.sh

@ -0,0 +1,6 @@
#!/bin/bash
set -Eeuo pipefail
/etc/quadlets/quay/quay_load_tls_certs.sh
systemctl --no-block restart quay-app.service

9
cookbooks/quay/quay-app.container

@ -1,8 +1,8 @@
[Unit] [Unit]
Description=Quay Container Registry Application Description=Quay Container Registry Application
Documentation=https://docs.projectquay.io/ Documentation=https://docs.projectquay.io/
After=network.target redis-server.service quay-init-certificate.service var-lib-virtiofs-data.mount After=network.target redis-server.service var-lib-virtiofs-data.mount
Requires=redis-server.service quay-init-certificate.service var-lib-virtiofs-data.mount Requires=redis-server.service var-lib-virtiofs-data.mount
# Only start if Quay has been configured # Only start if Quay has been configured
ConditionPathExists=/etc/quadlets/quay/app/config.yaml ConditionPathExists=/etc/quadlets/quay/app/config.yaml
@ -32,6 +32,8 @@ Volume=/var/lib/virtiofs/data/quay/storage:/datastorage:Z
# Configuration # Configuration
Volume=/etc/quadlets/quay/app:/quay-registry/conf/stack:Z,ro Volume=/etc/quadlets/quay/app:/quay-registry/conf/stack:Z,ro
Volume=/run/quadlets/quay/tls/ssl.cert:/quay-registry/conf/stack/ssl.cert:Z,ro
Volume=/run/quadlets/quay/tls/ssl.key:/quay-registry/conf/stack/ssl.key:Z,ro
# Health check # Health check
HealthCmd=curl -sk https://localhost:8443/health/instance HealthCmd=curl -sk https://localhost:8443/health/instance
@ -46,6 +48,9 @@ RestartSec=10
TimeoutStartSec=120 TimeoutStartSec=120
TimeoutStopSec=30 TimeoutStopSec=30
# Load TLS certificates from Lego before starting the container
ExecStartPre=/etc/quadlets/quay/quay_load_tls_certs.sh
# Wait for PostgreSQL to be ready on localhost # Wait for PostgreSQL to be ready on localhost
ExecStartPre=/bin/sh -c 'exec 2>/dev/null; for try in $(seq 0 12); do if ! /bin/true 5<> /dev/tcp/127.0.0.1/5432; then echo "Waiting for PostgreSQL to be available..."; sleep 5; else exit 0; fi; done; exit 1' ExecStartPre=/bin/sh -c 'exec 2>/dev/null; for try in $(seq 0 12); do if ! /bin/true 5<> /dev/tcp/127.0.0.1/5432; then echo "Waiting for PostgreSQL to be available..."; sleep 5; else exit 0; fi; done; exit 1'

15
cookbooks/quay/quay-init-certificate.service

@ -1,15 +0,0 @@
[Unit]
Description=Initialize Quay TLS certificates if not already present
Before=quay-app.service
After=lego.target
# Start/stop this unit when the target is started/stopped
PartOf=quay.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/etc/quadlets/quay/quay_load_tls_certs.sh
[Install]
WantedBy=quay.target

17
cookbooks/quay/quay-load-renewed-certificate.service

@ -1,17 +0,0 @@
[Unit]
Description=Reload Quay TLS certificate after Lego renewal
# Lego touches .renewed files when renewed certificates are available
ConditionPathExistsGlob=/var/lib/quadlets/lego/certificates/*.renewed
After=lego-renew.service
[Service]
Type=oneshot
# Copy the renewed certificates to the Quay TLS directory
ExecStart=/etc/quadlets/quay/quay_load_tls_certs.sh
# Restart Quay to load the new certificate
ExecStart=systemctl --no-block restart quay-app.service
# Remove the flag files after restarting Quay
ExecStartPost=/bin/sh -Eeuo pipefail -c 'rm -f /var/lib/quadlets/lego/certificates/*.renewed'
[Install]
WantedBy=lego-renew.service

4
cookbooks/quay/quay.target

@ -1,8 +1,8 @@
[Unit] [Unit]
Description=Quay Container Registry Target Description=Quay Container Registry Target
Documentation=https://docs.projectquay.io/ Documentation=https://docs.projectquay.io/
Requires=postgresql.target redis.target quay-clair.service quay-app.service quay-init-certificate.service Requires=postgresql.target redis.target lego.target quay-clair.service quay-app.service
After=postgresql.target redis.target quay-clair.service quay-app.service quay-init-certificate.service After=postgresql.target redis.target lego.target quay-clair.service quay-app.service
# Allow isolation - can stop/start this target independently # Allow isolation - can stop/start this target independently
AllowIsolate=yes AllowIsolate=yes

6
cookbooks/vsftpd/other/lego/vsftpd.sh

@ -0,0 +1,6 @@
#!/bin/bash
set -Eeuo pipefail
install -o 10015 -g 10000 -m 0600 -t /run/quadlets/vsftpd/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key
systemctl --no-block restart vsftpd.service

17
cookbooks/vsftpd/vsftpd-load-renewed-certificate.service

@ -1,17 +0,0 @@
[Unit]
Description=Restart Vsftpd if a new TLS certificate is available
# Lego touch .renewed files when renewed certificates are available
ConditionPathExistsGlob=/var/lib/quadlets/lego/certificates/*.renewed
After=lego-renew.service
[Service]
Type=oneshot
# Copy the renewed certificates to the vsftpd /run directory
ExecStartPre=/bin/sh -Eeuo pipefail -c 'install -o 10015 -g 10000 -m 0600 -t /run/quadlets/vsftpd/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key'
# Restart vsftpd to load the new certificates
ExecStart=systemctl --no-block restart vsftpd.service
# Remove the flag files after restarting vsftpd
ExecStartPost=/bin/sh -Eeuo pipefail -c 'rm -f /var/lib/quadlets/lego/certificates/*.renewed'
[Install]
WantedBy=lego-renew.service
Loading…
Cancel
Save