1
0
Fork 0

Compare commits

..

No commits in common. "e386e5454c4b6fa353d698b6fe2ed7b367c115e8" and "8115b622ed9d77502017f42be42b97baf65cdc56" have entirely different histories.

7 changed files with 280 additions and 10 deletions

View file

@ -26,6 +26,7 @@ in
extraPackages = with pkgs; [
steamtinkerlaunch
proton-ge-bin
awesome-flake.proton-ge-bin-9
];
};

View file

@ -0,0 +1,3 @@
{
programs.nvf.settings.vim.editorconfig.enable = true;
}

View file

@ -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;

View file

@ -58,9 +58,6 @@ in
useACMEHost = "stahl.sh";
locations."/" = {
root = enteApp;
extraConfig = ''
try_files $uri $uri/ /index.html;
'';
};
};
};

View file

@ -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=<secret>
POSTGRES_PASSWORD=<pass>
```
'';
};
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;

View file

@ -5,5 +5,5 @@
}:
final: prev: {
inherit (channels.unstable) prisma;
inherit (channels.stable) prisma;
}

View file

@ -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: <https://github.com/NixOS/nixpkgs/pull/294532#issuecomment-1987359650>
*/
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 ];
};
})