Install and configure PostgreSQL 17 with performance tuning and security hardening

Intermediate 45 min Mar 31, 2026 1,613 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Learn to install PostgreSQL 17 from official repositories, optimize performance with proper memory settings, and implement security best practices including SSL encryption and authentication hardening.

Prerequisites

  • Root or sudo access
  • At least 4GB RAM recommended
  • Basic understanding of SQL and database concepts

What this solves

PostgreSQL 17 brings significant performance improvements and new features for production databases. This tutorial helps you install PostgreSQL 17 from official repositories, configure optimal performance settings for your workload, and implement security hardening to protect your data.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you have the latest security patches.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Add PostgreSQL official repository

Install PostgreSQL 17 from the official PostgreSQL repository to get the latest version and timely security updates.

sudo apt install -y wget ca-certificates
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt update
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Install PostgreSQL 17

Install the PostgreSQL 17 server, client tools, and contrib modules for additional functionality.

sudo apt install -y postgresql-17 postgresql-client-17 postgresql-contrib-17
sudo dnf install -y postgresql17-server postgresql17 postgresql17-contrib

Initialize PostgreSQL database

Initialize the database cluster and start the PostgreSQL service. On RHEL-based systems, you must manually initialize the database.

sudo systemctl start postgresql
sudo systemctl enable postgresql
sudo /usr/pgsql-17/bin/postgresql-17-setup initdb
sudo systemctl enable --now postgresql-17

Set PostgreSQL superuser password

Set a strong password for the postgres superuser account to secure your database installation.

sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'YourSecurePassword123!';"
sudo -u postgres psql -c "\q"

Performance tuning configuration

Calculate optimal shared_buffers

Configure shared_buffers to 25% of total RAM for optimal caching performance. First, check your available memory.

free -h
echo "For 8GB RAM, set shared_buffers = 2GB"
echo "For 16GB RAM, set shared_buffers = 4GB"

Configure performance settings

Edit the PostgreSQL configuration file to optimize memory usage, checkpoints, and query performance.

sudo nano /etc/postgresql/17/main/postgresql.conf
sudo nano /var/lib/pgsql/17/data/postgresql.conf

Add these optimized settings at the end of the file:

# Memory Configuration
shared_buffers = 2GB                    # 25% of total RAM
effective_cache_size = 6GB               # 75% of total RAM
work_mem = 32MB                          # Per query operation
maintenance_work_mem = 512MB             # For VACUUM, CREATE INDEX

# Checkpoint Configuration
checkpoint_completion_target = 0.9
wal_buffers = 64MB
max_wal_size = 4GB
min_wal_size = 1GB

# Query Planner
random_page_cost = 1.1                   # For SSD storage
effective_io_concurrency = 200           # For SSD storage

# Connection Settings
max_connections = 200

# Logging
log_destination = 'stderr'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_min_duration_statement = 1000        # Log slow queries

Configure connection limits

Set up connection pooling configuration to handle concurrent connections efficiently.

# Additional connection settings
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all

Security hardening configuration

Configure authentication methods

Edit pg_hba.conf to enforce secure authentication methods and restrict access by IP address.

sudo cp /etc/postgresql/17/main/pg_hba.conf /etc/postgresql/17/main/pg_hba.conf.backup
sudo nano /etc/postgresql/17/main/pg_hba.conf
sudo cp /var/lib/pgsql/17/data/pg_hba.conf /var/lib/pgsql/17/data/pg_hba.conf.backup
sudo nano /var/lib/pgsql/17/data/pg_hba.conf

Replace the default configuration with these secure settings:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# Local connections require password
local   all             postgres                                scram-sha-256
local   all             all                                     scram-sha-256

# IPv4 local connections require password
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             10.0.0.0/8              scram-sha-256
host    all             all             192.168.0.0/16          scram-sha-256

# IPv6 local connections require password
host    all             all             ::1/128                 scram-sha-256

# Reject all other connections
host    all             all             0.0.0.0/0               reject

Enable SSL encryption

Generate SSL certificates and configure PostgreSQL to use encrypted connections.

sudo -u postgres openssl req -new -x509 -days 365 -nodes -text -out /etc/postgresql/17/main/server.crt -keyout /etc/postgresql/17/main/server.key -subj "/CN=postgresql.example.com"
sudo chown postgres:postgres /etc/postgresql/17/main/server.crt /etc/postgresql/17/main/server.key
sudo chmod 600 /etc/postgresql/17/main/server.key
sudo -u postgres openssl req -new -x509 -days 365 -nodes -text -out /var/lib/pgsql/17/data/server.crt -keyout /var/lib/pgsql/17/data/server.key -subj "/CN=postgresql.example.com"
sudo chown postgres:postgres /var/lib/pgsql/17/data/server.crt /var/lib/pgsql/17/data/server.key
sudo chmod 600 /var/lib/pgsql/17/data/server.key

Enable SSL in PostgreSQL configuration:

# SSL Configuration
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_protocols = 'TLSv1.2,TLSv1.3'
ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
ssl_prefer_server_ciphers = on

Configure firewall rules

Set up firewall rules to allow PostgreSQL connections only from trusted networks.

sudo ufw allow from 192.168.1.0/24 to any port 5432
sudo ufw allow from 10.0.0.0/8 to any port 5432
sudo ufw enable
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' port protocol='tcp' port='5432' accept"
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='10.0.0.0/8' port protocol='tcp' port='5432' accept"
sudo firewall-cmd --reload

Create application database and user

Create a dedicated database and user with minimal privileges for your applications.

sudo -u postgres createdb appdb
sudo -u postgres psql -c "CREATE USER appuser WITH ENCRYPTED PASSWORD 'SecureAppPassword123!';"
sudo -u postgres psql -c "GRANT CONNECT ON DATABASE appdb TO appuser;"
sudo -u postgres psql -c "\c appdb"
sudo -u postgres psql -d appdb -c "GRANT USAGE ON SCHEMA public TO appuser;"
sudo -u postgres psql -d appdb -c "GRANT CREATE ON SCHEMA public TO appuser;"

Restart PostgreSQL service

Apply all configuration changes by restarting the PostgreSQL service.

sudo systemctl restart postgresql
sudo systemctl status postgresql
sudo systemctl restart postgresql-17
sudo systemctl status postgresql-17

Backup automation setup

Create backup directory and script

Set up automated backups using pg_dump with compression and rotation.

sudo mkdir -p /var/backups/postgresql
sudo chown postgres:postgres /var/backups/postgresql
sudo chmod 750 /var/backups/postgresql

Create the backup script:

#!/bin/bash

# PostgreSQL backup script
BACKUP_DIR="/var/backups/postgresql"
DATE=$(date +"%Y%m%d_%H%M%S")
DATABASE="appdb"
BACKUP_FILE="${BACKUP_DIR}/${DATABASE}_${DATE}.sql.gz"

# Create backup
pg_dump -h localhost -U postgres -d $DATABASE | gzip > $BACKUP_FILE

# Set ownership and permissions
chown postgres:postgres $BACKUP_FILE
chmod 640 $BACKUP_FILE

# Remove backups older than 7 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete

# Log backup completion
echo "$(date): Backup completed: $BACKUP_FILE" >> /var/log/pg_backup.log
sudo chmod +x /usr/local/bin/pg_backup.sh
sudo chown postgres:postgres /usr/local/bin/pg_backup.sh

Schedule automated backups

Add a cron job to run backups daily at 2 AM.

sudo -u postgres crontab -e

Add this line to the crontab:

0 2 * * * /usr/local/bin/pg_backup.sh

Verify your setup

Test your PostgreSQL installation, performance settings, and security configuration.

# Check PostgreSQL version
sudo -u postgres psql -c "SELECT version();"

# Test SSL connection
psql "host=localhost dbname=appdb user=appuser sslmode=require" -c "SELECT current_database();"

# Check current settings
sudo -u postgres psql -c "SHOW shared_buffers;"
sudo -u postgres psql -c "SHOW max_connections;"
sudo -u postgres psql -c "SHOW ssl;"

# Test backup script
sudo -u postgres /usr/local/bin/pg_backup.sh
ls -la /var/backups/postgresql/
Note: You can monitor PostgreSQL performance and queries using Grafana with Prometheus for comprehensive database monitoring.

Common issues

SymptomCauseFix
Connection refused on port 5432PostgreSQL not listening on correct interfaceSet listen_addresses = '*' in postgresql.conf
Password authentication failedIncorrect pg_hba.conf configurationCheck authentication method and user permissions in pg_hba.conf
SSL connection errorCertificate permissions or missing SSL configEnsure server.key has 600 permissions and owned by postgres user
High memory usageshared_buffers set too highReduce shared_buffers to 25% of total RAM
Slow query performanceInadequate work_mem or missing indexesIncrease work_mem and analyze slow query log
Backup script failsPermission issues or missing pg_dumpEnsure postgres user can write to backup directory
Never use chmod 777 for PostgreSQL files. This gives every user on the system full access to your database files. Use proper ownership with chown postgres:postgres and minimal permissions like 640 for data files.

Next steps

Automated install script

Run this to automate the entire setup

Non vuoi gestirlo da solo?

Gestiamo l'infrastruttura di aziende che dipendono dall'uptime. Completamente gestita, con un referente fisso che conosce il tuo ambiente.

Avete un referente fisso che conosce il vostro ambiente

Alla scrivania a Rotterdam 09:45 · raggiungibile con un messaggio, senza modulo ticket