diff --git a/modules/nixos/apps/steam/default.nix b/modules/nixos/apps/steam/default.nix index 1051363..8ee103d 100644 --- a/modules/nixos/apps/steam/default.nix +++ b/modules/nixos/apps/steam/default.nix @@ -26,6 +26,7 @@ in extraPackages = with pkgs; [ steamtinkerlaunch proton-ge-bin + awesome-flake.proton-ge-bin-9 ]; }; diff --git a/modules/nixos/cli/neovim/editorconfig/default.nix b/modules/nixos/cli/neovim/editorconfig/default.nix new file mode 100644 index 0000000..0567c7a --- /dev/null +++ b/modules/nixos/cli/neovim/editorconfig/default.nix @@ -0,0 +1,3 @@ +{ + programs.nvf.settings.vim.editorconfig.enable = true; +} diff --git a/modules/nixos/cli/neovim/lsp/default.nix b/modules/nixos/cli/neovim/lsp/default.nix index 0509b91..670f9d9 100644 --- a/modules/nixos/cli/neovim/lsp/default.nix +++ b/modules/nixos/cli/neovim/lsp/default.nix @@ -4,7 +4,7 @@ languages = { enableTreesitter = true; nix.enable = true; - nix.format.type = [ "nixfmt" ]; + nix.format.type = "nixfmt"; bash.enable = true; go.enable = true; rust.enable = true; diff --git a/modules/nixos/services/ente-auth/default.nix b/modules/nixos/services/ente-auth/default.nix index e4d2744..9e351da 100644 --- a/modules/nixos/services/ente-auth/default.nix +++ b/modules/nixos/services/ente-auth/default.nix @@ -58,9 +58,6 @@ in useACMEHost = "stahl.sh"; locations."/" = { root = enteApp; - extraConfig = '' - try_files $uri $uri/ /index.html; - ''; }; }; }; diff --git a/modules/nixos/services/linkwarden/default.nix b/modules/nixos/services/linkwarden/default.nix index 598709b..5474e23 100644 --- a/modules/nixos/services/linkwarden/default.nix +++ b/modules/nixos/services/linkwarden/default.nix @@ -19,7 +19,7 @@ in { options.${namespace}.services.linkwarden = { enable = mkEnableOption "Linkwarden"; - package = lib.mkPackageOption pkgs "linkwarden" { }; + package = lib.mkPackageOption pkgs.awesome-flake "linkwarden" { }; nginx = { enable = mkEnableOption "Enable nginx for this service." // { default = true; @@ -32,6 +32,49 @@ in default = "link.stahl.sh"; }; + storageLocation = mkOption { + type = types.path; + default = "/var/lib/linkwarden"; + description = "Directory used to store media files. If it is not the default, the directory has to be created manually such that the linkwarden user is able to read and write to it."; + }; + cacheLocation = mkOption { + type = types.path; + default = "/var/cache/linkwarden"; + description = "Directory used as cache. If it is not the default, the directory has to be created manually such that the linkwarden user is able to read and write to it."; + }; + + environment = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { + PAGINATION_TAKE_COUNT = "50"; + }; + description = '' + Extra configuration environment variables. Refer to the [documentation](https://docs.linkwarden.app/self-hosting/environment-variables) for options. + ''; + }; + + secretsFile = mkOption { + type = types.str // { + # We don't want users to be able to pass a path literal here but + # it should look like a path. + check = it: lib.isString it && lib.types.path.check it; + }; + example = "/run/secrets/linkwarden"; + default = "/run/secrets/linkwarden"; + description = '' + Path of a file with extra environment variables to be loaded from disk. + This file is not added to the nix store, so it can be used to pass secrets to linkwarden. + Refer to the [documentation](https://docs.linkwarden.app/self-hosting/environment-variables) for options. + + Linkwarden needs at least a nextauth secret. To set a database password use POSTGRES_PASSWORD: + ``` + NEXTAUTH_SECRET= + POSTGRES_PASSWORD= + ``` + ''; + }; + host = mkOption { type = types.str; default = "0.0.0.0"; @@ -44,16 +87,162 @@ in description = "The port that Linkwarden will listen on."; }; + user = mkOption { + type = types.str; + default = "linkwarden"; + description = "The user Linkwarden should run as."; + }; + + group = mkOption { + type = types.str; + default = "linkwarden"; + description = "The group Linkwarden should run as."; + }; + + database = { + enable = + mkEnableOption "the postgresql database for use with Linkwarden. See {option}`services.postgresql`" + // { + default = true; + }; + + createDB = mkEnableOption "the automatic creation of the database for Linkwarden." // { + default = true; + }; + + name = mkOption { + type = types.str; + default = "linkwarden"; + description = "The name of the Linkwarden database."; + }; + + host = mkOption { + type = types.str; + default = "/run/postgresql"; + example = "127.0.0.1"; + description = "Hostname or address of the postgresql server. If an absolute path is given here, it will be interpreted as a unix socket path."; + }; + + port = mkOption { + type = types.port; + default = 5432; + description = "Port of the postgresql server."; + }; + + user = mkOption { + type = types.str; + default = "linkwarden"; + description = "The database user for Linkwarden."; + }; + }; }; config = mkIf cfg.enable { - services.linkwarden = { + assertions = [ + { + assertion = cfg.database.createDB -> cfg.database.name == cfg.database.user; + message = "The postgres module requires the database name and the database user name to be the same."; + } + ]; + + services.postgresql = mkIf cfg.database.enable { enable = true; - host = cfg.host; - port = cfg.port; - environmentFile = "/run/secrets/linkwarden"; + ensureDatabases = mkIf cfg.database.createDB [ cfg.database.name ]; + ensureUsers = mkIf cfg.database.createDB [ + { + name = cfg.database.user; + ensureDBOwnership = true; + ensureClauses.login = true; + } + ]; }; + networking.firewall.allowedTCPPorts = [ + cfg.port + 80 + 443 + ]; + + ${namespace}.services = { + acme.enable = mkIf cfg.nginx.enable true; + linkwarden.environment = { + LINKWARDEN_HOST = cfg.host; + LINKWARDEN_PORT = toString cfg.port; + LINKWARDEN_CACHE_DIR = cfg.cacheLocation; + STORAGE_FOLDER = cfg.storageLocation; + NEXT_PUBLIC_DISABLE_REGISTRATION = "true"; + NEXTAUTH_URL = "https://link.boehm.sh"; + NEXTAUTH_INTERNAL_URL = "https://link.boehm.sh"; + DATABASE_URL = mkIf isPostgresUnixSocket "postgresql://${lib.strings.escapeURL cfg.database.user}@localhost/${lib.strings.escapeURL cfg.database.name}?host=${cfg.database.host}"; + DATABASE_PORT = toString cfg.database.port; + DATABASE_HOST = mkIf (!isPostgresUnixSocket) cfg.database.host; + DATABASE_NAME = cfg.database.name; + DATABASE_USER = cfg.database.user; + }; + }; + + systemd.services.linkwarden = { + description = "Linkwarden (Self-hosted collaborative bookmark manager to collect, organize, and preserve webpages, articles, and more...)"; + requires = [ + "network-online.target" + ] + ++ lib.optionals cfg.database.enable [ "postgresql.service" ]; + after = [ + "network-online.target" + ] + ++ lib.optionals cfg.database.enable [ "postgresql.service" ]; + wantedBy = [ "multi-user.target" ]; + environment = cfg.environment // { + # Required, otherwise chrome dumps core + CHROME_CONFIG_HOME = cfg.cacheLocation; + }; + + serviceConfig = { + Type = "simple"; + Restart = "on-failure"; + RestartSec = 3; + + ExecStart = lib.getExe cfg.package; + EnvironmentFile = cfg.secretsFile; + StateDirectory = "linkwarden"; + CacheDirectory = "linkwarden"; + User = cfg.user; + Group = cfg.group; + + # Hardening + CapabilityBoundingSet = ""; + NoNewPrivileges = true; + PrivateUsers = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateMounts = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + }; + }; + + users.users = mkIf (cfg.user == "linkwarden") { + linkwarden = { + name = "linkwarden"; + group = cfg.group; + isSystemUser = true; + }; + }; + users.groups = mkIf (cfg.group == "linkwarden") { linkwarden = { }; }; + services.nginx = mkIf cfg.nginx.enable { enable = true; diff --git a/overlays/prisma/default.nix b/overlays/prisma/default.nix index 33a367e..f25d0bd 100644 --- a/overlays/prisma/default.nix +++ b/overlays/prisma/default.nix @@ -5,5 +5,5 @@ }: final: prev: { - inherit (channels.unstable) prisma; + inherit (channels.stable) prisma; } diff --git a/packages/proton-ge-bin-9/default.nix b/packages/proton-ge-bin-9/default.nix new file mode 100644 index 0000000..0d4dd2c --- /dev/null +++ b/packages/proton-ge-bin-9/default.nix @@ -0,0 +1,80 @@ +{ + lib, + stdenvNoCC, + fetchzip, + writeScript, + # Can be overridden to alter the display name in steam + # This could be useful if multiple versions should be installed together + steamDisplayName ? "GE-Proton", +}: +stdenvNoCC.mkDerivation (finalAttrs: { + pname = "proton-ge-bin-9"; + version = "GE-Proton9-27"; + + src = fetchzip { + url = "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/${finalAttrs.version}/${finalAttrs.version}.tar.gz"; + hash = "sha256-70au1dx9co3X+X7xkBCDGf1BxEouuw3zN+7eDyT7i5c="; + }; + + dontUnpack = true; + dontConfigure = true; + dontBuild = true; + + outputs = [ + "out" + "steamcompattool" + ]; + + installPhase = '' + runHook preInstall + + # Make it impossible to add to an environment. You should use the appropriate NixOS option. + # Also leave some breadcrumbs in the file. + echo "${finalAttrs.pname} should not be installed into environments. Please use programs.steam.extraCompatPackages instead." > $out + + mkdir $steamcompattool + ln -s $src/* $steamcompattool + rm $steamcompattool/compatibilitytool.vdf + cp $src/compatibilitytool.vdf $steamcompattool + + runHook postInstall + ''; + + preFixup = '' + substituteInPlace "$steamcompattool/compatibilitytool.vdf" \ + --replace-fail "${finalAttrs.version}" "${steamDisplayName}" + ''; + + /* + We use the created releases, and not the tags, for the update script as nix-update loads releases.atom + that contains both. Sometimes upstream pushes the tags but the Github releases don't get created due to + CI errors. Last time this happened was on 8-33, where a tag was created but no releases were created. + As of 2024-03-13, there have been no announcements indicating that the CI has been fixed, and thus + we avoid nix-update-script and use our own update script instead. + See: + */ + passthru.updateScript = writeScript "update-proton-ge" '' + #!/usr/bin/env nix-shell + #!nix-shell -i bash -p curl jq common-updater-scripts + repo="https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases" + version="$(curl -sL "$repo" | jq 'map(select(.prerelease == false)) | .[0].tag_name' --raw-output)" + update-source-version proton-ge-bin "$version" + ''; + + meta = { + description = '' + Compatibility tool for Steam Play based on Wine and additional components. + + (This is intended for use in the `programs.steam.extraCompatPackages` option only.) + ''; + homepage = "https://github.com/GloriousEggroll/proton-ge-custom"; + license = lib.licenses.bsd3; + maintainers = with lib.maintainers; [ + NotAShelf + Scrumplex + shawn8901 + ]; + platforms = [ "x86_64-linux" ]; + sourceProvenance = [ lib.sourceTypes.binaryNativeCode ]; + }; +})