Add scripts to renew certs with certbot
This commit is contained in:
parent
707695d631
commit
cd24eacee4
11
README.md
11
README.md
@ -85,11 +85,11 @@ PORTAINER_PASSWORD=
|
||||
AI_OPENAI_API_KEY=
|
||||
```
|
||||
|
||||
3. Edit GoTrue Dockerfile
|
||||
3. Edit GoTrue Dockerfile (Not needed on latest version)
|
||||
|
||||
Modify the base Dockerfile from the Appflowy-Cloud repo to the one in this repo that installs bash, so the healthcheck can run.
|
||||
|
||||
4. Edit nginx.conf
|
||||
4. Edit nginx.conf (Not needed on latest version)
|
||||
|
||||
Modify the base nginx.conf to the version in this repo to resolve a potential websocket DNS resolution issue.
|
||||
|
||||
@ -140,13 +140,14 @@ docker-compose up -d
|
||||
10. Set up auto renewal for the certificates with cron job:
|
||||
|
||||
```bash
|
||||
sudo crontab -e
|
||||
crontab -e
|
||||
```
|
||||
Add this line to run the renewal daily (it will only renew if necessary):
|
||||
Add this line to run the renewal every month on the 1st day at 2:00 AM:
|
||||
|
||||
```bash
|
||||
0 3 * * * certbot renew --quiet --deploy-hook "docker-compose restart nginx"
|
||||
0 2 1 * * /home/moeny/AppFlowy-Cloud/check-and-renew-certs.sh >> /var/log/cert-renewal.log 2>&1
|
||||
```
|
||||
You will need to add [check-and-renew-certs.sh](check-and-renew-certs.sh) and [renew-certs.sh](renew-certs.sh) in the `AppFlowy-Cloud` directory.
|
||||
|
||||
## Additional considerations
|
||||
|
||||
|
49
check-and-renew-certs.sh
Normal file
49
check-and-renew-certs.sh
Normal file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Run this script with a cron job every month on the 1st day at 2:00 AM
|
||||
# crontab -e
|
||||
# 0 2 1 * * /home/moeny/AppFlowy-Cloud/check-and-renew-certs.sh >> /var/log/cert-renewal.log 2>&1
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
COMPOSE_FILE="/home/moeny/AppFlowy-Cloud/docker-compose.yml"
|
||||
DEPLOY_TRIGGER="/etc/letsencrypt/deploy-hook-triggered"
|
||||
|
||||
# Ensure we're in the right directory
|
||||
cd "$(dirname "$COMPOSE_FILE")"
|
||||
|
||||
# Set environment variables to ensure non-interactive operation
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
export PYTHONUNBUFFERED=1
|
||||
|
||||
# Run certbot container with explicit non-interactive settings and timeout
|
||||
echo "[$(date)] Starting certificate renewal check..."
|
||||
if timeout --signal=KILL 5m docker compose -f "$COMPOSE_FILE" run --rm \
|
||||
-e TERM=dumb \
|
||||
-e PYTHONUNBUFFERED=1 \
|
||||
--no-TTY \
|
||||
< /dev/null \
|
||||
certbot; then
|
||||
echo "[$(date)] Certbot completed successfully"
|
||||
else
|
||||
exit_code=$?
|
||||
if [ $exit_code -eq 137 ]; then # SIGKILL exit code
|
||||
echo "[$(date)] ERROR: Certbot timed out after 5 minutes, killing container..."
|
||||
# Find and kill any hanging certbot containers
|
||||
docker ps --filter "name=certbot" -q | xargs -r docker kill
|
||||
else
|
||||
echo "[$(date)] ERROR: Certbot failed with exit code $exit_code"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if certificates were renewed
|
||||
if [ -f "$DEPLOY_TRIGGER" ]; then
|
||||
echo "[$(date)] Certificates were renewed, restarting nginx..."
|
||||
docker compose -f "$COMPOSE_FILE" restart nginx
|
||||
sudo rm "$DEPLOY_TRIGGER"
|
||||
echo "[$(date)] Nginx restarted successfully"
|
||||
else
|
||||
echo "[$(date)] No certificate renewal needed"
|
||||
fi
|
@ -219,6 +219,21 @@ services:
|
||||
environment:
|
||||
- AF_BASE_URL=${APPFLOWY_BASE_URL:?err}
|
||||
- AF_GOTRUE_URL=${API_EXTERNAL_URL}
|
||||
|
||||
certbot:
|
||||
image: certbot/certbot
|
||||
volumes:
|
||||
- /etc/letsencrypt:/etc/letsencrypt
|
||||
- /var/lib/letsencrypt:/var/lib/letsencrypt
|
||||
- /home/moeny/AppFlowy-Cloud/renew-certs.sh:/renew-certs.sh
|
||||
- /home/moeny/keys/tsig.key:/tsig.key:ro
|
||||
environment:
|
||||
- BIND_SERVER=ns1.moeny.ai
|
||||
- DOMAIN=appflowy.moeny.ai
|
||||
- EMAIL=appflowy-certbot@moeny.ai
|
||||
- TSIG_KEY=/tsig.key
|
||||
entrypoint: sh /renew-certs.sh
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
86
renew-certs.sh
Normal file
86
renew-certs.sh
Normal file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Install required packages
|
||||
apk add --no-cache bind-tools
|
||||
|
||||
# Use environment variables with fallbacks
|
||||
DOMAIN=${DOMAIN:-"appflowy.moeny.ai"}
|
||||
EMAIL=${EMAIL:-"appflowy-certbot@moeny.ai"}
|
||||
BIND_SERVER=${BIND_SERVER:-"ns1.moeny.ai"}
|
||||
TSIG_KEY=${TSIG_KEY:-"/tsig.key"} # This will be the path inside the container
|
||||
CERTBOT_DIR="/etc/letsencrypt"
|
||||
|
||||
# Create the auth script with embedded functions
|
||||
cat > /tmp/auth.sh << 'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Function to add DNS challenge record
|
||||
domain="$CERTBOT_DOMAIN"
|
||||
token="$CERTBOT_VALIDATION"
|
||||
|
||||
echo "Adding DNS challenge for $domain with token $token"
|
||||
nsupdate -k "/tsig.key" << NSUPDATE
|
||||
server $BIND_SERVER
|
||||
update add _acme-challenge.$domain. 300 IN TXT "$token"
|
||||
send
|
||||
NSUPDATE
|
||||
|
||||
# Wait for DNS propagation
|
||||
echo "Waiting 30 seconds for DNS propagation..."
|
||||
sleep 30
|
||||
|
||||
# Verify the record
|
||||
echo "Verifying DNS record..."
|
||||
if dig +short @$BIND_SERVER TXT _acme-challenge.$domain | grep -q "$token"; then
|
||||
echo "DNS challenge record verified successfully"
|
||||
exit 0
|
||||
else
|
||||
echo "ERROR: DNS challenge record not found or incorrect"
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
chmod +x /tmp/auth.sh
|
||||
|
||||
# Create cleanup script with embedded function
|
||||
cat > /tmp/cleanup.sh << 'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
domain="$CERTBOT_DOMAIN"
|
||||
echo "Removing DNS challenge for $domain"
|
||||
nsupdate -k "/tsig.key" << NSUPDATE
|
||||
server $BIND_SERVER
|
||||
update delete _acme-challenge.$domain. TXT
|
||||
send
|
||||
NSUPDATE
|
||||
EOF
|
||||
chmod +x /tmp/cleanup.sh
|
||||
|
||||
# Check if certificate already exists
|
||||
if [ -d "/etc/letsencrypt/live/$DOMAIN" ]; then
|
||||
echo "Certificate exists, attempting renewal..."
|
||||
certbot renew \
|
||||
--manual \
|
||||
--preferred-challenges dns \
|
||||
--manual-auth-hook /tmp/auth.sh \
|
||||
--manual-cleanup-hook /tmp/cleanup.sh \
|
||||
--deploy-hook "touch /etc/letsencrypt/deploy-hook-triggered" \
|
||||
--force-renewal
|
||||
else
|
||||
echo "No certificate found, performing initial certificate request..."
|
||||
certbot certonly \
|
||||
--manual \
|
||||
--preferred-challenges dns \
|
||||
--manual-auth-hook /tmp/auth.sh \
|
||||
--manual-cleanup-hook /tmp/cleanup.sh \
|
||||
--deploy-hook "touch /etc/letsencrypt/deploy-hook-triggered" \
|
||||
-d "$DOMAIN" \
|
||||
--email "$EMAIL" \
|
||||
--agree-tos \
|
||||
--non-interactive
|
||||
fi
|
||||
|
||||
# Clean up temporary scripts
|
||||
rm -f /tmp/auth.sh /tmp/cleanup.sh
|
||||
|
||||
echo "Certificate operation completed. Check /etc/letsencrypt/deploy-hook-triggered for successful deployment."
|
Loading…
Reference in New Issue
Block a user