├── .gitignore ├── pkgs └── filestash │ ├── fix-impure-build-date.patch │ └── default.nix ├── nix ├── filestash-vmtest.nix └── filestash-module.nix ├── LICENSE.md ├── .github └── workflows │ └── main.yaml ├── flake.nix ├── README.md └── flake.lock /.gitignore: -------------------------------------------------------------------------------- 1 | *result* 2 | -------------------------------------------------------------------------------- /pkgs/filestash/fix-impure-build-date.patch: -------------------------------------------------------------------------------- 1 | diff --git a/server/generator/constants.go b/server/generator/constants.go 2 | index 401f12e6..49dcf659 100644 3 | --- a/server/generator/constants.go 4 | +++ b/server/generator/constants.go 5 | @@ -19,7 +19,7 @@ func init() { 6 | BUILD_REF = "%s" 7 | BUILD_DATE = "%s" 8 | } 9 | -`, strings.TrimSpace(b.String()), time.Now().Format("20060102")) 10 | +`, strings.TrimSpace(b.String()), time.Unix(@build_date@, 0).Format("20060102")) 11 | 12 | f, err := os.OpenFile("../common/constants_generated.go", os.O_CREATE|os.O_WRONLY, os.ModePerm) 13 | if err != nil { 14 | -------------------------------------------------------------------------------- /nix/filestash-vmtest.nix: -------------------------------------------------------------------------------- 1 | { nixosTest, pkgs, nixosModule }: 2 | nixosTest { 3 | name = "filestash"; 4 | nodes = { 5 | client = { ... }: { 6 | environment.systemPackages = with pkgs; [ curl jq ]; 7 | }; 8 | server = { ... }: { 9 | imports = [ nixosModule ]; 10 | networking.firewall.allowedTCPPorts = [ 8334 ]; 11 | services.filestash.enable = true; 12 | }; 13 | }; 14 | testScript = '' 15 | start_all() 16 | client.wait_for_unit("multi-user.target") 17 | server.wait_for_unit("multi-user.target") 18 | 19 | server.wait_for_unit("filestash.service") 20 | server.sleep(3) 21 | 22 | with subtest("Check that the Filestash webserver can be reached."): 23 | assert "Filestash" in client.succeed( 24 | "curl -sSf http:/server:8334/manifest.json | jq '.name'" 25 | ) 26 | # Test that the endpoint 'admin/setup' does not 404, if it does, we've done 27 | # something wrong, or the program has changed substantially 28 | client.succeed("curl --fail http://server:8334/admin/setup --fail") 29 | ''; 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Matthew Croughan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /nix/filestash-module.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | let 3 | cfg = config.services.filestash; 4 | in { 5 | options.services.filestash = { 6 | enable = lib.mkEnableOption "filestash"; 7 | package = lib.mkOption { 8 | type = lib.types.package; 9 | default = pkgs.filestash; 10 | defaultText = "pkgs.filestash"; 11 | description = '' 12 | Which filestash package to use. 13 | ''; 14 | }; 15 | dataDir = lib.mkOption { 16 | default = "/var/lib/filestash"; 17 | type = lib.types.str; 18 | }; 19 | }; 20 | config = lib.mkIf cfg.enable { 21 | systemd = { 22 | tmpfiles.rules = [ 23 | "d ${cfg.dataDir}/data 0771 - - - -" 24 | "d ${cfg.dataDir}/data/state 0771 - - - -" 25 | ]; 26 | services.filestash = { 27 | description = "A modern web client for SFTP and more"; 28 | wantedBy = [ "multi-user.target" ]; 29 | wants = [ "network-online.target" ]; 30 | after = [ "network-online.target" ]; 31 | serviceConfig = { 32 | Type = "simple"; 33 | ExecStart = "${pkgs.bash}/bin/bash -c 'WORK_DIR=$STATE_DIRECTORY ${lib.getExe cfg.package}'"; 34 | Restart = "always"; 35 | DynamicUser = true; 36 | StateDirectory = baseNameOf cfg.dataDir; 37 | }; 38 | }; 39 | }; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: "Update Flake Inputs" 2 | on: 3 | schedule: 4 | - cron: '0 */2 * * *' 5 | 6 | jobs: 7 | update: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: cachix/install-nix-action@v17 11 | with: 12 | extra_nix_config: "system-features = nixos-test benchmark big-parallel kvm" 13 | install_url: https://github.com/numtide/nix-unstable-installer/releases/download/nix-2.12.0pre20221014_3093bd3/install 14 | - uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 # flakes don't work on shallow clones 17 | - name: git-setup 18 | run: | 19 | git config --global user.name 'Github Actions Are Bad' 20 | git config --global user.email 'dockerpocalypse@kubernetes.com' 21 | - name: update-flake-inputs 22 | run: | 23 | set -xeuo pipefail 24 | nix flake lock --update-input filestash-src --commit-lock-file --commit-lockfile-summary 'flake.lock: update `inputs.filestash-src`' 25 | - name: update-package-lock 26 | run: | 27 | set -xeuo pipefail 28 | nix run .#filestash.passthru.update 29 | git add ./dream2nix-packages/filestash/dream-lock.json 30 | git commit -m "filestash: update dream-lock.json" || true # ignore error if nothing to commit 31 | - name: build-and-check-flake 32 | run: | 33 | set -xeuo pipefail 34 | nix flake check 35 | nix build 36 | - name: push 37 | run: | 38 | git push origin HEAD 39 | 40 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A Flake for Mickael Kerjean's Filestash"; 3 | nixConfig = { 4 | extra-substituters = [ "https://matthewcroughan.cachix.org" ]; 5 | extra-trusted-public-keys = [ "matthewcroughan.cachix.org-1:fON2C9BdzJlp1qPan4t5AF0xlnx8sB0ghZf8VDo7+e8=" ]; 6 | }; 7 | inputs = { 8 | filestash-src = { 9 | url = "github:mickael-kerjean/filestash"; 10 | flake = false; 11 | }; 12 | nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; 13 | dream2nix.url = "github:nix-community/dream2nix"; 14 | flake-parts.url = "github:hercules-ci/flake-parts"; 15 | }; 16 | outputs = { self, nixpkgs, flake-parts, dream2nix, filestash-src }@inputs: 17 | flake-parts.lib.mkFlake { inherit inputs; } { 18 | systems = [ 19 | "x86_64-linux" 20 | "aarch64-linux" 21 | ]; 22 | flake = { 23 | herculesCI.ciSystems = [ "x86_64-linux" ]; 24 | overlay = final: prev: { 25 | filestash = self.packages.${prev.stdenv.hostPlatform.system}.filestash; 26 | }; 27 | nixosModule = { pkgs, lib, config, ... }: { 28 | imports = [ ./nix/filestash-module.nix ]; 29 | nixpkgs.overlays = [ self.overlay ]; 30 | }; 31 | }; 32 | perSystem = { config, self', inputs', pkgs, system, ... }: { 33 | checks = { 34 | filestash = pkgs.callPackage ./nix/filestash-vmtest.nix { nixosModule = self.nixosModule; }; 35 | }; 36 | packages = rec { 37 | default = filestash; 38 | filestash = pkgs.callPackage ./pkgs/filestash { 39 | inherit dream2nix pkgs filestash-src self; 40 | }; 41 | }; 42 | }; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # filestash-nix 2 | 3 | filestash-nix implements a NixOS Module, VM Test and Package (Derivation) for 4 | Mickael Kerjean's excellent piece of software 5 | [Filestash](https://github.com/mickael-kerjean/filestash). 6 | 7 | ## Usage 8 | 9 | To use `filestash-nix`, enable the filestash module on a nixosConfiguration in 10 | your `flake.nix`: 11 | 12 | ```nix 13 | { 14 | inputs.filestash-nix.url = "github:matthewcroughan/filestash-nix"; 15 | 16 | outputs = { self, nixpkgs, filestash-nix }: { 17 | nixosConfigurations.my-machine = nixpkgs.lib.nixosSystem { 18 | modules = [ 19 | filestash-nix.nixosModule 20 | { 21 | services.filestash.enable = true; 22 | } 23 | ]; 24 | }; 25 | }; 26 | } 27 | ``` 28 | 29 | It is then up to you to reverse proxy to the service on port 8334, for example, 30 | you might want to use [Traefik](https://traefik.io/) to reverse proxy to 31 | `dummy.domain.com`, with automatic LetsEncrypt SSL and HTTPS redirects, which 32 | can be achieved by adding the following configuration: 33 | 34 | ```nix 35 | { 36 | networking.firewall.allowedTCPPorts = [ 80 443 ]; 37 | services.traefik = { 38 | enable = true; 39 | dynamicConfigOptions = { 40 | http.middlewares.redirect-to-https.redirectscheme = { 41 | scheme = "https"; 42 | permanent = true; 43 | }; 44 | http = { 45 | services = { 46 | filestash.loadBalancer.servers = [ { url = "http://127.0.0.1:8334"; } ]; 47 | }; 48 | routers = { 49 | filestash-insecure = { 50 | rule = "Host(`dummy.domain.com`)"; 51 | entryPoints = [ "web" ]; 52 | service = "filestash"; 53 | middlewares = "redirect-to-https"; 54 | }; 55 | filestash = { 56 | rule = "Host(`dummy.domain.com`)"; 57 | entryPoints = [ "websecure" ]; 58 | service = "filestash"; 59 | tls.certresolver = "letsencrypt"; 60 | }; 61 | }; 62 | }; 63 | }; 64 | staticConfigOptions = { 65 | entryPoints = { 66 | web.address = ":80"; 67 | websecure.address = ":443"; 68 | certificatesResolvers = { 69 | letsencrypt.acme = { 70 | email = "letsencrypt@domain.com"; 71 | # caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"; 72 | storage = "/var/lib/traefik/cert.json"; 73 | }; 74 | }; 75 | }; 76 | }; 77 | }; 78 | } 79 | ``` 80 | 81 | # Why? 82 | 83 | The original software packaging is not very reproducible, easy to 84 | install/provision, or share, despite the author's best efforts to use 85 | docker/docker-compose. This NixOS module allows anybody to use Filestash simply 86 | by adding `services.filestash.enable = true;` to their NixOS config, and it will 87 | produce the same result each time, invariably, thanks to Nix. 88 | 89 | ## VM Test 90 | 91 | In order to build the QEMU VM integration test using the NixOS Testing 92 | Framework, run `nix build .#checks.x86_64-linux.filestash`, this will 93 | reproducibly: 94 | 95 | 1. Spawn two QEMU VMs, one with `environment.systemPackages = [ curl ]` and the 96 | other with `services.filestash.enable = true` 97 | 2. Wait for the filestash systemd service to become available 98 | 3. Test that Filestash responds correctly when a request is made with `curl` 99 | 100 | The test could be expanded in the future to perform more functions and test the 101 | software more thoroughly. 102 | 103 | ## Development 104 | 105 | ### Updating the Filestash flake input 106 | 107 | This does not require any contributions, as it is automated by CI, but below is 108 | an explanation of how it works. 109 | 110 | Because upstream do not provide a `package-lock.json`, we cannot use dream2nix 111 | directly on it. So, we use dream2nix to provide a `dream-lock.json` instead, 112 | effectively vendoring the upstream's missing lock feature. I have added the 113 | "resolve" script which dream2nix provides to the `passthru` set of the 114 | `filestash` package in this flake, it is available at 115 | `filestash.passthru.updateScript` 116 | 117 | To update: 118 | 119 | 1. `nix flake lock --update-input filestash` 120 | 2. `nix run .#filestash.passthru.update` 121 | 122 | -------------------------------------------------------------------------------- /pkgs/filestash/default.nix: -------------------------------------------------------------------------------- 1 | { buildGoModule 2 | , dream2nix 3 | , filestash-src 4 | , glib 5 | , gotools 6 | , libraw 7 | , pkg-config 8 | , pkgs 9 | , python 10 | , self 11 | , stdenv 12 | , vips 13 | , util-linux 14 | , writeShellScriptBin 15 | }: 16 | let 17 | updateScript = (dream2nix.lib.makeFlakeOutputs { 18 | inherit pkgs; 19 | config.projectRoot = filestash-src; 20 | source = filestash-src; 21 | settings = [ { subsystemInfo.nodejs = "14"; subsystemInfo.npmArgs = "--legacy-peer-deps"; } ]; 22 | autoProjects = true; 23 | }).packages.${pkgs.hostPlatform.system}.filestash.resolve; 24 | frontend = ((dream2nix.lib.init { inherit pkgs; }).dream2nix-interface.makeOutputsForDreamLock { 25 | dreamLock = ../../dream2nix-packages/filestash/dream-lock.json; 26 | sourceOverrides = oldSources: { 27 | "filestash"."0.0.0" = filestash-src; 28 | }; 29 | packageOverrides = { 30 | node-sass = { 31 | add-pre-build-steps = { 32 | buildInputs = old: old ++ [ 33 | pkgs.python 34 | ]; 35 | }; 36 | }; 37 | }; 38 | }).packages.filestash; 39 | libtranscode = stdenv.mkDerivation { 40 | name = "libtranscode"; 41 | src = filestash-src + "/server/plugin/plg_image_light/deps/src"; 42 | buildInputs = [ 43 | libraw 44 | ]; 45 | buildPhase = '' 46 | $CC -Wall -c libtranscode.c 47 | ar rcs libtranscode.a libtranscode.o 48 | ''; 49 | installPhase = '' 50 | mkdir -p $out/lib 51 | mv libtranscode.a $out/lib/ 52 | ''; 53 | }; 54 | libresize = stdenv.mkDerivation { 55 | name = "libresize"; 56 | src = filestash-src + "/server/plugin/plg_image_light/deps/src"; 57 | buildInputs = [ 58 | vips 59 | glib 60 | ]; 61 | nativeBuildInputs = [ 62 | pkg-config 63 | ]; 64 | buildPhase = '' 65 | $CC -Wall -c libresize.c `pkg-config --cflags glib-2.0` 66 | ar rcs libresize.a libresize.o 67 | ''; 68 | installPhase = '' 69 | mkdir -p $out/lib 70 | mv libresize.a $out/lib/ 71 | ''; 72 | }; 73 | in 74 | buildGoModule { 75 | passthru.update = updateScript; 76 | pname = "filestash"; 77 | version = "unstable-" + filestash-src.shortRev; 78 | 79 | src = frontend + "/lib/node_modules/filestash"; 80 | 81 | vendorHash = null; 82 | 83 | excludedPackages = [ 84 | "server/generator" 85 | "server/plugin/plg_starter_http2" 86 | "server/plugin/plg_starter_https" 87 | "server/plugin/plg_search_sqlitefts" 88 | ]; 89 | 90 | buildInputs = [ 91 | glib 92 | libraw 93 | libresize 94 | libtranscode 95 | vips 96 | ]; 97 | 98 | nativeBuildInputs = [ 99 | (writeShellScriptBin "git" "echo '${filestash-src.rev}'") 100 | gotools 101 | util-linux 102 | pkg-config 103 | ]; 104 | 105 | patches = [ 106 | ## Use flake input's lastModified as build date (see `postPatch` phase), as 107 | ## `time.Now()` is impure. The build date is used in Filestash's own version 108 | ## reporting and the http User-Agent when connecting to a backend. 109 | ./fix-impure-build-date.patch 110 | ]; 111 | 112 | postPatch = 113 | let 114 | platform = { 115 | aarch64-linux = "linux_arm"; 116 | x86_64-linux = "linux_amd64"; 117 | }.${pkgs.hostPlatform.system} or (throw "Unsupported system: ${pkgs.hostPlatform.system}"); 118 | in 119 | '' 120 | substituteInPlace server/generator/constants.go --subst-var-by build_date '${toString filestash-src.lastModified}' 121 | 122 | ## fix "imported and not used" errors 123 | goimports -w server/ 124 | 125 | sed -i 's#-L./deps -l:libresize_${platform}.a#-L${libresize.outPath}/lib -l:libresize.a -lvips#' server/plugin/plg_image_light/lib_resize_${platform}.go 126 | sed -i 's#-L./deps -l:libtranscode_${platform}.a#-L${libtranscode.outPath}/lib -l:libtranscode.a -lraw#' server/plugin/plg_image_light/lib_transcode_${platform}.go 127 | 128 | ## server/** requires globstar 129 | shopt -s globstar 130 | rename --no-overwrite --verbose linux_arm.go linux_arm64.go server/** 131 | ''; 132 | 133 | preBuild = '' 134 | make build_init 135 | ''; 136 | 137 | postInstall = '' 138 | mv $out/bin/server $out/bin/filestash 139 | ''; 140 | } 141 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "all-cabal-json": { 4 | "flake": false, 5 | "locked": { 6 | "lastModified": 1665552503, 7 | "narHash": "sha256-r14RmRSwzv5c+bWKUDaze6pXM7nOsiz1H8nvFHJvufc=", 8 | "owner": "nix-community", 9 | "repo": "all-cabal-json", 10 | "rev": "d7c0434eebffb305071404edcf9d5cd99703878e", 11 | "type": "github" 12 | }, 13 | "original": { 14 | "owner": "nix-community", 15 | "ref": "hackage", 16 | "repo": "all-cabal-json", 17 | "type": "github" 18 | } 19 | }, 20 | "crane": { 21 | "flake": false, 22 | "locked": { 23 | "lastModified": 1670900067, 24 | "narHash": "sha256-VXVa+KBfukhmWizaiGiHRVX/fuk66P8dgSFfkVN4/MY=", 25 | "owner": "ipetkov", 26 | "repo": "crane", 27 | "rev": "59b31b41a589c0a65e4a1f86b0e5eac68081468b", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "ipetkov", 32 | "repo": "crane", 33 | "type": "github" 34 | } 35 | }, 36 | "devshell": { 37 | "flake": false, 38 | "locked": { 39 | "lastModified": 1663445644, 40 | "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", 41 | "owner": "numtide", 42 | "repo": "devshell", 43 | "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", 44 | "type": "github" 45 | }, 46 | "original": { 47 | "owner": "numtide", 48 | "repo": "devshell", 49 | "type": "github" 50 | } 51 | }, 52 | "dream2nix": { 53 | "inputs": { 54 | "all-cabal-json": "all-cabal-json", 55 | "crane": "crane", 56 | "devshell": "devshell", 57 | "drv-parts": "drv-parts", 58 | "flake-compat": "flake-compat", 59 | "flake-parts": "flake-parts", 60 | "flake-utils-pre-commit": "flake-utils-pre-commit", 61 | "ghc-utils": "ghc-utils", 62 | "gomod2nix": "gomod2nix", 63 | "mach-nix": "mach-nix", 64 | "nix-pypi-fetcher": "nix-pypi-fetcher", 65 | "nixpkgs": "nixpkgs", 66 | "nixpkgsV1": "nixpkgsV1", 67 | "poetry2nix": "poetry2nix", 68 | "pre-commit-hooks": "pre-commit-hooks", 69 | "pruned-racket-catalog": "pruned-racket-catalog" 70 | }, 71 | "locked": { 72 | "lastModified": 1679749674, 73 | "narHash": "sha256-yUgXDvZctJmHMqfqHiBr3lriZ2iCQutWQzZo46nv94E=", 74 | "owner": "nix-community", 75 | "repo": "dream2nix", 76 | "rev": "a67a45657b5672a346edf1eb3e52593a627ab68d", 77 | "type": "github" 78 | }, 79 | "original": { 80 | "owner": "nix-community", 81 | "repo": "dream2nix", 82 | "type": "github" 83 | } 84 | }, 85 | "drv-parts": { 86 | "inputs": { 87 | "flake-compat": [ 88 | "dream2nix", 89 | "flake-compat" 90 | ], 91 | "flake-parts": [ 92 | "dream2nix", 93 | "flake-parts" 94 | ], 95 | "nixpkgs": [ 96 | "dream2nix", 97 | "nixpkgs" 98 | ] 99 | }, 100 | "locked": { 101 | "lastModified": 1679631398, 102 | "narHash": "sha256-LmA1XEzVoJhtLA6GLuMTrnYM0/2piTxdWxKXCVLiaxw=", 103 | "owner": "davhau", 104 | "repo": "drv-parts", 105 | "rev": "2544be2a9e7c8f347a3af98ba0298f2ee9d3f0fa", 106 | "type": "github" 107 | }, 108 | "original": { 109 | "owner": "davhau", 110 | "repo": "drv-parts", 111 | "type": "github" 112 | } 113 | }, 114 | "filestash-src": { 115 | "flake": false, 116 | "locked": { 117 | "lastModified": 1686124671, 118 | "narHash": "sha256-bDtZ5DY8XgJ2d2alk7bmS8h6ML0/nmT7ePFwuRhObI4=", 119 | "owner": "mickael-kerjean", 120 | "repo": "filestash", 121 | "rev": "5eadfac2ae7a8daa248dbdea146edee9da67189d", 122 | "type": "github" 123 | }, 124 | "original": { 125 | "owner": "mickael-kerjean", 126 | "repo": "filestash", 127 | "type": "github" 128 | } 129 | }, 130 | "flake-compat": { 131 | "flake": false, 132 | "locked": { 133 | "lastModified": 1673956053, 134 | "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", 135 | "owner": "edolstra", 136 | "repo": "flake-compat", 137 | "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", 138 | "type": "github" 139 | }, 140 | "original": { 141 | "owner": "edolstra", 142 | "repo": "flake-compat", 143 | "type": "github" 144 | } 145 | }, 146 | "flake-parts": { 147 | "inputs": { 148 | "nixpkgs-lib": [ 149 | "dream2nix", 150 | "nixpkgs" 151 | ] 152 | }, 153 | "locked": { 154 | "lastModified": 1675933616, 155 | "narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=", 156 | "owner": "hercules-ci", 157 | "repo": "flake-parts", 158 | "rev": "47478a4a003e745402acf63be7f9a092d51b83d7", 159 | "type": "github" 160 | }, 161 | "original": { 162 | "owner": "hercules-ci", 163 | "repo": "flake-parts", 164 | "type": "github" 165 | } 166 | }, 167 | "flake-parts_2": { 168 | "inputs": { 169 | "nixpkgs-lib": "nixpkgs-lib" 170 | }, 171 | "locked": { 172 | "lastModified": 1673362319, 173 | "narHash": "sha256-Pjp45Vnj7S/b3BRpZEVfdu8sqqA6nvVjvYu59okhOyI=", 174 | "owner": "hercules-ci", 175 | "repo": "flake-parts", 176 | "rev": "82c16f1682cf50c01cb0280b38a1eed202b3fe9f", 177 | "type": "github" 178 | }, 179 | "original": { 180 | "owner": "hercules-ci", 181 | "repo": "flake-parts", 182 | "type": "github" 183 | } 184 | }, 185 | "flake-utils-pre-commit": { 186 | "locked": { 187 | "lastModified": 1644229661, 188 | "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", 189 | "owner": "numtide", 190 | "repo": "flake-utils", 191 | "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", 192 | "type": "github" 193 | }, 194 | "original": { 195 | "owner": "numtide", 196 | "repo": "flake-utils", 197 | "type": "github" 198 | } 199 | }, 200 | "ghc-utils": { 201 | "flake": false, 202 | "locked": { 203 | "lastModified": 1662774800, 204 | "narHash": "sha256-1Rd2eohGUw/s1tfvkepeYpg8kCEXiIot0RijapUjAkE=", 205 | "ref": "refs/heads/master", 206 | "rev": "bb3a2d3dc52ff0253fb9c2812bd7aa2da03e0fea", 207 | "revCount": 1072, 208 | "type": "git", 209 | "url": "https://gitlab.haskell.org/bgamari/ghc-utils" 210 | }, 211 | "original": { 212 | "type": "git", 213 | "url": "https://gitlab.haskell.org/bgamari/ghc-utils" 214 | } 215 | }, 216 | "gomod2nix": { 217 | "flake": false, 218 | "locked": { 219 | "lastModified": 1627572165, 220 | "narHash": "sha256-MFpwnkvQpauj799b4QTBJQFEddbD02+Ln5k92QyHOSk=", 221 | "owner": "tweag", 222 | "repo": "gomod2nix", 223 | "rev": "67f22dd738d092c6ba88e420350ada0ed4992ae8", 224 | "type": "github" 225 | }, 226 | "original": { 227 | "owner": "tweag", 228 | "repo": "gomod2nix", 229 | "type": "github" 230 | } 231 | }, 232 | "mach-nix": { 233 | "flake": false, 234 | "locked": { 235 | "lastModified": 1634711045, 236 | "narHash": "sha256-m5A2Ty88NChLyFhXucECj6+AuiMZPHXNbw+9Kcs7F6Y=", 237 | "owner": "DavHau", 238 | "repo": "mach-nix", 239 | "rev": "4433f74a97b94b596fa6cd9b9c0402104aceef5d", 240 | "type": "github" 241 | }, 242 | "original": { 243 | "id": "mach-nix", 244 | "type": "indirect" 245 | } 246 | }, 247 | "nix-pypi-fetcher": { 248 | "flake": false, 249 | "locked": { 250 | "lastModified": 1669065297, 251 | "narHash": "sha256-UStjXjNIuIm7SzMOWvuYWIHBkPUKQ8Id63BMJjnIDoA=", 252 | "owner": "DavHau", 253 | "repo": "nix-pypi-fetcher", 254 | "rev": "a9885ac6a091576b5195d547ac743d45a2a615ac", 255 | "type": "github" 256 | }, 257 | "original": { 258 | "owner": "DavHau", 259 | "repo": "nix-pypi-fetcher", 260 | "type": "github" 261 | } 262 | }, 263 | "nixpkgs": { 264 | "locked": { 265 | "lastModified": 1665580254, 266 | "narHash": "sha256-hO61XPkp1Hphl4HGNzj1VvDH5URt7LI6LaY/385Eul4=", 267 | "owner": "NixOS", 268 | "repo": "nixpkgs", 269 | "rev": "f634d427b0224a5f531ea5aa10c3960ba6ec5f0f", 270 | "type": "github" 271 | }, 272 | "original": { 273 | "id": "nixpkgs", 274 | "ref": "nixos-unstable", 275 | "type": "indirect" 276 | } 277 | }, 278 | "nixpkgs-lib": { 279 | "locked": { 280 | "dir": "lib", 281 | "lastModified": 1672350804, 282 | "narHash": "sha256-jo6zkiCabUBn3ObuKXHGqqORUMH27gYDIFFfLq5P4wg=", 283 | "owner": "NixOS", 284 | "repo": "nixpkgs", 285 | "rev": "677ed08a50931e38382dbef01cba08a8f7eac8f6", 286 | "type": "github" 287 | }, 288 | "original": { 289 | "dir": "lib", 290 | "owner": "NixOS", 291 | "ref": "nixos-unstable", 292 | "repo": "nixpkgs", 293 | "type": "github" 294 | } 295 | }, 296 | "nixpkgsV1": { 297 | "locked": { 298 | "lastModified": 1678500271, 299 | "narHash": "sha256-tRBLElf6f02HJGG0ZR7znMNFv/Uf7b2fFInpTHiHaSE=", 300 | "owner": "NixOS", 301 | "repo": "nixpkgs", 302 | "rev": "5eb98948b66de29f899c7fe27ae112a47964baf8", 303 | "type": "github" 304 | }, 305 | "original": { 306 | "id": "nixpkgs", 307 | "ref": "nixos-22.11", 308 | "type": "indirect" 309 | } 310 | }, 311 | "nixpkgs_2": { 312 | "locked": { 313 | "lastModified": 1679748960, 314 | "narHash": "sha256-BP8XcYHyj1NxQi04RpyNW8e7KiXSoI+Fy1tXIK2GfdA=", 315 | "owner": "nixos", 316 | "repo": "nixpkgs", 317 | "rev": "da26ae9f6ce2c9ab380c0f394488892616fc5a6a", 318 | "type": "github" 319 | }, 320 | "original": { 321 | "owner": "nixos", 322 | "ref": "nixos-22.11", 323 | "repo": "nixpkgs", 324 | "type": "github" 325 | } 326 | }, 327 | "poetry2nix": { 328 | "flake": false, 329 | "locked": { 330 | "lastModified": 1666918719, 331 | "narHash": "sha256-BkK42fjAku+2WgCOv2/1NrPa754eQPV7gPBmoKQBWlc=", 332 | "owner": "nix-community", 333 | "repo": "poetry2nix", 334 | "rev": "289efb187123656a116b915206e66852f038720e", 335 | "type": "github" 336 | }, 337 | "original": { 338 | "owner": "nix-community", 339 | "ref": "1.36.0", 340 | "repo": "poetry2nix", 341 | "type": "github" 342 | } 343 | }, 344 | "pre-commit-hooks": { 345 | "inputs": { 346 | "flake-utils": [ 347 | "dream2nix", 348 | "flake-utils-pre-commit" 349 | ], 350 | "nixpkgs": [ 351 | "dream2nix", 352 | "nixpkgs" 353 | ] 354 | }, 355 | "locked": { 356 | "lastModified": 1646153636, 357 | "narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=", 358 | "owner": "cachix", 359 | "repo": "pre-commit-hooks.nix", 360 | "rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b", 361 | "type": "github" 362 | }, 363 | "original": { 364 | "owner": "cachix", 365 | "repo": "pre-commit-hooks.nix", 366 | "type": "github" 367 | } 368 | }, 369 | "pruned-racket-catalog": { 370 | "flake": false, 371 | "locked": { 372 | "lastModified": 1672537287, 373 | "narHash": "sha256-SuOvXVcLfakw18oJB/PuRMyvGyGG1+CQD3R+TGHIv44=", 374 | "owner": "nix-community", 375 | "repo": "pruned-racket-catalog", 376 | "rev": "c8b89557fb53b36efa2ee48a769c7364df0f6262", 377 | "type": "github" 378 | }, 379 | "original": { 380 | "owner": "nix-community", 381 | "ref": "catalog", 382 | "repo": "pruned-racket-catalog", 383 | "type": "github" 384 | } 385 | }, 386 | "root": { 387 | "inputs": { 388 | "dream2nix": "dream2nix", 389 | "filestash-src": "filestash-src", 390 | "flake-parts": "flake-parts_2", 391 | "nixpkgs": "nixpkgs_2" 392 | } 393 | } 394 | }, 395 | "root": "root", 396 | "version": 7 397 | } 398 | --------------------------------------------------------------------------------