Skip to content

Instantly share code, notes, and snippets.

@matejaputic
Created October 5, 2025 12:54
Show Gist options
  • Select an option

  • Save matejaputic/413315b3ec0d5cbc0ec2f29ec8266c89 to your computer and use it in GitHub Desktop.

Select an option

Save matejaputic/413315b3ec0d5cbc0ec2f29ec8266c89 to your computer and use it in GitHub Desktop.
Headless Siderolabs Omni

I've been trying to figure out how to use Omni to provision a Talos cluster completely headless and I've learned a couple things:

Just for some context, I've got a local docker compose stack going with Keycloak 26.4 and Omni 1.2.1. I realize this isn't anywhere near prod-worthy but I'm still just poking around.

First, to make it headless, the default SAML flow isn't going to work, so you have to use a service account with OIDC. I needed a minimal OIDC client in Keycloak to make this work. (I just set the client ID to omni and root and home URLs to https://omni.example.com.)

Second, you can pass a --create-initial-service-account flag to the Omni start command, it will do that for you on first run.

Third, if you expose the /_out directory from the Omni container to the host, you can get access to initial-service-account-key.

Finally, set OMNI_ENDPOINT and OMNI_SERVICE_ACCOUNT_KEY like so:

export OMNI_ENDPOINT=https://omni.example.com:443
export OMNI_SERVICE_ACCOUNT_KEY=$(cat initial-service-account-key)

And now to verify, run omnictl get rd, and you should see a list of resource definitions

name: omni
services:
keycloak:
container_name: keycloak
image: quay.io/keycloak/keycloak
command: start
network_mode: "host"
cap_add:
- NET_ADMIN
volumes:
- ${TLS_CERT}:/etc/x509/https/tls.crt
- ${TLS_KEY}:/etc/x509/https/tls.key
- ./keycloak/data:/opt/keycloak/data
- ./keycloak/data/import:/opt/keycloak/data/import
environment:
- KEYCLOAK_ADMIN
- KEYCLOAK_ADMIN_PASSWORD
- KC_HOSTNAME=${KEYCLOAK_HOSTNAME}
- KC_HTTPS_CERTIFICATE_FILE=/etc/x509/https/tls.crt
- KC_HTTPS_CERTIFICATE_KEY_FILE=/etc/x509/https/tls.key
- KC_HEALTH_ENABLED=true
healthcheck:
test:
[
"CMD-SHELL",
"exec 3<>/dev/tcp/127.0.0.1/9000; echo -e 'GET /health/ready HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n' >&3; grep -q 'HTTP/1.1 200' <&3 && echo 'UP' || echo 'DOWN'",
]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
omni:
container_name: omni
image: "ghcr.io/siderolabs/omni:${OMNI_IMG_TAG}"
depends_on:
keycloak:
condition: service_healthy
devices:
- /dev/net/tun
volumes:
- ${PWD}/omni/:/_out
- ${ETCD_ENCRYPTION_KEY}:/omni.asc:ro
- ${TLS_CERT}:/tls.crt:ro
- ${TLS_KEY}:/tls.key:ro
network_mode: "host"
cap_add:
- NET_ADMIN
command: >
--account-id=${OMNI_ACCOUNT_UUID}
--name=${NAME}
--cert=/tls.crt
--key=/tls.key
--machine-api-cert=/tls.crt
--machine-api-key=/tls.key
--private-key-source='file:///omni.asc'
--event-sink-port=${EVENT_SINK_PORT}
--bind-addr=${BIND_ADDR}
--machine-api-bind-addr=${MACHINE_API_BIND_ADDR}
--k8s-proxy-bind-addr=${K8S_PROXY_BIND_ADDR}
--advertised-api-url=${ADVERTISED_API_URL}
--advertised-kubernetes-proxy-url=${ADVERTISED_K8S_PROXY_URL}
--siderolink-api-advertised-url=${SIDEROLINK_ADVERTISED_API_URL}
--siderolink-wireguard-advertised-addr=${SIDEROLINK_WIREGUARD_ADVERTISED_ADDR}
--auth-oidc-enabled=true
--auth-oidc-provider-url=https://${KEYCLOAK_HOSTNAME}:8443/realms/omni
--auth-oidc-client-id=${OMNI_CLIENT_ID}
--auth-oidc-client-secret=${OMNI_CLIENT_SECRET}
--auth-oidc-scopes=openid
--auth-oidc-scopes=profile
--auth-oidc-scopes=email
--create-initial-service-account
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment