summaryrefslogtreecommitdiff
path: root/nix
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2020-04-19 16:50:36 -0700
committerBen Sima <ben@bsima.me>2020-04-19 17:51:39 -0700
commit35f0ade5ea77d17544d253f970ef94dd1c7cd9f0 (patch)
tree588c20152bc338f8ded6cba434817b2f8fdd5d1c /nix
parent42d1fab5fd7af5682bd693d4784d9da1a2d4bfef (diff)
Switch to niv for managing third party sources
Diffstat (limited to 'nix')
-rw-r--r--nix/build.nix121
-rw-r--r--nix/deps.nix53
-rw-r--r--nix/nixpkgs.nix10
-rw-r--r--nix/overlay.nix65
-rw-r--r--nix/sources.json26
-rw-r--r--nix/sources.nix134
6 files changed, 409 insertions, 0 deletions
diff --git a/nix/build.nix b/nix/build.nix
new file mode 100644
index 0000000..6f979d7
--- /dev/null
+++ b/nix/build.nix
@@ -0,0 +1,121 @@
+{ nixpkgs }:
+
+with nixpkgs;
+
+let
+ # provided by .envrc
+ root = builtins.getEnv "BIZ_ROOT";
+
+ # general functions to put in a lib
+ lines = s: lib.strings.splitString "\n" s;
+ removeNull = ls: builtins.filter (x: x != null) ls;
+
+ depsToPackageSet = packageSet: deps:
+ lib.attrsets.attrVals deps packageSet;
+
+ # returns true if a is a subset of b, where a and b are attrsets
+ subset = a: b: builtins.all
+ (x: builtins.elem x b) a;
+
+ allDeps = import ./deps.nix;
+
+ # gather data needed for compiling by analyzing the main module
+ analyze = main: rec {
+ # path to the module relative to the git root
+ relpath = builtins.replaceStrings ["${root}/"] [""]
+ (builtins.toString main);
+ # Haskell-appropriate name of the module
+ module = builtins.replaceStrings ["/" ".hs"] ["." ""] relpath;
+ # file contents
+ content = builtins.readFile main;
+ # search for the ': exe' declaration
+ exe = builtins.head (lib.lists.flatten (removeNull
+ (map (builtins.match "^-- : exe ([[:alnum:]._-]*)$")
+ (lines content))));
+ # collect all of the ': dep' declarations
+ deps = lib.lists.flatten (removeNull
+ (map (builtins.match "^-- : dep ([[:alnum:]._-]*)$")
+ (lines content)));
+ };
+
+ mkGhc = compiler: (deps: compiler (hp:
+ if (subset deps allDeps)
+ then depsToPackageSet hp deps
+ else throw ''
+ missing from deps.nix:
+ ${toString (lib.lists.subtractLists allDeps deps)}
+ ''));
+
+ ghc_ = mkGhc pkgs.haskell.packages.ghc865.ghcWithHoogle;
+ ghcjs_ = mkGhc pkgs.haskell.packages.ghcjs.ghcWithPackages;
+in {
+ ghc = main:
+ let
+ data = analyze main;
+ ghc = ghc_ data.deps;
+ in stdenv.mkDerivation {
+ name = data.module;
+ src = ../.;
+ nativeBuildInputs = [ ghc ];
+ strictDeps = true;
+ buildPhase = ''
+ mkdir -p $out/bin
+ # compile with ghc
+ ${ghc}/bin/ghc -Werror -i. \
+ --make ${main} \
+ -main-is ${data.module} \
+ -o $out/bin/${data.exe}
+ '';
+ # the install process was handled above
+ installPhase = "exit 0";
+ } // { env = ghc; };
+
+ ghcjs = main:
+ let
+ data = analyze main;
+ ghcjs = ghcjs_ data.deps;
+ in stdenv.mkDerivation {
+ name = data.module;
+ src = ../.;
+ nativeBuildInputs = [ ghcjs ];
+ strictDeps = true;
+ buildPhase = ''
+ mkdir -p $out/static
+ # compile with ghcjs
+ ${ghcjs}/bin/ghcjs -Werror -i. \
+ --make ${main} \
+ -main-is ${data.module} \
+ -o ${data.exe}
+ # optimize js output
+ ${pkgs.closurecompiler}/bin/closure-compiler \
+ ${data.exe}/all.js > $out/static/${data.exe}
+ '';
+ installPhase = "exit 0";
+ } // { env = ghcjs; };
+
+ env = ghc_ allDeps;
+
+ os = cfg: (nixos (args: lib.attrsets.recursiveUpdate cfg {
+ boot.cleanTmpDir = true;
+ networking.firewall.allowPing = true;
+ nix.binaryCaches = [ "https://cache.nixos.org" ];
+ nix.gc.automatic = true;
+ nix.gc.dates = "Sunday 02:15";
+ nix.optimise.automatic = true;
+ nix.optimise.dates = [ "Sunday 02:30" ];
+ nixpkgs.overlays = overlays;
+ programs.mosh.enable = true;
+ programs.mosh.withUtempter = true;
+ security.acme.email = "ben@bsima.me";
+ security.acme.acceptTerms = true;
+ security.sudo.wheelNeedsPassword = false;
+ services.clamav.daemon.enable = true; # security
+ services.clamav.updater.enable = true; # security
+ services.fail2ban.enable = true; # security
+ services.openssh.enable = true;
+ services.openssh.openFirewall = true;
+ services.openssh.forwardX11 = true;
+ services.openssh.passwordAuthentication = false;
+ system.autoUpgrade.enable = false; # 'true' breaks our nixpkgs pin
+ })).toplevel;
+}
diff --git a/nix/deps.nix b/nix/deps.nix
new file mode 100644
index 0000000..44c2050
--- /dev/null
+++ b/nix/deps.nix
@@ -0,0 +1,53 @@
+[
+ "MonadRandom"
+ "QuickCheck"
+ "acid-state"
+ "aeson"
+ "async"
+ "bytestring"
+ "capability"
+ "clay"
+ "config-ini"
+ "containers"
+ "dhall"
+ "directory"
+ "ekg"
+ "envy"
+ "fast-logger"
+ "filepath"
+ "ghcjs-base"
+ "http-types"
+ "ixset"
+ "katip"
+ "lucid"
+ "miso"
+ "monad-logger"
+ "monad-metrics"
+ "mtl"
+ "network-uri"
+ "process"
+ "protolude"
+ "quickcheck-instances"
+ "random"
+ "req"
+ "safecopy"
+ "scotty"
+ "servant"
+ "servant-lucid"
+ "servant-server"
+ "split"
+ "stm"
+ "string-quote"
+ "tasty"
+ "text"
+ "transformers"
+ "unagi-chan"
+ "unix"
+ "unordered-containers"
+ "vector"
+ "wai"
+ "wai-app-static"
+ "wai-extra"
+ "wai-middleware-metrics"
+ "warp"
+]
diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix
new file mode 100644
index 0000000..246b8a8
--- /dev/null
+++ b/nix/nixpkgs.nix
@@ -0,0 +1,10 @@
+let
+ sources = import ./sources.nix;
+ nixpkgs = import sources.nixpkgs {
+ system = "x86_64-linux";
+ overlays = [
+ (_: _: { niv = import sources.niv {}; })
+ (import ./overlay.nix)
+ ];
+ };
+in nixpkgs
diff --git a/nix/overlay.nix b/nix/overlay.nix
new file mode 100644
index 0000000..dcadf34
--- /dev/null
+++ b/nix/overlay.nix
@@ -0,0 +1,65 @@
+self: super:
+
+let
+ claySrc = super.pkgs.fetchFromGitHub {
+ owner = "sebastiaanvisser";
+ repo = "clay";
+ rev = "cc7729b1b42a79e261091ff7835f7fc2a7ae3cee";
+ sha256 = "1vd67976lvi5l4qq18zy6j44apynkl44ps04p8vwfx4gzr895dyp";
+ };
+ jsaddleSrc = super.pkgs.fetchFromGitHub {
+ owner = "ghcjs";
+ repo = "jsaddle";
+ rev = "1e39844";
+ sha256 = "1qrjrjagmrrlcalys33636w5cb67db52i183masb7xd93wir8963";
+ };
+ misoSrc = super.pkgs.fetchFromGitHub {
+ owner = "dmjio";
+ repo = "miso";
+ rev = "1.5";
+ sha256 = "00al7gw760vzzlqpf035k4n4li0rdymcjpxn184z9nc4m92cjv9z";
+ };
+in {
+ haskell = super.haskell // {
+ packages = super.haskell.packages // {
+ ghc865 = super.haskell.packages.ghc865.override (old: {
+ overrides = with super.pkgs.haskell.lib; self: super: {
+ clay = self.callCabal2nix "clay" claySrc {};
+ miso = self.callCabal2nix "miso" misoSrc {};
+ wai-middleware-metrics = dontCheck super.wai-middleware-metrics;
+ };
+ });
+ ghcjs = super.haskell.packages.ghcjs.override (old: {
+ overrides = with super.haskell.lib; self: super: {
+ QuickCheck = dontCheck super.QuickCheck;
+ base-compat-batteries = dontCheck super.http-types;
+ clay = dontCheck (self.callCabal2nix "clay" claySrc {});
+ comonad = dontCheck super.comonad;
+ jsaddle-warp = dontCheck (self.callCabal2nix "jsaddle-warp" "${jsaddleSrc}/jsaddle-warp" {});
+ http-types = dontCheck super.http-types;
+ miso = self.callCabal2nix "miso" misoSrc {};
+ network-uri= dontCheck super.network-uri;
+ scientific = dontCheck super.scientific; # takes forever
+ servant = dontCheck super.servant;
+ tasty-quickcheck = dontCheck super.tasty-quickcheck;
+ time-compat = dontCheck super.time-compat;
+ };
+ });
+ };
+ };
+ wemux = super.stdenv.mkDerivation rec {
+ name = "wemux";
+ version = "2020.04.03";
+ src = super.pkgs.fetchFromGitHub {
+ owner = "zolrath";
+ repo = "wemux";
+ rev = "01c6541f8deceff372711241db2a13f21c4b210c";
+ sha256 = "1y962nzvs7sf720pl3wa582l6irxc8vavd0gp4ag4243b2gs4qvm";
+ };
+ installPhase = ''
+ mkdir -p $out/bin
+ cp ${src}/wemux $out/bin
+ chmod +x $out/bin/wemux
+ '';
+ };
+}
diff --git a/nix/sources.json b/nix/sources.json
new file mode 100644
index 0000000..841f308
--- /dev/null
+++ b/nix/sources.json
@@ -0,0 +1,26 @@
+{
+ "niv": {
+ "branch": "master",
+ "description": "Easy dependency management for Nix projects",
+ "homepage": "https://github.com/nmattia/niv",
+ "owner": "nmattia",
+ "repo": "niv",
+ "rev": "f73bf8d584148677b01859677a63191c31911eae",
+ "sha256": "0jlmrx633jvqrqlyhlzpvdrnim128gc81q5psz2lpp2af8p8q9qs",
+ "type": "tarball",
+ "url": "https://github.com/nmattia/niv/archive/f73bf8d584148677b01859677a63191c31911eae.tar.gz",
+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+ },
+ "nixpkgs": {
+ "branch": "nixos-19.09",
+ "description": "Nix Packages collection",
+ "homepage": "https://github.com/NixOS/nixpkgs",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "b0c285807d6a9f1b7562ec417c24fa1a30ecc31a",
+ "sha256": "0waapr7aqz0h1fy1fqlx981ygllh91qx9sz1l2j2h59s46cdircl",
+ "type": "tarball",
+ "url": "https://github.com/NixOS/nixpkgs/archive/b0c285807d6a9f1b7562ec417c24fa1a30ecc31a.tar.gz",
+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+ }
+}
diff --git a/nix/sources.nix b/nix/sources.nix
new file mode 100644
index 0000000..8a725cb
--- /dev/null
+++ b/nix/sources.nix
@@ -0,0 +1,134 @@
+# This file has been generated by Niv.
+
+let
+
+ #
+ # The fetchers. fetch_<type> fetches specs of type <type>.
+ #
+
+ fetch_file = pkgs: spec:
+ if spec.builtin or true then
+ builtins_fetchurl { inherit (spec) url sha256; }
+ else
+ pkgs.fetchurl { inherit (spec) url sha256; };
+
+ fetch_tarball = pkgs: spec:
+ if spec.builtin or true then
+ builtins_fetchTarball { inherit (spec) url sha256; }
+ else
+ pkgs.fetchzip { inherit (spec) url sha256; };
+
+ fetch_git = spec:
+ builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
+
+ fetch_builtin-tarball = spec:
+ builtins.trace
+ ''
+ WARNING:
+ The niv type "builtin-tarball" will soon be deprecated. You should
+ instead use `builtin = true`.
+
+ $ niv modify <package> -a type=tarball -a builtin=true
+ ''
+ builtins_fetchTarball { inherit (spec) url sha256; };
+
+ fetch_builtin-url = spec:
+ builtins.trace
+ ''
+ WARNING:
+ The niv type "builtin-url" will soon be deprecated. You should
+ instead use `builtin = true`.
+
+ $ niv modify <package> -a type=file -a builtin=true
+ ''
+ (builtins_fetchurl { inherit (spec) url sha256; });
+
+ #
+ # Various helpers
+ #
+
+ # The set of packages used when specs are fetched using non-builtins.
+ mkPkgs = sources:
+ let
+ sourcesNixpkgs =
+ import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {};
+ hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
+ hasThisAsNixpkgsPath = <nixpkgs> == ./.;
+ in
+ if builtins.hasAttr "nixpkgs" sources
+ then sourcesNixpkgs
+ else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
+ import <nixpkgs> {}
+ else
+ abort
+ ''
+ Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
+ add a package called "nixpkgs" to your sources.json.
+ '';
+
+ # The actual fetching function.
+ fetch = pkgs: name: spec:
+
+ if ! builtins.hasAttr "type" spec then
+ abort "ERROR: niv spec ${name} does not have a 'type' attribute"
+ else if spec.type == "file" then fetch_file pkgs spec
+ else if spec.type == "tarball" then fetch_tarball pkgs spec
+ else if spec.type == "git" then fetch_git spec
+ else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec
+ else if spec.type == "builtin-url" then fetch_builtin-url spec
+ else
+ abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
+
+ # Ports of functions for older nix versions
+
+ # a Nix version of mapAttrs if the built-in doesn't exist
+ mapAttrs = builtins.mapAttrs or (
+ f: set: with builtins;
+ listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
+ );
+
+ # fetchTarball version that is compatible between all the versions of Nix
+ builtins_fetchTarball = { url, sha256 }@attrs:
+ let
+ inherit (builtins) lessThan nixVersion fetchTarball;
+ in
+ if lessThan nixVersion "1.12" then
+ fetchTarball { inherit url; }
+ else
+ fetchTarball attrs;
+
+ # fetchurl version that is compatible between all the versions of Nix
+ builtins_fetchurl = { url, sha256 }@attrs:
+ let
+ inherit (builtins) lessThan nixVersion fetchurl;
+ in
+ if lessThan nixVersion "1.12" then
+ fetchurl { inherit url; }
+ else
+ fetchurl attrs;
+
+ # Create the final "sources" from the config
+ mkSources = config:
+ mapAttrs (
+ name: spec:
+ if builtins.hasAttr "outPath" spec
+ then abort
+ "The values in sources.json should not have an 'outPath' attribute"
+ else
+ spec // { outPath = fetch config.pkgs name spec; }
+ ) config.sources;
+
+ # The "config" used by the fetchers
+ mkConfig =
+ { sourcesFile ? ./sources.json
+ , sources ? builtins.fromJSON (builtins.readFile sourcesFile)
+ , pkgs ? mkPkgs sources
+ }: rec {
+ # The sources, i.e. the attribute set of spec name to spec
+ inherit sources;
+
+ # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
+ inherit pkgs;
+ };
+in
+mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }