https://docs.siderolabs.com/omni/self-hosted/run-omni-on-prem

Skip steps 4.1 and 4.2 entirely since we are using our own AD CA.

Step 4.3 I remove the auth endpoint from the SSL cert since we are going to authenticate with EntraID

cat <<EOF > wildcard-csr.json
{
  "CN": "omni.#####.####",
  "hosts": [
    "${OMNI_ENDPOINT}",
    "127.0.0.1",
    "${HOST_PUBLIC_IP}",
    "${HOST_PRIVATE_IP}"
  ],
  "key": { "algo": "rsa", "size": 4096 }
}
EOF

cfssl genkey wildcard-csr.json | cfssljson -bare server

That gives you server-key.pem (stays on the Omni host) and server.csr. Submit the CSR to your AD CA

Then convert it

openssl x509 -inform der -in server.cer -out server.pem

cat server.pem issuing-ca.pem root-ca.pem > server-chain.pem

Omni supports generic OIDC natively now (since 1.2.0), and step 7.4 in the current guide is already using it — it just points at the local Dex container. To use Entra ID directly you swap the provider URL and credentials, and you get to delete Dex from the setup entirely.
Entra side — app registration:

Entra ID → App registrations → New registration. Single tenant is fine.

Platform: Web, redirect URI: https:///oidc/consume — that’s Omni’s OIDC callback path (you can see it in the guide’s Dex config, where it’s registered as the allowed redirectURIs for the omni client). Entra accepts non-public hostnames like omni.internal as long as it’s HTTPS.

Certificates & secrets → new client secret (Omni only supports secret auth, not cert-based client auth). Note the expiry — max 24 months, so calendar the rotation.

Token configuration → add the email optional claim to the ID token, and make sure your account actually has the mail attribute populated. This matters because Omni identifies users purely by the email claim, and Entra ID tokens frequently omit it by default — if it’s missing, login will succeed at Entra and fail at Omni.

The following is important when using EntraID
--auth-oidc-allow-unverified-email=true

export EULA_NAME="Grzegorz"
export EULA_EMAIL="########@######.###"

docker run -d \
  --name omni \
  --net=host \
  --cap-add=NET_ADMIN \
  --device /dev/net/tun:/dev/net/tun \
  --restart=unless-stopped \
  -v /opt/omni/ca.pem:/etc/ssl/certs/ca-certificates.crt:ro,Z \
  -v /opt/omni/server-key.pem:/server-key.pem:ro,Z \
  -v /opt/omni/server-chain.pem:/server-chain.pem:ro,Z \
  -v /opt/omni/omni.asc:/omni.asc:ro,Z \
  -v /opt/omni/sqlite:/_out/sqlite:rw,Z \
  ghcr.io/siderolabs/omni:${OMNI_VERSION} \
    --name=omni \
    --cert=/server-chain.pem \
    --key=/server-key.pem \
    --machine-api-cert=/server-chain.pem \
    --machine-api-key=/server-key.pem \
    --machine-api-bind-addr=0.0.0.0:8090 \
    --private-key-source=file:///omni.asc \
    --event-sink-port=8091 \
    --bind-addr=0.0.0.0:443 \
    --k8s-proxy-bind-addr=0.0.0.0:8100 \
    --advertised-api-url=https://${OMNI_ENDPOINT}/ \
    --siderolink-api-advertised-url=https://${OMNI_ENDPOINT}:8090/ \
    --siderolink-wireguard-advertised-addr=${HOST_PUBLIC_IP}:50180 \
    --advertised-kubernetes-proxy-url=https://${OMNI_ENDPOINT}:8100/ \
	--auth-auth0-enabled=false \
	--auth-oidc-enabled=true \
	--auth-oidc-provider-url=https://login.microsoftonline.com/#########-####-####-#######/v2.0 \
	--auth-oidc-client-id=#####-####-####-####-########## \
	--auth-oidc-client-secret=######################### \
	--auth-oidc-scopes=openid \
	--auth-oidc-scopes=profile \
	--auth-oidc-scopes=email \
	--sqlite-storage-path=/_out/sqlite/omni.db \
	--initial-users=########@######.### \
    --eula-accept-name="${EULA_NAME}" \
    --eula-accept-email="${EULA_EMAIL}" \
	--auth-oidc-allow-unverified-email=true