Kong Gateway on AWS User Guide
Overview
This image runs Kong Gateway, the open source API gateway and microservice management layer, fully installed and configured from the official Kong package repository. Kong runs in database backed mode against a local PostgreSQL 16 instance, with the database files held on a dedicated, independently resizable storage volume mounted at the database root.
The Kong proxy listens on port 8000 for HTTP traffic and 8443 for HTTPS. A small nginx instance on port 80 forwards traffic to the Kong proxy so the gateway is reachable from a browser or curl without specifying a non standard port. The Admin API is bound to the loopback interface on port 8001 and is reachable over an SSH tunnel; Kong Community Edition has no Admin API authentication so the loopback binding is the security boundary.
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. A per instance API key is generated for a sample consumer named cloudimg and the plain text values are stored in /root/kong-credentials.txt (mode 0600 root). No shared or default credentials ship in the image.
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 allowing inbound port 22 from your management network. Also open port 80 (and optionally 8000 or 8443) to your client network if you intend to call the gateway from outside the VPC
- The AWS CLI version 2 installed locally if you plan to deploy from the command line
Step 1: 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 cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger as a balanced default; size the instance to the API traffic you expect. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that allows inbound port 22 from your management network and port 80 from your client network. If you want 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.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Kong Gateway Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <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 attaches a dedicated 20 GiB PostgreSQL data volume automatically, 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.
Step 3: Connect to the Instance over SSH
Connect to the instance with SSH as the default login user for the operating system variant you launched. The login user differs by variant:
| Operating system variant | SSH login user |
|---|---|
| Ubuntu 24.04 | 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>
Step 4: Confirm Kong and the Backend Services
Check that the three services that make up the gateway stack are all active: PostgreSQL holds Kong's configuration, Kong runs the proxy and Admin API, and nginx forwards port 80 to the Kong proxy.
for s in postgresql kong nginx; do echo "$s=$(systemctl is-active $s)"; done
The output reports one line per service with active next to each:
postgresql=active
kong=active
nginx=active
Confirm the installed Kong version. The image ships Kong Gateway 3.9.x Community Edition.
kong version
Query the Admin API status endpoint on the loopback interface to confirm Kong's connection to PostgreSQL and to see the live request and connection counts.
curl -s http://127.0.0.1:8001/status
The response is a JSON document showing "database":{"reachable":true} and the nginx worker statistics:
{"server":{"connections_writing":3,"total_requests":18,...},"database":{"reachable":true},...}
Step 5: 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. The file is only readable by root.
sudo cat /root/kong-credentials.txt
The 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=cloudimg
kong.consumer.apikey=<per-instance-secret>
kong.example.route=/example
kong.example.test.cmd=curl -H 'apikey: <per-instance-secret>' http://<your-public-ip>/example
Keep the file private. The PostgreSQL password and the API key are unique to your instance and were generated locally on the instance; they are not stored anywhere off the instance.
Step 6: 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 cloudimg with the API key shown above. The combination is a complete demonstration of 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 through nginx on port 80, with the API key. Kong authenticates the consumer, proxies the request to httpbin and returns the httpbin response:
curl -H "apikey: $KEY" http://127.0.0.1/example
The response is the httpbin "anything" JSON, confirming 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.
Send the same request without the API key. Kong's key authentication plugin rejects the request before it reaches the upstream:
curl -i http://127.0.0.1/example
The response is HTTP/1.1 401 Unauthorized with a JSON body explaining that no API key was supplied.
Step 7: 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. Because Kong Community Edition has no Admin API authentication, 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/consumers
From 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 Admin API tunnel.
Step 8: Add Your Own Service, Route and Plugin
The example service and route are intended as a starting point. To proxy your own upstream, create a new service and route from 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/services
Attach 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/routes
Send 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-route
To require an API key on the new route, attach the key authentication plugin and 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/plugins
A wide range of plugins ships with the image (rate limiting, JWT, OAuth2, CORS, request and response transformers, Prometheus metrics, and so on). The Admin API lists them all at http://127.0.0.1:8001/plugins/enabled.
Step 9: The decK Declarative Configuration CLI
The image ships decK at /usr/local/bin/deck. decK lets you export the current gateway configuration to a YAML file, version it, and re apply it idempotently. To export the running configuration:
deck gateway dump --kong-addr http://127.0.0.1:8001 -o kong.yaml --yes
Edit the resulting kong.yaml and re apply with:
deck gateway sync --kong-addr http://127.0.0.1:8001 kong.yaml
Step 10: 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. Keeping the database tier off the operating system disk lets you grow the database independently of the root volume by enlarging the EBS volume from the EC2 console.
Confirm the database directory is a separate mounted filesystem:
findmnt /var/lib/postgresql
The output shows the mount source pointing at the dedicated NVMe device rather than the root device.
Step 11: Service Maintenance
Restart Kong after changing /etc/kong/kong.conf or when applying configuration that requires a reload:
sudo systemctl restart kong
Reload nginx after changing the reverse proxy configuration:
sudo systemctl reload nginx
View the Kong service logs to investigate an upstream timeout or a plugin error:
sudo journalctl -u kong -n 100 --no-pager
PostgreSQL is managed by the standard Ubuntu postgresql.service unit. To upgrade Kong itself, follow the upstream Kong upgrade documentation; the kong package is held by apt-mark hold in this image so that a routine apt upgrade will not bump it accidentally.
Screenshots



Support
Technical support for this image is provided by cloudimg 24/7 by email and chat. Help is available for Kong deployment, route and plugin configuration, upstream wiring, rate limiting, observability and gateway upgrades.