Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 48 additions & 14 deletions scripts/realm_export.sh
Original file line number Diff line number Diff line change
@@ -1,21 +1,55 @@
#!/bin/bash
set -euo pipefail

SCRIPT_PATH="$(readlink -f "$0")"
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
# Set defaults, but allow overrides via environment variables
KEYCLOAK_CONTAINER="${KEYCLOAK_CONTAINER:-keycloak}"
KEYCLOAK_REALM="${KEYCLOAK_REALM:-aiod}"
EXPORT_DIR="${EXPORT_DIR:-./keycloak-exports}"

cd $SCRIPT_DIR/..
REALM_FILE="aiod-realm.json"
USERS_FILE="aiod-users.json"
CONTAINER_TMP="/tmp/keycloak-export"

source .env
[ ! -f override.env ] && touch override.env
source override.env
DATA_PATH=$(realpath "$DATA_PATH")
LOCAL_BACKUP_PATH="$DATA_PATH"/keycloak_realm
log() {
echo "[realm_export] $1"
}

docker exec -i keycloak /bin/bash -c "/opt/keycloak/bin/kc.sh export --file /tmp/aiod.json --realm aiod --users realm_file"

if [ ! -d "$LOCAL_BACKUP_PATH" ]; then
mkdir "$LOCAL_BACKUP_PATH"
# Bail out early if the container isn't up
if ! docker inspect --format '{{.State.Running}}' "${KEYCLOAK_CONTAINER}" 2>/dev/null | grep -q "^true$"; then
echo "Error: Container '${KEYCLOAK_CONTAINER}' doesn't seem to be running." >&2
echo "Make sure Keycloak is up before running the backup script." >&2
exit 1
fi

docker cp keycloak:/tmp/aiod.json "$LOCAL_BACKUP_PATH"/aiod.json
docker exec -i keycloak /bin/bash -c "rm /tmp/aiod.json"
# Prep the local and container directories
mkdir -p "${EXPORT_DIR}"
docker exec "${KEYCLOAK_CONTAINER}" mkdir -p "${CONTAINER_TMP}"

# --- 1. Export the realm config (skipping users) ---
log "Exporting realm config to ${REALM_FILE}..."

docker exec "${KEYCLOAK_CONTAINER}" \
/opt/keycloak/bin/kc.sh export \
--dir "${CONTAINER_TMP}" \
--realm "${KEYCLOAK_REALM}" \
--users skip

# kc.sh generates the file as <realm>-realm.json, pull it out and rename it
docker cp "${KEYCLOAK_CONTAINER}:${CONTAINER_TMP}/${KEYCLOAK_REALM}-realm.json" "${EXPORT_DIR}/${REALM_FILE}"
log "✔ Realm config saved."

# --- 2. Export the user data ---
log "Exporting user data to ${USERS_FILE}..."

docker exec "${KEYCLOAK_CONTAINER}" \
/opt/keycloak/bin/kc.sh export \
--dir "${CONTAINER_TMP}" \
--realm "${KEYCLOAK_REALM}" \
--users realm_file

# Keycloak chunks user exports, giving it a '-0' suffix.
# Grab it and rename it to our clean target filename.
docker cp "${KEYCLOAK_CONTAINER}:${CONTAINER_TMP}/${KEYCLOAK_REALM}-users-0.json" "${EXPORT_DIR}/${USERS_FILE}"
log "✔ User data saved."

# Clean up the temp folder inside the container so we don'
48 changes: 48 additions & 0 deletions scripts/realm_import_users.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
# script to import users into keycloak without breaking the realm config
# fixes issue #304

set -euo pipefail # stop on errors

# set variables or use defaults
KEYCLOAK_CONTAINER="${KEYCLOAK_CONTAINER:-keycloak}"
KEYCLOAK_REALM="${KEYCLOAK_REALM:-aiod}"
EXPORT_DIR="${EXPORT_DIR:-./keycloak-exports}"

# get file from args or use default
USERS_FILE="${1:-${EXPORT_DIR}/aiod-users.json}"
CONTAINER_TMP="/tmp/keycloak-import"

# check if backup file actually exists
if [[ ! -f "${USERS_FILE}" ]]; then
echo "error: can't find the users file at ${USERS_FILE}" >&2
echo "run the export script first or pass the exact path" >&2
exit 1
fi

# check if docker container is running
if ! docker inspect --format '{{.State.Running}}' "${KEYCLOAK_CONTAINER}" 2>/dev/null | grep -q "^true$"; then
echo "error: keycloak container isn't running right now" >&2
exit 1
fi

echo "importing users from ${USERS_FILE}..."

# make temp dir inside container
docker exec "${KEYCLOAK_CONTAINER}" mkdir -p "${CONTAINER_TMP}"

# copy backup file into the container
docker cp "${USERS_FILE}" "${KEYCLOAK_CONTAINER}:${CONTAINER_TMP}/aiod-users.json"

# run the import
# using --override false so we don't accidentally overwrite existing users
docker exec "${KEYCLOAK_CONTAINER}" \
/opt/keycloak/bin/kc.sh import \
--dir "${CONTAINER_TMP}" \
--realm "${KEYCLOAK_REALM}" \
--override false

# clean up temp files
docker exec "${KEYCLOAK_CONTAINER}" rm -rf "${CONTAINER_TMP}"

echo "done! users imported safely."