commit d6c38fb9bd525a8bb47f5d7d8f0576d6c11a44ae Author: Erwin Boskma Date: Mon Sep 26 11:59:48 2022 +0200 Initial commit diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..a6bd698 --- /dev/null +++ b/default.nix @@ -0,0 +1,9 @@ +(import ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + }) { + src = ./.; +}).defaultNix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bdc21f4 --- /dev/null +++ b/flake.lock @@ -0,0 +1,39 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1663850217, + "narHash": "sha256-tp9nXo1/IdN/xN9m06ryy0QUAEfoN6K56ObM/1QTAjc=", + "path": "/nix/store/if56vv9237zafkzgzcdkqxf2lmp86myq-source", + "rev": "ae1dc133ea5f1538d035af41e5ddbc2ebcb67b90", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..d6e18f2 --- /dev/null +++ b/flake.nix @@ -0,0 +1,125 @@ +{ + description = "A very basic flake"; + + inputs = { + nixpkgs = { }; + flake-utils = { }; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachSystem [ "x86_64-linux" ] (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + lib = nixpkgs.lib; + in + { + formatter = pkgs.nixpkgs-fmt; + packages = { + sunshine = pkgs.stdenv.mkDerivation { + pname = "sunshine"; + version = "0.14.1"; + + src = pkgs.fetchFromGitHub { + owner = "LizardByte"; + repo = "Sunshine"; + rev = "6000b85b1a4ec574d93fbc7545f5bf48f3d5aaa7"; + sha256 = "SB2DAOYf2izIwwRWEw2wt5L5oCDbb6YOqXw/z/PD1pQ="; + fetchSubmodules = true; + }; + + buildInputs = with pkgs; [ + avahi + (boost.override { enableStatic = true; }) + ffmpeg + libevdev + libpulseaudio + xorg.libX11 + xorg.libxcb + xorg.libXfixes + xorg.libXrandr + xorg.libXtst + openssl + libopus + udev + libdrm + valgrind.dev + wayland + libffi + icu + ]; + + hardeningDisable = [ "format" ]; + + nativeBuildInputs = with pkgs; [ + cmake + pkgconf + makeWrapper + ]; + + cmakeFlags = [ + "-DSUNSHINE_ASSETS_DIR=${placeholder "out"}/etc/sunshine" + "-DSUNSHINE_CONFIG_DIR=${placeholder "out"}/etc/sunshine" + ]; + + # patches = [ ./001-cmake-find-evdev.patch ]; + patches = [ ./sunshine.patch ]; + + preConfigure = '' + substituteInPlace CMakeLists.txt \ + --replace "/usr/include/libevdev-1.0" "${pkgs.libevdev}/include/libevdev-1.0" \ + --replace "/etc/udev/rules.d" "$out/etc/udev/rules.d" \ + --replace "/usr/bin" "$out/bin" \ + --replace "/usr/lib/systemd/user" "$out/lib/systemd/user" + ''; + + postInstall = '' + wrapProgram $out/bin/sunshine --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath (with pkgs; [ avahi mesa libGL ])}" + ''; + }; + }; + packages.default = self.packages.${system}.sunshine; + + devShells.default = with pkgs; mkShell { + nativeBuildInputs = [ nix-prefetch-scripts nix-prefetch-github cmake-language-server ]; + inputsFrom = [ self.packages.${system}.sunshine ]; + }; + + }) // { + nixosModule.sunshine = { pkgs, config, lib, ... }: + with lib; + let + cfg = config.services.sunshine; + sunshine = self.packages.${pkgs.system}.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 = true; + + users.extraUsers.${cfg.user}.extraGroups = [ "uinput" "video" ]; + security.wrappers.sunshine = { + owner = "root"; + group = "root"; + capabilities = "cap_sys_admin+p"; + source = "${sunshine}/bin/sunshine"; + }; + }; + }; + }; +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..e35e01f --- /dev/null +++ b/shell.nix @@ -0,0 +1,9 @@ +(import ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + }) { + src = ./.; +}).shellNix diff --git a/sunshine.patch b/sunshine.patch new file mode 100644 index 0000000..cde882a --- /dev/null +++ b/sunshine.patch @@ -0,0 +1,48 @@ +diff --git a/src/config.cpp b/src/config.cpp +index fd88760..04f2489 100644 +--- a/src/config.cpp ++++ b/src/config.cpp +@@ -20,7 +20,7 @@ using namespace std::literals; + #define PRIVATE_KEY_FILE CA_DIR "/cakey.pem" + #define CERTIFICATE_FILE CA_DIR "/cacert.pem" + +-#define APPS_JSON_PATH platf::appdata().string() + "/apps.json" ++#define APPS_JSON_PATH "apps.json" + namespace config { + + namespace nv { +@@ -292,7 +292,7 @@ sunshine_t sunshine { + {}, // Username + {}, // Password + {}, // Password Salt +- platf::appdata().string() + "/sunshine.conf", // config file ++ "sunshine.conf", // config file + {}, // cmd args + 47989, + }; +@@ -703,6 +703,7 @@ int apply_flags(const char *line) { + void apply_config(std::unordered_map &&vars) { + if(!fs::exists(stream.file_apps.c_str())) { + fs::copy_file(SUNSHINE_CONFIG_DIR "/apps.json", stream.file_apps); ++ fs::permissions(stream.file_apps, fs::perms::owner_write, fs::perm_options::add); + } + + for(auto &[name, val] : vars) { +@@ -910,11 +911,16 @@ int parse(int argc, char *argv[]) { + } + } + ++ std::unordered_map vars; ++ path_f(vars, "config_file", sunshine.config_file); ++ path_f(vars, "file_apps", stream.file_apps); ++ + if(!fs::exists(sunshine.config_file)) { + fs::copy_file(SUNSHINE_CONFIG_DIR "/sunshine.conf", sunshine.config_file); ++ fs::permissions(sunshine.config_file, fs::perms::owner_write, fs::perm_options::add); + } + +- auto vars = parse_config(read_file(sunshine.config_file.c_str())); ++ vars = parse_config(read_file(sunshine.config_file.c_str())); + + for(auto &[name, value] : cmd_vars) { + vars.insert_or_assign(std::move(name), std::move(value));