Developer Tools AWS

Apache Camel Karavan 4.22.1 on AWS User Guide

| Product: Apache Camel Karavan 4.22.1 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and verifying Apache Camel Karavan 4.22.1 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg developer and API tools listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

Apache Camel Karavan is a low-code integration designer for Apache Camel. In a browser you draw routes from Camel's 300+ components and Enterprise Integration Patterns (timers, HTTP and REST, Kafka, JMS, files, databases, transformations, splitters, aggregators and more), edit REST APIs and OpenAPI definitions, keep projects in git with commit history, and run any integration with one click in developer mode, which starts it as its own container and streams its log back to the UI.

What is on the image:

  • Apache Camel Karavan 4.22.1 (ASF release) on an Eclipse Temurin 25 runtime image built by cloudimg, matching upstream fix 39054f656 for issue #1653. The official ghcr.io/apache/camel-karavan:4.22.1 image does not start (it ships a Java 21 base for an application compiled for Java 25). The image here runs the unmodified ASF karavan.jar (sha256 b1bb9f35bf541f7c595ce6878122788f5d38d7f48ecd425295c3cab70b5d6784) on eclipse-temurin:25-jre, with jackson-core and jackson-databind updated to the 2.21.7 security releases.
  • The Karavan developer-mode runtime (camel-karavan-devmode:4.22.1, Camel 4.22.1) with FreeMarker 2.3.35, Jolokia 2.6.2, Jackson 2.22.3 and the Red Hat UBI pcre2 and openssl security updates applied. Each integration you run starts from this image.
  • PostgreSQL 18.6 (postgres:18.6-alpine, pinned by digest) for Karavan's projects and sessions, created empty on your instance's first boot, and a local git repository for your projects
  • A rootless Docker engine that runs as the unprivileged karavan account. The root Docker daemon is disabled on this image.
  • nginx as the only network-facing service: HTTPS on port 443 with a self-signed certificate made on first boot, port 80 redirecting to HTTPS
  • Per-instance passwords for both built-in Karavan accounts, generated on first boot into a root-only file
  • karavan-set-hostname, a helper that serves Karavan under your own DNS name and re-issues the certificate for it

The Dockerfiles of both cloudimg-built images ship on the instance in /usr/share/doc/cloudimg-karavan/.

Default user: ubuntu · Architecture: x86_64 · Root volume: 20 GiB gp3

Security posture

  • No default login. Upstream Karavan seeds two accounts, admin and developer, with one published default password. On this image the admin password is generated on each instance's first boot, the developer account gets a different password of its own, and the PostgreSQL password is a third random value. None is in the image. A guard refuses to start Karavan with a short, world-readable or published-default password.
  • Two locks on the door. nginx asks for a per-instance username and password (an HTTP access gate) before any request reaches Karavan, except a static /healthz. Karavan then asks for its own sign-in. Karavan's API, its /public and /platform/internal endpoints and path tricks such as ;, %3B and %2F all stop at the gate with 401.
  • The Docker API Karavan holds is not root. Karavan needs a Docker API to run integrations. On this image that API belongs to a rootless Docker engine running as the unprivileged karavan account, with no password, no login shell and no sudo rights. A Karavan sign-in, or any flaw in Karavan, gives at most that account's privileges. At build time even a privileged container with the whole root filesystem mounted and host networking could not read /etc/shadow, the credentials file, the TLS key or the gate passwords, could not write to /etc or /root, did not see the instance's network and could not reach the instance metadata service.
  • Integrations cannot read instance metadata. Integrations call URLs you configure, so every path out of the engine is blocked from 169.254.169.254, 168.63.129.16 and fd00:ec2::254 by two independent walls: systemd IPAddressDeny on the engine's service (it holds the engine and every container process) and an iptables owner-match rule for the karavan account. Each build proves it from inside a running integration, and removes each wall in turn to show that the other one still holds.
  • Integrations stay private. Integration containers join Karavan's own network (never the host network), get no Docker socket, and publish their ports on 127.0.0.1 only. PostgreSQL sits on an internal network that integrations cannot reach and has no host port.
  • Only nginx faces the network. Karavan listens on 127.0.0.1:8080. nginx answers only for the configured hostname (any other Host header gets its connection closed), uses TLS 1.2 or 1.3, refuses cross-origin POST requests and WebSocket upgrades (403), strips CORS headers, rate-limits sign-in, keeps the session cookie Secure, HttpOnly and SameSite=Lax, replaces any client-supplied X-Forwarded-For, X-Real-IP or Forwarded header with the real peer address, and never passes the gate password on to Karavan.
  • The hostname comes from configuration, never from a request. First boot reads it from EC2 instance metadata (IMDSv2) and nginx hands Karavan that fixed name.
  • Least-privilege containers. Karavan runs with a read-only root filesystem, every Linux capability dropped and no-new-privileges. PostgreSQL runs as its own unprivileged user with every capability dropped.
  • No secret in a container environment. Karavan reads its passwords from a mounted file (/opt/karavan/secrets/karavan-secrets.properties) and PostgreSQL from POSTGRES_PASSWORD_FILE, so docker inspect never shows them.
  • IMDSv2 required (the AMI is registered with ImdsSupport v2.0), and per-instance identity: SSH host keys, the machine ID, the TLS certificate, the Docker engine ID and the git repository are created fresh on every instance.

Known library advisories. Each build scans the shipped images. These remain, have no fix in the same release line, and are not reachable on this image (the build asserts each condition): Netty's SNI routing bypass (CVE-2026-75595) needs Karavan to terminate TLS, and it does not (nginx does); Apache HttpComponents Core 5.3.6 (CVE-2026-54399, CVE-2026-54428) is used only by Karavan's Docker client on the local Unix socket; the Go runtime CVEs in PostgreSQL's gosu helper do not apply because PostgreSQL starts as its own user and gosu never runs. The developer-mode runtime is based on Red Hat UBI 9.8, which has open advisories with no released fix yet (expat, gnutls, python3, util-linux, X11 libraries, maven-resolver). Camel integrations do not use them, and they are updated when Red Hat ships fixes. Do not build FreeMarker templates from untrusted input.

Prerequisites

  1. An AWS account and permission to launch EC2 instances
  2. An EC2 key pair in the Region you launch in
  3. Outbound internet access from the instance: Camel downloads the components a route uses from Maven Central the first time it runs

Recommended instance type: m5.large. Karavan (a JVM capped at a 1 GiB heap), PostgreSQL and one or two running integrations (each its own JVM, about 1.5 GiB) fit in 8 GiB of memory. Choose m5.xlarge if you run several integrations at the same time.

Connecting to your instance

Version Operating system SSH user
Apache Camel Karavan 4.22.1 on Ubuntu 24.04 Ubuntu 24.04 LTS ubuntu

Step 1: Launch the instance

Option A: AWS Marketplace console

  1. Open the cloudimg Hardened Node.js & Developer and API Tools 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 Apache Camel Karavan 4.22.1 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: the listing's default group opens SSH (22), HTTP (80) and HTTPS (443). Restrict all three to your own and your team's addresses.
  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. It creates a security group that allows SSH from your management address and HTTPS from your team's network, then launches the instance. 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 karavan \
  --description "Apache Camel Karavan" --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 203.0.113.0/24
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr 203.0.113.0/24
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=karavan}]'

You do not need --metadata-options: the AMI already makes IMDSv2 required. If you want the address to survive a stop and start, associate an Elastic IP.

Step 2: Connect and find your login

Connect as ubuntu with the key pair you chose:

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

First boot finishes within two or three minutes of launch. It sets the hostname Karavan is served as (the instance's public DNS name when it has one), creates the TLS certificate, generates the passwords, creates the local git repository, starts PostgreSQL and Karavan, proves both accounts sign in with their own passwords, loads a demo integration and writes /root/karavan-credentials.txt (mode 0600, root). Only then does it open nginx. These are the entries in that file (the passwords are not shown here):

sudo grep -E '^KARAVAN_(URL|USERNAME|DEVELOPER_USERNAME)=' /root/karavan-credentials.txt
sudo grep -oE '^[A-Z_]+=' /root/karavan-credentials.txt
sudo stat -c '%a %U:%G' /root/karavan-credentials.txt
KARAVAN_URL=https://ec2-3-95-166-62.compute-1.amazonaws.com/
KARAVAN_USERNAME=admin
KARAVAN_DEVELOPER_USERNAME=developer
KARAVAN_URL=
KARAVAN_USERNAME=
KARAVAN_PASSWORD=
KARAVAN_DEVELOPER_USERNAME=
KARAVAN_DEVELOPER_PASSWORD=
600 root:root
Value What it is for
KARAVAN_URL The address of this instance's Karavan
KARAVAN_USERNAME / KARAVAN_PASSWORD The admin account (all roles), generated on this instance. It opens both the access gate and Karavan's sign-in.
KARAVAN_DEVELOPER_USERNAME / KARAVAN_DEVELOPER_PASSWORD The built-in developer account (developer role) with its own password, for both the gate and Karavan

To read the values, run sudo cat /root/karavan-credentials.txt in your own session and store them in your password manager.

Step 3: Confirm Karavan is running

The metadata wall, the rootless engine, the first-boot units, Karavan and nginx are active. Only sshd and nginx listen beyond loopback: Karavan is on 127.0.0.1:8080, integrations you run publish on 127.0.0.1 too, and PostgreSQL's port exists only inside its internal container network. The engine belongs to the karavan account, so its containers are listed with sudo -u karavan:

systemctl is-active cloudimg-karavan-imds-deny.service karavan-docker.service karavan-firstboot.service karavan.service karavan-postboot.service nginx.service
kd() { (cd / && sudo -u karavan env HOME=/var/lib/karavan DOCKER_HOST=unix:///run/karavan-docker/docker.sock docker "$@"); }
kd ps --format '{{.Names}} {{.Image}} {{.Ports}}'
sudo ss -Htlnp | awk '{print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort -u
curl -sk https://127.0.0.1/healthz
active
active
active
active
active
active
karavan cloudimg/camel-karavan:4.22.1-temurin25 127.0.0.1:8080->8080/tcp
karavan-postgres postgres:18.6-alpine 5432/tcp
0.0.0.0:22 users:(("sshd"),("systemd"))
0.0.0.0:443 users:(("nginx"),("nginx"),("nginx"))
0.0.0.0:80 users:(("nginx"),("nginx"),("nginx"))
127.0.0.1:8080 users:(("rootlesskit"))
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"))
[::]:80 users:(("nginx"),("nginx"),("nginx"))
ok

/healthz is answered by nginx itself and reveals nothing, so it is safe to use as a load balancer health check.

Step 4: Prove the gate, the sign-in and the web defaults

Signed-out requests stop at the access gate, including the path variants that bypass path-based authorization in some web frameworks. The gate alone gives no access to Karavan's API: Karavan's own session is needed too. A cross-origin POST is refused, an unknown Host header gets no answer, and plain HTTP redirects to the configured HTTPS name. The last line signs in to Karavan with this instance's admin password and reads its version:

H=$(sudo sed -n 's/^set \$app_host "\(.*\)";$/\1/p' /etc/nginx/karavan-host.conf)
P=$(sudo grep '^KARAVAN_PASSWORD=' /root/karavan-credentials.txt | cut -d= -f2-)
R=(--resolve "$H:443:127.0.0.1")
for path in / "/ui/project" "/ui/project;x" "/ui/project%3Bx" "/ui%2Fproject"; do
  curl -sk "${R[@]}" --path-as-is -o /dev/null -w "anonymous $path -> %{http_code}\n" "https://$H$path"
done
curl -sk "${R[@]}" -o /dev/null -w 'gate, wrong password -> %{http_code}\n' -K <(printf 'user = "admin:not-the-password"\n') "https://$H/"
curl -sk "${R[@]}" -o /dev/null -w 'gate, your password -> %{http_code}\n' -K <(printf 'user = "admin:%s"\n' "$P") "https://$H/"
curl -sk "${R[@]}" -o /dev/null -w 'API without a Karavan session -> %{http_code}\n' -K <(printf 'user = "admin:%s"\n' "$P") "https://$H/ui/project"
curl -sk "${R[@]}" -o /dev/null -w 'cross-origin POST -> %{http_code}\n' -K <(printf 'user = "admin:%s"\n' "$P") -X POST \
  -H 'Origin: https://evil.example' -H 'Content-Type: application/json' -d '{}' "https://$H/ui/auth/login"
curl -sk -o /dev/null -w 'unknown Host -> %{http_code}\n' -H 'Host: evil.example' https://127.0.0.1/ || true
curl -s -o /dev/null -w 'http -> %{http_code} %{redirect_url}\n' -H "Host: $H" http://127.0.0.1/
J=$(mktemp); curl -sk "${R[@]}" -o /dev/null -c "$J" -K <(printf 'user = "admin:%s"\n' "$P") -H "Origin: https://$H" \
  -H 'Content-Type: application/json' --data-binary @<(printf '{"username":"admin","password":"%s"}' "$P") "https://$H/ui/auth/login"
curl -sk "${R[@]}" -b "$J" -K <(printf 'user = "admin:%s"\n' "$P") "https://$H/ui/configuration" | jq -c '{title, version, infrastructure}'
rm -f "$J"
anonymous / -> 401
anonymous /ui/project -> 401
anonymous /ui/project;x -> 401
anonymous /ui/project%3Bx -> 401
anonymous /ui%2Fproject -> 401
gate, wrong password -> 401
gate, your password -> 200
API without a Karavan session -> 401
cross-origin POST -> 403
unknown Host -> 000
http -> 301 https://ec2-3-95-166-62.compute-1.amazonaws.com/
{"title":"Apache Camel Karavan","version":"4.22.1","infrastructure":"docker"}

The password reaches curl through files on file descriptors (-K <(...) and --data-binary @<(...)), so it never appears on a command line or in your shell history.

Step 5: Sign in to Karavan

Browse to KARAVAN_URL (https://<public-dns-name>/). The certificate is self-signed, so your browser warns once; accept it for this host, or install your own certificate (Step 9). Your browser first asks for the access gate username and password: enter admin and KARAVAN_PASSWORD. Karavan's sign-in page then opens; enter the same username and password and choose Access Platform:

The Apache Camel Karavan 4.22.1 sign-in page with username and password fields and the Access Platform button, shown after the per-instance access gate

The Integrations page lists your projects. A new instance has one, Demo Integration (demo), with two routes, committed to the instance's local git repository:

The Karavan Integrations page listing the demo project with two routes, committed and saved, and the Create Integration and Import project buttons

Step 6: Design an integration

Open demo, choose Source and select heartbeat.camel.yaml. The Designer shows the route as a flow: a Timer that fires every 10 seconds, a Set Body step and a Log step. Select a step to edit its properties on the right; drag components and patterns from the palette to extend the route. Code shows the same route as Camel YAML and Diff shows your changes since the last commit.

The Karavan route designer showing the heartbeat route with Timer, Set Body and Log Data steps, and the Timer properties panel with the timer name heartbeat and a 1000 ms delay

To create your own project choose Create Integration on the Integrations page. Under Source, Commits shows the git history of the project and Push commits your changes to the local repository.

Step 7: Run an integration in developer mode

In the project, open Containers and choose Run. Karavan starts the integration as its own container from the developer-mode runtime image, on the rootless engine:

The Karavan Containers tab for the demo project showing the demo developer-mode container running from the cloudimg devmode image with its CPU and memory use, and the Run, Stop and Delete buttons

Log streams the container's output. The demo's two routes log a heartbeat every 10 seconds and a greeting every 30 seconds:

The Karavan Log tab streaming the demo integration's log, with the heartbeat route logging cloudimg Karavan demo heartbeat every 10 seconds and the greeting route logging Hello from Apache Camel Karavan on cloudimg

The same thing from the command line, through the access gate and Karavan's API:

H=$(sudo sed -n 's/^set \$app_host "\(.*\)";$/\1/p' /etc/nginx/karavan-host.conf)
P=$(sudo grep '^KARAVAN_PASSWORD=' /root/karavan-credentials.txt | cut -d= -f2-)
R=(--resolve "$H:443:127.0.0.1"); J=$(mktemp)
G() { curl -sk "${R[@]}" -K <(printf 'user = "admin:%s"\n' "$P") -b "$J" -c "$J" -H "Origin: https://$H" "$@"; }
G -o /dev/null -H 'Content-Type: application/json' --data-binary @<(printf '{"username":"admin","password":"%s"}' "$P") "https://$H/ui/auth/login"
CSRF=$(awk '$6=="csrf"{print $7}' "$J")
G -o /dev/null -w 'run demo in developer mode -> %{http_code}\n' -H "X-CSRF-Token: $CSRF" "https://$H/ui/devmode/run/demo"
kd() { (cd / && sudo -u karavan env HOME=/var/lib/karavan DOCKER_HOST=unix:///run/karavan-docker/docker.sock docker "$@"); }
for i in $(seq 1 30); do L=$(kd logs demo 2>&1 || true); [[ "$L" == *"demo heartbeat"* ]] && break; sleep 5; done
kd ps --filter name=^demo$ --format '{{.Names}} {{.Image}} {{.Ports}}'
grep -m1 -o 'Body: cloudimg Karavan demo heartbeat' <<<"$L"
rm -f "$J"
run demo in developer mode -> 200
demo cloudimg/camel-karavan-devmode:4.22.1-cloudimg1 8443/tcp, 127.0.0.1:8081->8080/tcp
Body: cloudimg Karavan demo heartbeat

The first run of a route downloads the Camel components it uses from Maven Central, so it takes a little longer. An integration's HTTP port (here 8081) is bound to 127.0.0.1 only; to reach it from elsewhere, add an nginx location for it or use an SSH tunnel (ssh -L 8081:127.0.0.1:8081 ubuntu@<public-ip>). Docker reports developer-mode containers as unhealthy after a few minutes because Karavan 4.22.1's container health check probes an older management port; the integration keeps running and Karavan shows it as running.

Step 8: Check the security controls

The engine runs as karavan in rootless mode and the root Docker daemon is masked. From inside the running demo integration the internet is reachable but the instance metadata service is not, and both metadata walls are in place:

kd() { (cd / && sudo -u karavan env HOME=/var/lib/karavan DOCKER_HOST=unix:///run/karavan-docker/docker.sock docker "$@"); }
echo "engine runs as: $(ps -o user= -p "$(systemctl show -p MainPID --value karavan-docker.service)")"
kd info --format '{{json .SecurityOptions}}'
systemctl is-enabled docker.service docker.socket containerd.service
kd exec demo curl -s -m 10 -o /dev/null -w 'integration -> internet: %{http_code}\n' https://checkip.amazonaws.com/
kd exec demo curl -s -m 6 -o /dev/null -w 'integration -> instance metadata: %{http_code}\n' -X PUT \
  -H 'X-aws-ec2-metadata-token-ttl-seconds: 60' http://169.254.169.254/latest/api/token || true
systemctl show -p IPAddressDeny karavan-docker.service
sudo iptables -S OUTPUT | grep -c 'uid-owner'
engine runs as: karavan
["name=seccomp,profile=builtin","name=rootless","name=cgroupns"]
masked
masked
masked
integration -> internet: 200
integration -> instance metadata: 000
IPAddressDeny=fd00:ec2::254/128 168.63.129.16/32 169.254.169.254/32
4

000 means the connection never got an answer. If an integration needs AWS credentials, give it an access key through its own configuration (or a secrets service) rather than the instance role: the instance role is deliberately out of reach.

Step 9: Serve Karavan under your own DNS name

Point a DNS record at the instance (an Elastic IP keeps the address stable), then set the name. The helper re-issues the self-signed certificate for it, updates nginx and the Origin guard, and updates KARAVAN_URL:

sudo karavan-set-hostname <your-domain>

To use a certificate from a public CA, replace /etc/ssl/karavan/karavan.crt and /etc/ssl/karavan/karavan.key (key mode 0600, root) with your own and reload nginx (sudo systemctl reload nginx). Without a pinned name, the instance follows its public DNS name across a stop and start.

Step 10: Build images and deploy (optional)

Developer mode works out of the box. Karavan's Build and Deploy actions package an integration as a container image, push it to a registry and run it from there; they need a git remote and a container registry that you provide. Edit /opt/karavan/docker-compose.yml: set KARAVAN_GIT_REPOSITORY to your remote (with KARAVAN_GIT_USERNAME and KARAVAN_GIT_PASSWORD for an HTTPS remote) and add KARAVAN_CONTAINER_IMAGE_REGISTRY, KARAVAN_CONTAINER_IMAGE_REGISTRY_USERNAME and KARAVAN_CONTAINER_IMAGE_REGISTRY_PASSWORD. Then run sudo systemctl restart karavan to apply it. Keep these values out of shared files: the compose file is world-readable, so a production setup puts them in /opt/karavan/secrets/karavan-secrets.properties as karavan.git.password= and karavan.container-image.registry-password= lines instead.

Step 11: Change the passwords

In Karavan, open your profile from the account menu and use Change password for the signed-in account (as admin you can also set other accounts' passwords on the access management page). Then set the same new password for that account at the access gate (it asks for the password twice and stores only a bcrypt hash):

sudo htpasswd -B /etc/nginx/karavan.htpasswd admin   # enter <new-password> twice

Update /root/karavan-credentials.txt to match. The value in /opt/karavan/secrets/karavan-secrets.properties only seeds the admin account on the first start of an empty database; changing it later does not change an existing password.

Maintenance

  • Operating system: security updates install automatically (unattended-upgrades). Docker CE comes from Docker's apt repository: sudo apt-get update && sudo apt-get install --only-upgrade docker-ce docker-ce-cli docker-ce-rootless-extras containerd.io docker-compose-plugin, then sudo systemctl restart karavan-docker karavan.
  • Karavan and its runtime: cloudimg publishes a new version in the listing when Karavan, its runtime or PostgreSQL needs an update. Back up first.
  • Backups: your projects are in PostgreSQL (the karavan-pgdata volume under /var/lib/karavan/.local/share/docker/volumes/) and in the git repository at /var/lib/karavan/git/karavan.git. Snapshot the EBS volume, or stop karavan.service and copy both.

Troubleshooting

  • The browser keeps asking for a password: the access gate and Karavan's sign-in are separate; both take the same username and password from the credentials file.
  • "Max failed attempts reached": Karavan locks an account after six wrong passwords in a row, and a correct password no longer opens it. As admin you can reset the developer account's password on the access management page. To unlock admin itself, reset its counter in the database and restart Karavan:

text kd exec -i -u 70 karavan-postgres psql -U karavan -d karavan -c \ "UPDATE access_state SET data = jsonb_set(data, '{failedAttempts}', '0') WHERE key = 'AccessPassword:dev:admin';" sudo systemctl restart karavan * A route fails to start on its first run: the instance must reach Maven Central (repo1.maven.org) to download Camel components. Check outbound HTTPS in your security group and network ACLs. * Logs: journalctl -u karavan-firstboot -u karavan -u karavan-postboot -u karavan-docker, and kd logs karavan (with the kd function from Step 3).

Support

cloudimg provides support for this image by email at support@cloudimg.co.uk. Apache, Apache Camel, Camel and Karavan are trademarks of The Apache Software Foundation. cloudimg is not affiliated with, endorsed by or sponsored by The Apache Software Foundation. Apache Camel Karavan is licensed under the Apache License 2.0; Eclipse Temurin under the GNU General Public License, version 2, with the Classpath Exception. The licence texts and cloudimg's notes are on the instance in /usr/share/doc/cloudimg-karavan/.