Learn to configure PostgreSQL, MySQL, and MariaDB development databases using environment variables for secure connection management and simplified configuration across different environments.
Prerequisites
- Root or sudo access
- Basic command line knowledge
What this solves
Managing database connections across development environments becomes complex when hardcoding credentials in application code. Environment variables provide a secure, flexible way to configure database connections that works across local development, testing, and staging environments. This approach separates configuration from code and prevents accidental credential exposure in version control.
Environment variables overview and best practices
Environment variables store configuration values outside your application code, making them accessible to running processes. For database configurations, they typically include connection strings, usernames, passwords, host addresses, and port numbers.
Create environment configuration directory
Set up a dedicated directory for your development environment configurations.
mkdir -p ~/dev-config/database-envs
cd ~/dev-config/database-envsCreate base environment template
Create a template file that defines standard database environment variables.
# Database Configuration Template
PostgreSQL
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=devdb
POSTGRES_USER=devuser
POSTGRES_PASSWORD=secure_password_here
DATABASE_URL=postgresql://devuser:secure_password_here@localhost:5432/devdb
MySQL/MariaDB
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=devdb
MYSQL_USER=devuser
MYSQL_PASSWORD=secure_password_here
MYSQL_ROOT_PASSWORD=root_password_here
Application Settings
ENVIRONMENT=development
DEBUG=true
LOG_LEVEL=debugSet secure file permissions
Environment files often contain sensitive credentials and should be readable only by the file owner.
chmod 600 .env.template
echo ".env*" >> ~/.gitignorePostgreSQL development environment setup
Install PostgreSQL server
Install PostgreSQL database server and client tools for development use.
sudo apt update
sudo apt install -y postgresql postgresql-contrib postgresql-clientStart and enable PostgreSQL
Enable PostgreSQL to start automatically and start the service now.
sudo systemctl enable --now postgresql
sudo systemctl status postgresqlCreate development database and user
Set up a dedicated database and user for development work with appropriate permissions.
sudo -u postgres createuser --interactive --pwprompt devuser
sudo -u postgres createdb -O devuser devdbWhen prompted, enter a secure password for the devuser account and answer 'n' to superuser, database creation, and role creation prompts.
Configure PostgreSQL authentication
Update PostgreSQL configuration to allow password authentication for development.
sudo cp /etc/postgresql//main/pg_hba.conf /etc/postgresql//main/pg_hba.conf.backupEdit the authentication configuration file:
# Add this line after the existing local connections
local devdb devuser md5
host devdb devuser 127.0.0.1/32 md5
host devdb devuser ::1/128 md5sudo systemctl reload postgresqlCreate PostgreSQL environment file
Create a specific environment configuration for your PostgreSQL development setup.
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=devdb
POSTGRES_USER=devuser
POSTGRES_PASSWORD=your_secure_password
DATABASE_URL=postgresql://devuser:your_secure_password@localhost:5432/devdb
ENVIRONMENT=developmentchmod 600 .env.postgresTest PostgreSQL connection with environment variables
Verify the connection works by loading environment variables and connecting to the database.
set -a; source .env.postgres; set +a
psql "$DATABASE_URL" -c "SELECT version();"
psql "$DATABASE_URL" -c "\dt"MySQL and MariaDB configuration with environment variables
Install MariaDB server
Install MariaDB as a drop-in replacement for MySQL with better performance and licensing.
sudo apt update
sudo apt install -y mariadb-server mariadb-clientStart and enable MariaDB
Enable MariaDB to start automatically and start the service now.
sudo systemctl enable --now mariadb
sudo systemctl status mariadbSecure MariaDB installation
Run the security script to set root password and remove insecure defaults.
sudo mysql_secure_installationFollow the prompts to set a root password, remove anonymous users, disable remote root login, and remove the test database. Answer 'Y' to all security questions.
Create development database and user
Create a dedicated database and user for development with limited privileges.
sudo mysql -u root -pCREATE DATABASE devdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'devuser'@'localhost' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON devdb.* TO 'devuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;Create MariaDB environment file
Create environment configuration for MariaDB development setup with connection pooling options.
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=devdb
MYSQL_USER=devuser
MYSQL_PASSWORD=your_secure_password
MYSQL_ROOT_PASSWORD=your_root_password
DATABASE_URL=mysql://devuser:your_secure_password@localhost:3306/devdb
DB_CONNECTION_LIMIT=20
DB_IDLE_TIMEOUT=300
ENVIRONMENT=developmentchmod 600 .env.mariadbTest MariaDB connection with environment variables
Verify the connection works by loading environment variables and connecting to the database.
set -a; source .env.mariadb; set +a
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" -e "SELECT VERSION();"
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" -e "SHOW TABLES;"Database connection management and security
Create connection testing script
Build a utility script to test database connections across different environments.
#!/bin/bash
test_postgres() {
echo "Testing PostgreSQL connection..."
set -a; source .env.postgres; set +a
if psql "$DATABASE_URL" -c "SELECT 1;" &>/dev/null; then
echo "✓ PostgreSQL connection successful"
else
echo "✗ PostgreSQL connection failed"
return 1
fi
}
test_mariadb() {
echo "Testing MariaDB connection..."
set -a; source .env.mariadb; set +a
if mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" -e "SELECT 1;" &>/dev/null; then
echo "✓ MariaDB connection successful"
else
echo "✗ MariaDB connection failed"
return 1
fi
}
echo "=== Database Connection Tests ==="
test_postgres
test_mariadb
echo "=== Tests Complete ==="chmod +x test-connections.shCreate environment switcher script
Build a script to easily switch between different database environments during development.
#!/bin/bash
ENV_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
switch_environment() {
local env_name="$1"
local env_file="$ENV_DIR/.env.$env_name"
if [ ! -f "$env_file" ]; then
echo "Environment file $env_file not found"
return 1
fi
# Create current environment symlink
ln -sf "$env_file" "$ENV_DIR/.env.current"
echo "Switched to $env_name environment"
echo "Load with: set -a; source $ENV_DIR/.env.current; set +a"
}
list_environments() {
echo "Available environments:"
for env_file in "$ENV_DIR"/.env.*; do
[ -f "$env_file" ] && basename "$env_file" | sed 's/^.env.//'
done
}
case "$1" in
list)
list_environments
;;
*)
if [ -n "$1" ]; then
switch_environment "$1"
else
echo "Usage: $0 {environment_name|list}"
list_environments
fi
;;
esacchmod +x switch-env.shConfigure connection pooling and security
Create a comprehensive configuration file that includes connection pooling and security settings.
# Database Security Configuration
DB_SSL_MODE=require
DB_SSL_CERT=/path/to/client-cert.pem
DB_SSL_KEY=/path/to/client-key.pem
DB_SSL_CA=/path/to/ca-cert.pem
Connection Pooling
DB_POOL_MIN_SIZE=5
DB_POOL_MAX_SIZE=20
DB_POOL_TIMEOUT=30
DB_POOL_IDLE_TIMEOUT=300
Query and Connection Timeouts
DB_CONNECT_TIMEOUT=10
DB_QUERY_TIMEOUT=30
DB_IDLE_IN_TRANSACTION_TIMEOUT=60
Application Security
ENVIRONMENT=development
DEBUG=false
LOG_LEVEL=info
SECURE_COOKIES=true
SESSION_TIMEOUT=1800This configuration provides a foundation for secure database connections that can be customized for different environments. The PostgreSQL SSL encryption tutorial covers advanced security hardening, while the MariaDB monitoring setup helps track database performance across environments.
Verify your setup
# Test environment switching
./switch-env.sh list
./switch-env.sh postgres
set -a; source .env.current; set +a
echo "Database: $POSTGRES_DB on $POSTGRES_HOST:$POSTGRES_PORT"
Test database connections
./test-connections.sh
Verify PostgreSQL connection
psql "$DATABASE_URL" -c "\l"
Test MariaDB connection
./switch-env.sh mariadb
set -a; source .env.current; set +a
mysql -h"$MYSQL_HOST" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW DATABASES;"
Check file permissions
ls -la .env.Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Environment variables not loaded | Missing set -a before source | set -a; source .env.file; set +a |
| PostgreSQL connection refused | Service not running or wrong host | sudo systemctl status postgresql and check POSTGRES_HOST |
| MySQL access denied | Wrong password or user permissions | Reset password with mysql -u root -p and recreate user |
| Permission denied on .env files | File permissions too restrictive | chmod 600 .env. for owner read/write only |
| Database does not exist | Database not created or wrong name | Check database name in environment file and recreate if needed |
| Scripts not executable | Missing execute permission | chmod +x *.sh to make scripts executable |
Next steps
- Configure FastAPI database connection pooling
- Set up PostgreSQL streaming replication with PgBouncer
- Implement MySQL backup automation
- Configure database environment variables for Docker containers
- Set up database connection pooling for production applications
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Default values
DB_PASSWORD=""
ROOT_PASSWORD=""
DB_USER="devuser"
DB_NAME="devdb"
INSTALL_POSTGRES=true
INSTALL_MYSQL=false
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --db-password PASSWORD Database user password (required)"
echo " --root-password PASSWORD Root/admin password (required for MySQL)"
echo " --db-user USER Database username (default: devuser)"
echo " --db-name NAME Database name (default: devdb)"
echo " --postgres Install PostgreSQL (default)"
echo " --mysql Install MySQL/MariaDB instead"
echo " --help Show this help"
exit 1
}
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
cleanup() {
log_error "Script failed. Check logs above for details."
exit 1
}
trap cleanup ERR
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--db-password)
DB_PASSWORD="$2"
shift 2
;;
--root-password)
ROOT_PASSWORD="$2"
shift 2
;;
--db-user)
DB_USER="$2"
shift 2
;;
--db-name)
DB_NAME="$2"
shift 2
;;
--postgres)
INSTALL_POSTGRES=true
INSTALL_MYSQL=false
shift
;;
--mysql)
INSTALL_POSTGRES=false
INSTALL_MYSQL=true
shift
;;
--help)
usage
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done
# Validate required parameters
if [[ -z "$DB_PASSWORD" ]]; then
log_error "Database password is required (--db-password)"
usage
fi
if [[ "$INSTALL_MYSQL" == true && -z "$ROOT_PASSWORD" ]]; then
log_error "Root password is required for MySQL (--root-password)"
usage
fi
echo "[1/8] Checking prerequisites..."
# Check if running as root or with sudo
if [[ $EUID -eq 0 ]]; then
SUDO=""
else
if ! command -v sudo &> /dev/null; then
log_error "This script requires sudo privileges"
exit 1
fi
SUDO="sudo"
fi
# Detect distribution and package manager
echo "[2/8] Detecting distribution..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
PG_VERSION=$(apt-cache search postgresql | grep "^postgresql-[0-9]" | head -1 | cut -d' ' -f1 | cut -d'-' -f2)
PG_CONFIG_DIR="/etc/postgresql/${PG_VERSION:-*/main"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
PG_CONFIG_DIR="/var/lib/pgsql/data"
;;
fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
PG_CONFIG_DIR="/var/lib/pgsql/data"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
PG_CONFIG_DIR="/var/lib/pgsql/data"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
log_info "Detected $PRETTY_NAME"
else
log_error "Cannot detect distribution"
exit 1
fi
echo "[3/8] Creating environment configuration directory..."
# Create configuration directory
CONFIG_DIR="$HOME/dev-config/database-envs"
mkdir -p "$CONFIG_DIR"
cd "$CONFIG_DIR"
# Set up .gitignore
if [[ ! -f "$HOME/.gitignore" ]] || ! grep -q ".env" "$HOME/.gitignore" 2>/dev/null; then
echo ".env*" >> "$HOME/.gitignore"
fi
echo "[4/8] Updating package manager..."
$SUDO $PKG_UPDATE
if [[ "$INSTALL_POSTGRES" == true ]]; then
echo "[5/8] Installing PostgreSQL..."
case "$ID" in
ubuntu|debian)
$SUDO $PKG_INSTALL postgresql postgresql-contrib postgresql-client
;;
*)
$SUDO $PKG_INSTALL postgresql postgresql-server postgresql-contrib
# Initialize database for RHEL-based systems
if [[ ! -f "$PG_CONFIG_DIR/postgresql.conf" ]]; then
$SUDO postgresql-setup --initdb
fi
;;
esac
echo "[6/8] Starting and enabling PostgreSQL..."
$SUDO systemctl enable postgresql
$SUDO systemctl start postgresql
echo "[7/8] Creating PostgreSQL database and user..."
# Create user and database
$SUDO -u postgres psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';" 2>/dev/null || true
$SUDO -u postgres createdb -O "$DB_USER" "$DB_NAME" 2>/dev/null || true
# Configure authentication
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
PG_VERSION=$(ls /etc/postgresql/ | head -1)
HBA_CONF="/etc/postgresql/${PG_VERSION}/main/pg_hba.conf"
else
HBA_CONF="$PG_CONFIG_DIR/pg_hba.conf"
fi
$SUDO cp "$HBA_CONF" "${HBA_CONF}.backup"
# Add authentication rules if not already present
if ! $SUDO grep -q "^local.*${DB_NAME}.*${DB_USER}" "$HBA_CONF"; then
$SUDO tee -a "$HBA_CONF" > /dev/null << EOF
local ${DB_NAME} ${DB_USER} md5
host ${DB_NAME} ${DB_USER} 127.0.0.1/32 md5
host ${DB_NAME} ${DB_USER} ::1/128 md5
EOF
fi
$SUDO systemctl reload postgresql
# Create environment file
cat > .env.postgres << EOF
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=${DB_NAME}
POSTGRES_USER=${DB_USER}
POSTGRES_PASSWORD=${DB_PASSWORD}
DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@localhost:5432/${DB_NAME}
ENVIRONMENT=development
DEBUG=true
LOG_LEVEL=debug
EOF
chmod 600 .env.postgres
elif [[ "$INSTALL_MYSQL" == true ]]; then
echo "[5/8] Installing MariaDB..."
$SUDO $PKG_INSTALL mariadb-server mariadb
echo "[6/8] Starting and enabling MariaDB..."
$SUDO systemctl enable mariadb
$SUDO systemctl start mariadb
echo "[7/8] Securing MariaDB and creating database..."
# Set root password and create database/user
$SUDO mysql -e "ALTER USER root@localhost IDENTIFIED BY '${ROOT_PASSWORD}';" 2>/dev/null || \
$SUDO mysql -e "SET PASSWORD FOR root@localhost = PASSWORD('${ROOT_PASSWORD}');" 2>/dev/null || true
mysql -u root -p"${ROOT_PASSWORD}" << EOF
CREATE DATABASE IF NOT EXISTS ${DB_NAME};
CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASSWORD}';
GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
EOF
# Create environment file
cat > .env.mysql << EOF
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=${DB_NAME}
MYSQL_USER=${DB_USER}
MYSQL_PASSWORD=${DB_PASSWORD}
MYSQL_ROOT_PASSWORD=${ROOT_PASSWORD}
DATABASE_URL=mysql://${DB_USER}:${DB_PASSWORD}@localhost:3306/${DB_NAME}
ENVIRONMENT=development
DEBUG=true
LOG_LEVEL=debug
EOF
chmod 600 .env.mysql
fi
echo "[8/8] Running verification tests..."
if [[ "$INSTALL_POSTGRES" == true ]]; then
# Test PostgreSQL connection
set -a; source .env.postgres; set +a
if psql "$DATABASE_URL" -c "SELECT version();" &>/dev/null; then
log_info "PostgreSQL connection test: PASSED"
else
log_error "PostgreSQL connection test: FAILED"
exit 1
fi
log_info "PostgreSQL environment file created: $CONFIG_DIR/.env.postgres"
log_info "Load with: set -a; source $CONFIG_DIR/.env.postgres; set +a"
elif [[ "$INSTALL_MYSQL" == true ]]; then
# Test MySQL connection
if mysql -u"$DB_USER" -p"$DB_PASSWORD" -e "SELECT VERSION();" "$DB_NAME" &>/dev/null; then
log_info "MariaDB connection test: PASSED"
else
log_error "MariaDB connection test: FAILED"
exit 1
fi
log_info "MariaDB environment file created: $CONFIG_DIR/.env.mysql"
log_info "Load with: set -a; source $CONFIG_DIR/.env.mysql; set +a"
fi
log_info "Database development environment setup completed successfully!"
log_info "Environment files are located in: $CONFIG_DIR"
log_warn "Remember: Never commit .env files to version control!"
Review the script before running. Execute with: bash install.sh