# The official relay's push sender. index.js, fcm.js, unifiedpush.js, package*.json # and node_modules live in /opt/hollow-push, owned by root. # /etc/hollow-push/service-account.json Firebase Admin credential, root 0600 # /etc/hollow-push/push.env PUSH_TOKEN=, root 0600 [Unit] Description=Hollow Push Notification Sidecar After=network-online.target hollow-relay.service Wants=network-online.target [Service] Type=simple User=hollow-push Group=hollow-push WorkingDirectory=/opt/hollow-push ExecStart=/usr/bin/node /opt/hollow-push/index.js # Without it the lines are tagged "node" and slip past the rsyslog rule that # keeps every hollow-* line off the disk. SyslogIdentifier=hollow-push Environment=PUSH_PORT=3001 # systemd copies the credential into a private RAM directory only this service # can read; the file under /etc stays root-only. LoadCredential=service-account.json:/etc/hollow-push/service-account.json Environment=FIREBASE_KEY_PATH=%d/service-account.json EnvironmentFile=/etc/hollow-push/push.env Restart=always RestartSec=3 LimitCORE=0 MemorySwapMax=0 CapabilityBoundingSet= NoNewPrivileges=yes PrivateUsers=yes ProtectSystem=strict ProtectHome=yes PrivateTmp=yes PrivateDevices=yes PrivateIPC=yes ProtectKernelTunables=yes ProtectKernelModules=yes ProtectKernelLogs=yes ProtectControlGroups=yes ProtectClock=yes ProtectHostname=yes ProtectProc=invisible RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK # A second wall under unifiedpush.js's address guard: no push endpoint is private. # Loopback stays open for the relay's calls and the 127.0.0.53 resolver; a host whose # resolver has a private address adds it to IPAddressAllow (install.sh does). IPAddressAllow=localhost IPAddressDeny=0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 169.254.0.0/16 172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 IPAddressDeny=192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24 224.0.0.0/4 240.0.0.0/4 IPAddressDeny=::/128 64:ff9b::/96 100::/64 2001:db8::/32 fc00::/7 fe80::/10 ff00::/8 RestrictNamespaces=yes RestrictRealtime=yes RestrictSUIDSGID=yes LockPersonality=yes # No MemoryDenyWriteExecute: V8 compiles JavaScript to machine code at run time. SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallFilter=~@privileged SystemCallErrorNumber=EPERM RemoveIPC=yes UMask=0077 InaccessiblePaths=-/etc/letsencrypt -/etc/hollow-relay -/etc/hollow-forwarder -/etc/turnserver.conf [Install] WantedBy=multi-user.target