-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpolyemesis.service
More file actions
121 lines (111 loc) · 5.26 KB
/
Copy pathpolyemesis.service
File metadata and controls
121 lines (111 loc) · 5.26 KB
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
# systemd unit for polyemesis.
#
# sudo cp polyemesis /usr/local/bin/
# sudo useradd --system --home /var/lib/polyemesis --shell /usr/sbin/nologin polyemesis
# sudo mkdir -p /var/lib/polyemesis /etc/polyemesis
# sudo chmod 0750 /var/lib/polyemesis # holds stream keys -- see #297
# sudo chown polyemesis:polyemesis /var/lib/polyemesis
# sudo cp config.example.yaml /etc/polyemesis/config.yaml
# sudo cp deploy/polyemesis.service /etc/systemd/system/
# sudo systemctl daemon-reload && sudo systemctl enable --now polyemesis
# journalctl -u polyemesis -f
[Unit]
Description=polyemesis restreaming server
Documentation=https://github.com/rainmanjam/polyemesis
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=polyemesis
Group=polyemesis
# 0077, so anything this service creates is private to it. Issue #297: the
# state database holds every destination stream key in plaintext, and it was
# created 0644 under the default 022 -- readable by any local user, since the
# install notes above make /var/lib/polyemesis with a plain mkdir (0755).
#
# internal/db chmods the database itself on open, which covers an existing
# install. This covers everything else the service ever writes there, including
# files added later by someone who does not know to secure them.
UMask=0077
ExecStart=/usr/local/bin/polyemesis \
--config /etc/polyemesis/config.yaml \
--data /var/lib/polyemesis \
--addr :8080
# --- The listen address ---
# `--addr :8080` is EXPLICIT ON PURPOSE and must stay that way. With no addr
# from a flag or config.yaml, polyemesis binds 127.0.0.1:8080 and is reachable
# only from this host -- deliberately, because the do-nothing configuration used
# to serve a login form and its session cookie in cleartext on every interface.
# This unit is a considered deployment, so it says what it binds. If this box is
# reachable by anyone you do not trust, put TLS in front of it (tls.mode: auto,
# or the reverse proxy in deploy/nginx.conf.example) rather than deleting the
# line: dropping it narrows the bind, it does not encrypt anything.
# --- TLS ---
# As written this serves whatever /etc/polyemesis/config.yaml asks for on :8080.
#
# If polyemesis terminates TLS itself (tls.mode acme/selfsigned/manual) it also
# tries to bind :80 for the HTTP->HTTPS redirect, and in acme mode for the
# Let's Encrypt HTTP-01 challenge. Ports below 1024 are privileged and this unit
# runs as an unprivileged user, so that bind fails: polyemesis logs a warning
# and keeps serving HTTPS, but ACME issuance will never complete.
#
# For mode: acme, change --addr to :443 and uncomment both lines below, then
# check `journalctl -u polyemesis` on the next start to confirm the bind
# succeeded rather than assuming it did.
#
# AmbientCapabilities=CAP_NET_BIND_SERVICE
# CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#
# Alternatives, if you would rather grant nothing: set the sysctl
# net.ipv4.ip_unprivileged_port_start=80, or forward 80/443 to 8080 with an
# nftables/iptables redirect. Both keep this unit unprivileged, and the redirect
# also works when something else already owns port 80 on the host.
#
# Generated TLS material (the local CA, the ACME cache, private keys) is written
# under --data, which ReadWritePaths already covers. For mode: manual, note that
# ProtectHome=true below makes anything under /home unreadable — keep certFile
# and keyFile somewhere like /etc/ssl/polyemesis/ and make them readable by this
# user.
# polyemesis shuts its FFmpeg children down in order on SIGTERM, so that a
# recording is finalised rather than truncated. Give it room to finish.
KillSignal=SIGTERM
TimeoutStopSec=45
# Send the signal to the main process only. polyemesis puts each child in its
# own process group and tears them down itself; letting systemd kill the whole
# cgroup first would cut recordings off mid-write.
KillMode=mixed
Restart=on-failure
RestartSec=5s
# --- hardening ---
# polyemesis needs to exec ffmpeg and write to its data directory, and nothing
# else. NoNewPrivileges is safe because the FFmpeg children need no privileges.
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
# THE STREAM KEY IS IN FFmpeg'S ARGV, AND ARGV IS WORLD-READABLE BY DEFAULT.
# A destination's RTMP target is built as rtmp://host/app/<streamKey> and handed
# to the child as an argument, so on a stock Linux host any local account can
# read a live stream key out of /proc/<pid>/cmdline or plain `ps`. polyemesis
# masks its own renderings of that command line and cannot mask the kernel's.
# ProtectProc=invisible hides other users' processes from this unit's view and,
# with hidepid on /proc, is what keeps the key off a shared box. It is one line
# and it costs nothing on a single-operator VPS.
ProtectProc=invisible
ProtectHome=true
ReadWritePaths=/var/lib/polyemesis
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
# AF_INET/AF_INET6 for HTTP, RTMP and SRT; AF_UNIX for local sockets.
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
# Several FFmpeg processes each hold a handful of descriptors; the default
# soft limit is fine but headroom costs nothing.
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target