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
rootaccount or an account withsudoprivileges on the serverA 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 type | What it protects | What it does not protect |
|---|---|---|
Exact-match (example.com) | example.com only | www.example.com or any subdomain |
Exact-match (www.example.com) | www.example.com only | The root domain or other subdomains |
Wildcard (*.example.com) | First-level subdomains: www.example.com, a.example.com | Root domain example.com, multi-level subdomains like a.b.example.com |
To protect a multi-level subdomain likea.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
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.
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
.pemfile and no.keyfile, 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.
Upload the
.pemand.keyfiles 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> 443If 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> 443If 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
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:
| Field | Value |
|---|---|
| Action | Allow |
| Protocol | Custom TCP |
| Destination (Current Instance) | HTTPS (443) |
| Source | 0.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"
fiIf 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 --reloadufw
sudo ufw allow 443/tcpnftables
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/nulliptables
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPTTo persist iptables rules after a reboot:
RHEL/CentOS:
sudo yum install -y iptables-services sudo service iptables saveDebian/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 returnsnginx: 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.
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 nginxDebian/Ubuntu
# Upgrade Nginx.
sudo apt-get update
sudo apt-get install --only-upgrade nginxCompiling from source
Install build dependencies.
RHEL/CentOS
sudo yum install -y gcc pcre-devel zlib-devel openssl-develDebian/Ubuntu
sudo apt-get update sudo apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-devRecord the current compile parameters.
nginx -VCopy all parameters shown after
configure arguments:. You will need them in step 4.Download the source code for your current Nginx version. Run
nginx -vto 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.2Recompile Nginx with the SSL module. Append
--with-http_ssl_moduleto the parameters you recorded and recompile:If you see
error: 'ENGINE_by_id' is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations], runmake CFLAGS='-Wno-error=deprecated-declarations'instead.# Keep all original parameters to avoid losing existing modules. ./configure <Original parameters> --with-http_ssl_module makeReplace the Nginx binary. Back up the original binary (using
/usr/local/nginx/sbin/nginxas 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.bakOverwrite 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/nginxVerify the SSL module is installed.
nginx -V 2>&1 | grep -o -- '--with-http_ssl_module'The output
--with-http_ssl_moduleconfirms the module is installed.
Configure the SSL certificate
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?
Open the configuration file.
sudo vim /etc/nginx/nginx.confAdd a server block for HTTPS. Copy the existing
serverblock that listens on port 80, changelisten 80tolisten 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 }(Optional) Redirect HTTP to HTTPS. Add the
returndirective 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. }Test the configuration for syntax errors.
sudo nginx -t -c /etc/nginx/nginx.confIf the output includes both
syntax is okandtest is successful, the configuration is valid. Otherwise, fix the errors reported and run the test again.
Reload Nginx
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 reloadIf the reload fails, see the FAQ for troubleshooting.
Nginx is not running
Start it:
nginxStep 4: Verify the deployment
Open a browser and navigate to
https://yourdomain. Replaceyourdomainwith your actual domain.A lock icon in the address bar confirms the certificate is deployed successfully. Starting from Chrome version 117, the
icon has been replaced with a new
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.
If issues persist, see the FAQ for troubleshooting.
Going live
When deploying to production, apply the following best practices:
| Practice | Why it matters | How to apply |
|---|---|---|
| Run as a non-root user | Limits the blast radius of a security incident | Create a dedicated low-privilege system user for the application |
| Terminate SSL at the gateway | Simplifies certificate management and reduces backend complexity | Deploy the certificate on a Server Load Balancer (SLB). The SLB terminates HTTPS and forwards plain HTTP to the backend |
| Externalize secrets | Prevents credentials from leaking through source code or config files | Use environment variables, HashiCorp Vault, or Alibaba Cloud Key Management Service instead of hardcoding passwords |
| Enforce HTTP-to-HTTPS redirect | Prevents man-in-the-middle attacks on unencrypted traffic | Add return 301 https://$host$request_uri; to the port 80 server block |
| Disable insecure TLS versions | SSLv3, TLSv1.0, and TLSv1.1 are vulnerable to known attacks | Set ssl_protocols TLSv1.2 TLSv1.3; in the Nginx configuration |
| Monitor certificates and renew on time | An expired certificate breaks HTTPS for all users | Enable 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_certificateorssl_certificate_keydirectives point to incorrect paths. Verify the absolute paths to your.pemand.keyfiles.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?
Back up the current
.pemand.keyfiles on the server.Download the new certificate and private key from the Certificate Management Service console.
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.
Reload Nginx:
sudo nginx -s reload.
How can I find the active Nginx configuration file (nginx.conf) on a Linux server?
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.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.
Find the Nginx worker user: look for the
userdirective innginx.conf(for example,user nginx;).Grant that user read (
r) permission on the certificate and private key files, and execute (x) permission on all parent directories in the path.