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 file4096= key length in bits
Recommended minimum key length:
| Environment | Recommended |
|---|---|
| Internal services | 2048-bit |
| Internet-facing services | 4096-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
Step 4 — Generate a CSR with SAN (Recommended)
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_extensionsnot 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:
- Faster certificate issuance
- Browser compatibility
- Strong cryptographic standards
- Reduced operational errors
For production environments, always:
- Use SAN-enabled CSRs
- Protect private keys
- Standardize CSR templates
- Automate certificate requests where possible
A consistent CSR generation process is an essential foundation for secure certificate management operations.