diff --git a/home/david/configurations/Tytonidae/default.nix b/home/david/configurations/Tytonidae/default.nix index 908b254..9ed9af6 100644 --- a/home/david/configurations/Tytonidae/default.nix +++ b/home/david/configurations/Tytonidae/default.nix @@ -15,6 +15,7 @@ youthlic = { xdg-dirs.enable = true; programs = { + rustypaste-cli.enable = true; firefox.enable = true; fuzzel.enable = true; helix.enable = true; diff --git a/home/modules/programs/default.nix b/home/modules/programs/default.nix index 9e38361..35c726a 100644 --- a/home/modules/programs/default.nix +++ b/home/modules/programs/default.nix @@ -1,6 +1,7 @@ { ... }: { imports = [ + ./rustypaste-cli.nix ./atuin.nix ./firefox.nix ./shell diff --git a/home/modules/programs/rustypaste-cli.nix b/home/modules/programs/rustypaste-cli.nix new file mode 100644 index 0000000..82dcba4 --- /dev/null +++ b/home/modules/programs/rustypaste-cli.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.youthlic.programs.rustypaste-cli; +in +{ + options = { + youthlic.programs.rustypaste-cli = { + enable = lib.mkEnableOption "rustypaste-cli"; + }; + }; + config = lib.mkIf cfg.enable { + home.packages = [ pkgs.rustypaste-cli ]; + sops = { + secrets = { + "rustypaste/auth" = { }; + "rustypaste/delete" = { }; + }; + templates."rustypaste-config.toml" = { + path = "${config.xdg.configHome}/rustypaste/config.toml"; + content = '' + [server] + address = "https://paste.youthlic.fun" + auth_token = "${config.sops.placeholder."rustypaste/auth"}" + delete_token = "${config.sops.placeholder."rustypaste/delete"}" + + [paste] + oneshot = false + + [style] + prettify = true + ''; + }; + }; + }; +} diff --git a/nixos/configurations/Cape/default.nix b/nixos/configurations/Cape/default.nix index 33450fc..20a8c50 100644 --- a/nixos/configurations/Cape/default.nix +++ b/nixos/configurations/Cape/default.nix @@ -20,6 +20,10 @@ }; users.deploy.enable = true; programs = { + rustypaste = { + enable = true; + url = "https://paste.youthlic.fun"; + }; openssh.enable = true; tailscale.enable = true; conduwuit = { diff --git a/nixos/modules/programs/default.nix b/nixos/modules/programs/default.nix index 42d2af1..0356117 100644 --- a/nixos/modules/programs/default.nix +++ b/nixos/modules/programs/default.nix @@ -1,6 +1,7 @@ { config, lib, ... }: { imports = [ + ./rustypaste ./mautrix-telegram.nix ./caddy.nix ./dae diff --git a/nixos/modules/programs/rustypaste/default.nix b/nixos/modules/programs/rustypaste/default.nix new file mode 100644 index 0000000..f866287 --- /dev/null +++ b/nixos/modules/programs/rustypaste/default.nix @@ -0,0 +1,147 @@ +{ lib, config, ... }: +let + cfg = config.youthlic.programs.rustypaste; +in +{ + imports = [ + ./template.nix + ]; + + options = { + youthlic.programs.rustypaste = { + enable = lib.mkEnableOption "rustypaste"; + listen = lib.mkOption { + type = lib.types.nonEmptyStr; + example = "0.0.0.0"; + default = "127.0.0.1"; + }; + url = lib.mkOption { + type = lib.types.nullOr lib.types.nonEmptyStr; + example = "https://paste.example.com"; + default = null; + }; + }; + }; + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + sops.secrets = { + "rustypaste/auth" = { + group = "rustypaste"; + mode = "0440"; + }; + "rustypaste/delete" = { + group = "rustypaste"; + mode = "0440"; + }; + }; + services.rustypaste = { + enable = true; + port = 8483; + group = "rustypaste"; + settings = { + config = { + refresh_rate = "1s"; + }; + server = { + address = "${cfg.listen}:8483"; + url = lib.mkIf (cfg.url != null) cfg.url; + upload_path = "/var/lib/rustypaste/"; + max_content_length = "10GB"; + timeout = "30s"; + expose_version = true; + expose_list = true; + handle_spaces = "encode"; + }; + paste = { + duplicate_files = true; + default_expiry = "3h"; + delete_expired_files = { + enabled = true; + interval = "3h"; + }; + random_url = { + type = "petname"; + words = 2; + separator = "-"; + }; + default_extension = "txt"; + main_blacklist = [ + "application/x-dosexec" + "application/java-archive" + "application/java-vm" + ]; + mine_override = [ + { + mime = "image/jpeg"; + regex = "^.*\\.jpg$"; + } + { + mime = "image/png"; + regex = "^.*\\.png$"; + } + { + mime = "image/svg+xml"; + regex = "^.*\\.svg$"; + } + { + mime = "video/webm"; + regex = "^.*\\.webm$"; + } + { + mime = "video/x-matroska"; + regex = "^.*\\.mkv$"; + } + { + mime = "application/octet-stream"; + regex = "^.*\\.bin$"; + } + { + mime = "text/plain"; + regex = "^.*\\.(log|txt|diff|sh|rs|toml|py|json|yaml|yml|ts|js|go|c|C|c++|cpp|cxx)$"; + } + ]; + }; + landing_page = { + content_type = "text/plain; charset=utf-8"; + text = '' + ┬─┐┬ ┬┌─┐┌┬┐┬ ┬┌─┐┌─┐┌─┐┌┬┐┌─┐ + ├┬┘│ │└─┐ │ └┬┘├─┘├─┤└─┐ │ ├┤ + ┴└─└─┘└─┘ ┴ ┴ ┴ ┴ ┴└─┘ ┴ └─┘ + + Submit files via HTTP POST here: + curl -F 'file=@example.txt' + This will return the URL of the uploaded file. + + The server administrator might remove any pastes that they do not personally + want to host. + + If you are the server administrator and want to change this page, just go + into your config file and change it! If you change the expiry time, it is + recommended that you do. + + By default, pastes expire every hour. The server admin may or may not have + changed this. + + Check out the GitHub repository at https://github.com/orhun/rustypaste + Command line tool is available at https://github.com/orhun/rustypaste-cli + ''; + }; + }; + env = { + AUTH_TOKENS_FILE = "${config.sops.secrets."rustypaste/auth".path}"; + DELETE_TOKENS_FILE = "${config.sops.secrets."rustypaste/delete".path}"; + }; + openFirewall = true; + }; + }) + (lib.mkIf (cfg.enable && config.youthlic.programs.caddy.enable) { + services.caddy.virtualHosts = { + "paste.${config.youthlic.programs.caddy.baseDomain}" = { + extraConfig = '' + reverse_proxy 127.0.0.1:8483 + ''; + }; + }; + }) + ]; +} diff --git a/nixos/modules/programs/rustypaste/template.nix b/nixos/modules/programs/rustypaste/template.nix new file mode 100644 index 0000000..2cf4d9b --- /dev/null +++ b/nixos/modules/programs/rustypaste/template.nix @@ -0,0 +1,102 @@ +{ + pkgs, + lib, + config, + ... +}: +let + cfg = config.services.rustypaste; + settingsFormat = pkgs.formats.toml { }; + configFile = settingsFormat.generate "rustypaste-config.toml" cfg.settings; +in +{ + options = { + services.rustypaste = { + enable = lib.mkEnableOption "rustypaste"; + package = lib.mkPackageOption pkgs "rustypaste" { }; + settings = lib.mkOption { + type = settingsFormat.type; + default = { }; + description = '' + Rustypaste configuration + ''; + }; + port = lib.mkOption { + type = lib.types.port; + default = 8000; + example = 32456; + }; + group = lib.mkOption { + type = lib.types.nonEmptyStr; + example = "rustypaste"; + default = "rustypaste"; + }; + env = { + AUTH_TOKENS_FILE = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + }; + DELETE_TOKENS_FILE = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + }; + }; + openFirewall = lib.mkEnableOption "open port for rustypaste"; + }; + }; + config = lib.mkIf cfg.enable { + environment.systemPackages = [ + cfg.package + ]; + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ + cfg.port + ]; + allowedUDPPorts = [ + cfg.port + ]; + }; + users = { + users.rustypaste = { + group = cfg.group; + home = "/var/lib/rustypaste"; + isSystemUser = true; + }; + groups = lib.optionalAttrs (cfg.group == "rustypaste") { + rustypaste = { }; + }; + }; + systemd.services.rustypaste = { + description = '' + rustypaste Service + ''; + documentation = [ + "https://github.com/orhun/rustypaste" + ]; + after = [ + "network.target" + ]; + wantedBy = [ + "multi-user.target" + ]; + environment = { + CONFIG = "${configFile}"; + AUTH_TOKENS_FILE = lib.mkIf (cfg.env.AUTH_TOKENS_FILE != null) cfg.env.AUTH_TOKENS_FILE; + DELETE_TOKENS_FILE = lib.mkIf (cfg.env.DELETE_TOKENS_FILE != null) cfg.env.DELETE_TOKENS_FILE; + }; + serviceConfig = { + Type = "simple"; + Restart = "on-failure"; + Home = "/var/lib/rustypaste"; + ReadWritePaths = [ "/var/lib/rustypaste" ]; + StateDirectory = [ "rustypaste" ]; + ExecStart = '' + ${lib.getExe cfg.package} + ''; + Group = cfg.group; + User = "rustypaste"; + RestartPreventExitStatus = 1; + }; + }; + }; +} diff --git a/secrets/general.yaml b/secrets/general.yaml index 379ea97..10c4d0c 100644 --- a/secrets/general.yaml +++ b/secrets/general.yaml @@ -1,3 +1,6 @@ +rustypaste: + auth: ENC[AES256_GCM,data:DORM12zY0wQQxqBNFYG3oYodhevUJXNjdqJcnyOnuPnZQIsUdEtm4TyNHokUKYoc30s8c6INOFoAB+7210y0dQE3hfg=,iv:Kms90lNPaL5fvQjD31+DZGJf+YQU/tTGLTxrqkvsbDY=,tag:5voNZlwGf2adVQoVqgyRqA==,type:str] + delete: ENC[AES256_GCM,data:fbhJiJhh4YSMZQ6/dfquesJE0sNSn2PUkbjtJmisj5qHtsM=,iv:M1R7giNyLhbj98iiCPENQy44Ixqnie1PHlNcsVs5TLs=,tag:zdBbZ4NR7D4HxsxCizTliw==,type:str] atuin-key: ENC[AES256_GCM,data:e3K7/7BaeXuR+vHJdtO79UQp3XRvROcD8ISkuCp3KGCSlBKUM3GuCwhIeFoIl0fOUqVYOzcCAcjsH2nBRqcXhtS8jhM=,iv:Mh3jsu6mdj0VOLSIoNz/0awyydVf7q3/E7iB7CJi+UA=,tag:xuHhUmK/J2stdjRrtbhQSw==,type:str] matrix-telegram-bot: ENC[AES256_GCM,data:4G9JSR4l3043SM63gvJr0xBFuS11eoesi9rrobTxN9HpEGNklYDWHH/+Bm7P/2Bxnye3CiO/Z8KffvbjH8slRHLtbSpo8lRsfi9uRAbeMl7aXe/nTjpN078QSN3WXXc9XqYq0sxwNKPrnW3bmPQsHUiykZ3Go5A9Qw1iIPvPpXITyNbeD0gA+2CBB7PIURI7X0PIgSfUtMFZvl2J9znqCnlfC41bj6aC3sywsEkpuFJiMEojrwl+XmVS/u4eNMq8KiofVn9QlGx5gdGZ9LfZZdc+8E6u5GovqP2JTwwfaeZPzdwdZ2YsdoAvmgAusMfjCNZvHF7msLsOyNJW4592ZC7+fHhRbkKnVKc3OwA4ILWd9Jl0p0BoS0Ckn3V5nUQFgxVJ2O0yd/FLFaEqbeBLHNqC6u9CTYk82Uy23ilXQYKIc9h2wQkM329E6j9Mk0f9uavoYVPkpz6ahLzcni2W26FUkeaZ7PkrHmHWfJvvvi32GB4+q1m0phPmcd3cKVhXhbhLXiBcx2Rj7Q==,iv:Br0w0SiYajFr8p5CZEg47x3KpJ+AOleHthsEc3ho4YI=,tag:k+wptcSnNzfefF66Ug824Q==,type:str] matrix-reg-token: ENC[AES256_GCM,data:Cr5560L9gQo/tKUz1sQOAg5dckI6SyDxeNyrjW4oI6qkV8bxUrMaAGnVkkeF9TF9FgAnRb+7Lm+axd2SmkPWnqrLll2NzLC01zXht9Mq9RroAPXFraEV1X1Ge1qAAtkr,iv:42r93HLVDKuDCOYlfem7oi3gcHfhDYiNbFKOCHxim+o=,tag:9hWGQrWHsv2eYNgFlHtfeA==,type:str] @@ -50,8 +53,8 @@ sops: a1Y1NU9CK2h1SS83VW42bzBMa01yMXMKI1DBtgNlkNCrxUQvnD6a45mQKNfg5gM4 Zb5buo9Jofj4dn/HFwng3T3gxKTrP2Dh74CAH4L0M5yrF9fzk5TCcQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-02-03T11:00:21Z" - mac: ENC[AES256_GCM,data:tWVQhBcoXzdlC5wQkJ3WHxVSMLOGRqQXjvvNA94BnAgqJgTHymuvLik/8zR2OIskZqzYL0lTXq4OFbm8r552fkx+3+ip45wrtjB0hiSp7lq4lITWnjfZDWr3dBkbFfO2aFij37slpwbVmzGmsM1WaIlfRcauwjOD5IkewiBDY9Y=,iv:GK1WcUSK2WPPplo3uoRJNSmEAPpFObDi784kLuYWtww=,tag:M7YLy1o/bhZPV+bUJ/AQow==,type:str] + lastmodified: "2025-02-04T05:04:29Z" + mac: ENC[AES256_GCM,data:D0C2biLcMcfSMqx+1Zb1JWMzGElste8rJTAsOwnjx+rfm/fUr7sOXfOOQTMO4+LXVDeZPSsKL4BXhNQQynKFDlyCGmBA8FWqRjM42XO0wZ+So1s5fSY1Ep00E21SbMtoJ6jHWFEB7PXI737ueS7pJSLAN2vUPEZLn4bdsSy0E18=,iv:7316v8T/w4CAG2OZlYOci1mF+Xge2dvfeQ4PHc3jFTE=,tag:vDE2s7SVeCXppjNMUtFXkg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.4