199 lines
6.2 KiB
Bash
199 lines
6.2 KiB
Bash
#!/bin/sh
|
|
|
|
# Configuration
|
|
|
|
DB_TYPE="${DB_TYPE:-pyscopg2}" # Default to PostgreSQL
|
|
POSTGRES_DB="${POSTGRES_DB:-matrix}"
|
|
POSTGRES_USER="${POSTGRES_USER:-matrix}"
|
|
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-matrix}"
|
|
POSTGRES_HOST=matrixpostgres-db
|
|
DB_PORT="5432"
|
|
|
|
SYNAPSE_HOST="${SYNAPSE_SERVER_NAME:-localhost}"
|
|
SYNAPSE_PORT="${SYNAPSE_PORT:-8008}"
|
|
ADMIN_USERNAME="${ADMIN_USERNAME:-admin}"
|
|
ADMIN_PASSWORD="${ADMIN_PASSWORD:-changeme}"
|
|
HOMESERVER_URL="${HOMESERVER_URL:-http://$SYNAPSE_HOST:$SYNAPSE_PORT}"
|
|
|
|
prepare_postgres () {
|
|
if [ -f "/data/homeserver.yaml" ]; then;
|
|
DB_TYPE=$(yq '.database.name' /data/homeserver.yaml 2>/dev/null )
|
|
if [ "$DB_TYPE" != "psycopg2" ]; then
|
|
echo "Preparing PostgreSQL database..."
|
|
YAML='.server_name = "'$SYNAPSE_HOST'" |
|
|
.database.name = "psycopg2" |
|
|
.database.args.user = "'$POSTGRES_USER'" |
|
|
.database.args.password = "'$POSTGRES_PASSWORD'" |
|
|
.database.args.database = "'$POSTGRES_DB'" |
|
|
.database.args.host = "'$POSTGRES_HOST'" |
|
|
.database.args.port = "'$DB_PORT'" |
|
|
.database.args.cp_min = 5 |
|
|
.database.args.cp_max = 10'
|
|
yq eval "$YAML" /data/homeserver.yaml > /data/homeserver.yaml.tmp && mv /data/homeserver.yaml.tmp /data/homeserver.yaml
|
|
exit 0
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Get registration shared secret from template.json
|
|
get_registration_secret() {
|
|
if [ -f "/data/homeserver.yaml" ]; then
|
|
SHARED_SECRET=$(yq '.registration_shared_secret' /data/homeserver.yaml 2>/dev/null)
|
|
fi
|
|
}
|
|
|
|
# Wait for Synapse to be ready
|
|
wait_for_synapse() {
|
|
echo "Waiting for Synapse to be ready..."
|
|
local max_attempts=30
|
|
local attempt=1
|
|
|
|
while [ $attempt -le $max_attempts ]; do
|
|
if curl -s "$HOMESERVER_URL/_matrix/client/versions" >/dev/null 2>&1; then
|
|
echo "Synapse is ready!"
|
|
return 0
|
|
fi
|
|
echo "Attempt $attempt/$max_attempts - Synapse not ready yet..."
|
|
sleep 2
|
|
attempt=$((attempt + 1))
|
|
done
|
|
|
|
echo "Error: Synapse did not become ready within expected time"
|
|
return 1
|
|
}
|
|
|
|
# Check if any admin users exist using admin API
|
|
check_admin_exists() {
|
|
# Try to get a temporary admin token first
|
|
local temp_token=$(get_admin_token)
|
|
|
|
if [ -n "$temp_token" ]; then
|
|
local response=$(curl -s -X GET \
|
|
"$HOMESERVER_URL/_synapse/admin/v2/users?deactivated=false" \
|
|
-H "Authorization: Bearer $temp_token" 2>/dev/null || echo "")
|
|
|
|
if echo "$response" | grep -q '"admin": true'; then
|
|
return 0 # Admin exists
|
|
fi
|
|
fi
|
|
|
|
return 1 # No admin or couldn't check
|
|
}
|
|
|
|
# Get admin token (this requires an existing admin user)
|
|
get_admin_token() {
|
|
# This function would need an existing admin to work
|
|
# For initial setup, we'll rely on registration shared secret
|
|
echo ""
|
|
}
|
|
|
|
# Register admin user using shared secret
|
|
register_admin_user() {
|
|
local SHARED_SECRET=$1
|
|
|
|
echo "Registering admin user: $ADMIN_USERNAME"
|
|
|
|
# Generate registration MAC
|
|
local nonce=$(date +%s)
|
|
local username_lower=$(echo "$ADMIN_USERNAME" | tr '[:upper:]' '[:lower:]')
|
|
|
|
# Calculate HMAC (simplified - in practice you'd want to use proper HMAC)
|
|
local mac=$(echo -n "${nonce}${username_lower}${ADMIN_PASSWORD}admin" | openssl dgst -sha1 -hmac "$SHARED_SECRET" -binary | base64)
|
|
|
|
# Register user
|
|
local response=$(curl -s -X POST "$HOMESERVER_URL/_synapse/admin/v1/register" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"nonce\": \"$nonce\",
|
|
\"username\": \"$username_lower\",
|
|
\"password\": \"$ADMIN_PASSWORD\",
|
|
\"admin\": true,
|
|
\"mac\": \"$mac\"
|
|
}" 2>/dev/null)
|
|
|
|
if echo "$response" | grep -q "access_token"; then
|
|
echo "Admin user created successfully!"
|
|
return 0
|
|
else
|
|
echo "Failed to create admin user. Response: $response"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Alternative method using registration endpoint
|
|
register_user_simple() {
|
|
local SHARED_SECRET=$1
|
|
|
|
echo "Attempting simple registration for: $ADMIN_USERNAME"
|
|
|
|
# Try the simpler registration method
|
|
local response=$(curl -s -X POST "$HOMESERVER_URL/_matrix/client/r0/admin/register" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"username\": \"$ADMIN_USERNAME\",
|
|
\"password\": \"$ADMIN_PASSWORD\",
|
|
\"admin\": true,
|
|
\"shared_secret\": \"$SHARED_SECRET\"
|
|
}" 2>/dev/null)
|
|
|
|
echo "Registration response: $response"
|
|
}
|
|
|
|
# Check if admin exists by trying to login
|
|
check_admin_by_login() {
|
|
local response=$(curl -s -X POST "$HOMESERVER_URL/_matrix/client/r0/login" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"type\": \"m.login.password\",
|
|
\"user\": \"$ADMIN_USERNAME\",
|
|
\"password\": \"$ADMIN_PASSWORD\"
|
|
}" 2>/dev/null)
|
|
|
|
if echo "$response" | grep -q "access_token"; then
|
|
return 0 # User exists and password is correct
|
|
fi
|
|
return 1 # User doesn't exist or wrong password
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
echo "Starting Synapse admin initialization..."
|
|
|
|
if ! wait_for_synapse; then
|
|
exit 1
|
|
fi
|
|
|
|
# Get registration shared secret
|
|
local SHARED_SECRET=$(get_registration_secret)
|
|
if [ -z "$SHARED_SECRET" ]; then
|
|
echo "Error: Could not find registration_shared_secret"
|
|
echo "Make sure template.json contains the encoded configuration"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Found registration shared secret"
|
|
|
|
# Check if admin already exists by trying to login
|
|
if check_admin_by_login; then
|
|
echo "Admin user '$ADMIN_USERNAME' already exists and is accessible"
|
|
exit 0
|
|
fi
|
|
|
|
echo "No accessible admin user found. Creating admin user..."
|
|
|
|
# Try to register admin user
|
|
if ! register_admin_user "$SHARED_SECRET"; then
|
|
echo "Primary registration method failed, trying alternative..."
|
|
register_user_simple "$SHARED_SECRET"
|
|
fi
|
|
}
|
|
|
|
# Validate environment
|
|
if [ -z "$ADMIN_PASSWORD" ] || [ "$ADMIN_PASSWORD" = "changeme" ]; then
|
|
echo "Warning: Please set a secure ADMIN_PASSWORD"
|
|
fi
|
|
|
|
prepare_postgres
|
|
|
|
main "$@"
|