diff --git a/misc/tools.func b/misc/tools.func index b55f1de1b..8a39009d3 100644 --- a/misc/tools.func +++ b/misc/tools.func @@ -3818,6 +3818,103 @@ function setup_postgresql() { fi } +# ------------------------------------------------------------------------------ +# Creates PostgreSQL database with user and optional extensions +# +# Description: +# - Creates PostgreSQL role with login and password +# - Creates database with UTF8 encoding and template0 +# - Installs optional extensions (postgis, pgvector, etc.) +# - Configures ALTER ROLE settings for Django/Rails compatibility +# - Saves credentials to file +# - Exports variables for use in calling script +# +# Usage: +# DB_NAME="myapp_db" DB_USER="myapp_user" setup_postgresql_db +# DB_NAME="immich" DB_USER="immich" DB_EXTENSIONS="pgvector" setup_postgresql_db +# DB_NAME="ghostfolio" DB_USER="ghostfolio" DB_GRANT_SUPERUSER="true" setup_postgresql_db +# DB_NAME="adventurelog" DB_USER="adventurelog" DB_EXTENSIONS="postgis" setup_postgresql_db +# +# Variables: +# DB_NAME - Database name (required) +# DB_USER - Database user (required) +# DB_PASS - Database password (optional, auto-generated if empty) +# DB_EXTENSIONS - Comma-separated list of extensions (optional, e.g. "postgis,pgvector") +# DB_GRANT_SUPERUSER - Grant SUPERUSER privilege (optional, "true" to enable, security risk!) +# DB_SCHEMA_PERMS - Grant schema-level permissions (optional, "true" to enable) +# DB_SKIP_ALTER_ROLE - Skip ALTER ROLE settings (optional, "true" to skip) +# DB_CREDS_FILE - Credentials file path (optional, default: ~/pg_${DB_NAME}.creds) +# +# Exports: +# PG_DB_NAME, PG_DB_USER, PG_DB_PASS - For use in calling script +# ------------------------------------------------------------------------------ + +function setup_postgresql_db() { + # Validation + if [[ -z "$DB_NAME" || -z "$DB_USER" ]]; then + msg_error "DB_NAME and DB_USER must be set before calling setup_postgresql_db" + return 1 + fi + + # Generate password if not provided + if [[ -z "$DB_PASS" ]]; then + DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) + fi + + msg_info "Setting up PostgreSQL Database" + $STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';" + $STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;" + + # Install extensions (comma-separated) + if [[ -n "$DB_EXTENSIONS" ]]; then + IFS=',' read -ra EXT_LIST <<<"$DB_EXTENSIONS" + for ext in "${EXT_LIST[@]}"; do + ext=$(echo "$ext" | xargs) # Trim whitespace + $STD sudo -u postgres psql -d "$DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS $ext;" + done + fi + + # ALTER ROLE settings for Django/Rails compatibility (unless skipped) + if [[ "$DB_SKIP_ALTER_ROLE" != "true" ]]; then + $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';" + $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';" + $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';" + fi + + # Schema permissions (if requested) + if [[ "$DB_SCHEMA_PERMS" == "true" ]]; then + $STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" + $STD sudo -u postgres psql -c "ALTER USER $DB_USER CREATEDB;" + $STD sudo -u postgres psql -d "$DB_NAME" -c "GRANT ALL ON SCHEMA public TO $DB_USER;" + $STD sudo -u postgres psql -d "$DB_NAME" -c "GRANT CREATE ON SCHEMA public TO $DB_USER;" + $STD sudo -u postgres psql -d "$DB_NAME" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO $DB_USER;" + $STD sudo -u postgres psql -d "$DB_NAME" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO $DB_USER;" + fi + + # Superuser grant (if requested - WARNING!) + if [[ "$DB_GRANT_SUPERUSER" == "true" ]]; then + msg_warn "Granting SUPERUSER privilege (security risk!)" + $STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME to $DB_USER;" + $STD sudo -u postgres psql -c "ALTER USER $DB_USER WITH SUPERUSER;" + fi + + # Save credentials + local CREDS_FILE="${DB_CREDS_FILE:-~/pg_${DB_NAME}.creds}" + { + echo "PostgreSQL Credentials" + echo "Database: $DB_NAME" + echo "User: $DB_USER" + echo "Password: $DB_PASS" + } >>"$CREDS_FILE" + + msg_ok "Set up PostgreSQL Database" + + # Export for use in calling script + export PG_DB_NAME="$DB_NAME" + export PG_DB_USER="$DB_USER" + export PG_DB_PASS="$DB_PASS" +} + # ------------------------------------------------------------------------------ # Installs rbenv and ruby-build, installs Ruby and optionally Rails. #