All Products
Search
Document Center

Certificate Management Service:Install an SSL certificate on an Nginx or Tengine server (Linux)

Last Updated:Mar 31, 2026

Enable HTTPS on your Nginx or Tengine server by installing an SSL certificate. This guide walks you through downloading the certificate, opening port 443, configuring the Nginx server block, and verifying the result.

What you'll accomplish:

  • Download the certificate package from the SSL Certificates console and upload it to your server

  • Open port 443 in your security group and system firewall

  • Add an HTTPS server block to your Nginx configuration

  • Reload Nginx and confirm the certificate is working

The steps also apply to Tengine, which is compatible with Nginx configurations.

Prerequisites

Before you begin, ensure that you have:

  • An SSL certificate issued by a trusted certificate authority (CA). If the certificate is expired or about to expire, renew it first

  • A root account or an account with sudo privileges on the server

  • A domain DNS record configured to resolve to the server's public IP address

  • A certificate that covers all domains you want to secure

Domain coverage rules:

Coverage typeWhat it protectsWhat it does not protect
Exact-match (example.com)example.com onlywww.example.com or any subdomain
Exact-match (www.example.com)www.example.com onlyThe root domain or other subdomains
Wildcard (*.example.com)First-level subdomains: www.example.com, a.example.comRoot domain example.com, multi-level subdomains like a.b.example.com
To protect a multi-level subdomain like a.b.example.com, the Bound Domains field must contain either the exact domain or a corresponding wildcard such as *.b.example.com.

To add or change domain names, purchase a commercial certificate or append and replace domain names.

Step 1: Prepare the SSL certificate

  1. Go to the SSL Certificates page. In the Actions column for the target certificate, click Download Certificate. On the Download tab, select Nginx as the Server Type and download the package.

  2. Unzip the downloaded package:

    • If the package contains a certificate file (.pem) and a private key file (.key), save both. You will need them in the next step.

    • If the package contains only a .pem file and no .key file, use the private key file you saved locally when you generated the Certificate Signing Request (CSR).

    If you used OpenSSL or keytool to generate the CSR, the private key was saved only on your local machine — it is not included in the downloaded package. If the private key is lost, the certificate is unusable. Purchase a new commercial certificate and generate a new CSR and private key.
  3. Upload the .pem and .key files to your server. Store them in a secure directory, such as /etc/ssl/cert.

    Use the file upload feature of a remote login tool such as PuTTY, Xshell, or WinSCP. If your server is an Alibaba Cloud Elastic Compute Service (ECS) instance, see Upload or download files.

Step 2: Open port 443

HTTPS traffic uses TCP port 443. Confirm it is open in both your cloud security group and your system firewall.

Check whether port 443 is open

Run the following command to test connectivity on port 443. Replace <your_server_public_ip> with the server's public IP address.

RHEL/CentOS

command -v nc > /dev/null 2>&1 || sudo yum install -y nc
# Replace <your_server_public_ip> with the public IP address of your server.
sudo ss -tlnp | grep -q ':443 ' || sudo nc -l 443 & sleep 1; nc -w 3 -vz <your_server_public_ip> 443

If the output is Ncat: Connected to <your_server_public_ip>:443, port 443 is open. Otherwise, complete the steps below.

Debian/Ubuntu

command -v nc > /dev/null 2>&1 || sudo apt-get install -y netcat
# Replace <your_server_public_ip> with the public IP address of your server.
sudo ss -tlnp | grep -q ':443 ' || sudo nc -l -p 443 & sleep 1; nc -w 3 -vz <your_server_public_ip> 443

If the output is Connection to <your_server_public_ip> port [tcp/https] succeeded! or [<your_server_public_ip>] 443 (https) open, port 443 is open. Otherwise, complete the steps below.

Open port 443 in your security group

Important

If your server runs on a cloud platform, its security group must allow inbound TCP traffic on port 443. The steps below use Alibaba Cloud ECS as an example. For other cloud platforms, refer to their documentation.

Go to the Elastic Compute Service (ECS) instances page and click the target instance name. In the Security Group Details section, add a rule with the following settings and then click Add a security group rule:

FieldValue
ActionAllow
ProtocolCustom TCP
Destination (Current Instance)HTTPS (443)
Source0.0.0.0/0 (anywhere)

Open port 443 in your system firewall

Run the following command to identify your active firewall:

if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
    echo "firewalld"
elif command -v ufw >/dev/null 2>&1 && sudo ufw status | grep -qw active; then
    echo "ufw"
elif command -v nft >/dev/null 2>&1 && sudo nft list ruleset 2>/dev/null | grep -q 'table'; then
    echo "nftables"
elif command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet iptables; then
    echo "iptables"
elif command -v iptables >/dev/null 2>&1 && sudo iptables -L 2>/dev/null | grep -qE 'REJECT|DROP|ACCEPT'; then
    echo "iptables"
else
    echo "none"
fi

If the output is none, no firewall action is required. Otherwise, run the command for your firewall type:

firewalld

sudo firewall-cmd --permanent --add-port=443/tcp && sudo firewall-cmd --reload

ufw

sudo ufw allow 443/tcp

nftables

sudo nft add table inet filter 2>/dev/null
sudo nft add chain inet filter input '{ type filter hook input priority 0; }' 2>/dev/null
sudo nft add rule inet filter input tcp dport 443 counter accept 2>/dev/null

iptables

sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

To persist iptables rules after a reboot:

  • RHEL/CentOS:

    sudo yum install -y iptables-services
    sudo service iptables save
  • Debian/Ubuntu:

    sudo apt-get install -y iptables-persistent
    sudo iptables-save | sudo tee /etc/iptables/rules.v4 >/dev/null

Step 3: Install the SSL certificate on Nginx

Install the SSL module

Run the following command. If the output is --with-http_ssl_module, the SSL module is already installed and you can skip to Configure the SSL certificate.

nginx -V 2>&1 | grep -o -- '--with-http_ssl_module'
If the system returns nginx: command not found, use the full installation path, for example: /usr/local/nginx/sbin/nginx -V 2>&1 | grep -o -- '--with-http_ssl_module'.

If the SSL module is missing, install it using one of the methods below based on how Nginx was installed.

Important

Adding the SSL module may briefly interrupt the Nginx service. Back up your Nginx configuration and data first, and perform this change during off-peak hours.

Using a package manager

Run the following commands in your server terminal:

RHEL/CentOS

# Add the official Nginx repository.
sudo tee /etc/yum.repos.d/nginx.repo <<EOF
[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF

# Upgrade Nginx.
sudo yum upgrade nginx

Debian/Ubuntu

# Upgrade Nginx.
sudo apt-get update
sudo apt-get install --only-upgrade nginx

Compiling from source

  1. Install build dependencies.

    RHEL/CentOS

    sudo yum install -y gcc pcre-devel zlib-devel openssl-devel

    Debian/Ubuntu

    sudo apt-get update
    sudo apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
  2. Record the current compile parameters.

    nginx -V

    Copy all parameters shown after configure arguments:. You will need them in step 4.

  3. Download the source code for your current Nginx version. Run nginx -v to check the version (1.14.2 is used as an example). Then download and extract the source package:

    wget http://nginx.org/download/nginx-1.14.2.tar.gz
    tar -zxvf nginx-1.14.2.tar.gz
    cd nginx-1.14.2
  4. Recompile Nginx with the SSL module. Append --with-http_ssl_module to the parameters you recorded and recompile:

    If you see error: 'ENGINE_by_id' is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations], run make CFLAGS='-Wno-error=deprecated-declarations' instead.
    # Keep all original parameters to avoid losing existing modules.
    ./configure <Original parameters> --with-http_ssl_module
    make
  5. Replace the Nginx binary. Back up the original binary (using /usr/local/nginx/sbin/nginx as an example):

    # Replace /usr/local/nginx/sbin/nginx with the actual path to your nginx binary.
    sudo cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak

    Overwrite with the newly compiled binary:

    # Replace /usr/local/nginx/sbin/nginx with the actual path to your nginx binary.
    sudo cp objs/nginx /usr/local/nginx/sbin/nginx
  6. Verify the SSL module is installed.

    nginx -V 2>&1 | grep -o -- '--with-http_ssl_module'

    The output --with-http_ssl_module confirms the module is installed.

Configure the SSL certificate

Important

The following steps use Nginx 1.14.2 and the configuration file /etc/nginx/nginx.conf as an example. To find the active configuration file on your server, see How can I find the active Nginx configuration file?

  1. Open the configuration file.

    sudo vim /etc/nginx/nginx.conf
  2. Add a server block for HTTPS. Copy the existing server block that listens on port 80, change listen 80 to listen 443 ssl, and add the SSL directives shown below. Keep all other settings unchanged.

    # Original server block listening on port 80
    server {
        listen 80;
        server_name yourdomain www.yourdomain;
    
        # Other configurations
        location / {
            proxy_pass http://127.0.0.1:8000;
        }
    }
    
    # New server block for HTTPS.
    server {
        # Change the original 'listen 80' to 'listen 443 ssl'.
        listen 443 ssl;
        # Original server_name. You can add more domain names supported by the current certificate.
        server_name yourdomain www.yourdomain;
    
        # ======================= Start of certificate configuration =======================
        # Specify the certificate file (the intermediate certificate can be appended to this .pem file). Replace /etc/ssl/cert/ssl.pem with the absolute path of your certificate file.
        ssl_certificate /etc/ssl/cert/ssl.pem;
        # Specify the private key file. Replace /etc/ssl/cert/ssl.key with the absolute path of your private key file.
        ssl_certificate_key /etc/ssl/cert/ssl.key;
        # Configure the SSL session cache to improve performance.
        ssl_session_cache shared:SSL:1m;
        # Set the SSL session timeout period.
        ssl_session_timeout 5m;
        # Customize the TLS protocol types and cipher suites to use (the following is an example configuration; evaluate whether you need to configure it).
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        # Specify the allowed TLS protocol versions. Higher TLS versions provide better security for HTTPS communication, but have poorer browser compatibility than lower TLS versions.
        ssl_protocols TLSv1.2 TLSv1.3;
        # Prioritize the cipher suites specified by the server.
        ssl_prefer_server_ciphers on;
        # ======================= End of certificate configuration =======================
    
        # Other configurations
    }
  3. (Optional) Redirect HTTP to HTTPS. Add the return directive to the port 80 server block.

    # Original server block listening on port 80
    server {
        listen 80;
        server_name yourdomain www.yourdomain;
    
        # Redirect all HTTP traffic to HTTPS.
        return 301 https://$host$request_uri;
    
        # Other original configurations can be removed as they will no longer be reached.
    }
  4. Test the configuration for syntax errors.

    sudo nginx -t -c /etc/nginx/nginx.conf

    If the output includes both syntax is ok and test is successful, the configuration is valid. Otherwise, fix the errors reported and run the test again.

Reload Nginx

Important

These commands assume Nginx was started with the default configuration path. If you have a custom installation path or configuration file, adjust accordingly.

Nginx is running

Reload the configuration without restarting the service:

sudo nginx -s reload

If the reload fails, see the FAQ for troubleshooting.

Nginx is not running

Start it:

nginx

Step 4: Verify the deployment

  1. Open a browser and navigate to https://yourdomain. Replace yourdomain with your actual domain.

  2. A lock icon in the address bar confirms the certificate is deployed successfully. Starting from Chrome version 117, the image icon has been replaced with a new image icon. Click it to view the certificate details. If you see access errors or no lock icon, clear your browser cache or retry in incognito mode.

    image

If issues persist, see the FAQ for troubleshooting.

Going live

When deploying to production, apply the following best practices:

PracticeWhy it mattersHow to apply
Run as a non-root userLimits the blast radius of a security incidentCreate a dedicated low-privilege system user for the application
Terminate SSL at the gatewaySimplifies certificate management and reduces backend complexityDeploy the certificate on a Server Load Balancer (SLB). The SLB terminates HTTPS and forwards plain HTTP to the backend
Externalize secretsPrevents credentials from leaking through source code or config filesUse environment variables, HashiCorp Vault, or Alibaba Cloud Key Management Service instead of hardcoding passwords
Enforce HTTP-to-HTTPS redirectPrevents man-in-the-middle attacks on unencrypted trafficAdd return 301 https://$host$request_uri; to the port 80 server block
Disable insecure TLS versionsSSLv3, TLSv1.0, and TLSv1.1 are vulnerable to known attacksSet ssl_protocols TLSv1.2 TLSv1.3; in the Nginx configuration
Monitor certificates and renew on timeAn expired certificate breaks HTTPS for all usersEnable domain monitoring. Alibaba Cloud checks certificate validity and sends renewal reminders before expiration. See Purchase and enable public domain name monitoring

FAQ

Why is HTTPS inaccessible after installation?

Check the following in order:

  • Port 443 is blocked — The security group or firewall does not allow inbound traffic on port 443. See Open port 443.

  • Domain mismatch — The domain you are accessing is not listed in the certificate's Bound Domains. See the domain coverage table in Prerequisites.

  • Nginx not reloaded — The configuration was not reloaded after the changes. Run sudo nginx -s reload.

  • Wrong file paths — The ssl_certificate or ssl_certificate_key directives point to incorrect paths. Verify the absolute paths to your .pem and .key files.

  • Certificate missing on upstream services — If your domain routes through a Content Delivery Network (CDN), Server Load Balancer (SLB), or Web Application Firewall (WAF), the certificate must be installed on those services as well. See Certificate deployment locations when traffic passes through multiple Alibaba Cloud services.

  • Certificate not deployed on all servers — If the domain DNS resolves to multiple servers, install the certificate on each one.

For further help, see Resolve certificate deployment issues based on browser error messages and SSL certificate deployment troubleshooting guide.

How do I update or replace an SSL certificate without downtime?

  1. Back up the current .pem and .key files on the server.

  2. Download the new certificate and private key from the Certificate Management Service console.

  3. Upload the new files to the server, replacing the existing ones. Use the exact same file paths and names that are referenced in your Nginx configuration.

  4. Reload Nginx: sudo nginx -s reload.

How can I find the active Nginx configuration file (nginx.conf) on a Linux server?

  1. Run ps -ef | grep '[n]ginx: master' | grep -- ' -c '. If the output includes something like -c /etc/nginx/custom.conf, Nginx is using that custom configuration file.

  2. If step 1 returns no output, Nginx is using its default compiled path. Run nginx -V 2>&1 | grep -oP -- '--conf-path=[^ ]*' to display the default path, for example --conf-path=/etc/nginx/nginx.conf.

How do I disable TLSv1.0 and TLSv1.1 to fix "certificate does not meet standards" warnings?

Set the ssl_protocols directive in your Nginx configuration to:

ssl_protocols TLSv1.2 TLSv1.3;

This disables the insecure TLSv1.0 and TLSv1.1 protocols. After saving the file, run nginx -s reload to apply the change.

Why does nginx -t fail with bind() to 0.0.0.0:443 failed (98: Address already in use)?

Another process is already listening on port 443. Run sudo ss -tlnp | grep :443 to identify it. Then either stop the conflicting process (such as another web server or a hung Nginx instance) or reconfigure it to use a different port.

Why does nginx -t fail with cannot load certificate "/etc/nginx/ssl/domain.pem": BIO_new_file() failed?

Nginx cannot find the certificate file at the path specified in your configuration. Correct the ssl_certificate directive in nginx.conf to point to the actual absolute path of your .pem file.

Why does reloading Nginx fail with the "ssl" parameter requires ngx_http_ssl_module?

The Nginx build is missing the SSL module. Install or recompile Nginx with ngx_http_ssl_module enabled. See Install the SSL module.

Why do I get No such file or directory: fopen('/cert/3970497_demo.aliyundoc.com.pem','r') when reloading Nginx?

The path specified for ssl_certificate or ssl_certificate_key is incorrect. Verify that the paths in your configuration are correct absolute paths and that the files exist at those locations.

Why does Nginx fail to read the SSL certificate files with a permission denied error?

The Nginx worker process user does not have read access to the certificate files.

  1. Find the Nginx worker user: look for the user directive in nginx.conf (for example, user nginx;).

  2. Grant that user read (r) permission on the certificate and private key files, and execute (x) permission on all parent directories in the path.