Fedora packages PostgreSQL itself, so the first decision is whether to use those packages or the PGDG repository from the PostgreSQL project. On Fedora 45 that choice is already made, because PGDG has not published a Fedora 45 tree yet. The distribution packages are also the only path that survives a release upgrade without manual surgery.
We install PostgreSQL from the default repositories, initialise the cluster and fix the Ident authentication failed error every fresh install hits. Then we open the server to an application subnet and test from a second host.
After that come PGDG on Fedora 44 and its two traps, a major upgrade from 16 to 18, the collation warning after a Fedora 44 to 45 upgrade, and a data directory move with SELinux enforcing. Every command ran in October 2026 on Fedora 45 and Fedora 44 with SELinux in enforcing mode.
Choose a PostgreSQL version
Both releases default to PostgreSQL 18 and ship the two previous majors as versioned packages. Upstream support dates come from the PostgreSQL versioning policy.
| PostgreSQL major | Fedora 45 package | Fedora 44 package | Upstream support ends |
|---|---|---|---|
| 18 | postgresql-server (default) | postgresql-server (default) | November 2030 |
| 17 | postgresql17-server | postgresql17-server | November 2029 |
| 16 | postgresql16-server | postgresql16-server | November 2028 |
List the server packages your release offers.
dnf list --available 'postgresql*-server'
Fedora 45 returns the three supported majors plus a development build of the next one.
Available packages
postgresql-server.i686 18.3-12.fc45 fedora
postgresql-server.x86_64 18.3-12.fc45 fedora
postgresql16-server.i686 16.14-5.fc45 fedora
postgresql16-server.x86_64 16.14-5.fc45 fedora
postgresql17-server.i686 17.9-10.fc45 fedora
postgresql17-server.x86_64 17.9-10.fc45 fedora
postgresql19-server.i686 19beta1-6.fc45 fedora
postgresql19-server.x86_64 19beta1-6.fc45 fedora
Leave postgresql19-server alone on anything that holds real data. On Fedora 44 the same query returned 18.6, 17.11 and 16.15 from updates.
Unlike PGDG, Fedora’s packages are not parallel installs. Every server package provides postgresql-server-any and conflicts with the others. All of them use the same postgresql.service unit and the same /var/lib/pgsql/data directory, so asking for 17 next to an installed 18 fails.
Failed to resolve the transaction:
Problem: problem with installed package
- installed package postgresql-server-18.3-12.fc45.x86_64 conflicts with postgresql-server-any provided by postgresql17-server-17.9-10.fc45.x86_64 from fedora
New servers should take 18. Pick 17 or 16 only when an application or extension is certified for nothing newer, and replace postgresql-server with that package name in the commands below.
Install PostgreSQL server
Install the server and the contrib modules. Contrib carries pg_stat_statements, pgcrypto and amcheck, which most production setups end up loading.
sudo dnf install -y postgresql-server postgresql-contrib
Its client comes in as a dependency.
Installing:
postgresql-contrib x86_64 0:18.3-12.fc45 fedora 3.6 MiB
postgresql-server x86_64 0:18.3-12.fc45 fedora 32.1 MiB
Installing dependencies:
libxslt x86_64 0:1.1.43-10.fc45 fedora 471.8 KiB
postgresql x86_64 0:18.3-12.fc45 fedora 8.3 MiB
postgresql-private-libs x86_64 0:18.3-12.fc45 fedora 379.9 KiB
uuid x86_64 0:1.6.2-70.fc45 fedora 128.4 KiB
Fedora does not create a cluster at install time. Initialise it with the packaged helper, which runs initdb with the right paths, SELinux labels and log directory.
sudo postgresql-setup --initdb
It reports where the cluster and its log went.
* Initializing database in '/var/lib/pgsql/data'
* Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log
Start the service and enable it at boot.
sudo systemctl enable --now postgresql
Then confirm the unit is running and ask the server for its version.
systemctl status postgresql --no-pager
sudo -u postgres psql -c 'SELECT version();'
Those three io worker processes are new in 18. They are the default asynchronous I/O method, so seeing them is expected.

A new cluster uses UTF8, stores passwords as scram-sha-256, keeps data in /var/lib/pgsql/data and listens on localhost only. Data checksums are on by default from 18, which matters later during upgrades.
Create a database and fix “Ident authentication failed”
Create an application role with a password, then a database it owns. createuser prompts for the password twice.
sudo -u postgres createuser --pwprompt appuser
sudo -u postgres createdb -O appuser appdb
Now try to log in as that role, first over the socket and then over TCP.
psql -U appuser -d appdb -c 'SELECT 1;'
psql -h 127.0.0.1 -U appuser -d appdb -c 'SELECT 1;'
Neither works. Both errors confuse anyone who has not read the default Fedora pg_hba.conf.
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "appuser"
psql: error: connection to server at "127.0.0.1", port 5432 failed: FATAL: Ident authentication failed for user "appuser"
Below is the same session in the terminal, with the matching server log lines.

The server log names the culprit. postgresql-setup runs initdb --auth=ident, so local socket logins use peer and TCP logins on localhost use ident.
sudo grep -Ev '^#|^$' /var/lib/pgsql/data/pg_hba.conf
Out of the box the file holds six rules.
local all all peer
host all all 127.0.0.1/32 ident
host all all ::1/128 ident
local replication all peer
host replication all 127.0.0.1/32 ident
host replication all ::1/128 ident
peer only lets an operating system user in as the database role of the same name. That’s why sudo -u postgres psql works.
ident asks an identd daemon on port 113, and Fedora does not run one, so it always fails. Keep peer on the socket for administration and switch the TCP rules to passwords.
sudo sed -i -E '/^host/ s/ident$/scram-sha-256/' /var/lib/pgsql/data/pg_hba.conf
A reload or restart applies the change. We restart in the next section anyway, so the login test follows there.
Allow remote connections
Two settings control remote access. listen_addresses decides which interfaces the server binds to, and pg_hba.conf decides who may log in.
Add a rule for the application subnet first. It only admits appuser to appdb.
echo 'host appdb appuser 10.0.1.0/24 scram-sha-256' | sudo tee -a /var/lib/pgsql/data/pg_hba.conf
Set listen_addresses with ALTER SYSTEM instead of editing postgresql.conf. It lands in postgresql.auto.conf, which is easy to audit. Changing it needs a restart.
sudo -u postgres psql -c "ALTER SYSTEM SET listen_addresses = '*';"
sudo systemctl restart postgresql
Check the rules as the server parsed them. A typo shows up in the error column instead of silently locking people out.
sudo -u postgres psql -c 'SELECT type, database, user_name, address, netmask, auth_method, error FROM pg_hba_file_rules;'
All seven rules loaded, and the error column is empty.
type | database | user_name | address | netmask | auth_method | error
-------+---------------+-----------+-----------+-----------------------------------------+---------------+-------
local | {all} | {all} | | | peer |
host | {all} | {all} | 127.0.0.1 | 255.255.255.255 | scram-sha-256 |
host | {all} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256 |
local | {replication} | {all} | | | peer |
host | {replication} | {all} | 127.0.0.1 | 255.255.255.255 | scram-sha-256 |
host | {replication} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256 |
host | {appdb} | {appuser} | 10.0.1.0 | 255.255.255.0 | scram-sha-256 |
(7 rows)
Confirm the listener moved off localhost and that a password login over TCP now works.
ss -tln | grep 5432
psql -h 127.0.0.1 -U appuser -d appdb -c 'SELECT current_user, inet_server_addr();'
Now the server binds every IPv4 and IPv6 address, and appuser gets in with its password.
LISTEN 0 200 0.0.0.0:5432 0.0.0.0:*
LISTEN 0 200 [::]:5432 [::]:*
current_user | inet_server_addr
--------------+------------------
appuser | 127.0.0.1
(1 row)
Open port 5432 in firewalld
What the firewall does depends on the Fedora edition. The Workstation zone, FedoraWorkstation, already allows ports 1025 to 65535, so 5432 is reachable the moment PostgreSQL listens on it.
On Fedora Server, the FedoraServer zone doesn’t open that range. On Server, --get-default-zone prints FedoraServer.
Cloud images ship without firewalld at all, so either rely on the provider security group or install it. The public zone keeps SSH on port 22 open, so enabling it won’t lock you out. If sshd listens on a different port, add that port first. On a Cloud image, run this.
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
Check the active zone and what it allows.
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-services
On our Cloud-based test server, only SSH, mDNS and DHCPv6 were allowed.
public
dhcpv6-client mdns ssh
From the application host app01 (10.0.1.51), a connection to the server at 10.0.1.50 is rejected. “No route to host” is what a firewalld reject looks like from the client side. It is not a routing problem.
psql: error: connection to server at "10.0.1.50", port 5432 failed: No route to host
Is the server running on that host and accepting TCP/IP connections?
firewalld ships a postgresql service definition. Add it permanently and reload.
sudo firewall-cmd --permanent --add-service=postgresql
sudo firewall-cmd --reload
Adding the service opens 5432 to the whole zone, and only pg_hba.conf narrows it. To admit just the application subnet at the firewall as well, replace the service with a rich rule.
sudo firewall-cmd --permanent --remove-service=postgresql
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" service name="postgresql" accept'
sudo firewall-cmd --reload
On Workstation the port is already open, so tighten instead. Bind listen_addresses to the one interface the application uses, or move that interface to a stricter zone. The firewalld guide covers zones and rich rules.
Run the test again from app01. It only needs the client package, sudo dnf install -y postgresql.
psql -h 10.0.1.50 -U appuser -d appdb -c 'SELECT current_user, inet_client_addr(), version();'
Our server sees the client address and answers.
current_user | inet_client_addr | version
--------------+------------------+--------------------------------------------------------------------------------------------------------------
appuser | 10.0.1.51 | PostgreSQL 18.3 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 16.2.1 20260819 (Red Hat 16.2.1-2), 64-bit
(1 row)
Our pg_hba.conf rule is scoped to one database, so the same user asking for postgres is refused. Expect this error whenever a rule is missing.
psql: error: connection to server at "10.0.1.50", port 5432 failed: FATAL: no pg_hba.conf entry for host "10.0.1.51", user "appuser", database "postgres", no encryption
“no encryption” means the session would be plain text. For anything that leaves the host, add TLS with the PostgreSQL SSL guide and switch the rule type from host to hostssl.
Use the PGDG repository instead
PGDG publishes every minor release on the day it ships. It installs each major side by side, under /usr/pgsql-18 with its own postgresql-18 unit and /var/lib/pgsql/18/data, and it carries extension builds Fedora does not.
On Fedora 45 it isn’t an option yet. Its repository package URL returns 404.
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/F-$(rpm -E %fedora)-x86_64/pgdg-fedora-repo-latest.noarch.rpm
Fedora 45 gets nothing back.
Failed to download files
Librepo error: Status code: 404 for https://download.postgresql.org/pub/repos/yum/reporpms/F-45-x86_64/pgdg-fedora-repo-latest.noarch.rpm
That same command works on Fedora 44 and adds one repository per major from 14 to 18. Before installing anything from it, exclude PostgreSQL from the Fedora repositories.
sudo dnf config-manager setopt fedora.excludepkgs='postgresql*' updates.excludepkgs='postgresql*'
Skip that line and you hit two problems. The Fedora postgresql-server also provides postgresql18-server, and the Fedora client package obsoletes the PGDG postgresql18.
On a host that already has the Fedora psql, dnf install postgresql18-server quietly installs the Fedora server and skips PGDG.
Installing:
postgresql-server x86_64 0:18.6-1.fc44 updates 32.2 MiB
Skipping packages with broken dependencies:
postgresql18-server x86_64 18.6-4PGDG.f44 pgdg18 31.1 MiB
It gets worse in reverse. On a working PGDG server, installing the Fedora postgresql client, directly or as another package’s dependency, replaces the PGDG server binaries.
Installing:
postgresql x86_64 0:18.6-1.fc44 updates 8.4 MiB
replacing postgresql18 x86_64 0:18.6-4PGDG.f44 pgdg18 11.1 MiB
postgresql-contrib x86_64 0:18.6-1.fc44 updates 3.6 MiB
replacing postgresql18-contrib x86_64 0:18.6-4PGDG.f44 pgdg18 2.7 MiB
postgresql-server x86_64 0:18.6-1.fc44 updates 32.2 MiB
replacing postgresql18-server x86_64 0:18.6-4PGDG.f44 pgdg18 31.1 MiB
With the exclude in place, install and initialise the PGDG build. Its setup script and unit names carry the major version.
sudo dnf install -y postgresql18-server postgresql18-contrib
sudo /usr/pgsql-18/bin/postgresql-18-setup initdb
sudo systemctl enable --now postgresql-18
Ask the server for its version with sudo -u postgres psql -c 'SELECT version();'. You’ll see x86_64-pc-linux-gnu for the PGDG build, where Fedora’s says redhat-linux-gnu.
PostgreSQL 18.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 16.2.1 20260819 (Red Hat 16.2.1-2), 64-bit
Remember what you signed up for when it’s time to upgrade Fedora 44 to 45. The PGDG repositories are skipped as unavailable, and the transaction stops on a PGDG package linked against the Fedora 44 Perl library.
Failed to resolve the transaction:
Problem: installed package postgresql18-contrib-18.6-4PGDG.f44.x86_64 requires libperl.so.5.42()(64bit), but none of the providers can be installed
- perl-libs-4:5.42.3-525.fc44.x86_64 does not belong to a distupgrade repository
A PGDG host stays on Fedora 44 until PGDG publishes fedora-45-x86_64, or until you move it to the Fedora packages with a dump and restore. Check https://download.postgresql.org/pub/repos/yum/18/fedora/ for that directory before planning the upgrade.
Upgrade PostgreSQL 16 or 17 to 18
Fedora handles major upgrades with postgresql-setup --upgrade, which wraps pg_upgrade. The old binaries come from postgresql-upgrade, which bundles the 16 and 17 engines.
Our test server ran postgresql16-server with a 100,000 row table. Take a pg_dumpall first. The PostgreSQL backup and PITR guide covers the full approach. Then stop the server and swap packages.
sudo systemctl stop postgresql
sudo dnf swap -y postgresql16-server postgresql-server --allowerasing
sudo dnf install -y postgresql-upgrade postgresql-contrib
Swapping removes the old contrib package and disables the service. The scriptlet says so.
>>> Running %post scriptlet: postgresql-server-0:18.3-12.fc45.x86_64
>>> Finished %post scriptlet: postgresql-server-0:18.3-12.fc45.x86_64
>>> Scriptlet output:
>>> Removed '/etc/systemd/system/multi-user.target.wants/postgresql.service'.
List the upgrade sources. The ID for 16 is postgresql16, and plain postgresql means 17.
sudo postgresql-setup --upgrade-ids
Two sources are available.
postgresql - Upgrade data from system PostgreSQL version (PostgreSQL 17)
postgresql16 - Upgrade data from system PostgreSQL version (PostgreSQL 16)
The obvious command fails on any cluster created before 18. New clusters get data checksums by default, and pg_upgrade will not mix the two.

Pass --data-checksums to enable them on the old cluster before the upgrade, or --no-data-checksums to keep them off. Enabling them reads and rewrites every data page.
It took seconds on our test set, but it scales with database size. Checksums catch silent storage corruption, so take the time unless the maintenance window cannot absorb it.
sudo postgresql-setup --upgrade --upgrade-from=postgresql16 --data-checksums
Read the warning it prints. The upgrade installs fresh postgresql.conf and pg_hba.conf files and leaves yours in /var/lib/pgsql/data-old. Bring your access rules back before starting the service, or remote clients lose access.
listen_addresses was set with ALTER SYSTEM, so it lives in postgresql.auto.conf, not postgresql.conf. Copy both files, then review postgresql.auto.conf for parameters the new major no longer accepts.
sudo -u postgres cp /var/lib/pgsql/data-old/pg_hba.conf /var/lib/pgsql/data-old/postgresql.auto.conf /var/lib/pgsql/data/
Edits made directly in the old postgresql.conf need the same treatment. Compare it with diff against the new file and carry the changes over by hand. Then enable the service again and rebuild planner statistics, which pg_upgrade does not carry over in full.
sudo systemctl enable --now postgresql
sudo -u postgres vacuumdb --all --analyze-in-stages --missing-stats-only
Our upgraded server reported 18.3 with checksums on, and all 100,000 rows were present. Once the application has run cleanly for a while, run /var/lib/pgsql/delete_old_cluster.sh as postgres to reclaim the space held by data-old.
Fix the collation version mismatch after Fedora 45
Fedora 44 and 45 both default to PostgreSQL 18, so a release upgrade needs no pg_upgrade. It does change glibc from 2.43 to 2.44, and PostgreSQL records the glibc version each database was created with.
We put a Fedora 44 server holding a database with 50,000 rows and a text index through dnf system-upgrade. On that day, the Fedora 45 repository carried 18.3 while Fedora 44 updates had 18.6, so the transaction listed the server under “Downgrading”.
Minor releases share the on-disk format, and the cluster came up without complaint. sudo dnf upgrade moves it forward again once newer builds reach Fedora 45.
Your first connection to each database after the reboot prints a warning.
WARNING: database "shop" has a collation version mismatch
DETAIL: The database was created using collation version 2.43, but the operating system provides version 2.44.
HINT: Rebuild all objects in this database that use the default collation and run ALTER DATABASE shop REFRESH COLLATION VERSION, or build PostgreSQL with the right library version.
Don’t treat that warning as noise. If glibc changed the sort order of any characters in your data, B-tree indexes on text columns are now ordered differently from what the server expects.
Lookups can then miss rows that exist, and unique constraints can let duplicates through. Rebuild the indexes in every database, then record the new version.
sudo -u postgres reindexdb --all
for db in $(sudo -u postgres psql -Atc 'SELECT datname FROM pg_database WHERE datallowconn' 2>/dev/null); do sudo -u postgres psql -qc "ALTER DATABASE \"$db\" REFRESH COLLATION VERSION;" 2>&1 | grep -v -e WARNING -e DETAIL -e HINT; done
Each database reports the version change, and the stored and actual versions match afterwards.

reindexdb takes locks that block writes to each table while its indexes rebuild. On a large database, schedule it, or use reindexdb --all --concurrently. That avoids the write lock, but it skips system catalogs and takes longer.
Indexes are the usual casualty, but the PostgreSQL docs ask for every object that depends on the collation to be rebuilt. That includes text range or list partition keys, CHECK constraints that compare strings, and materialized views.
Don’t just run REFRESH COLLATION VERSION to silence the warning. It only updates the stored number, and any misordered index stays broken.
Move the data directory with SELinux enforcing
Moving the cluster to a dedicated disk is common, and SELinux is where it goes wrong. The service reads PGDATA from its unit, so point it there with a drop-in after copying the data.
sudo systemctl stop postgresql
sudo mkdir -p /srv/pgsql
sudo cp -a /var/lib/pgsql/data /srv/pgsql/
sudo mkdir -p /etc/systemd/system/postgresql.service.d
printf '[Service]\nEnvironment=PGDATA=/srv/pgsql/data\n' | sudo tee /etc/systemd/system/postgresql.service.d/datadir.conf
sudo systemctl daemon-reload
sudo systemctl start postgresql
It starts, and that’s the trap. cp -a copied the postgresql_db_t label along with the files, but the policy has no rule for /srv/pgsql. The next restorecon or full relabel resets the files to var_t, and the following restart fails.
postgres: could not access the server configuration file "/srv/pgsql/data/postgresql.conf": Permission denied
postgresql.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
postgresql.service: Failed with result 'exit-code'.
Make the label permanent by declaring /srv/pgsql equivalent to /var/lib/pgsql. semanage comes from policycoreutils-python-utils, which minimal installs lack.
sudo dnf install -y policycoreutils-python-utils
sudo semanage fcontext -a -e /var/lib/pgsql /srv/pgsql
sudo restorecon -R /srv/pgsql
sudo systemctl restart postgresql
Our equivalence rule survives relabels. Confirm it, and confirm the server runs from the new path.
sudo semanage fcontext -l -C
sudo -u postgres psql -Atc 'SHOW data_directory;'
Both checks agree.
SELinux Local fcontext Equivalence
/srv/pgsql = /var/lib/pgsql
/srv/pgsql/data
Remove /var/lib/pgsql/data only after a restart from the new location has worked. postgresql-setup --upgrade reads the same PGDATA, so the drop-in also covers the next major upgrade.
From here, this single server is the base for most of what follows. Add vector search with pgvector, or build out PostgreSQL high availability with Patroni, etcd and HAProxy when one node isn’t enough.
For a GUI, pgAdmin in Podman runs well on the same Fedora host. If the application needs MySQL compatibility instead, see MariaDB on Fedora.