packages feed

nix-cache-server (empty) → 0.1.0.0

raw patch · 2 files changed

+174/−0 lines, 2 filesdep +basedep +bytestringdep +nix

Dependencies added: base, bytestring, nix, nix-serve-ng, relude, wai

Files

+ nix-cache-server.cabal view
@@ -0,0 +1,66 @@+cabal-version: 2.0++-- This file has been generated from package.yaml by hpack version 0.38.2.+--+-- see: https://github.com/sol/hpack++name:           nix-cache-server+version:        0.1.0.0+synopsis:       Nix binary cache server using nix-serve-ng+description:    WAI application for serving a Nix binary cache using nix-serve-ng+category:       System+homepage:       https://github.com/juspay/vira/tree/main/packages/nix-cache-server+author:         Sridhar Ratnakumar+maintainer:     srid@srid.ca+copyright:      2025 Sridhar Ratnakumar+license:        MIT+build-type:     Simple++library+  exposed-modules:+      System.Nix.Cache.Server+  other-modules:+      Paths_nix_cache_server+  autogen-modules:+      Paths_nix_cache_server+  hs-source-dirs:+      src+  default-extensions:+      DataKinds+      DeriveDataTypeable+      DeriveGeneric+      DeriveTraversable+      DerivingStrategies+      DerivingVia+      ExplicitForAll+      FlexibleContexts+      FlexibleInstances+      GeneralizedNewtypeDeriving+      ImportQualifiedPost+      LambdaCase+      MultiParamTypeClasses+      MultiWayIf+      NamedFieldPuns+      NoStarIsType+      NumericUnderscores+      OverloadedStrings+      ScopedTypeVariables+      StrictData+      TypeApplications+      TypeFamilies+      TypeOperators+      TypeSynonymInstances+      ViewPatterns+  ghc-options: -Wall -optP-Wno-nonportable-include-path -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Wunused-foralls -fprint-explicit-foralls -fprint-explicit-kinds+  build-depends:+      base ==4.*+    , bytestring+    , nix+    , nix-serve-ng+    , relude >=1.0+    , wai+  mixins:+      base hiding (Prelude)+    , relude (Relude as Prelude, Relude.Container.One)+    , relude +  default-language: GHC2021
+ src/System/Nix/Cache/Server.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE DuplicateRecordFields #-}++{- | Nix binary cache server integration using nix-serve-ng++This module provides a WAI application for serving a Nix binary cache using+the <https://github.com/aristanetworks/nix-serve-ng nix-serve-ng> library.++= Usage++The typical flow is:++1. Generate or load cache signing keys using "System.Nix.Cache.Keys"+2. Call 'makeCacheApplication' with the keys to create a WAI Application+3. Mount the application in your web server (e.g., at @\/cache@)++The resulting cache server exposes standard Nix cache endpoints like:++* @\/nix-cache-info@ - Cache metadata+* @\/*.narinfo@ - NAR info files+* @\/nar\/*.nar@ - NAR archives++This integrates with nix-serve-ng which handles all the Nix-specific+protocols and signing of NAR files.+-}+module System.Nix.Cache.Server (+  -- * Cache server+  makeCacheServer,+  cacheMiddleware,+) where++import Data.ByteString qualified as ByteString+import Network.Wai (Application, Middleware, pathInfo, rawPathInfo)+import Nix qualified+import NixServeNg (ApplicationOptions (..), makeApplication)+import System.Nix.Cache.Keys (SecretKey, secretKeyByteString)++{- | Create a cache server WAI Application++This function:++1. Initializes the Nix store using the @nix@ library+2. Retrieves the Nix store directory path+3. Creates a nix-serve-ng application with the provided signing key++The returned WAI 'Application' can be mounted at any path in your web server+(commonly @\/cache@). It will handle all Nix binary cache protocol requests.++The cache is configured with a hardcoded priority of 30 (lower numbers have+higher priority in Nix's cache resolution).++Example:++@+CacheKeys {secretKey, publicKey} <- ensureCacheKeys "\/path\/to\/keys"+cacheApp <- makeCacheServer secretKey+-- Mount cacheApp at \/cache in your WAI server+-- Use publicKey for UI display+@+-}+makeCacheServer :: SecretKey -> IO Application+makeCacheServer secretKey = do+  -- Initialize Nix store+  Nix.initStore++  -- Get store directory+  storePath <- Nix.getStoreDir++  -- Create application options with hardcoded priority+  let options =+        ApplicationOptions+          { priority = 30 -- Lower is higher priority+          , storeDirectory = storePath+          , secretKey = Just (secretKeyByteString secretKey)+          }++  -- Return the application+  pure $ makeApplication options++{- | Middleware to mount cache server at a path prefix++This middleware intercepts requests starting with the given path prefix+(e.g., @\/cache\/*@) and routes them to the cache application, while allowing+requests to the prefix itself (e.g., @\/cache@) to pass through to the main+application.++This is useful when you want to serve a UI page at @\/cache@ while serving+the actual cache protocol at @\/cache\/nix-cache-info@, @\/cache\/*.narinfo@, etc.++Example:++@+cacheApp <- makeCacheServer secretKey+let middleware = cacheMiddleware "cache" cacheApp+@+-}+cacheMiddleware :: Text -> Application -> Middleware+cacheMiddleware prefix cacheApp app req respond =+  case pathInfo req of+    (p : rest@(_ : _)) | p == prefix -> do+      -- Only intercept if there's at least one path segment after prefix+      -- This allows /prefix (UI page) to pass through to servant+      -- while /prefix/nix-cache-info, /prefix/*.narinfo, etc go to cache app+      let rawPath = rawPathInfo req+          prefixBytes = "/" <> encodeUtf8 prefix+          rawPath' = fromMaybe rawPath $ ByteString.stripPrefix prefixBytes rawPath+          req' = req {pathInfo = rest, rawPathInfo = rawPath'}+      cacheApp req' respond+    _ -> app req respond