#!/usr/bin/env bash
# stacks/auth/bootstrap.sh
# One-off bootstrap for the auth stack. Generates secrets, creates the
# admin user in lldap, and writes the Authelia totp bootstrap hash so
# the admin can log in for the first time.
#
# Idempotent: existing secrets are kept. Run as root.
#
# Docs: mercemay.top/src/homelab-compose/
set -euo pipefail
STACK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SECRETS_DIR="${SECRETS_DIR:-/srv/homelab/secrets/auth}"
say() { printf '[bootstrap] %s\n' "$*" >&2; }
gen_secret() {
local name="$1" bytes="${2:-48}"
local path="${SECRETS_DIR}/${name}"
if [[ -s "${path}" ]]; then
say "keep ${name}"
return 0
fi
install -d -m 0700 "${SECRETS_DIR}"
openssl rand -hex "${bytes}" > "${path}"
chmod 0600 "${path}"
say "wrote ${name}"
}
require() {
command -v "$1" >/dev/null 2>&1 || { say "missing dep: $1"; exit 1; }
}
main() {
require docker
require openssl
gen_secret authelia_jwt 48
gen_secret authelia_session 48
gen_secret authelia_storage 48
gen_secret lldap_jwt 48
gen_secret lldap_key_seed 48
gen_secret lldap_admin_pass 24
gen_secret redis_password 32
gen_secret slack_webhook 0 2>/dev/null || true
say "starting lldap + redis"
(cd "${STACK_DIR}" && docker compose up -d redis lldap)
say "waiting for lldap health"
for _ in $(seq 1 30); do
if docker compose -f "${STACK_DIR}/docker-compose.yml" \
exec -T lldap wget -q -O - http://localhost:17170/health >/dev/null 2>&1; then
break
fi
sleep 2
done
if ! docker compose -f "${STACK_DIR}/docker-compose.yml" \
exec -T lldap sh -c 'lldap_set_password --help' >/dev/null 2>&1; then
say "lldap CLI unavailable, skipping admin reset"
else
local admin_pass
admin_pass=$(cat "${SECRETS_DIR}/lldap_admin_pass")
docker compose -f "${STACK_DIR}/docker-compose.yml" \
exec -T lldap lldap_set_password \
--base-url http://localhost:17170 \
--username admin \
--password "${admin_pass}" \
|| say "failed to set admin password (maybe already set)"
fi
say "starting authelia"
(cd "${STACK_DIR}" && docker compose up -d authelia)
say "done. Admin password is in ${SECRETS_DIR}/lldap_admin_pass"
}
main "$@"