Installing the SSL Certificate to NGINX on Debian

by Lance Gold

After NGINX is installed, next is to make http: an https: with an ‘s’

Return to index

After successful installation, the NGINX server is unsecure.

NGINX over insecure http:

What to do after you have a certificate

To make the server run nginx securely over an https:// connection, the SSL Certificate needs to be installed.

•CSR (Certificate Signing Request): also named CSR Code, Download CSR, generated with Private Key, the .csr file, text starts with "BEGIN CERTIFICATE REQUEST"

•Private Key (sent via email), the private_key.pem format file, .key file, your_domain_name.com.key file

•Certificate (CRT): also named Download Certificate, actual SSL Certificate Code, The root certificate, the .crt format file, a leaf certificate, ,pub-key.pem format file, your_leaf_certificate.crt file, text begins with "BEGIN CERTIFICATE"

•Intermediate/Chain files: also named Download Intermediate/Chain, cross-signed certificate, the .ca format file, ca-chain.pem file, your_intermediate_chain.crt file, text begins with "BEGIN CERTIFICATE"

•PEM: also named Download PEM, CA Bundle code, contains the root and intermediate CA certificates, the .ca-bundle format file, the .pem file, the full-chain.pem file, text is the .crt + .ca files.

From the website instructions:

https://www.ssldragon.com/how-to/install-ssl-certificate/nginx/

Have the certificates available:

• Your primary certificate (.crt file)

• The root and intermediate certificates (.ca-bundle file)

You can make the combination manually using a text editor. The order of SSL certificates is important.

Here is the sequence:

1. Your primary certificate for your domain name

de.somewhere.com.crt

2. Intermediate certificates

de.somewhere.com.ca (first half)

3. Root certificate

de.somewhere.com.ca (second half)

Or you can combine the certificates from separate files:


cat de.somewhere.com.crt intermediate.crt root.crt > ssl-bundle.crt

If your intermediate and root certificates are inside a single file with .ca-bundle extension, run:


cat example_com.crt bundle.crt > ssl-bundle.crt
	cat de.somewhere.com.crt de.somewhere.com.ca > ssl-bundle.crt

For Windows, use the "type” command


C:\Users\you\Documents\ssl certs>dir
 Volume in drive C has no label.
 Volume Serial Number is 0B6C-6190

 Directory of C:\Users\you\Documents\ssl certs

01/17/2026  08:18 PM              .
01/17/2026  08:18 PM              ..
01/17/2026  08:17 PM             6,680 de.somewhere.com.ca
01/17/2026  08:13 PM             2,305 de.somewhere.com.crt
01/17/2026  08:15 PM              old b4 2025
               2 File(s)          8,985 bytes
               3 Dir(s)  121,397,415,936 bytes free

C:\Users\you\Documents\ssl certs>cat de.somewhere.com.crt de.somewhere.com.ca > ssl-bundle.crt
'cat' is not recognized as an internal or external command,
operable program or batch file.

C:\Users\you\Documents\ssl certs>type de.somewhere.com.crt de.somewhere.com.ca > ssl-bundle.crt

Save the new, combined file in the SSL directory of your NGINX server.

Put the ssl-bundle.crt file into the SSL directory of the NGINX server.

Do I have sftp?

From the Windows terminal:


C:\Users\you\Documents\ssl certs>sftp you@de.somewhere.com
you@de.somewhere.com's password:
Connected to de.somewhere.com.
sftp>

Put (send, upload) the file to the destination working directory


sftp> put ssl-bundle.crt
Uploading ssl-bundle.crt to /home/x/ssl-bundle.crt
ssl-bundle.crt                 100% 8985   219.4KB/s   00:00
sftp> quit

C:\Users\you\Documents\ssl certs>

‘q’ doesn’t exit.

From the Server:

you@de:~$ ls
you@de:~$ ls
ssl-bundle.crt
you@de:~$

Copy and past the private key text to a file "de.somewhere.com.key" change from "Windows CR/LF" encoding to "UTF-8" encoding.

Upload the file to the Server.


C:\Users\you\Documents\ssl certs>sftp you@de.somewhere.com
you@de.somewhere.com's password:
Connected to de.somewhere.com.
sftp> put de.somewhere.com.key
Uploading de.somewhere.com.key to /home/x/de.somewhere.com.key
de.somewhere.com.key               100% 1736    41.4KB/s   00:00
sftp> quit

C:\Users\you\Documents\ssl certs>

View and check the file (check the encoding) on the Server.


you@de:~$ more de.somewhere.com.key
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDxq6drVqiolEIG
uqbRjoT0XC9RRMCfSYyG/ODM6Jqr1hgDqQz6iDMUdCdcrLmuAKmioHmzwSUFugNK
...
bMQOa9zRtc6QWIdlNp2ROMIqeZlBIcrNA/dVPxJ2uEtHdUdW25EJ8wSkXc3oGoYk
KVtdg9rIQtNQ+Luz9ZgKJ8AJXw==
-----END PRIVATE KEY-----
you@de:~$

Move two files to directories.

From the Google AI overview:

In Debian, there is no single, mandatory default "SSL directory" for Nginx. By convention, certificates and private keys are typically stored in standard system-wide directories, though their specific location is defined within the Nginx configuration files.
Default Debian Locations:

Certificates ( .crt, .pem files): /etc/ssl/certs/

Private Keys ( .key files): /etc/ssl/private/

Use -a to view hidden files and directories

Use -al to view and note the directory access


you@de:~$ ls -al /etc/ssl/
total 48
drwxr-xr-x  4 root root  4096 Jan 16 19:14 .
drwxr-xr-x 78 root root  4096 Jan 17 18:09 ..
drwxr-xr-x  2 root root 20480 Aug 19 11:08 certs
-rw-r--r--  1 root root 12411 Jul 12  2025 openssl.cnf
drwx------  2 root root  4096 Jul 12  2025 private
you@de:~$

Set ownership to 600 for key file.

Before:


you@de:~$ sudo ls -l /etc/ssl/private/
total 4
-rw-rw-r-- 1 x x 1736 Jan 18 12:16 de.somewhere.com.key
you@de:~$

Make the change:


you@de:~$ sudo chown root:root /etc/ssl/private/de.somewhere.com.key
you@de:~$ sudo chmod 600 /etc/ssl/private/de.somewhere.com.key
you@de:~$

After:


you@de:~$ sudo ls -l /etc/ssl/private/
total 4
-rw------- 1 root root 1736 Jan 18 12:16 de.somewhere.com.key
you@de:~$

Move the bundle certificate, rename with .pem to not confuse with .crt security file.


you@de:~$ sudo mv ssl-bundle.crt /etc/ssl/certs/de.somewhere.com.pem
you@de:~$

Change ownership and permission:

Before:


you@de:~$ sudo ls -l /etc/ssl/certs/de.somewhere.com.pem
-rw-rw-r-- 1 x x 8985 Jan 18 11:57 /etc/ssl/certs/de.somewhere.com.pem
you@de:~$

Make the change:


you@de:~$ sudo chown root:root /etc/ssl/certs/de.somewhere.com.pem
you@de:~$ sudo chmod 644 /etc/ssl/certs/de.somewhere.com.pem
you@de:~$

After:


you@de:~$ sudo ls -l /etc/ssl/certs/de.somewhere.com.pem
-rw-r--r-- 1 root root 8985 Jan 18 11:57 /etc/ssl/certs/de.somewhere.com.pem
you@de:~$

Next Ensure directory permission are correct:
From Google AI:
The ssl-cert Group
The directories containing the keys also need proper permissions to allow the service to traverse them.

For /etc/ssl/private, permissions of 710 (drwxr-x---) (owner root, group ssl-cert) are common and secure in Debian, and

755 (drwxr-xr-x) is standard for /etc/ssl/certs

Before:


you@de:~$ sudo ls -l /etc/ssl
total 40
drwxr-xr-x 2 root root 20480 Jan 18 13:17 certs
-rw-r--r-- 1 root root 12411 Jul 12  2025 openssl.cnf
drwx------ 2 root root  4096 Jan 18 12:58 private
you@de:~$

Here is that command:


sudo chown root:ssl-cert /path/to/your/ssl_file.

But:


you@de:~$ sudo chown root:ssl-cert /etc/ssl/private
chown: invalid group: ‘root:ssl-cert’
you@de:~$

Here is an additional note from Google A.I. from 2018 (PostgreSQL) and 2019 (certbot):
The ssl-cert Group:
Debian uses the special ssl-cert group to allow various daemon processes (which do not run as the root user) to access the private keys without compromising system security. Services like PostgreSQL or web servers can be made members of this group, granting them the necessary read access to the keys in /etc/ssl/private/.

Nginx configuration

At the end of the configuration file /etc/nginx/nginx.conf is the line:


http {
...
        include /etc/nginx/sites-enabled/*;
}

The nginx.conf file contains the location, so take a look to check in the configuration file which whould contain locations of the ssl files.

There are two directories:

/etc/nginx/sites-enabled/

/etc/nginx/sites-available/

In the /etc/nginx/sites-available/default file (no .conf) is the comment instruction line:

# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#

In the “sites-available” directory will go configuration files for each different way we want NGINX to operate.

In the “sites-enabled” directory we will unlink the current .conf file in use, and create a link to the new .conf file needed.

As examples, a .conf file to send port 3000 traffic to node.js, to send other ports to MariaDB, or to Tornado (Python)

Here is the sites-available directory with two configuration files:


you@de:~$ ls -l /etc/nginx/sites-available/
total 8
-rw-r--r-- 1 root root 2412 Aug 29 07:10 default
-rw-r--r-- 1 root root 2817 Jan 18 22:56 with-ssl.conf
you@de:~$

Here is a listing of the sites-enabled directory. There is a link to the default file, so when nginx looks for the configuration, the link will connect to the default.

you@de:~$ ls -l /etc/nginx/sites-enabled/
total 0
lrwxrwxrwx 1 root root 34 Aug 29 08:28 default -> /etc/nginx/sites-available/default
you@de:~$

Here is the contents of the nginx default file:

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration
#
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#       listen 80;
#       listen [::]:80;
#
#       server_name example.com;
#
#       root /var/www/example.com;
#       index index.html;
#
#       location / {
#               try_files $uri $uri/ =404;
#       }
#}

Make changes in with-ssl.conf file to accept port 443 https


server {
        listen 80 default_server;
        listen [::]:80 default_server;

        listen 443 ssl;
        #ssl on; (for releases before 1.15.0);
        ssl_certificate /etc/ssl/certs/de.somewhere.com.pem;
        ssl_certificate_key /etc/ssl/private/de.somewhere.com.key;
        server_name de.somewhere.com;
#      access_log /var/log/nginx/access.log;		unresolved error 
# 1640172#1640172: invalid log level "root" in /etc/nginx/sites-enabled/with-ssl.conf:48
#      error_log /var/log/nginx/error.logo

        root /var/www/html;
        # may need to add root /var/www/de.somewhere.com/html; later

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name de.somewhere.com;

...
}

Now we can point nginx away from the default to the new configuration file.

We delete the symbolic link in sites-enabled, not the original file in sites-available

first get the name of the link.

From the resource “https://blog.logrocket.com/how-to-run-node-js-server-nginx/”


you@de:~$ ls -l /etc/nginx/sites-enabled/
total 0
lrwxrwxrwx 1 root root 34 Aug 29 08:28 default -> /etc/nginx/sites-available/default
you@de:~$ ls -l /etc/nginx/sites-enabled/default
lrwxrwxrwx 1 root root 34 Aug 29 08:28 /etc/nginx/sites-enabled/default -> /etc/nginx/sites-available/default
you@de:~$ sudo unlink /etc/nginx/sites-enabled/default
you@de:~$ ls -l /etc/nginx/sites-enabled/
total 0
you@de:~$

Enable the desired configuration file by creating a symlink (symbolic) link from it to the sites-enabled directory, which Nginx reads from at startup.


you@de:~$ ls -l /etc/nginx/sites-available/
total 8
-rw-r--r-- 1 root root 2815 Jan 27 09:01 default
-rw-r--r-- 1 root root 2817 Jan 18 22:56 with-ssl.conf
you@de:~$ sudo ln -s /etc/nginx/sites-available/with-ssl.conf /etc/nginx/sites-enabled/
you@de:~$ ls -l /etc/nginx/sites-enabled/
total 0
lrwxrwxrwx 1 root root 40 Jan 27 09:17 with-ssl.conf -> /etc/nginx/sites-available/with-ssl.conf
you@de:~$

Restart NGINX


sudo nginx -t #test the configuration

you@de:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
you@de:~$

sudo systemctl reload nginx #apply changes without downtime
sudo systemctl restart nginx #completely stops and then starts the nginx server, closing all existing connections.

sudo nginx -s reload   # fallback if systemctl is misssing

nginx welcome screen with secure https:

Service Management

You can control the Nginx process using these standard systemctl commands:
Start: sudo systemctl start nginx

Stop: sudo systemctl stop nginx

Restart: sudo systemctl restart nginx (useful for major changes)

Reload: sudo systemctl reload nginx (applies config changes without dropping connections)

Enable on Boot: sudo systemctl enable nginx

Configuration File Locations
Main Config: /etc/nginx/nginx.conf

Site Blocks: /etc/nginx/sites-available/ (configs are stored here)

Active Sites: /etc/nginx/sites-enabled/ (symlink files here to activate them)

Web Root: /var/www/html/ (default location for your website files)

Logs: /var/log/nginx/access.log and /var/log/nginx/error.log