Kong 3
Overview
Kong Gateway is an open-source API gateway and microservices ingress. It is a Lua/OpenResty data plane on top of nginx that handles routing, authentication, rate limiting, transformations and observability through its plugin ecosystem.
This image installs Kong Gateway 3.9.1 OSS Community Edition, pinned with apt-mark hold and backed by PostgreSQL 16 on loopback. The Admin API is bound strictly to 127.0.0.1:8001. Kong OSS has no Admin API authentication, so loopback is the security boundary. A first-boot oneshot wires up an example service, route, key-auth plugin and consumer, so the gateway handles real upstream traffic as soon as the VM finishes booting. The decK CLI is bundled at /usr/local/bin/deck for declarative configuration management.
What you get:
- Kong Gateway 3.9.1 OSS Community Edition (Apache 2.0) from the official Cloudsmith repository
gateway-39/noble, pinned withapt-mark hold kong=3.9.1 - PostgreSQL 16 from Ubuntu noble main, with a per-VM
kongrole andkongdatabase, listening on127.0.0.1:5432only - Admin API on
127.0.0.1:8001, loopback only and never exposed - Proxy plane on
0.0.0.0:8000(HTTP) and0.0.0.0:8443(HTTPS) - decK CLI 1.59.1 at
/usr/local/bin/deckfor declarative config management kong-firstboot.serviceoneshot, which runs the migrations bootstrap, generates the per-VM database password and consumer API key, writes/etc/kong/kong-firstboot.envand touches/var/lib/sac/data/kong-firstboot.donekong-postboot.serviceoneshot, which waits for the Admin API, creates the example service, route, key-auth plugin and consumer through the Admin API, touches/var/lib/sac/data/kong-postboot.doneand then disables itself- Per-VM credentials log at
/stage/scripts/kong-credentials.log(root:root 0600) carryingKONG_DB_PASSWORD,KONG_CONSUMER_API_KEYandKONG_PROXY_URL - 24/7 SecureAnyCloud support
There is no web UI. Administer Kong OSS through the Admin API, the decK CLI or any Kong-compatible tooling.
Prerequisites
You need an active Azure subscription, an SSH key, and a virtual network with a subnet. Standard_B2s (4 GB RAM) is comfortable for a single-node Kong and PostgreSQL on the same VM.
In the network security group (NSG), allow 22/tcp inbound from your management CIDR. Allow 8000/tcp and 8443/tcp from any client CIDR that needs to reach the proxy. Never expose 8001/tcp. That port is the Admin API, and it has no authentication in Kong OSS.
Step 1-3: Deploy and connect over SSH
Deploy the VM from the Azure Marketplace, then connect over SSH.
ssh azureuser@<vm-ip>Check service status and versions
Check that the services are running and note the installed versions.
sudo systemctl is-active kong.service postgresql.service kong-firstboot.service kong-postboot.service /usr/local/bin/kong version /usr/local/bin/deck versionAll four services report active. Kong reports 3.9.1 and decK reports v1.59.1.
Read the per-VM credentials
Print the credentials log.
sudo cat /stage/scripts/kong-credentials.logNote these values:
KONG_CONSUMER_API_KEYis the demo consumer's key-auth credential. You use it in Step 8.KONG_PROXY_URLis the proxy address.KONG_DB_PASSWORDis the per-VM PostgreSQL password Kong uses to reach its database.
The file is root:root 0600.
Check Admin API health
Query the Admin API status endpoint.
curl -sf http://127.0.0.1:8001/status | jqThe response shows the gateway's connection counters, lua_shared_dicts memory utilisation and database.reachable: true, which confirms a PostgreSQL round trip.
The Admin API listens on 127.0.0.1:8001 only. It is bound to loopback because the Kong OSS Admin API has no authentication, and exposing it would let any client reconfigure the gateway. For remote administration, tunnel through SSH with ssh -L 8001:127.0.0.1:8001 azureuser@<vm-ip>. You can also front the Admin API with a reverse proxy that does its own authentication.
List services and routes
List the services and routes that the first-boot oneshot created.
curl -sf http://127.0.0.1:8001/services | jq '.data[].name'
curl -sf http://127.0.0.1:8001/routes | jq '.data[].paths'You see sac-firstboot-service and ["/example"]. This is the demo set up by the postboot oneshot. The service points to https://httpbin.org/anything, and a key-auth plugin protects the route.
Test the proxy with key-auth
Read the consumer's API key from the credentials log. Then call the proxy with and without the key.
KEY=$(sudo grep '^KONG_CONSUMER_API_KEY=' /stage/scripts/kong-credentials.log | cut -d= -f2)
curl -sf -H "apikey: $KEY" http://127.0.0.1:8000/example | jq '.url'
curl -sI http://127.0.0.1:8000/example | head -1The first call returns the upstream URL string from httpbin.org, which shows that Kong proxied the request. The second call has no apikey header and returns HTTP/1.1 401 Unauthorized, which shows that the key-auth plugin enforces the credential.
Manage routes with the Admin API
Add a new service and route with the Admin API. This example adds a route on /github that proxies to https://api.github.com.
curl -s -X POST http://127.0.0.1:8001/services \
-d 'name=github-api' \
-d 'url=https://api.github.com'
curl -s -X POST http://127.0.0.1:8001/services/github-api/routes \
-d 'name=github-route' \
-d 'paths[]=/github'
curl -sf http://127.0.0.1:8001/routes | jq '.data[].paths'To remove a route or service, send DELETE to the same endpoints.
curl -s -X DELETE http://127.0.0.1:8001/routes/github-route
curl -s -X DELETE http://127.0.0.1:8001/services/github-apiManage routes with decK (declarative)
decK treats the gateway's configuration as a YAML file that you can keep under version control. Dump the current configuration, edit it, then sync it back.
sudo /usr/local/bin/deck gateway dump --kong-addr http://127.0.0.1:8001 -o /tmp/kong.yaml
sudo /usr/local/bin/deck gateway diff --kong-addr http://127.0.0.1:8001 /tmp/kong.yamldump writes a snapshot of every service, route, plugin, consumer and credential. diff shows the difference between the YAML file and the live gateway. It reports no changes immediately after a fresh dump.
To apply the YAML back, run deck gateway sync. In production, keep the YAML in git and run deck gateway sync from CI.
Add plugins
Kong's plugin ecosystem covers rate limiting, authentication (jwt, oauth2, basic-auth, ldap-auth), transformations, observability (prometheus, opentelemetry, zipkin), traffic control and more. Attach the rate-limiting plugin to the example service.
curl -s -X POST http://127.0.0.1:8001/services/sac-firstboot-service/plugins \
-d 'name=rate-limiting' \
-d 'config.minute=10'Browse the full plugin catalogue at https://docs.konghq.com/hub/. You can attach plugins at the global, service, route or consumer scope.
Tune worker processes
Kong inherits nginx's worker model. Edit /etc/kong/kong.conf to set nginx_worker_processes.
sudo sed -i 's/^#nginx_worker_processes.*/nginx_worker_processes = auto/' /etc/kong/kong.conf
sudo systemctl restart kong.serviceThe defaults on Standard_B2s are:
admin_listen:127.0.0.1:8001(loopback only, which is the security boundary)proxy_listen:0.0.0.0:8000, 0.0.0.0:8443 ssl- database: postgres
pg_host:127.0.0.1nginx_worker_processes:auto(one worker per vCPU)
On bigger VMs, auto is usually the right choice for higher throughput. Kong's data plane is heavily I/O-bound and benefits from one worker per CPU core.
Open the proxy to public traffic
The NSG attached to this VM at deploy time already allows 8000/tcp and 8443/tcp from your chosen client CIDR. To restrict access further, for example to your CDN's egress ranges only, edit the NSG inbound rules in the Azure portal or run the following command.
az network nsg rule update -g <rg> --nsg-name <nsg> -n allow-kong-8000 \
--source-address-prefixes <your-cidr>Inside the VM, the Ubuntu firewall (ufw) is disabled, so Kong listens directly. If you enable ufw, add sudo ufw allow 8000/tcp and sudo ufw allow 8443/tcp.
Install a Let's Encrypt certificate
Kong has an official ACME plugin that handles Let's Encrypt issuance and renewal inside the gateway. Enable it with the following command.
curl -s -X POST http://127.0.0.1:8001/plugins \
-d 'name=acme' \
-d 'config.account_email=you@example.com' \
-d 'config.tos_accepted=true' \
-d 'config.domains[]=apps.example.com'Point your domain's DNS A record at this VM, then run curl https://apps.example.com:8443/example. Kong requests a certificate from Let's Encrypt on the first request and serves it from then on. Kong's internal scheduler renews the certificate automatically.
Alternatively, terminate SSL at nginx or Caddy in front of Kong and proxy to 127.0.0.1:8000. This older pattern is useful if you already have a reverse proxy in front. For new deployments, the ACME plugin is the simpler choice.
Back up
Kong's only persistent state is its PostgreSQL database. Take a consistent backup while the gateway is running.
PASS=$(sudo grep '^KONG_DB_PASSWORD=' /stage/scripts/kong-credentials.log | cut -d= -f2-) PGPASSWORD="$PASS" pg_dump -h 127.0.0.1 -U kong kong | gzip > /var/backups/kong-db-$(date +%F).sql.gz
sudo cp /etc/kong/kong.conf /var/backups/kong.conf-$(date +%F)If you manage Kong declaratively with decK (Step 10), also commit your YAML to git. The YAML and a fresh PostgreSQL pg_dump together form a complete, replayable backup. Copy /var/backups to Azure Blob Storage (az storage blob upload-batch) regularly to keep a copy off the VM.
Logs and troubleshooting
Read the service logs.
sudo journalctl -u kong.service --no-pager -n 80
sudo journalctl -u kong-firstboot.service --no-pager -n 30
sudo journalctl -u kong-postboot.service --no-pager -n 30
sudo tail -50 /usr/local/kong/logs/access.log
sudo tail -50 /usr/local/kong/logs/error.logkong reload is a graceful nginx reload. It applies configuration changes without dropping in-flight connections.
sudo /usr/local/bin/kong reloadFor a deeper inspection, the Admin API exposes everything: curl http://127.0.0.1:8001/status, /services, /routes, /plugins, /consumers, /upstreams and /targets. It also serves Prometheus-style metrics if you enable the prometheus plugin.
Security
- The Admin API is bound to
127.0.0.1:8001only. Kong OSS has no Admin API authentication, so loopback is the boundary. Never bind the Admin API to a routable interface. - PostgreSQL listens on
127.0.0.1:5432only, and Kong is its only consumer. - A per-VM
KONG_DB_PASSWORD(32 hex chars) is generated at first boot. - A per-VM
KONG_CONSUMER_API_KEYis generated for the demo consumer. Rotate or replace it once you set up your own consumers. - NSG inbound opens
22/tcp,8000/tcpand8443/tcponly, never8001/tcp. - Use the decK CLI's
gateway diffworkflow to catch unintended configuration drift before you apply changes. - Use the
key-auth,jwt,oauth2orbasic-authplugins on every public route. Kong does not authenticate requests by default.
Support
SecureAnyCloud provides 24/7/365 expert technical support, with a guaranteed response within 24 hours and a one-hour average for critical issues. Contact sales@secureanycloud.com.
Deploy on Azure
Launch Kong Gateway 3.9.1 OSS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com