Fix HestiaCP Certificate Renewal Failure (v-update-letsencrypt-ssl errors): Patch v-generate-ssl-cert for OpenSSL 3.x Compatibility

If you run into an error while renewing a certificate with v-update-letsencrypt-ssl, modify v-generate-ssl-cert and try again.

v-generate-ssl-cert script (full English version)

#!/bin/bash
# info: generate self signed certificate and CSR request
# options: DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT] [KEY_ALGO]
#
# example: v-generate-ssl-cert example.com [email protected] USA California Monterey ACME.COM IT
#
# This function generates self signed SSL certificate and CSR request

#----------------------------------------------------------#
#                Variables & Functions                     #
#----------------------------------------------------------#

# Argument definition
domain=$1
domain=$(echo "$domain" | sed -e 's/\.*$//g' -e 's/^\.*//g')
domain_alias=$domain
email=$2
country=$3
state=$4
city=$5
org=$6
org_unit=$7
aliases=$8
format=${9-shell}
# Key algorithm: ecdsa-256 (default) | ecdsa-384 | rsa
key_algo="${10:-ecdsa-256}"
key_algo="${key_algo,,}"

# Set curve based on key_algo
if [ "$key_algo" = 'ecdsa-256' ]; then
	ec_curve='prime256v1'
elif [ "$key_algo" = 'ecdsa-384' ]; then
	ec_curve='secp384r1'
fi

KEY_SIZE=4096
DAYS=365

# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
source /etc/hestiacp/hestia.conf
# shellcheck source=/usr/local/hestia/func/main.sh
source $HESTIA/func/main.sh
# load config file
source_conf "$HESTIA/conf/hestia.conf"

# JSON function
json_list_ssl() {
	jq -n \
		--arg domain "$domain" \
		--arg crt "$crt" \
		--arg key "$key" \
		--arg csr "$csr" \
		--arg dir "$workdir" \
		'{
            ($domain): {
                CRT: $crt,
                KEY: $key,
                CSR: $csr,
                DIR: $dir
            }
        }'
}
# Shell function
shell_list_ssl() {
	if [ -n "$crt" ]; then
		printf '%s\n' "$crt"
	fi

	if [ -n "$key" ]; then
		printf '\n%s\n' "$key"
	fi

	if [ -n "$csr" ]; then
		printf '\n%s\n' "$csr"
	fi

	printf '\nDirectory: %s\n' "$workdir"
}

# Additional argument formatting
format_domain_idn
if [[ "$email" = *[![:ascii:]]* ]]; then
	local=$(echo "$email" | cut -f1 -d'@')
	email_domain=$(echo "$email" | cut -f2 -d'@')
	email_domain_idn=$(idn2 --quiet $email_domain)
	email="$local"@"$email_domain_idn"
fi

#----------------------------------------------------------#
#                    Verifications                         #
#----------------------------------------------------------#

args_usage='DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT] [KEY_ALGO]'
check_args '7' "$#" "$args_usage"
is_format_valid 'domain' 'aliases' 'format' 'email' 'key_algo'
is_common_format_valid "$country" "country"
is_common_format_spaces_valid "$state" "state"
is_common_format_spaces_valid "$org" "org"
is_common_format_spaces_valid "$unit" "unit"

release="$(lsb_release -s -r)"

if [ -z "$email" ] && [ "$release" = "18.04" ]; then
	echo "Email address is required"
	exit 2
fi
if [ ! -f /root/.rnd ]; then
	touch /root/.rnd
fi

# Perform verification if read-only mode is enabled
check_hestia_demo_mode

#----------------------------------------------------------#
#                       Action                             #
#----------------------------------------------------------#

# Create temporary work directory
workdir=$(mktemp -d)
cd $workdir

# Generate private key
if [[ "$key_algo" = "ecdsa-256" || "$key_algo" = "ecdsa-384" ]]; then
	openssl ecparam -name "$ec_curve" -genkey -noout -out "$domain.key" 2> /dev/null
else
	openssl genrsa "$KEY_SIZE" > "$domain.key" 2> /dev/null
fi

subj=""
# Generate the CSR
if [ -n "$email" ]; then
	subj="/emailAddress=$email"
fi

subj="$subj/C=$country/ST=$state/L=$city/O=$org"
subj="$subj/OU=$org_unit"

# The CN (CommonName) has an ASN.1 limit of 64 characters in OpenSSL.
# If the domain exceeds this limit, the CN is omitted and only the SAN
# (subjectAltName) is trusted, which is what modern browsers validate.
if [ ${#domain_idn} -le 64 ]; then
	subj="$subj/CN=$domain_idn"
fi

if [ -e "/etc/ssl/openssl.cnf" ]; then
	ssl_conf='/etc/ssl/openssl.cnf'
else
	ssl_conf="/etc/pki/tls/openssl.cnf"
fi

if [ -z "$aliases" ]; then
	cat > "$workdir/openssl-san.cnf" <<EOF
[ req ]
distinguished_name = req_distinguished_name
req_extensions = SAN
prompt = no

[ req_distinguished_name ]
CN = $domain_idn

[ SAN ]
subjectAltName = DNS:$domain
EOF
	openssl req -sha256 -new \
		-batch \
		-subj "$subj" \
		-key $domain.key \
		-config "$workdir/openssl-san.cnf" \
		-out $domain.csr
else
	for alias in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
		if [[ "$alias" = *[![:ascii:]]* ]]; then
			alias=$(idn2 --quiet $alias)
		fi
		dns_aliases="${dns_aliases}DNS:$alias,"
	done
	dns_aliases=$(echo $dns_aliases | sed "s/,$//")
	cat > "$workdir/openssl-san.cnf" <<EOF
[ req ]
distinguished_name = req_distinguished_name
req_extensions = SAN
prompt = no

[ req_distinguished_name ]
CN = $domain_idn

[ SAN ]
subjectAltName = $dns_aliases
EOF
	openssl req -sha256 -new \
		-batch \
		-subj "$subj" \
		-key $domain.key \
		-config "$workdir/openssl-san.cnf" \
		-out $domain.csr
fi

# Generate the certificate for 1 year
# >>> FIX: Same as above - use a standalone temp config file instead of
# >>> `-extfile <(printf ...)`. OpenSSL 3.x rejects process substitution here too.
if [ -z "$aliases" ]; then
	cat > "$workdir/openssl-ext.cnf" <<EOF
[SAN]
subjectAltName = DNS:$domain
EOF
	openssl x509 -req -sha256 \
		-days $DAYS \
		-in $domain.csr \
		-signkey $domain.key \
		-extfile "$workdir/openssl-ext.cnf" \
		-extensions SAN \
		-out $domain.crt
else
	cat > "$workdir/openssl-ext.cnf" <<EOF
[SAN]
subjectAltName = $dns_aliases
EOF
	openssl x509 -req -sha256 \
		-days $DAYS \
		-in $domain.csr \
		-signkey $domain.key \
		-extfile "$workdir/openssl-ext.cnf" \
		-extensions SAN \
		-out $domain.crt
fi

# Listing certificates
if [ -e "$domain.crt" ]; then
	crt=$(< "$domain.crt")
fi

if [ -e "$domain.key" ]; then
	key=$(< "$domain.key")
fi

if [ -e "$domain.csr" ]; then
	csr=$(< "$domain.csr")
fi

case $format in
	json) json_list_ssl ;;
	plain | shell) shell_list_ssl ;;
	*) check_args '1' '0' '[FORMAT]' ;;
esac

# Don't allow non-root users to view the folder
chmod 660 $workdir
# Clean up the mess
echo "rm -rf $workdir" | at -M "now +15 minute" > /dev/null 2>&1
# Delete tmp dir
#rm -rf $workdir

#----------------------------------------------------------#
#                       Hestia                             #
#----------------------------------------------------------#

# Logging
log_event "$OK" "$ARGUMENTS"

exit

Use it to check the current LETSENCRYPT_FAIL_COUNT

Use the following to check the current LETSENCRYPT_FAIL_COUNT for each domain. Once it exceeds 31, v-update-letsencrypt-ssl will skip issuing the certificate.

for conf in /usr/local/hestia/data/users/*/web.conf; do
    [ -f "$conf" ] || continue
    user=$(echo "$conf" | sed -E 's#.*/users/([^/]+)/web.conf#\1#')
    grep -o "DOMAIN='[^']*'\|LETSENCRYPT_FAIL_COUNT='[^']*'" "$conf" | \
      paste - - | awk -v u="$user" '{printf "%-8s %-30s %s\n", u, $1, $2}'
done

This command can reset the counter

This command resets the fail counter.

for conf in /usr/local/hestia/data/users/*/web.conf; do
    [ -f "$conf" ] || continue
    echo "===== $conf ====="
    echo "--- Before reset ---"
    grep -o "DOMAIN='[^']*'\|LETSENCRYPT_FAIL_COUNT='[^']*'" "$conf" | paste - -
    sed -i "s/LETSENCRYPT_FAIL_COUNT='[0-9]*'/LETSENCRYPT_FAIL_COUNT='0'/g" "$conf"
    echo "--- After reset ---"
    grep -o "DOMAIN='[^']*'\|LETSENCRYPT_FAIL_COUNT='[^']*'" "$conf" | paste - -
done

Short summary

If certificate renewal via v-update-letsencrypt-ssl fails, patch v-generate-ssl-cert (the OpenSSL 3.x process-substitution fix shown above) and retry. Use the first loop to inspect each domain’s current LETSENCRYPT_FAIL_COUNT; once it exceeds 31, HestiaCP will skip issuing the certificate. Use the second loop to reset the counter back to 0 so the next renewal attempt is allowed.

:pushpin: PR submitted: #5831 — fixes OpenSSL 3.x compatibility in v-generate-ssl-cert. Use the manual patch below until merged.

Hi,

Sorry but I can’t reproduce the issue on Debian 13.

❯ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
NAME="Debian GNU/Linux"
VERSION_ID="13"
VERSION="13 (trixie)"
VERSION_CODENAME=trixie
DEBIAN_VERSION_FULL=13.7
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
❯ openssl version
OpenSSL 3.5.7 9 Jun 2026 (Library: OpenSSL 3.5.7 9 Jun 2026)
❯ v-generate-ssl-cert example.com [email protected] US California 'San Francisco' MyOrg MyUnit 'sub1.example.com,sub2.example.com'
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----
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
N1iGmby1yPffHvsI423lTBXfoBgjIw==
-----END PRIVATE KEY-----

-----BEGIN CERTIFICATE REQUEST-----
MIIFKzCCAxMCAQAwgZgxJTAjBgkqhkiG9w0BCQEWFnBvc3RtYXN0ZXJAZXhhbXBs
ZS5jb20xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1TYW4gRnJhbmNpc2NvMQ4wDAYDVQQKDAVNeU9yZzEPMA0GA1UECwwGTXlVbml0
MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
AgoCggIBAMM811C552BMGrZOcBP6AuxdU9v8FV/mE9ZGi63KwQwDzkUWydncYDV1
OQeBx5CoP8nm7sNgqpSFKi9HSHAhdbfvdtZB6BKFRlzkI91uG4/7wjQqODRpJgPr
5xly0ETN3O/M35a6BiOJDW4y6c/Bd31nZyI3dH1gHtDPTurQYCWNFNeske4SdggU
5dEk3itQfKdmuoYb7iJtw3VJFvw/+sLmsVQo3OmJSmES1HC0uLA92PKMV11Dbme0
AYjpxfgHx9azDBZYTZT6n5W2Cw8vzQijFZ1r/XMi21GhsWyVHjVQoIJCoFTMZVAV
ezXwli4JMRCpYFzxWjGlQgluzHBicy4x1v5lCJx8DxhGekMfX5npMi4wZgqHfPKi
H8xM7aL5Pe6c0JzNoZ7zMZdHLtQkc0FfMNaJDGunwZW4/PZeAZX5weGACNJGOgv8
ZCwzjLSQzxQlWvIQQtydSJ9yPjF5aNvO7HAC6lfmP32NqtPkGP1Jf0GC8Lneze8w
CTSA2+msBsCOW4frO1S0mj+0lIqIPLMtRWt1OgRKljCA1uFueRnkmUKlbjT/lbWq
XInp+txbqfk9mHNTUVlm1ygDOZGoKiOuwBp/+vVcrEOMsaEfuSnqkBs2iyAQOQrF
mYfcInQffyBgJr30gaKHb0Tik0W2PSTfUakCcWb78FF8ElsEAfBdAgMBAAGgTTBL
BgkqhkiG9w0BCQ4xPjA8MDoGA1UdEQQzMDGCC2V4YW1wbGUuY29tghBzdWIxLmV4
YW1wbGUuY29tghBzdWIyLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQB8
/ElcvkirwhSxqzLTiRCB9Y80qBaU83SlC2Mluxm3r+EgIPBUW9eBCBWeDaLcXAdT
C9WTYNYOMuvqUxzPyeTtJpMXmWP17sPapwZ8tc4zDjm205zCxqgLmdkMIpTn0hIq
N+fvWXHJhyQSAptAvfjaX6izsn2OZvDoOPpFucWoD609hYx61uSxm1LEbnWfKoEP
xtaJIBeD1Km5DLIYIDHltF4jhMgfhAycQA6rFfb274AZvnM995YRmE/KIPXQ1u7d
OxwJ/9TRKbkq7XUvUj9kZZhlDFcHOCxEetV/s8i00MiYeb/qsZ4Ip38dW+RTomR9
nhtzJ8Ouo5NDpIpWfEzuDDN7PkJ7BhapNmnmYcN0+Wk4Y/n7i2yXePAQTov9Wsb5
CSkNAV91tiZ45Mt3p560e1iAC94/ILn4eGWP9VPDSegU0iE4ISnZi3+iK+PItGVa
QANqt1Hffys2rtkXU7C8cPXuqnajJM7mJjlnGi46DKOtx9mrFln3cg0RtrRUTOyF
TTOMGyKfF5Y+Re0/7nQOExv/dKIsElHHmRfYTyGPsmfPKGMlIVFH+j1f8udQLBrl
gOPyCohIwsdb8wj86cqTOYsp+oyCz6RRIgGDpVxDthAaessMEtIIL1Tdt+2cRBeR
aMjIJeU3I9J3y7kMiCWpZrQ5nj5+kQaeWh2WQRV0yw==
-----END CERTIFICATE REQUEST-----

Directory: /tmp/tmp.Bhlumf0LUn
❯ openssl x509 -in /tmp/tmp.Bhlumf0LUn/example.com.crt -noout -dates -subject -ext subjectAltName
notBefore=Oct 23 19:01:34 2026 GMT
notAfter=Oct 23 19:01:34 2027 GMT
[email protected], C=US, ST=California, L=San Francisco, O=MyOrg, OU=MyUnit, CN=example.com
X509v3 Subject Alternative Name:
    DNS:example.com, DNS:sub1.example.com, DNS:sub2.example.com

This is the issuance record from my previous server.

root@debian:~# cat /usr/local/hestia/log/LE-admin-blog.example.com.log


=============================
Date Time: 2026-10-01 03:05:02
WEB_SYSTEM: apache2
PROXY_SYSTEM: nginx
user: admin
domain: blog.example.com


- aliases: 
- proto: http-01
- wildcard: 


==[Step 1]==
- status: 200
- nonce: lsSsO6Kwl-TPaUeZPLEg0ZqvUG6M_WwbrOwk2qc1glNEPu69oG0
- answer: HTTP/2 200 
server: nginx
date: Wed, 30 Sep 2026 19:05:03 GMT
content-type: application/json
content-length: 961
cache-control: public, max-age=0, no-cache
replay-nonce: lsSsO6Kwl-TPaUeZPLEg0ZqvUG6M_WwbrOwk2qc1glNEPu69oG0
x-frame-options: DENY
strict-transport-security: max-age=604800



==[API call]==
exit status: 0


==[Step 2]==
- status: 201
- nonce: VFHddbRsdY8CY6DYUH2JAuG39KqjX7K2edussvQdthV3Ff0tvmI
- authz: https://acme-v02.api.letsencrypt.org/acme/authz/1528084546/780051686106
- finalize: https://acme-v02.api.letsencrypt.org/acme/finalize/1528084546/563341861906
- payload: {"identifiers":[{"type":"dns","value":"blog.example.com"}]}
- answer: HTTP/2 201 
server: nginx
date: Wed, 30 Sep 2026 19:05:04 GMT
content-type: application/json
content-length: 349
boulder-requester: 1528084546
cache-control: public, max-age=0, no-cache
link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
location: https://acme-v02.api.letsencrypt.org/acme/order/1528084546/563341861906
replay-nonce: VFHddbRsdY8CY6DYUH2JAuG39KqjX7K2edussvQdthV3Ff0tvmI
x-frame-options: DENY
strict-transport-security: max-age=604800

{
  "status": "ready",
  "expires": "2026-10-06T19:05:05Z",
  "identifiers": [
    {
      "type": "dns",
      "value": "blog.example.com"
    }
  ],
  "authorizations": [
    "https://acme-v02.api.letsencrypt.org/acme/authz/1528084546/780051686106"
  ],
  "finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/1528084546/563341861906"
}
 order: https://acme-v02.api.letsencrypt.org/acme/order/1528084546/563341861906


==[API call]==
exit status: 0

They all point to the v-generate-ssl-cert not being able to get the configuration. After I corrected v-generate-ssl-cert using this method, it generated the CSR file when issuing.

The previous script was like this

#!/bin/bash
# info: generate self signed certificate and CSR request
# options: DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT]
#
# example: v-generate-ssl-cert example.com [email protected] USA California Monterey ACME.COM IT
#
# This function generates self signed SSL certificate and CSR request

#----------------------------------------------------------#
#                Variables & Functions                     #
#----------------------------------------------------------#

# Argument definition
domain=$1
domain=$(echo "$domain" | sed -e 's/\.*$//g' -e 's/^\.*//g')
domain_alias=$domain
email=$2
country=$3
state=$4
city=$5
org=$6
org_unit=$7
aliases=$8
format=${9-shell}
KEY_SIZE=4096
DAYS=365

# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
source /etc/hestiacp/hestia.conf
# shellcheck source=/usr/local/hestia/func/main.sh
source $HESTIA/func/main.sh
# load config file
source_conf "$HESTIA/conf/hestia.conf"

# Json function
json_list_ssl() {
	i='1' # iterator
	echo '{'
	echo -e "\t\"$domain\": {"
	echo "        \"CRT\": \"$crt\","
	echo "        \"KEY\": \"$key\","
	echo "        \"CSR\": \"$csr\","
	echo "        \"DIR\": \"$workdir\""
	echo -e "\t}\n}"
}

# Shell function
shell_list_ssl() {
	if [ -n "$crt" ]; then
		echo -e "$crt"
	fi
	if [ -n "$key" ]; then
		echo -e "\n$key"
	fi
	if [ -n "$csr" ]; then
		echo -e "\n$csr"
	fi
	echo -e "\nDirectory: $workdir"
}

# Additional argument formatting
format_domain_idn
if [[ "$email" = *[![:ascii:]]* ]]; then
	local=$(echo "$email" | cut -f1 -d'@')
	email_domain=$(echo "$email" | cut -f2 -d'@')
	email_domain_idn=$(idn2 --quiet $email_domain)
	email="$local"@"$email_domain_idn"
fi

#----------------------------------------------------------#
#                    Verifications                         #
#----------------------------------------------------------#

args_usage='DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT]'
check_args '7' "$#" "$args_usage"
is_format_valid 'domain' 'aliases' 'format' 'email'
is_common_format_valid "$country" "country"
is_common_format_spaces_valid "$state" "state"
is_common_format_spaces_valid "$org" "org"
is_common_format_spaces_valid "$unit" "unit"

release="$(lsb_release -s -r)"

if [ -z "$email" ] && [ "$release" = "18.04" ]; then
	echo "Email address is required"
	exit 2
fi
if [ ! -f /root/.rnd ]; then
	touch /root/.rnd
fi

# Perform verification if read-only mode is enabled
check_hestia_demo_mode

#----------------------------------------------------------#
#                       Action                             #
#----------------------------------------------------------#

# Create temporary work directory
workdir=$(mktemp -d)
cd $workdir

# Generate private key
openssl genrsa "$KEY_SIZE" > "$domain.key" 2> /dev/null

subj=""
# Generate the CSR
if [ -n "$email" ]; then
	subj="/emailAddress=$email"
fi

subj="$subj/C=$country/ST=$state/L=$city/O=$org"
subj="$subj/OU=$org_unit"

# The CN (CommonName) has an ASN.1 limit of 64 characters in OpenSSL.
# If the domain exceeds this limit, the CN is omitted and only the SAN
# (subjectAltName) is trusted, which is what modern browsers validate.
if [ ${#domain_idn} -le 64 ]; then
	subj="$subj/CN=$domain_idn"
fi

if [ -e "/etc/ssl/openssl.cnf" ]; then
	ssl_conf='/etc/ssl/openssl.cnf'
else
	ssl_conf="/etc/pki/tls/openssl.cnf"
fi

if [ -z "$aliases" ]; then
	openssl req -sha256 -new \
		-batch \
		-subj "$subj" \
		-key $domain.key \
		-reqexts SAN \
		-config <(cat $ssl_conf \
			<(printf "[SAN]\nsubjectAltName=DNS:$domain")) \
		-out $domain.csr > /dev/null 2>&1
else
	for alias in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
		if [[ "$alias" = *[![:ascii:]]* ]]; then
			alias=$(idn2 --quiet $alias)
		fi
		dns_aliases="${dns_aliases}DNS:$alias,"
	done
	dns_aliases=$(echo $dns_aliases | sed "s/,$//")
	openssl req -sha256 -new \
		-batch \
		-subj "$subj" \
		-key $domain.key \
		-reqexts SAN \
		-config <(cat $ssl_conf \
			<(printf "[SAN]\nsubjectAltName=$dns_aliases")) \
		-out $domain.csr > /dev/null 2>&1
fi

# Generate the cert 1 year
if [ -z "$aliases" ]; then
	openssl x509 -req -sha256 \
		-days $DAYS \
		-in $domain.csr \
		-signkey $domain.key \
		-extfile <(printf "[SAN]\nsubjectAltName=DNS:$domain") \
		-extensions SAN \
		-out $domain.crt > /dev/null 2>&1
else
	openssl x509 -req -sha256 \
		-days $DAYS \
		-in $domain.csr \
		-signkey $domain.key \
		-extfile <(printf "[SAN]\nsubjectAltName=$dns_aliases") \
		-extensions SAN \
		-out $domain.crt > /dev/null 2>&1
fi

# Listing certificates
if [ -e "$domain.crt" ]; then
	crt=$(cat $domain.crt | sed ':a;N;$!ba;s/\n/\\n/g')
fi

if [ -e "$domain.key" ]; then
	key=$(cat $domain.key | sed ':a;N;$!ba;s/\n/\\n/g')
fi

if [ -e "$domain.csr" ]; then
	csr=$(cat $domain.csr | sed ':a;N;$!ba;s/\n/\\n/g')
fi

case $format in
	json) json_list_ssl ;;
	plain)
		nohead=1
		shell_list_ssl
		;;
	shell) shell_list_ssl ;;
	*) check_args '1' '0' '[FORMAT]' ;;
esac

# Don't allow non root users view folder
chmod 660 $workdir
# Clean up the mess
echo "rm -rf $workdir" | at -M "now +15 minute" > /dev/null 2>&1
# Delete tmp dir
#rm -rf $workdir

#----------------------------------------------------------#
#                       Hestia                             #
#----------------------------------------------------------#

# Logging
log_event "$OK" "$ARGUMENTS"

exit
root@debian:~# crt=/home/admin/conf/web/blog.example.com/ssl/blog.example.com.crt
root@debian:~# if [ -f "$crt" ]; then
>     openssl x509 -in "$crt" -noout -dates -subject
>     not_after=$(openssl x509 -in "$crt" -noout -enddate | cut -d= -f2)
>     expiration=$(date -d "$not_after" +%s)
>     now=$(date +%s)
>     days=$(( (expiration - now) / 86400 ))
>     echo "剩余 $days 天"
> fi
notBefore=Jul 17 18:06:58 2026 GMT
notAfter=Oct 15 18:06:57 2026 GMT
subject=CN=blog.example.com
剩余 0 天
root@debian:~# v-add-letsencrypt-domain admin blog.example.com
Certificate request self-signature ok
[email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
root@debian:~# echo "exit=$?"
exit=0
root@debian:~# 
root@debian:~# cat /usr/local/hestia/log/LE-admin-blog.example.com.log
cat: /usr/local/hestia/log/LE-admin-blog.example.com.log: No such file or directory
root@debian:~#
root@debian:~# crt=/home/admin/conf/web/blog.example.com/ssl/blog.example.com.crt
root@debian:~# openssl x509 -in "$crt" -noout -dates -subject
notBefore=Oct 16 02:38:21 2026 GMT
notAfter=Jan 14 02:38:20 2027 GMT
subject=CN=blog.example.com
root@debian:~#

Those who need to renew due to errors should do additional verification to check if this is the mistake. We can consider merging based on follow-up tracking.

I don’t know what happened in your case but I can’t see the relation between your change to v-generate-ssl-cert and the original one.

Could you please show the output of these commands?

cd $(mktemp -d)
openssl genrsa -out t.key 2048
bash -c 'openssl req -sha256 -new -batch -subj "/CN=blog.example.com" \
  -key t.key -reqexts SAN \
  -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:blog.example.com")) \
  -out t.csr'
echo "exit: $?"; openssl req -in t.csr -noout -text | grep -E "Subject:|DNS:" | sed -E 's/^\s*//'

I’m using the fixed v-generate-ssl-cert script, but it seems like this command can’t verify.

root@debian:~# cd $(mktemp -d)
root@debian:/tmp/tmp.BAHMm48UBD# openssl genrsa -out t.key 2048
root@debian:/tmp/tmp.BAHMm48UBD# bash -c 'openssl req -sha256 -new -batch -subj "/CN=blog.example.com" \
>   -key t.key -reqexts SAN \
>   -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:blog.example.com")) \
>   -out t.csr'
Error checking request extension section SAN
root@debian:/tmp/tmp.BAHMm48UBD# echo "exit: $?"; openssl req -in t.csr -noout -text | grep -E "Subject:|DNS:" | sed -E 's/^\s*//'
exit: 1
Can't open "t.csr" for reading, No such file or directory
40A7268BB87F0000:error:80000002:system library:BIO_new_file:No such file or directory:../crypto/bio/bss_file.c:67:calling fopen(t.csr, rb)
40A7268BB87F0000:error:10000080:BIO routines:BIO_new_file:no such file:../crypto/bio/bss_file.c:75:
error: unable to load X509 request from file 't.csr'
root@debian:/tmp/tmp.BAHMm48UBD# 

Try this:

 cd $(mktemp -d)
openssl genrsa -out t.key 2048
bash -c 'openssl req -sha256 -new -batch -subj "/CN=blog.example.com" \
  -key t.key -reqexts SAN \
  -config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:blog.example.com")) \
  -out t.csr'
echo "exit: $?"; openssl req -in t.csr -noout -text | grep -E "Subject:|DNS:" | sed -E 's/^\s*//'

If this fails too, show me the file /etc/ssl/openssl.cnf

cat -A /etc/ssl/openssl.cnf

What you need to test is whether the original v-generate-ssl-cert script can generate CSR/certificate files. Without it, certificates can’t be issued. I can’t actually test it right now because the certificates have already been issued.

Here’s my simulation of testing the old v-generate-ssl-cert script. I only corrected the change inside the v-generate-ssl-cert file:

<(printf "[SAN]\nsubjectAltName

changed to

<(printf "\n[SAN]\nsubjectAltName

Generated the CSR file

root@debian:~# D=blog.example.com
root@debian:~# E="[email protected]"
root@debian:~# C=US; S=California; L="San Francisco"; O=Hestia; OU=IT
root@debian:~# 
root@debian:~# # ① 默认 ecdsa-256(不传第 10 参)
root@debian:~# echo "===== ecdsa-256 (default) ====="
===== ecdsa-256 (default) =====
root@debian:~# /usr/local/hestia/bin/v-generate-ssl-cert "$D" "$E" "$C" "$S" "$L" "$O" "$OU" "" shell
-----BEGIN CERTIFICATE-----
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
hUIu/w==
-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----
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
om43nQuJduXqx0nchR/+6GTkiEJl
-----END PRIVATE KEY-----

-----BEGIN CERTIFICATE REQUEST-----
MIIFDTCCAvUCAQAwgZkxJDAiBgkqhkiG9w0BCQEWFWluZm9AYmxvZy5leGFtcGxl
LmNvbTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkhlc3RpYTELMAkGA1UECwwCSVQxGTAX
BgNVBAMMEGJsb2cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQDKKk6CjWT6Y2O0oxi5jp+MjHO/FfYJjTI0R2JhJDy5MCRQpAN8vjyc
SOQXBEDXkySRFZPxf0tye8xn0paDX7ukiuyxDos4bcE2Ju1Ni+52QizLxNcwfsVA
YX79f657izYRbfFD65MEyp1fAWC3aKYe3mq3EjsKVQQuOj92qxS6a36+104sj5Z9
JUusGqElJ5Sfuzi9OpuN1Zl1A82w8dywYeBYFpMjGQ8Nq+BwyKomQn/HNCjFFwoN
l4zlu4VUexOpPKEPitUagTb7JNRZBnHDycjo3yMD9v3PjSrThcMYnEeGjbCGDSea
nH+uiHsNBGUoLcgLrOIukk4T/Zfm3N9OxfrIHSJW7Bq/DV4gg8Nfv8/DaYJGplYt
3W3MbEADVsaTzW9y99TwwGqHqDogYhEGVvP53LaEEEhSNgySywjP+ao+B+X+kq0N
VoOVtqIXuUnSr1Z2E/OjH8szhsd9x8/De0o7vY8R0pv6DwT8GGpsJjrQySN0vm4M
5JG+HVgkCEdEj6t0a9SwWR7JS8jnuaGSc8SEWANqgWrYt/aRBQ0nu604eYOhq/YV
mEsAFzDxX6TkSFM3JIVl3VG4OpldTcD5krLJ61/o38g8D/ddm1OFvL2JT1hp70xJ
ho0Vy1UX+h9xtrYBmvN9Ec1u/JvfLDEpHy5xmt4m0LrKpImbkDwUsQIDAQABoC4w
LAYJKoZIhvcNAQkOMR8wHTAbBgNVHREEFDASghBibG9nLmV4YW1wbGUuY29tMA0G
CSqGSIb3DQEBCwUAA4ICAQAV+JcKJ3BlJ1gBv/kPpkmBCCFDIQMkhcaWi0mZqSdV
T/rzdRloCvjoUJhKnZTa8ndDypHKu18jMVRCj8DNmrvlvveJTReZZ3Y8wHy8CyHD
RdHsADWgCHOd/Waeu+Avlbkt8NdNle4MPgXcXWCq3NDo35GZAEmVdBd+MrQuzJE0
KNgiYFao76PPU4+dOaitQ3Rj6UiWvbbt5pP+uAqtnxDC/VCWuh4AcQLXTkteGFaE
2G+8rmg20gpwKnVeygInrFSsEm2ecpDKQqyvQ8xMh1B6yRhYsyULNu7IdL6Aiwvd
vGTL1ydjIoeZLGlalvuwOwLShercM4G6x6ryraPVcLJZznqZc0wJReSo093XL1Rm
P7LuKGEbNCGKp/w6BMhMz8hjyk7kDj1tYJl+ILYv/Rypi/s2jlkOs37V70+qjisd
YAn1E2QnQCto+eFFpuKdUHYYqHjB6Hc+XClX12s1bYNdMTZoebMcsrvVLvhsZTxJ
cL3xC81dJ5QutWfeqHoboIzC5moj06JL9xed73fc096jPkivlBrwj4Z2DuD9GhMo
xrJfA0Br6ld4T/go3Pi2KmWGaZb/AvbmI8IL8Yf7G/lNZxlPOjw+mrYtU3DL7GiC
qgaQe9pCDgrR+asqkqhh0oD5DfMjKBkN9HQ9kgiKPKP8rECErBn0UrPUdNdNGCdi
AA==
-----END CERTIFICATE REQUEST-----

Directory: /tmp/tmp.kwrYTi97gX
root@debian:~# echo "exit=$?"
exit=0
root@debian:~# 
root@debian:~# # ② ecdsa-384
root@debian:~# echo "===== ecdsa-384 ====="
===== ecdsa-384 =====
root@debian:~# /usr/local/hestia/bin/v-generate-ssl-cert "$D" "$E" "$C" "$S" "$L" "$O" "$OU" "" shell ecdsa-384
-----BEGIN CERTIFICATE-----
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
v3xPjA==
-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC5CLf68NoBLTw2
4uAEF7RoboYxsul5oolK3R+LZcfHdh4xVdMbtHL/wYu5nAI/v8ONdJwaeqVYtdja
aK0aE+V+YYE1Ixt/8n6CEVnXH33pe3h1Ph5jR7TzCHMNOzWfWChVdibQykOg/3ru
2wQVSw46lxTulnO6wh+onhtufb/yxjn2z/DZyTcSGbxLmn+a3mNzuybVp4c+hlrB
SB2OFH61tjqJmDeqkJaCNA657wh01LnpjwrFA1Pwab5ijXfAQ5PelD3ml3rW6MdJ
0IfPKPs1Hd1kZLhLADrLkdLFjXKqE+Xxx6Ucp9MN9qyoNMHGof6sdMzxlIfzcEqb
DikoLEP+dVKkULs74KwhxpOrjrLvQI51FMWo/U0mijAj0nGsKeC7Tuhwncxc18Bp
zzFV0Xl+RXtmrzvWM1CWOBTTYeBvd1mUV1nVDjnHhMuiOjsYdo1+Ql4zHAUoqNzI
XROtl7ZtMBmw7s2VkT7SOcMFKyAO9cV6ccqtNwBA0E6V92oNvXfW/EMR4d+kFcdE
Zd2I1p2u/bEilYRbmcVUfAReQlBYPTZMfb8pr9MQnddtdhh0yG3RNBWhRV+vzVTb
Q5zzMcvK12GvfvMKm0x2QfDhSwSxbz2U8vLSrG/JkjyqwW26DohOtvgIwaGI+gXc
tjFOHd+RcTE8ZcKWCZyc/wWNd7MYWwIDAQABAoICAAi/KsNIA2Yu1zvY+bH31OVi
5CERTgwb7NWHImiahRkeskquve3/V7hTU+GQSGLvE7VqH774sTxCTF/2tsgWzLBu
t4blg/VGZ0iKvW535KHW3ljceN9Ekn8ylQ25EM3Zgv6XOTqBdTT1HsCPxd+jzqZi
YfDtV8cqSgjUgIN2mk5FpJPQPJhu9JV8dfQ093dAr/7Wh/1tj+0auMuONydyPJMm
bBn5AhikARlikJelfwbWz3sE8gNiJuOkfAV4noKOLz1EULDH1Fy4YENTAjh+vXFD
WiXWxQd2mVDqMcZ460Sy8Bm/0ERMgqOUV5ET/V0AZ2OLmeyJkuulEUHHJ5bokMYv
3fRTV8loxaiPQD+qVU6Zv9SF2Up+t3Bv5vGgsrv0pK21uuVTv5VhIh9hSe8QSaTB
nOOhzKpfG5dNYByGO7AvOsin1k9n4eHe+H6I4TbJVllpEGBCO96x1ztbfOd6C4ZX
aSOE6D1N/mQlunrTTVtP+lnX4avfwjwSCihBeRIQUkVT4lkfRN90Qsbd5ilB08TO
Be7oalp9EucdpHKXU/VJmizks/0iDtEjhwHzpP5oBAAbTfcVFvgUc8JPbickO6Zt
LpR/g1vXXBOCpqb3ndkwXvLpKuYdycDzX8g2DzpOTod9D8Zy9Vu3pSbTGN3ZJzvG
9jskhFnByjlEJny/iZhhAoIBAQDy/UXfIWQRAuhZxmNtgrzCuRKbogEdoPF8Z9Lh
bQwoEImqwI96E02f2cjLuBxw2Torb6O7AYtGCQV1OXh2FHWQz3ep5cmDXW61+fkF
JU02N+6koqX3IZng1N7WupsvLfCbz8FhaNv1NmaWCOJANqVnoOup865rs6QKD9Ec
2si/uMrtUgXRinmFJuWLPVres0j5EcfqVS0qsxq/oedBGtiSmJnc+zc8JngqH7X7
rdDU8aj2uDrIVZt00XAV3VAyBDJNSIPZ+l1xweMz+DcPLbLFPVNN/RsCWbiTpRbY
NX9WBwA3CSo9952UUJLsAmuiTSGIsnoG/wLVtXzp1P6+3aQzAoIBAQDC8QkO7T28
PIiDYHWyDEHGL27lExm+IPTRrRX4bNrk1saDjEZlQk3LsQosL6aZ6mKSjjhnEHc8
xsmy39Nfd31gwftoSqAaNPNtnHxOZFLkBVgidd0/ptPjJBLyk6mMzzB6jMrb6mjG
M4syIt7YYv+saiZ6NDoB1CVtpIyxdq7QGsy/eXmrBhvDLel1O0VFrApPwiYVrYlg
6I/17xasDPULAvdOjesCzOOe1ykg7bGVvpW0WhAhpFfSqN8ZN5Lvruqb3TRlWuYe
zkMrinZ7kNrIZh7tsYVdvj+BwRgjcLiHL65jkV40rn2947CQ3FZ/x5OXBHPOXJco
Ve7NUYlub1M5AoIBAEoI4UEa62JDgIfZ6nFzZA/wU7sXoT9lyi4ddCM7FnkekNN1
2EFZoE0UDhoD/qZjiVWyrjBMSCMOnJsa55kSor98dvlNChj8Xr8TaswmkV/zqsJ+
zBKAKmJWeY7zTFUTqjvPERyc1mfgK2GLU2Q9QihQ33zowjwOf+yQ5SXlg0TnCO1G
EH/HsT7gmw/Rod44wgMhZ8f+K8TWzU+WBN/RTitcU4UBBdNN5U7wWoJUc0xuVQzX
FRH1A2iUZ5JB3C1hGfJyJbpEjjQa3x72gdAeHFn8VWVtuMz+iT5zDoLRyfpsJ6Sd
JkG7MEgARMOj+Sd6WL1No+B90l9K7MRSIUwGPAECggEBAKoz0PjbYj9rirVKDvi5
guQKngQbvSonlBlNyhTw1d1fOEu6uevHDC2AEaWqpQdVgWL8EXrLAZBq78fhbKe5
qBpGw763CTpYaQGW02GObmDv2Zec2OOuQOncoT5ydmKes3EMZEHGVFxYvHu1vmOn
bBuZQqcH2m2mUFd+h+iZ+t9vxryWzwfneW3cNC1K5pyCLS6eEKp0rbGS276aVW06
kuheWpaXik0TntkceqhpX9eiYwroZ5U37AXds4xM3Vmvmt8jL5Ae4TScWkE1z2Tr
gFnf77kQeaTzandbpDutOy+tDdGZJmtQvjCBD7Qq7Mr78Xy1Qnc2mDN7c9iIDDoD
sOECggEASCc40OG4CnPQfIZJ3jscC3YFmosUwwkoHx6QGUiYK/DMM3RYHt0ry/L+
/jot4d0MtQ+7ze+QJ105KUITEzzN8+uIe1TSacIRD8HnLxSWYMDE6xyCwbG8uv+B
+jT79Gb64cHwymVeQ6lFejQGGUK+2hhPlhTqufNw5anJUTWL4Pgjl8Jfoh8ppmcF
q1XBoxpbGtFNb6XcfyD12RHy87hvOxOBRA3rqZf57d2cVLhj0DsRvevkVHmR7WyL
4yenku+HWNaaMtOIdNRj0U2Ya4CG0nv/U59KZyRe/7XIAtl1/XvFk2QVam06zWdl
p+kdemmbofsY6ccb1v+kZF3K/R9YYA==
-----END PRIVATE KEY-----

-----BEGIN CERTIFICATE REQUEST-----
MIIFDTCCAvUCAQAwgZkxJDAiBgkqhkiG9w0BCQEWFWluZm9AYmxvZy5leGFtcGxl
LmNvbTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkhlc3RpYTELMAkGA1UECwwCSVQxGTAX
BgNVBAMMEGJsb2cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQC5CLf68NoBLTw24uAEF7RoboYxsul5oolK3R+LZcfHdh4xVdMbtHL/
wYu5nAI/v8ONdJwaeqVYtdjaaK0aE+V+YYE1Ixt/8n6CEVnXH33pe3h1Ph5jR7Tz
CHMNOzWfWChVdibQykOg/3ru2wQVSw46lxTulnO6wh+onhtufb/yxjn2z/DZyTcS
GbxLmn+a3mNzuybVp4c+hlrBSB2OFH61tjqJmDeqkJaCNA657wh01LnpjwrFA1Pw
ab5ijXfAQ5PelD3ml3rW6MdJ0IfPKPs1Hd1kZLhLADrLkdLFjXKqE+Xxx6Ucp9MN
9qyoNMHGof6sdMzxlIfzcEqbDikoLEP+dVKkULs74KwhxpOrjrLvQI51FMWo/U0m
ijAj0nGsKeC7Tuhwncxc18BpzzFV0Xl+RXtmrzvWM1CWOBTTYeBvd1mUV1nVDjnH
hMuiOjsYdo1+Ql4zHAUoqNzIXROtl7ZtMBmw7s2VkT7SOcMFKyAO9cV6ccqtNwBA
0E6V92oNvXfW/EMR4d+kFcdEZd2I1p2u/bEilYRbmcVUfAReQlBYPTZMfb8pr9MQ
nddtdhh0yG3RNBWhRV+vzVTbQ5zzMcvK12GvfvMKm0x2QfDhSwSxbz2U8vLSrG/J
kjyqwW26DohOtvgIwaGI+gXctjFOHd+RcTE8ZcKWCZyc/wWNd7MYWwIDAQABoC4w
LAYJKoZIhvcNAQkOMR8wHTAbBgNVHREEFDASghBibG9nLmV4YW1wbGUuY29tMA0G
CSqGSIb3DQEBCwUAA4ICAQB//ZGGH8axOYLGQm70R86DYeuQ3eOE8dDG6Ebd3Q1q
lFivVZKs40OXchpYnHnrLgCvDTvkvzE6YoheQGIn1w1mCOUyoR6e8JEc7Z5IUyTk
BIji+I8RHd5bTv7vVP/O5Jxj2rGlTGoSJhVq2IrKWVw62wpNauWvt7gh+miIH5bW
s9pyG67AMQx0GqiKxlUj8zSA53AuhD2ATdtPZroVKE442bvUtOvsB61ChrQFcv7E
1e+EW4zeHSeCYrYEIDqvi9opOYRvMFkb6TRemOmfM3q87dNKTR+tWyhE/XOBIxHY
uQ69CFNyc6VeXQp8Yi3y0dSNOovtsviP0cTWDc323j8gMz6GXoX5ROg4d6hDNAh/
InAzQautkDqrI9GmtJalU5XPu1v4GGvaEILMZzxYK+KyhwHTdBYqp2RlKJGMlvlO
BWNKZGknTGl1CCMyt7WuQUqVESRj4f4GiPW4opnnDcV8Y+GuI7TBxztT1bUDgZfK
cqFF+CNiJ+Ph0xBzhbWTZ2TTYswCLx/dvvFT5Xce58YsswuZ9KXwKR2pgob1SII0
KbzftQSFUEPVn7RUNQGPycDEA68aQnSRuazCFJeK4CquAug7jfpWnZ+jGi3yxvm0
39E+YlVSdcCp/QWEpxQO81H/ubjaZCVL7xSwa66I0L5KNhKetrJwaYmVhsAne5yj
+Q==
-----END CERTIFICATE REQUEST-----

Directory: /tmp/tmp.VHpZraf5sm
root@debian:~# echo "exit=$?"
exit=0
root@debian:~# 
root@debian:~# # ③ rsa
root@debian:~# echo "===== rsa ====="
===== rsa =====
root@debian:~# /usr/local/hestia/bin/v-generate-ssl-cert "$D" "$E" "$C" "$S" "$L" "$O" "$OU" "" shell rsa
-----BEGIN CERTIFICATE-----
MIIGADCCA+igAwIBAgIUF4X5Xj5uDUsgjSYYMqBn+xORsWUwDQYJKoZIhvcNAQEL
BQAwgZkxJDAiBgkqhkiG9w0BCQEWFWluZm9AYmxvZy5leGFtcGxlLmNvbTELMAkG
A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFu
Y2lzY28xDzANBgNVBAoMBkhlc3RpYTELMAkGA1UECwwCSVQxGTAXBgNVBAMMEGJs
b2cuZXhhbXBsZS5jb20wHhcNMjYxMDIzMjA0NTE5WhcNMjcxMDIzMjA0NTE5WjCB
mTEkMCIGCSqGSIb3DQEJARYVaW5mb0BibG9nLmV4YW1wbGUuY29tMQswCQYDVQQG
EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNj
bzEPMA0GA1UECgwGSGVzdGlhMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQYmxvZy5l
eGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKPIgRfZ
7+WEbXKqhieXKMBoT9DJHYQ+xaby5rUY4AZYQdlXYx90uzBfq8ZFikKZty0bolK2
qs6lNVrXIeJyRFJoWada5tN0Zm+k/fcOonESPEvi1W2NnjYnRbThv8ldETwBygZh
7r+YhaaPBpsBMmE2NE+KTKSt4K9VGaazPqPSY002ide+mFLM0okcFYuiWh8x5Uek
tHgk5SlJNpesixvWUlw4WCVvvDvyVUvkhqbqv+ULeVjgr6EvWZd6/Z+55pdua931
AiokDd03jXpjo5QZ0gW3CZaGv55iQk+LkTPrAG2S72Xp006l5E/Hjf9BYyOdDqQC
/GGkDCjfOAA6C10GswLi2gfQdoJQH30rUu3yLW0GiJAkUisOLnX1I6xrIRHEoIrb
PF8wrZ39A7VzgVEPs/JUKR72KzlicocKu6ykq8td5yIFV/4wVFgrl21Bbuxqzl6Q
K/nGO9Su+5LDg7bmj8b3lMvZjlbt9eHnwOCZmARpC1EbSYy4LKuvru2UcCR2dwho
u/IavH4YU+9dZetN/Ywj5h6NsGG7dC/jQz2PYuSseBDDtWwcGy3FFW6A2zOmm2FV
84hdMlquodBP0dXoaQqUeWgKhQGgKiCZa3+MGruDccPGL8CbdMj+XunxZHHokylu
S2sowWHsg243AwYQAO65xZK5ZvSeWBrhsK/7AgMBAAGjPjA8MBsGA1UdEQQUMBKC
EGJsb2cuZXhhbXBsZS5jb20wHQYDVR0OBBYEFKB47ETGm+55ZsYRCezaxSNAzwcK
MA0GCSqGSIb3DQEBCwUAA4ICAQAJYaPvvCkYUEJJWNLvAzmc1yELNqlFeAQMsBUU
KyM3K6QHmvtjmtxAR2zP47zlaq5MTe9bV8wL3NiWNJASe8+wMU1KMVMMtvcpaEYQ
Tu3CTHfiJnG+Ph9XFxOb3ofMzZ7BfhipYAVk5/iFwFdod2uCUWcwrd+xfK90FOfd
nAxWYKlWX2HIQoltB84dIhKgpXqNv3+Vtnr3CVFySoY5ny3/DsN+faNlfSCXZ58K
dTOxsPFODQuN9PLMVlJBPVyo7V6UUHdqGLXQb5bEpjnwSLsPrzzvSpEbKRrXkrQl
Km8EoHSwQmBtulncW5AC8DZRCSQza5zY21h3vKj9STcz2gJem2EO5iaj19NjTNJu
ThFRXhtlc5/kF0a53Qehy0igu11euKK+tLFrf3ZmECU7PyX+nmXolphbgZRkNkKc
1jW5Ybl6qxyRqwLU805mP/NV2WPCWkHmiR45kULZ8gzkmEe6JMdYbwD0KR+DrMzF
S+mwKE15wg4Frsvuhp1LLpVaMjdu7VddyXPf7sWEbrV3CONq9LpKW6MqvhQ20llq
eUKg2qgACAESiTii921p6R+j77jMC/5Cxhi7AU/p7hXBKYnOONMfEhJv25IS1Vvt
RFoYp7U1pOSLq39xGCXL6P2Rb98Ko33mO1K5TI+ea7OhV9rHGNL54yBoUeTTymaq
zjzy/A==
-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----
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
GK+NMjzkft4C6oemIa5GKFsegwtcbQ==
-----END PRIVATE KEY-----

-----BEGIN CERTIFICATE REQUEST-----
MIIFDTCCAvUCAQAwgZkxJDAiBgkqhkiG9w0BCQEWFWluZm9AYmxvZy5leGFtcGxl
LmNvbTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkhlc3RpYTELMAkGA1UECwwCSVQxGTAX
BgNVBAMMEGJsb2cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQCjyIEX2e/lhG1yqoYnlyjAaE/QyR2EPsWm8ua1GOAGWEHZV2MfdLsw
X6vGRYpCmbctG6JStqrOpTVa1yHickRSaFmnWubTdGZvpP33DqJxEjxL4tVtjZ42
J0W04b/JXRE8AcoGYe6/mIWmjwabATJhNjRPikykreCvVRmmsz6j0mNNNonXvphS
zNKJHBWLolofMeVHpLR4JOUpSTaXrIsb1lJcOFglb7w78lVL5Iam6r/lC3lY4K+h
L1mXev2fueaXbmvd9QIqJA3dN416Y6OUGdIFtwmWhr+eYkJPi5Ez6wBtku9l6dNO
peRPx43/QWMjnQ6kAvxhpAwo3zgAOgtdBrMC4toH0HaCUB99K1Lt8i1tBoiQJFIr
Di519SOsayERxKCK2zxfMK2d/QO1c4FRD7PyVCke9is5YnKHCruspKvLXeciBVf+
MFRYK5dtQW7sas5ekCv5xjvUrvuSw4O25o/G95TL2Y5W7fXh58DgmZgEaQtRG0mM
uCyrr67tlHAkdncIaLvyGrx+GFPvXWXrTf2MI+YejbBhu3Qv40M9j2LkrHgQw7Vs
HBstxRVugNszppthVfOIXTJarqHQT9HV6GkKlHloCoUBoCogmWt/jBq7g3HDxi/A
m3TI/l7p8WRx6JMpbktrKMFh7INuNwMGEADuucWSuWb0nlga4bCv+wIDAQABoC4w
LAYJKoZIhvcNAQkOMR8wHTAbBgNVHREEFDASghBibG9nLmV4YW1wbGUuY29tMA0G
CSqGSIb3DQEBCwUAA4ICAQA3nYsSHsBMZ2UkKC0eOofPOz89bYcjcTAotuggEhrE
qQORygtnQ/kMUEYSMakiPcBzEb/TbfYt6XFUjyQwxmZWEFtZhT3FYVj/QVMsWhir
bWsNNT4jTBjHLYHt2LaZZT48KRfir6t6+EbTseT1TeY6T1GP3979LZFVPCF9tBK+
bEZv+h3nuipizUP8ZMTRrXnydeaS9BtotUtBFpG1g0Cm71uLVwVI8QhxHjlQEiBN
sk6W7M0Yq9hV1xD3Tk5a/Tq0MEli5PjY6vjap7+7Ov6d20plz6equv4DB54UYqJG
2Kht0wLf5fxZfv8UujRbYD4FnMuyFJCj5MaLI0oJKwbV8wRiFbrM/rbbrmOCXGiO
IgcrfZ7fo9flHteiRcnd4MPXXsE/5njeEm6Sw4T44UYJUmYJ+9yb6wxwWPjW0o38
YVmZ+ng2u5H+31wYukunK1CUk7ACqGj8j1JTufkYyokFzK+0pCkqMnd5IGIprFgH
AbgQ2r9EwwEQNEtG79R1XruBhq8cQvCKr8ZGlfuDn6laz3QAHZfRFszVVmSG3lZM
ebSzmWhAs67magSVbrx7ea0pDDW2mxfSRHMQdFFJ5oYbTbcQCZdPEXMjnIiob3vz
HI+JQNIi2GyaRk1VVCqMjXhT/6YBWJUGZVHARhthjDjCMz7ZDuzz20ttqyOkRd+/
2Q==
-----END CERTIFICATE REQUEST-----

Directory: /tmp/tmp.haCC7Moo3I
root@debian:~# echo "exit=$?"
exit=0
root@debian:~# for d in /tmp/tmp.OXxCKqDM9H /tmp/tmp.q4BUrcemQy /tmp/tmp.dqHGvwaO6N; do
>   echo "=== $d ==="
>   ls -la "$d" 2>/dev/null | grep -E '\.csr|\.crt|\.key'
>   [ -f "$d/blog.example.com.csr" ] && echo "CSR EXISTS" || echo "CSR MISSING"
> done
=== /tmp/tmp.OXxCKqDM9H ===
-rw-r--r--  1 root root 3272 10月24日 04:39 blog.example.com.key
CSR MISSING
=== /tmp/tmp.q4BUrcemQy ===
-rw-r--r--  1 root root 3268 10月24日 04:39 blog.example.com.key
CSR MISSING
=== /tmp/tmp.dqHGvwaO6N ===
-rw-r--r--  1 root root 3272 10月24日 04:39 blog.example.com.key
CSR MISSING
root@debian:~# for d in /tmp/tmp.kwrYTi97gX /tmp/tmp.VHpZraf5sm /tmp/tmp.haCC7Moo3I; do
>   echo "=== $d ==="
>   ls -la "$d" 2>/dev/null
>   [ -f "$d/blog.example.com.csr" ] && echo "CSR EXISTS" || echo "CSR MISSING"
> done
=== /tmp/tmp.kwrYTi97gX ===
总计 12
drw-rw----  2 root root  100 10月24日 04:45 .
drwxrwxrwt 36 root root  840 10月24日 04:45 ..
-rw-r--r--  1 root root 2143 10月24日 04:45 blog.example.com.crt
-rw-r--r--  1 root root 1830 10月24日 04:45 blog.example.com.csr
-rw-r--r--  1 root root 3268 10月24日 04:45 blog.example.com.key
CSR EXISTS
=== /tmp/tmp.VHpZraf5sm ===
总计 12
drw-rw----  2 root root  100 10月24日 04:45 .
drwxrwxrwt 36 root root  840 10月24日 04:45 ..
-rw-r--r--  1 root root 2143 10月24日 04:45 blog.example.com.crt
-rw-r--r--  1 root root 1830 10月24日 04:45 blog.example.com.csr
-rw-r--r--  1 root root 3272 10月24日 04:45 blog.example.com.key
CSR EXISTS
=== /tmp/tmp.haCC7Moo3I ===
总计 12
drw-rw----  2 root root  100 10月24日 04:45 .
drwxrwxrwt 36 root root  840 10月24日 04:45 ..
-rw-r--r--  1 root root 2143 10月24日 04:45 blog.example.com.crt
-rw-r--r--  1 root root 1830 10月24日 04:45 blog.example.com.csr
-rw-r--r--  1 root root 3272 10月24日 04:45 blog.example.com.key
CSR EXISTS
root@debian:~# for d in /tmp/tmp.kwrYTi97gX /tmp/tmp.VHpZraf5sm /tmp/tmp.haCC7Moo3I; do
>   echo "=== $d ==="
>   openssl req -in "$d/blog.example.com.csr" -noout -text 2>/dev/null \
>     | grep -E 'Subject:|DNS:'
>   openssl x509 -in "$d/blog.example.com.crt" -noout -text 2>/dev/null \
>     | grep -E 'Subject:|DNS:'
> done
=== /tmp/tmp.kwrYTi97gX ===
        Subject: [email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
                    DNS:blog.example.com
        Subject: [email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
                DNS:blog.example.com
=== /tmp/tmp.VHpZraf5sm ===
        Subject: [email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
                    DNS:blog.example.com
        Subject: [email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
                DNS:blog.example.com
=== /tmp/tmp.haCC7Moo3I ===
        Subject: [email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
                    DNS:blog.example.com
        Subject: [email protected], C=US, ST=California, L=San Francisco, O=Hestia, OU=IT, CN=blog.example.com
                DNS:blog.example.com
root@debian:~# grep -nA4 'openssl req -sha256 -new' /usr/local/hestia/bin/v-generate-ssl-cert
130:    openssl req -sha256 -new \
131-            -batch \
132-            -subj "$subj" \
133-            -key $domain.key \
134-            -reqexts SAN \
--
146:    openssl req -sha256 -new \
147-            -batch \
148-            -subj "$subj" \
149-            -key $domain.key \
150-            -reqexts SAN \
root@debian:~# grep -nA7 'openssl req -sha256 -new' /usr/local/hestia/bin/v-generate-ssl-cert
130:    openssl req -sha256 -new \
131-            -batch \
132-            -subj "$subj" \
133-            -key $domain.key \
134-            -reqexts SAN \
135-            -config <(cat $ssl_conf \
136-                    <(printf "\n[SAN]\nsubjectAltName=DNS:$domain")) \
137-            -out $domain.csr > /dev/null 2>&1
--
146:    openssl req -sha256 -new \
147-            -batch \
148-            -subj "$subj" \
149-            -key $domain.key \
150-            -reqexts SAN \
151-            -config <(cat $ssl_conf \
152-                    <(printf "\n[SAN]\nsubjectAltName=$dns_aliases")) \
153-            -out $domain.csr > /dev/null 2>&1
root@debian:~# grep -nA6 'openssl x509 -req' /usr/local/hestia/bin/v-generate-ssl-cert
158:    openssl x509 -req -sha256 \
159-            -days $DAYS \
160-            -in $domain.csr \
161-            -signkey $domain.key \
162-            -extfile <(printf "\n[SAN]\nsubjectAltName=DNS:$domain") \
163-            -extensions SAN \
164-            -out $domain.crt > /dev/null 2>&1
--
166:    openssl x509 -req -sha256 \
167-            -days $DAYS \
168-            -in $domain.csr \
169-            -signkey $domain.key \
170-            -extfile <(printf "\n[SAN]\nsubjectAltName=$dns_aliases") \
171-            -extensions SAN \
172-            -out $domain.crt > /dev/null 2>&1
root@debian:~# 

Ok, so the problem is /etc/ssl/openssl.cnf:

cat -A /etc/ssl/openssl.cnf

Currently, the v-generate-ssl-cert file on the main branch of the GitHub repository also needs the \n newline character added in order to generate the .csr and .crt files.

root@debian:~# # 手动跑三次,看 key 类型是否随 key_algo 变化
root@debian:~# D=blog.example.com; E="info@$D"
root@debian:~# C=US; S=California; L="San Francisco"; O=Hestia; OU=IT
root@debian:~# for algo in ecdsa-256 ecdsa-384 rsa; do
>   out=$(/usr/local/hestia/bin/v-generate-ssl-cert "$D" "$E" "$C" "$S" "$L" "$O" "$OU" "" shell "$algo" 2>&1)
>   d=$(echo "$out" | sed -n 's/^Directory: //p')
>   echo "=== $algo (dir=$d) ==="
>   ls -la "$d" 2>/dev/null
>   [ -f "$d/$D.csr" ] && echo "CSR EXISTS" || echo "CSR MISSING"
>   openssl pkey -in "$d/$D.key" -noout -text 2>/dev/null | head -1
> done
=== ecdsa-256 (dir=/tmp/tmp.iVEedN4OT5) ===
总计 4
drw-rw----  2 root root  60 10月24日 05:13 .
drwxrwxrwt 31 root root 740 10月24日 05:13 ..
-rw-------  1 root root 227 10月24日 05:13 blog.example.com.key
CSR MISSING
Private-Key: (256 bit)
=== ecdsa-384 (dir=/tmp/tmp.ej3iBc2poG) ===
总计 4
drw-rw----  2 root root  60 10月24日 05:13 .
drwxrwxrwt 32 root root 760 10月24日 05:13 ..
-rw-------  1 root root 288 10月24日 05:13 blog.example.com.key
CSR MISSING
Private-Key: (384 bit)
=== rsa (dir=/tmp/tmp.HxCMP3tddP) ===
总计 4
drw-rw----  2 root root   60 10月24日 05:13 .
drwxrwxrwt 33 root root  780 10月24日 05:13 ..
-rw-r--r--  1 root root 3268 10月24日 05:13 blog.example.com.key
CSR MISSING
Private-Key: (4096 bit, 2 primes)
root@debian:~# # 手动跑三次,看 key 类型是否随 key_algo 变化
root@debian:~# D=blog.example.com; E="info@$D"
root@debian:~# C=US; S=California; L="San Francisco"; O=Hestia; OU=IT
root@debian:~# for algo in ecdsa-256 ecdsa-384 rsa; do
>   out=$(/usr/local/hestia/bin/v-generate-ssl-cert "$D" "$E" "$C" "$S" "$L" "$O" "$OU" "" shell "$algo" 2>&1)
>   d=$(echo "$out" | sed -n 's/^Directory: //p')
>   echo "=== $algo (dir=$d) ==="
>   ls -la "$d" 2>/dev/null
>   [ -f "$d/$D.csr" ] && echo "CSR EXISTS" || echo "CSR MISSING"
>   openssl pkey -in "$d/$D.key" -noout -text 2>/dev/null | head -1
> done
=== ecdsa-256 (dir=/tmp/tmp.UG5Z1FERdp) ===
总计 12
drw-rw----  2 root root 100 10月24日 05:15 .
drwxrwxrwt 34 root root 800 10月24日 05:15 ..
-rw-r--r--  1 root root 912 10月24日 05:15 blog.example.com.crt
-rw-r--r--  1 root root 603 10月24日 05:15 blog.example.com.csr
-rw-------  1 root root 227 10月24日 05:15 blog.example.com.key
CSR EXISTS
Private-Key: (256 bit)
=== ecdsa-384 (dir=/tmp/tmp.bCcJDA6XHw) ===
总计 12
drw-rw----  2 root root 100 10月24日 05:15 .
drwxrwxrwt 35 root root 820 10月24日 05:15 ..
-rw-r--r--  1 root root 993 10月24日 05:15 blog.example.com.crt
-rw-r--r--  1 root root 688 10月24日 05:15 blog.example.com.csr
-rw-------  1 root root 288 10月24日 05:15 blog.example.com.key
CSR EXISTS
Private-Key: (384 bit)
=== rsa (dir=/tmp/tmp.l9jQQR0llI) ===
总计 12
drw-rw----  2 root root  100 10月24日 05:15 .
drwxrwxrwt 36 root root  840 10月24日 05:15 ..
-rw-r--r--  1 root root 2143 10月24日 05:15 blog.example.com.crt
-rw-r--r--  1 root root 1830 10月24日 05:15 blog.example.com.csr
-rw-r--r--  1 root root 3272 10月24日 05:15 blog.example.com.key
CSR EXISTS
Private-Key: (4096 bit, 2 primes)
root@debian:~# cat /usr/local/hestia/bin/v-generate-ssl-cert
#!/bin/bash
# info: generate self signed certificate and CSR request
# options: DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT] [KEY_ALGO]
#
# example: v-generate-ssl-cert example.com [email protected] USA California Monterey ACME.COM IT
#
# This function generates self signed SSL certificate and CSR request

#----------------------------------------------------------#
#                Variables & Functions                     #
#----------------------------------------------------------#

# Argument definition
domain=$1
domain=$(echo "$domain" | sed -e 's/\.*$//g' -e 's/^\.*//g')
domain_alias=$domain
email=$2
country=$3
state=$4
city=$5
org=$6
org_unit=$7
aliases=$8
format=${9-shell}
# Key algorithm: ecdsa-256 (default) | ecdsa-384 | rsa
key_algo="${10:-ecdsa-256}"
key_algo="${key_algo,,}"

# Set curve based on key_algo
if [ "$key_algo" = 'ecdsa-256' ]; then
        ec_curve='prime256v1'
elif [ "$key_algo" = 'ecdsa-384' ]; then
        ec_curve='secp384r1'
fi

KEY_SIZE=4096
DAYS=365

# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
source /etc/hestiacp/hestia.conf
# shellcheck source=/usr/local/hestia/func/main.sh
source $HESTIA/func/main.sh
# load config file
source_conf "$HESTIA/conf/hestia.conf"

# Json function
json_list_ssl() {
        jq -n \
                --arg domain "$domain" \
                --arg crt "$crt" \
                --arg key "$key" \
                --arg csr "$csr" \
                --arg dir "$workdir" \
                '{
            ($domain): {
                CRT: $crt,
                KEY: $key,
                CSR: $csr,
                DIR: $dir
            }
        }'
}
# Shell function
shell_list_ssl() {
        if [ -n "$crt" ]; then
                printf '%s\n' "$crt"
        fi

        if [ -n "$key" ]; then
                printf '\n%s\n' "$key"
        fi

        if [ -n "$csr" ]; then
                printf '\n%s\n' "$csr"
        fi

        printf '\nDirectory: %s\n' "$workdir"
}

# Additional argument formatting
format_domain_idn
if [[ "$email" = *[![:ascii:]]* ]]; then
        local=$(echo "$email" | cut -f1 -d'@')
        email_domain=$(echo "$email" | cut -f2 -d'@')
        email_domain_idn=$(idn2 --quiet $email_domain)
        email="$local"@"$email_domain_idn"
fi

#----------------------------------------------------------#
#                    Verifications                         #
#----------------------------------------------------------#

args_usage='DOMAIN EMAIL COUNTRY STATE CITY ORG UNIT [ALIASES] [FORMAT] [KEY_ALGO]'
check_args '7' "$#" "$args_usage"
is_format_valid 'domain' 'aliases' 'format' 'email' 'key_algo'
is_common_format_valid "$country" "country"
is_common_format_spaces_valid "$state" "state"
is_common_format_spaces_valid "$org" "org"
is_common_format_spaces_valid "$unit" "unit"

release="$(lsb_release -s -r)"

if [ -z "$email" ] && [ "$release" = "18.04" ]; then
        echo "Email address is required"
        exit 2
fi
if [ ! -f /root/.rnd ]; then
        touch /root/.rnd
fi

# Perform verification if read-only mode is enabled
check_hestia_demo_mode

#----------------------------------------------------------#
#                       Action                             #
#----------------------------------------------------------#

# Create temporary work directory
workdir=$(mktemp -d)
cd $workdir

# Generate private key
if [[ "$key_algo" = "ecdsa-256" || "$key_algo" = "ecdsa-384" ]]; then
        openssl ecparam -name "$ec_curve" -genkey -noout -out "$domain.key" 2> /dev/null
else
        openssl genrsa "$KEY_SIZE" > "$domain.key" 2> /dev/null
fi

subj=""
# Generate the CSR
if [ -n "$email" ]; then
        subj="/emailAddress=$email"
fi

subj="$subj/C=$country/ST=$state/L=$city/O=$org"
subj="$subj/OU=$org_unit"

# The CN (CommonName) has an ASN.1 limit of 64 characters in OpenSSL.
# If the domain exceeds this limit, the CN is omitted and only the SAN
# (subjectAltName) is trusted, which is what modern browsers validate.
if [ ${#domain_idn} -le 64 ]; then
        subj="$subj/CN=$domain_idn"
fi

if [ -e "/etc/ssl/openssl.cnf" ]; then
        ssl_conf='/etc/ssl/openssl.cnf'
else
        ssl_conf="/etc/pki/tls/openssl.cnf"
fi

if [ -z "$aliases" ]; then
        openssl req -sha256 -new \
                -batch \
                -subj "$subj" \
                -key $domain.key \
                -reqexts SAN \
                -config <(cat $ssl_conf \
                        <(printf "\n[SAN]\nsubjectAltName=DNS:$domain")) \
                -out $domain.csr > /dev/null 2>&1
else
        for alias in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
                if [[ "$alias" = *[![:ascii:]]* ]]; then
                        alias=$(idn2 --quiet $alias)
                fi
                dns_aliases="${dns_aliases}DNS:$alias,"
        done
        dns_aliases=$(echo $dns_aliases | sed "s/,$//")
        openssl req -sha256 -new \
                -batch \
                -subj "$subj" \
                -key $domain.key \
                -reqexts SAN \
                -config <(cat $ssl_conf \
                        <(printf "\n[SAN]\nsubjectAltName=$dns_aliases")) \
                -out $domain.csr > /dev/null 2>&1
fi

# Generate the cert 1 year
if [ -z "$aliases" ]; then
        openssl x509 -req -sha256 \
                -days $DAYS \
                -in $domain.csr \
                -signkey $domain.key \
                -extfile <(printf "\n[SAN]\nsubjectAltName=DNS:$domain") \
                -extensions SAN \
                -out $domain.crt > /dev/null 2>&1
else
        openssl x509 -req -sha256 \
                -days $DAYS \
                -in $domain.csr \
                -signkey $domain.key \
                -extfile <(printf "\n[SAN]\nsubjectAltName=$dns_aliases") \
                -extensions SAN \
                -out $domain.crt > /dev/null 2>&1
fi

# Listing certificates
if [ -e "$domain.crt" ]; then
        crt=$(< "$domain.crt")
fi

if [ -e "$domain.key" ]; then
        key=$(< "$domain.key")
fi

if [ -e "$domain.csr" ]; then
        csr=$(< "$domain.csr")
fi

case $format in
        json) json_list_ssl ;;
        plain | shell) shell_list_ssl ;;
        *) check_args '1' '0' '[FORMAT]' ;;
esac

# Don't allow non root users view folder
chmod 660 $workdir
# Clean up the mess
echo "rm -rf $workdir" | at -M "now +15 minute" > /dev/null 2>&1
# Delete tmp dir
#rm -rf $workdir

#----------------------------------------------------------#
#                       Hestia                             #
#----------------------------------------------------------#

# Logging
log_event "$OK" "$ARGUMENTS"

exitroot@debian:~# cat -A /etc/ssl/openssl.cnf
#$
# OpenSSL example configuration file.$
# See doc/man5/config.pod for more info.$
#$
# This is mostly being used for generation of certificate requests,$
# but may be used for auto loading of providers$
$
# Note that you can include other files from the main configuration$
# file using the .include directive.$
#.include filename$
$
# This definition stops the following lines choking if HOME isn't$
# defined.$
HOME^I^I^I= .$
$
# Use this in order to automatically load providers.$
openssl_conf = openssl_init$
$
# Comment out the next line to ignore configuration errors$
config_diagnostics = 1$
$
# Extra OBJECT IDENTIFIER info:$
# oid_file       = $ENV::HOME/.oid$
oid_section = new_oids$
$
# To use this configuration file with the "-extfile" option of the$
# "openssl x509" utility, name here the section containing the$
# X.509v3 extensions to use:$
# extensions^I^I=$
# (Alternatively, use a configuration file that has only$
# X.509v3 extensions in its main [= default] section.)$
$
[ new_oids ]$
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.$
# Add a simple OID like this:$
# testoid1=1.2.3.4$
# Or use config file substitution like this:$
# testoid2=${testoid1}.5.6$
$
# Policies used by the TSA examples.$
tsa_policy1 = 1.2.3.4.1$
tsa_policy2 = 1.2.3.4.5.6$
tsa_policy3 = 1.2.3.4.5.7$
$
# For FIPS$
# Optionally include a file that is generated by the OpenSSL fipsinstall$
# application. This file contains configuration data required by the OpenSSL$
# fips provider. It contains a named section e.g. [fips_sect] which is$
# referenced from the [provider_sect] below.$
# Refer to the OpenSSL security policy for more information.$
# .include fipsmodule.cnf$
$
[openssl_init]$
providers = provider_sect$
ssl_conf = ssl_sect$
$
# List of providers to load$
[provider_sect]$
default = default_sect$
# The fips section name should match the section name inside the$
# included fipsmodule.cnf.$
# fips = fips_sect$
$
# If no providers are activated explicitly, the default one is activated implicitly.$
# See man 7 OSSL_PROVIDER-default for more details.$
#$
# If you add a section explicitly activating any other provider(s), you most$
# probably need to explicitly activate the default provider, otherwise it$
# becomes unavailable in openssl.  As a consequence applications depending on$
# OpenSSL may not work correctly which could lead to significant system$
# problems including inability to remotely access the system.$
[default_sect]$
# activate = 1$
$
$
####################################################################$
[ ca ]$
default_ca^I= CA_default^I^I# The default ca section$
$
####################################################################$
[ CA_default ]$
$
dir^I^I= ./demoCA^I^I# Where everything is kept$
certs^I^I= $dir/certs^I^I# Where the issued certs are kept$
crl_dir^I^I= $dir/crl^I^I# Where the issued crl are kept$
database^I= $dir/index.txt^I# database index file.$
#unique_subject^I= no^I^I^I# Set to 'no' to allow creation of$
^I^I^I^I^I# several certs with same subject.$
new_certs_dir^I= $dir/newcerts^I^I# default place for new certs.$
$
certificate^I= $dir/cacert.pem ^I# The CA certificate$
serial^I^I= $dir/serial ^I^I# The current serial number$
crlnumber^I= $dir/crlnumber^I# the current crl number$
^I^I^I^I^I# must be commented out to leave a V1 CRL$
crl^I^I= $dir/crl.pem ^I^I# The current CRL$
private_key^I= $dir/private/cakey.pem # The private key$
$
x509_extensions^I= usr_cert^I^I# The extensions to add to the cert$
$
# Comment out the following two lines for the "traditional"$
# (and highly broken) format.$
name_opt ^I= ca_default^I^I# Subject Name options$
cert_opt ^I= ca_default^I^I# Certificate field options$
$
# Extension copying option: use with caution.$
# copy_extensions = copy$
$
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs$
# so this is commented out by default to leave a V1 CRL.$
# crlnumber must also be commented out to leave a V1 CRL.$
# crl_extensions^I= crl_ext$
$
default_days^I= 365^I^I^I# how long to certify for$
default_crl_days= 30^I^I^I# how long before next CRL$
default_md^I= default^I^I# use public key default MD$
preserve^I= no^I^I^I# keep passed DN ordering$
$
# A few difference way of specifying how similar the request should look$
# For type CA, the listed attributes must be the same, and the optional$
# and supplied fields are just that :-)$
policy^I^I= policy_match$
$
# For the CA policy$
[ policy_match ]$
countryName^I^I= match$
stateOrProvinceName^I= match$
organizationName^I= match$
organizationalUnitName^I= optional$
commonName^I^I= supplied$
emailAddress^I^I= optional$
$
# For the 'anything' policy$
# At this point in time, you must list all acceptable 'object'$
# types.$
[ policy_anything ]$
countryName^I^I= optional$
stateOrProvinceName^I= optional$
localityName^I^I= optional$
organizationName^I= optional$
organizationalUnitName^I= optional$
commonName^I^I= supplied$
emailAddress^I^I= optional$
$
####################################################################$
[ req ]$
default_bits^I^I= 2048$
default_keyfile ^I= privkey.pem$
distinguished_name^I= req_distinguished_name$
attributes^I^I= req_attributes$
x509_extensions^I= v3_ca^I# The extensions to add to the self signed cert$
$
# Passwords for private keys if not present they will be prompted for$
# input_password = secret$
# output_password = secret$
$
# This sets a mask for permitted string types. There are several options.$
# default: PrintableString, T61String, BMPString.$
# pkix^I : PrintableString, BMPString (PKIX recommendation before 2004)$
# utf8only: only UTF8Strings (PKIX recommendation after 2004).$
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).$
# MASK:XXXX a literal mask value.$
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.$
string_mask = utf8only$
$
req_extensions = v3_req # The extensions to add to a certificate request$
$
[ req_distinguished_name ]$
countryName^I^I^I= Country Name (2 letter code)$
countryName_default^I^I= AU$
countryName_min^I^I^I= 2$
countryName_max^I^I^I= 2$
$
stateOrProvinceName^I^I= State or Province Name (full name)$
stateOrProvinceName_default^I= Some-State$
$
localityName^I^I^I= Locality Name (eg, city)$
$
0.organizationName^I^I= Organization Name (eg, company)$
0.organizationName_default^I= Internet Widgits Pty Ltd$
$
# we can do this but it is not needed normally :-)$
#1.organizationName^I^I= Second Organization Name (eg, company)$
#1.organizationName_default^I= World Wide Web Pty Ltd$
$
organizationalUnitName^I^I= Organizational Unit Name (eg, section)$
#organizationalUnitName_default^I=$
$
commonName^I^I^I= Common Name (e.g. server FQDN or YOUR name)$
commonName_max^I^I^I= 64$
$
emailAddress^I^I^I= Email Address$
emailAddress_max^I^I= 64$
$
# SET-ex3^I^I^I= SET extension number 3$
$
[ req_attributes ]$
challengePassword^I^I= A challenge password$
challengePassword_min^I^I= 4$
challengePassword_max^I^I= 20$
$
unstructuredName^I^I= An optional company name$
$
[ usr_cert ]$
$
# These extensions are added when 'ca' signs a request.$
$
# This goes against PKIX guidelines but some CAs do it and some software$
# requires this to avoid interpreting an end user certificate as a CA.$
$
basicConstraints=CA:FALSE$
$
# This is typical in keyUsage for a client certificate.$
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment$
$
# PKIX recommendations harmless if included in all certificates.$
subjectKeyIdentifier=hash$
authorityKeyIdentifier=keyid,issuer$
$
# This stuff is for subjectAltName and issuerAltname.$
# Import the email address.$
# subjectAltName=email:copy$
# An alternative to produce certificates that aren't$
# deprecated according to PKIX.$
# subjectAltName=email:move$
$
# Copy subject details$
# issuerAltName=issuer:copy$
$
# This is required for TSA certificates.$
# extendedKeyUsage = critical,timeStamping$
$
[ v3_req ]$
$
# Extensions to add to a certificate request$
$
basicConstraints = CA:FALSE$
keyUsage = nonRepudiation, digitalSignature, keyEncipherment$
$
[ v3_ca ]$
$
$
# Extensions for a typical CA$
$
$
# PKIX recommendation.$
$
subjectKeyIdentifier=hash$
$
authorityKeyIdentifier=keyid:always,issuer$
$
basicConstraints = critical,CA:true$
$
# Key usage: this is typical for a CA certificate. However since it will$
# prevent it being used as an test self-signed certificate it is best$
# left out by default.$
# keyUsage = cRLSign, keyCertSign$
$
# Include email address in subject alt name: another PKIX recommendation$
# subjectAltName=email:copy$
# Copy issuer details$
# issuerAltName=issuer:copy$
$
# DER hex encoding of an extension: beware experts only!$
# obj=DER:02:03$
# Where 'obj' is a standard or added object$
# You can even override a supported extension:$
# basicConstraints= critical, DER:30:03:01:01:FF$
$
[ crl_ext ]$
$
# CRL extensions.$
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.$
$
# issuerAltName=issuer:copy$
authorityKeyIdentifier=keyid:always$
$
[ proxy_cert_ext ]$
# These extensions should be added when creating a proxy certificate$
$
# This goes against PKIX guidelines but some CAs do it and some software$
# requires this to avoid interpreting an end user certificate as a CA.$
$
basicConstraints=CA:FALSE$
$
# This is typical in keyUsage for a client certificate.$
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment$
$
# PKIX recommendations harmless if included in all certificates.$
subjectKeyIdentifier=hash$
authorityKeyIdentifier=keyid,issuer$
$
# This stuff is for subjectAltName and issuerAltname.$
# Import the email address.$
# subjectAltName=email:copy$
# An alternative to produce certificates that aren't$
# deprecated according to PKIX.$
# subjectAltName=email:move$
$
# Copy subject details$
# issuerAltName=issuer:copy$
$
# This really needs to be in place for it to be a proxy certificate.$
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo$
$
####################################################################$
[ tsa ]$
$
default_tsa = tsa_config1^I# the default TSA section$
$
[ tsa_config1 ]$
$
# These are used by the TSA reply generation only.$
dir^I^I= ./demoCA^I^I# TSA root directory$
serial^I^I= $dir/tsaserial^I# The current serial number (mandatory)$
crypto_device^I= builtin^I^I# OpenSSL engine to use for signing$
signer_cert^I= $dir/tsacert.pem ^I# The TSA signing certificate$
^I^I^I^I^I# (optional)$
certs^I^I= $dir/cacert.pem^I# Certificate chain to include in reply$
^I^I^I^I^I# (optional)$
signer_key^I= $dir/private/tsakey.pem # The TSA private key (optional)$
signer_digest  = sha256^I^I^I# Signing digest to use. (Optional)$
default_policy^I= tsa_policy1^I^I# Policy if request did not specify it$
^I^I^I^I^I# (optional)$
other_policies^I= tsa_policy2, tsa_policy3^I# acceptable policies (optional)$
digests     = sha1, sha256, sha384, sha512  # Acceptable message digests (mandatory)$
accuracy^I= secs:1, millisecs:500, microsecs:100^I# (optional)$
clock_precision_digits  = 0^I# number of digits after dot. (optional)$
ordering^I^I= yes^I# Is ordering defined for timestamps?$
^I^I^I^I# (optional, default: no)$
tsa_name^I^I= yes^I# Must the TSA name be included in the reply?$
^I^I^I^I# (optional, default: no)$
ess_cert_id_chain^I= no^I# Must the ESS cert id chain be included?$
^I^I^I^I# (optional, default: no)$
ess_cert_id_alg^I^I= sha256^I# algorithm to compute certificate$
^I^I^I^I# identifier (optional, default: sha256)$
$
[insta] # CMP using Insta Demo CA$
# Message transfer$
server = pki.certificate.fi:8700$
# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080$
# tls_use = 0$
path = pkix/$
$
# Server authentication$
recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer$
ignore_keyusage = 1 # quirk needed to accept Insta CA cert not including digitalsignature$
unprotected_errors = 1 # quirk needed to accept negative responses possibly not protected$
extracertsout = insta.extracerts.pem$
$
# Client authentication$
ref = 3078 # user identification$
secret = pass:insta # can be used for both client and server side$
$
# Generic message options$
cmd = ir # default operation, can be overridden on cmd line with, e.g., kur$
$
# Certificate enrollment$
subject = "/CN=openssl-cmp-test"$
newkey = insta.priv.pem$
out_trusted = apps/insta.ca.crt # does not include keyUsage digitalSignature$
certout = insta.cert.pem$
$
[pbm] # Password-based protection for Insta CA$
# Server and client authentication$
ref = $insta::ref # 3078$
secret = $insta::secret # pass:insta$
$
[signature] # Signature-based protection for Insta CA$
# Server authentication$
trusted = $insta::out_trusted # apps/insta.ca.crt$
$
# Client authentication$
secret = # disable PBM$
key = $insta::newkey # insta.priv.pem$
cert = $insta::certout # insta.cert.pem$
$
[ir]$
cmd = ir$
$
[cr]$
cmd = cr$
$
[kur]$
# Certificate update$
cmd = kur$
oldcert = $insta::certout # insta.cert.pem$
$
[rr]$
# Certificate revocation$
cmd = rr $
oldcert = $insta::certout # insta.cert.pem$
 $
[ssl_sect] $
system_default = hestia_openssl_sect $
$
[hestia_openssl_sect] $
Ciphersuites = TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384$
Options = PrioritizeChaCharoot@debian:~# 

Yes, great, that’s the reason I asked to try it but I need your /etc/ssl/openssl.cnf to reproduce the issue.

I added the full content of the /etc/ssl/openssl.cnf file in the code block above

I apologize, I didn’t see it

exitroot@debian:~# cat -A /etc/ssl/openssl.cnf
#$
# OpenSSL example configuration file.$
# See doc/man5/config.pod for more info.$
#$
# This is mostly being used for generation of certificate requests,$
# but may be used for auto loading of providers$
$
# Note that you can include other files from the main configuration$
# file using the .include directive.$
#.include filename$
$
# This definition stops the following lines choking if HOME isn't$
# defined.$
HOME^I^I^I= .$
$
# Use this in order to automatically load providers.$
openssl_conf = openssl_init$
$
# Comment out the next line to ignore configuration errors$
config_diagnostics = 1$
$
# Extra OBJECT IDENTIFIER info:$
# oid_file       = $ENV::HOME/.oid$
oid_section = new_oids$
$
# To use this configuration file with the "-extfile" option of the$
# "openssl x509" utility, name here the section containing the$
# X.509v3 extensions to use:$
# extensions^I^I=$
# (Alternatively, use a configuration file that has only$
# X.509v3 extensions in its main [= default] section.)$
$
[ new_oids ]$
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.$
# Add a simple OID like this:$
# testoid1=1.2.3.4$
# Or use config file substitution like this:$
# testoid2=${testoid1}.5.6$
$
# Policies used by the TSA examples.$
tsa_policy1 = 1.2.3.4.1$
tsa_policy2 = 1.2.3.4.5.6$
tsa_policy3 = 1.2.3.4.5.7$
$
# For FIPS$
# Optionally include a file that is generated by the OpenSSL fipsinstall$
# application. This file contains configuration data required by the OpenSSL$
# fips provider. It contains a named section e.g. [fips_sect] which is$
# referenced from the [provider_sect] below.$
# Refer to the OpenSSL security policy for more information.$
# .include fipsmodule.cnf$
$
[openssl_init]$
providers = provider_sect$
ssl_conf = ssl_sect$
$
# List of providers to load$
[provider_sect]$
default = default_sect$
# The fips section name should match the section name inside the$
# included fipsmodule.cnf.$
# fips = fips_sect$
$
# If no providers are activated explicitly, the default one is activated implicitly.$
# See man 7 OSSL_PROVIDER-default for more details.$
#$
# If you add a section explicitly activating any other provider(s), you most$
# probably need to explicitly activate the default provider, otherwise it$
# becomes unavailable in openssl.  As a consequence applications depending on$
# OpenSSL may not work correctly which could lead to significant system$
# problems including inability to remotely access the system.$
[default_sect]$
# activate = 1$
$
$
####################################################################$
[ ca ]$
default_ca^I= CA_default^I^I# The default ca section$
$
####################################################################$
[ CA_default ]$
$
dir^I^I= ./demoCA^I^I# Where everything is kept$
certs^I^I= $dir/certs^I^I# Where the issued certs are kept$
crl_dir^I^I= $dir/crl^I^I# Where the issued crl are kept$
database^I= $dir/index.txt^I# database index file.$
#unique_subject^I= no^I^I^I# Set to 'no' to allow creation of$
^I^I^I^I^I# several certs with same subject.$
new_certs_dir^I= $dir/newcerts^I^I# default place for new certs.$
$
certificate^I= $dir/cacert.pem ^I# The CA certificate$
serial^I^I= $dir/serial ^I^I# The current serial number$
crlnumber^I= $dir/crlnumber^I# the current crl number$
^I^I^I^I^I# must be commented out to leave a V1 CRL$
crl^I^I= $dir/crl.pem ^I^I# The current CRL$
private_key^I= $dir/private/cakey.pem # The private key$
$
x509_extensions^I= usr_cert^I^I# The extensions to add to the cert$
$
# Comment out the following two lines for the "traditional"$
# (and highly broken) format.$
name_opt ^I= ca_default^I^I# Subject Name options$
cert_opt ^I= ca_default^I^I# Certificate field options$
$
# Extension copying option: use with caution.$
# copy_extensions = copy$
$
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs$
# so this is commented out by default to leave a V1 CRL.$
# crlnumber must also be commented out to leave a V1 CRL.$
# crl_extensions^I= crl_ext$
$
default_days^I= 365^I^I^I# how long to certify for$
default_crl_days= 30^I^I^I# how long before next CRL$
default_md^I= default^I^I# use public key default MD$
preserve^I= no^I^I^I# keep passed DN ordering$
$
# A few difference way of specifying how similar the request should look$
# For type CA, the listed attributes must be the same, and the optional$
# and supplied fields are just that :-)$
policy^I^I= policy_match$
$
# For the CA policy$
[ policy_match ]$
countryName^I^I= match$
stateOrProvinceName^I= match$
organizationName^I= match$
organizationalUnitName^I= optional$
commonName^I^I= supplied$
emailAddress^I^I= optional$
$
# For the 'anything' policy$
# At this point in time, you must list all acceptable 'object'$
# types.$
[ policy_anything ]$
countryName^I^I= optional$
stateOrProvinceName^I= optional$
localityName^I^I= optional$
organizationName^I= optional$
organizationalUnitName^I= optional$
commonName^I^I= supplied$
emailAddress^I^I= optional$
$
####################################################################$
[ req ]$
default_bits^I^I= 2048$
default_keyfile ^I= privkey.pem$
distinguished_name^I= req_distinguished_name$
attributes^I^I= req_attributes$
x509_extensions^I= v3_ca^I# The extensions to add to the self signed cert$
$
# Passwords for private keys if not present they will be prompted for$
# input_password = secret$
# output_password = secret$
$
# This sets a mask for permitted string types. There are several options.$
# default: PrintableString, T61String, BMPString.$
# pkix^I : PrintableString, BMPString (PKIX recommendation before 2004)$
# utf8only: only UTF8Strings (PKIX recommendation after 2004).$
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).$
# MASK:XXXX a literal mask value.$
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.$
string_mask = utf8only$
$
req_extensions = v3_req # The extensions to add to a certificate request$
$
[ req_distinguished_name ]$
countryName^I^I^I= Country Name (2 letter code)$
countryName_default^I^I= AU$
countryName_min^I^I^I= 2$
countryName_max^I^I^I= 2$
$
stateOrProvinceName^I^I= State or Province Name (full name)$
stateOrProvinceName_default^I= Some-State$
$
localityName^I^I^I= Locality Name (eg, city)$
$
0.organizationName^I^I= Organization Name (eg, company)$
0.organizationName_default^I= Internet Widgits Pty Ltd$
$
# we can do this but it is not needed normally :-)$
#1.organizationName^I^I= Second Organization Name (eg, company)$
#1.organizationName_default^I= World Wide Web Pty Ltd$
$
organizationalUnitName^I^I= Organizational Unit Name (eg, section)$
#organizationalUnitName_default^I=$
$
commonName^I^I^I= Common Name (e.g. server FQDN or YOUR name)$
commonName_max^I^I^I= 64$
$
emailAddress^I^I^I= Email Address$
emailAddress_max^I^I= 64$
$
# SET-ex3^I^I^I= SET extension number 3$
$
[ req_attributes ]$
challengePassword^I^I= A challenge password$
challengePassword_min^I^I= 4$
challengePassword_max^I^I= 20$
$
unstructuredName^I^I= An optional company name$
$
[ usr_cert ]$
$
# These extensions are added when 'ca' signs a request.$
$
# This goes against PKIX guidelines but some CAs do it and some software$
# requires this to avoid interpreting an end user certificate as a CA.$
$
basicConstraints=CA:FALSE$
$
# This is typical in keyUsage for a client certificate.$
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment$
$
# PKIX recommendations harmless if included in all certificates.$
subjectKeyIdentifier=hash$
authorityKeyIdentifier=keyid,issuer$
$
# This stuff is for subjectAltName and issuerAltname.$
# Import the email address.$
# subjectAltName=email:copy$
# An alternative to produce certificates that aren't$
# deprecated according to PKIX.$
# subjectAltName=email:move$
$
# Copy subject details$
# issuerAltName=issuer:copy$
$
# This is required for TSA certificates.$
# extendedKeyUsage = critical,timeStamping$
$
[ v3_req ]$
$
# Extensions to add to a certificate request$
$
basicConstraints = CA:FALSE$
keyUsage = nonRepudiation, digitalSignature, keyEncipherment$
$
[ v3_ca ]$
$
$
# Extensions for a typical CA$
$
$
# PKIX recommendation.$
$
subjectKeyIdentifier=hash$
$
authorityKeyIdentifier=keyid:always,issuer$
$
basicConstraints = critical,CA:true$
$
# Key usage: this is typical for a CA certificate. However since it will$
# prevent it being used as an test self-signed certificate it is best$
# left out by default.$
# keyUsage = cRLSign, keyCertSign$
$
# Include email address in subject alt name: another PKIX recommendation$
# subjectAltName=email:copy$
# Copy issuer details$
# issuerAltName=issuer:copy$
$
# DER hex encoding of an extension: beware experts only!$
# obj=DER:02:03$
# Where 'obj' is a standard or added object$
# You can even override a supported extension:$
# basicConstraints= critical, DER:30:03:01:01:FF$
$
[ crl_ext ]$
$
# CRL extensions.$
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.$
$
# issuerAltName=issuer:copy$
authorityKeyIdentifier=keyid:always$
$
[ proxy_cert_ext ]$
# These extensions should be added when creating a proxy certificate$
$
# This goes against PKIX guidelines but some CAs do it and some software$
# requires this to avoid interpreting an end user certificate as a CA.$
$
basicConstraints=CA:FALSE$
$
# This is typical in keyUsage for a client certificate.$
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment$
$
# PKIX recommendations harmless if included in all certificates.$
subjectKeyIdentifier=hash$
authorityKeyIdentifier=keyid,issuer$
$
# This stuff is for subjectAltName and issuerAltname.$
# Import the email address.$
# subjectAltName=email:copy$
# An alternative to produce certificates that aren't$
# deprecated according to PKIX.$
# subjectAltName=email:move$
$
# Copy subject details$
# issuerAltName=issuer:copy$
$
# This really needs to be in place for it to be a proxy certificate.$
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo$
$
####################################################################$
[ tsa ]$
$
default_tsa = tsa_config1^I# the default TSA section$
$
[ tsa_config1 ]$
$
# These are used by the TSA reply generation only.$
dir^I^I= ./demoCA^I^I# TSA root directory$
serial^I^I= $dir/tsaserial^I# The current serial number (mandatory)$
crypto_device^I= builtin^I^I# OpenSSL engine to use for signing$
signer_cert^I= $dir/tsacert.pem ^I# The TSA signing certificate$
^I^I^I^I^I# (optional)$
certs^I^I= $dir/cacert.pem^I# Certificate chain to include in reply$
^I^I^I^I^I# (optional)$
signer_key^I= $dir/private/tsakey.pem # The TSA private key (optional)$
signer_digest  = sha256^I^I^I# Signing digest to use. (Optional)$
default_policy^I= tsa_policy1^I^I# Policy if request did not specify it$
^I^I^I^I^I# (optional)$
other_policies^I= tsa_policy2, tsa_policy3^I# acceptable policies (optional)$
digests     = sha1, sha256, sha384, sha512  # Acceptable message digests (mandatory)$
accuracy^I= secs:1, millisecs:500, microsecs:100^I# (optional)$
clock_precision_digits  = 0^I# number of digits after dot. (optional)$
ordering^I^I= yes^I# Is ordering defined for timestamps?$
^I^I^I^I# (optional, default: no)$
tsa_name^I^I= yes^I# Must the TSA name be included in the reply?$
^I^I^I^I# (optional, default: no)$
ess_cert_id_chain^I= no^I# Must the ESS cert id chain be included?$
^I^I^I^I# (optional, default: no)$
ess_cert_id_alg^I^I= sha256^I# algorithm to compute certificate$
^I^I^I^I# identifier (optional, default: sha256)$
$
[insta] # CMP using Insta Demo CA$
# Message transfer$
server = pki.certificate.fi:8700$
# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080$
# tls_use = 0$
path = pkix/$
$
# Server authentication$
recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer$
ignore_keyusage = 1 # quirk needed to accept Insta CA cert not including digitalsignature$
unprotected_errors = 1 # quirk needed to accept negative responses possibly not protected$
extracertsout = insta.extracerts.pem$
$
# Client authentication$
ref = 3078 # user identification$
secret = pass:insta # can be used for both client and server side$
$
# Generic message options$
cmd = ir # default operation, can be overridden on cmd line with, e.g., kur$
$
# Certificate enrollment$
subject = "/CN=openssl-cmp-test"$
newkey = insta.priv.pem$
out_trusted = apps/insta.ca.crt # does not include keyUsage digitalSignature$
certout = insta.cert.pem$
$
[pbm] # Password-based protection for Insta CA$
# Server and client authentication$
ref = $insta::ref # 3078$
secret = $insta::secret # pass:insta$
$
[signature] # Signature-based protection for Insta CA$
# Server authentication$
trusted = $insta::out_trusted # apps/insta.ca.crt$
$
# Client authentication$
secret = # disable PBM$
key = $insta::newkey # insta.priv.pem$
cert = $insta::certout # insta.cert.pem$
$
[ir]$
cmd = ir$
$
[cr]$
cmd = cr$
$
[kur]$
# Certificate update$
cmd = kur$
oldcert = $insta::certout # insta.cert.pem$
$
[rr]$
# Certificate revocation$
cmd = rr $
oldcert = $insta::certout # insta.cert.pem$
 $
[ssl_sect] $
system_default = hestia_openssl_sect $
$
[hestia_openssl_sect] $
Ciphersuites = TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384$
Options = PrioritizeChaCharoot@debian:~#

I think I get it, is this problem caused by my server’s /etc/ssl/openssl.cnf file?

Yes, there was no line feed at the end of the file you pasted previously, which is why it failed. It worked when you modified v-generate-ssl-cert to use a temporary file or added a line feed (\n) in printf, as in <(printf "\n[SAN]\nsubjectAltName.

I don’t know how your openssl.cnf file ended up like that.