#!/bin/sh -e # AliasVault Container Initialization Script # This script runs once at container startup and handles all initialization tasks # Get verbosity level (0=minimal, 1=normal, 2=verbose) VERBOSITY="${ALIASVAULT_VERBOSITY:-0}" # Helper function for logging based on verbosity log() { level=$1 shift if [ "$VERBOSITY" -ge "$level" ]; then echo "$@" fi } # Always show header and critical messages (level 0) echo "" echo "==================================================" echo " _ _ _ __ __ _ _ " echo " / \\ | (_) __ _ ___ \\ \\ / /_ _ _ _| | |_" echo " / _ \\ | | |/ _\` / __| \\ \\/\\/ / _\` | | | | | __|" echo " / ___ \\| | | (_| \\__ \\ \\ / / (_| | |_| | | |_ " echo "/_/ \\_\\_|_|\\__,_|___/ \\/ \\__,__|\\__,_|_|\\__|" echo "" echo "==================================================" echo "" echo "[init] Starting AliasVault..." echo "" # Create required directories if [ ! -d /database/postgres ] || [ ! -d /logs/postgres ] || [ ! -d /certificates ] || [ ! -d /secrets ] || [ ! -d /var/run/postgresql ]; then mkdir -p /database/postgres /logs/postgres /certificates /secrets /var/run/postgresql log 0 "[init] Required directories created" else log 0 "[init] ✅ Required directories already exist" fi if [ ! -f /secrets/postgres_password ]; then log 0 "[init] → Generating PostgreSQL password..." openssl rand -base64 32 | tr -d "\n" > /secrets/postgres_password chmod 600 /secrets/postgres_password else log 0 "[init] ✅ PostgreSQL password already exists " fi if [ ! -f /secrets/data_protection_cert_pass ]; then log 0 "[init] → Generating Data Protection Certificate password..." openssl rand -base64 32 | tr -d "\n" > /secrets/data_protection_cert_pass chmod 600 /secrets/data_protection_cert_pass else log 0 "[init] ✅ Data Protection Certificate password already exists" fi if [ ! -f /secrets/jwt_key ]; then log 0 "[init] → Generating JWT key..." openssl rand -base64 32 | tr -d "\n" > /secrets/jwt_key chmod 600 /secrets/jwt_key else log 0 "[init] ✅ JWT key already exists" fi # Admin password is not created by default # Users must run reset-admin-password.sh to configure the admin password log 0 "[init] ✅ Admin password configuration deferred to manual setup" # Read PostgreSQL password for database initialization POSTGRES_PASSWORD=$(cat /secrets/postgres_password) export PGDATA="/database/postgres" # Initialize PostgreSQL if needed if [ ! -d "$PGDATA/base" ]; then log 0 "" log 0 "[init] PostgreSQL database not found, initializing..." # Set proper permissions chown -R postgres:postgres /database/postgres /logs/postgres /var/run/postgresql chmod 700 /database/postgres # Initialize database as postgres user log 1 "[init] → Running initdb..." if [ "$VERBOSITY" -ge 2 ]; then su - postgres -c "/usr/lib/postgresql/16/bin/initdb -D $PGDATA --locale=C.UTF-8 --encoding=UTF8" 2>&1 | tee /logs/postgres/initdb.log else su - postgres -c "/usr/lib/postgresql/16/bin/initdb -D $PGDATA --locale=C.UTF-8 --encoding=UTF8" > /logs/postgres/initdb.log 2>&1 fi # Configure PostgreSQL log 0 "[init] → Configuring PostgreSQL..." # Listen on all container interfaces (covers localhost & Docker networks) echo "listen_addresses = '*'" >> "$PGDATA/postgresql.conf" # Store SCRAM hashes instead of MD5 echo "password_encryption = scram-sha-256" >> "$PGDATA/postgresql.conf" # Allow local Unix-socket connections (processes inside the same container) echo "local all all trust" >> "$PGDATA/pg_hba.conf" # Allow any client on the same subnet(s) as this container (bridge/overlay) # Prefer SCRAM if enabled above; otherwise MD5 if grep -qi '^password_encryption *= *scram-sha-256' "$PGDATA/postgresql.conf"; then AUTH_METHOD="scram-sha-256" else AUTH_METHOD="md5" fi echo "host all all samenet ${AUTH_METHOD}" >> "$PGDATA/pg_hba.conf" # Start PostgreSQL temporarily to create database and user log 0 "[init] → Starting PostgreSQL temporarily for setup..." if [ "$VERBOSITY" -ge 2 ]; then su - postgres -c "/usr/lib/postgresql/16/bin/pg_ctl -D $PGDATA -l /logs/postgres/postgres.log start" else su - postgres -c "/usr/lib/postgresql/16/bin/pg_ctl -D $PGDATA -l /logs/postgres/postgres.log start" >/dev/null 2>&1 fi # Wait for PostgreSQL to be ready log 0 "[init] → Waiting for PostgreSQL to be ready..." i=1 while [ $i -le 30 ]; do if su - postgres -c "/usr/lib/postgresql/16/bin/psql -c 'SELECT 1;'" >/dev/null 2>&1; then break fi sleep 1 i=$((i + 1)) done # Create database and user log 0 "[init] → Creating AliasVault database and user..." if [ "$VERBOSITY" -ge 2 ]; then su - postgres -c "/usr/lib/postgresql/16/bin/psql -c \"CREATE USER aliasvault WITH PASSWORD '$POSTGRES_PASSWORD'\"" su - postgres -c "/usr/lib/postgresql/16/bin/psql -c \"CREATE DATABASE aliasvault OWNER aliasvault LOCALE 'C.UTF-8';\"" su - postgres -c "/usr/lib/postgresql/16/bin/psql -c \"GRANT ALL PRIVILEGES ON DATABASE aliasvault TO aliasvault;\"" else su - postgres -c "/usr/lib/postgresql/16/bin/psql -c \"CREATE USER aliasvault WITH PASSWORD '$POSTGRES_PASSWORD'\"" >/dev/null 2>&1 su - postgres -c "/usr/lib/postgresql/16/bin/psql -c \"CREATE DATABASE aliasvault OWNER aliasvault LOCALE 'C.UTF-8';\"" >/dev/null 2>&1 su - postgres -c "/usr/lib/postgresql/16/bin/psql -c \"GRANT ALL PRIVILEGES ON DATABASE aliasvault TO aliasvault;\"" >/dev/null 2>&1 fi # Stop PostgreSQL log 0 "[init] → Stopping PostgreSQL..." if [ "$VERBOSITY" -ge 2 ]; then su - postgres -c "/usr/lib/postgresql/16/bin/pg_ctl -D $PGDATA stop" else su - postgres -c "/usr/lib/postgresql/16/bin/pg_ctl -D $PGDATA stop" >/dev/null 2>&1 fi sleep 2 log 0 "[init] PostgreSQL initialization complete" else log 0 "[init] ✅ PostgreSQL database already initialized" # Just ensure permissions are correct chown -R postgres:postgres /database/postgres /logs/postgres /var/run/postgresql chmod 700 /database/postgres fi # Future: Database migrations could go here # log 1 "[init] Checking for database migrations..." # if [ -f /app/migrations/pending ]; then # log 1 "[init] → Running database migrations..." # # Run migration logic here # fi # Generate SSL certificates if needed if [ ! -f /certificates/ssl/cert.pem ] || [ ! -f /certificates/ssl/key.pem ]; then log 0 "" log 0 "[init] Generating SSL certificates..." mkdir -p /certificates/ssl if [ "$VERBOSITY" -ge 2 ]; then openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /certificates/ssl/key.pem \ -out /certificates/ssl/cert.pem \ -subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME:-localhost}" else openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /certificates/ssl/key.pem \ -out /certificates/ssl/cert.pem \ -subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME:-localhost}" \ >/dev/null 2>&1 fi chmod 600 /certificates/ssl/key.pem chmod 644 /certificates/ssl/cert.pem log 0 "[init] Self-signed SSL certificates generated" else log 0 "[init] ✅ Self-signed SSL certificates already exist" fi echo "" echo "[init] Waiting for all services to be ready... this can take a short while..." echo "" # Oneshot service exits successfully, dependencies can now start