KrakenD Community Edition 3.0.2 on AWS User Guide
Overview
This guide covers launching and using the KrakenD Community Edition 3.0.2 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg application infrastructure listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Which KrakenD this is. KrakenD Community Edition is the open source KrakenD API gateway, published under the Apache License 2.0. KrakenD Enterprise is a separate commercial product from KrakenD and is not included.
KrakenD is a stateless, declarative, high performance API gateway. You describe your public API in one JSON file: each endpoint lists the backend calls behind it, and KrakenD routes, aggregates, filters and secures those calls, with JWT validation, rate limiting, circuit breakers and response manipulation built in. It keeps no database, so a gateway is just a binary and a configuration file.
The cloudimg image gives you a KrakenD that is safe to put on a public address from the first minute:
- CVE-2026-111943 fixed and provable. KrakenD 3.0.2 is built with Go 1.26.10, which refuses certificate chains through the eight compromised eMudhra intermediate CAs, and the Ubuntu trust store on the image no longer carries the roots those chains end in.
sudo krakend-cve-2026-111943-checkproves both on your instance (Step 9). - HTTPS from the first boot. nginx terminates TLS on port 443 with a certificate generated on your instance's first boot (TLS 1.2 or newer) and hands requests to KrakenD on
127.0.0.1:8080. No certificate or key is baked into the image, and nothing listens on port 80. - Never an open proxy. KrakenD only serves the endpoints declared in
/etc/krakend/krakend.json. The shipped endpoints call one fixed demo backend on127.0.0.1:8081, which you replace with your own services. Requests for other host names, and absolute URLs aimed at another host (such as the instance metadata address), are dropped. - Internal endpoints stay private. KrakenD's
/__healthanswers on loopback only, its/__debugand/__echoendpoints are switched off, no metrics listener is configured, and nginx returns 404 for every/__path. The public/healthprobe returnsokonly while KrakenD is healthy. - A JWT protected endpoint with a per instance key.
/v1/secure/users/{id}is protected by KrakenD's JWT validator against an HS256 signing key generated on your instance's first boot; a demo token is in a root only file, and a helper mints more. - The real client address. nginx overwrites
X-Forwarded-ForandX-Real-IPwith the connection's address and drops client suppliedForwardedandX-Forwarded-Hostheaders, and KrakenD trusts forwarding headers from127.0.0.1only. - Sandboxed and fail closed. KrakenD runs as the unprivileged
krakenduser with no capabilities under a locked down systemd unit that cannot reach the instance metadata service, with KrakenD's anonymous usage reporting switched off. KrakenD and nginx will not start until first boot has generated the keys, and the configuration is checked against KrakenD's schema before every start. - Built from the unmodified source. The image compiles the tagged 3.0.2 source, with its
go.modandgo.sumexactly as released, using Go 1.26.10 (the Go release KrakenD builds 3.0.2 with).govulncheckreports 0 reachable advisories, and the binary is reproducible (Step 12). - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on, and SSH set to key only logins with no root login.
What is on the image: KrakenD Community Edition 3.0.2 (/usr/local/bin/krakend, licence and build provenance in /usr/share/doc/krakend), the gateway configuration /etc/krakend/krakend.json (KrakenD 3.0 configuration format, "version": 4), nginx, the krakend.service and krakend-firstboot.service units, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH) from your own networks only and TCP 443 (HTTPS) from the clients that call your API. Nothing else needs to be open: KrakenD and the demo backend listen on loopback only, and there is no port 80 listener.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick KrakenD Community Edition 3.0.2 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (KrakenD is light; size up for high request rates), your key pair, and a security group as above.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=krakend}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| KrakenD Community Edition 3.0.2 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot generates the certificate, the JWT signing key and a demo token, then KrakenD and nginx start:
systemctl is-active krakend nginx
sudo test -f /var/lib/cloudimg/krakend-firstboot.done && echo FIRSTBOOT_DONE
krakend version
active
active
FIRSTBOOT_DONE
KrakenD Version: 3.0.2
Go Version: 1.26.10
Glibc Version: STATIC-CGO-DISABLED
nginx listens on port 443 on every address; KrakenD (8080) and the demo backend (8081) listen on loopback only:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | sed -E 's/pid=[0-9]+,fd=[0-9]+/.../g' | sort -u
0.0.0.0:22 users:(("sshd",...),("systemd",...))
0.0.0.0:443 users:(("nginx",...),("nginx",...),("nginx",...))
127.0.0.1:8080 users:(("krakend",...))
127.0.0.1:8081 users:(("nginx",...),("nginx",...),("nginx",...))
127.0.0.53%lo:53 users:(("systemd-resolve",...))
127.0.0.54:53 users:(("systemd-resolve",...))
[::]:22 users:(("sshd",...),("systemd",...))
[::]:443 users:(("nginx",...),("nginx",...),("nginx",...))
(nginx runs one worker per vCPU, so the number of nginx entries matches your instance size.)
Step 4: Your instance's URL and demo token
sudo cat /root/krakend-credentials.txt
The file is readable by root only:
# KrakenD Community Edition 3.0.2 - generated on first boot by krakend-firstboot.service
# The JWT signing key and the demo token are unique to this instance; none was baked into the image. Keep this secret.
KRAKEND_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
KRAKEND_CERT_SHA256=<sha256-fingerprint>
KRAKEND_CONFIG=/etc/krakend/krakend.json
KRAKEND_JWK_FILE=/etc/krakend/jwk-cloudimg.json
KRAKEND_JWT_ISSUER=cloudimg-krakend-demo
KRAKEND_DEMO_TOKEN=<KRAKEND_DEMO_TOKEN>
#
# nginx (HTTPS) is the only public entry point; KrakenD runs on 127.0.0.1:8080 and the demo backend on 127.0.0.1:8081.
# KRAKEND_DEMO_TOKEN (30 days) opens /v1/secure/users/{id}: curl -H "Authorization: Bearer <token>" .../v1/secure/users/1
# New demo token: sudo krakend-demo-token --ttl 3600
# New signing key + token: sudo krakend-rotate-jwt-key
# Change the name it serves as: sudo krakend-set-hostname <your-dns-name>
# User guide: https://www.cloudimg.co.uk/guides/krakend-community-edition-3-0-2-on-ubuntu-24-04-aws/
The URL uses the instance's public DNS name from EC2 instance metadata. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too. To serve your own DNS name, see Step 10.
Step 5: Send requests through KrakenD
The shipped configuration declares three endpoints in front of the demo backend. /v1/hello proxies one backend call, and /v1/users/{id} calls the backend twice (the user record and the user's orders) and merges both answers into one response. From the instance itself, trusting the instance's own certificate:
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
curl -s --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/hello" | jq .
curl -s --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/users/1" | jq .
curl -s -o /dev/null -D - --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/hello" | tr -d '\r' | grep -iE '^(HTTP|content-type|x-krakend|strict-transport|x-content)'
{
"message": "Hello from the demo backend on 127.0.0.1:8081, routed through KrakenD",
"service": "cloudimg-krakend-demo-backend"
}
{
"orders": {
"orders": [
{
"id": 1001,
"status": "shipped",
"total": 42.50
},
{
"id": 1002,
"status": "processing",
"total": 19.99
}
]
},
"user": {
"email": "ada@example.com",
"id": 1,
"name": "Ada Lovelace",
"plan": "enterprise"
}
}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Krakend: Version 3.0.2
X-Krakend-Completed: true
Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
From your own machine, call the gateway over the internet (the certificate is self signed, so -k skips the check; Step 10 covers your own name and certificate):
curl -k https://<public-ip>/v1/users/2
KrakenD only answers the endpoints you declare. Any other path is 404, a host name the instance does not serve is dropped, an absolute URL that tries to use the gateway as a forward proxy to another host (here the instance metadata address) is dropped, and nothing answers on port 80:
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
for p in /v1/nope /latest/meta-data/; do curl -s -o /dev/null -w "$p -> %{http_code}\n" --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H$p"; done
curl -sk -o /dev/null -w 'unknown host name -> %{http_code}\n' --resolve "other.example:443:127.0.0.1" "https://other.example/v1/hello"
curl -sk -o /dev/null -w 'absolute URL for another host -> %{http_code}\n' --request-target 'http://169.254.169.254/latest/meta-data/' -H "Host: $H" https://127.0.0.1/
curl -s -o /dev/null -w 'port 80 -> %{http_code}\n' http://127.0.0.1/ || true
/v1/nope -> 404
/latest/meta-data/ -> 404
unknown host name -> 000
absolute URL for another host -> 000
port 80 -> 000
000 means the connection was closed without an answer.
Step 6: The JWT protected endpoint
/v1/secure/users/{id} is protected by KrakenD's auth/validator: it accepts only an HS256 token signed with this instance's key (/etc/krakend/jwk-cloudimg.json, generated on first boot), issued by cloudimg-krakend-demo, with the role demo. Without a valid token the request never reaches the backend:
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
T=$(sudo sed -n 's/^KRAKEND_DEMO_TOKEN=//p' /root/krakend-credentials.txt)
curl -s -o /dev/null -w 'no token -> %{http_code}\n' --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/secure/users/3"
curl -s -o /dev/null -w 'bad token -> %{http_code}\n' -H 'Authorization: Bearer not.a.token' --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/secure/users/3"
curl -s -K <(printf 'header = "Authorization: Bearer %s"\n' "$T") --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/secure/users/3" | jq .
no token -> 401
bad token -> 401
{
"email": "grace@example.com",
"id": 3,
"name": "Grace Hopper",
"plan": "starter"
}
(curl -K reads the header from a file descriptor, so the token never appears on a command line.) Mint more tokens with krakend-demo-token (--sub, --ttl in seconds, --role); a token with another role gets 403:
T2=$(sudo krakend-demo-token --sub alice --ttl 600)
echo "$T2" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | jq -c '{iss, sub, roles}'
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
curl -s -o /dev/null -w 'new token -> %{http_code}\n' -K <(printf 'header = "Authorization: Bearer %s"\n' "$T2") --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H/v1/secure/users/2"
{"iss":"cloudimg-krakend-demo","sub":"alice","roles":["demo"]}
new token -> 200
sudo krakend-rotate-jwt-key replaces the signing key (every older token stops working), writes a new demo token and restarts KrakenD. In production you will usually point the validator at your identity provider's JWKS URL (jwk_url) instead of a local key; the KrakenD JWT validation documentation covers every option. KrakenD verifies that URL's certificate against the system trust store, which is the store Step 9 checks.
Step 7: Health and internal endpoints
Load balancers and monitoring can use the public /health probe: nginx answers ok only while KrakenD's own /__health reports healthy. KrakenD's internal endpoints are never reachable from the network, and the debug and echo endpoints are switched off even on loopback:
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
for p in /health /__health /__debug/ /__echo/ /__stats; do curl -s -o /dev/null -w "public $p -> %{http_code}\n" --cacert /etc/nginx/tls/krakend.crt --resolve "$H:443:127.0.0.1" "https://$H$p"; done
curl -s http://127.0.0.1:8080/__health | jq -c '{status}'
curl -s -o /dev/null -w 'loopback /__debug/ -> %{http_code}\n' http://127.0.0.1:8080/__debug/
public /health -> 200
public /__health -> 404
public /__debug/ -> 404
public /__echo/ -> 404
public /__stats -> 404
{"status":"ok"}
loopback /__debug/ -> 404
If you enable KrakenD's OpenTelemetry exporters later, keep any port they open bound to 127.0.0.1 and never open it in a security group.
Step 8: Put your own services behind KrakenD
Edit /etc/krakend/krakend.json and replace the demo endpoints with your own API. The file uses the KrakenD 3.0 configuration format ("version": 4 and the v3.0 schema); KrakenD 3.0 refuses files that still say "version": 3:
sudo jq -c '{"$schema", version, listen_ip, port}' /etc/krakend/krakend.json
{"$schema":"https://www.krakend.io/schema/v3.0/krakend.json","version":4,"listen_ip":"127.0.0.1","port":8080}
sudo nano /etc/krakend/krakend.json
Each endpoint lists its backends; a backend can be a service on this instance or a private address in your VPC. For example, an endpoint that proxies an orders service on a private host:
{
"endpoint": "/v1/orders/{id}",
"method": "GET",
"backend": [
{ "host": ["http://10.0.1.25:3000"], "url_pattern": "/orders/{id}" }
]
}
Keep "listen_ip": "127.0.0.1" (nginx is the public entry point) and leave debug_endpoint and echo_endpoint off. Check the file against KrakenD's built in schema before you restart, so a typing mistake never takes the gateway down (the unit runs the same check before every start):
sudo krakend check -c /etc/krakend/krakend.json -n
Parsing configuration file: /etc/krakend/krakend.json
Syntax OK!
sudo systemctl restart krakend
The demo backend (127.0.0.1:8081) can stay or go; once your own services are behind KrakenD you can remove its server block from /etc/nginx/sites-available/cloudimg-krakend. Whatever you route to, KrakenD cannot reach the instance metadata service (Step 11).
Moving a 2.x configuration: KrakenD 3.0 needs "version": 4, has no Go plugin support in the Community Edition (Lua scripts cover many of the same needs), and dropped the OpenCensus, InfluxDB and separate metrics port components in favour of OpenTelemetry. See KrakenD's upgrade notes and run krakend check --lint on the result.
Step 9: Check CVE-2026-111943 (compromised eMudhra CAs)
CVE-2026-111943 is a Critical advisory: the private keys of eight eMudhra intermediate certificate authorities were compromised, so anyone holding them could issue a certificate that a vulnerable client trusts for any host name. KrakenD verifies certificates with Go's crypto/x509 against the operating system trust store (/etc/ssl/certs), both for its calls to HTTPS backends, JWK URLs and telemetry exporters and for client certificates when you enable mTLS. KrakenD Community Edition 3.0.2 is the fixed release.
This image closes it twice over: KrakenD is built with Go 1.26.10, whose crypto/x509 rejects any chain through the eight intermediates whatever the trust store says, and Ubuntu's ca-certificates update (20260816ubuntu0.24.04.1) removed the roots those chains end in. The shipped check proves both on your own instance:
sudo krakend-cve-2026-111943-check
cve-2026-111943: ok KrakenD 3.0.2 (>= 3.0.2)
cve-2026-111943: ok built with Go 1.26.10 (>= 1.26.10)
cve-2026-111943: ok Go's distrust list of the 8 eMudhra intermediates is compiled into /usr/local/bin/krakend
cve-2026-111943: ok the running KrakenD (pid <pid>) uses the system trust store
cve-2026-111943: ok 120 trusted certificates: no eMudhra intermediate and no root of the affected chains
cve-2026-111943: ok positive controls (Amazon Root CA 1, ISRG Root X1) present
cve-2026-111943: ok ca-certificates 20260816ubuntu0.24.04.1 (>= 20260816ubuntu0.24.04.1)
cve-2026-111943: RESULT CLOSED
Run it again after you add your own CA certificates to the system store or replace the KrakenD binary. If you enable mTLS for clients (enable_mtls), KrakenD also trusts the system store for client certificates unless you set disable_system_ca_pool with an explicit ca_certs list, as KrakenD's advisory recommends.
Step 10: Your own DNS name and certificate
Point a DNS record at the instance, then set the name the gateway serves. This mints a new self signed certificate for the name, updates the nginx host settings, reloads nginx and keeps the name across reboots:
sudo krakend-set-hostname <your-domain>
To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx (running krakend-set-hostname again replaces it with a self signed one):
sudo install -m 0644 <your-domain>.crt /etc/nginx/tls/krakend.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/tls/krakend.key
sudo nginx -t && sudo systemctl reload nginx
Step 11: Check the security posture
The certificate was generated on this instance and names its own addresses; the TLS key and the credentials file are readable only by root, and the JWT signing key only by root and the krakend group:
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
sudo stat -c '%a %U:%G %n' /etc/nginx/tls/krakend.key /etc/nginx/tls/krakend.crt /etc/krakend/jwk-cloudimg.json /etc/krakend/krakend.json /root/krakend-credentials.txt
subject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost
600 root:root /etc/nginx/tls/krakend.key
644 root:root /etc/nginx/tls/krakend.crt
640 root:krakend /etc/krakend/jwk-cloudimg.json
640 root:krakend /etc/krakend/krakend.json
600 root:root /root/krakend-credentials.txt
The client address comes from the connection. A request that claims to come from somewhere else in X-Forwarded-For, and names another host in X-Forwarded-Host, is logged by nginx and KrakenD with its real address, and the backend receives only that address and the configured host name:
H=$(sudo sed -n 's#^KRAKEND_URL=https://\(.*\)/$#\1#p' /root/krakend-credentials.txt)
P=$(hostname -I | awk '{print $1}')
curl -sk -o /dev/null --resolve "$H:443:$P" -H 'X-Forwarded-For: 203.0.113.9' -H 'X-Forwarded-Host: evil.example' "https://$H/v1/users/spoof-test"
sleep 1
sudo grep -h 'spoof-test' /var/log/nginx/access.log | tail -1 | cut -d' ' -f1,6-9
sudo journalctl -u krakend --no-pager -o cat | grep 'GIN.*spoof-test' | tail -1 | tr -s ' '
sudo grep -h 'users/spoof-test' /var/log/nginx/krakend-demo-backend.log | tail -1
<private-ip> "GET /v1/users/spoof-test HTTP/1.1" 500
[GIN] <time> | 500 | <duration> | <private-ip> | GET "/v1/users/spoof-test"
127.0.0.1 [<time>] "GET /users/spoof-test HTTP/1.1" 404 xff="<private-ip>" xfh="ec2-<public-ip-dashed>.compute-1.amazonaws.com" host="127.0.0.1" ua="KrakenD Version 3.0.2"
(The 500 is expected: the demo backend has no user called spoof-test.)
KrakenD runs as the krakend user with no capabilities and no core dumps, cannot reach the instance metadata service, does not report usage to KrakenD's servers, and does not start before first boot has finished or with a configuration that fails the schema check:
systemctl show krakend -p User -p NoNewPrivileges -p ProtectSystem -p ProtectHome -p CapabilityBoundingSet -p IPAddressDeny -p LimitCORE
systemctl cat krakend | grep -E '^(ExecStartPre|Environment)='
IPAddressDeny=168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
LimitCORE=0
CapabilityBoundingSet=
User=krakend
ProtectHome=yes
ProtectSystem=strict
NoNewPrivileges=yes
Environment=USAGE_DISABLE=1
ExecStartPre=+/usr/local/sbin/krakend-guard
ExecStartPre=/usr/local/bin/krakend check -c /etc/krakend/krakend.json -n
The metadata block covers every connection KrakenD makes, including calls to backends you configure: an endpoint whose backend is 169.254.169.254 cannot reach the metadata service from inside the krakend service. nginx and the first boot unit carry the same block.
SSH accepts keys only, with no root login and no X11 forwarding (/etc/ssh/sshd_config.d/00-cloudimg.conf):
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|x11forwarding) '
permitrootlogin no
passwordauthentication no
x11forwarding no
Step 12: Build provenance
KrakenD on this image was compiled by cloudimg from the unmodified upstream 3.0.2 source: the tagged go.mod and go.sum are used exactly as released (no module was changed). The build record, the go.mod and go.sum, and the govulncheck result ship with the image:
ls -l /usr/share/doc/krakend | awk 'NR>1{print $1,$5,$9}'
sha256sum /usr/local/bin/krakend
sed -n '/^source /,/^toolchain sha256/p' /usr/share/doc/krakend/BUILD-PROVENANCE.txt
grep '^Your code' /usr/share/doc/krakend/govulncheck-binary.txt
-rw-r--r-- 2256 BUILD-PROVENANCE.txt
-rw-r--r-- 11357 LICENSE
-rw-r--r-- 5594 README.md
-rw-r--r-- 13676 go.mod
-rw-r--r-- 65043 go.sum
-rw-r--r-- 301 govulncheck-binary.txt
46fc12a2ec8eb0f4239bee84c954b328c34094bddf7a6c6c6b5bfbf423a9de5b /usr/local/bin/krakend
source https://github.com/krakend/krakend-ce/archive/refs/tags/v3.0.2.tar.gz
source sha256 8f05f699e3161ec7396011f5eaf0cf4995f0f9f2ff9b925e044e1668d1bdbaac
tag commit 0ecf3bf041136d6a6a44e330ebce2c466485f8d0
go.mod / go.sum unchanged (sha256 afeea0f8d4267d5e1ae23aa17039e67c0c72965b6f18688f6cca2ba3a81c2fd6 / 9d321168d67c267a5472c3a6a6a81868d436c1a410e25f369cbbce654f5ec824)
schema https://raw.githubusercontent.com/krakend/krakend-schema/0dab76c651fc6be9e578d7cab8e79674e9840a79/v3.0/krakend.json (sha256 8429674ca1ef8d4519079d36099667653546af7300053adb7c4a0f9a7557d9e6; byte-identical to the schema in upstream's 3.0.2 binary)
toolchain go1.26.10 linux/amd64, official tarball https://go.dev/dl/go1.26.10.linux-amd64.tar.gz
toolchain sha256 ccfe7ae822d2c2f41f4fe7c956199967a4dac22d0ee0d2b2bfdb440aab3b20c5
Your code is affected by 0 vulnerabilities.
The build is reproducible: compiling the same source archive and flags (recorded in BUILD-PROVENANCE.txt) with Go 1.26.10 gives the same SHA-256. It is a static build (CGO_ENABLED=0). The Go toolchain and module cache were used on a temporary in memory filesystem and are not on the image.
Step 13: Logs
KrakenD writes its startup messages and one line per request (client address and HTTP method included) to the journal; nginx logs public requests to /var/log/nginx/access.log and the demo backend's requests to /var/log/nginx/krakend-demo-backend.log:
sudo journalctl -u krakend --no-pager -o cat | sed 's/\x1b\[[0-9;]*m//g' | grep -E 'Starting KrakenD|Listening on' | tail -2
[KRAKEND] <time> ▶ INFO Starting KrakenD v3.0.2
[KRAKEND] <time> ▶ INFO [SERVICE: Gin] Listening on port: 8080
KrakenD 3.0 also adds the HTTP method to its endpoint log lines (for example [ENDPOINT: GET /v1/users/:id]), so update any log parsing you carried over from KrakenD 2.x.
Step 14: Server components
| Component | Path |
|---|---|
| KrakenD binary | /usr/local/bin/krakend |
| Gateway configuration | /etc/krakend/krakend.json |
| JWT signing key (demo endpoint) | /etc/krakend/jwk-cloudimg.json |
| HTTPS front end | /etc/nginx/sites-available/cloudimg-krakend |
| Certificate and key | /etc/nginx/tls/ |
| Demo backend content | /usr/share/cloudimg-krakend/demo-backend/ |
| Service units | krakend.service, krakend-firstboot.service, nginx.service |
| Metadata block | /etc/systemd/system/krakend.service.d/50-cloudimg-imds-deny.conf (and nginx, first boot) |
| Helpers | krakend-set-hostname, krakend-demo-token, krakend-rotate-jwt-key, krakend-cve-2026-111943-check in /usr/local/sbin |
| Licence and build provenance | /usr/share/doc/krakend/ |
| Instance details | /root/krakend-credentials.txt (mode 0600) |
Step 15: Updating KrakenD
Ubuntu's security updates install automatically, including the ca-certificates trust store KrakenD uses. KrakenD is a single binary that is not managed by apt on this image. KrakenD publishes security fixes for the 3.x line of the Community Edition. To move to a newer KrakenD release, replace /usr/local/bin/krakend with a newer official release (or your own build), check your configuration with the new binary, and restart:
sudo /tmp/krakend-<version>/krakend check -c /etc/krakend/krakend.json -n
sudo install -m 0755 /tmp/krakend-<version>/krakend /usr/local/bin/krakend && sudo systemctl restart krakend
Read the KrakenD release notes and security advisories first, and run sudo krakend-cve-2026-111943-check after a replacement. cloudimg publishes updated versions of this image as new KrakenD releases ship.
Support
cloudimg provides 24/7 support for this image, the Ubuntu OS and deployment. Support for KrakenD itself is from the KrakenD community; commercial support is available from KrakenD. Contact cloudimg at support@cloudimg.co.uk.
KrakenD is a trademark of its respective owner. cloudimg is not affiliated with or endorsed by KrakenD or the KrakenD project.