Add fullchain PEM support and improve permissions handling

The changes add support for combining certificates and private keys into a
single PEM file, while also refactoring the permissions handling logic to
be more robust and consistent.
This commit is contained in:
Ruben Solvang 2025-04-08 14:59:21 +02:00
parent f73342e8ae
commit e526c98d37
2 changed files with 37 additions and 6 deletions

View file

@ -96,6 +96,11 @@ Flags can be combined:
./certman.sh --silent --force ./certman.sh --silent --force
``` ```
### Fullchain PEM
Use the `--fullchain-pem` flag to combine certificate and private key into a single PEM file:
```bash
./certman.sh --fullchain-pem
### Cron Configuration ### Cron Configuration
Add these lines to your crontab for automated certificate management: Add these lines to your crontab for automated certificate management:
```cron ```cron
@ -111,6 +116,7 @@ Add these lines to your crontab for automated certificate management:
| CERT_PATH | Directory for certificate storage | Yes | | CERT_PATH | Directory for certificate storage | Yes |
| KEY_PATH | Directory for private key storage | Yes | | KEY_PATH | Directory for private key storage | Yes |
| TEMP_PATH | Temporary directory for downloads | Yes | | TEMP_PATH | Temporary directory for downloads | Yes |
| FULLCHAIN_PEM | Optional: Combine cert and key into single PEM file | No |
| SERVICE_NAME | Service to reload after certificate updates | Yes | | SERVICE_NAME | Service to reload after certificate updates | Yes |
| CERT_OWNER | User owner for certificate files | Yes | | CERT_OWNER | User owner for certificate files | Yes |
| CERT_GROUP | Group owner for certificate files | Yes | | CERT_GROUP | Group owner for certificate files | Yes |

View file

@ -26,6 +26,8 @@ load_env || exit 1
AUTO_MODE="false" AUTO_MODE="false"
FORCE_UPDATE="false" FORCE_UPDATE="false"
FULLCHAIN_PEM="${FULLCHAIN_PEM:-false}"
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case $1 in case $1 in
--silent) --silent)
@ -36,6 +38,10 @@ while [[ $# -gt 0 ]]; do
FORCE_UPDATE="true" FORCE_UPDATE="true"
shift shift
;; ;;
--fullchain-pem)
FULLCHAIN_PEM="true"
shift
;;
*) *)
shift shift
;; ;;
@ -81,6 +87,7 @@ download_and_verify_cert() {
local key_api_key=$3 local key_api_key=$3
local temp_cert="$TEMP_DIR/$domain.crt" local temp_cert="$TEMP_DIR/$domain.crt"
local temp_key="$TEMP_DIR/$domain.key" local temp_key="$TEMP_DIR/$domain.key"
local temp_fullchain="$TEMP_DIR/$domain.pem"
echo -e "${BLUE}Processing certificate for $domain${NC}" echo -e "${BLUE}Processing certificate for $domain${NC}"
@ -104,6 +111,11 @@ download_and_verify_cert() {
return 1 return 1
fi fi
# Create fullchain PEM if requested
if [ "$FULLCHAIN_PEM" = "true" ]; then
cat "$temp_cert" "$temp_key" > "$temp_fullchain"
fi
# Validate certificate and key match # Validate certificate and key match
local cert_fingerprint local cert_fingerprint
cert_fingerprint=$(openssl x509 -in "$temp_cert" -noout -pubkey | cert_fingerprint=$(openssl x509 -in "$temp_cert" -noout -pubkey |
@ -125,8 +137,10 @@ install_certificate() {
local domain=$1 local domain=$1
local final_cert="$CERT_PATH/$domain.crt" local final_cert="$CERT_PATH/$domain.crt"
local final_key="$KEY_PATH/$domain.key" local final_key="$KEY_PATH/$domain.key"
local final_fullchain="$CERT_PATH/$domain.pem"
local temp_cert="$TEMP_DIR/$domain.crt" local temp_cert="$TEMP_DIR/$domain.crt"
local temp_key="$TEMP_DIR/$domain.key" local temp_key="$TEMP_DIR/$domain.key"
local temp_fullchain="$TEMP_DIR/$domain.pem"
local needs_reload=0 local needs_reload=0
# Check if certificate needs updating # Check if certificate needs updating
@ -147,13 +161,24 @@ install_certificate() {
return 1 return 1
fi fi
# Set permissions and ownership if [ "$FULLCHAIN_PEM" = "true" ]; then
if ! chown "$CERT_OWNER:$CERT_GROUP" "$final_cert" "$final_key" || \ if ! cp -f "$temp_fullchain" "$final_fullchain"; then
! chmod "$CERT_PERMISSIONS" "$final_cert" || \ echo -e "${RED}Failed to install fullchain PEM for $domain${NC}"
! chmod "$KEY_PERMISSIONS" "$final_key"; then
echo -e "${RED}Failed to set permissions for $domain${NC}"
return 1 return 1
fi fi
fi
# Set permissions and ownership
local files=("$final_cert" "$final_key")
[ "$FULLCHAIN_PEM" = "true" ] && files+=("$final_fullchain")
for file in "${files[@]}"; do
if ! chown "$CERT_OWNER:$CERT_GROUP" "$file" || \
! chmod "$CERT_PERMISSIONS" "$file"; then
echo -e "${RED}Failed to set permissions for $file${NC}"
return 1
fi
done
echo -e "${GREEN}Certificate updated for $domain${NC}" echo -e "${GREEN}Certificate updated for $domain${NC}"
return 0 return 0