[Unit] Description=GoMail — self-hosted email server Documentation=https://gomail After=network-online.target Wants=network-online.target [Service] Type=simple User=gomail Group=gomail EnvironmentFile=/etc/gomail/gomail.env ExecStart=/usr/local/bin/gomail -config /etc/gomail/gomail.yaml Restart=on-failure RestartSec=5s # GoMail binds privileged ports (25, 80, 443, 993, etc.) — grant only the # specific capability needed to bind them as a non-root user, rather than # running the whole process as root. AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE # ── Sandboxing ──────────────────────────────────────────────────────────────── # Everything below restricts what a compromised gomail process could do, # independent of what the AmbientCapabilities line above grants for binding # ports. Review `systemd-analyze security gomail.service` after install to # see the resulting exposure score. NoNewPrivileges=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/lib/gomail /var/log/gomail PrivateTmp=true PrivateDevices=true ProtectKernelTunables=true ProtectKernelModules=true ProtectKernelLogs=true ProtectControlGroups=true ProtectClock=true ProtectHostname=true RestrictNamespaces=true RestrictSUIDSGID=true RestrictRealtime=true LockPersonality=true # NOTE: this binary uses CGO (mattn/go-sqlite3 requires it). This directive # is a standard hardening default and works on most systems, but if the # service fails to start with a memory-protection-related error, this is # the first line to try removing — some CGO/glibc combinations need # executable memory in ways MemoryDenyWriteExecute forbids. MemoryDenyWriteExecute=true SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallFilter=~@privileged @resources @mount @debug # Reasonable resource ceilings — adjust for your actual traffic; these are # starting points, not hard requirements. LimitNOFILE=65536 TasksMax=512 [Install] WantedBy=multi-user.target