How to Generate a CSR on Linux

Introduction

A Certificate Signing Request (CSR) is a required step when requesting an SSL/TLS certificate from a Certificate Authority (CA). The CSR contains information about the server, organization, and the public key that will be included in the certificate.

On Linux systems, CSRs are commonly generated using the OpenSSL toolkit. This document explains how to generate a CSR securely and correctly for web servers, load balancers, APIs, and internal applications.

Target audience: DevOps engineers, platform engineers, system administrators, and IT operations teams.


The Problem

Organizations frequently need to request or renew TLS certificates for:

  • Web applications
  • Reverse proxies
  • Kubernetes ingress controllers
  • API gateways
  • Internal PKI environments

Improper CSR generation can lead to:

  • Incorrect Common Name (CN)
  • Missing Subject Alternative Names (SANs)
  • Weak cryptographic algorithms
  • Private key exposure
  • Certificate issuance delays

A standardized CSR generation procedure helps reduce operational risk and improves certificate lifecycle management.


Solution

Prerequisites

Verify OpenSSL is installed:

openssl version

Example output:

OpenSSL 3.0.2 15 Mar 2022

If OpenSSL is not installed:

Ubuntu / Debian

sudo apt update
sudo apt install openssl

RHEL / CentOS / Rocky Linux

sudo dnf install openssl

Step 1 — Create a Private Key

Generate a new RSA private key:

openssl genrsa -out server.key 4096

Explanation:

  • server.key = private key file
  • 4096 = key length in bits

Recommended minimum key length:

EnvironmentRecommended
Internal services2048-bit
Internet-facing services4096-bit

Verify the private key:

openssl rsa -in server.key -check

Example output:

RSA key ok

Step 2 — Generate the CSR

Generate the CSR using the private key:

openssl req -new -key server.key -out server.csr

You will be prompted for certificate details.

Example:

Country Name (2 letter code) [AU]:NL
State or Province Name (full name) []:Zuid-Holland
Locality Name (eg, city) []:The Hague
Organization Name (eg, company) []:Example Municipality
Organizational Unit Name (eg, section) []:IT Operations
Common Name (e.g. server FQDN or YOUR name) []:portal.example.gov
Email Address []:admin@example.gov

Step 3 — Verify the CSR

Inspect the generated CSR:

openssl req -text -noout -verify -in server.csr

This validates:

  • CSR structure
  • Public key
  • Distinguished Name (DN)
  • Signature integrity

Example output excerpt:

Certificate Request:
    Subject:
        C = NL
        ST = Zuid-Holland
        L = The Hague
        O = Example Municipality
        OU = IT Operations
        CN = portal.example.gov

Modern browsers ignore the Common Name field if SANs are missing.

Create a configuration file:

nano csr.conf

Example configuration:

[req]
default_bits = 4096
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[dn]
C = NL
ST = Zuid-Holland
L = The Hague
O = Example Municipality
OU = IT Operations
CN = portal.example.gov

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = portal.example.gov
DNS.2 = api.example.gov
DNS.3 = internal.example.local

Generate the CSR:

openssl req -new -nodes \
-out server.csr \
-newkey rsa:4096 \
-keyout server.key \
-config csr.conf

Step 5 — Verify SAN Entries

Validate SAN information:

openssl req -text -noout -in server.csr

Look for:

X509v3 Subject Alternative Name:
    DNS:portal.example.gov,
    DNS:api.example.gov,
    DNS:internal.example.local

Security Best Practices

Protect the Private Key

Restrict permissions:

chmod 600 server.key

Recommended ownership:

chown root:root server.key

Never Share the Private Key

Only share:

  • server.csr

Never share:

  • server.key

Use Strong Algorithms

Recommended:

  • RSA 2048 or 4096
  • SHA-256 or higher

Avoid:

  • SHA-1
  • 1024-bit RSA

Example File Structure

/etc/ssl/private/server.key
/etc/ssl/csr/server.csr
/etc/ssl/certs/server.crt

Automation Example

Example Bash script:

#!/bin/bash

DOMAIN="portal.example.gov"

openssl req -new -newkey rsa:4096 -nodes \
-keyout ${DOMAIN}.key \
-out ${DOMAIN}.csr \
-subj "/C=NL/ST=Zuid-Holland/L=The Hague/O=Example Municipality/OU=IT/CN=${DOMAIN}"

echo "CSR generated:"
echo "  Key: ${DOMAIN}.key"
echo "  CSR: ${DOMAIN}.csr"

Make executable:

chmod +x generate-csr.sh

Run:

./generate-csr.sh

Troubleshooting

Error: unable to load Private Key

Cause:

  • Incorrect key path
  • Corrupted key
  • Wrong permissions

Verify:

openssl rsa -check -in server.key

CSR Missing SANs

Cause:

  • SAN section missing from OpenSSL config
  • req_extensions not configured

Solution:

Verify configuration contains:

req_extensions = req_ext

Certificate Does Not Match Private Key

Compare modulus:

openssl rsa -noout -modulus -in server.key | openssl md5
openssl req -noout -modulus -in server.csr | openssl md5

Hashes must match.


Placeholder Screenshots

[Screenshot Placeholder — Terminal showing successful CSR generation]

[Screenshot Placeholder — OpenSSL CSR verification output]

[Screenshot Placeholder — Example SAN configuration file]

Conclusion

Generating a CSR on Linux using OpenSSL is a straightforward but critical task in certificate lifecycle management. Properly generated CSRs ensure:

    1. Faster certificate issuance
    2. Browser compatibility
    3. Strong cryptographic standards
    4. Reduced operational errors

For production environments, always:

    1. Use SAN-enabled CSRs
    2. Protect private keys
    3. Standardize CSR templates
    4. Automate certificate requests where possible

A consistent CSR generation process is an essential foundation for secure certificate management operations.

Was this helpful?