2017-10-26 21:20:01 +00:00
= PostgreSQL
[[installation]]
2018-07-29 11:01:46 +00:00
== Installation
2017-10-26 21:20:01 +00:00
The installation and initialization of the postgresql server is a little
2021-12-31 17:32:46 +00:00
bit different in comparison to other packages and other Linux distros.
2017-10-26 21:20:01 +00:00
This document aims to summarize basic installation steps relevant to
2021-12-31 17:38:19 +00:00
recent Fedora Linux releases.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2021-01-27 10:06:55 +00:00
sudo dnf install postgresql-server postgresql-contrib
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2022-01-01 19:39:54 +00:00
The postgresql server is not running and disabled by default. To set it to start at boot, run:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2022-01-01 19:39:54 +00:00
sudo systemctl enable postgresql
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2021-12-31 07:18:49 +00:00
The database needs to be populated with initial data after installation. The database initialization could be done using following command. It
creates the configuration files postgresql.conf and pg_hba.conf
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2021-12-31 07:18:49 +00:00
sudo postgresql-setup --initdb --unit postgresql
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2022-01-01 19:39:54 +00:00
To start the postgresql server manually, run
2020-10-13 06:18:28 +00:00
....
2021-12-31 07:18:49 +00:00
sudo systemctl start postgresql
....
[[user-creation-and-database-creation]]
== User Creation and Database Creation
2021-12-31 17:32:46 +00:00
Now you need to create a user and database for the user. This needs to be run from a `postgres` user account on your system.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2021-12-31 17:32:46 +00:00
sudo -u postgres psql
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2022-01-01 19:39:54 +00:00
From here you can create a postgres user and database. Here, we will assume your computer's user account is called `lenny`. Note: you can also run this from the shell as well with `createuser lenny` and `createdb --owner=lenny carl`.
2021-12-31 07:18:49 +00:00
....
postgres=# CREATE USER lenny WITH PASSWORD 'leonard';
2022-01-01 19:39:54 +00:00
postgres=# CREATE DATABASE my_project OWNER lenny;
2021-12-31 07:18:49 +00:00
....
2021-12-31 07:31:12 +00:00
It might be good idea to add password for the `postgres` user while you're at it:
2021-12-31 07:18:49 +00:00
....
2021-12-31 07:31:12 +00:00
postgres=# \password postgres
2021-12-31 07:18:49 +00:00
....
2022-01-01 19:39:54 +00:00
Press Ctrl + D or `\q` to leave the psql session running as user `postgres`. Now you can access your new database from your user account (`lenny`) and start using it.
2021-12-31 07:31:12 +00:00
....
2022-01-01 19:39:54 +00:00
psql my_project
2021-12-31 07:18:49 +00:00
....
2021-12-31 09:15:50 +00:00
[[initial configuration]]
== Initial Configuration
2021-12-31 07:18:49 +00:00
The postgresql server is using two main configuration files
* /var/lib/pgsql/data/postgresql.conf
* /var/lib/pgsql/data/pg_hba.conf
2021-12-31 07:31:12 +00:00
If you’ re getting ident errors from your app you’ ll probably need to perform the accepted solution described at https://serverfault.com/questions/406606/postgres-error-message-fatal-ident-authentication-failed-for-user?newreg=a4fdc3e21349449985cc65b82399c5b4
....
sudo gedit /var/lib/pgsql/data/pg_hba.conf
....
2021-12-31 09:15:50 +00:00
and edit `host all all 127.0.0.1/32 ident` to `host all all 127.0.0.1/32 md5`. This should allow most applications to connect with username/password.
2021-12-31 07:31:12 +00:00
2021-12-31 07:18:49 +00:00
2017-10-26 21:20:01 +00:00
[[upgrade]]
2018-07-29 11:01:46 +00:00
== Upgrade
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
As you can see from the error message in my example, it is not a fresh
2022-12-29 21:42:56 +00:00
installation, but an upgrade.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
Nov 14 11:45:56 mlich-lenovo.usersys.redhat.com postgresql-check-db-dir[2108]: An old version of the database format was found.
Nov 14 11:45:56 mlich-lenovo.usersys.redhat.com postgresql-check-db-dir[2108]: Use "postgresql-setup upgrade" to upgrade to version 9.3.
....
2017-10-26 21:20:01 +00:00
2022-01-01 19:39:54 +00:00
With version 9 you can use the upgrade tool. It is packaged as `postgresql-upgrade`:
2017-10-26 21:20:01 +00:00
....
2021-01-27 10:06:55 +00:00
postgresql-setup upgrade
2017-10-26 21:20:01 +00:00
Redirecting to /bin/systemctl stop postgresql.service
Upgrading database: OK
The configuration files was replaced by default configuration.
The previous configuration and data are stored in folder /var/lib/pgsql/data-old.
See /var/lib/pgsql/pgupgrade.log for details.
....
The data are located at
* /var/lib/pgsql/data
* /var/lib/pgsql/data-old
The upgrade itself will backup your existing data and migrate your
2020-10-13 06:18:28 +00:00
database. Don't forget to migrate your configuration (with meld, for
2017-10-26 21:20:01 +00:00
example: `meld /var/lib/pgsql/data{,-old}/postgresql.conf`).
2020-10-13 06:18:28 +00:00
You may need to switch postgresql to trust mode before updating. This
2017-10-26 21:20:01 +00:00
should be fixed already.
You can also upgrade by dumping your database and loading it again. For
2020-10-13 06:18:28 +00:00
more information, see the link:#link-upgrade[official documentation].
2017-10-26 21:20:01 +00:00
[[firewall]]
2018-07-29 11:01:46 +00:00
== Firewall
2017-10-26 21:20:01 +00:00
PostgreSQL operates on port 5432 (or whatever else you set in your
`postgresql.conf`). In firewalld you can open it like this:
2020-10-13 06:18:28 +00:00
....
2021-01-27 10:06:55 +00:00
# make it last after reboot
firewall-cmd --permanent --add-port=5432/tcp
# change runtime configuration
firewall-cmd --add-port=5432/tcp
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
In the case of iptables:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2021-01-27 10:06:55 +00:00
iptables -A INPUT -p tcp --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
Bear in mind that you probably don't want to open your database server
to the whole world.
[[selinux]]
2018-07-29 11:01:46 +00:00
== SELinux
2017-10-26 21:20:01 +00:00
If you have SELinux enforced, you may run into trouble when trying to do
2020-10-13 06:18:28 +00:00
some non-standard configuration. For example, if you would like to change
2017-10-26 21:20:01 +00:00
a location of your database, you have to add new context mapping for the
new location:
2020-10-13 06:18:28 +00:00
....
2021-01-27 10:06:55 +00:00
semanage fcontext -a -t postgresql_db_t "/my/new/location(/.*)?"
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
If the default port doesn't work for you, you may need to map postgre's port type to your desired port:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2021-01-27 10:06:55 +00:00
semanage port -a -t postgresql_port_t -p tcp 5433
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
If you install a webapp that wants to communicate with PostgreSQL via
TCP/IP, you will have to tell SELinux to allow this on the webserver
host:
2020-10-13 06:18:28 +00:00
....
2021-01-27 10:06:55 +00:00
setsebool -P httpd_can_network_connect_db on
2020-10-13 06:18:28 +00:00
....
2017-10-26 21:20:01 +00:00
2021-12-31 09:15:50 +00:00
[[configuration]]
== Configuration
As mentioned above, the postgresql server is using two main configuration files
* /var/lib/pgsql/data/postgresql.conf
* /var/lib/pgsql/data/pg_hba.conf
2017-10-26 21:20:01 +00:00
[[systemd]]
2018-07-29 11:01:46 +00:00
=== systemd
2017-10-26 21:20:01 +00:00
Some configuration parameters are passed to daemon via command line
2020-10-13 06:18:28 +00:00
options. This behaviour may override settings in `postgresql.conf`. For
2017-10-26 21:20:01 +00:00
example, if you want to change the server's port number to 5433, create
2020-10-13 06:18:28 +00:00
a file named `/etc/systemd/system/postgresql.service` containing:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
.include /lib/systemd/system/postgresql.service
[Service]
Environment=PGPORT=5433
....
2017-10-26 21:20:01 +00:00
Note: changing PGPORT or PGDATA will typically require adjusting SELinux
configuration as well; see section selinux.
Please follow the systemd documentation
2018-02-26 16:43:59 +00:00
http://fedoraproject.org/wiki/systemd#How_do_I_customize_a_unit_file.2F_add_a_custom_unit_file.3F[2]
2017-10-26 21:20:01 +00:00
for more details.
[[postgresql.conf]]
2018-07-29 11:01:46 +00:00
=== postgresql.conf
2017-10-26 21:20:01 +00:00
If you want postgres to accept network connections, you should change
2020-10-13 06:18:28 +00:00
....
listen_addresses = 'localhost'
....
2017-10-26 21:20:01 +00:00
to
2020-10-13 06:18:28 +00:00
....
listen_addresses = '*'
....
2017-10-26 21:20:01 +00:00
[[pg_hba.conf]]
2018-07-29 11:01:46 +00:00
=== pg_hba.conf
2017-10-26 21:20:01 +00:00
Once your database is set up, you need to configure access to your
database server. This may be done by editing file
`/var/lib/pgsql/data/pg_hba.conf`. There are rules like this in the
file:
2020-10-13 06:18:28 +00:00
....
# TYPE DATABASE USER ADDRESS METHOD
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
local all postgres peer
....
2017-10-26 21:20:01 +00:00
First field stands for connection type. It can have these values:
* *local* — Unix-domain socket
* *host* — plain or SSL-encrypted TCP/IP socket
2020-10-13 06:18:28 +00:00
* *hostssl* — an SSL-encrypted TCP/IP socket
2017-10-26 21:20:01 +00:00
* *hostnossl* — plain TCP/IP socket
Last column specifies which authentication method will be used.
* *md5* — client has to supply password processed with MD5 algorithm
* *ident* — obtain user name of connecting client from operating system
2020-04-18 21:27:08 +00:00
and consult it with specified map
2017-10-26 21:20:01 +00:00
* *trust* — anyone who is able to connect to PostgreSQL server may act
2020-04-18 21:27:08 +00:00
as any user without supplying password
2017-10-26 21:20:01 +00:00
* *peer* — obtains user's name from operating system and checks if it
2020-04-18 21:27:08 +00:00
matches database user name
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
When the database server is authenticating the client, it seeks for a record with a matching connection type, client address, requested database, and user name. As soon as it finds these credentials, it performs the authentication. If the authentication fails, no more subsequent records are taken into account. If no record matches, the client's access is denied.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
The default settings are usually restricted to localhost.
2017-10-26 21:20:01 +00:00
When you install your database server and at first you try to "make it
2020-10-13 06:18:28 +00:00
work", you should turn off firewall, SELinux and make the `postgres`
authentication permissive. _Bear in mind this will greatly expose your
server, so do it [.underline]#only# on a trusted network — preferably with no network at all_:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
host all all 127.0.0.1/32 trust
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
As soon as you are able to connect, turn on the security systems one by
2017-10-26 21:20:01 +00:00
one while verifying the connection can be established.
For more information see official documentation for
link:#link-pghba[pg_hba.conf file].
2020-10-13 06:18:28 +00:00
[[optimization]]
== Optimization
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
The default configuration of postgres is severely undertuned. It can handle simple applications without consistent database access, but if you require higher performance, you should re-configure your instance. All the magic is happening in `/var/lib/pgsql/data/postgresql.conf\``. Also, the logging mechanism is not configured very intuitively.
2017-10-26 21:20:01 +00:00
[[performance]]
2018-07-29 11:01:46 +00:00
=== Performance
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
The number of clients which may be connected to PostgreSQL at the same time:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
max_connections = <number>
....
2017-10-26 21:20:01 +00:00
`shared_buffers` is the entry point. This is telling PostgreSQL how much
memory is dedicated for caching. Setting this to 25% of total memory of
your system is a good start. If it doesn't work for you, try to go for
something between 15% - 40% of total memory.
2020-10-13 06:18:28 +00:00
....
shared_buffers = <memory unit>
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
This value is used by the query planner to know how much memory is available in the system. The query planner uses this information to figure out whether the plan fits into memory or not. Setting this to 50% of total memory is a common practice.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
effective_cache_size = <memory unit>
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
When PostgreSQL performs sorting operations, it plans its strategy
2017-10-26 21:20:01 +00:00
whether to sort the query on disk or in memory. Bear in mind that this
memory is available for every sorting instance. In case of multiple
2020-10-13 06:18:28 +00:00
users submitting queries to your database server, this can ramp up
2017-10-26 21:20:01 +00:00
pretty high. Therefore this is tightly bound to `max_connections`.
2020-10-13 06:18:28 +00:00
....
work_mem = <memory unit>
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
For more information about this topic I advise you to read the
link:#link-tuning[official documentation] about tuning PostgreSQL.
2017-10-26 21:20:01 +00:00
[[logging]]
2018-07-29 11:01:46 +00:00
=== Logging
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
By default, logs are rotated every week and you might not find much
information in there. One could miss a log level, date, time, etc. Also,
for simple web applications, some prefer to increase verbosity.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
log_destination = 'stderr'
....
2017-10-26 21:20:01 +00:00
This is just fine. If you would like syslog to take care of your logs,
2020-10-13 06:18:28 +00:00
change `'stderr'` to `'syslog'`, or even `'syslog,stderr'`. If you go for
2017-10-26 21:20:01 +00:00
syslog, don't forget to configure syslog itself too; for more info, see
2020-10-13 06:18:28 +00:00
link:#link-logging[official documentation].
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
logging_collector = on
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
In case of logging to `stderr`, `postgres` will grab all the logs if you
enable the `logging_collector` option.
2017-10-26 21:20:01 +00:00
This is default option:
2020-10-13 06:18:28 +00:00
....
log_filename = 'postgresql-%a.log'
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
A preferred method could be to name log files by date when they were
2017-10-26 21:20:01 +00:00
created:
2020-10-13 06:18:28 +00:00
....
log_filename = 'postgresql-%G-%m.log
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
Rotation. This really depends on the app itself. In the case of a simple app with little data in the database, all the logs may be kept persistently on disk without rotation.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
log_truncate_on_rotation = off
log_rotation_age = 31d
....
2017-10-26 21:20:01 +00:00
Increase number of entries in log:
2020-10-13 06:18:28 +00:00
....
client_min_messages = notice # default notice
log_min_messages = info # default warning
log_min_error_statement = notice # default error
....
2017-10-26 21:20:01 +00:00
If you would like to log slow queries, feel free to use this option:
2020-10-13 06:18:28 +00:00
....
log_min_duration_statement = 1000 # in ms
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
The default log entry doesn't contain much info:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
FATAL: Ident authentication failed for user "test"
DETAIL: Connection matched pg_hba.conf line 84: "host all all ::1/128 ident"
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
Let's improve it to:
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
2013-12-30 17:51:36 CET testx@::1(50867):postgres [11213] FATAL: password authentication failed for user "testx"
2013-12-30 17:51:36 CET testx@::1(50867):postgres [11213] DETAIL: Connection matched pg_hba.conf line 84: "host all all ::1/128 md5 "
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
You just have to alter the option `log_line_prefix`.
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
# %t -- timestamp
# %u -- user
# %r -- client's host
# %d -- database
# %p -- PID
log_line_prefix = '%t %u@%r:%d [%p] '
....
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
If you are running only a single database with a single user connecting, it makes more sense to simplify the prefix to
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
log_line_prefix = '%t [%p] '
....
2017-10-26 21:20:01 +00:00
[[final-recipe]]
2018-07-29 11:01:46 +00:00
==== Final recipe
2017-10-26 21:20:01 +00:00
2020-10-13 06:18:28 +00:00
....
log_destination = 'stderr'
logging_collector = on
log_filename = 'postgresql-%G-%m.log'
log_truncate_on_rotation = off
log_rotation_age = 31d
client_min_messages = notice
log_min_messages = info
log_min_error_statement = notice
log_line_prefix = '%t %u@%r:%d [%p] '
....
2017-10-26 21:20:01 +00:00
[[reference]]
2018-07-29 11:01:46 +00:00
== Reference
2017-10-26 21:20:01 +00:00
link:PostgreSQL/README.rpm-dist[Full RPM packaging documentation]
2021-02-10 08:21:48 +00:00
https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server[Tuning
2017-10-26 21:20:01 +00:00
performance]
2021-02-10 08:21:48 +00:00
https://www.postgresql.org/docs/9.1/runtime-config-logging.html[Logging
2017-10-26 21:20:01 +00:00
configuration]
2021-02-10 08:21:48 +00:00
https://www.postgresql.org/docs/9.1/static/upgrading.html[Upgrading
2017-10-26 21:20:01 +00:00
PostgreSQL]
2021-02-10 08:21:48 +00:00
https://www.postgresql.org/docs/8.3/static/auth-pg-hba-conf.html[pg_hba.conf
2017-10-26 21:20:01 +00:00
file]
See a typo, something missing or out of date, or anything else which can be
2017-11-10 15:16:19 +00:00
improved? Edit this document at https://pagure.io/fedora-docs/quick-docs.