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:

  • Revocation lists

    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.

    [Read more…]

    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.

    [Read more…]