Variables
PRIMARY_API="https://$(hostname -f)/univention/provisioning"
BACKUP_API="https://backup.example.test/univention/provisioning"
#Subscription
SUB_NAME="curl-ha-test"
SUB_PASSWORD="ein-langes-test-passwort"
# Sequenznummer ist pro Queue
PRIMARY_SEQ="$(printf '%s\n' "$PRIMARY_MSG" | jq -r '.sequence_number')"
BACKUP_SEQ="$(printf '%s\n' "$BACKUP_MSG" | jq -r '.sequence_number')"
Passwords:
The Admin-passwords are stored on the respective UCS-System:
PRIMARY_ADMIN_PASSWORD="$( jq -r '.PROVISIONING_API_ADMIN_PASSWORD' /etc/provisioning-secrets.json)"
EVENTS_PASSWORD="$(jq -r '.EVENTS_PASSWORD_UDM' /etc/provisioning-secrets.json)"
NATS_PASSWORD="$( jq -r '.NATS_PASSWORD' /etc/provisioning-secrets.json)"
1. check APIs
curl -sS -o /dev/null -w 'Primary: HTTP %{http_code}\n' \
"$PRIMARY_API/openapi.json"
2. put a subscription
For the first test, we’ll use our own topic and disable prefill:
SUBSCRIPTION_JSON='{
"name": "curl-ha-test",
"realms_topics": [
{"realm": "test", "topic": "curl"}
],
"request_prefill": false,
"password": "ein-langes-test-passwort"
}'
curl -sS -o /dev/null -w 'Primary create: HTTP %{http_code}\n' \
-u "admin:${PRIMARY_ADMIN_PASSWORD}" \
-H 'Content-Type: application/json' \
--data "$SUBSCRIPTION_JSON" \
"$PRIMARY_API/v1/subscriptions"
3. check the subscription
curl -sS \
-u "${SUB_NAME}:${SUB_PASSWORD}" \
"$PRIMARY_API/v1/subscriptions/$SUB_NAME" | jq
Test:
curl -sS \
-w '\nHTTP %{http_code}\n' \
-u "admin:${PRIMARY_ADMIN_PASSWORD}" \
"$PRIMARY_API/v1/subscriptions"
4. Testevent am Primary erzeugen
Send a uniquely identified event to the primary:
MARKER="curl-ha-$(date +%s)"
TS="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
curl -sS -o /dev/null -w 'Publish: HTTP %{http_code}\n' \
-u "udm:${EVENTS_PASSWORD}" \
-H 'Content-Type: application/json' \
--data "{
\"publisher_name\": \"consumer_client_test\",
\"ts\": \"$TS\",
\"realm\": \"test\",
\"topic\": \"curl\",
\"body\": {
\"old\": {},
\"new\": {
\"objectType\": \"test/curl\",
\"marker\": \"$MARKER\"
}
}
}" \
"$PRIMARY_API/v1/messages"
Expected is a HTTP 202.
5. Retrieve a message from the server
PRIMARY_MSG="$(
curl -sS --max-time 15 \
-u "${SUB_NAME}:${SUB_PASSWORD}" \
"$PRIMARY_API/v1/subscriptions/$SUB_NAME/messages/next?timeout=10"
)"
printf '%s\n' "$PRIMARY_MSG" | jq
A response of zero means that no message arrived within the long-poll time window. In that case, poll again.
6. Confirm Messages
curl -sS -o /dev/null -w 'Primary ACK: HTTP %{http_code}\n' \
-X PATCH \
-u "${SUB_NAME}:${SUB_PASSWORD}" \
-H 'Content-Type: application/json' \
--data '{"status":"ok"}' \
"$PRIMARY_API/v1/subscriptions/$SUB_NAME/messages/$PRIMARY_SEQ/status"
NATs
Health test
curl -sS http://127.0.0.1:8222/healthz
JetStream-Information:
curl -sS 'http://127.0.0.1:8222/jsz?streams=true&consumers=true' | jq
show connections:
curl -sS http://127.0.0.1:8222/connz | jq
show subscriptions on NATS-Protokolllayer:
curl -sS http://127.0.0.1:8222/subsz | jq
The NATs container has no shell, so to check nats, we canuse a nats-box:
NATS_PASSWORD="$(
jq -r '.NATS_PASSWORD' /etc/provisioning-secrets.json
)"
docker run --rm -it \
--network nubus-provisioning \
-e NATS_URL='nats://nats:4222' \
-e NATS_USER='api' \
-e NATS_PASSWORD="$NATS_PASSWORD" \
natsio/nats-box:latest
in this container you can use:
nats stream ls
╭───────────────────────────────────────────────────────────────────────────────────────────────╮
│ Streams │
├─────────────────────────┬─────────────┬─────────────────────┬──────────┬───────┬──────────────┤
│ Name │ Description │ Created │ Messages │ Size │ Last Message │
├─────────────────────────┼─────────────┼─────────────────────┼──────────┼───────┼──────────────┤
│ stream:incoming │ │ 2026-08-25 12:02:27 │ 0 │ 0 B │ 32m17s │
│ stream:ldap-producer │ │ 2026-08-25 12:02:24 │ 0 │ 0 B │ 32m17s │
│ stream:prefill │ │ 2026-08-25 12:02:27 │ 0 │ 0 B │ never │
│ stream:prefill-failures │ │ 2026-08-25 12:02:27 │ 0 │ 0 B │ never │
│ stream:curl-ha-test │ │ 2026-08-25 12:29:11 │ 1 │ 306 B │ 1h58m42s │
╰─────────────────────────┴─────────────┴─────────────────────┴──────────┴───────┴──────────────╯
fa91a3c3fa9b:~# nats stream info
? Select a Stream stream:curl-ha-test
Information for Stream stream:curl-ha-test created 2026-08-25 12:29:11
Subjects: curl-ha-test.main, curl-ha-test.prefill
Replicas: 1
Storage: File
Options:
Retention: Limits
Acknowledgments: true
Discard Policy: Old
Duplicate Window: 2m0s
Allows Atomic Batch Publish: false
Allows Fast Batch Publish: false
Allows Counters: false
Allows Msg Delete: true
Allows Per-Message TTL: false
Allows Purge: true
Allows Schedules: false
Allows Rollups: false
Limits:
Maximum Messages: unlimited
Maximum Per Subject: unlimited
Maximum Bytes: unlimited
Maximum Age: unlimited
Maximum Message Size: unlimited
Maximum Consumers: unlimited
State:
Host Version: 2.14.3
Required API Level: 0 hosted at level 4
Messages: 1
Bytes: 306 B
First Sequence: 1 @ 2026-08-25 12:33:40
Last Sequence: 1 @ 2026-08-25 12:33:40
Active Consumers: 1
Number of Subjects: 1
fa91a3c3fa9b:~# nats kv get SUBSCRIPTIONS curl-ha-test
SUBSCRIPTIONS > curl-ha-test revision: 1 created @ 2026-08-25 12:29:11
Showing first 120 bytes of 137, use --raw for full data
{"name": "curl-ha-test", "realms_topics": [{"realm": "test", "topic": "curl"}], "request_prefill": false, "prefill_queue