Kong Gateway
Overview
Kong Gateway is an open-source API gateway and microservice management layer. This SecureAnyCloud image runs Kong Gateway, installed and configured from the official Kong package repository, in database-backed mode against a local PostgreSQL 16 instance.
On the first boot of every deployed instance, a one-shot service generates a fresh PostgreSQL password for the Kong role, runs the Kong database migrations, and wires an example service, route and key authentication plugin. It also generates a per-instance API key for a sample consumer named SecureAnyCloud. The plain-text values are stored in /root/kong-credentials.txt (mode 0600 root). No shared or default credentials ship in the image.
What you get:
- The Kong proxy on port 8000 for HTTP traffic and port 8443 for HTTPS
- A small nginx instance on port 80 that forwards traffic to the Kong proxy, so the gateway is reachable from a browser or curl without a non-standard port
- The Admin API bound to the loopback interface on port 8001, reachable over an SSH tunnel. Kong Community Edition has no Admin API authentication, so the loopback binding is the security boundary
- Database files held on a dedicated, independently resizable storage volume mounted at the database root
- A per-instance PostgreSQL password and API key generated on first boot
Prerequisites
Before you deploy this image, you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network. Also open port 80 (and optionally 8000 or 8443) to your client network if you call the gateway from outside the VPC
- The AWS CLI version 2 installed locally, if you plan to deploy from the command line
Launch the instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Kong Gateway. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of m5.large or larger as a balanced default, and size it to the API traffic you expect. Choose your EC2 key pair under Key pair (login).
Under Network settings, select your VPC and subnet, and create or select a security group that allows inbound port 22 from your management network and port 80 from your client network. To address the Kong proxy directly without going through nginx, also open ports 8000 and 8443. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialisation takes only a few seconds after the instance state becomes Running and the status checks pass.
Launch the instance from the AWS CLI
The following command launches an instance from the SecureAnyCloud Kong Gateway Marketplace AMI into an existing subnet and security group.
Replace <ami-id> with the AMI ID shown on the Marketplace listing. Replace <key-name> with your EC2 key pair name and <subnet-id> with your subnet ID. Replace <security-group-id> with a security group that opens port 22 from your management network and port 80 from your client network.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":12,"VolumeType":"gp3"}}' \
--metadata-options 'HttpTokens=required,HttpEndpoint=enabled' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=kong-gateway}]'The image automatically attaches a dedicated 20 GiB PostgreSQL data volume, mounted at the database root. To start with more database storage, enlarge that volume on the Storage step in the console, or add a second block device mapping on the CLI.
Connect to the instance over SSH
Connect to the instance over SSH as the default login user for the operating system variant you launched. The login user differs by variant. For the Ubuntu 24.04 variant, the SSH login user is ubuntu.
Replace <key-file> with the path to your private key file and <instance-public-ip> with the public IP address or DNS name of the instance.
ssh -i <key-file> ubuntu@<instance-public-ip>Confirm Kong and the backend services
Check that the three services of the gateway stack are all active. PostgreSQL holds Kong's configuration, Kong runs the proxy and the Admin API, and nginx forwards port 80 to the Kong proxy.
for s in postgresql kong nginx; do echo "$s=$(systemctl is-active $s)"; doneThe output shows one line per service, with active next to each:
postgresql=active kong=active nginx=activeConfirm the installed Kong version. The image ships Kong Gateway 3.9.x Community Edition.
kong versionQuery the Admin API status endpoint on the loopback interface. It confirms Kong's connection to PostgreSQL and shows the live request and connection counts.
curl -s http://127.0.0.1:8001/statusThe response is a JSON document showing "database":{"reachable":true} and the nginx worker statistics:
{"server":{"connections_writing":3,"total_requests":18,...},"database":{"reachable":true},...}View the per-instance credentials
The first-boot service generated a fresh PostgreSQL password and a fresh consumer API key, and wrote them to /root/kong-credentials.txt. Only root can read the file.
sudo cat /root/kong-credentials.txtThe file lists the proxy URLs, the Admin API URL, the PostgreSQL connection details and the API key for the example consumer.
# Kong Gateway 3 CE — Per-instance credentials
# Generated: Sun May 24 13:34:13 UTC 2026 kong.version=3.9.1 kong.proxy.url=http://<your-public-ip>/ kong.proxy.url.direct=http://<your-public-ip>:8000 kong.proxy.tls.url=https://<your-public-ip>:8443 kong.admin.url=http://127.0.0.1:8001 kong.db.name=kong kong.db.user=kong kong.db.password=<per-instance-secret> kong.consumer.name=sac kong.consumer.apikey=<per-instance-secret> kong.example.route=/example kong.example.test.cmd=curl -H 'apikey: <per-instance-secret>' http://<your-public-ip>/exampleKeep the file private. The PostgreSQL password and the API key are unique to your instance. They were generated locally on the instance and are not stored anywhere off it.
Send a request through the gateway
The first-boot service wired an example service that forwards to httpbin.org, an example route on the path /example, the key authentication plugin on that route, and a consumer named SecureAnyCloud with the API key shown above. Together they demonstrate authenticated proxying through Kong.
Capture the API key from the credentials file:
KEY=$(sudo grep '^kong.consumer.apikey=' /root/kong-credentials.txt | cut -d= -f2-)Send a request with the API key through nginx on port 80. Kong authenticates the consumer, proxies the request to httpbin and returns the httpbin response:
curl -H "apikey: $KEY" http://127.0.0.1/exampleThe response is the httpbin "anything" JSON. It confirms that nginx forwarded the request to Kong, Kong matched the route, the key authentication plugin accepted the API key, and Kong reached the upstream and returned the answer.
Now send the same request without the API key. Kong's key authentication plugin rejects it before it reaches the upstream:
curl -i http://127.0.0.1/exampleThe response is HTTP/1.1 401 Unauthorized with a JSON body explaining that no API key was supplied.
Use the Admin API on the loopback interface
The Kong Admin API is the configuration surface for the gateway. It manages services, routes, plugins, consumers, certificates and more. Kong Community Edition has no Admin API authentication, so the image binds the Admin API to the loopback interface only. There are two recommended ways to reach it.
From a shell on the instance, query the Admin API directly:
curl -s http://127.0.0.1:8001/services
curl -s http://127.0.0.1:8001/routes
curl -s http://127.0.0.1:8001/consumersFrom your workstation, open an SSH tunnel that forwards a local port to the Admin API:
ssh -i <key-file> -L 8001:127.0.0.1:8001 ubuntu@<instance-public-ip>With the tunnel open, point your local Admin API client at http://127.0.0.1:8001 on your workstation. Closing the SSH session closes the tunnel.
Add your own service, route and plugin
The example service and route are a starting point. To proxy your own upstream, create a new service and route with the Admin API. Replace https://my-upstream.example.com with your upstream URL.
curl -s -X POST -H 'Content-Type: application/json' \
--data '{"name":"my-service","url":"https://my-upstream.example.com"}' \
http://127.0.0.1:8001/servicesAttach a route on the path /my-route:
curl -s -X POST -H 'Content-Type: application/json' \
--data '{"name":"my-route","paths":["/my-route"],"strip_path":true}' \
http://127.0.0.1:8001/services/my-service/routesSend a test request through the gateway. The route has no plugins attached, so any client can call it:
curl -s http://127.0.0.1/my-routeTo require an API key on the new route, attach the key authentication plugin. Then add the consumer's existing API key to the new route's allow list.
curl -s -X POST -H 'Content-Type: application/json' \
--data '{"name":"key-auth"}' \
http://127.0.0.1:8001/routes/my-route/pluginsA wide range of plugins ships with the image, including rate limiting, JWT, OAuth2, CORS, request and response transformers, and Prometheus metrics. The Admin API lists them all at http://127.0.0.1:8001/plugins/enabled.
Manage configuration with decK
The image ships decK, the declarative configuration CLI, at /usr/local/bin/deck. decK exports the current gateway configuration to a YAML file that you can version and re-apply idempotently. To export the running configuration:
deck gateway dump --kong-addr http://127.0.0.1:8001 -o kong.yaml --yesEdit the resulting kong.yaml, then re-apply it with:
deck gateway sync --kong-addr http://127.0.0.1:8001 kong.yamlReview PostgreSQL on a dedicated data volume
Kong's configuration lives in a PostgreSQL 16 database whose data directory is mounted on a dedicated EBS volume at /var/lib/postgresql. Because the database tier is off the operating system disk, you can grow it independently of the root volume by enlarging the EBS volume in the EC2 console.
Confirm that the database directory is a separate mounted filesystem:
findmnt /var/lib/postgresqlThe output shows the mount source pointing at the dedicated NVMe device rather than the root device.
Maintain the services
Restart Kong after you change /etc/kong/kong.conf or apply configuration that requires a reload:
sudo systemctl restart kongReload nginx after you change the reverse proxy configuration:
sudo systemctl reload nginxView the Kong service logs to investigate an upstream timeout or a plugin error:
sudo journalctl -u kong -n 100 --no-pagerPostgreSQL is managed by the standard Ubuntu postgresql.service unit.
To upgrade Kong itself, follow the upstream Kong upgrade documentation. The kong package is held with apt-mark hold in this image, so a routine apt upgrade does not upgrade it by accident.
Support
SecureAnyCloud provides 24/7 technical support for this image by email and chat. Support covers Kong deployment, route and plugin configuration, upstream wiring, rate limiting, observability and gateway upgrades.
Deploy on AWS
Launch Kong Gateway on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com