{ pkgs, lib, ... }:
let
  inherit (lib) concatStringsSep;
in
{
  # Sadly, steam-run requires some X libs
  environment.noXlibs = false;

  systemd.services.starbound = {
    description = "Starbound";
    after = [ "network.target" ];

    serviceConfig = {
      ExecStart = "${pkgs.local.starbound}/bin/launch-starbound ${./configs/starbound.json}";

      Type = "simple";

      # Credential loading for steam auth (if necessary; prefer
      # anonymous login wherever possible).
      LoadCredential = "steam:/run/secrets/steam/tlater";

      # Security settings
      DynamicUser = true;

      # This is where the StateDirectory ends up
      WorkingDirectory = "/var/lib/starbound";
      # Creates /var/lib/starbound (or rather, a symlink there to
      # /var/lib/private/starbound), and sets it up to be writeable to
      # by the dynamic user.
      StateDirectory = "starbound";

      # Note some settings below are basically tautologous with
      # `NoNewPrivileges`, but they all work slightly differently so
      # add additional layers in case of bugs.

      ## THESE SETTINGS ARE A GOOD IDEA BUT THE STEAM CLIENT IS
      ## REALLY, REALLY BAD, AND FOR SOME REASON I NEED TO USE IT TO
      ## DOWNLOAD GAME SERVERS AS WELL:
      ##
      # To guarantee the above (only permits 64-bit syscalls, 32-bit
      # syscalls can circumvent the above restrictions).
      #
      # Obviously, if running a 32 bit game server, change this.
      # SystemCallArchitectures = "native";
      # Game servers shouldn't need to create new namespaces ever.
      #
      # TODO: Since steam uses namespaces for things *entirely
      # unrelated* to installing game servers, we need to allow
      # namespace access. Ideally I'd instead do this in an
      # ExecStartPre, but alas, this isn't possible because of
      # https://github.com/systemd/systemd/issues/19604.
      #
      # RestrictNamespaces = true;

      # Don't need to let the game server see other user accounts
      PrivateUsers = true;
      # *Probably* not harmful for game servers, which probably don't update dynamically
      ProtectHostname = true;
      # Yeah, if a game server tries to edit the hardware clock something's fishy
      ProtectClock = true;
      # Don't let game servers modify kernel settings, duh
      ProtectKernelTunables = true;
      ProtectKernelModules = true;
      ProtectKernelLogs = true;
      # Game servers shouldn't use cgroups themselves either
      ProtectControlGroups = true;
      # Most game servers will never need other socket types
      RestrictAddressFamilies = [ "AF_UNIX AF_INET AF_INET6" ];
      # Also a no-brainer, no game server should ever need this
      LockPersonality = true;
      # Some game servers will probably try to set this, but they
      # don't need it. It's only required for audio processing and
      # such, which the server end doesn't need to do.
      RestrictRealtime = true;
      # Don't allow a variety of syscalls that gameservers have no
      # business using anyway
      SystemCallFilter =
        "~"
        + (concatStringsSep " " [
          "@clock"
          "@cpu-emulation"
          "@debug"
          "@keyring"
          "@memlock"
          "@module"
          # "@mount"  TODO: Consider adding when steamcmd is run in ExecStartPre
          "@obsolete"
          "@raw-io"
          "@reboot"
          # "@resources" TODO: Ditto
          "@setuid"
          "@swap"
        ]);
      # Normally only "read-only", but steamcmd will puke if there is
      # no home directory to write to (though the nix package will
      # implicitly symlink to the path that we set in its override, so
      # no actual files are created, besides a symlink).
      ProtectHome = "tmpfs";

      # Implied by DynamicUser anyway, but it doesn't hurt to add
      # these explicitly, at least for reference.
      RemoveIPC = true;
      PrivateTmp = true;
      PrivateDevices = true;
      NoNewPrivileges = true;
      RestrictSUIDSGID = true;
      ProtectSystem = "strict";
      # ProtectHome = "read-only"; # See further up
    };
  };

  services.backups.starbound = {
    user = "root";
    paths = [ "/var/lib/private/starbound/storage/universe/" ];
    pauseServices = [ "starbound.service" ];
  };
}