Migrate from NGINX to APISIX
Users migrate from NGINX to APISIX because of its ease of use and extensibility. For instance, APISIX:
- enables configuration reload without downtime.
- supports canary release, authentication, and observability out-of-the-box.
- can be configured through the Admin API, or YAML configuration files.
- provides extensibility that allows users to develop custom plugins in Lua and other programming languages.
This guide will walk you through the process of migrating NGINX configurations for typical scenarios, to equivalent APISIX configurations.
Make sure to test the migrated configuration in a sandboxed environment before deploying to production.
Configure Reverse Proxy
Acting as a proxy and forwarding requests to an upstream server is the primary functionality of NGINX and APISIX.
This example uses NGINX and APISIX to forward requests to the /anything/
path to the upstream, httpbin.org
.
To proxy requests in NGINX, the proxy_pass
directive is used:
http {
server {
listen 80;
location /anything/ {
proxy_pass http://httpbin.org:80;
}
}
}
❶ Listen for requests on port 80.
❷ Match locations starting with /anything/
.
❸ Proxy the matched request to httpbin.org
.
APISIX achieves the same configuration through routes.
Create a route as shown below:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-anything",
"uri": "/anything/*",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
❶ Match all requests with the path prefix /anything/
.
❷ Proxy the matched request to httpbin.org
.
Send a request to the created route:
curl -i "http://127.0.0.1:9080/anything/nothing"
You should see a HTTP/1.1 200 OK
response with the following content:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.4.0",
"X-Amzn-Trace-Id": "Root=1-661fc252-35c621bc2d2b961c6ce98366",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"method": "GET",
"origin": "192.168.289.1, 45.253.168.124",
"url": "http://127.0.0.1/anything/nothing"
}
See the Traffic Management guides for more complex routing scenarios.
Configure Load Balancing
NGINX is also used extensively as a load balancer to distribute incoming requests among several upstream servers.
This example uses NGINX and APISIX to balance the load between two upstreams, httpbin.org
and mock.api7.ai
, while keeping a failover server, 192.0.0.1
, for failures.
These upstreams are specified in an upstream
block (context) in NGINX configuration:
http {
upstream backend {
server httpbin.org:443;
server mock.api7.ai:443;
server 192.0.0.1:443 backup;
}
server {
listen 80;
location / {
proxy_pass https://backend;
}
}
}
❶ Create an upstream named backend
.
❷ Configure upstream nodes, httpbin.org
and mock.api7.ai
.
❸ Configure failover server, 192.0.0.1
, to fallback to if the above nodes fail.
APISIX achieves the same configuration through the nodes
attribute in the upstream configuration.
Create a route with multiple upstream nodes:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-headers",
"uri": "/headers",
"upstream" : {
"type": "roundrobin",
"nodes": [
{ "host": "httpbin.org", "port": 443, "weight": 3 },
{ "host": "mock.api7.ai", "port": 443, "weight": 1 },
{ "host": "192.0.0.1", "port": 443, "priority": -1 }
],
"pass_host": "node",
"scheme": "https"
}
}'
❶ Use the weighted round robin algorithm for load balancing. See Load Balancing for other options.
❷ Configure upstream nodes, httpbin.org
and mock.api7.ai
.
❸ Configure failover server, 192.0.0.1
, to fallback to if the above nodes fail.
Send 50 requests to the created route to verify load balancing:
resp=$(seq 50 | xargs -I{} curl "http://127.0.0.1:9080/headers" -sL) && \
count_httpbin=$(echo "$resp" | grep "httpbin.org" | wc -l) && \
count_mockapi7=$(echo "$resp" | grep "mock.api7.ai" | wc -l) && \
echo httpbin.org: $count_httpbin, mock.api7.ai: $count_mockapi7
You should see a similar response:
httpbin.org: 49, mock.api7.ai: 1
Serve Static Files
NGINX and APISIX can serve static files directly. These typically include HTML, CSS, JavaScript, images, fonts, and other media files that are served without any modification to the client.
This example uses NGINX and APISIX to cache and proxy static files from the Web Hypertext Application Technology Working Group (WHATWG) public GitHub repository.
NGINX supports using regular expressions in the location block to match files based on its extension, as shown below:
http {
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m;
server {
listen 80;
proxy_cache mycache;
location ~* ^/whatwg/(.+\.(jpeg|html))$ {
proxy_pass https://raw.githubusercontent.com;
}
}
}
❶ Store the cached content in /data/nginx/cache
with a shared memory zone of size 10 MB for storing cache keys.
❷ Use the created cache, mycache
.
❸ Match requests with /whatwg/
prefix and a file extension of either .jpeg
or .html
using a regular expression.
❹ Proxy matched requests to raw.githubusercontent.com
.
APISIX uses variables to match paths. Then, to cache the responses, APISIX uses the proxy-cache
plugin.
Create a route with proxy-cache
enabled:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-whatwg",
"uri": "/whatwg/*",
"vars": [["uri", "~~", "(.jpeg|.html)$"]],
"plugins": {
"proxy-cache": {}
},
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": {
"raw.githubusercontent.com": 1
}
}
}'
❶ Match requests which end in .jpeg
or .html
using the uri
variable.
❷ Enable proxy-cache
to cache responses.
❸ Proxy matched requests to raw.githubusercontent.com
.
Send a request to the created route for an HTML file:
curl -i "http://127.0.0.1:9080/whatwg/html/main/404.html"
You should receive an HTTP/1.1 200 OK
response and see the following file content:
<!DOCTYPE html>
<script src="/link-fixup.js" defer></script>
<title>404 Not Found</title>
<style>
body.loading div.failed,
body.failed div.loading,
div.failed {
display: none;
}
body.loading div.loading,
body.failed div.failed,
div.loading {
display: block;
}
</style>
<body onload="document.body.className = 'failed'">
<script>
document.body.className = "loading";
</script>
<div class="loading">
<p>Loading...</p>
</div>
<div class="failed">
<h1>Not Found</h1>
<p>The page you are looking for is no longer available at this URL.</p>
<p>
Links to the multipage version of the specification are unfortunately
likely to break over time. You might be able to find what you want from
<a href="/multipage/">the contents page</a>.
</p>
<p>
If you have found a broken link on the WHATWG site itself, please
<a href="https://github.com/whatwg/html/issues/new">file an issue</a>. If
you found a broken link from another site pointing to the WHATWG site,
please let that site know of the problem instead. Thanks!
</p>
</div>
</body>
Configure SSL Termination
NGINX can terminate HTTPS traffic from clients to offload the upstream from the additional burden of decryption. APISIX also supports this feature out-of-the-box.
This example uses NGINX and APISIX to terminate SSL before proxying requests to the upstream, httpbin.org
, over HTTP.
NGINX uses the provided SSL certificates to set up SSL termination:
http {
server {
listen 443 ssl;
server_name www.test.com;
ssl_certificate /etc/nginx/ssl/website.com/certificate.crt;
ssl_certificate_key /etc/nginx/ssl/website.com/private.key;
location /ip {
proxy_pass http://httpbin.org:80;
}
}
}
❶ Listen on port 443 for HTTPS requests.
❷ Configure path to SSL certificate.
❸ Configure path to SSL certificate key.
APISIX uses an SSL certificate object to store the certificate and the private key:
curl -i "http://127.0.0.1:9180/apisix/admin/ssls" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-test-com-ssl",
"sni": "www.test.com",
"cert": "'"$(cat certificate.crt)"'",
"key": "'"$(cat private.key)"'"
}'
❶ Configure SSL certificate.
❷ Configure SSL certificate key.
See Configure HTTPS Between Client and APISIX for a detailed guide on configuring SSL.
Redirect HTTP to HTTPS
In addition to terminating HTTPS traffic, NGINX can also be configured to redirect HTTP traffic to HTTPS.
NGINX uses the return
directive to redirect with a 301 Moved Permanently
status code:
http {
server {
listen 80;
server_name www.test.com;
return 301 https://$host$request_uri;
}
}
❶ Redirect to the HTTPS version of the requested URI.
APISIX uses the redirect
plugin to achieve the same behavior:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-redirect",
"uri": "/*",
"plugins": {
"redirect": {
"http_to_https": true,
"ret_code": 301
}
}
}'
❶ Redirect HTTP requests to HTTPS.
❷ Return a 301 Moved Permanently
status code while redirecting.
Send an HTTP request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should see an HTTP/1.1 301 Moved Permanently
response.
Configure IP Access Control
One way to use NGINX as a firewall is by restricting access to your services to specific IP addresses. This helps prevent unauthorized access and malicious users.
This example uses NGINX and APISIX to allow requests only from the IP address 192.168.1.0/24
.
NGINX uses the allow
directive to allow access to IP addresses and the deny
directive to deny access as shown below:
http {
server {
listen 80;
location /anything/ {
allow 192.168.1.0/24;
deny all;
proxy_pass http://httpbin.org:80;
}
}
}
❶ Allow access to the IP address 192.168.1.0/24
.
❷ Deny access to all other IP addresses.
APISIX achieves the same configuration through the ip-restriction
plugin.
Create a route with ip-restriction
enabled:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-anything",
"uri": "/anything",
"plugins": {
"ip-restriction": {
"whitelist": ["192.168.1.0/24"]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
❶ Add the IP address, 192.168.1.0/24
, to the whitelist to allow access.
Send a request to the created route:
curl -i "http://127.0.0.1:9080/anything"
If your IP is allowed, you should receive an HTTP/1.1 200 OK
response. If not, you should receive an HTTP/1.1 403 Forbidden
response with the following error message:
{"message":"Access denied"}
Customize NGINX Configuration Generated by APISIX
APISIX generates an NGINX configuration file from the configurations in apisix/cli/config.lua
. To customize the NGINX configuration, add snippets to the nginx_config
field in the conf/config.yaml
file.
The example below shows the available snippets with examples:
nginx_config:
main_configuration_snippet: |
daemon on;
http_configuration_snippet: |
server
{
listen 45651;
server_name _;
access_log off;
location /ysec_status {
req_status_show;
allow 127.0.0.1;
deny all;
}
}
chunked_transfer_encoding on;
http_server_configuration_snippet: |
set $my "var";
http_admin_configuration_snippet: |
log_format admin "$request_time $pipe";
http_end_configuration_snippet: |
server_names_hash_bucket_size 128;
stream_configuration_snippet: |
tcp_nodelay off;
❶ Add custom directives to the main
context (outside other contexts).
❷ Add custom configuration to the http
context.
❸ Add custom directives to the server
context.
❹ Add custom directives to the admin
server
context.
❺ Add custom directives to the end of the http
context.
❻ Add custom configuration to the stream
context.
Make sure to indent the custom configurations correctly. Incorrect indent may cause APISIX to fail while generating NGINX configuration.
FAQ and Troubleshooting
HTTP Requests Automatically Redirected to HTTPS with HTTP/1.1 301 Moved Permanently
or HTTP/1.1 308 Permanent Redirect
Status Codes
APISIX does not force a 301
redirect to HTTPS unless the redirect
plugin is configured as shown in the section above.
If you intend to support both HTTP and HTTPS on the same domain, you do not have to configure the redirect
plugin with http_to_https
enabled.