Deployment guide

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
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 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.

2

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.

3

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>
4

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)"; done

The output shows 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. It confirms Kong's connection to PostgreSQL and shows 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},...}
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. Only root can read the file.

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=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>/example

Keep 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.

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 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/example

The 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/example

The response is HTTP/1.1 401 Unauthorized with a JSON body explaining that no API key was supplied.

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. 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/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 tunnel.

8

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/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. 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/plugins

A 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.

9

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 --yes

Edit the resulting kong.yaml, then re-apply it with:

deck gateway sync --kong-addr http://127.0.0.1:8001 kong.yaml
10

Review 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/postgresql

The output shows the mount source pointing at the dedicated NVMe device rather than the root device.

11

Maintain the services

Restart Kong after you change /etc/kong/kong.conf or apply configuration that requires a reload:

sudo systemctl restart kong

Reload nginx after you change 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 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

Deploy on AWS