This assumes you are using common GNU tools, so that your hostname
and getent
commands exist and function the same. Obviously update /L=Location/ST=State/C=GB
to reflect your own location.
openssl req -x509 \
-keyout "$(hostname -f).key" \
-out "$(hostname -f).crt" \
-new -newkey rsa:4096 -nodes -sha256 -days 1180 \
-subj "/CN=$(hostname -f)/O=$(hostname -d)/OU=$(getent passwd "$USER" | \
cut -d':' -f5 | sed 's/,.*//')/L=Location/ST=State/C=GB" \
-extensions EXT -config <( \
printf "[dn]\nCN=%s\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:%s\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth" \
"$(hostname -f)" "$(hostname -f)")
You can then examine the resulting public certificate:
openssl x509 -in "$(hostname -f).crt" -text -noout
It should be noted that major browsers will refuse to use any SSL certificate that has an expiration date more than 39 months in to the future, hence the rather arbitary looking -days 1180
argument.
Google stopped trusting the certificate common name (CN) from Chrome 59. This certificate correctly encodes the distinguished name and subject alternative name, so it should play nicely with recent versions of Chrome.
https://github.com/jsha/minica is also interesting.