Last updated: 15 May 2026
Keycloak includes a CLI tool called kcadm.sh inside the container. Always use one of these confirmed-working patterns:
cat > /tmp/role.json << 'EOF'
{ "name": "wiki-user", "composite": false }
EOF
docker cp /tmp/role.json keycloak:/tmp/
docker exec keycloak /opt/keycloak/bin/kcadm.sh create roles -r veripath -f /tmp/role.json
docker exec -i keycloak /opt/keycloak/bin/kcadm.sh create clients -r veripath -f - << 'EOF'
{ "clientId": "wiki-js", "publicClient": true, "redirectUris": ["https://wiki.veripath.co.uk/*"] }
EOF
cat /tmp/payload.json | docker exec -i keycloak /opt/keycloak/bin/kcadm.sh create clients -r veripath -f -
docker exec keycloak /opt/keycloak/bin/kcadm.sh get users -r veripath
docker exec keycloak /opt/keycloak/bin/kcadm.sh get clients -r veripath
# Get user ID first:
USER_ID=$(docker exec keycloak /opt/keycloak/bin/kcadm.sh get users -r veripath -q username=matthew --fields id --format csv | tail -1 | tr -d '"')
# Get client UUID:
CLIENT_UUID=$(docker exec keycloak /opt/keycloak/bin/kcadm.sh get clients -r veripath -q clientId=wiki-js --fields id --format csv | tail -1 | tr -d '"')
# Create role mapping payload:
cat > /tmp/role-mapping.json << 'EOF'
[{"name": "wiki-user", "clientRole": true}]
EOF
docker cp /tmp/role-mapping.json keycloak:/tmp/
docker exec keycloak /opt/keycloak/bin/kcadm.sh create users/$USER_ID/role-mappings/clients/$CLIENT_UUID -r veripath -f /tmp/role-mapping.json
docker exec keycloak /opt/keycloak/bin/kcadm.sh get users/<USER_ID>/role-mappings -r veripath
The following does NOT work through docker exec:
# BROKEN - stdin forwarding doesn't work through non-interactive docker exec
docker exec keycloak /opt/keycloak/bin/kcadm.sh create clients -r veripath -f /dev/stdin
This fails silently and may corrupt client configuration.