Strapi as a private API: Only expose Strapi API endpoints to whitelisted server IPs (not public)

System Information
  • Strapi Version: Strapi v3.6.8 (Community Edition)
  • Operating System: macOS 10.13.6
  • Database: PostgreSQL 9.3.5
  • Node Version: 14.15.5
  • NPM Version: 6.14.11
  • Yarn Version: 1.19.1

I’m a relative newcomer to Strapi (I have only deployed one production backend with it so far), but I’m deploying a second soon and am looking for a way to only expose my Strapi REST API endpoints (e.g. https://my-api-server.com/resource where resource is a Content-Type) to my own frontend applications: effectively, use Strapi to create a private API.

I found (through watching hours of YouTube tutorials) how the traditional way to make a pubic API is by navigating in the Strapi admin:
Settings > (Users & Permissions Plugin) > Roles > Public
…and then scrolling down to the Permissions section, under Application, and checking the boxes next to find and findOne for each Content-Type.

However, this exposes the API endpoints to any outside source that discovers my API URL. In other words, if a malicious server finds my API URL (which wouldn’t be very hard to do), they could extract all of the information from my API, and/or make repeated requests which would tax my server resources (and incur unnecessary hosting costs).

In short, I’m looking to use Strapi to create a private API: only expose my API endpoints to a whitelist of my own frontend application server IP addresses that will be requesting data from the API. I only want my own applications to be able to access the data I enter into Strapi, not the rest of the world.

How can I do this? Thanks so much in advance!

hello @beschler did you find a reliable technique?

I found a way to do something slightly similar (hide API from ouside, domain & IP direct access) :

  1. Run strapi production mode into your server (assumed to run on port 1337)
  2. Disable direct 1337 port access with iptables, for everyone excepts 127.0.0.1
iptables -A INPUT -p tcp --dport 1337 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 1337 -j DROP

  1. Setup nginx or apache with proxy and proxy pass your server_name to 127.0.0.1:1337
server {
    listen 80;
    server_name your-api-server.com;
    location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass         http://127.0.0.1:1337/;
    }
    location /api {
        deny all;
       // use your own rules to deny or allow who you want
        return 403;
    }
}

That way you’ll be able to :

  • Access admin panel & do whatever admin tasks you want at your-api-server.com/admin
  • Allow local access to /api/* (interesting if your clients app are hosted on the same machine)
  • Deny access to your-api-server.com/api/* to who you want
  • Deny access to server-ip:1337/* to everyone