diff --git a/.git-age.yaml b/.git-age.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1ed230cddb2e4fc0c3979b5e34dd45a006e3fa9a --- /dev/null +++ b/.git-age.yaml @@ -0,0 +1,6 @@ +machines/dragonwell/dex.nix: + - age105cm5awxxegyrqthh4vhnxzr0tdy86q8uq52wkkjacfkutp2vprqwseak7 +machines/dragonwell/tandoor.nix: + - age105cm5awxxegyrqthh4vhnxzr0tdy86q8uq52wkkjacfkutp2vprqwseak7 +machines/dragonwell/vikunja.nix: + - age105cm5awxxegyrqthh4vhnxzr0tdy86q8uq52wkkjacfkutp2vprqwseak7 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..c835046eef15d7f0ad36fcd0466be024cd56cfe3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Age +machines/dragonwell/dex.nix filter=git-age diff=git-age +machines/dragonwell/vikunja.nix filter=git-age diff=git-age +machines/dragonwell/tandoor.nix filter=git-age diff=git-age diff --git a/apps/nogui/default.nix b/apps/nogui/default.nix index 4b3266f70b64bb2209555cb370cfaa99d17a2c03..61355e1f26d57877e778c8e1b868744b3c92d36e 100644 --- a/apps/nogui/default.nix +++ b/apps/nogui/default.nix @@ -33,9 +33,12 @@ just ripgrep usql + jolheiser.gist + jolheiser.git-age tclip templ jolheiser.helix + jolheiser.tmpl jolheiser.gomodinit jolheiser.cfg jolheiser.spectre @@ -45,6 +48,13 @@ ${pkgs.nvd}/bin/nvd --nix-bin-dir=${pkgs.nix}/bin diff $oldGenPath $newGenPath ''; stateVersion = "22.11"; ./aerc.nix + ./bottom.nix + + xdg.configFile."gist/config.yaml".text = '' + username: jolheiser + password-file: ${config.age.secrets.gist-pw.path} + domain: gist.jojodev.com + ./atuin.nix ./bottom.nix programs.home-manager.enable = true; diff --git a/apps/nogui/nushell.nix b/apps/nogui/nushell.nix index 660bc92206ab16683716ff99bc8aedce2a4f0880..b9fcbce5485cf63bb62d439c4cc547cdf44b00ff 100644 --- a/apps/nogui/nushell.nix +++ b/apps/nogui/nushell.nix @@ -20,6 +20,8 @@ use ${nu_scripts}/share/nu_scripts/custom-completions/git/git-completions.nu * use ${nu_scripts}/share/nu_scripts/custom-completions/glow/glow-completions.nu * use ${nu_scripts}/share/nu_scripts/custom-completions/just/just-completions.nu * use ${nu_scripts}/share/nu_scripts/custom-completions/nix/nix-completions.nu * + + use ${jolheiser.tmpl}/share/tmpl-completions.nu * ''; extraEnv = '' $env.GOPATH = "${config.xdg.dataHome}/go" diff --git a/flake.lock b/flake.lock index 6ceed491bf0c468145adef3e72a2e32048673aab..a88e5d4a758f0e9ea0389041c5dae4c67cb70ee5 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,25 @@ { "nodes": { + "actual": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733551027, + "narHash": "sha256-nlZWAq4E+cNywCuxpnYcyky4fd+8bVzJHrS2e8QTtVs=", + "ref": "refs/heads/main", + "rev": "7f041ffa7f204deb0fc2e36908b382804f2e108d", + "revCount": 18, + "type": "git", + "url": "https://git.xeno.science/xenofem/actual-nix.git" + }, + "original": { + "type": "git", + "url": "https://git.xeno.science/xenofem/actual-nix.git" + } + }, "agenix": { "inputs": { "darwin": [], @@ -24,6 +44,50 @@ "type": "github" } }, "nodes": { + "flake-utils": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1720757073, + "narHash": "sha256-URQMDzLPs5kckDybkMqrKZN2aqt0GvAt9V5NT4kpMW8=", + "ref": "refs/heads/main", + "rev": "bd7287aa0d13d5af400f659963655c004789715f", + "revCount": 4, + "type": "git", + "url": "https://git.jolheiser.com/bennet.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/bennet.git" + } + }, + "blog": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "templ": [ + "templ" + ] + }, + "locked": { + "lastModified": 1728680363, + "narHash": "sha256-0aJJUY0lKcDnkqLBESOFju8cgIYYrt8jvMwyFTii2Do=", + "ref": "refs/heads/main", + "rev": "03a7f37a42affd2689a72340b8d86731bfd3d28c", + "revCount": 26, + "type": "git", + "url": "https://git.jolheiser.com/blog.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/blog.git" + } + }, + "nodes": { "nodes": { "inputs": { "nixpkgs": [ @@ -42,6 +106,26 @@ }, "original": { "type": "git", "url": "https://git.jolheiser.com/cfg.git" + } + }, + "cfg-playground": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729196682, + "narHash": "sha256-hLbpRWxw12/mqapicSSq1wxvNFfEKwEiXhzykpXWUDI=", + "ref": "refs/heads/main", + "rev": "63c7a6886570f332ebb187e5a5580302603b4c4e", + "revCount": 6, + "type": "git", + "url": "https://git.jolheiser.com/cfg-playground.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/cfg-playground.git" } }, "flake-parts": { @@ -134,6 +218,24 @@ "repo": "flake-utils", "type": "github" } }, + "foundry": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1726638033, + "narHash": "sha256-+hcgXKG5t/9wibv+8T9WASWItBAWb0tsmcZXH+VIYdw=", + "owner": "reckenrode", + "repo": "nix-foundryvtt", + "rev": "bf07f9dd916a97a091f8ab83358c2f295bea9ec9", + "type": "github" + }, + "original": { + "owner": "reckenrode", + "repo": "nix-foundryvtt", + "type": "github" + } + }, "ghostty": { "inputs": { "nixpkgs-stable": "nixpkgs-stable", @@ -154,6 +256,69 @@ "type": "git", "url": "ssh://git@github.com/ghostty-org/ghostty" } }, + "gist": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1702606669, + "narHash": "sha256-98XV0l+3b4sFhxdepNoanqDzhgnEen5ZcrGtqoRp4cA=", + "ref": "refs/heads/main", + "rev": "f393c786b0ad826866d7e30d1abbd3bea319cb34", + "revCount": 3, + "type": "git", + "url": "https://git.jolheiser.com/gist.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/gist.git" + } + }, + "git-age": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699932777, + "narHash": "sha256-2OF5y1geNjHd+As+FwFEYlHxQoQ+LHxizlhSx9u/4dA=", + "ref": "refs/heads/main", + "rev": "72352f984f8c4b2291bcb2c08b7b6dc718619a38", + "revCount": 9, + "type": "git", + "url": "https://git.jolheiser.com/git-age.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/git-age.git" + } + }, + "git-pr": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724120640, + "narHash": "sha256-LLWEHAraOLKFYZ2zbR3O+AhC2PCUNsXP1xcGoDj80xs=", + "ref": "refs/heads/main", + "rev": "6a3bca9ad87b454427940c82f3d111f2eb2c256e", + "revCount": 10, + "type": "git", + "url": "https://git.jolheiser.com/git-pr-nix.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/git-pr-nix.git" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -172,6 +337,29 @@ }, "original": { "owner": "hercules-ci", "repo": "gitignore.nix", + "type": "github" + } + }, + "golink": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733941744, + "narHash": "sha256-cIml0ewF5j2cQySLHkMmV1rl7cVH8wuoPFeFDCARi1A=", + "owner": "tailscale", + "repo": "golink", + "rev": "d55b2a3302777d7f9943863644d4c84ecacb31b7", + "type": "github" + }, + "original": { + "owner": "tailscale", + "repo": "golink", "type": "github" } }, @@ -262,7 +450,7 @@ }, "jolheiser": { "inputs": { "systems": "systems" -{ + "nixpkgs" }, "locked": { "lastModified": 1730336659, @@ -280,7 +468,7 @@ } }, "jolheiser_2": { "inputs": { - "systems": "systems" + "revCount": 10, "nixpkgs" }, "locked": { @@ -315,23 +503,20 @@ } }, "nixpkgs": { "locked": { -{ "nodes": { -{ + "jolheiser", - "locked": { "nodes": { + "lastModified": 1730337479, "owner": "nixos", "repo": "nixpkgs", -{ "nodes": { - "inputs": { + "narHash": "sha256-38K7kYt5T+XltWnyktSDdWIPi5dHq7S28UQgzdMl7MA=", "type": "github" }, "original": { "owner": "nixos", -{ "nodes": { - "darwin": [], + "rev": "13d625fa4fbe60cb320ef111e6fb96eddfc8a799", "repo": "nixpkgs", "type": "github" } @@ -387,6 +572,23 @@ }, "nixpkgs_3": { "locked": { { + }, + "narHash": "sha256-RP+OQ6koQQLX5nw0NmcDrzvGL8HDLnyXt/jHhL1jwjM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "18536bf04cd71abd345f9579158841376fdd0c5a", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { +{ "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", "narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=", "owner": "nixos", @@ -402,7 +604,7 @@ "type": "github" } }, "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", -{ + "nodes": { "locked": { "lastModified": 1734119587, "narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=", @@ -418,8 +620,8 @@ "repo": "nixpkgs", "type": "github" } }, - "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", "nodes": { + "revCount": 22, "locked": { "lastModified": 1728888510, "narHash": "sha256-nsNdSldaAyu6PE3YUA+YQLqUDJh+gRbBooMMekZJwvI=", @@ -438,7 +640,7 @@ "nur": { "inputs": { "flake-parts": "flake-parts", { - "flake-utils_3": { + "jolheiser": "jolheiser", "treefmt-nix": "treefmt-nix" }, "locked": { @@ -455,25 +657,62 @@ "repo": "NUR", "type": "github" } }, + "resume": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697473034, + "narHash": "sha256-hIee7tDD9B1LRNUE7Cy11M1yrbbHHa6pnUZes3CGKxg=", + "ref": "refs/heads/main", + "rev": "94593c9097917604f006a4dcd5e7b10a1b42beb1", + "revCount": 6, + "type": "git", + "url": "https://git.jolheiser.com/resume.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/resume.git" + } + }, "root": { "inputs": { + "actual": "actual", "agenix": "agenix", + "bennet": "bennet", + "blog": "blog", "cfg": "cfg", + "cfg-playground": "cfg-playground", "flake-utils": "flake-utils", + "foundry": "foundry", "ghostty": "ghostty", + "gist": "gist", + "git-age": "git-age", + "git-pr": "git-pr", + "golink": "golink", "gomodinit": "gomodinit", "helix": "helix", "home-manager": "home-manager", "jolheiser": "jolheiser_2", "nixos-hardware": "nixos-hardware", { - "revCount": 8305, + "flake-utils_3": { "nur": "nur", + "resume": "resume", "spectre": "spectre", + "tailproxy": "tailproxy", "tclip": "tclip", + "agenix": { { - "nixpkgs": [ + "flake-parts": { { + "ugit": "ugit", + "website": "website" } }, "spectre": { @@ -556,12 +795,117 @@ "repo": "default", "type": "github" } }, + "agenix": { { + "inputs": { + "inputs": { + "nixpkgs": [ "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729968274, + "narHash": "sha256-YmGgnwar4mGwK3+TRO3W7wvFHcIZ21JEm95PRroJpzQ=", + "ref": "refs/heads/main", + "flake-parts": { "nixpkgs": [ + "revCount": 9, + "type": "git", + "url": "https://git.jolheiser.com/tailproxy.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/tailproxy.git" + } + }, + "tailwind-ctp": { "inputs": { + "nixpkgs": [ + "ugit", + "nixpkgs" + ] { +{ + "locked": { + "lastModified": 1695841587, + "narHash": "sha256-fgiZd5AV+hi8Ne0bJ8SyAx5nppseW4aXJQEIDSr0VNA=", + "ref": "refs/heads/main", + "rev": "afca060674b20e0ccecde2d6fe88c887790219a5", + "revCount": 1, + "type": "git", + "url": "https://git.jolheiser.com/tailwind-ctp" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/tailwind-ctp" + } + }, + "tailwind-ctp-lsp": { + "inputs": { + "nixpkgs": [ + "ugit", "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699401590, + "narHash": "sha256-nx8ExuBRUux9eXSUgkWp1LJMvA3dmA76+2xggZjHTU0=", + "ref": "refs/heads/master", + "rev": "b321333ad08bf21db242f246b10ad4a50b8fc8a0", + "revCount": 848, + "type": "git", + "url": "https://git.jolheiser.com/tailwind-ctp-intellisense" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/tailwind-ctp-intellisense" + } + }, + "tailwind-ctp-lsp_2": { + "inputs": { + "nixpkgs": [ + "website", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699401590, + "narHash": "sha256-nx8ExuBRUux9eXSUgkWp1LJMvA3dmA76+2xggZjHTU0=", + "ref": "refs/heads/master", + "rev": "b321333ad08bf21db242f246b10ad4a50b8fc8a0", + "revCount": 848, + "type": "git", + "url": "https://git.jojodev.com/jolheiser/tailwind-ctp-intellisense" + }, + "original": { + "type": "git", + "url": "https://git.jojodev.com/jolheiser/tailwind-ctp-intellisense" + } + }, + "tailwind-ctp_2": { + "inputs": { + "nixpkgs": [ + "website", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1695841587, + "narHash": "sha256-fgiZd5AV+hi8Ne0bJ8SyAx5nppseW4aXJQEIDSr0VNA=", + "ref": "refs/heads/main", + "rev": "afca060674b20e0ccecde2d6fe88c887790219a5", + "revCount": 1, + "type": "git", + "url": "https://git.jojodev.com/jolheiser/tailwind-ctp" + }, + "original": { + "type": "git", + "url": "https://git.jojodev.com/jolheiser/tailwind-ctp" + } + }, + "tclip": { + "inputs": { + "nur", "nixpkgs" "utils": [ "flake-utils" @@ -604,6 +948,26 @@ "repo": "templ", "type": "github" } }, + "tmpl": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1707601935, + "narHash": "sha256-SX1AT7onZVSEgkE0Egl1bDnHffWROCo8jrRMcDS6ELQ=", + "ref": "refs/heads/main", + "rev": "c828078874c9897a8aa10b3f8d5602684f23f0f9", + "revCount": 36, + "type": "git", + "url": "https://git.jolheiser.com/tmpl.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/tmpl.git" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -623,6 +987,56 @@ "original": { "owner": "numtide", "repo": "treefmt-nix", "type": "github" + } + }, + "ugit": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "tailwind-ctp": "tailwind-ctp", + "tailwind-ctp-lsp": "tailwind-ctp-lsp" + }, + "locked": { + "lastModified": 1729739080, + "narHash": "sha256-Ps6Wo2oSK/yRd/hfxUqh+PLfXw5AcQtC2nRZ3vnBJYs=", + "ref": "refs/heads/main", + "rev": "0f4b6ec93640a2a2aa265434e7af69360b713a04", + "revCount": 66, + "type": "git", + "url": "https://git.jolheiser.com/ugit.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/ugit.git" + } + }, + "website": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "tailwind-ctp": "tailwind-ctp_2", + "tailwind-ctp-lsp": "tailwind-ctp-lsp_2", + "templ": [ + "templ" + ] + }, + "locked": { + "lastModified": 1729007532, + "narHash": "sha256-WTCnUYILllGWI6MuG/a3Fp5HVASqPdpPbVNr7k49ZMQ=", + "ref": "refs/heads/main", + "rev": "82a84f0c62b0a1dddf9e7e7e464680a002439dcb", + "revCount": 18, + "type": "git", + "url": "https://git.jolheiser.com/jolheiser.com.git" + }, + "original": { + "type": "git", + "url": "https://git.jolheiser.com/jolheiser.com.git" } }, "xc": { diff --git a/flake.nix b/flake.nix index 9f21ca62acebde42b8a6f315b834dca80353073f..0b7b2e8682be01345b3744103adbf6e84aff6d1b 100644 --- a/flake.nix +++ b/flake.nix @@ -24,37 +24,118 @@ helix = { url = "git+https://git.jolheiser.com/helix.drv.git"; inputs.nixpkgs.follows = "jolheiser/nixpkgs"; }; +{ description = "jolheiser's nixos config"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + url = "git+https://git.jolheiser.com/jolheiser.com.git"; +{ inputs = { + nixpkgs.follows = "nixpkgs"; +{ description = "jolheiser's nixos config"; + flake-utils.url = "github:numtide/flake-utils"; # Only expressed here to use for followers + templ.follows = "templ"; + }; + }; + resume = { + url = "git+https://git.jolheiser.com/resume.git"; + inputs = { +{ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; { + url = "git+https://git.jolheiser.com/cfg.git"; + }; }; + blog = { + url = "git+https://git.jolheiser.com/blog.git"; + inputs = { + nixpkgs.follows = "nixpkgs"; +{ description = "jolheiser's nixos config"; + home-manager = { + }; + }; + bennet = { + url = "git+https://git.jolheiser.com/bennet.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + git-age = { + url = "github:ryantm/agenix"; jolheiser.url = "git+https://git.jolheiser.com/nixpkgs.git"; + inputs = { + nixpkgs.follows = "nixpkgs"; +{ url = "git+https://git.jolheiser.com/cfg.git"; { + home-manager = { + }; + gist = { + url = "git+https://git.jolheiser.com/gist.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + tmpl = { + url = "git+https://git.jolheiser.com/tmpl.git"; +{ }; description = "jolheiser's nixos config"; - home-manager = { + inputs = { + url = "git+https://git.jolheiser.com/gomodinit.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + cfg = { + url = "git+https://git.jolheiser.com/cfg.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + cfg-playground = { + inputs = { description = "jolheiser's nixos config"; - url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; + inputs = { + url = "git+https://git.jolheiser.com/ugit.git"; +{ - + }; { + let + url = "git+https://git.jolheiser.com/git-pr-nix.git"; inputs.nixpkgs.follows = "nixpkgs"; }; - description = "jolheiser's nixos config"; + home-manager = { + url = "git+https://git.jolheiser.com/go-spectre.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # Other flakes + golink = { + url = "github:tailscale/golink"; + inputs = { + nixpkgs.follows = "nixpkgs"; + flake-utils.follows = "flake-utils"; + }; + }; tclip = { url = "github:tailscale-dev/tclip"; inputs = { + #nixpkgs.follows = "nixpkgs"; utils.follows = "flake-utils"; }; }; + url = "github:a-h/templ"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + actual = { + url = "git+https://git.xeno.science/xenofem/actual-nix.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + foundry.url = "github:reckenrode/nix-foundryvtt"; + tailproxy = { + url = "git+https://git.jolheiser.com/tailproxy.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + ghostty.url = "git+ssh://git@github.com/ghostty-org/ghostty"; + jolheiser.url = "git+https://git.jolheiser.com/nixpkgs.git"; outputs = @@ -73,14 +155,22 @@ pkgs = prev; }; jolheiser = { helix = inputs.helix.packages.${prev.system}.default; + website = inputs.website.packages.${prev.system}.default; + resume = inputs.resume.packages.${prev.system}.default; + git-age = inputs.git-age.packages.${prev.system}.default; + gist = inputs.gist.packages.${prev.system}.default; + tmpl = inputs.tmpl.packages.${prev.system}.default; gomodinit = inputs.gomodinit.packages.${prev.system}.default; cfg = inputs.cfg.packages.${prev.system}.default; + blog = inputs.blog.packages.${prev.system}.default; + bennet = inputs.bennet.packages.${prev.system}.default; spectre = inputs.spectre.packages.${prev.system}.default; }; tclip = inputs.tclip.packages.${prev.system}.tclip; templ = inputs.templ.packages.${prev.system}.templ; ghostty = inputs.ghostty.packages.${prev.system}.ghostty; }) + inputs.golink.overlay ]; pkgs = import inputs.nixpkgs { inherit overlays system; @@ -91,6 +181,8 @@ { config, ... }: { config = { nixpkgs.overlays = overlays; + # TODO Remove when apps are updated + nixpkgs.config.permittedInsecurePackages = [ "electron-25.9.0" ]; }; }; username = "jolheiser"; @@ -107,23 +199,24 @@ secretsDir = "/home/${username}/.agenix/agenix"; secretsMountPoint = "/home/${username}/.agenix/agenix.d"; identityPaths = [ "/home/${username}/.ssh/nix" ]; secrets = { - ssh-config.file = ./secrets/ssh-config.age; + ssh-config.file = ./secrets/shared/ssh-config.age; spotify = { - file = ./secrets/spotify.age; + file = ./secrets/shared/spotify.age; path = "/home/${username}/.cache/spotify-player/credentials.json"; }; - home-manager = { + darwin.follows = ""; home-manager = { - home-manager = { + darwin.follows = ""; url = "github:nix-community/home-manager"; - url = "github:nix-community/home-manager"; + home-manager.follows = ""; + git-send-email.file = ./secrets/shared/git-send-email.age; cachix = { - url = "github:nix-community/home-manager"; + home-manager.follows = ""; description = "jolheiser's nixos config"; path = "/home/${username}/.config/cachix/cachix.dhall"; }; llm = { - file = ./secrets/llm.age; + file = ./secrets/shared/llm.age; path = "/home/${username}/.config/io.datasette.llm/keys.json"; }; }; @@ -158,6 +251,39 @@ ]; }; }; { + agenix.homeManagerModules.age + meta = { + nixpkgs = import nixpkgs { inherit overlays system; }; + specialArgs = { + inherit inputs; + }; + }; + dragonwell = + { pkgs, ... }: + { + imports = [ + inputs.agenix.nixosModules.default + inputs.golink.nixosModules.default + inputs.ugit.nixosModules.default + inputs.git-pr.nixosModules.default + inputs.actual.nixosModules.default + inputs.tailproxy.nixosModules.default + inputs.foundry.nixosModules.foundryvtt + inputs.cfg-playground.nixosModules.default + ./modules/tclip + ./modules/miniserve + ./machines/dragonwell + ]; + services.tclip.package = inputs.tclip.packages.${pkgs.system}.tclipd; + }; + gunpowder = { + imports = [ + inputs.tailproxy.nixosModules.default + ./machines/gunpowder + ]; + }; + }; +{ darwin.follows = ""; extra-substitutors = [ "https://jolheiser.cachix.org" ]; extra-trusted-public-keys = [ @@ -167,6 +293,7 @@ }; devShells.${system}.default = pkgs.mkShell { nativeBuildInputs = [ agenix.packages.${system}.agenix + pkgs.colmena ]; }; }; diff --git a/justfile b/justfile index 75be876041824dc4cd62de3d38b010fe2760d72f..24bc25406e22af6b55e8ff1b301b3f339afbfe00 100644 --- a/justfile +++ b/justfile @@ -20,6 +20,11 @@ # Rebuild the current machine for next boot boot *args: @just rebuild boot {{args}} +# Run colmena for remote deploy +colmena node: + @git add . + @nix run nixpkgs#colmena -- apply --on {{node}} + # Update the flake update-flake: @nix flake update diff --git a/machines/dragonwell/actual.nix b/machines/dragonwell/actual.nix new file mode 100644 index 0000000000000000000000000000000000000000..e09d2750e9c73fd63b78dc56bbcf602be23ea26d --- /dev/null +++ b/machines/dragonwell/actual.nix @@ -0,0 +1,15 @@ +{ + services = { + actual = { + enable = true; + hostname = "127.0.0.1"; + port = 5006; + }; + tailproxy.actualbudget = { + enable = true; + hostname = "actualbudget"; + port = 5006; + authKey = "tskey-auth-kC3B2nznCk11CNTRL-G5QvPvrNWrcHcbQxh2XCrcCz3qe2jUrsh"; # One-time key + }; + }; +} diff --git a/machines/dragonwell/caddy.nix b/machines/dragonwell/caddy.nix new file mode 100644 index 0000000000000000000000000000000000000000..2ef0c23a555ab0e9ec1fdf325c7df4c3b0329ff3 --- /dev/null +++ b/machines/dragonwell/caddy.nix @@ -0,0 +1,85 @@ +{ pkgs, ... }: +let + modules = import ./go.nix; +in +{ + services.caddy = { + enable = true; + virtualHosts = { + "jolheiser.com" = { + extraConfig = '' + handle_path /.well-known/webfinger { + header Content-Type application/jrd+json + respond ${ + builtins.toJSON { + subject = "acct:john@jolheiser.com"; + links = [ + { + rel = "http://openid.net/specs/connect/1.0/issuer"; + href = "https://auth.jolheiser.com"; + } + ]; + } + } + } + handle_path /bennet* { + root * ${pkgs.jolheiser.bennet} + file_server + } + handle /resume* { + root * ${pkgs.jolheiser.resume} + rewrite /resume /resume.pdf + file_server + } + handle { + root * ${pkgs.jolheiser.website} + file_server + } + ''; + serverAliases = [ "www.jolheiser.com" ]; + }; + "blog.jolheiser.com" = { + extraConfig = '' + root * ${pkgs.jolheiser.blog} + file_server + ''; + }; + "go.jolheiser.com" = { + extraConfig = '' + header Content-Type text/html + ${modules} + respond /* ` + + + + Redirecting to https://pkg.go.dev/go.jolheiser.com{path} + ` + ''; + }; + "git.jolheiser.com".extraConfig = '' + reverse_proxy localhost:8449 + ''; + "pr.jolheiser.com".extraConfig = '' + reverse_proxy localhost:7449 + ''; + "social.jolheiser.com".extraConfig = '' + reverse_proxy localhost:4686 + ''; + "auth.jolheiser.com".extraConfig = '' + reverse_proxy localhost:2884 + ''; + "todo.jolheiser.com".extraConfig = '' + reverse_proxy localhost:8636 + ''; + "recipes.jolheiser.com".extraConfig = '' + reverse_proxy localhost:3663 + ''; + "irc.jolheiser.com".extraConfig = '' + reverse_proxy localhost:7658 + ''; + "dnd.jolheiser.com".extraConfig = '' + reverse_proxy localhost:30000 + ''; + }; + }; +} diff --git a/machines/dragonwell/cfg.nix b/machines/dragonwell/cfg.nix new file mode 100644 index 0000000000000000000000000000000000000000..9e87a2de2abf80a251a0dc373da6643335dd1c26 --- /dev/null +++ b/machines/dragonwell/cfg.nix @@ -0,0 +1,7 @@ +{ + services.cfg-playground = { + enable = true; + verbose = true; + auth-key = "tskey-auth-ksTZtpeU1i11CNTRL-HmmWuAFifG3xxy8UDr1yG3UdjiYJ3mtGe"; # One-time key + }; +} diff --git a/machines/dragonwell/default.nix b/machines/dragonwell/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..825c922173caee708188a9830a265085a2b31022 --- /dev/null +++ b/machines/dragonwell/default.nix @@ -0,0 +1,61 @@ +let + username = "jolheiser"; + key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL+uhnfFLhlyfGGsksSxh5IIY6gnIMryeQ2EiM979kZa"; +in +{ + imports = [ + # ./actual.nix + ./caddy.nix + ./cfg.nix + ./dex.nix + ./foundry.nix + ./git-pr.nix + ./golink.nix + ./gotosocial.nix + ./miniserve.nix + ./pubserve.nix + ./restic.nix + ./soju.nix + ./tandoor.nix + ./tclip.nix + ./ugit.nix + ./vikunja.nix + ./hardware.nix + ]; + + boot.tmp.cleanOnBoot = true; + zramSwap.enable = true; + + networking = { + hostName = "dragonwell"; + + firewall = { + enable = true; + allowedTCPPorts = [ + 80 + 443 + 6697 + ]; + }; + }; + + services = { + openssh.enable = true; + tailscale.enable = true; + }; + + users.users = { + "${username}" = { + extraGroups = [ + "wheel" + "docker" + "storage" + ]; + isNormalUser = true; + openssh.authorizedKeys.keys = [ key ]; + }; + "root".openssh.authorizedKeys.keys = [ key ]; + }; + + system.stateVersion = "22.11"; +} diff --git a/machines/dragonwell/dex.nix b/machines/dragonwell/dex.nix new file mode 100644 index 0000000000000000000000000000000000000000..744c2633c796de2ce006acdd4fc0a3e9432712e2 Binary files /dev/null and b/machines/dragonwell/dex.nix differ diff --git a/machines/dragonwell/foundry.nix b/machines/dragonwell/foundry.nix new file mode 100644 index 0000000000000000000000000000000000000000..ca0ea9a3367ce0fe564d8fdf8a807a57576323a0 --- /dev/null +++ b/machines/dragonwell/foundry.nix @@ -0,0 +1,12 @@ +{ inputs, pkgs, ... }: +{ + services.foundryvtt = { + enable = true; + hostName = "dnd.jolheiser.com"; + minifyStaticFiles = true; + proxyPort = 443; + proxySSL = true; + upnp = false; + package = inputs.foundry.packages.${pkgs.system}.foundryvtt_12; + }; +} diff --git a/machines/dragonwell/git-pr.nix b/machines/dragonwell/git-pr.nix new file mode 100644 index 0000000000000000000000000000000000000000..bcb7b506eb2a7b3336aa263227f328afba83bf45 --- /dev/null +++ b/machines/dragonwell/git-pr.nix @@ -0,0 +1,25 @@ +{ + services.git-pr = { + enable = true; + openFirewall = true; + url = "pr.jolheiser.com"; + admins = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXoiWcPkL5kUAqJfMxnPM/ND4qJ4kKShDhXdqnYv2ZB" ]; + sshPort = 7448; + enableWeb = true; + webPort = 7449; + theme = "catppuccin-mocha"; + timeFormat = "01/02/2006 at 03:04:05PM"; + repos = [ + { + id = "ugit"; + cloneAddr = "https://git.jolheiser.com/ugit.git"; + desc = "Minimal git service"; + } + { + id = "git-pr-nix"; + cloneAddr = "https://git.jolheiser.com/git-pr-nix.git"; + desc = "Nix flake, package, and module for git-pr"; + } + ]; + }; +} diff --git a/machines/dragonwell/go.nix b/machines/dragonwell/go.nix new file mode 100644 index 0000000000000000000000000000000000000000..fe1f7cf41895bf96e315a5d1a3a765dfba07b170 --- /dev/null +++ b/machines/dragonwell/go.nix @@ -0,0 +1,22 @@ +let + modules = [ + { + name = "hcaptcha"; + repo = "gitea.com/jolheiser/hcaptcha"; + } + { + name = "pwn"; + repo = "gitea.com/jolheiser/pwn"; + } + ]; +in +builtins.concatStringsSep "\n" ( + builtins.map (module: '' + respond /${module.name}* ` + + + + Redirecting to https://pkg.go.dev/go.jolheiser.com/${module.name} + ` + '') modules +) diff --git a/machines/dragonwell/golink.nix b/machines/dragonwell/golink.nix new file mode 100644 index 0000000000000000000000000000000000000000..9e65524a795e059659db3b5e229f266a533b2a86 --- /dev/null +++ b/machines/dragonwell/golink.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: +{ + services.golink = { + enable = true; + tailscaleAuthKeyFile = pkgs.writeText "tskey" "tskey-auth-kGaKxz5CNTRL-nvyRLm7J38B37QZ2gCDM8BqtwyC6zJUh7"; # One-time key + }; +} diff --git a/machines/dragonwell/gotosocial.nix b/machines/dragonwell/gotosocial.nix new file mode 100644 index 0000000000000000000000000000000000000000..e7a909f22cde18740de9ba6bfafc752efecaac24 --- /dev/null +++ b/machines/dragonwell/gotosocial.nix @@ -0,0 +1,12 @@ +{ + services.gotosocial = { + enable = true; + settings = { + application-name = "jolheiser GtS"; + host = "social.jolheiser.com"; + port = 4686; + accounts-registration-open = false; + landing-page-user = "jolheiser"; + }; + }; +} diff --git a/machines/dragonwell/hardware.nix b/machines/dragonwell/hardware.nix new file mode 100644 index 0000000000000000000000000000000000000000..8ec43119828fbd561cbc95a3155fb1ec4fe6a714 --- /dev/null +++ b/machines/dragonwell/hardware.nix @@ -0,0 +1,16 @@ +{ modulesPath, ... }: +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + boot.loader.grub.device = "/dev/sda"; + boot.initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "xen_blkfront" + "vmw_pvscsi" + ]; + boot.initrd.kernelModules = [ "nvme" ]; + fileSystems."/" = { + device = "/dev/sda1"; + fsType = "ext4"; + }; +} diff --git a/machines/dragonwell/miniserve.nix b/machines/dragonwell/miniserve.nix new file mode 100644 index 0000000000000000000000000000000000000000..8905b1380508bd53125223ee2bf8cd2330961d3e --- /dev/null +++ b/machines/dragonwell/miniserve.nix @@ -0,0 +1,26 @@ +{ + services = { + miniserve = { + enable = true; + port = 3453; + showHidden = true; + uploadFiles = ""; + mkdir = true; + overwriteFiles = true; + enableTar = true; + enableTarGz = true; + enableZip = true; + dirsFirst = true; + title = "Files"; + hideThemeSelector = true; + hideVersionFooter = true; + readme = true; + }; + tailproxy.miniserve = { + enable = true; + hostname = "files"; + port = 3453; + authKey = "tskey-auth-kNNZJXfSDb11CNTRL-DsdZPygdA7Lrye5WJjnr6LGNffgzo3PUH"; # One-time key + }; + }; +} diff --git a/machines/dragonwell/pubserve.nix b/machines/dragonwell/pubserve.nix new file mode 100644 index 0000000000000000000000000000000000000000..ed05fc5ce2adb9a5209ab2ff4ab2174ac2684fdc --- /dev/null +++ b/machines/dragonwell/pubserve.nix @@ -0,0 +1,68 @@ +{ pkgs, lib, ... }: +let + user = "pubserve"; + path = "/var/lib/pubserve"; +in +{ + users.users.${user} = { + group = user; + home = path; + createHome = true; + isSystemUser = true; + isNormalUser = false; + + }; + users.groups.${user} = { }; + + systemd.services = + let + commonArgs = [ + "-i '127.0.0.1'" + "-H" + "-D" + "-F" + "--hide-theme-selector" + "--readme" + path + ]; + in + { + pubserve = { + description = "Miniserve Public File Server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.miniserve}/bin/miniserve -t 'PubServe' -p 3454 ${lib.concatStringsSep " " commonArgs}"; + Restart = "on-failure"; + User = user; + Group = user; + }; + }; + privserve = { + description = "Miniserve Public File Server (Admin)"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.miniserve}/bin/miniserve -u -U -o -t 'PrivServe' -p 3455 ${lib.concatStringsSep " " commonArgs}"; + Restart = "on-failure"; + User = user; + Group = user; + }; + }; + }; + services.tailproxy = { + pubserve = { + enable = true; + hostname = "pubserve"; + funnel = true; + port = 3454; + authKey = "tskey-auth-kJrnknpMsL11CNTRL-ot1kkasErR2cLZZmfuKYR2b9za7fCzVR"; # One-time key + }; + privserve = { + enable = true; + hostname = "privserve"; + port = 3455; + authKey = "tskey-auth-kKFv865ykk11CNTRL-dfmxUREHP5evuuMsfPy55ehXECXrLF1N7"; # One-time key + }; + }; +} diff --git a/machines/dragonwell/restic.nix b/machines/dragonwell/restic.nix new file mode 100644 index 0000000000000000000000000000000000000000..26e025424f33c896120eb701c18c940acdff9c7c --- /dev/null +++ b/machines/dragonwell/restic.nix @@ -0,0 +1,29 @@ +{ config, ... }: +{ + age.secrets = { + restic-env.file = ../../secrets/personal/restic-env.age; + restic-pass.file = ../../secrets/personal/restic-pass.age; + restic-repo.file = ../../secrets/personal/restic-repo.age; + }; + services.restic.backups.dragonwell = { + initialize = true; + environmentFile = config.age.secrets.restic-env.path; + passwordFile = config.age.secrets.restic-pass.path; + repositoryFile = config.age.secrets.restic-repo.path; + paths = [ + "/var/lib/ugit/repos" + "/var/lib/miniserve" + "/var/lib/foundryvtt/Data" + "/var/lib/foundryvtt/Config" + ]; + pruneOpts = [ + "--keep-daily 7" + "--keep-weekly 2" + "--keep-monthly 2" + ]; + timerConfig = { + OnCalendar = "daily"; + Persistent = true; + }; + }; +} diff --git a/machines/dragonwell/soju.nix b/machines/dragonwell/soju.nix new file mode 100644 index 0000000000000000000000000000000000000000..6f5e86c30b141cc339b38ec48f09d95cd300ccc2 --- /dev/null +++ b/machines/dragonwell/soju.nix @@ -0,0 +1,33 @@ +{ lib, ... }: +let + baseCertPath = "/var/lib/acme/irc.jolheiser.com"; +in +{ + security.acme = { + acceptTerms = true; + email = "irc@jolheiser.com"; + certs."irc.jolheiser.com" = { + listenHTTP = ":7658"; + postRun = "systemctl reload soju"; + group = "soju"; + }; + }; + services.soju = { + enable = true; + tlsCertificate = "${baseCertPath}/fullchain.pem"; + tlsCertificateKey = "${baseCertPath}/key.pem"; + }; + systemd.services.soju.serviceConfig = { + DynamicUser = lib.mkForce false; + User = "soju"; + Group = "soju"; + ReadOnlyPaths = baseCertPath; + }; + users = { + users.soju = { + isSystemUser = true; + group = "soju"; + }; + groups.soju = { }; + }; +} diff --git a/machines/dragonwell/tandoor.nix b/machines/dragonwell/tandoor.nix new file mode 100644 index 0000000000000000000000000000000000000000..efc40612cf2e6e88cc44a601151a0b70b4bdcf5f Binary files /dev/null and b/machines/dragonwell/tandoor.nix differ diff --git a/machines/dragonwell/tclip.nix b/machines/dragonwell/tclip.nix new file mode 100644 index 0000000000000000000000000000000000000000..db4dcd802fb6603260966715df18c83518968242 --- /dev/null +++ b/machines/dragonwell/tclip.nix @@ -0,0 +1,9 @@ +{ + services.tclip = { + enable = true; + hostname = "paste"; + useFunnel = true; + hideFunnelUsers = true; + authKey = "tskey-auth-k1VerP4gam11CNTRL-89rpeDcfTdJqkF9AECWmdJLVgo1jQcSAB"; # One-time key + }; +} diff --git a/machines/dragonwell/ugit.nix b/machines/dragonwell/ugit.nix new file mode 100644 index 0000000000000000000000000000000000000000..c7ef77e513623cf422d4a0e091a746ead8f30246 --- /dev/null +++ b/machines/dragonwell/ugit.nix @@ -0,0 +1,29 @@ +{ + services.ugit = { + enable = true; + openFirewall = true; + authorizedKeys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXoiWcPkL5kUAqJfMxnPM/ND4qJ4kKShDhXdqnYv2ZB" + ]; + tsAuthKey = "tskey-auth-kRUJE7zxH621CNTRL-Td29STXSrtTUHdacaKaYtTD82uyDXZj7"; # One-time key + config = { + ssh.clone-url = "ugit@git.jolheiser.com"; + http.clone-url = "https://git.jolheiser.com"; + log.json = true; + profile = { + username = "jolheiser"; + email = "ugit@jolheiser.com"; + links = [ + "Github,https://github.com/jolheiser" + "Gitea,https://gitea.com/jolheiser" + "JoJoDev,https://git.jojodev.com/jolheiser" + "Fediverse,https://social.jolheiser.com/@jolheiser" + ]; + }; + tailscale = { + enable = true; + hostname = "git"; + }; + }; + }; +} diff --git a/machines/dragonwell/vikunja.nix b/machines/dragonwell/vikunja.nix new file mode 100644 index 0000000000000000000000000000000000000000..045a5210fb7f4d097343c5398dd483fa21c984b5 Binary files /dev/null and b/machines/dragonwell/vikunja.nix differ diff --git a/modules/miniserve/default.nix b/modules/miniserve/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..9b6fcf6ad28f41d9508002736b1050ab9d564fb3 --- /dev/null +++ b/modules/miniserve/default.nix @@ -0,0 +1,438 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.miniserve; + inherit (lib) + mkEnableOption + mkOption + mkIf + types + optionalString + concatMapStringsSep + concatStringsSep + ; +in +{ + options.services.miniserve = { + enable = mkEnableOption "miniserve service"; + + package = mkOption { + type = types.package; + description = "miniserve package to use"; + default = pkgs.miniserve; + }; + + user = mkOption { + type = types.str; + default = "miniserve"; + description = "User account for miniserve service"; + }; + + group = mkOption { + type = types.str; + default = "miniserve"; + description = "Group for miniserve service"; + }; + + path = mkOption { + type = types.str; + default = "/var/lib/miniserve"; + description = "Which path to serve"; + }; + + port = mkOption { + type = types.port; + default = 8080; + description = "Port to use"; + }; + + interfaces = mkOption { + type = types.listOf types.str; + default = [ "127.0.0.1" ]; + description = "Interface to listen on"; + }; + + verbose = mkOption { + type = types.bool; + default = false; + description = "Be verbose, includes emitting access logs"; + }; + + indexFile = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The name of a directory index file to serve, like "index.html" + + Normally, when miniserve serves a directory, it creates a listing for that directory. However, if a directory + contains this file, miniserve will serve that file instead. + ''; + }; + + spa = mkOption { + type = types.bool; + default = false; + description = '' + Activate SPA (Single Page Application) mode + + This will cause the file given by --index to be served for all non-existing file paths. In effect, this will serve + the index file whenever a 404 would otherwise occur in order to allow the SPA router to handle the request instead. + ''; + }; + + prettyUrls = mkOption { + type = types.bool; + default = false; + description = '' + Activate Pretty URLs mode + + This will cause the server to serve the equivalent `.html` file indicated by the path. + + `/about` will try to find `about.html` and serve it. + ''; + }; + + auth = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Set authentication + + Currently supported formats: + username:password, username:sha256:hash, username:sha512:hash + (e.g. joe:123, joe:sha256:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3) + ''; + }; + + authFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Read authentication values from a file + + Example file content: + + joe:123 + bob:sha256:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 + bill: + ''; + }; + + routePrefix = mkOption { + type = types.nullOr types.str; + default = null; + description = "Use a specific route prefix"; + }; + + randomRoute = mkOption { + type = types.bool; + default = false; + description = "Generate a random 6-hexdigit route"; + }; + + hideSymlinks = mkOption { + type = types.bool; + default = false; + description = "Hide symlinks in listing and prevent them from being followed"; + }; + + showHidden = mkOption { + type = types.bool; + default = false; + description = "Show hidden files"; + }; + + sortingMethod = mkOption { + type = types.enum [ + "name" + "size" + "date" + ]; + default = "name"; + description = '' + Default sorting method for file list + + Possible values: + - name: Sort by name + - size: Sort by size + - date: Sort by last modification date (natural sort: follows alphanumerical order) + ''; + }; + + sortingOrder = mkOption { + type = types.enum [ + "asc" + "desc" + ]; + default = "desc"; + description = '' + Default sorting order for file list + + Possible values: + - asc: Ascending order + - desc: Descending order + ''; + }; + + colorScheme = mkOption { + type = types.enum [ + "squirrel" + "archlinux" + "zenburn" + "monokai" + ]; + default = "squirrel"; + description = '' + Default color scheme + + Possible values: squirrel, archlinux, zenburn, monokai + ''; + }; + + colorSchemeDark = mkOption { + type = types.enum [ + "squirrel" + "archlinux" + "zenburn" + "monokai" + ]; + default = "archlinux"; + description = '' + Default color scheme + + Possible values: squirrel, archlinux, zenburn, monokai + ''; + }; + + qrcode = mkOption { + type = types.bool; + default = false; + description = "Enable QR code display"; + }; + + uploadFiles = mkOption { + type = types.nullOr types.str; + default = null; + description = "Enable file uploading (and optionally specify for which directory)"; + }; + + mkdir = mkOption { + type = types.bool; + default = false; + description = "Enable creating directories"; + }; + + mediaType = mkOption { + type = types.nullOr ( + types.enum [ + "image" + "audio" + "video" + ] + ); + default = null; + description = '' + Specify uploadable media types + + Possible values: image, audio, video + ''; + }; + + rawMediaType = mkOption { + type = types.nullOr types.str; + default = null; + description = "Directly specify the uploadable media type expression"; + }; + + overwriteFiles = mkOption { + type = types.bool; + default = false; + description = "Enable overriding existing files during file upload"; + }; + + enableTar = mkOption { + type = types.bool; + default = false; + description = "Enable uncompressed tar archive generation"; + }; + + enableTarGz = mkOption { + type = types.bool; + default = false; + description = "Enable gz-compressed tar archive generation"; + }; + + enableZip = mkOption { + type = types.bool; + default = false; + description = '' + Enable zip archive generation + + WARNING: Zipping large directories can result in out-of-memory exception because zip generation is done in memory + and cannot be sent on the fly + ''; + }; + + compressResponse = mkOption { + type = types.bool; + default = false; + description = '' + Compress response + + WARNING: Enabling this option may slow down transfers due to CPU overhead, so it is disabled by default. + + Only enable this option if you know that your users have slow connections or if you want to minimize your server's bandwidth usage. + ''; + }; + + dirsFirst = mkOption { + type = types.bool; + default = false; + description = "List directories first"; + }; + + title = mkOption { + type = types.nullOr types.str; + default = null; + description = "Shown instead of host in page title and heading"; + }; + + headers = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Inserts custom headers into the responses. Specify each header as a 'Header:Value' pair. + This parameter can be used multiple times to add multiple headers. + + Example: + --header "Header1:Value1" --header "Header2:Value2" + (If a header is already set or previously inserted, it will not be overwritten.) + ''; + }; + + showSymlinkInfo = mkOption { + type = types.bool; + default = false; + description = "Visualize symlinks in directory listing"; + }; + + hideVersionFooter = mkOption { + type = types.bool; + default = false; + description = "Hide version footer"; + }; + + hideThemeSelector = mkOption { + type = types.bool; + default = false; + description = "Hide theme selector"; + }; + + showWgetFooter = mkOption { + type = types.bool; + default = false; + description = "If enabled, display a wget command to recursively download the current directory"; + }; + + tlsCert = mkOption { + type = types.nullOr types.path; + default = null; + description = "TLS certificate to use"; + }; + + tlsKey = mkOption { + type = types.nullOr types.path; + default = null; + description = "TLS private key to use"; + }; + + readme = mkOption { + type = types.bool; + default = false; + description = "Enable README.md rendering in directories"; + }; + + disableIndexing = mkOption { + type = types.bool; + default = false; + description = '' + Disable indexing + + This will prevent directory listings from being generated and return an error instead. + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.miniserve = { + description = "Miniserve File Server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = + let + args = [ + (optionalString cfg.verbose "-v") + (optionalString (cfg.indexFile != null) "--index '${cfg.indexFile}'") + (optionalString cfg.spa "--spa") + (optionalString cfg.prettyUrls "--pretty-urls") + "-p ${toString cfg.port}" + (concatMapStringsSep " " (i: "-i ${i}") cfg.interfaces) + (optionalString (cfg.auth != null) "-a '${cfg.auth}'") + (optionalString (cfg.authFile != null) "--auth-file ${cfg.authFile}") + (optionalString (cfg.routePrefix != null) "--route-prefix '${cfg.routePrefix}'") + (optionalString cfg.randomRoute "--random-route") + (optionalString cfg.hideSymlinks "-P") + (optionalString cfg.showHidden "-H") + "-S ${cfg.sortingMethod}" + "-O ${cfg.sortingOrder}" + "-c ${cfg.colorScheme}" + "-d ${cfg.colorSchemeDark}" + (optionalString cfg.qrcode "-q") + (optionalString (cfg.uploadFiles != null) ( + if (cfg.uploadFiles != "") then "-u '${cfg.uploadFiles}'" else "-u" + )) + (optionalString cfg.mkdir "-U") + (optionalString (cfg.mediaType != null) "-m ${cfg.mediaType}") + (optionalString (cfg.rawMediaType != null) "-M '${cfg.rawMediaType}'") + (optionalString cfg.overwriteFiles "-o") + (optionalString cfg.enableTar "-r") + (optionalString cfg.enableTarGz "-g") + (optionalString cfg.enableZip "-z") + (optionalString cfg.compressResponse "-C") + (optionalString cfg.dirsFirst "-D") + (optionalString (cfg.title != null) "-t '${cfg.title}'") + (concatMapStringsSep " " (h: "--header '${h}'") cfg.headers) + (optionalString cfg.showSymlinkInfo "-l") + (optionalString cfg.hideVersionFooter "-F") + (optionalString cfg.hideThemeSelector "--hide-theme-selector") + (optionalString cfg.showWgetFooter "-W") + (optionalString (cfg.tlsCert != null) "--tls-cert ${cfg.tlsCert}") + (optionalString (cfg.tlsKey != null) "--tls-key ${cfg.tlsKey}") + (optionalString cfg.readme "--readme") + (optionalString cfg.disableIndexing "-I") + cfg.path + ]; + in + "${pkgs.miniserve}/bin/miniserve ${concatStringsSep " " args}"; + Restart = "on-failure"; + User = cfg.user; + Group = cfg.group; + }; + }; + + users.users.${cfg.user} = { + group = cfg.group; + home = cfg.path; + createHome = true; + isSystemUser = true; + isNormalUser = false; + }; + users.groups.${cfg.group} = { }; + }; +} diff --git a/modules/tclip/default.nix b/modules/tclip/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..c8c68763d3bccb388e5dd08d61f645cc0214273c --- /dev/null +++ b/modules/tclip/default.nix @@ -0,0 +1,108 @@ +{ config, lib, ... }: +let + cfg = config.services.tclip; +in +{ + options.services.tclip = { + enable = lib.mkEnableOption "tclip service"; + + hostname = lib.mkOption { + type = lib.types.str; + default = "paste"; + description = "The hostname to use on your tailnet"; + }; + + dataLocation = lib.mkOption { + type = lib.types.str; + default = "/var/lib/tclip"; + description = "Where program data is stored"; + }; + + tsnetVerbose = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Log verbosely to stderr"; + }; + + useFunnel = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Expose pastes with tailscale funnel"; + }; + + hideFunnelUsers = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Hide usernamd/image on funnel"; + }; + + httpPort = lib.mkOption { + type = lib.types.nullOr lib.types.port; + default = null; + description = "Expose pastes on an HTTP server at the given port"; + }; + + controlURL = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Custom control server (e.g. headscale)"; + }; + + disableHTTPS = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Disable serving on HTTPS"; + }; + + package = lib.mkOption { + type = lib.types.package; + description = "The tclip package to use"; + }; + + authKey = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Tailscale auth key"; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.tclip = { + description = "tclip Service"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = + let + args = + lib.optionals (cfg.httpPort != null) [ "--http-port=${cfg.httpPort}" ] + ++ lib.optionals (cfg.controlURL != null) [ "--control-url=${cfg.controlURL}" ] + ++ [ + (lib.optionalString cfg.disableHTTPS "--disable-https") + "--hostname=${cfg.hostname}" + "--data-location=${cfg.dataLocation}" + (lib.optionalString cfg.tsnetVerbose "--tsnet-verbose") + (lib.optionalString cfg.useFunnel "--use-funnel") + (lib.optionalString cfg.hideFunnelUsers "--hide-funnel-users") + ]; + in + "${cfg.package}/bin/tclipd ${lib.concatStringsSep " " args}"; + Restart = "always"; + User = "tclip"; + Group = "tclip"; + Environment = [ "TS_AUTHKEY=${cfg.authKey}" ]; + }; + }; + + # Create user and group + users.users.tclip = { + isSystemUser = true; + group = "tclip"; + home = cfg.dataLocation; + createHome = true; + }; + + users.groups.tclip = { }; + }; +} diff --git a/secrets/cachix.age b/secrets/shared/cachix.age rename from secrets/cachix.age rename to secrets/shared/cachix.age diff --git a/secrets/git-send-email.age b/secrets/shared/git-send-email.age rename from secrets/git-send-email.age rename to secrets/shared/git-send-email.age diff --git a/secrets/irc-pw.age b/secrets/shared/irc-pw.age rename from secrets/irc-pw.age rename to secrets/shared/irc-pw.age diff --git a/secrets/llm.age b/secrets/shared/llm.age rename from secrets/llm.age rename to secrets/shared/llm.age diff --git a/secrets/personal/dex-tailscale.age b/secrets/personal/dex-tailscale.age new file mode 100644 index 0000000000000000000000000000000000000000..126c2e80f7aabd778dee4d1a18afbb1273253097 --- /dev/null +++ b/secrets/personal/dex-tailscale.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 E8j6/g QWZGgeu5+89wRzWH31D1GdNuhrNyyKsKqv/b4Kkyn2s +3vYwTYDVOMyiNeE+NtNPyplmGiknjyTQvln2DRxUPg0 +-> ssh-ed25519 f31uNA NVB2C1IjxvB25uA+PdB9lmNgmPQ16wSRl8lS0Wp4Tzg +Fe7BCcnb+1HzJ43Iq+YtHCI/i2m7TT5xO1rZwb9yZ70 +--- 4Fmm3sQzE/funn3yI79REu1SVRzgUMQ1r8bUaNgVYZE +΍ +,F/~ŔTDِۨt`)9+xy~+ \ No newline at end of file diff --git a/secrets/personal/dex-tandoor.age b/secrets/personal/dex-tandoor.age new file mode 100644 index 0000000000000000000000000000000000000000..764061e9a96a34c1c32a34424abc7e190b9f0b48 --- /dev/null +++ b/secrets/personal/dex-tandoor.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 E8j6/g npvjWOaLtdQ8shF6rkXfUlXXf1MAe/pvPBPIPY9R1XY +gO6lr8kHN7fOQb5NXaybFqhghx5VqcK0LaHCVvlsdvs +-> ssh-ed25519 f31uNA qrbvpL4AuM1wPSR2Qc9VKSpO4Ho0WgpmOIThWvotBCQ +Q1oMS4SAxzqb1vQffM4dpsnlXP1M2fZ5nYYIpyB9uoA +--- ESb6mxdTZnHs053UowTuWZRn+W+QlOeVM8/kL1VWSgw + HDݭD֢wokGEJ-_up!!B \ No newline at end of file diff --git a/secrets/personal/dex-vikunja.age b/secrets/personal/dex-vikunja.age new file mode 100644 index 0000000000000000000000000000000000000000..fdcdfa10e6423a11b1827ab53939cb1b350f9c4c --- /dev/null +++ b/secrets/personal/dex-vikunja.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 E8j6/g rUc81FjzuShzhp/3we9dQPPAqIPEoKAagCF9K0/S9lw +0mv/S6RCEosLF1aWvb/2+oPdQEfTHraOqVI8v3PMcrI +-> ssh-ed25519 f31uNA C3OusAWxSswFYZxr26XtuB5EpJUzkxcP0US+F4SZFlc +L/soUr5i+7+RyZ8mMUI6AOfTXdWzqO+a9OFLHGw28SI +--- rVDcNMV2dVpwhNiIx964+sw6ak5lcZzaeGASLlVNac8 +&sE +H'/S|%8ӛԧ@Z:2j1 5p. \ No newline at end of file diff --git a/secrets/personal/dex.age b/secrets/personal/dex.age new file mode 100644 index 0000000000000000000000000000000000000000..afde76e712eaecda1252e887cbe5d7ff4dfb8e65 Binary files /dev/null and b/secrets/personal/dex.age differ diff --git a/secrets/personal/restic-env.age b/secrets/personal/restic-env.age new file mode 100644 index 0000000000000000000000000000000000000000..8ca40dc79344a0a11f2b07a33dc206c005415d58 Binary files /dev/null and b/secrets/personal/restic-env.age differ diff --git a/secrets/personal/restic-pass.age b/secrets/personal/restic-pass.age new file mode 100644 index 0000000000000000000000000000000000000000..1a2664a6f90d67687dafe515b905611a78e6e7c6 --- /dev/null +++ b/secrets/personal/restic-pass.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 E8j6/g c3mP+3muM3Nk+CR8X2GRdVDgc88Y5FHblV7EzxaYF08 +dVEE+rQ6Y7ki9Uyr+8B3xYRZtO9VeGWwFboasp5ycqg +-> ssh-ed25519 f31uNA Xq8QkBgX9mpIkenoJQCt+hyg/AVf/kwkVMJnOxqEARM +tkte19pOr+Lb2lk1BVQibsC8d8k38oKwllx6cySVtt0 +--- geKlgkUKw/FYhJNqGSZmXoTSTfRQR+dlz7fq5WzL7SU +l,ٗWL4VEb6Y8 \ No newline at end of file diff --git a/secrets/personal/restic-repo.age b/secrets/personal/restic-repo.age new file mode 100644 index 0000000000000000000000000000000000000000..08d2997d2f7a326a5d729e5a8dc95cb8d9b79060 --- /dev/null +++ b/secrets/personal/restic-repo.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 E8j6/g vLXo/gyZOwGUJyLHIqcrpCmvLmbFpgrFHBRLmqzyiwg +ha7V1vSM3r5Y0PQyeNL01wqqvSuMOWfwbdZjJSMpzhk +-> ssh-ed25519 f31uNA NGUshv3FTRw4kARWfLgSqp2EbLvPnm638rKAULFLZlY +3owquk+she5gB+cjdpPYdIFlz+RtA25RbwxIGftD6BI +--- MZfK5Wquy6pyOWuQdRYa9y46X8lD1ndOeXqkImvIDpM +e7kUWsm7ߨ㗛Dd\(1ܪdj$$N^Јi.b*}(2$%B[5So1A徱+#c \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index d6546bf6a2cef026bcdf3cb84e7a989efe7697b0..4f4156f3621ce08c2dec6b1ad4aafda7a54dc082 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -3,26 +3,63 @@ jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; genmaicha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKhyzwMV0eoS8RSAcUvLkPhbXoR9/06cLoBmUVyb9DTw"; sencha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJurjAMu4IXgpBwgUP0QvE2ySE5/Orn/yflkdWVvy6Am"; + dragonwell = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN32Cwxer2AOGvEqSqXSPp49gj1VtR7G2XmPnmXj6o53"; all = [ jolheiser matcha genmaicha sencha + dragonwell ]; in { + "shared/cachix.age".publicKeys = all; + "shared/ssh-config.age".publicKeys = all; + "shared/spotify.age".publicKeys = all; + "shared/irc-pw.age".publicKeys = all; + "shared/gist-pw.age".publicKeys = all; + "shared/git-send-email.age".publicKeys = all; + matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; let + "shared/spectre-pw.age".publicKeys = [ jolheiser ]; + "personal/restic-env.age".publicKeys = [ + jolheiser + dragonwell + ]; + "personal/restic-pass.age".publicKeys = [ + jolheiser + dragonwell + ]; + matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; sencha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJurjAMu4IXgpBwgUP0QvE2ySE5/Orn/yflkdWVvy6Am"; + jolheiser + dragonwell let + jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; + matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; + jolheiser + dragonwell let + jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; + matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; all = [ + jolheiser + dragonwell let + jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; + matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; jolheiser + jolheiser + dragonwell let + jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; + matcha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZxjkZLj/9xvmg1enK+B7k8qf6Px0j4kTZ2caQfYmB1"; matcha + jolheiser jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; + genmaicha = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKhyzwMV0eoS8RSAcUvLkPhbXoR9/06cLoBmUVyb9DTw"; - jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; let + jolheiser = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrPUqk9v7FE7OgMDaOMdlnItiXSDkmS+eU94RzQFiMS"; } diff --git a/secrets/shared/gist-pw.age b/secrets/shared/gist-pw.age new file mode 100644 index 0000000000000000000000000000000000000000..6e0eb99c00a6de509b77671b1e29e1c64225d860 Binary files /dev/null and b/secrets/shared/gist-pw.age differ diff --git a/secrets/spectre-pw.age b/secrets/shared/spectre-pw.age rename from secrets/spectre-pw.age rename to secrets/shared/spectre-pw.age diff --git a/secrets/spotify.age b/secrets/shared/spotify.age rename from secrets/spotify.age rename to secrets/shared/spotify.age diff --git a/secrets/ssh-config.age b/secrets/shared/ssh-config.age rename from secrets/ssh-config.age rename to secrets/shared/ssh-config.age