In the last post we’ve seen that it is quite easy to get started with PostgreSQL on OpenBSD when you install from the provided packages. The downside of this was, that not the latest version of PostgreSQL was provided, 14.2 instead of 14.5, which is the current version as of today. If you want to stay more up to date, and you really should, then you can always install PostgreSQL from source code for your own.
We’ll start again from a fresh installation but this time, the latest patches are already applied. As we need a group and a user to run PostgreSQL let’s create those:
openbsd-latest$ groupadd -g 1000 postgres
openbsd-latest$ useradd -g postgres -d /home/postgres/ -m -u 1000 postgres
As there is no sudo in OpenBSD we need to configure doas, that makes life a bit easier because we do not need to switch accounts for root related tasks:
openbsd-latest$ cat /etc/doas.conf
permit postgres as root
permit nopass keepenv postgres
Once we have that we need to download and extract the PostgreSQL source code. I’ll use wget for that:
openbsd-latest$ su - postgres
openbsd-latest$ doas pkg_add wget
quirks-5.5 signed on 2022-10-08T12:25:54Z
wget-1.21.3: ok
openbsd-latest$ wget https://ftp.postgresql.org/pub/source/v15rc2/postgresql-15rc2.tar.bz2
openbsd-latest$ bunzip2 postgresql-15rc2.tar.bz2
openbsd-latest$ tar xf postgresql-15rc2.tar
openbsd-latest$ cd postgresql-15rc2
Our Linux, the default configuration we use for the PostgreSQL source code looks like this:
./configure --prefix=${PGHOME} \
--exec-prefix=${PGHOME} \
--bindir=${PGHOME}/bin \
--libdir=${PGHOME}/lib \
--sysconfdir=${PGHOME}/etc \
--includedir=${PGHOME}/include \
--datarootdir=${PGHOME}/share \
--datadir=${PGHOME}/share \
--with-pgport=5432 \
--with-perl \
--with-python \
--with-openssl \
--with-pam \
--with-ldap \
--with-libxml \
--with-libxslt \
--with-segsize=${SEGSIZE} \
--with-blocksize=${BLOCKSIZE} \
--with-llvm LLVM_CONFIG='/usr/bin/llvm-config' \
--with-uuid=ossp \
--with-lz4 \
--with-zstd \
--with-gssapi \
--with-systemd \
--with-icu \
--with-system-tzdata=/usr/share/zoneinfo
What OS packages do we need to get a comparable build on OpenBSD? First of all, there is no PAM authentication on OpenBSD, so we can replace that with “–with-bsd-auth” and there is no systemd, no gssapi, this will give us this:
./configure --prefix=${PGHOME} \
--exec-prefix=${PGHOME} \
--bindir=${PGHOME}/bin \
--libdir=${PGHOME}/lib \
--sysconfdir=${PGHOME}/etc \
--includedir=${PGHOME}/include \
--datarootdir=${PGHOME}/share \
--datadir=${PGHOME}/share \
--with-pgport=5432 \
--with-perl \
--with-python \
--with-openssl \
--with-bsd-auth \
--with-ldap \
--with-libxml \
--with-libxslt \
--with-segsize=${SEGSIZE} \
--with-blocksize=${BLOCKSIZE} \
--with-llvm LLVM_CONFIG='/usr/bin/llvm-config' \
--with-uuid=ossp \
--with-lz4 \
--with-zstd \
--with-icu \
--with-system-tzdata=/usr/share/zoneinfo
Getting this to configure properly, we need these packages:
openbsd-latest$ doas pkg_add icu4c lz4 zstd python3 libxml libxslt openldap-client p5-ossp-UUID
Having that installed, configuration goes fine:
openbsd-latest$ PGHOME=/u01/app/postgres/product/15/db_0/
openbsd-latest$ SEGSIZE=2
openbsd-latest$ BLOCKSIZE=8
./configure --prefix=${PGHOME} \
--exec-prefix=${PGHOME} \
--bindir=${PGHOME}/bin \
--libdir=${PGHOME}/lib \
--sysconfdir=${PGHOME}/etc \
--includedir=${PGHOME}/include \
--datarootdir=${PGHOME}/share \
--datadir=${PGHOME}/share \
--with-pgport=5432 \
--with-perl \
--with-python \
--with-openssl \
--with-bsd-auth \
--with-ldap \
--with-libxml \
--with-libxslt \
--with-segsize=${SEGSIZE} \
--with-blocksize=${BLOCKSIZE} \
--with-llvm LLVM_CONFIG='/usr/bin/llvm-config' \
--with-uuid=ossp \
--with-lz4 \
--with-zstd \
--with-icu \
--with-system-tzdata=/usr/share/zoneinfo
I’ll not paste the whole output of this, but the end of the output should look like this:
checking build system type... x86_64-unknown-openbsd7.1
checking host system type... x86_64-unknown-openbsd7.1
checking which template to use... openbsd
...
config.status: linking src/backend/port/sysv_sema.c to src/backend/port/pg_sema.c
config.status: linking src/backend/port/sysv_shmem.c to src/backend/port/pg_shmem.c
config.status: linking src/include/port/openbsd.h to src/include/pg_config_os.h
config.status: linking src/makefiles/Makefile.openbsd to src/Makefile.port
Ready to compile:
openbsd-latest$ make all
You must use GNU make to build PostgreSQL.
*** Error 1 in /home/postgres/postgresql-15rc2 (Makefile:47 'all': @IFS=':' ; for dir in $PATH; do for prog in gmake gnumake make; do if ...)
OK, this seems to be obvious, we need GNU Make for this:
openbsd-latest$ doas pkg_add gmake
quirks-5.5 signed on 2022-10-08T12:25:54Z
gmake-4.3: ok
openbsd-latest$ gmake all
...
gmake[1]: Entering directory '/home/postgres/postgresql-15rc2/config'
gmake[1]: Nothing to be done for 'all'.
gmake[1]: Leaving directory '/home/postgres/postgresql-15rc2/config'
Done, so install and add the extensions, but first create the directory structure. Here you have the choice, we’ll usually do it like this to make it easier for our service desk to work on both, Oracle and PostgreSQL:
openbsd-latest$ doas mkdir -p /u01/app/postgres/local
openbsd-latest$ doas mkdir /u02
openbsd-latest$ doas mkdir /u99
openbsd-latest$ doas chown -R postgres:postgres /u01/
openbsd-latest$ doas chown postgres:postgres /u02
openbsd-latest$ doas chown postgres:postgres /u99
openbsd-latest$ doas chmod 770 /u01/app/postgres
openbsd-latest$ doas chmod 770 /u02
openbsd-latest$ doas chmod 770 /u99
The last steps to do for bringing the PostgreSQL server and the extensions onto the system:
openbsd-latest$ doas ln -s /usr/local/bin/llvm-lto /usr/bin/llvm-lto
openbsd-latest$ gmake install
Using GNU make found at /usr/local/bin/gmake
/usr/local/bin/gmake -C ./src/backend generated-headers
gmake[1]: Entering directory '/home/postgres/postgresql-15rc2/src/backend'
/usr/local/bin/gmake -C catalog distprep generated-header-symlinks
openbsd-latest$ cd contrib/
openbsd-latest$ gmake install
gmake -C ../src/backend generated-headers
gmake[1]: Entering directory '/home/postgres/postgresql-15rc2/src/backend'
gmake -C catalog distprep generated-header-symlinks
gmake[2]: Entering directory '/home/postgres/postgresql-15rc2/src/backend/catalog'
...
cd '/u01/app/postgres/product/15/db_0//lib/bitcode' && /usr/bin/llvm-lto -thinlto -thinlto-action=thinlink -o ltree_plpython3.index.bc ltree_plpython3/ltree_plpython.bc
gmake[1]: Leaving directory '/home/postgres/postgresql-15rc2/contrib/ltree_plpython'
Done. Initializing the cluster is nothing special:
openbsd-latest$ /u01/app/postgres/product/15/db_0/bin/initdb -D /u02/pgdata/15/PG1
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "C".
The default database encoding has accordingly been set to "SQL_ASCII".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory /u02/pgdata/15/PG1 ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 20
selecting default shared_buffers ... 128MB
selecting default time zone ... Europe/Berlin
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
initdb: warning: enabling "trust" authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
/u01/app/postgres/product/15/db_0/bin/pg_ctl -D /u02/pgdata/15/PG1 -l logfile start
The last step is to create a service, so PostgreSQL will start automatically when the system comes up. How does that work on OpenBSD. We’ve already seen in the last post that OpenBSD uses rc to manage system daemons. All we need to do is to create a script like this in /etc/rc.d (this is stolen from the PostgreSQL packages):
openbsd-latest$ cat /etc/rc.d/postgres
#!/bin/ksh
daemon="/u01/app/postgres/product/15/db_0/bin/pg_ctl"
daemon_flags="-D /u02/pgdata/15/PG1/ -w -l /u02/pgdata/15/PG1/log/postgresql.log"
daemon_user="postgres"
daemon_timeout=300
. /etc/rc.d/rc.subr
rc_usercheck=NO
rc_check() {
${rcexec} "${daemon} status ${daemon_flags}"
}
rc_reload() {
${rcexec} "${daemon} reload ${daemon_flags}"
}
rc_start() {
${rcexec} "${daemon} start ${daemon_flags}"
}
rc_stop() {
${rcexec} "${daemon} stop ${daemon_flags} -m fast" || \
${rcexec} "${daemon} stop ${daemon_flags} -m immediate"
}
rc_cmd $1
Enable and start the service, and that’s it:
openbsd-latest# chmod 755 /etc/rc.d/postgres
openbsd-latest# rcctl enable postgres
openbsd-latest# rcctl start postgres
openbsd-latest# /u01/app/postgres/product/15/db_0/bin/psql -U postgres postgres
psql (15rc2)
Type "help" for help.
postgres=#
Conclusion: We anyway prefer to install PostgreSQL from source code, because in that case we are independent from the package manager, whatever it is. In the case of OpenBSD it seems to be even more important, because the packages provided by the OS do not reflect the latest PostgreSQL minor version. Doing it that way is quite simple, once you figured out the required dependencies and how the init systems works.