Install and configure PostgreSQL 17 with performance tuning and security hardening

Intermediate 45 min Mar 31, 2026 55 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

#postgresql #database #performance-tuning #security #backup #ssl

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer