Quickstart¶
Goal: in ~5 minutes, get Aegis-KMS running on your machine and use it to sign + verify a message. Step 0 → Step 9, every command runnable, every output shown.
For a deeper hands-on tour covering every operation (encrypt, decrypt, wrap, unwrap, rotate, compromise, audit log, metrics, traces, CLI, JWT, AWS KMS), see the full walkthrough (~20 minutes).
Step 0 — Prerequisites¶
You need Docker. That's it. (No JDK, no sbt — we use the published Docker image.)
```bash docker --version
→ Docker version 27.x.x or newer¶
```
Optional but recommended:
bash
curl --version | head -1 # any recent curl
jq --version # for pretty-printing JSON
If Docker isn't installed: https://docs.docker.com/get-docker/.
Step 1 — Get the repo¶
We use the Docker Compose file shipped in the repo (it brings up Postgres alongside the server). You don't need to build anything from source.
bash
git clone https://github.com/sharma-bhaskar/aegis-kms.git
cd aegis-kms
Step 2 — Boot the server¶
Aegis requires you to set the Postgres password explicitly. There is no insecure default — this is a deliberate security choice.
bash
export POSTGRES_PASSWORD="$(openssl rand -base64 24)"
docker compose -f deploy/docker/docker-compose.yml up -d
Expected output:
[+] Running 3/3
✔ Network aegis-kms_default Created
✔ Container aegis-postgres Started
✔ Container aegis-server Started
Watch the logs in another terminal so you can see audit events as you make requests:
bash
docker compose -f deploy/docker/docker-compose.yml logs -f aegis-server
You should see Boot complete after ~2 seconds.
Step 3 — Verify the server is up¶
The fastest check: open the Swagger UI in your browser.
```bash open http://localhost:8080/docs/
(Linux: xdg-open; or paste in a browser tab)¶
```
You should see Swagger UI with every Aegis endpoint listed: POST /v1/keys,
POST /v1/keys/{id}/sign, POST /v1/keys/{id}/encrypt, etc.
If the page doesn't load, check the log tail from Step 2 — most failures are
configuration issues (e.g. POSTGRES_PASSWORD not set in the shell).
Step 4 — Set shell variables¶
You'll use these in every step.
bash
export AEGIS=http://localhost:8080
export USER_HEADER="X-Aegis-User: alice"
X-Aegis-User: alice is the dev-mode auth header — every request you make will be
attributed to the principal alice. Production deployments use JWT bearer auth (covered in
the full walkthrough).
Step 5 — Create your first key¶
Create a 256-bit AES key named quickstart-demo:
bash
RESPONSE=$(curl -s -X POST "$AEGIS/v1/keys" \
-H "$USER_HEADER" \
-H "Content-Type: application/json" \
-d '{
"spec": {
"name": "quickstart-demo",
"algorithm": "AES",
"sizeBits": 256,
"objectType": "SymmetricKey"
}
}')
echo "$RESPONSE" | jq
Expected output:
json
{
"id": "8a3f1e25-6b0a-4f5d-8e92-1c4f6a83b2d9",
"spec": {
"name": "quickstart-demo",
"algorithm": "AES",
"sizeBits": 256,
"objectType": "SymmetricKey"
},
"state": "PreActive",
"currentVersion": 1,
"createdAt": "2026-05-09T01:23:45Z"
}
The key is in state PreActive. By design, you can't sign or encrypt yet — a key
starts pre-active so a policy engine, auditor, or human operator has a chance to review
before it goes live. We'll activate it in Step 6.
Capture the id for the rest of the walkthrough:
bash
export KEY_ID=$(echo "$RESPONSE" | jq -r '.id')
echo "KEY_ID=$KEY_ID"
Step 6 — Activate the key¶
bash
curl -s -X POST "$AEGIS/v1/keys/$KEY_ID/activate" -H "$USER_HEADER" | jq
Expected output:
json
{
"id": "8a3f1e25-...",
"state": "Active",
"activatedAt": "2026-05-09T01:24:01Z"
}
The key is now usable for crypto operations.
Step 7 — Sign a message¶
We'll sign the message "hello" with RSA-PSS-SHA-256.
```bash MSG_B64=$(echo -n 'hello' | base64)
SIG_RESPONSE=$(curl -s -X POST "$AEGIS/v1/keys/$KEY_ID/sign" \ -H "$USER_HEADER" -H "Content-Type: application/json" \ -d "{\"messageBase64\":\"$MSG_B64\",\"algorithm\":\"RsaPssSha256\"}") echo "$SIG_RESPONSE" | jq ```
Expected output:
json
{
"signatureBase64": "kY3Z0bH9eXqPQ8a7cF6V4t5RmN1pL2rS3sO9wJxK8uM=",
"algorithm": "RsaPssSha256",
"keyVersion": 1
}
Capture the signature:
bash
export SIG=$(echo "$SIG_RESPONSE" | jq -r '.signatureBase64')
Look at your log-tail terminal — you should see a fresh audit row:
{"ts":"...","actor":"alice","actorKind":"Human","op":"Sign","keyId":"...","outcome":"Success","keyVersion":1,"alg":"RsaPssSha256"}
Every state change and every crypto operation generates an audit row.
Step 8 — Verify the signature¶
bash
curl -s -X POST "$AEGIS/v1/keys/$KEY_ID/verify" \
-H "$USER_HEADER" -H "Content-Type: application/json" \
-d "{\"messageBase64\":\"$MSG_B64\",\"signatureBase64\":\"$SIG\",\"algorithm\":\"RsaPssSha256\"}" \
| jq
Expected output:
json
{
"valid": true,
"algorithm": "RsaPssSha256"
}
Try a tampered message — change 'hello' to 'helloo':
```bash TAMPERED_B64=$(echo -n 'helloo' | base64)
curl -s -X POST "$AEGIS/v1/keys/$KEY_ID/verify" \ -H "$USER_HEADER" -H "Content-Type: application/json" \ -d "{\"messageBase64\":\"$TAMPERED_B64\",\"signatureBase64\":\"$SIG\",\"algorithm\":\"RsaPssSha256\"}" \ | jq ```
Expected output (HTTP status is still 200 — valid: false is a successful
verification result, not an error):
json
{
"valid": false,
"algorithm": "RsaPssSha256"
}
That's the cryptographic guarantee working: even a one-byte change to the message produces
valid: false.
Step 9 — Stop the server¶
bash
docker compose -f deploy/docker/docker-compose.yml down
This stops both containers. Add -v to also remove the Postgres volume (deletes all keys):
bash
docker compose -f deploy/docker/docker-compose.yml down -v
What you just did¶
In ~5 minutes you:
- Booted Aegis-KMS with a Postgres event journal
- Created a key (in safe
PreActivestate by default) - Activated the key (explicit transition)
- Signed a message with RSA-PSS-SHA-256
- Verified the signature (and saw the tamper detection work)
- Watched audit rows land on stdout in real time
Every operation was attributed to alice (the principal you passed via X-Aegis-User),
recorded in the audit journal, exposed as a Prometheus metric on /metrics, and traced as
an OpenTelemetry span (when an OTel exporter is wired in).
Where to next¶
-
Want the full hands-on tour?
The Usage Walkthrough is the same flow extended to 20 steps: encrypt + decrypt with EncryptionContext, wrap + unwrap a DEK, rotate, mark as compromised, inspect the audit log + Prometheus + Jaeger, switch to JWT auth, and configure AWS KMS as the Root of Trust.
-
Want to understand how it works?
Architecture covers the decorator stack, the actor model, the two-tier module split, and the request lifecycle end-to-end.
-
Want to embed Aegis in your JVM app?
Library jars on Maven Central are coming in v0.1.2. For now, see Developer Guide → Quickstart to
sbt publishLocalfrom source. -
Want to compare to AWS KMS / Vault / OpenBao?
Comparison — including a clear "do not pick Aegis if…" section.