DEV Community

Cover image for Access HTTPS APIs Behind IP Whitelisting Using Nginx Reverse Proxy in Docker
Jaykishan Ka.Patel
Jaykishan Ka.Patel

Posted on

Access HTTPS APIs Behind IP Whitelisting Using Nginx Reverse Proxy in Docker

πŸ”’ Problem

Have you ever faced this situation?

You have a local system for development,
but the external public cloud server IP is whitelisted to a third party API server for accessing their APIs.

For example:

  • https://xyz.com/api is accessible only from your public server’s IP
  • Your local system's IP is not whitelisted

You want to call the API from local for development or testing β€” but the API rejects it.

Let's learn how to tunnel HTTPS API requests through a whitelisted public server using Nginx reverse proxy in Docker. Perfect for local development behind IP restrictions.

This post walks you through setting up a secure reverse proxy using
Nginx and Docker, complete with JWT-based authentication.


βš™οΈ Architecture Overview

We’ll create a reverse proxy on your public server (the one with the whitelisted IP) and your local machine will call this proxy instead of the actual API.

Here's the flow:

Local System  ──────>  Public Server (Nginx Proxy)  ──────>  https://xyz.com/api
                        ↑
                        Whitelisted IP βœ…
Enter fullscreen mode Exit fullscreen mode

This way, your API calls will appear to come from the public server, even when originating locally.


βš™οΈ Step 1: Prepare the Directory Structure

On your public server, create a folder for the proxy setup:

mkdir -p /opt/api-proxy/nginx
cd /opt/api-proxy
Enter fullscreen mode Exit fullscreen mode

Directory layout:

/opt/api-proxy/
β”œβ”€β”€ docker-compose.yml
└── nginx/
    └── default.conf
Enter fullscreen mode Exit fullscreen mode

🐳 Step 2: Docker Compose Setup

Here’s the Docker Compose file (docker-compose.yml):

version: "3.8"

services:
  api-proxy:
    image: nginx:alpine
    container_name: api-proxy
    restart: unless-stopped
    ports:
      - "8443:443"     # HTTPS port
      - "8080:80"      # Optional HTTP port for testing
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      - ./nginx/certs:/etc/nginx/certs:ro
    environment:
      - TZ=Asia/Kolkata
Enter fullscreen mode Exit fullscreen mode

🧱 Step 3: Nginx Reverse Proxy Configuration

Create the file /opt/api-proxy/nginx/default.conf with the following content:

server {
    listen 80;
    listen 443 ssl;
    server_name _;

    # SSL certificates (replace with real ones if you have them)
    ssl_certificate     /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    # 1️⃣ TOKEN ENDPOINT
    location /token {
        proxy_pass https://xyz.com/token;
        proxy_set_header Host xyz.com;
        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;
        proxy_ssl_server_name on;

        client_max_body_size 10M;
        proxy_connect_timeout 30s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # 2️⃣ API ENDPOINT
    location /api/ {
        proxy_pass https://xyz.com/api/;
        proxy_set_header Host xyz.com;
        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;
        proxy_ssl_server_name on;
        proxy_pass_request_headers on;

        proxy_connect_timeout 30s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # 3️⃣ HEALTH CHECK
    location /health {
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }
}

Enter fullscreen mode Exit fullscreen mode

πŸ” Step 4: Add SSL Certificates

If you have a valid domain for your public server, you can issue free SSL certs with Let’s Encrypt:

sudo apt install certbot python3-certbot-nginx
sudo certbot certonly --nginx -d your-public-server.com
Enter fullscreen mode Exit fullscreen mode

Then copy the certificates into:

/opt/api-proxy/nginx/certs/fullchain.pem
/opt/api-proxy/nginx/certs/privkey.pem
Enter fullscreen mode Exit fullscreen mode

If you don’t have a domain yet, comment out the SSL lines and use only listen 80;.


πŸš€ Step 5: Run the Proxy

Start the container:

cd /opt/api-proxy
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Check if it’s running:

docker ps
curl http://<your-public-server-ip>:8080/health
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Step 6: Test From Local System

Once the container is up, your local machine can call the proxy instead of the real API.

1️⃣ Get Token

curl -k -X POST https://<public-server-domain>:8443/token \
     -H "Content-Type: application/json" \
     -d '{"username":"user","password":"pass"}'
Enter fullscreen mode Exit fullscreen mode

Response:

{"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
Enter fullscreen mode Exit fullscreen mode

2️⃣ Call Actual API

curl -k -X GET https://<public-server-domain>:8443/api/data \
     -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Enter fullscreen mode Exit fullscreen mode

βœ… The request goes through your public server
βœ… The API sees your whitelisted IP
βœ… You will get the response locally β€” as if you were calling from the server


🧠 Conclusion

You can now access secure APIs behind IP whitelisting from your local machine β€” safely and efficiently.

This setup is perfect for:

  • Developers working behind NAT or firewalls
  • Local testing with real APIs
  • CI/CD environments that require whitelisted access

βœ… Key Takeaways

  • Use Docker + Nginx for isolated, reproducible setups.
  • Always enforce HTTPS to secure external communications.
  • Handle JWT tokens securely before proxying API calls.
  • Perfect for developers testing third-party API integrations

Author: Jaykishan KaPatel
LinkedIn: Jaykishan KaPatel

Top comments (0)