When working with SSL/TLS on Ubuntu servers, it's crucial to distinguish between different file types:
# Example of common SSL-related files:
- example.com.key # Private key (MUST be kept secure)
- example.com.crt # Public certificate
- example.com.pem # Often contains both cert and private key
- example.com.csr # Certificate signing request
- example.com.bundle.crt # Certificate chain
Ubuntu follows the Filesystem Hierarchy Standard (FHS) with specific directories for SSL materials:
/etc/ssl/
├── certs/ # For public certificate files (.crt, .pem)
│ └── ca-certificates.crt # System-wide CA certs
├── private/ # For private keys (.key)
│ └── (protected directory)
└── openssl.cnf # OpenSSL configuration
Proper file permissions are critical for security:
# Set permissions for private key (readable only by owner)
sudo chmod 600 /etc/ssl/private/example.com.key
sudo chown root:root /etc/ssl/private/example.com.key
# Certificate files can have more relaxed permissions
sudo chmod 644 /etc/ssl/certs/example.com.crt
Here's how to properly reference these files in Nginx:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Additional security settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
}
The /etc/ssl/private directory is typically:
- Owned by root:root
- Has 700 permissions (drwx------)
- Access restricted to privileged users
Public certificates in /etc/ssl/certs are intentionally world-readable because:
- They contain no sensitive information
- They need to be accessible by services running as non-root users
- They're meant to be distributed to clients
For containerized environments or specific security requirements:
# Option 1: Dedicated SSL directory for service
/etc/nginx/ssl/
├── cert.pem
└── key.pem
# Option 2: Using apparmor for additional protection
/etc/apparmor.d/usr.sbin.nginx:
/etc/ssl/private/* r,
- Verify private keys are never stored with certificates
- Ensure private keys have 600 permissions
- Use separate certificates for different services
- Regularly audit file permissions
- Consider using encrypted partitions for /etc/ssl/private
When configuring SSL/TLS on Ubuntu servers, the fundamental principle is to maintain strict separation between public certificates and private keys. The certificate (.crt
) contains public information and can be safely distributed, while the private key (.key
) must remain absolutely confidential.
Ubuntu's FHS-compliant default locations:
/etc/ssl/certs/ # For certificate files (755 permissions)
/etc/ssl/private/ # For private keys (700 permissions)
Example deployment for Nginx:
# Certificate (public)
sudo cp example.com.crt /etc/ssl/certs/
sudo chmod 644 /etc/ssl/certs/example.com.crt
# Private key (secured)
sudo cp example.com.key /etc/ssl/private/
sudo chmod 600 /etc/ssl/private/example.com.key
sudo chown root:root /etc/ssl/private/example.com.key
SSL certificates contain:
- Public key
- Domain information
- Issuer details
- Validity period
Since these are designed to be public, /etc/ssl/certs/
with 755 permissions is appropriate. The private key in /etc/ssl/private/
has stricter 700 permissions by default in Ubuntu.
For high-security environments:
# Set immutable flag on private key
sudo chattr +i /etc/ssl/private/example.com.key
# Configure AppArmor for Nginx
echo "/etc/ssl/private/* r," >> /etc/apparmor.d/usr.sbin.nginx
sudo systemctl reload apparmor
Proper reference in your Nginx sites:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Rest of your configuration...
}
Regularly check permissions and access:
# Verify permissions
ls -l /etc/ssl/private/ /etc/ssl/certs/
# Monitor access attempts
sudo auditctl -w /etc/ssl/private/ -p rwxa -k ssl_private_access
Remember to test your configuration after changes:
sudo nginx -t
sudo systemctl reload nginx