How to Install PostgreSQL 18 on Rocky Linux 10.2 with SELinux & firewalld

Install PostgreSQL 18 on Rocky Linux 10 with SELinux

PostgreSQL 18 is available straight from the Rocky Linux 10.2 repositories, so you no longer have to add the community PGDG repository just to get a current major version. This guide shows both routes, explains how they differ, and then walks through initialization, a first database and role, secure remote access with SCRAM authentication, firewalld, SELinux, and troubleshooting.

Table of Contents

  1. Which installation method should you use?
  2. Prerequisites
  3. Step 1: Check your Rocky Linux release
  4. Step 2: Install PostgreSQL 18 (native AppStream)
  5. Step 3: Initialize and start the server
  6. Step 4: Verify the installation
  7. Step 5: Create a role and database
  8. Step 6: Allow remote connections securely
  9. Step 7: firewalld
  10. SELinux: custom ports and data directories
  11. Alternative: install from PGDG
  12. What is new in PostgreSQL 18 for fresh installs
  13. Updating and uninstalling
  14. Troubleshooting
  15. FAQ
  16. Next steps

1. Which installation method should you use?

Native AppStream (Rocky 10.2+)PGDG (community repository)
Install commanddnf install postgresql18-serverdnf install postgresql18-server (after adding the PGDG repo RPM)
Initializepostgresql-setup --initdb/usr/pgsql-18/bin/postgresql-18-setup initdb
Service namepostgresql.servicepostgresql-18.service
Binaries/usr/bin/usr/pgsql-18/bin
Data directory/var/lib/pgsql/data/var/lib/pgsql/18/data
Best forSimple, distribution-supported setupsSeveral major versions side by side, PGDG-only extensions, community release cadence

Pick one method and stay with it. Do not enable PGDG halfway through a native installation, because the two use different service names, paths, and helper scripts.

Rocky Linux 10 does not use the old DNF module system for PostgreSQL, so there is no dnf module disable postgresql step on this release.

2. Prerequisites

RequirementDetail
OSRocky Linux 10.2 (AlmaLinux 10.2 and RHEL 10.2 behave the same)
Accesssudo privileges
NetworkOutbound access to the Rocky mirrors (and PGDG if you use it)
SELinuxEnforcing; leave it that way
Existing PostgreSQLNone. If an older cluster exists in /var/lib/pgsql/data, stop and plan a major-version upgrade instead

Warning: Never run postgresql-setup --initdb on a server that already has a PostgreSQL data directory. It creates a new cluster; it is not an upgrade tool.

3. Step 1: Check your Rocky Linux release

cat /etc/os-release | grep -E 'PRETTY_NAME|VERSION_ID'
uname -m
sudo dnf makecache --refresh

Expected output includes Rocky Linux 10.2 (Red Quartz) and x86_64. Then check that the package is available:

dnf info postgresql18-server
dnf list --available 'postgresql18*'

You should see postgresql18-server from the appstream repository, along with postgresql18, postgresql18-contrib, and, depending on your repositories, extension packages such as pgvector and PostGIS builds.

If the package is missing, update to 10.2 first (sudo dnf -y update), confirm AppStream is enabled with dnf repolist, or use the PGDG method below.

4. Step 2: Install PostgreSQL 18 (native AppStream)

sudo dnf install -y postgresql18-server postgresql18-contrib
rpm -q postgresql18-server

postgresql18-contrib provides extensions such as pgcrypto and pg_stat_statements. Related packages you may want later:

PackagePurpose
postgresql18Client tools (psql, pg_dump)
postgresql18-serverThe database server
postgresql18-contribBundled extensions
postgresql18-develHeaders for building extensions
postgresql18-docsDocumentation

5. Step 3: Initialize and start the server

sudo postgresql-setup --initdb

This creates /var/lib/pgsql/data with postgresql.conf, pg_hba.conf, and the postgres, template0, and template1 databases. Locale, encoding, and checksum settings are fixed at this moment, so decide on them first if you need something unusual.

Enable at boot and start now:

sudo systemctl enable --now postgresql.service
systemctl status postgresql.service --no-pager

You should see active (running) and a process like /usr/bin/postgres -D /var/lib/pgsql/data. If it fails, read the log:

sudo journalctl -u postgresql.service --no-pager -n 50

6. Step 4: Verify the installation

sudo -u postgres pg_isready
# /var/run/postgresql:5432 - accepting connections

sudo -u postgres psql -c 'SELECT version();'

Check the server version rather than only psql --version, which reports the client binary found on your PATH.

Inspect the effective settings:

sudo -u postgres psql -c "
SELECT name, setting FROM pg_settings
WHERE name IN ('server_version','data_directory','config_file','hba_file',
               'port','listen_addresses','data_checksums','password_encryption')
ORDER BY name;"

A fresh PostgreSQL 18 cluster shows data_checksums = on, listen_addresses = localhost, and password_encryption = scram-sha-256.

7. Step 5: Create a role and database

Keep three identities separate:

IdentityWhat it is
Linux user postgresOS account that owns the server process and data files
PostgreSQL role postgresDatabase superuser
Application roles (for example appuser)Least-privilege accounts your software uses
sudo -u postgres psql
CREATE ROLE appuser LOGIN;
\password appuser
CREATE DATABASE appdb OWNER appuser;
\q

\password prompts for the password interactively, so it never lands in shell history or the SQL log. Confirm:

sudo -u postgres psql -c '\du'
sudo -u postgres psql -c '\l appdb'

Enable a contrib extension in your database to test the contrib package:

sudo -u postgres psql -d appdb -c 'CREATE EXTENSION IF NOT EXISTS pgcrypto;'

8. Step 6: Allow remote connections securely

Remote access has three layers. All three must allow the connection.

 +-----------+      +-------------+      +--------------------+      +-------------+ |  Client   | ---> |  firewalld  | ---> | postgresql.conf    | ---> | pg_hba.conf |
 | 10.0.5.20 |      | TCP 5432 for|      | listen_addresses   |      | host appdb  |
 +-----------+      | 10.0.5.0/24 |      | = server's address |      | appuser     |
                    +-------------+      +--------------------+      | scram-sha-  |
                                                                     | 256         |
                                                                     +-------------+

1. Listen on a network address. Edit /var/lib/pgsql/data/postgresql.conf:

listen_addresses = 'localhost,192.168.10.20'   # your server's IP, not '*' unless you must

2. Authorize the client network. Add a narrow rule to /var/lib/pgsql/data/pg_hba.conf:

# TYPE  DATABASE  USER     ADDRESS           METHOD
host    appdb     appuser  192.168.10.0/24   scram-sha-256

Never use host all all 0.0.0.0/0 trust.

3. Validate and apply. listen_addresses needs a restart; pg_hba.conf only a reload.

sudo -u postgres psql -c "SELECT line_number, type, database, user_name, address, auth_method, error FROM pg_hba_file_rules;"
sudo systemctl restart postgresql.service

The error column should be empty for your new rule. Check the listener:

ss -ltn | grep ':5432'

On a fresh native install, TCP connections to 127.0.0.1 may match an ident rule while socket connections use peer. If password login over localhost fails, inspect the generated pg_hba.conf and add an explicit scram-sha-256 line instead of relying on defaults.

9. Step 7: firewalld

Open PostgreSQL only to the networks that need it.

# Option A: open to the active zone (simple, broader)
sudo firewall-cmd --permanent --add-service=postgresql
sudo firewall-cmd --reload

# Option B: restrict to one subnet (recommended)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" service name="postgresql" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Test from a client machine:

psql -h 192.168.10.20 -U appuser -d appdb -c 'SELECT current_database(), current_user;'

More recipes are in firewalld on Rocky Linux 10: Zones, Rich Rules & Real-World Recipes.

10. SELinux: custom ports and data directories

The packaged policy already labels the default port 5432 and the default data directory. You only need SELinux changes when you move things.

Custom port (for example 5433):

sudo semanage port -a -t postgresql_port_t -p tcp 5433
sudo semanage port -l | grep postgresql

If semanage is missing: sudo dnf install -y policycoreutils-python-utils.

Custom data directory (for example a dedicated disk mounted at /data/pgsql):

sudo semanage fcontext -a -t postgresql_db_t "/data/pgsql(/.*)?"
sudo restorecon -Rv /data/pgsql
ls -ldZ /data/pgsql

Then point the service at the new location with a systemd override (sudo systemctl edit postgresql.service) or an initdb in the new path, depending on your setup.

Diagnosing denials:

sudo ausearch -m avc -ts recent | grep postgres

Never disable SELinux to make PostgreSQL work. Our SELinux troubleshooting guide for Rocky Linux 10 shows how to read and fix denials safely.

11. Alternative: install from PGDG

Use PGDG only if you need several major versions on one host, PGDG-only extensions, or the community packaging lifecycle.

sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-10-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf makecache --refresh
dnf repolist --enabled | grep -i pgdg

dnf info postgresql18-server        # repository should be pgdg18, not appstream
sudo dnf install -y postgresql18-server postgresql18-contrib

sudo /usr/pgsql-18/bin/postgresql-18-setup initdb
sudo systemctl enable --now postgresql-18.service

With PGDG, use the full binary path for client tools, for example sudo -u postgres /usr/pgsql-18/bin/psql, and the data directory is /var/lib/pgsql/18/data. Do not run dnf module disable postgresql on EL 10; that is an EL 9 step.

12. What is new in PostgreSQL 18 for fresh installs

ChangeWhat it means for you
Data checksums on by default for new clustersSilent disk corruption is detected; small CPU cost
MD5 password authentication deprecatedUse SCRAM (scram-sha-256) for new roles and pg_hba.conf rules
New configurations should avoid MD5 entriesMigrate old roles by resetting their passwords under SCRAM

Major-version upgrades from 16 or 17 need pg_upgrade or dump/restore, not this guide.

13. Updating and uninstalling

Minor updates within version 18:

sudo dnf upgrade 'postgresql18*'
sudo systemctl restart postgresql.service
sudo -u postgres psql -c 'SHOW server_version;'

Uninstall (back up first; this deletes data if you remove the directory):

sudo systemctl disable --now postgresql.service
sudo dnf remove -y postgresql18-server postgresql18-contrib postgresql18
sudo rm -rf /var/lib/pgsql/data      # permanently deletes all databases

For PGDG, use postgresql-18.service and remove /var/lib/pgsql/18/data.

14. Troubleshooting

SymptomLikely causeFix
No match for argument: postgresql18-serverRocky release older than 10.2, AppStream disabled, or stale metadatasudo dnf -y update; dnf repolist; dnf makecache --refresh
postgresql-setup: command not foundYou installed PGDG packagesUse /usr/pgsql-18/bin/postgresql-18-setup initdb
postgresql-18.service not foundYou installed native packagesUse postgresql.service
Service fails right after startCluster not initializedRun the matching initdb helper
initdb refuses: directory not emptyExisting cluster or leftover filesIdentify what is there; never delete blindly
FATAL: Peer authentication failed for user "appuser"OS user does not match role on a socket connectionUse -h 127.0.0.1 with a password rule, or sudo -u postgres
Password login over 127.0.0.1 failsDefault ident rule for TCP localhostAdd a host ... 127.0.0.1/32 scram-sha-256 rule above it and reload
no pg_hba.conf entry for hostNo matching rule for client IPAdd a narrow CIDR rule and reload
Connection refused from other hostStill listening on localhost onlySet listen_addresses and restart
Connection timed outfirewalld blocking port 5432Add service or rich rule, then reload
port 5432 already in useAnother PostgreSQL instancess -ltnp | grep 5432; stop or change the port
Custom port fails with SELinux denialPort not labeledsemanage port -a -t postgresql_port_t -p tcp <port>
Custom data dir permission deniedWrong SELinux context or ownershipsemanage fcontext + restorecon -Rv; chown postgres:postgres
psql --version shows a different versionAnother client first in PATHCompare with SHOW server_version;
database files are incompatible with serverData from another major versionUse pg_upgrade; do not point v18 at v16 data
extension "x" is not availableExtension package missingInstall the matching postgresql18-* package

15. FAQ

Native AppStream or PGDG on Rocky Linux 10?
Use native packages when postgresql18-server is available, as it is on 10.2: fewer moving parts and distribution-managed updates. Choose PGDG for multiple parallel major versions or PGDG-only extensions.

Can I install PostgreSQL 17 or 16 instead?
Yes, from PGDG (postgresql17-server, postgresql16-server) or other distribution packages, depending on your release. Use their versioned initdb helpers and service names.

Why does psql report a different version than the server?
psql --version shows the client binary on your PATH. Run SELECT version(); against the running server.

Should I allow listen_addresses = '*'?
Only if you also restrict access with pg_hba.conf and firewalld. A specific address is safer.

How do I back up PostgreSQL?
Start with pg_dump for logical backups, then move to continuous archiving. See PostgreSQL Backup with pgBackRest.

How do I add a standby server?
Follow PostgreSQL Streaming Replication on Rocky Linux 10.

Can I run PostgreSQL in a container instead?
Yes. See How to Install Docker on Rocky Linux 10 with SELinux for the container runtime side.

(Visited 3 times, 2 visits today)

You may also like