Local RootCA Certificate Authority with OpenSSL
by Ramses Soto-Navarro ramses@sotosystems.com, Aug 24, 2026
Overview
Bash script of OpenSSL commands in order to create:
- Local Certificate Authority (CA)
- Signed certificate
- Wildcard cert
- SAN DNS for signed cert
Audience is experienced Linux systems administrators.
About the Script
myrootca.sh script:
- Follow the logic and modify variables and functions as needed.
- Creates local Certificate Authority certificate, also generating a CA key pair
- Creates local signed client certificate.
- For the CN variable modify for a wildcard or a subdomain.
- For the SAN variable, add as many needed or comment out.
- Great for dedicated certificate server; for testing and signing certs on-prem.
TODO:
The Script
$ cat myrootca.sh
#!/bin/bash
# Create a local RootCA for example.com.
# Signs a wildcard certificate for example.com.
# Everything can be modified.
# Modify the client NAME and CN here:
export ROOTCA=exampleca
export NAME=example.com
export CN=*.example.com
export SAN='DNS:example.com,DNS:://example.com,DNS:www.example.com,IP:192.168.1.20'
###########################################
# RootCA configuration file
###########################################
f_openssl_cnf () {
cat > openssl.cnf <<EOF
[ ca ]
default_ca = ExampleCA
[ CA_default ]
preserve = no
[ req ]
prompt = no
default_bits = 4096
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
C = US
ST = FL
L = Hialeah
O = ExampleCA
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOF
}
###########################################
# Create RootCA certificate
###########################################
f_create_rootca () {
openssl genrsa -out $ROOTCA.key 4096
openssl req -config openssl.cnf -new -days 3650 -x509
-extensions v3_ca -key $ROOTCA.key -out $ROOTCA.pem
}
###########################################
# Create client key and CSR
###########################################
f_create_client_key_and_csr () {
#Create client key and a cert signing request;
#replace -subj values with org name:
openssl req
-newkey rsa:2048
-nodes
-subj "/CN=$CN"
-keyout $NAME.key
-out $NAME.csr
}
###########################################
# Create client extensions
###########################################
f_create_client_extensions () {
#Prevent cert from acting as a CA.
#Add SAN below if necessary:
cat > client-cert-extensions.cnf <<EOF
basicConstraints = CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[SAN]
subjectAltName = "$SAN"
EOF
}
###########################################
# Sign client cert
###########################################
f_sign_client_cert () {
openssl x509
-req
-days 3650
-in $NAME.csr
-CA $ROOTCA.pem
-CAkey $ROOTCA.key
-CAcreateserial
-extfile client-cert-extensions.cnf
-extensions SAN
-out $NAME.pem
}
###########################################
# Verify signed cert against RootCA
###########################################
f_verify () {
openssl verify -CAfile $ROOTCA.pem $NAME.pem
}
###########################################
# Uncomment as needed
###########################################
f_openssl_cnf
f_create_rootca
f_create_client_key_and_csr
f_create_client_extensions
f_sign_client_cert
f_verify
Results
Notice the following for the CA cert:
- Not After : Aug 21 16:03:13 2036 GMT
- CA:TRUE
Notice the following for the signed cert:
- Issuer: C=US, ST=FL, L=Hialeah, O=ExampleCA
- Not After : Aug 21 16:03:13 2036 GMT
- Subject: CN=*.example.com
- X509v3 Subject Alternative Name:
RootCA:
$ ls -lh total 88K -rw-r--r-- 1 ramses users 248 Aug 24 12:03 client-cert-extensions.cnf -rw------- 1 ramses users 3.2K Aug 24 12:03 exampleca.key -rw-r--r-- 1 ramses users 2.0K Aug 24 12:03 exampleca.pem -rw-r--r-- 1 ramses users 41 Aug 24 12:03 exampleca.srl -rw-r--r-- 1 ramses users 895 Aug 24 12:03 example.com.csr -rw------- 1 ramses users 1.7K Aug 24 12:03 example.com.key -rw-r--r-- 1 ramses users 1.6K Aug 24 12:03 example.com.pem -rwxr-xr-x 1 ramses root 2.7K Aug 24 12:03 myrootca.sh -rw-r--r-- 1 ramses users 394 Aug 24 12:03 openssl.cnf $ openssl x509 -text -in exampleca.pem Certificate: Data: Version: 3 (0x2) Serial Number: 3d:12:df:08:94:d9:1d:a4:72:ea:99:50:cb:a9:0b:f6:51:77:70:77 Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=FL, L=Hialeah, O=ExampleCA Validity Not Before: Aug 24 16:03:13 2026 GMT Not After : Aug 21 16:03:13 2036 GMT Subject: C=US, ST=FL, L=Hialeah, O=ExampleCA Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: 00:b3:78:0d:c3:16:d6:e2:87:b0:85:f7:08:7b:73: ad:59:45:b5:cc:eb:e1:df:7d:6b:36:f1:a1:28:64: 69:3e:67:bc:21:2f:4c:7c:3b:fc:5a:a1:dd:09:9c: ... Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: AC:67:8F:92:86:16:34:99:E5:E0:48:D2:C5:7B:A1:BB:7A:A0:54:51 X509v3 Authority Key Identifier: AC:67:8F:92:86:16:34:99:E5:E0:48:D2:C5:7B:A1:BB:7A:A0:54:51 X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption Signature Value: 86:ba:4f:ce:49:3e:cc:33:d2:0d:71:62:d7:f7:83:7b:b4:b6: bf:5f:8f:f6:c0:41:98:e0:12:68:6c:5a:5a:f4:56:dc:aa:69: 4e:97:c7:a6:15:68:16:6a:41:85:8f:c4:c8:01:f1:63:89:b2: ... -----BEGIN CERTIFICATE----- MIIFcTCCA1mgAwIBAgIUPRLfCJTZHaRy6plQy6kL9lF3cHcwDQYJKoZIhvcNAQEL BQAwQDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkZMMRAwDgYDVQQHDAdIaWFsZWFo MRIwEAYDVQQKDAlFeGFtcGxlQ0EwHhcNMjYwODI0MTYwMzEzWhcNMzYwODIxMTYw ... -----END CERTIFICATE-----
Signed Cert:
$ openssl x509 -text -in example.com.pem Certificate: Data: Version: 3 (0x2) Serial Number: 42:c6:f3:88:8b:6b:b6:9b:37:5f:0d:b0:7d:11:40:df:91:69:ff:cf Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=FL, L=Hialeah, O=ExampleCA Validity Not Before: Aug 24 16:03:13 2026 GMT Not After : Aug 21 16:03:13 2036 GMT Subject: CN=*.example.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:cf:90:86:06:1e:b3:63:8b:8f:e3:29:39:f2:fa: 4a:54:77:68:ae:67:c9:39:93:63:21:13:2b:9f:2e: 71:1e:9a:85:74:02:e7:3e:86:5f:05:41:de:3d:18: ... Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Alternative Name: DNS:example.com, DNS:://example.com, DNS:www.example.com, IP Address:192.168.1.20 X509v3 Subject Key Identifier: 5C:73:0D:DC:F0:7F:61:6F:31:DA:5C:D7:8D:DE:22:34:B2:C8:E3:80 X509v3 Authority Key Identifier: AC:67:8F:92:86:16:34:99:E5:E0:48:D2:C5:7B:A1:BB:7A:A0:54:51 Signature Algorithm: sha256WithRSAEncryption Signature Value: 47:61:a5:b0:b8:f6:1d:bc:46:20:36:a7:04:1a:2e:d6:ff:8b: e0:08:38:94:63:86:40:33:9e:d8:f8:1f:4e:3d:5b:37:b3:0d: bd:75:39:30:de:29:63:63:b4:c9:a3:17:cd:76:47:d5:2a:11: ... -----BEGIN CERTIFICATE----- MIIEaDCCAlCgAwIBAgIUQsbziItrtps3Xw2wfRFA35Fp/88wDQYJKoZIhvcNAQEL BQAwQDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkZMMRAwDgYDVQQHDAdIaWFsZWFo MRIwEAYDVQQKDAlFeGFtcGxlQ0EwHhcNMjYwODI0MTYwMzEzWhcNMzYwODIxMTYw ... -----END CERTIFICATE-----
Reserved Domains
DNS domain names reserved for testing, safe experimentation and config examples:
example.com example.net example.org invalid.com invalid.net invalid.org test.com test.net test.org
The End.
htDig Search Engine Installation on Debian 12
by Ramses Soto-Navarro ramses@sotosystems.com, 6/12/2025
Overview
htDig is a light web search engine written in C++. I’ve been using it for almost 20 years; makes it easy to search lots of text; great for IT administrators that need to search their own technical notes. htDig can also parse pdf, doc, and other types alike. htDig uses CGI. It is an old and simple web search engine but it still works great and is simple to setup once you know how. Here I put together some steps for a quick setup.
Simple Backup Script
Simple Backup Script
A simple backup script which backs up the OS directories of a Linux system remotely. root SSH keys must be configured between systems. SSHFS must be installed and the mailer must be running and configured to send mail. The script mounts the root directory of another system, in read-only mode, via SSHFS. It finds remote incremental files of OS directories only, which are one day old, then creates a tarball in the /dump/os/ directory; else a full backup every Friday. Next, deletes backup files more than 2 weeks old; all scheduled via cron. Last, it sends an email of the success or failure.