If you need the latest version of PostgreSQL on OpenBSD, the limits for the semaphores must be increased. Indeed, let imagine you want to deploy a fresh postgresql database (assuming the /var/postgresql/data directory was not created or purged).
$ doas pkg_add postgresql-server
...
$ cd /var/postgresql
$ doas -u _postgresql initdb -D data
The files belonging to this database system will be owned by user "_postgresql".
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 enabled.
fixing permissions on existing directory data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 20
selecting default "shared_buffers" ... 400kB
selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ... 2026-09-14 17:44:41.502 UTC [93045] FATAL: could not create semaphores: No space left on device
2026-09-14 17:44:41.502 UTC [93045] DETAIL: Failed system call was semget(3810418, 17, 03600).
2026-09-14 17:44:41.502 UTC [93045] HINT: This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel
parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its "max_connections" parameter.
The PostgreSQL documentation contains more information about configuring your system for PostgreSQL.
child process exited with exit code 1
initdb: removing contents of data directory "data"
An error! To fix it, kern.seminfo.semmni and kern.seminfo.semmns need to be modified.
$ doas sysctl kern.seminfo.semmni=256
kern.seminfo.semmni: 10 -> 256
$ doas sysctl kern.seminfo.semmns=2048
kern.seminfo.semmns: 60 -> 2048
Now, the database can be initialized without issue.
$ doas -u _postgresql initdb -D data
The files belonging to this database system will be owned by user "_postgresql".
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 enabled.
fixing permissions on existing directory data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 100
selecting default "shared_buffers" ... 128MB
selecting default time zone ... UTC
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:
pg_ctl -D data -l logfile start
$ doas rcctl start postgresql
postgresql(ok)
It looks way better! The new configuration can now be added into /etc/sysctl.conf
$ echo "kern.seminfo.semmni=256" | doas tee -a /etc/sysctl.conf
$ echo "sysctl kern.seminfo.semmns=2048" | doas tee -a /etc/sysctl.conf
The server should reboot with the good configuration now. You can configure your postgresql server now.
$ doas -u _postgresql psql postgres
psql (18.6)
Type "help" for help.
postgres=#
Happy hacking and have fun!
Cover Image by Dan Seddon on Unsplash
Top comments (0)