{ description = "NixOS module for Shunshine"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; flake-parts = { url = "github:hercules-ci/flake-parts"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, flake-parts, ... }@inputs: flake-parts.lib.mkFlake { inherit inputs; } { systems = [ "x86_64-linux" ]; perSystem = { self', pkgs, lib, ... }: { formatter = pkgs.nixpkgs-fmt; devShells.default = with pkgs; mkShell { }; }; flake = { nixosModules.sunshine = { pkgs, config, lib, ... }: with lib; let inherit (pkgs) sunshine; cfg = config.services.sunshine; in { options.services.sunshine = { enable = mkEnableOption "sunshine"; user = mkOption { description = "The user using sunshine"; type = types.str; }; openFirewall = mkOption { description = "Open the necessary ports for sunshine"; type = types.bool; default = false; }; }; config = mkIf cfg.enable { environment.systemPackages = [ sunshine ]; hardware.uinput.enable = true; users.extraUsers.${cfg.user}.extraGroups = [ "uinput" "video" ]; security.wrappers.sunshine = { owner = "root"; group = "root"; capabilities = "cap_sys_admin+p"; source = "${sunshine}/bin/sunshine"; }; systemd.user.services.sunshine = { description = "Sunshine is a Gamestream host for Moonlight"; serviceConfig.ExecStart = "${config.security.wrapperDir}/sunshine"; wantedBy = [ "graphical-session.target" ]; }; networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = [ 48010 ]; allowedTCPPortRanges = [ { from = 47984; to = 47990; } ]; allowedUDPPortRanges = [ { from = 47998; to = 48000; } ]; }; }; }; }; }; }