KAHIBARO
Discord Login Register

23.7. HTTPS Configuration

Why HTTPS Configuration Matters

When you ship a backend application to real users, you must protect three things: the data in transit, the identity of your server, and the integrity of the traffic. HTTPS solves all three.

HTTPS is simply HTTP over TLS. You keep all the HTTP concepts from earlier (methods, status codes, headers), but the connection is encrypted and authenticated by a TLS layer.

Rule: All production backends that handle real users or sensitive data must use HTTPS, never plain HTTP.

In this chapter you will learn how HTTPS configuration fits into a backend deployment, how TLS certificates work, and how to put all the pieces together with a reverse proxy such as Nginx or a containerized setup.

You will not learn TLS internals here. Focus on what you need as a backend developer to configure and operate HTTPS in practice.


Core Concepts for HTTPS Setup

Before touching configuration files, you need a few practical concepts.

TLS vs SSL

You will see both terms used in docs and configs.

Many tools still say “SSL certificate,” but they really mean a TLS certificate. In this course we will simply say “certificate” or “TLS certificate.”

Certificates, Keys, and Trust

A working HTTPS setup always involves at least:

Rule: Never expose or commit your private key to version control, logs, screenshots, support tickets, or chat.

At a high level:

  1. You generate a key pair on your server.
  2. You prove to a CA that you control a domain.
  3. The CA issues a certificate bound to that domain.
  4. You configure your web server or reverse proxy to use the certificate and private key.
  5. Browsers and clients trust your certificate because they already trust the CA.

Typical HTTPS Architecture in Backend Deployments

Most production setups use a reverse proxy in front of the application server:

LayerRoleExample tools
ClientBrowser or mobile appChrome, curl
Reverse proxyTerminates TLS, handles HTTPSNginx, Traefik, Caddy
Application serverRuns your backend applicationUvicorn, Gunicorn

In many real deployments:

  1. Clients connect to https://yourdomain.com.
  2. The reverse proxy (for example Nginx) listens on port 443, handles TLS, and forwards the request to your app.
  3. Your app listens on an internal port, for example 127.0.0.1:8000 or a Docker network port, usually plain HTTP.

Your HTTPS configuration usually focuses on the reverse proxy, not the application itself.


Preparing for HTTPS

Before you configure HTTPS, you typically need:

  1. A domain name pointing to your server’s public IP (covered in earlier chapters).
  2. Ports 80 and 443 open on the server.
  3. Root or sudo access on the server.

You can test from your local machine:

bash
ping yourdomain.com

You should see replies from your server’s IP.

If you are behind a provider firewall or cloud security group (like AWS Security Groups), ensure:

Self-Signed vs CA-Signed Certificates

There are two main ways to get a certificate:

TypeTrust in browsersTypical use
Self-signedNot trustedInternal testing or development
CA-signed (public)TrustedProduction sites, real users

Self-signed certificate example (for local or internal testing)

On a Linux server you can create a self-signed certificate with OpenSSL:

bash
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

This will ask several questions. The most important field is Common Name (CN), where you enter your domain or IP, for example api.localtest.me.

Then you would configure your reverse proxy with:

Browsers will show a security warning, since there is no trusted CA.

CA-signed certificate for production

For real users you must use certificates signed by a trusted CA. Common options:

Most modern deployments use Let’s Encrypt because it is free and automated.


Automating HTTPS with Let’s Encrypt and Certbot

Let’s Encrypt issues free certificates and Certbot is a common tool to obtain and renew them automatically.

The exact commands depend on your OS and web server, but the flow is similar.

Typical Certbot flow with Nginx

  1. Install Nginx and Certbot:
bash
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx
  1. Ensure your Nginx server block is set up for your domain on port 80:
nginx
server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}
  1. Run Certbot:
bash
sudo certbot --nginx -d api.example.com

Certbot will:

  1. Certbot will also set up automatic renewal via a cron job or systemd timer.

You can test renewal with:

bash
sudo certbot renew --dry-run

Rule: Always verify that automatic certificate renewal works. An expired certificate will break HTTPS and your users will see scary browser warnings.


Basic HTTPS Configuration with Nginx

Let us look at a minimal Nginx configuration that terminates HTTPS and forwards traffic to a backend.

Example: HTTP to HTTPS redirect and HTTPS server block

nginx
# Redirect all HTTP to HTTPS
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}
# HTTPS server
server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    location / {
        proxy_pass         http://127.0.0.1:8000;
        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

Key ideas:

HTTPS in Containerized Environments (Docker & Docker Compose)

If you use Docker for deployment, you typically keep TLS at the edge of your system:

Simple Docker Compose example

docker-compose.yml:

yaml
version: "3.8"
services:
  app:
    image: my-fastapi-app:latest
    expose:
      - "8000"
  nginx:
    image: nginx:stable
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - /etc/letsencrypt:/etc/letsencrypt:ro
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - app

nginx.conf:

nginx
events {}
http {
    upstream app_backend {
        server app:8000;
    }
    server {
        listen 80;
        server_name api.example.com;
        return 301 https://$host$request_uri;
    }
    server {
        listen 443 ssl;
        server_name api.example.com;
        ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
        location / {
            proxy_pass http://app_backend;
            proxy_set_header Host              $host;
            proxy_set_header X-Real-IP         $remote_addr;
            proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

In this setup:

Security-focused HTTPS Settings

Beyond basic TLS, you should tune your HTTPS configuration to avoid weak ciphers and insecure protocol versions.

Exact settings change over time, but a common Nginx pattern is:

nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:...';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

You can generate recommended settings for your server version using tools such as:

Rule: Disable old, insecure protocols like SSLv3, TLS 1.0, and TLS 1.1 in production.


HSTS and Redirects

HTTP Strict Transport Security (HSTS) tells browsers to always use HTTPS for your domain.

Example Nginx header:

nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Rule: Only enable HSTS for long durations after you are sure your HTTPS configuration is stable and correct. HSTS can “lock in” HTTPS and make mistakes harder to recover from.

You should also ensure all HTTP traffic is redirected to HTTPS with a 301 or 308 redirect, as shown earlier.


Testing and Troubleshooting HTTPS

Once you configure HTTPS, verify that everything works correctly.

Quick local tests

From your machine:

bash
curl -v https://api.example.com

Look for:

To see certificate details:

bash
echo | openssl s_client -connect api.example.com:443 -servername api.example.com

Check:

Online tools

You can use external tools (searchable online) that analyze:

These are useful to double-check your HTTPS security and configuration.


Common HTTPS Configuration Pitfalls

Here are frequent problems you will see in real deployments:

ProblemSymptomFix idea
Wrong server_nameWrong certificate shown or requests handled by wrong blockMatch Nginx server_name to your domain exactly
Ports not openCannot reach site at allOpen ports 80 and 443 in firewall / security groups
Expired certificateBrowser shows “connection not private”Renew certificate (automatically with Certbot)
Missing intermediate certificatesSome clients reject certUse full chain file (fullchain.pem with Let’s Encrypt)
Certificate for wrong domain“Certificate does not match hostname”Request a cert for the exact domain and configure it
Forgot redirect from HTTP to HTTPSUsers still access HTTP or mixed-content issuesAdd port 80 server block with 301 redirect to HTTPS

When something breaks:

  1. Check Nginx error logs.
  2. Confirm certificate files exist and paths are correct.
  3. Test from the server itself with curl https://yourdomain.com.

Practical Checklist for HTTPS Configuration

Use this as a quick reference when you deploy a backend with HTTPS:

  1. Domain and DNS
    • Domain points to your server IP.
    • DNS changes have propagated.
  2. Server basics
    • Ports 80 and 443 open on firewall / cloud security group.
    • Reverse proxy installed (for example Nginx).
  3. Certificates
    • For production, use Let’s Encrypt or another CA.
    • Certbot (or similar) installed and configured for your web server.
    • Automatic renewal tested with certbot renew --dry-run.
  4. Reverse proxy config
    • server_name matches your domain.
    • HTTP (port 80) server block redirects to HTTPS.
    • HTTPS (port 443) server block uses ssl_certificate and ssl_certificate_key.
    • Traffic is proxied to your backend app.
  5. Security options
    • Only TLS 1.2 and TLS 1.3 enabled.
    • Reasonable cipher suite configuration.
    • HSTS considered and optionally enabled correctly.
  6. Testing
    • curl -v https://yourdomain.com works.
    • Browser shows secure lock icon without errors.
    • Online SSL checker shows no critical issues.

If you walk through this list step by step, you can consistently bring up a secure HTTPS endpoint for your backend application.

Views: 7

Comments

Please login to add a comment.

Don't have an account? Register now!