From 4b5fe5c5fb02c6c5317d0d7aac82f115996061b1 Mon Sep 17 00:00:00 2001
From: Christoph Berg <myon@debian.org>
Date: Fri, 30 Mar 2018 17:08:58 +0200
Subject: [PATCH] Support per-user clusters in ~/.config/postgresql/

---
 PgCommon.pm                      |   2 +-
 pg_createcluster                 |  14 +-
 pg_launchcluster                 | 223 +++++++++++++++++++++++++++++
 pg_lsclusters                    |   3 +
 pg_preparecluster                | 232 +++++++++++++++++++++++++++++++
 systemd/Makefile                 |   2 +
 systemd/postgresql@.service      |   4 +-
 systemd/user/postgresql@.service |  34 +++++
 8 files changed, 508 insertions(+), 6 deletions(-)
 create mode 100755 pg_launchcluster
 create mode 100755 pg_preparecluster
 create mode 100644 systemd/user/postgresql@.service

diff --git a/PgCommon.pm b/PgCommon.pm
index ace9b472..a69ae68d 100644
--- a/PgCommon.pm
+++ b/PgCommon.pm
@@ -425,7 +425,7 @@ sub get_cluster_socketdir {
 
     if ($_[0] && $_[1]) {
         my $datadir = cluster_data_directory $_[0], $_[1];
-        error "Invalid data directory for cluster $_[0] $_[1]" unless $datadir;
+        error "Could not determine data directory of cluster $_[0] $_[1]" unless $datadir;
         my @datadirstat = stat $datadir;
         unless (@datadirstat) {
             my @p = split '/', $datadir;
diff --git a/pg_createcluster b/pg_createcluster
index 454b3aa1..e78a2654 100755
--- a/pg_createcluster
+++ b/pg_createcluster
@@ -4,7 +4,7 @@
 # the postgresql-common infrastructure.
 #
 # (C) 2005-2013 Martin Pitt <mpitt@debian.org>
-# (C) 2012-2017 Christoph Berg <myon@debian.org>
+# (C) 2012-2018 Christoph Berg <myon@debian.org>
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
@@ -190,6 +190,7 @@ my $startconf = '';
 my $pgoptions = [];
 my $createclusterconf = "$PgCommon::common_confdir/createcluster.conf";
 my $environmentfile = "$PgCommon::common_confdir/environment";
+my $usercluster = 0;
 
 exit 1 unless GetOptions ('u|user=s' => \$owneruid, 'g|group=s' => \$ownergid,
     's|socketdir=s' => \$socketdir, 'd|datadir=s' => \$datadir, 
@@ -203,7 +204,12 @@ exit 1 unless GetOptions ('u|user=s' => \$owneruid, 'g|group=s' => \$ownergid,
     'p|port=i' => \$port, 'locale=s' => \$locale,
     'lc-collate=s' => \$lc_collate, 'lc-ctype=s' => \$lc_ctype,
     'lc-messages=s' => \$lc_messages, 'lc-monetary=s' => \$lc_monetary,
-    'lc-numeric=s' => \$lc_numeric, 'lc-time=s' => \$lc_time);
+    'lc-numeric=s' => \$lc_numeric, 'lc-time=s' => \$lc_time,
+    'user-cluster' => sub {
+        $usercluster = 1;
+        $PgCommon::confroot = $ENV{PG_CLUSTER_CONF_ROOT} = "$ENV{HOME}/.config/postgresql";
+    },
+);
 
 # read defaults from /etc/postgresql-common/createcluster.conf
 %defaultconf = PgCommon::read_conf_file ($createclusterconf);
@@ -287,7 +293,9 @@ foreach my $argv (@ARGV) {
 
 my $datadirp_created;
 if (!defined $datadir) {
-    $datadir = replace_v_c ($defaultconf{'data_directory'} || "/var/lib/postgresql/%v/%c", $version, $cluster);
+    my $default_datadir = $usercluster ? "$ENV{HOME}/.config/postgresql/%v/%c" :
+        $defaultconf{'data_directory'} || "/var/lib/postgresql/%v/%c";
+    $datadir = replace_v_c ($default_datadir, $version, $cluster);
     $datadir =~ s!/+$!!;
     my $pd = $datadir;
     $pd =~ s!/[^/]*$!!;
diff --git a/pg_launchcluster b/pg_launchcluster
new file mode 100755
index 00000000..d786738d
--- /dev/null
+++ b/pg_launchcluster
@@ -0,0 +1,223 @@
+#!/usr/bin/perl -wT
+
+# multiversion/cluster aware pg_ctl wrapper; this also supplies the correct
+# configuration parameters to 'start', and makes sure that postgres really
+# stops on 'stop'.
+#
+# (C) 2005-2009 Martin Pitt <mpitt@debian.org>
+# (C) 2009 Cyril Bouthors <cyril@bouthors.org>
+# (C) 2013-2018 Christoph Berg <myon@debian.org>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw/setsid dup2 :sys_wait_h/;
+use PgCommon;
+use Fcntl qw(SEEK_SET O_RDWR O_CREAT O_EXCL);
+use POSIX qw(lchown);
+
+my ($version, $cluster, $pg_ctl, $force);
+my (@postgres_auxoptions, @pg_ctl_opts_from_cli);
+my (%postgresql_conf, %info);
+
+# untaint environment
+$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+
+#
+# main
+#
+
+exit 1 unless GetOptions (
+    'user-cluster' => sub {
+        #$usercluster = 1;
+        $PgCommon::confroot = $ENV{PG_CLUSTER_CONF_ROOT} = "$ENV{HOME}/.config/postgresql";
+    },
+);
+
+if (@ARGV != 1) {
+    error "Usage: $0 <version>-<cluster>\n";
+    exit 1;
+}
+
+if ($ARGV[0] =~ m!^(\d+\.?\d)[-/](.+)!) {
+    ($version, $cluster) = ($1, $2);
+}
+
+($version) = $version =~ /^(\d+\.?\d+)$/; # untaint
+($cluster) = $cluster =~ /^([^'"\s]+)$/; # untaint
+error 'specified cluster does not exist' unless $version && $cluster && cluster_exists $version, $cluster;
+%info = cluster_info ($version, $cluster);
+
+unless (-d $info{'pgdata'} && defined $info{'owneruid'}) {
+    error "$info{pgdata} is not accessible or does not exist";
+}
+
+# check that owner uid/gid is valid
+unless (getpwuid $info{'owneruid'}) {
+    error "The cluster is owned by user id $info{owneruid} which does not exist";
+}
+unless (getgrgid $info{'ownergid'}) {
+    error "The cluster is owned by group id $info{ownergid} which does not exist";
+}
+# owneruid and configuid need to match, unless configuid is root
+if (($< == 0 or $> == 0) and $info{'configuid'} != 0 and
+        $info{'configuid'} != $info{'owneruid'}) {
+    my $configowner = (getpwuid $info{'configuid'})[0] || "(unknown)";
+    my $dataowner = (getpwuid $info{'owneruid'})[0];
+    error "Config owner ($configowner:$info{configuid}) and data owner ($dataowner:$info{owneruid}) do not match, and config owner is not root";
+}
+
+exec "/usr/lib/postgresql/$version/bin/postgres", "-D", $info{pgdata}
+    or error "/usr/lib/postgresql/$version/bin/postgres: $!";
+
+__END__
+
+=head1 NAME
+
+pg_ctlcluster - start/stop/restart/reload a PostgreSQL cluster
+
+=head1 SYNOPSIS
+
+B<pg_ctlcluster> [I<options>] I<cluster-version> I<cluster-name> I<action> [B<--> I<pg_ctl options>]
+
+where I<action> = B<start>|B<stop>|B<restart>|B<reload>|B<status>|B<promote>
+
+=head1 DESCRIPTION
+
+This program controls the B<postgres> server for a particular cluster. It
+essentially wraps the L<pg_ctl(1)> command. It determines the cluster version
+and data path and calls the right version of B<pg_ctl> with appropriate
+configuration parameters and paths.
+
+You have to start this program as the user who owns the database cluster or as
+root.
+
+To ease integration with B<systemd> operation, the alternative syntax
+"B<pg_ctlcluster> I<version>B<->I<cluster> I<action>" is also supported.
+
+=head1 ACTIONS
+
+=over 4
+
+=item B<start>
+
+A log file for this specific cluster is created if it does not exist yet (by
+default,
+C</var/log/postgresql/postgresql->I<cluster-version>C<->I<cluster-name>C<.log>),
+and a PostgreSQL server process (L<postgres(1)>) is started on it. Exits with
+0 on success, with 2 if the server is already running, and with 1 on other
+failure conditions.
+
+=item B<stop>
+
+Stops the L<postgres(1)> server of the given cluster. By default, "smart"
+shutdown mode is used, which waits until all clients disconnected.
+
+=item B<restart>
+
+Stops the server if it is running and starts it (again).
+
+=item B<reload>
+
+Causes the configuration files to be re-read without a full shutdown of the
+server.
+
+=item B<status>
+
+Checks whether a server is running. If it is, the PID and the command line
+options that were used to invoke it are displayed.
+
+=item B<promote>
+
+Commands a running standby server to exit recovery and begin read-write
+operations.
+
+=back
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-f>|B<--force>
+
+For B<stop> and B<restart>, the "fast" mode is used which rolls back all active
+transactions, disconnects clients immediately and thus shuts down cleanly. If
+that does not work, shutdown is attempted again in "immediate" mode, which can
+leave the cluster in an inconsistent state and thus will lead to a recovery run
+at the next start. If this still does not help, the B<postgres> process is
+killed.  Exits with 0 on success, with 2 if the server is not running, and with
+1 on other failure conditions. This mode should only be used when the machine
+is about to be shut down.
+
+=item B<-m>|B<--mode> [B<smart>|B<fast>|B<immediate>]
+
+Shutdown mode to use for B<stop> and B<restart> actions, default is B<smart>.
+See pg_ctl(1) for documentation.
+
+=item B<--foreground>
+
+Start B<postgres> in foreground, without daemonizing via B<pg_ctl>.
+
+=item B<--stdlog>
+
+When B<--foreground> is in use, redirect stderr to the standard logfile in
+C</var/log/postgresql/>.  (Default when not run in foreground.)
+
+=item B<--bindir> I<directory>
+
+Path to B<pg_ctl>.  (Default is C</usr/lib/postgresql/>I<version>C</bin>.)
+
+=item B<-o>|B<--options> I<option>
+
+Pass given I<option> as command line option to the C<postgres> process. It is
+possible to specify B<-o> multiple times. See L<postgres(1)> for a
+description of valid options.
+
+=item I<pg_ctl options>
+
+Pass given I<pg_ctl options> as command line options to B<pg_ctl>. See L<pg_ctl(1)>
+for a description of valid options.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=item C</etc/postgresql/>I<cluster-version>C</>I<cluster-name>C</pg_ctl.conf>
+
+This configuration file contains cluster specific options to be passed to
+L<pg_ctl(1)>.
+
+=item C</etc/postgresql/>I<cluster-version>C</>I<cluster-name>C</start.conf>
+
+This configuration file controls the start/stop behavior of the cluster. See
+section "STARTUP CONTROL" in L<pg_createcluster(8)> for details.
+
+=back
+
+=head1 BUGS
+
+Changing the port number on startup using B<-o -p> will not work as it breaks
+the checks for running clusters.
+
+=head1 SEE ALSO
+
+L<pg_createcluster(8)>, L<pg_ctl(1)>, L<pg_wrapper(1)>, L<pg_lsclusters(1)>,
+L<postgres(1)>
+
+=head1 AUTHOR
+
+Martin Pitt L<E<lt>mpitt@debian.orgE<gt>>
+
diff --git a/pg_lsclusters b/pg_lsclusters
index 0cb263af..57e6682e 100755
--- a/pg_lsclusters
+++ b/pg_lsclusters
@@ -41,6 +41,9 @@ help(1) unless GetOptions (
     'h|no-header' => \$no_header,
     'j|json' => \$json,
     's|start-conf' => \$start_conf,
+    'u|user-clusters' => sub {
+        $PgCommon::confroot = $ENV{PG_CLUSTER_CONF_ROOT} = "$ENV{HOME}/.config/postgresql";
+    },
 );
 
 my (@versions, $ls_cluster);
diff --git a/pg_preparecluster b/pg_preparecluster
new file mode 100755
index 00000000..6d201990
--- /dev/null
+++ b/pg_preparecluster
@@ -0,0 +1,232 @@
+#!/usr/bin/perl -wT
+
+# multiversion/cluster aware pg_ctl wrapper; this also supplies the correct
+# configuration parameters to 'start', and makes sure that postgres really
+# stops on 'stop'.
+#
+# (C) 2005-2009 Martin Pitt <mpitt@debian.org>
+# (C) 2009 Cyril Bouthors <cyril@bouthors.org>
+# (C) 2013-2018 Christoph Berg <myon@debian.org>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw/setsid dup2 :sys_wait_h/;
+use PgCommon;
+use Fcntl qw(SEEK_SET O_RDWR O_CREAT O_EXCL);
+use POSIX qw(lchown);
+
+my ($version, $cluster, $pg_ctl, $force);
+my (@postgres_auxoptions, @pg_ctl_opts_from_cli);
+my (%postgresql_conf, %info);
+
+# untaint environment
+$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+
+#
+# main
+#
+
+exit 1 unless GetOptions (
+    'user-cluster' => sub {
+        #$usercluster = 1;
+        $PgCommon::confroot = $ENV{PG_CLUSTER_CONF_ROOT} = "$ENV{HOME}/.config/postgresql";
+    },
+);
+
+if (@ARGV != 1) {
+    error "Usage: $0 <version>-<cluster>\n";
+    exit 1;
+}
+
+if ($ARGV[0] =~ m!^(\d+\.?\d)[-/](.+)!) {
+    ($version, $cluster) = ($1, $2);
+}
+
+($version) = $version =~ /^(\d+\.?\d+)$/; # untaint
+($cluster) = $cluster =~ /^([^'"\s]+)$/; # untaint
+error 'specified cluster does not exist' unless $version && $cluster && cluster_exists $version, $cluster;
+%info = cluster_info ($version, $cluster);
+
+unless (-d $info{'pgdata'} && defined $info{'owneruid'}) {
+    error "$info{pgdata} is not accessible or does not exist";
+}
+
+# check that owner uid/gid is valid
+unless (getpwuid $info{'owneruid'}) {
+    error "The cluster is owned by user id $info{owneruid} which does not exist";
+}
+unless (getgrgid $info{'ownergid'}) {
+    error "The cluster is owned by group id $info{ownergid} which does not exist";
+}
+# owneruid and configuid need to match, unless configuid is root
+if (($< == 0 or $> == 0) and $info{'configuid'} != 0 and
+        $info{'configuid'} != $info{'owneruid'}) {
+    my $configowner = (getpwuid $info{'configuid'})[0] || "(unknown)";
+    my $dataowner = (getpwuid $info{'owneruid'})[0];
+    error "Config owner ($configowner:$info{configuid}) and data owner ($dataowner:$info{owneruid}) do not match, and config owner is not root";
+}
+
+# recreate /var/run/postgresql
+if (! -d $info{socketdir}) {
+    system 'install', '-d', '-m', 2775,
+	'-o', $info{'owneruid'}, '-g', $info{'ownergid'}, $info{'socketdir'};
+}
+
+# recreate stats_temp_directory
+if ($info{config}->{stats_temp_directory} && ! -d $info{config}->{stats_temp_directory}) {
+    system 'install', '-d', '-m', 750,
+	'-o', $info{'owneruid'}, '-g', $info{'ownergid'}, $info{config}->{stats_temp_directory};
+}
+
+__END__
+
+=head1 NAME
+
+pg_ctlcluster - start/stop/restart/reload a PostgreSQL cluster
+
+=head1 SYNOPSIS
+
+B<pg_ctlcluster> [I<options>] I<cluster-version> I<cluster-name> I<action> [B<--> I<pg_ctl options>]
+
+where I<action> = B<start>|B<stop>|B<restart>|B<reload>|B<status>|B<promote>
+
+=head1 DESCRIPTION
+
+This program controls the B<postgres> server for a particular cluster. It
+essentially wraps the L<pg_ctl(1)> command. It determines the cluster version
+and data path and calls the right version of B<pg_ctl> with appropriate
+configuration parameters and paths.
+
+You have to start this program as the user who owns the database cluster or as
+root.
+
+To ease integration with B<systemd> operation, the alternative syntax
+"B<pg_ctlcluster> I<version>B<->I<cluster> I<action>" is also supported.
+
+=head1 ACTIONS
+
+=over 4
+
+=item B<start>
+
+A log file for this specific cluster is created if it does not exist yet (by
+default,
+C</var/log/postgresql/postgresql->I<cluster-version>C<->I<cluster-name>C<.log>),
+and a PostgreSQL server process (L<postgres(1)>) is started on it. Exits with
+0 on success, with 2 if the server is already running, and with 1 on other
+failure conditions.
+
+=item B<stop>
+
+Stops the L<postgres(1)> server of the given cluster. By default, "smart"
+shutdown mode is used, which waits until all clients disconnected.
+
+=item B<restart>
+
+Stops the server if it is running and starts it (again).
+
+=item B<reload>
+
+Causes the configuration files to be re-read without a full shutdown of the
+server.
+
+=item B<status>
+
+Checks whether a server is running. If it is, the PID and the command line
+options that were used to invoke it are displayed.
+
+=item B<promote>
+
+Commands a running standby server to exit recovery and begin read-write
+operations.
+
+=back
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-f>|B<--force>
+
+For B<stop> and B<restart>, the "fast" mode is used which rolls back all active
+transactions, disconnects clients immediately and thus shuts down cleanly. If
+that does not work, shutdown is attempted again in "immediate" mode, which can
+leave the cluster in an inconsistent state and thus will lead to a recovery run
+at the next start. If this still does not help, the B<postgres> process is
+killed.  Exits with 0 on success, with 2 if the server is not running, and with
+1 on other failure conditions. This mode should only be used when the machine
+is about to be shut down.
+
+=item B<-m>|B<--mode> [B<smart>|B<fast>|B<immediate>]
+
+Shutdown mode to use for B<stop> and B<restart> actions, default is B<smart>.
+See pg_ctl(1) for documentation.
+
+=item B<--foreground>
+
+Start B<postgres> in foreground, without daemonizing via B<pg_ctl>.
+
+=item B<--stdlog>
+
+When B<--foreground> is in use, redirect stderr to the standard logfile in
+C</var/log/postgresql/>.  (Default when not run in foreground.)
+
+=item B<--bindir> I<directory>
+
+Path to B<pg_ctl>.  (Default is C</usr/lib/postgresql/>I<version>C</bin>.)
+
+=item B<-o>|B<--options> I<option>
+
+Pass given I<option> as command line option to the C<postgres> process. It is
+possible to specify B<-o> multiple times. See L<postgres(1)> for a
+description of valid options.
+
+=item I<pg_ctl options>
+
+Pass given I<pg_ctl options> as command line options to B<pg_ctl>. See L<pg_ctl(1)>
+for a description of valid options.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=item C</etc/postgresql/>I<cluster-version>C</>I<cluster-name>C</pg_ctl.conf>
+
+This configuration file contains cluster specific options to be passed to
+L<pg_ctl(1)>.
+
+=item C</etc/postgresql/>I<cluster-version>C</>I<cluster-name>C</start.conf>
+
+This configuration file controls the start/stop behavior of the cluster. See
+section "STARTUP CONTROL" in L<pg_createcluster(8)> for details.
+
+=back
+
+=head1 BUGS
+
+Changing the port number on startup using B<-o -p> will not work as it breaks
+the checks for running clusters.
+
+=head1 SEE ALSO
+
+L<pg_createcluster(8)>, L<pg_ctl(1)>, L<pg_wrapper(1)>, L<pg_lsclusters(1)>,
+L<postgres(1)>
+
+=head1 AUTHOR
+
+Martin Pitt L<E<lt>mpitt@debian.orgE<gt>>
+
diff --git a/systemd/Makefile b/systemd/Makefile
index ace0c2d1..486da1b5 100644
--- a/systemd/Makefile
+++ b/systemd/Makefile
@@ -2,6 +2,8 @@ install:
 	install -d $(DESTDIR)/lib/systemd/system-generators/ $(DESTDIR)/lib/systemd/system/
 	install postgresql-generator $(DESTDIR)/lib/systemd/system-generators/
 	install -m644 postgresql*.service $(DESTDIR)/lib/systemd/system/
+	install -d $(DESTDIR)/usr/lib/systemd/user/
+	install -m644 user/postgresql*.service $(DESTDIR)/usr/lib/systemd/user/
 
 reload: install
 	systemctl daemon-reload
diff --git a/systemd/postgresql@.service b/systemd/postgresql@.service
index d9f8d32b..7b61efb2 100644
--- a/systemd/postgresql@.service
+++ b/systemd/postgresql@.service
@@ -1,17 +1,17 @@
 # systemd service template for PostgreSQL clusters. The actual instances will
 # be called "postgresql@version-cluster", e.g. "postgresql@9.3-main". The
 # variable %i expands to "version-cluster", %I expands to "version/cluster".
-# (%I breaks for cluster names containing dashes.)
 
 [Unit]
 Description=PostgreSQL Cluster %i
-ConditionPathExists=/etc/postgresql/%I/postgresql.conf
+AssertPathExists=/etc/postgresql/%I/postgresql.conf
 PartOf=postgresql.service
 ReloadPropagatedFrom=postgresql.service
 Before=postgresql.service
 
 [Service]
 Type=forking
+ExecStartPre=/usr/bin/pg_lsclusters %i
 # -: ignore startup failure (recovery might take arbitrarily long)
 # the actual pg_ctl timeout is configured in pg_ctl.conf
 ExecStart=-/usr/bin/pg_ctlcluster --skip-systemctl-redirect %i start
diff --git a/systemd/user/postgresql@.service b/systemd/user/postgresql@.service
new file mode 100644
index 00000000..113c7608
--- /dev/null
+++ b/systemd/user/postgresql@.service
@@ -0,0 +1,34 @@
+# systemd service template for PostgreSQL clusters. The actual instances will
+# be called "postgresql@version-cluster", e.g. "postgresql@9.3-main". The
+# variable %i expands to "version-cluster", %I expands to "version/cluster".
+
+[Unit]
+Description=PostgreSQL Cluster %i
+PartOf=postgresql.service
+ReloadPropagatedFrom=postgresql.service
+Before=postgresql.service
+
+[Service]
+Type=notify
+ExecStartPre=/usr/bin/pg_preparecluster --user-cluster %i
+ExecStart=/usr/bin/pg_launchcluster --user-cluster %i
+# 0 is the same as infinity, but "infinity" needs systemd 229
+TimeoutStartSec=0
+ExecStop=/bin/kill -INT $MAINPID
+TimeoutStopSec=1h
+ExecReload=/bin/kill -HUP $MAINPID
+SyslogIdentifier=postgresql@%i
+# prevent OOM killer from choosing the postmaster (individual backends will
+# reset the score to 0)
+OOMScoreAdjust=-900
+Environment="PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj"
+# restarting automatically will prevent "pg_ctlcluster ... stop" from working,
+# so we disable it here. Also, the postmaster will restart by itself on most
+# problems anyway, so it is questionable if one wants to enable external
+# automatic restarts.
+#Restart=on-failure
+# (This should make pg_ctlcluster stop work, but doesn't:)
+#RestartPreventExitStatus=SIGINT SIGTERM
+
+[Install]
+WantedBy=multi-user.target
-- 
GitLab