HTTPS and Domain Setup
Table of Contents
Overview
In the final project, your backend will run on a real server and must be reachable securely over HTTPS using a human friendly domain name. This chapter walks through the practical setup from “I have an IP” to “my API is available at https://api.myapp.com”.
You will connect four main pieces:
- DNS (your domain name)
- Your server (IP address and ports)
- TLS certificate (for HTTPS)
- Your reverse proxy / web server (typically Nginx or Traefik)
We will focus on simple, repeatable setups that work for small production systems.
Domains, DNS, and IPs
Before you can enable HTTPS, you must have:
- A domain name, for example
myapp.com - A server with a public IP address, for example
203.0.113.10
Domain and DNS basics for this project
You buy a domain name from a domain registrar such as:
- Namecheap
- Google Domains (if still available in your region)
- Cloudflare Registrar
- GoDaddy
The domain has DNS records. DNS is a global phonebook that translates names like api.myapp.com to IP addresses like 203.0.113.10.
You control DNS records from your registrar or from a DNS provider like Cloudflare or AWS Route 53.
Two record types are most useful for your backend:
| Record type | Typical use | Example |
|---|---|---|
| A | Map name to IPv4 address | api.myapp.com -> 203.0.113.10 |
| CNAME | Alias one name to another name | www.myapp.com -> myapp.com |
For HTTPS, certificate authorities must be able to resolve your domain to your server IP, so DNS must be correct before you request certificates.
Example: DNS records for a backend API
Imagine you have:
- Domain:
myapp.com - Backend API:
api.myapp.com - Server IP:
203.0.113.10
In your DNS panel you might create:
| Name | Type | Value | Purpose |
|---|---|---|---|
myapp.com | A | 203.0.113.10 | Main website / frontend |
api.myapp.com | A | 203.0.113.10 | Backend API |
www | CNAME | myapp.com | www.myapp.com to myapp.com |
After saving, DNS changes can take minutes to propagate. Use tools such as:
# On Linux/macOS
dig api.myapp.com
# On Windows
nslookup api.myapp.com
Verify that api.myapp.com resolves to your server IP before going further.
HTTP vs HTTPS in production
Your backend may already work with HTTP, for example:
- You run Uvicorn on port 8000
- You can call
http://203.0.113.10:8000/docs
This is fine for local development, but not safe for production.
Why HTTPS is mandatory
HTTPS is simply HTTP over TLS. It provides:
- Encryption: Request and response bodies are not readable by others on the network.
- Integrity: Data cannot be modified in transit without detection.
- Authentication: The client can be sure it talks to
api.myapp.com, not an impostor.
Without HTTPS:
- Passwords, tokens, and cookies travel in plain text.
- Attackers can intercept and modify responses.
- Many browsers display warnings or block requests, especially for APIs accessed from browsers.
Always expose your production backend only over HTTPS. Never send credentials, tokens, or session cookies over plain HTTP in production.
In your final project, you will keep HTTP internally on the same machine (for example Nginx to Uvicorn) and expose only HTTPS to the internet.
Reverse proxy for HTTPS
Your FastAPI app usually runs on an internal port such as 8000. A reverse proxy sits in front of it, listens on ports 80 and 443, and forwards requests to your app.
Common choices:
- Nginx
- Traefik
- Caddy
This chapter will describe Nginx because it is widely used and integrates well with Docker.
Typical production flow
- Client accesses
https://api.myapp.com/users. - DNS resolves
api.myapp.comto your server IP. - Nginx on your server terminates HTTPS on port 443 (handles TLS).
- Nginx forwards the request using HTTP to
http://backend:8000orhttp://127.0.0.1:8000. - FastAPI receives the request and returns a response.
- Nginx sends the encrypted response back to the client.
This lets Nginx handle certificates, redirects, compression, and buffering, while your app focuses on business logic.
Getting TLS certificates with Let’s Encrypt
To serve HTTPS you need a TLS certificate. Buying one manually is possible, but for small production systems Let’s Encrypt is the standard free option.
Let’s Encrypt uses the ACME protocol and tools like certbot to:
- Prove that you control a domain.
- Issue a certificate for that domain.
- Renew the certificate automatically.
Requirements for Let’s Encrypt HTTP validation
For HTTP-01 validation:
- Port 80 on your server must be reachable from the internet.
- DNS for your domain must point to the correct IP.
- Certbot and your web server must serve special challenge files on port 80 when requested.
If port 80 is blocked by firewall or ISP, you may need DNS-01 validation instead, which is usually managed via DNS APIs.
Basic Certbot + Nginx setup (without Docker)
If your final project is not containerized, a common setup is:
- Ubuntu server
- Nginx installed from package manager
- Certbot installed with Nginx plugin
Step 1: Install Nginx
On Ubuntu:
sudo apt update
sudo apt install nginxStart and enable Nginx:
sudo systemctl enable nginx
sudo systemctl start nginx
Visit http://your-server-ip/ to confirm you see the default Nginx welcome page.
Step 2: Create an Nginx server block
Create a configuration for your API, for example /etc/nginx/sites-available/api.myapp.com:
server {
listen 80;
server_name api.myapp.com;
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;
}
}Enable it:
sudo ln -s /etc/nginx/sites-available/api.myapp.com \
/etc/nginx/sites-enabled/api.myapp.com
sudo nginx -t # test configuration
sudo systemctl reload nginx
Ensure your FastAPI app is running on 127.0.0.1:8000. Now http://api.myapp.com/docs should proxy correctly over HTTP.
Step 3: Install Certbot
On Ubuntu:
sudo apt install certbot python3-certbot-nginxStep 4: Obtain and configure the certificate
Run:
sudo certbot --nginx -d api.myapp.comCertbot will:
- Check DNS for
api.myapp.com. - Temporarily handle a challenge on port 80.
- Obtain a certificate.
- Edit your Nginx config to add HTTPS and a redirect.
At the end you will have an Nginx configuration similar to:
server {
listen 80;
server_name api.myapp.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name api.myapp.com;
ssl_certificate /etc/letsencrypt/live/api.myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.myapp.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;
}
}
Try visiting https://api.myapp.com/docs. The browser should show a secure connection.
HTTPS with Docker and Nginx
In your final project you will likely run your backend in Docker. A common pattern is:
- One container for your FastAPI app (Uvicorn or Uvicorn + Gunicorn).
- One container for Nginx.
- Optionally one container for Certbot.
Example Docker Compose setup
A minimal docker-compose.yml could look like:
version: "3.9"
services:
backend:
build: ./backend
container_name: backend
expose:
- "8000"
environment:
- ENV=production
nginx:
image: nginx:1.27-alpine
container_name: nginx
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- /etc/letsencrypt:/etc/letsencrypt:ro
ports:
- "80:80"
- "443:443"
depends_on:
- backendHere:
- The Nginx container listens on host ports 80 and 443.
- Certificates are mounted from
/etc/letsencrypton the host.
A simple Nginx config in ./nginx/conf.d/api.myapp.com.conf:
upstream backend_app {
server backend:8000;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name api.myapp.com;
ssl_certificate /etc/letsencrypt/live/api.myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.myapp.com/privkey.pem;
location / {
proxy_pass http://backend_app;
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 example, Certbot is run on the host, not inside Docker, using the same /etc/letsencrypt path that is mounted read only into the Nginx container.
You would then run the same certbot --nginx -d api.myapp.com on the host, but adjust for the Docker based Nginx if needed, or use a webroot method.
Using Certbot with webroot in Docker setups
Sometimes the Certbot Nginx plugin does not work well inside Docker. In that case you can use the webroot method:
- Configure Nginx to serve a directory for ACME challenges.
- Point Certbot at that directory.
Nginx config:
server {
listen 80;
server_name api.myapp.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_pass http://backend_app;
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;
}
}Mount the directory into Nginx and Certbot:
services:
nginx:
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./certbot/www:/var/www/certbot
- ./certbot/conf:/etc/letsencrypt
certbot:
image: certbot/certbot
volumes:
- ./certbot/www:/var/www/certbot
- ./certbot/conf:/etc/letsencryptThen, on the host:
docker compose run --rm certbot certonly \
--webroot \
--webroot-path /var/www/certbot \
-d api.myapp.com
After this, certificates appear under ./certbot/conf/live/api.myapp.com/, which are shared with Nginx.
Automatic certificate renewal
Let’s Encrypt certificates are valid for 90 days. You must renew them regularly.
With Certbot installed on a Linux host, a systemd timer or cron job is usually set up automatically. You can check renewal with:
sudo certbot renew --dry-run
In a Docker based certbot container approach, you can add a scheduled job on the host:
0 3 * * * docker compose run --rm certbot certbot renew \
--webroot --webroot-path /var/www/certbot && \
docker compose kill -s HUP nginx
This example, to be placed in root crontab via sudo crontab -e, will:
- Attempt renewal every night at 03:00.
- Tell Nginx to reload configuration and certificates with
HUPif renewal succeeded.
Do not wait for certificates to expire. Always set up automated renewal and verify with a --dry-run command.
Redirecting HTTP to HTTPS
Once HTTPS works, you should ensure that all HTTP traffic is redirected to HTTPS.
In Nginx this is the standard pattern:
server {
listen 80;
server_name api.myapp.com;
return 301 https://$host$request_uri;
}Key points:
- Use
301for permanent redirect in production. - Redirect at the root server block, not inside a location, so every path is covered.
Test using curl:
curl -I http://api.myapp.com/usersYou should see:
HTTP/1.1 301 Moved Permanently
Location: https://api.myapp.com/usersConfiguring your backend for HTTPS behind a proxy
Your FastAPI app still receives plain HTTP requests from Nginx, but the original client used HTTPS. For many APIs this is fine, but some frameworks use the scheme (http vs https) to:
- Generate redirect URLs.
- Generate absolute URLs (for example in OpenAPI docs).
- Enforce secure cookies.
Behind a reverse proxy, you should rely on headers that Nginx sets:
X-Forwarded-Proto:httporhttpsX-Forwarded-For: original client IPHost: original host, for exampleapi.myapp.com
For Uvicorn / FastAPI behind Nginx, consider:
- Running with
--proxy-headersso Uvicorn respectsX-Forwarded-Protoand related headers.
Example systemd service ExecStart:
ExecStart=/usr/bin/uvicorn app.main:app \
--host 127.0.0.1 \
--port 8000 \
--proxy-headersThis helps FastAPI generate correct HTTPS URLs in docs and handle security logic that depends on scheme.
Testing the full chain
After configuration, you should test:
- DNS:
dig api.myapp.comshows your server IP. - HTTP redirect:
curl -I http://api.myapp.com/healthResponse should be a 301 redirect to HTTPS.
- HTTPS response:
curl -I https://api.myapp.com/health
Response should be 200 OK or your health check status.
- Certificate validity:
- Use
curl -v https://api.myapp.com/healthand see certificate details. - Use online SSL checkers such as SSL Labs.
- OpenAPI docs in browser:
- Visit
https://api.myapp.com/docsand check that: - No mixed content warnings appear.
- All API calls are made to
https://api.myapp.com. - Renewal dry run:
sudo certbot renew --dry-runSecurity tips for HTTPS and domains
While the full security topic is covered in other chapters, keep these HTTPS related rules in mind:
Important HTTPS and domain rules:
- Always redirect HTTP to HTTPS for production domains.
- Never expose sensitive APIs over plain HTTP to the internet.
- Use strong TLS settings in Nginx and keep it updated.
- Protect private keys (
privkey.pem) and restrict their permissions. - Use separate subdomains for internal admin panels, for example
admin.myapp.com, and lock them behind strict authentication.
Additional practical tips:
- Use
HSTSheader when you are confident HTTPS is permanent:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;- Avoid wildcard DNS records that might accidentally point internal names to production servers.
- Monitor certificate expiry, for example with external monitors that alert you when expiry is near.
Putting it together for the final project
For your final project, a simple, realistic setup is:
- Buy a domain, for example
myfinalapp.com. - Create DNS
Arecord: api.myfinalapp.com -> <your-server-ip>.- On your production server:
- Run your FastAPI app on
127.0.0.1:8000or inside a Docker container. - Install Nginx and configure it as a reverse proxy to your app.
- Install Certbot and obtain a Let’s Encrypt certificate for
api.myfinalapp.com. - Configure Nginx:
- Listen on 80 and redirect to 443.
- Listen on 443 with the certificate.
- Proxy requests to your FastAPI app.
- Set up automatic certificate renewal and reload Nginx after renewals.
- Test the full flow and update configuration if you change domains or add more subdomains.
Once this is working, your production backend will be securely reachable at:
https://api.myfinalapp.comYour other deployment tasks, such as CI/CD, logging, and monitoring, will build on top of this HTTPS and domain setup.
Views: 9
KAHIBARO