This guide shows how to enable HTTPS on a Python Flask development server by installing an SSL certificate. The examples use Linux, Python 3.6, and Flask 2.0.3.
Prerequisites
Before you begin, make sure you have:
An SSL certificate issued by a trusted certificate authority (CA). If your certificate has expired, renew it first.
A certificate that covers all the domain names you want to secure. The following coverage rules apply: To add domain names, purchase a commercial certificate or Append and replace domain names.
Exact-match domain:
example.comprotects onlyexample.com.www.example.comprotects onlywww.example.com.Wildcard domain:
*.example.comcovers first-level subdomains such aswww.example.comanda.example.com, but does not cover the root domainexample.comor multi-level subdomains such asa.b.example.com. > Note: To secure multi-level subdomains, add the exact domain (such asa.b.example.com) or a matching wildcard (such as*.b.example.com) to the Bound Domains field.
A
rootaccount or an account withsudoprivileges on the server.A DNS record for your domain that resolves to the server's public IP address.
Domain name resolution: The domain's DNS record is configured and resolves to the server's public IP address.
Python and Flask installed on the server.
Step 1: Prepare the SSL certificate
Go to the SSL Certificate Management page. Find your certificate and click Download Certificate in the Actions column. On the Download tab, select Other 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 files — you need them for deployment.If the package contains only a certificate file (
.pem) and no private key file (.key), deploy the certificate together with the private key file saved on your local machine.
If you used a tool such as OpenSSL or keytool to generate a Certificate Signing Request (CSR) when applying for the certificate, the private key was saved only on your local machine and is not included in the downloaded package. If the private key is lost, the certificate is unusable. You must purchase a new certificate and generate a new CSR and private key.
Step 2: Configure the system and network environment
Make sure your server's security group and system firewall allow inbound traffic on TCP port 443 (HTTPS).
Check whether port 443 is open
Run the following command to check port 443 status. Replace <your_server_public_ip> with your 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 port 443 is open, the output looks like:
Ncat: Connected to <your_server_public_ip>:443Debian/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 port 443 is open, the output looks like:
Connection to <your_server_public_ip> port [tcp/https] succeeded!or
[<your_server_public_ip>] 443 (https) openIf port 443 is not open, complete the next two steps to open it.
Open port 443 in the security group
If your server runs on a cloud platform, its security group must allow inbound traffic on TCP port 443. Otherwise, the service will be unreachable. The following steps use Alibaba Cloud Elastic Compute Service (ECS) as an example. For other cloud platforms, refer to their documentation.
Go to the ECS instances page and click the target instance to open its details page. In the Security Group Details section, add a security group rule with the following settings:
| Field | Value |
|---|---|
| Action | Allow |
| Protocol | Custom TCP |
| Destination (Current Instance) | HTTPS (443) |
| Source | 0.0.0.0/0 (anywhere) |
Open port 443 in the firewall
Run the following command to identify the active firewall service:
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 further action is needed. Otherwise, run the corresponding command below to open port 443.
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 across reboots:
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 certificate in your Flask application
Create a directory to store your certificate files:
mkdir /sslUpload the certificate file (
.pem) and the private key file (.key) to/ssl.Use your remote login tool's file upload feature to transfer files. Common tools include PuTTY, Xshell, and WinSCP. If you use an Alibaba Cloud ECS instance, see Upload or download files.
Open your Flask application file and configure SSL using
ssl_context. The following is a complete example — copy it, update the certificate paths, and save it astest.pyto run a quick test.# Import the Flask web framework from flask import Flask app = Flask(__name__) @app.route("/") def main(): return "<p>Hello, World!</p>" # Configure the SSL certificate. # The default HTTPS port is 443. # Replace '/ssl/cert.pem' with the absolute path to your certificate file. # Replace '/ssl/cert.key' with the absolute path to your private key file. context = (r'/ssl/cert.pem', r'/ssl/cert.key') app.run(host="0.0.0.0", port=443, ssl_context=context)Navigate to the directory containing
test.pyand start the Flask service:# Replace test.py with your actual filename. python test.pyIf Flask starts successfully, the output looks like:
* Serving Flask app 'test' * Running on all addresses (0.0.0.0) * Running on https://127.0.0.1:443 * Running on https://<your_server_public_ip>:443
Verify the installation
Check the certificate in a browser
Open https://yourdomain in a browser (replace yourdomain with your actual domain). A lock icon in the address bar confirms the certificate is deployed correctly.

Starting from version 117, the
icon in Chrome has been replaced with
. Click this icon to view the certificate details.
If the lock icon does not appear or you get an access error, clear your browser cache or try again in incognito mode.
If the issue persists, see Resolve certificate deployment issues based on browser error messages and SSL certificate deployment troubleshooting guide.
Going live
When moving to production, apply the following practices to improve security and stability:
Run as a non-root user: Create a dedicated, low-privilege system user for the application. Never run the application as root or with administrator privileges.
For production deployments, configure SSL termination at the gateway layer instead of directly in Flask. Deploy the certificate on a Server Load Balancer (SLB) or a reverse proxy such as Nginx. The gateway handles HTTPS and forwards decrypted HTTP traffic to the Flask application.
Keep credentials out of code: Store passwords and sensitive information in environment variables, Vault, or a cloud key management service. Never hard-code them in source files or configuration files.
Redirect HTTP to HTTPS: Configure your server to redirect all HTTP traffic to HTTPS to prevent man-in-the-middle attacks.
Disable legacy protocols: In your server configuration, disable SSLv3, TLS 1.0, and TLS 1.1. Enable only TLS 1.2 and TLS 1.3.
Monitor certificate expiry: After deployment, enable domain monitoring in the Certificate Management Service. Alibaba Cloud checks the certificate validity period and sends renewal reminders before expiration. For details, see Purchase and enable public domain name monitoring.
FAQ
Why is HTTPS inaccessible after installing or updating the certificate?
This is usually caused by one of the following. Check them in order:
Port 443 is blocked: The security group or firewall does not allow traffic on port 443. See Step 2: Configure the system and network environment.
Domain mismatch: The domain you're accessing is not listed in the certificate's Bound Domains. See the domain name matching rules in Prerequisites.
Flask not restarted: Restart Flask after modifying the application file.
Incorrect certificate path: Verify that the
.pemand.keyfile paths inssl_contextare correct and that you're using the latest, valid certificate files.Missing certificate on other services: If your domain uses a Content Delivery Network (CDN), Server Load Balancer (SLB), or Web Application Firewall (WAF), install the certificate on those services as well. See Certificate deployment locations when traffic passes through multiple Alibaba Cloud services.
Partial deployment across multiple servers: If your domain's DNS resolves to multiple servers, install the certificate on all of them.
How do I update or replace an installed certificate?
Back up the existing
.pemand.keyfiles on your server.Download the new certificate and private key files from your Certificate Management Service console.
Upload the new files to your server, overwriting the old ones. Keep the same file paths and names as specified in your Flask configuration.
Restart Flask to apply the new certificate.
Flask throws FileNotFoundError on startup
This error means the file path in ssl_context is wrong. Check if the paths for the certificate and private key files provided in ssl_context are correct. Paths should be relative to the directory where you run the python <your-app-file>.py command, or you should use absolute paths.
The browser shows ERR_SSL_PROTOCOL_ERROR or resets the connection
Check the following:
The certificate file and private key file match each other.
The certificate file is a complete certificate chain (usually a
.pemfile). Certificate files downloaded from Alibaba Cloud already include the full chain.The security group and firewall allow inbound traffic on port 443.