1. Introduction

Now, imagine that you are a network administrator who manages several services within the nexus.org domain. Your boss has tasked you to introduce Gitlab as a new service to your fellow developers in your organization, with it’s planned URL as https://gitlab.nexus.org.

Using this example, we will be covering some basic, yet convenient OpenSSL commands to easily get you started on self-signed certificates!

2. Generating CA Key & Cert

If you already have a set of existing CA key and certificate, you can ignore this section. Else, we will need to generate one first. You may follow the template below and edit the values only for -days, -keyout, -out and -subj options.

$ openssl req -x509 \
  -newkey rsa:4096 -sha256 -nodes \
  -days 1000 \
  -keyout ca.key \
  -out ca.crt -outform PEM \
  -subj "/C=SG/ST=Singapore/L=Singapore/O=Nexus/OU=Infra/CN=ca.nexus.org/emailAddress=admin@nexus.org" \
  -addext "subjectKeyIdentifier=hash" \
  -addext "authorityKeyIdentifier=keyid:always,issuer" \
  -addext "basicConstraints=critical,CA:true" \
  -addext "keyUsage=keyCertSign,cRLSign"
Generating CA Key & Cert

3. Generating Server Key & Certificate Signing Request (CSR)

Before we can even get our server’s certificate, we need to execute an intermediate step to generate a Certificate Signing Request (CSR), along with its private key.

Important
  • Pay special attention to subjectAltName extension. Its FQDN must be correct!

$ openssl req \
  -newkey rsa:2048 -sha256 -nodes \
  -keyout server.key \
  -out server.csr -outform PEM \
  -subj "/C=SG/ST=Singapore/L=Singapore/O=Nexus/CN=gitlab.nexus.org/emailAddress=admin@nexus.org" \
  -addext "subjectKeyIdentifier=hash" \
  -addext "basicConstraints=CA:FALSE" \
  -addext "keyUsage=digitalSignature,keyEncipherment" \
  -addext "subjectAltName=DNS:gitlab.nexus.org"
Generating Server Key & CSR

4. Signing Server CSR

Lastly, we will use the CA private key and certificate to sign the CSR.

Important
  • Pay special attention to subjectAltName extension. Its FQDN must match the one defined in the CSR!

$ openssl x509 -req \
  -in server.csr \
  -CA ca.crt \
  -CAkey ca.key \
  -CAcreateserial \
  -out server.crt \
  -days 1000 \
  -sha256 \
  -extfile <(printf "[ext]\nsubjectAltName=DNS:gitlab.nexus.org\nbasicConstraints=CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment") \
  -extensions ext
Signing Server CSR

5. Conclusion

And that’s it! You’ve just created your own Certificate Authority (CA) and issued a self-signed certificate for a service under your domain. While this approach is perfectly fine for internal services, testing, or lab environments, remember that browsers and clients won’t trust your CA by default. You’ll need to explicitly import your CA certificate into their trust stores to avoid TLS warnings.

For production-facing services, it’s strongly recommended to generate certificates from a trusted public CA (e.g., Let’s Encrypt) to ensure universal trust and avoid security pitfalls.

Still, being comfortable with OpenSSL and self-signed certificates is a great skill to have as a sysadmin or developer.