Tool for encrypting and syncing certificates via S3 with automatic renewal support using LEGO.
1. Install the package:
# Detect architecture
ARCH="$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
# Debian/Ubuntu
PACKAGE="$(curl -s "https://api.github.com/repos/digilolnet/digilol-cert-pushpuller/releases/latest" | grep -oP "\"browser_download_url\": \"\K[^\"]*linux_${ARCH}\.deb")"
curl -LO "$PACKAGE"
sudo dpkg -i "$(basename "$PACKAGE")"
# RHEL/Fedora/CentOS
PACKAGE="$(curl -s "https://api.github.com/repos/digilolnet/digilol-cert-pushpuller/releases/latest" | grep -oP "\"browser_download_url\": \"\K[^\"]*linux_${ARCH}\.rpm")"
curl -LO "$PACKAGE"
sudo rpm -i "$(basename "$PACKAGE")"
# Alpine Linux
PACKAGE="$(curl -s "https://api.github.com/repos/digilolnet/digilol-cert-pushpuller/releases/latest" | grep -oP "\"browser_download_url\": \"\K[^\"]*linux_${ARCH}\.apk")"
curl -LO "$PACKAGE"
sudo apk add --allow-untrusted "$(basename "$PACKAGE")"
# Or download binary archive for any OS
PACKAGE="$(curl -s "https://api.github.com/repos/digilolnet/digilol-cert-pushpuller/releases/latest" | grep -oP "\"browser_download_url\": \"\K[^\"]*linux_${ARCH}\.tar\.gz")"
curl -LO "$PACKAGE"
tar xzf "$(basename "$PACKAGE")" digilol-cert-pushpuller
sudo mv digilol-cert-pushpuller /usr/local/bin/
2. Configure:
For push (server), edit /etc/digilol-cert-pushpuller/push.toml
:
key_dir = "/var/lib/digilol-cert-pushpuller/keys"
cert_dir = ".lego/certificates"
reload_cmd = "systemctl reload nginx"
[daemon]
enabled = false
interval_secs = 86400
jitter_secs = 3600
[s3]
bucket = "my-certificates-bucket"
endpoint = "https://s3.example.com"
region = "us-east-1"
prefix = ""
force_path_style = true
access_key = "your-s3-access-key"
secret_key = "your-s3-secret-key"
[[lego_commands]]
command = "lego -d '*.example.com' -d example.com -a -m [email protected] --dns cloudflare renew"
[lego_commands.env]
CF_DNS_API_TOKEN = "your-cloudflare-token"
[[lego_commands]]
command = "lego -d '*.example.net' -d example.net -s https://acme.zerossl.com/v2/DV90 -a -m [email protected] --eab --kid your-eab-kid --hmac your-eab-hmac --dns bunny renew"
[lego_commands.env]
BUNNY_API_KEY = "your-bunny-api-key"
For pull (client), edit /etc/digilol-cert-pushpuller/pull.toml
:
key_dir = "/var/lib/digilol-cert-pushpuller/keys"
cert_dir = "/var/lib/digilol-cert-pushpuller/certificates"
reload_cmd = "systemctl reload nginx"
[daemon]
enabled = false
interval_secs = 300
jitter_secs = 0
[s3]
bucket = "my-certificates-bucket"
endpoint = "https://s3.example.com"
region = "us-east-1"
prefix = ""
force_path_style = true
access_key = "your-s3-access-key"
secret_key = "your-s3-secret-key"
3. Enable services:
# Debian/Ubuntu/RHEL/Fedora (systemd)
sudo systemctl enable --now digilol-cert-pushpuller-push.timer # For server (push)
sudo systemctl enable --now digilol-cert-pushpuller-pull.timer # For client (pull)
# Alpine Linux (OpenRC)
sudo rc-update add digilol-cert-pushpuller-push default
sudo rc-update add digilol-cert-pushpuller-pull default
sudo rc-service digilol-cert-pushpuller-push start
sudo rc-service digilol-cert-pushpuller-pull start
Done! The server will renew and push certificates daily (with 1h random delay), clients will pull every 5 minutes.
Note: Supports Linux, macOS, and FreeBSD. Packages available for Debian, Ubuntu, RHEL, Fedora, CentOS, and Alpine Linux.
Daemon Mode: On Alpine Linux or systems without systemd timers, you can enable daemon mode by setting daemon.enabled = true
in the config file. The tool will run continuously with built-in scheduling instead of relying on external cron/timer systems.
See push.example.toml and pull.example.toml for complete examples.
Push config fields:
key_dir
: Directory for encryption keyscert_dir
: Directory containing certificates to pushlego_commands
: Array of lego renewal commands (optional)reload_cmd
: Command to run after push (optional)daemon.enabled
: Enable daemon mode (default: false)daemon.interval_secs
: Seconds between runs (default: 86400 for push)daemon.jitter_secs
: Random delay in seconds (default: 3600 for push)s3.bucket
: S3 bucket names3.region
: S3 regions3.access_key
: S3 access keys3.secret_key
: S3 secret keys3.endpoint
: S3 endpoint URLs3.prefix
: S3 key prefix/folder (optional)s3.force_path_style
: Use path-style URLs (required for most S3-compatible services)
Pull config fields:
key_dir
: Directory for encryption keyscert_dir
: Directory to store pulled certificatesreload_cmd
: Command to run after pull (optional)daemon.enabled
: Enable daemon mode (default: false)daemon.interval_secs
: Seconds between runs (default: 300 for pull)daemon.jitter_secs
: Random delay in seconds (default: 0 for pull)s3.bucket
: S3 bucket names3.region
: S3 regions3.access_key
: S3 access keys3.secret_key
: S3 secret keys3.endpoint
: S3 endpoint URLs3.prefix
: S3 key prefix/folder (optional)s3.force_path_style
: Use path-style URLs (required for most S3-compatible services)
Push (server):
- Runs lego commands to renew certificates
- Calculates SHA256 checksum of each certificate file
- Compares with
.hashes.json
in S3 to skip unchanged files - Encrypts changed certificates with unique keys
- Uploads encrypted
.enc
files to S3 - Updates
.hashes.json
in S3 - Runs reload command
Pull (client):
- Downloads
.hashes.json
from S3 - Lists
.enc
files in S3 - For each file, checks if local file exists and compares SHA256 checksum
- Skips download if checksum matches (file unchanged)
- Downloads and decrypts only changed files (and only if local encryption key exists)
- Runs reload command
Security:
- Each certificate domain has a unique 256-bit encryption key (per-certificate encryption allows selective access: clients can only decrypt certificates for which they have the corresponding key file)
- Keys stored as raw 32-byte
.key
files with 0600 permissions - Encryption: ChaCha20-Poly1305 via
github.com/minio/sio
- Clients only pull and decrypt certificates for which they have the key files
# Push certificates
digilol-cert-pushpuller push --config /etc/digilol-cert-pushpuller/push.toml
# Pull certificates
digilol-cert-pushpuller pull --config /etc/digilol-cert-pushpuller/pull.toml
go build -trimpath -ldflags="-s -w"
Apache License 2.0 - see LICENSE.txt