77 lines
2.8 KiB
Bash
Executable File
77 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
if [[ $# -lt 2 || $# -gt 3 ]]; then
|
|
echo "Usage: $0 <db_name> <db_user> [db_password]"
|
|
echo "Example: $0 project1_db project1_user"
|
|
echo "Example: $0 project1_db project1_user 'very-strong-password'"
|
|
exit 1
|
|
fi
|
|
|
|
DB_NAME="$1"
|
|
DB_USER="$2"
|
|
DB_PASSWORD="${3:-}"
|
|
|
|
if [[ ! "${DB_NAME}" =~ ^[a-zA-Z0-9_]+$ ]]; then
|
|
echo "Error: db_name must match [a-zA-Z0-9_]+"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! "${DB_USER}" =~ ^[a-zA-Z0-9_]+$ ]]; then
|
|
echo "Error: db_user must match [a-zA-Z0-9_]+"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "${DB_PASSWORD}" ]]; then
|
|
# Generate a random URL-safe password if none was provided.
|
|
DB_PASSWORD="$(openssl rand -base64 24 | tr -d '\n' | tr '/+' '_-')"
|
|
fi
|
|
|
|
POSTGRES_ADMIN_USER="${POSTGRES_USER:-admin}"
|
|
POSTGRES_ADMIN_DB="${POSTGRES_DB:-app}"
|
|
POSTGRES_CONTAINER="${POSTGRES_CONTAINER_NAME:-postgres}"
|
|
|
|
sql_escape() {
|
|
printf "%s" "$1" | sed "s/'/''/g"
|
|
}
|
|
|
|
DB_NAME_ESCAPED="$(sql_escape "${DB_NAME}")"
|
|
DB_USER_ESCAPED="$(sql_escape "${DB_USER}")"
|
|
DB_PASSWORD_ESCAPED="$(sql_escape "${DB_PASSWORD}")"
|
|
|
|
echo "Creating database user and database in container '${POSTGRES_CONTAINER}'..."
|
|
|
|
ROLE_EXISTS="$(docker exec "${POSTGRES_CONTAINER}" psql -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" -tAc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER_ESCAPED}'" || true)"
|
|
if [[ "${ROLE_EXISTS}" == "1" ]]; then
|
|
docker exec "${POSTGRES_CONTAINER}" psql -v ON_ERROR_STOP=1 -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" \
|
|
-c "ALTER ROLE \"${DB_USER}\" WITH LOGIN PASSWORD '${DB_PASSWORD_ESCAPED}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION;"
|
|
else
|
|
docker exec "${POSTGRES_CONTAINER}" psql -v ON_ERROR_STOP=1 -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" \
|
|
-c "CREATE ROLE \"${DB_USER}\" LOGIN PASSWORD '${DB_PASSWORD_ESCAPED}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION;"
|
|
fi
|
|
|
|
DB_EXISTS="$(docker exec "${POSTGRES_CONTAINER}" psql -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" -tAc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME_ESCAPED}'" || true)"
|
|
if [[ "${DB_EXISTS}" == "1" ]]; then
|
|
echo "Database '${DB_NAME}' already exists."
|
|
else
|
|
docker exec "${POSTGRES_CONTAINER}" psql -v ON_ERROR_STOP=1 -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" \
|
|
-c "CREATE DATABASE \"${DB_NAME}\" OWNER \"${DB_USER}\";"
|
|
fi
|
|
|
|
docker exec "${POSTGRES_CONTAINER}" psql -v ON_ERROR_STOP=1 -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" \
|
|
-c "REVOKE CONNECT, TEMP ON DATABASE \"${DB_NAME}\" FROM PUBLIC;"
|
|
docker exec "${POSTGRES_CONTAINER}" psql -v ON_ERROR_STOP=1 -U "${POSTGRES_ADMIN_USER}" -d "${POSTGRES_ADMIN_DB}" \
|
|
-c "GRANT CONNECT, TEMP ON DATABASE \"${DB_NAME}\" TO \"${DB_USER}\";"
|
|
|
|
cat <<EOF
|
|
Done.
|
|
|
|
Use these values in your app .env:
|
|
DB_HOST=postgres
|
|
DB_PORT=5432
|
|
DB_NAME=${DB_NAME}
|
|
DB_USER=${DB_USER}
|
|
DB_PASSWORD=${DB_PASSWORD}
|
|
EOF
|