PostgreSQL: How to define a custom data directory to be update-proof

Running a PostgreSQL-database in an user defined data directory /mnt/Daten/Technik//PostgreSQL, I experienced different issues over the time in regards to major updates for PostgreSQL and / or MANJARO-updates:

  • PostgreSQL 18 / Manjaro UPdate 2025-12-08
    now seems to be mandatory, to have this declaration in
    /usr/lib/systemd/system/postgresql.service to
    Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL
  • 04.04.2023 AND 05.02.2025 Override-File
    File etc/systemd/system/
    [Service] Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL
  • PostgreSQL 18 / Manjaro UPdate 2026-02-01
    Manjaro UPdate broke this and I had again
    Environment=PGROOT=/var/lib/postgres
  • 11.01.2021
    File /var/lib/postgres having
    data_directory = '/mnt/Daten/Technik/PostgreSQL/data'

My questions:

  1. Is this in relation running PostgreSQL as systemd-service (which would be my preferred option)? How to check this?
  2. How to define the data directory to be update-proof?

Thank you!

PostgreSQL not running (UPdate 2025-12-08) - #33 by MaMicha

systemctl status postgresql

To avoid having an update remove changes to the service, you can look at some instructions here:

3 Likes

Thank you @nikgnomic,
my result is

$ systemctl status postgresql
● postgresql.service - PostgreSQL database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: disabled)
     Active: active (running) since Mon 2026-02-02 19:43:35 CET; 22h ago
 Invocation: 27c600b4caf0466096b5cd1c6e049b9c
       Docs: man:postgres(1)
    Process: 1000 ExecStartPre=/usr/bin/postgresql-check-db-dir ${PGROOT}/data (code=exited, status=0/SUCCESS)
   Main PID: 1003 (postgres)
      Tasks: 10 (limit: 37444)
     Memory: 325.7M (peak: 335.6M)
        CPU: 30.312s
     CGroup: /system.slice/postgresql.service
             ├─1003 /usr/bin/postgres -D /mnt/Daten/Technik/PostgreSQL/data
             ├─1006 "postgres: io worker 0"
             ├─1007 "postgres: io worker 1"
             ├─1008 "postgres: io worker 2"
             ├─1009 "postgres: checkpointer "
             ├─1010 "postgres: background writer "
             ├─1012 "postgres: walwriter "
             ├─1013 "postgres: autovacuum launcher "
             ├─1014 "postgres: logical replication launcher "

So my PostgreSQL is running as systemd-service?

Thank you @Phemisters. I’m sorry, but don’t understand what you mean …

In principle, all daemons are. :wink:

Thank you @Phemisters. I’m sorry, but don’t understand

If I understand you correctly, part of your question was that a change to /usr/lib/systemd/system/postgresql.service was removed when you updated. And that you wanted to prevent that. A way to do that is to have a custom change which is not updated, which is what the linked doc was explaining.

So one approach (from the linked doc) would be to use this command:

sudo systemctl edit postgresql.service 

This opens an editor, and you can add your custom line (read the notes in the opened file - lines with a # at the start are comments which do not affect anything but tell you what to do and show existing lines from the main service file):

Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

and then close the editor, to save the changes. This creates a custom file to override the old setting, and should be unaffected by any later updates.

By the way, I have never done this, but that’s what the docs say.

Certainly looks that way to me.

1 Like

Thank you @Phemisters,

It’s confusing for me:

I fired sudo systemctl edit postgresql.service and got this:

### Editing /etc/systemd/system/postgresql.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file   COMM1

### Edits below this comment will be discarded


### /usr/lib/systemd/system/postgresql.service
# [Unit]
# Description=PostgreSQL database server
# Documentation=man:postgres(1)
# After=network-online.target
# Wants=network-online.target
#
# [Service]
# Type=notify
# TimeoutSec=120
# User=postgres
# Group=postgres
#
# #Environment=PGROOT=/var/lib/postgres     COMM2
# Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL     COMM2
#
# SyslogIdentifier=postgres
# PIDFile=/var/lib/postgres/data/postmaster.pid
# RuntimeDirectory=postgresql
# RuntimeDirectoryMode=755
#
# ExecStartPre=/usr/bin/postgresql-check-db-dir ${PGROOT}/data
# ExecStart=/usr/bin/postgres -D ${PGROOT}/data
# ExecReload=/bin/kill -HUP ${MAINPID}
# KillMode=mixed
# KillSignal=SIGINT
#
# # Due to PostgreSQL's use of shared memory, OOM killer is often overzealous in
# # killing Postgres, so adjust it downward
# OOMScoreAdjust=-200
#
# # Additional security-related features
# PrivateTmp=true
# ProtectHome=true
# ProtectSystem=full
# NoNewPrivileges=true
# ProtectControlGroups=true
# ProtectKernelModules=true
# ProtectKernelTunables=true
# PrivateDevices=true
# RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
# RestrictNamespaces=true
# RestrictRealtime=true
# SystemCallArchitectures=native
#
# [Install]
# WantedBy=multi-user.target

As far as I understand, I have to add my content there “COMM1”

Anything between here and the comment below will become the contents of the drop-in file

Edits below this comment will be discarded

But why these lines are already existing:

#Environment=PGROOT=/var/lib/postgres

Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

Should I remove the two?

Everything in this file is commented. Firstly with a hash, and secondly on the wrong place. So you basically have an empty file now.
It should probably look like this

2 Likes

They don’t exist.
Not in the file content that you posted.
In that file, all the lines are commented
(every line has a # in front)

This here is probably what it should look like:

Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

… no # in front - and the correct PATH

2 Likes

Thank you @Teo:

It should probably look like this
### Anything between here and the comment below will become the contents of the drop-in file COMM1
Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL
### Edits below this comment will be discarded

I will apply this.But besides that, actually I have

  • /usr/lib/systemd/system/postgresql.service with
    Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL
    • would you agree that I DROP thhis line?
  • /var/lib/postgres/data/postgresql.conf with
    data_directory = ‘/mnt/Daten/Technik/PostgreSQL/data’
    • would yo agree that I KEEP this line?

Sorry, i have absolutely no experience with PostgreSQL. I was only commenting the wrong syntax.

Take note that if you want to change a value, you must first empty it. For example, here is my overridden cups.service:

$ systemctl cat cups.service
[...]
# /etc/systemd/system/cups.service.d/override.conf
[Unit]
Requires=
Requires=cups.socket avahi-daemon.service

[Install]
Also=
Also=avahi-daemon.service cups.socket cups.path
2 Likes

I would suggest you would want to change it back to the default value instead of removing it; on my system the default is

Environment=PGROOT=/var/lib/postgres

Yes, I think you want to keep that line unchanged.

1 Like

Thank you @Mirdarthos, but I don’t fully understand:

Actually I have this:

$ systemctl cat postgresql.service
$ systemctl cat postgresql.service
# /usr/lib/systemd/system/postgresql.service
[Unit]
Description=PostgreSQL database server
Documentation=man:postgres(1)
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
TimeoutSec=120
User=postgres
Group=postgres

#Environment=PGROOT=/var/lib/postgres                          **QUESTION REF. BELOW**
Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

SyslogIdentifier=postgres
PIDFile=/var/lib/postgres/data/postmaster.pid
RuntimeDirectory=postgresql
RuntimeDirectoryMode=755

ExecStartPre=/usr/bin/postgresql-check-db-dir ${PGROOT}/data
ExecStart=/usr/bin/postgres -D ${PGROOT}/data
ExecReload=/bin/kill -HUP ${MAINPID}
KillMode=mixed
KillSignal=SIGINT

# Due to PostgreSQL's use of shared memory, OOM killer is often overzealous in
# killing Postgres, so adjust it downward
OOMScoreAdjust=-200

# Additional security-related features
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
NoNewPrivileges=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
PrivateDevices=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=true
RestrictRealtime=true
SystemCallArchitectures=native

[Install]
WantedBy=multi-user.target$ 

Is your recommendation to have (code below having first line added)

Environment=
#Environment=PGROOT=/var/lib/postgres
Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

in /usr/lib/systemd/system/postgresql.service or wherelse?

It is, indeed. :grin:

I think the goal is to have your custom path in a custom systemd file, not in the installed /usr/lib/systemd/system/postgresql.service (to allow the installed one to change, if necessary, when you next update).

Using the suggested sudo systemctl edit postgresql.service command will result in a custom file, which is where you want your custom data path. At least, that is what I think is wanted.

So this

Environment=
#Environment=PGROOT=/var/lib/postgres
Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

goes in the file opened when you run the systemctl edit command.

I think this topic is - kind-of xy-problem.

The real problem is not having a custom data folder - but rather keeping PostgreSQL at a specific version.

When postgresql is updated from one major to the next, there is update procedures that must be run to ensure the database structure matches the new major version.

While I have little experience with PostgreSQL - I know that systemd overrides created to change the default behavior of a service will always survive an update - suffice your overrides are created in /etc/systemd/system and this is important - **never touch the files in /usr tree - your change will be overwritten with an update.

If you want to ensure a postgresql production database is never touched by an update, add postgresql to the list of IgnorePkg in the [options] section of /etc/pacman.conf.

Thanks, but it’s not working: The file /etc/systemd/system/postgresql.service.d/ has been created with:

Environment=
Environment=PGROOT=/mnt/Daten/Technik/PostgreSQL

I re-started the system, started PostgreSQL and got

$ systemctl status postgresql
× postgresql.service - PostgreSQL database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: disabled)
    Drop-In: /etc/systemd/system/postgresql.service.d
             └─override.conf
     Active: failed (Result: exit-code) since Sat 2026-02-07 13:43:49 CET; 6s ago
 Invocation: 30c15206e3244696b10247f1bd4ac4e0
       Docs: man:postgres(1)
    Process: 6520 ExecStartPre=/usr/bin/postgresql-check-db-dir ${PGROOT}/data (code=exited, status=1/FAILURE)
   Mem peak: 2.2M
        CPU: 40ms

Feb 07 13:43:49 systemd[1]: postgresql.service: Control process exited, code=exited, status=1/FAILURE
Feb 07 13:43:49 systemd[1]: postgresql.service: Failed with result 'exit-code'.
Feb 07 13:43:49 systemd[1]: Failed to start PostgreSQL database server.
Feb 07 13:43:56 systemd[1]: /etc/systemd/system/postgresql.service.d/override.conf:1: Assignment outside of section. Ignoring.
Feb 07 13:43:56 systemd[1]: /etc/systemd/system/postgresql.service.d/override.conf:2: Assignment outside of section. Ignoring.

Now what?

You need to add the correct section to the override file. See the message you posted.

Use again the systemctl edit command to edit the service and add above the lines you already have [service]

1 Like