Networking AWS

Tyk Gateway 5.16.0 on AWS User Guide

| Product: Tyk Gateway 5.16.0 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and verifying Tyk Gateway 5.16.0 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened WireGuard VPN & VPN, Proxy and Remote Access AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other VPN, proxy and remote access servers in the listing are described on the listing's guide hub.

Tyk Gateway is an open source API gateway: you describe each of your APIs (its public listen path and the upstream service it forwards to) and Tyk Gateway authenticates, rate limits, transforms and proxies the requests. It supports REST, GraphQL, TCP and gRPC APIs, keys and policies, and is configured through its own Gateway API or API definition files. It is a headless service with no web console; this image ships the open source Gateway only (no Tyk Dashboard, Pump or other licensed components).

What cloudimg adds

  • A supported datastore. Tyk Gateway needs a Redis-compatible datastore. Ubuntu 24.04's redis-server package is in the universe component, which has no standard security support, so this image ships Valkey 9.1.3 (BSD-3-Clause, a version Tyk lists as tested for 5.16) built from the unmodified upstream release after its SHA-256 checksum was checked against the Valkey project's published hashes. The compiler and build tools are removed again before the image is captured.
  • The stock Tyk build, verified. Tyk Gateway 5.16.0 is Tyk's own open source package from its packagecloud repository, installed through apt with the repository key pinned by fingerprint (9179 6215 A875 8C40 AB57 5F03 87BE 71BD 5FB8 3118) and the package checksum pinned.
  • Secrets on every instance. First boot generates the Gateway API secret, the node secret and the Valkey password for each instance. Valkey stores only a SHA-256 hash of its password. Tyk's public sample secret and the image's placeholder are refused.
  • HTTPS from the first boot. nginx serves your APIs on port 443 with a certificate generated on the instance for its public DNS name and addresses (an end-entity certificate, not a certificate authority). Port 80 redirects to that name; requests for any other host name get no answer.
  • The Gateway API stays on the instance. Tyk's management API listens on 127.0.0.1:9696 only and is never proxied by nginx (/tyk/ answers 404 on the public ports). Valkey listens on 127.0.0.1:6379 only.
  • No route to the instance metadata service. Tyk can send requests to any upstream an API definition names, including through load balancing, URL rewrites and service discovery. The Tyk Gateway, Valkey and nginx services are blocked from the instance metadata service at the system level, whatever an API definition says.
  • Fail-closed start and hardened services. Valkey, Tyk Gateway and nginx start only after first boot has finished; if first boot fails, they stay stopped. Tyk Gateway runs as the unprivileged tyk user (the upstream package runs it as root) and Valkey as valkey, each with no capabilities, a read-only system apart from its own data directories and a restricted set of system calls.

Prerequisites

  1. An AWS account and permission to launch EC2 instances
  2. An EC2 key pair in the Region you launch in
  3. The upstream services you want to publish through the gateway

Recommended instance type: m5.large.

Connecting to your instance

Version Operating system SSH user
Tyk Gateway 5.16.0 on Ubuntu 24.04 Ubuntu 24.04 LTS ubuntu

Step 1: Launch the instance

Option A: AWS Marketplace console

  1. Open the cloudimg Hardened WireGuard VPN & VPN, Proxy and Remote Access AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
  2. Once the subscription is active, choose Launch your software.
  3. Choose One-click launch from AWS Marketplace (or Launch from EC2 Console for the full launch wizard). In Version, choose Tyk Gateway 5.16.0 on Ubuntu 24.04, then choose your Region.
  4. Pick an instance type (m5.large recommended; the software charge is $0.04 per vCPU per hour) and your key pair.
  5. Security group: allow SSH (22) from your own IP address, and HTTPS (443) and HTTP (80, which only redirects to HTTPS) from the clients that will call your APIs.
  6. Choose your VPC and subnet, leave the metadata defaults (the image already requires IMDSv2), then choose Launch.

Option B: AWS CLI

Run this on your own workstation. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the VPC, subnet, key pair and CIDR ranges with your own:

SG=$(aws ec2 create-security-group --group-name tyk-gateway \
  --description "Tyk Gateway" --vpc-id vpc-0123456789abcdef0 \
  --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 443 --cidr <your-client-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr <your-client-cidr>
aws ec2 run-instances \
  --image-id ami-0123456789abcdef0 \
  --instance-type m5.large \
  --key-name my-key-pair \
  --security-group-ids "$SG" \
  --subnet-id subnet-0123456789abcdef0 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=tyk-gateway}]'

You do not need --metadata-options: the AMI already makes IMDSv2 required.

Step 2: Connect and read the credentials

Connect as ubuntu with the key pair you chose:

ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>

First boot finishes within a minute of launch. It generates this instance's Gateway API secret, node secret and Valkey password, writes Tyk's configuration and Valkey's access list (which stores only a SHA-256 hash of the password), creates the TLS certificate for the instance's public DNS name, starts Valkey, Tyk Gateway and nginx, and checks that the Gateway API refuses requests without the secret. The details are in /root/tyk-gateway-credentials.txt, readable only by root. This command prints everything except the three secret lines:

sudo grep -vE '^(TYK_SECRET|TYK_NODE_SECRET|VALKEY_PASSWORD)=' /root/tyk-gateway-credentials.txt
# Tyk Gateway 5.16.0 (open source, MPL-2.0) - generated on first boot by tyk-gateway-firstboot.service.
# Every value below is unique to this instance; nothing was baked into the image. Keep this file private.
#
# Your APIs:        https://ec2-54-172-240-122.compute-1.amazonaws.com/<listen-path>/   (:80 redirects here; open 443 in the security group)
# Health:           https://ec2-54-172-240-122.compute-1.amazonaws.com/hello
# Gateway API:      http://127.0.0.1:9696/tyk/...  ON THIS INSTANCE ONLY, header x-tyk-authorization: <TYK_SECRET>
TYK_GATEWAY_API=http://127.0.0.1:9696
VALKEY_HOST=127.0.0.1
VALKEY_PORT=6379

# Self-test: sudo tyk-gateway-selftest    Another host name: sudo tyk-gateway-set-host <name>
# Guide: https://www.cloudimg.co.uk/guides/tyk-gateway-5-16-0-on-ubuntu-24-04-aws/
TYK_HOST=ec2-54-172-240-122.compute-1.amazonaws.com
TYK_URL=https://ec2-54-172-240-122.compute-1.amazonaws.com/
TLS_CERT_SHA256=08:0C:23:9A:33:7C:3F:7A:99:B1:FA:A3:00:E9:10:F9:04:3C:45:EA:08:65:55:EA:40:63:A9:AB:75:13:81:5A

TYK_HOST is your instance's public DNS name (or its IP address when the subnet gives it no public name). TLS_CERT_SHA256 is the fingerprint of the certificate nginx serves: compare it with the fingerprint your client shows the first time it connects. To read the secrets when you need them, run sudo cat /root/tyk-gateway-credentials.txt.

Step 3: Confirm the services are running

systemctl is-active valkey tyk-gateway nginx tyk-gateway-firstboot
ps -o user=,comm= -C tyk,valkey-server,nginx | sort -u
active
active
active
active
root     nginx
tyk      tyk
valkey   valkey-server
www-data nginx

Tyk Gateway runs as tyk and Valkey as valkey; only the nginx master process runs as root (it reads the TLS key and opens ports 80 and 443).

sudo ss -Hltn | awk '{print $4}' | sort
0.0.0.0:22
0.0.0.0:443
0.0.0.0:80
127.0.0.1:6379
127.0.0.1:8080
127.0.0.1:9696
127.0.0.53%lo:53
127.0.0.54:53
[::]:22
[::]:443
[::]:80

Only SSH and nginx (80, 443) listen on the network. Valkey (6379), Tyk's data plane (8080) and the Gateway API (9696) listen on 127.0.0.1 only. Tyk opens 8080 only while at least one API is loaded, and once it has proxied a request it also keeps an internal "all hosts are down" helper on one random 127.0.0.1 port. The two :53 sockets are Ubuntu's local DNS resolver.

Step 4: Run the self-test

The image includes a self-test that exercises the whole path without printing a secret. It creates a temporary API, sends a request through nginx and Tyk Gateway, and deletes the API again:

sudo tyk-gateway-selftest
SELFTEST_OK valkey=auth-required tyk=tyk gateway-api=403/403/200 https-hello=200 tyk-path-via-nginx=404 proxied-api=200 imds-from-tyk=000

Step 5: Use the Gateway API

Tyk Gateway is configured through its Gateway API on http://127.0.0.1:9696/tyk/, with the secret in the x-tyk-authorization header. Put the header in a root-only file on the instance's temporary file system (it is removed at reboot), so the secret never appears on a command line or in your shell history:

sudo sh -c 'umask 077; printf "x-tyk-authorization: %s\n" "$(sed -n "s/^TYK_SECRET=//p" /root/tyk-gateway-credentials.txt)" > /run/tyk-gateway-api.header'
sudo curl -s -H @/run/tyk-gateway-api.header http://127.0.0.1:9696/tyk/apis; echo
[]

The gateway starts with no APIs. Without the secret, the Gateway API refuses the request:

curl -s http://127.0.0.1:9696/tyk/apis; echo
{"status":"error","message":"Attempted administrative access with invalid or missing key!"}

Step 6: Publish your first API

This creates a keyless API that publishes https://ip-ranges.amazonaws.com/ under the listen path /aws-ip-ranges/, then hot-reloads the gateway:

sudo curl -s -H @/run/tyk-gateway-api.header -H 'Content-Type: application/json' \
  -d '{"name":"aws-ip-ranges","api_id":"aws-ip-ranges","org_id":"default","use_keyless":true,"active":true,
       "version_data":{"not_versioned":true,"versions":{"Default":{"name":"Default"}}},
       "proxy":{"listen_path":"/aws-ip-ranges/","target_url":"https://ip-ranges.amazonaws.com/","strip_listen_path":true}}' \
  http://127.0.0.1:9696/tyk/apis; echo
sudo curl -s -H @/run/tyk-gateway-api.header http://127.0.0.1:9696/tyk/reload/group; echo
{"key":"aws-ip-ranges","status":"ok","action":"added"}
{"status":"ok","message":""}

Call it through nginx and Tyk. On the instance itself, --resolve points the instance's host name at 127.0.0.1; from your workstation, call https://<TYK_HOST>/aws-ip-ranges/ip-ranges.json directly (after you open port 443 to it):

H=$(sudo sed -n 's/^TYK_HOST=//p' /root/tyk-gateway-credentials.txt)
sleep 2
curl -s -o /dev/null -w '%{http_code} %{content_type}\n' --cacert /etc/nginx/cloudimg/tls/tyk-gateway.crt \
  --resolve "$H:443:127.0.0.1" "https://$H/aws-ip-ranges/ip-ranges.json"
200 application/json

Port 80 only redirects to the configured host on HTTPS:

H=$(sudo sed -n 's/^TYK_HOST=//p' /root/tyk-gateway-credentials.txt)
curl -s -o /dev/null -D - --resolve "$H:80:127.0.0.1" "http://$H/aws-ip-ranges/ip-ranges.json" | tr -d '\r' \
  | awk -v want="https://$H/aws-ip-ranges/ip-ranges.json" 'NR==1{print $2} tolower($1)=="location:"{print ($2==want ? "Location: https, same host and path" : "Location: unexpected")}'
301
Location: https, same host and path

To protect an API with keys, set "use_keyless": false and an authentication method in its definition, then create keys with POST /tyk/keys/create; Tyk's documentation covers keys, policies, rate limits and the other API definition options. API definitions you create through the Gateway API are stored in /opt/tyk-gateway/apps/; keys and sessions are stored in Valkey.

Step 7: The Gateway API is not reachable from the network

nginx never forwards /tyk/, and the Gateway API listens on loopback only:

H=$(sudo sed -n 's/^TYK_HOST=//p' /root/tyk-gateway-credentials.txt)
curl -s -o /dev/null -w '%{http_code}\n' --cacert /etc/nginx/cloudimg/tls/tyk-gateway.crt --resolve "$H:443:127.0.0.1" "https://$H/tyk/apis"
curl -s -m 5 "http://$(hostname -I | awk '{print $1}'):9696/hello" || echo "connection refused on the private address"
404
connection refused on the private address

Requests for any host name that is not this instance's configured name or address get no answer, so the gateway cannot be reached through someone else's DNS name.

Step 8: Instance metadata is unreachable through the gateway

An API definition can point Tyk Gateway at any upstream, so the image blocks the instance metadata service (169.254.169.254, its IPv6 address and 168.63.129.16) for the Tyk Gateway, Valkey and nginx services at the system level. This publishes an API whose upstream is the metadata service and calls it; Tyk waits 15 seconds for an answer that never comes:

sudo curl -s -H @/run/tyk-gateway-api.header -H 'Content-Type: application/json' \
  -d '{"name":"imds-test","api_id":"imds-test","org_id":"default","use_keyless":true,"active":true,
       "version_data":{"not_versioned":true,"versions":{"Default":{"name":"Default"}}},
       "proxy":{"listen_path":"/imds-test/","target_url":"http://169.254.169.254/latest/meta-data/","strip_listen_path":true}}' \
  http://127.0.0.1:9696/tyk/apis; echo
sudo curl -s -H @/run/tyk-gateway-api.header http://127.0.0.1:9696/tyk/reload/group; echo
H=$(sudo sed -n 's/^TYK_HOST=//p' /root/tyk-gateway-credentials.txt)
sleep 2
curl -s -w '\nHTTP %{http_code}\n' --cacert /etc/nginx/cloudimg/tls/tyk-gateway.crt --resolve "$H:443:127.0.0.1" "https://$H/imds-test/"
{"key":"imds-test","status":"ok","action":"added"}
{"status":"ok","message":""}
{
    "error": "There was a problem proxying the request"
}
HTTP 500

The block covers every way Tyk can send a request (upstream URLs, load-balancing target lists, URL rewrites, service discovery, JWKS and introspection fetches, webhooks). Remove the test API and the example API, and the header file:

for a in imds-test aws-ip-ranges; do sudo curl -s -X DELETE -H @/run/tyk-gateway-api.header "http://127.0.0.1:9696/tyk/apis/$a"; echo; done
sudo curl -s -H @/run/tyk-gateway-api.header http://127.0.0.1:9696/tyk/reload/group; echo
sudo shred -u /run/tyk-gateway-api.header
{"key":"imds-test","status":"ok","action":"deleted"}
{"key":"aws-ip-ranges","status":"ok","action":"deleted"}
{"status":"ok","message":""}

Step 9: Valkey requires the password

valkey-cli -h 127.0.0.1 PING
NOAUTH Authentication required.

Tyk Gateway already has the password in /opt/tyk-gateway/tyk.conf. For your own maintenance, sudo cat /root/tyk-gateway-credentials.txt shows VALKEY_PASSWORD; use it with valkey-cli --askpass so it never lands on a command line.

Step 10: Use your own domain name

Point a DNS name at the instance (an Elastic IP is recommended so the address survives a stop and start), then:

sudo tyk-gateway-set-host api.example.com

This creates a new key and certificate for the name, makes it the name port 80 redirects to and updates TYK_HOST, TYK_URL and TLS_CERT_SHA256 in the credentials file. The instance's public and private IP addresses stay accepted. For production, replace /etc/nginx/cloudimg/tls/tyk-gateway.crt and .key with a certificate from your certificate authority and reload nginx (sudo systemctl reload nginx). Browser applications on other origins that open WebSockets through the gateway must be listed in /etc/nginx/cloudimg/tyk-gateway-origins.map (one "https://app.example.com" 1; line each); non-browser clients are not affected.

Step 11: Upgrading Tyk Gateway

The image ships Tyk's packagecloud repository with its signing key pinned, but disabled, so nothing changes the gateway unexpectedly. To upgrade, set Enabled: yes in /etc/apt/sources.list.d/tyk-gateway.sources, then run sudo apt-get update && sudo apt-get install --only-upgrade tyk-gateway. Read Tyk's release notes for configuration changes first. Ubuntu security updates install automatically as usual.

How the secure start works

  1. The image contains no secret: tyk.conf holds a placeholder that Tyk Gateway never runs with, Valkey has no access list and nginx has no certificate.
  2. Valkey, Tyk Gateway and nginx start only when the ready marker /var/lib/cloudimg/tyk-gateway-ready exists. Only a completed first boot writes it.
  3. tyk-gateway-firstboot.service generates the secrets and certificate, starts the services, and checks that Valkey refuses unauthenticated clients and that the Gateway API refuses no secret, the image placeholder and Tyk's public sample secret, before it writes the credentials file.
  4. If any step fails, the three services are stopped and the ready marker is removed; the next boot tries again.

Security recommendations

  • Open port 443 (and 80) only to the clients that call your APIs, and SSH only to your own address.
  • Keep the credentials file private; anyone with the Gateway API secret can change every API on the gateway.
  • Give the instance an IAM role only if an API or plugin needs one: the gateway cannot reach the instance metadata service, so it cannot use the role's credentials anyway.
  • JWT authentication with a JWKS URL: point it only at identity providers you trust. Tyk 5.16.0 parses JWKS documents with go-jose v3, for which a denial-of-service advisory (GHSA-mgcc-cww5-fp2q, a crafted RSA key) has no fix; it can only be triggered by the JWKS endpoint you configure, never by a client request. cloudimg will publish an updated version when Tyk ships a release that moves to a fixed library.
  • Replace the self-signed certificate with one from your certificate authority for production traffic.

Support and licensing

Tyk Gateway is open source software under the Mozilla Public License 2.0 (/opt/share/docs/tyk-gateway/LICENSE.md); this image ships the open source Gateway only, not Tyk's licensed products. Valkey is under the BSD 3-Clause licence (/usr/local/share/doc/valkey/). Tyk is a trademark of Tyk Technologies Ltd and Valkey is a trademark of the Linux Foundation; cloudimg is not affiliated with or endorsed by either. For help with this image, contact cloudimg support through the AWS Marketplace listing.