# This systemd unit puts the PostgreSQL storage on tmpfs and (tries to) sync # it back at shutdown. # Of course, in case of power failure or any problem preventing this # unit to stop properly and sync back the data to disk : DATA LOSS. # To install : # - apt install rsync # - copy this file to /etc/systemd/system/postgresqlontmpfs@.service # - in the following lines, replace NN-xxxx by the version and cluster name targeted, for example: postgresqlontmpfs@15-main # - systemctl enable postgresqlontmpfs@NN-xxxx # - systemctl stop postgresql # - systemctl start postgresqlontmpfs@NN-xxxxx # - systemctl start postgresql # This file is free software licensed under the WTFPL (v2) # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE # Version 2, December 2004 # # Copyright (C) 2004 Sam Hocevar # # Everyone is permitted to copy and distribute verbatim or modified # copies of this license document, and changing it is allowed as long # as the name is changed. # # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION # # 0. You just DO WHAT THE FUCK YOU WANT TO. [Unit] Description=Put /var/lib/postgresql/%I on tmpfs before PostgreSQL starts Before=postgresql@%i.service ConditionPathIsDirectory=/var/lib/postgresql/%I ConditionPathExists=/usr/bin/rsync [Install] WantedBy=multi-user.target [Service] Type=oneshot RemainAfterExit=yes Restart=no # We double-check that PostgreSQL is not running before doing anything # Per https://www.freedesktop.org/software/systemd/man/systemd.service.html # when an ExecCondition= command exits with exit code 1 through 254 # (inclusive), the remaining commands are skipped and the unit is not marked as # failed. However, if an ExecCondition= command exits with 255 or abnormally # (e.g. timeout, killed by a signal, etc.), the unit will be considered failed # (and remaining commands will be skipped). ExecCondition=/bin/sh -c "systemctl --quiet is-active postgresql@%i && echo 'PostgreSQL still active' && exit 255 || exit 0" # If the ON-DISK directory doesn't exist, simply rename /var/lib/postgresql/NN/main to # /var/lib/postgresql/NN/main.ON-DISK and recreate /var/lib/postgresql/NN/main ExecStart=/bin/sh -c "if [ ! -e /var/lib/postgresql/%I.ON-DISK ] ; then mv -v /var/lib/postgresql/%I /var/lib/postgresql/%I.ON-DISK && mkdir -v /var/lib/postgresql/%I && chown -v postgres:postgres /var/lib/postgresql/%I; fi" # Mount the tmpfs # (note: to forcefully limit memory consumption, we can add 'size=1024M' to the mount options) ExecStart=/bin/mount -v -t tmpfs -o uid=postgres,gid=postgres,mode=0755 none /var/lib/postgresql/%I # Copy the ON-DISK content to the tmpfs ExecStart=/usr/bin/rsync -avH --delete /var/lib/postgresql/%I.ON-DISK/ /var/lib/postgresql/%I/ # At stop : # - Little notice for the logs ExecStop=/bin/sh -c "echo 'Syncing tmpfs:/var/lib/postgresql/%i to disk'" # - fetch back the in-memory data to disk ExecStop=/usr/bin/rsync -avH --delete /var/lib/postgresql/%I/ /var/lib/postgresql/%I.ON-DISK/ # - destroy the tmpfs ExecStop=/bin/umount -v /var/lib/postgresql/%I # - put back the on-disk storage in its original path ExecStop=/bin/sh -c "rmdir -v /var/lib/postgresql/%I && mv -v /var/lib/postgresql/%I.ON-DISK /var/lib/postgresql/%I"