diff --git a/flake.lock b/flake.lock index 4dc2a78..0de2c64 100644 --- a/flake.lock +++ b/flake.lock @@ -114,6 +114,22 @@ "type": "github" } }, + "coffeepaste": { + "flake": false, + "locked": { + "lastModified": 1633818370, + "narHash": "sha256-zsdLUdTiqnnYRe17HndoAfOWGGB08UBsXP6A7FpG1Sc=", + "owner": "~mort", + "repo": "coffeepaste", + "rev": "92795c856c6227d334635538d5176f6fe34de988", + "type": "sourcehut" + }, + "original": { + "owner": "~mort", + "repo": "coffeepaste", + "type": "sourcehut" + } + }, "deploy-rs": { "inputs": { "flake-compat": "flake-compat", @@ -567,6 +583,7 @@ }, "root": { "inputs": { + "coffeepaste": "coffeepaste", "deploy-rs": "deploy-rs", "disko": "disko", "flake-utils": "flake-utils", diff --git a/flake.nix b/flake.nix index 0841277..da212a0 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,11 @@ url = "github:Alexays/Waybar"; inputs.nixpkgs.follows = "nixpkgs"; }; + + coffeepaste = { + url = "sourcehut:~mort/coffeepaste"; + flake = false; + }; }; outputs = { diff --git a/host/common/coffeepaste.nix b/host/common/coffeepaste.nix new file mode 100644 index 0000000..46e050c --- /dev/null +++ b/host/common/coffeepaste.nix @@ -0,0 +1,138 @@ +{ + config, + lib, + pkgs, + inputs, + ... +}: let + inherit (lib) mkDefault; + inherit (lib.options) mkOption mkEnableOption; + cfg = config.services.coffeepaste; + + configFile = (pkgs.formats.toml {}).generate "config.toml" { + inherit (cfg) url max_file_size expiration_days; + listen = "${cfg.listenAddr}:${builtins.toString cfg.listenPort}"; + data = "${cfg.dataDir}/data"; + }; +in { + options.services.coffeepaste = { + enable = mkEnableOption "coffeepaste"; + + user = mkOption { + default = "coffeepaste"; + type = lib.types.str; + }; + + group = mkOption { + default = "coffeepaste"; + type = lib.types.str; + }; + + url = mkOption { + default = "https://example.com"; + type = lib.types.str; + }; + + listenAddr = mkOption { + default = "[::1]"; + type = lib.types.str; + }; + listenPort = mkOption { + default = 8080; + type = lib.types.ints.unsigned; + }; + + dataDir = mkOption { + default = "/var/lib/coffeepaste"; + type = lib.types.path; + }; + + max_file_size = mkOption { + default = 15000000; + type = lib.types.ints.unsigned; + }; + + expiration_days = mkOption { + default = 30; + type = lib.types.ints.unsigned; + }; + }; + + config = lib.mkIf cfg.enable { + nixpkgs.overlays = [ + (final: _: { + coffeepaste = final.rustPlatform.buildRustPackage rec { + pname = "coffeepaste"; + version = "1.5.1"; + + src = inputs.coffeepaste; + cargoLock.lockFile = "${src}/Cargo.lock"; + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + buildInputs = with pkgs; [ + glib + gexiv2 + ]; + + postInstall = '' + mkdir -p "$out/share" + cp ${configFile} "$out/share/config.toml" + ''; + + meta = with pkgs.lib; { + description = "A neat pastebin"; + homepage = "https://git.sr.ht/~mort/coffeepaste"; + license = licenses.agpl3Only; + maintainers = [ + { + name = "aftix"; + email = "aftix@aftix.xyz"; + github = "aftix"; + } + ]; + }; + }; + }) + ]; + + users = { + users.${cfg.user} = { + isSystemUser = mkDefault true; + group = mkDefault cfg.group; + shell = mkDefault "/run/current-system/sw/bin/nologin"; + }; + groups.${cfg.group} = {}; + }; + + systemd = { + tmpfiles.rules = [ + "d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} -" + "d ${cfg.dataDir}/data 0750 ${cfg.user} ${cfg.group} -" + ]; + + services.coffeepaste = { + wants = ["network.target"]; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + unitConfig.Description = "A neat pastebin"; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + WorkingDirectory = cfg.dataDir; + ProtectSystem = "strict"; + PrivateTmp = true; + PrivateDevices = true; + ProtectHome = "read-only"; + NoNewPrivileges = true; + ReadWritePaths = cfg.dataDir; + MemoryDenyWriteExecute = true; + }; + script = "${pkgs.coffeepaste}/bin/coffeepaste"; + preStart = "cp ${pkgs.coffeepaste}/share/config.toml ${cfg.dataDir}/config.toml"; + }; + }; + }; +} diff --git a/host/common/default.nix b/host/common/default.nix index a6a29b3..9e2142a 100644 --- a/host/common/default.nix +++ b/host/common/default.nix @@ -9,6 +9,7 @@ in { imports = [ ./apparmor.nix ./channels.nix + ./coffeepaste.nix ./nh.nix ./root.nix ./sleep.nix diff --git a/host/fermi.nix b/host/fermi.nix index e387f58..06dfbb5 100644 --- a/host/fermi.nix +++ b/host/fermi.nix @@ -49,6 +49,7 @@ in { services = { openssh.settings.AllowUsers = ["aftix"]; + coffeepaste.enable = true; }; users = { diff --git a/host/opt/www/coffeepaste.nix b/host/opt/www/coffeepaste.nix new file mode 100644 index 0000000..8358358 --- /dev/null +++ b/host/opt/www/coffeepaste.nix @@ -0,0 +1,61 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf mkDefault; + cfg = config.my.www; +in { + options.my.www.coffeepasteSubdomain = lib.options.mkOption { + default = "file"; + type = lib.types.str; + }; + + config = mkIf config.services.coffeepaste.enable { + security.acme.certs.${cfg.hostname}.extraDomainNames = [ + "${cfg.coffeepasteSubdomain}.${cfg.hostname}" + "www.${cfg.coffeepasteSubdomain}.${cfg.hostname}" + ]; + + services = { + coffeepaste = { + user = mkDefault cfg.user; + group = mkDefault cfg.group; + url = mkDefault "https://${cfg.coffeepasteSubdomain}.${cfg.hostname}"; + }; + + nginx.virtualHosts."${cfg.coffeepasteSubdomain}.${cfg.hostname}" = { + serverName = "${cfg.coffeepasteSubdomain}.${cfg.hostname} www.${cfg.coffeepasteSubdomain}.${cfg.hostname}"; + kTLS = true; + forceSSL = true; + useACMEHost = cfg.hostname; + + extraConfig = '' + error_page 599 = @putrequest; + if ($request_method = 'PUT') { + return 599; + } + ''; + + locations = { + "/" = { + proxyPass = "http://localhost:${builtins.toString config.services.coffeepaste.listenPort}"; + extraConfig = '' + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + ''; + }; + + "@putrequest" = { + proxyPass = "http://localhost:${builtins.toString config.services.coffeepaste.listenPort}"; + extraConfig = '' + limit_req zone=put_request_by_addr burst=10; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + ''; + }; + }; + }; + }; + }; +} diff --git a/host/opt/www/default.nix b/host/opt/www/default.nix index 1d4aa71..97651d4 100644 --- a/host/opt/www/default.nix +++ b/host/opt/www/default.nix @@ -9,6 +9,7 @@ in { imports = [ ./blog.nix + ./coffeepaste.nix ./searx.nix ./znc.nix ]; @@ -115,11 +116,7 @@ in { certs.${cfg.hostname} = { inherit (cfg) group; - extraDomainNames = [ - "www.${cfg.hostname}" - "auth.${cfg.hostname}" - "www.auth.${cfg.hostname}" - ]; + extraDomainNames = ["www.${cfg.hostname}"]; }; }; }; diff --git a/host/opt/www/searx.nix b/host/opt/www/searx.nix index 8eb8f34..0933eaa 100644 --- a/host/opt/www/searx.nix +++ b/host/opt/www/searx.nix @@ -35,7 +35,7 @@ in { systemd.tmpfiles.rules = let inherit (config.services.searx.uwsgiConfig) immediate-uid immediate-gid; in [ - "d ${builtins.baseNameOf socket} 0775 ${immediate-uid} ${immediate-gid} -" + "d ${builtins.dirOf socket} 0775 ${immediate-uid} ${immediate-gid} -" ]; environment.etc."nginx/uwsgi_params".text = ''