summaryrefslogtreecommitdiffstats
path: root/debian/bin/generate-systemd-service-files
blob: c7eafabe4938ded56296695f7d4d737acc0bfb67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/bin/sh

for BINARY in redis-server redis-sentinel
do
	for MODE in default templated
	do
		case "${BINARY}" in
		redis-server)
			NAME="redis"
			;;
		redis-sentinel)
			NAME="sentinel"
			;;
		esac

		case "${MODE}" in
		default)
			EXTRA="Alias=${NAME}.service"
			TARGET="debian/${BINARY}.service"
			NAMESPACED="${NAME}"
			DESCRIPTION="Advanced key-value store"
			;;
		templated)
			EXTRA=""
			TARGET="debian/${BINARY}@.service"
			NAMESPACED="${NAME}-%i"
			DESCRIPTION="Advanced key-value store (%I)"
			;;
		esac

		: >${TARGET}

		if [ "${MODE}" = "templated" ]
		then
			cat >> ${TARGET} <<EOF
# Templated service file for ${BINARY}(1)
#
# Each instance of ${BINARY} requires its own configuration file:
#
#   $ cp /etc/redis/${NAME}.conf /etc/redis/${NAME}-myname.conf
#   $ chown redis:redis /etc/redis/${NAME}-myname.conf
#
# Ensure each instance is using their own database:
#
#   $ sed -i -e 's@^dbfilename .*@dbfilename dump-myname.rdb@' /etc/redis/${NAME}-myname.conf
#
# We then listen exlusively on UNIX sockets to avoid TCP port collisions:
#
#   $ sed -i -e 's@^port .*@port 0@' /etc/redis/${NAME}-myname.conf
#   $ sed -i -e 's@^\\(# \\)\\{0,1\\}unixsocket .*@unixsocket /run/${NAME}-myname/${BINARY}.sock@' /etc/redis/${NAME}-myname.conf
#
# ... and ensure we are logging, etc. in a unique location:
#
#   $ sed -i -e 's@^logfile .*@logfile /var/log/redis/${BINARY}-myname.log@' /etc/redis/${NAME}-myname.conf
#   $ sed -i -e 's@^pidfile .*@pidfile /run/redis-myname/${BINARY}.pid@' /etc/redis/${NAME}-myname.conf
#
# We can then start the service as follows, validating we are using our own
# configuration:
#
#   $ systemctl start ${BINARY}@myname.service
#   $ redis-cli -s /run/${NAME}-myname/${BINARY}.sock info | grep config_file
#
#  -- Chris Lamb <lamby@debian.org>  Mon, 09 Oct 2017 22:17:24 +0100
EOF
		fi

		cat >> ${TARGET} <<EOF
[Unit]
Description=${DESCRIPTION}
After=network.target
Documentation=http://redis.io/documentation, man:${BINARY}(1)

[Service]
Type=notify
ExecStart=/usr/bin/${BINARY} /etc/redis/${NAMESPACED}.conf --supervised systemd --daemonize no
PIDFile=/run/${NAMESPACED}/${BINARY}.pid
TimeoutStopSec=0
Restart=always
User=redis
Group=redis
RuntimeDirectory=${NAMESPACED}
RuntimeDirectoryMode=2755

UMask=007
PrivateTmp=true
LimitNOFILE=65535
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=-/var/lib/redis
ReadWritePaths=-/var/log/redis
ReadWritePaths=-/var/run/${NAMESPACED}

CapabilityBoundingSet=
LockPersonality=true
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateUsers=true
ProtectClock=true
ProtectControlGroups=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
RemoveIPC=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~ @privileged @resources

# ${BINARY} can write to its own config file when in cluster mode so we
# permit writing there by default. If you are not using this feature, it is
# recommended that you remove this line.
ReadWriteDirectories=-/etc/redis

# This restricts this service from executing binaries other than ${BINARY}
# itself. This is really effective at e.g. making it impossible to an
# attacker to spawn a shell on the system, but might be more restrictive
# than desired. If you need to, you can permit the execution of extra
# binaries by adding an extra ExecPaths= directive with the command
# systemctl edit ${BINARY}.service
NoExecPaths=/
ExecPaths=/usr/bin/${BINARY} /usr/lib /lib

[Install]
WantedBy=multi-user.target
EOF
		if [ "${EXTRA}" != "" ]
		then
			echo "${EXTRA}" >> "${TARGET}"
		fi
	done
done