Add README.md (#4)
… and make matching changes to `flake.nix` to support the usage documented in the `README`
This commit is contained in:
parent
166672a78f
commit
e686b2b1fc
175
README.md
Normal file
175
README.md
Normal file
@ -0,0 +1,175 @@
|
||||
# `nix-serve-ng`
|
||||
|
||||
`nix-serve-ng` is a faster, more reliable, drop-in replacement for `nix-serve`.
|
||||
|
||||
## Quick start
|
||||
|
||||
There are two main approaches you can use to upgrade a NixOS system to replace
|
||||
the old `nix-serve` with `nix-serve-ng`.
|
||||
|
||||
If you specify your desired NixOS system within `flake.nix` then you can do
|
||||
something like this:
|
||||
|
||||
```nix
|
||||
{ inputs = {
|
||||
nixpkgs.url = github:NixOS/nixpkgs;
|
||||
|
||||
nix-serve-ng.url = github:aristanetworks/nix-serve-ng;
|
||||
};
|
||||
|
||||
outputs = { nixpkgs, nix-serve-ng, ... }: {
|
||||
nixosConfigurations.default = nixpkgs.lib.nixosSystem {
|
||||
modules = [
|
||||
nix-serve-ng.nixosModules.default
|
||||
|
||||
{ services.nix-serve.enable = true;
|
||||
|
||||
…
|
||||
}
|
||||
];
|
||||
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
If you don't use `flake.nix` then you can instead define your NixOS module:
|
||||
like this:
|
||||
|
||||
```nix
|
||||
let
|
||||
nix-serve-ng-src = builtins.fetchTarball {
|
||||
# Replace the URL and hash with whatever you actually need
|
||||
url = "https://github.com/aristanetworks/nix-serve-ng/archive/166672a78f20e4ec58b0a9748f4f04fc9f341ea3.tar.gz";
|
||||
|
||||
sha256 = "0giib41mjb1j91an1qwpgh94bvrn841azdjv082kwd4kcjhms52h";
|
||||
};
|
||||
|
||||
nix-serve-ng = import nix-serve-ng-src;
|
||||
|
||||
in
|
||||
{ ... }: {
|
||||
imports = [ nix-serve-ng.nixosModules.default ];
|
||||
|
||||
…
|
||||
}
|
||||
```
|
||||
|
||||
## Motivation
|
||||
|
||||
Our requirements for this project were:
|
||||
|
||||
* Improve reliability
|
||||
|
||||
… since `nix-serve` would intermittently hang and require restarts
|
||||
|
||||
* Improve efficiency
|
||||
|
||||
… since `nix-serve` was doing some obviously inefficient things which we
|
||||
felt we could improve upon
|
||||
|
||||
* Be backwards-compatible
|
||||
|
||||
Our replacement would need to be a drop-in replacement for the original
|
||||
`nix-serve`, supporting the same command-line options and even sharing the
|
||||
same executable name
|
||||
|
||||
The only exception is logging: we provide more detailed logging than before
|
||||
|
||||
Did we satisfy those requirements?
|
||||
|
||||
## Results
|
||||
|
||||
* Reliability
|
||||
|
||||
We have test-driven this internally under heavy load with stable memory
|
||||
usage and without any failures but it's probably premature to declare victory.
|
||||
|
||||
In particular, we have *not* done the following things:
|
||||
|
||||
* Memory leak detection
|
||||
|
||||
In other words, we haven't put our `nix-serve` through, say, `valgrind`
|
||||
|
||||
* Exploit detection
|
||||
|
||||
In other words, we haven't attempted to crash or sabotage the service with
|
||||
maliciously-crafted payload
|
||||
|
||||
* Performance
|
||||
|
||||
We have improved significantly on efficiency, not only compared to `nix-serve`
|
||||
but also compared to other `nix-serve` rewrites. We are more efficient than:
|
||||
|
||||
* The original `nix-serve`
|
||||
|
||||
* [`eris`](https://github.com/thoughtpolice/eris) - A Perl rewrite of
|
||||
`nix-serve`
|
||||
|
||||
* [`harmonia`](https://github.com/helsinki-systems/harmonia) - A Rust rewrite
|
||||
of `nix-serve`
|
||||
|
||||
* Backwards-compatibility
|
||||
|
||||
We have excellent backwards-compatibility. In particular, in the vast
|
||||
majority of cases, you can simply replace `pkgs.nix-serve` with
|
||||
`pkgs.nix-serve-ng` and make no other changes.
|
||||
|
||||
* Our executable shares the same name (`nix-serve`) as the original program
|
||||
|
||||
* We support most the original command-line options
|
||||
|
||||
The options that we're aware of that we do not currently support fall into
|
||||
two categories:
|
||||
|
||||
* Useless options which are only relevant to `starman`:
|
||||
|
||||
Upon request, we can still parse and ignore the following irrelevant
|
||||
options for extra backwards compatibility:
|
||||
|
||||
* `--workers`
|
||||
|
||||
We do not use worker subprocess like `starman` does. Instead we use
|
||||
`warp` which internally uses Haskell green threads to service a much
|
||||
larger number of requests with less overhead and lower footprint when
|
||||
idle.
|
||||
|
||||
* `--preload-app`
|
||||
|
||||
This optimization is meaningless for a compiled Haskell executable.
|
||||
|
||||
* `--disable-proctitle`
|
||||
|
||||
* Useful options
|
||||
|
||||
We might accept requests to support the following options, but we might
|
||||
explore other alternatives first before supporting them:
|
||||
|
||||
* `--max-requests`
|
||||
|
||||
`warp` itself is unlikely to be a bottleneck to servicing a large number
|
||||
of requests but there may still be Nix-specific or disk-specific
|
||||
reasons to cap the number of requests.
|
||||
|
||||
* `--disable-keepalive`
|
||||
|
||||
* `--keepalive-timeout`
|
||||
|
||||
* `--read-timeout`
|
||||
|
||||
* `--user`
|
||||
|
||||
* `--group`
|
||||
|
||||
* `--pid`
|
||||
|
||||
* `--error-log`
|
||||
|
||||
Because of this backwards-compatibility you only need to replace the old
|
||||
`nix-serve` executable with the `nix-serve` executable built by this package
|
||||
(which is what the included NixOS module does).
|
||||
|
||||
You don't need to define or use any new NixOS options. You continue to use
|
||||
the old `services.nix-serve` options hierarchy to configure the upgraded
|
||||
service.
|
||||
123
flake.nix
123
flake.nix
@ -10,60 +10,87 @@
|
||||
};
|
||||
|
||||
outputs = { nixpkgs, utils, ... }:
|
||||
utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
overlay = pkgsNew: pkgsOld: {
|
||||
haskellPackages = pkgsOld.haskellPackages.override (old: {
|
||||
overrides =
|
||||
pkgsNew.lib.fold pkgsNew.lib.composeExtensions (old.overrides or (_: _: { })) [
|
||||
(pkgsNew.haskell.lib.packageSourceOverrides {
|
||||
nix-serve-ng = ./.;
|
||||
})
|
||||
(haskellPackagesNew: haskellPackagesOld: {
|
||||
nix-serve-ng =
|
||||
pkgsNew.haskell.lib.overrideCabal
|
||||
haskellPackagesOld.nix-serve-ng
|
||||
(old: {
|
||||
executableSystemDepends = (old.executableSystemDepends or []) ++ [
|
||||
pkgsNew.boost.dev
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
});
|
||||
let
|
||||
overlay = pkgsNew: pkgsOld: {
|
||||
haskellPackages = pkgsOld.haskellPackages.override (old: {
|
||||
overrides =
|
||||
pkgsNew.lib.fold pkgsNew.lib.composeExtensions (old.overrides or (_: _: { })) [
|
||||
(pkgsNew.haskell.lib.packageSourceOverrides {
|
||||
nix-serve-ng = ./.;
|
||||
})
|
||||
(haskellPackagesNew: haskellPackagesOld: {
|
||||
nix-serve-ng =
|
||||
pkgsNew.haskell.lib.overrideCabal
|
||||
haskellPackagesOld.nix-serve-ng
|
||||
(old: {
|
||||
executableSystemDepends = (old.executableSystemDepends or []) ++ [
|
||||
pkgsNew.boost.dev
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
});
|
||||
|
||||
nix-serve-ng =
|
||||
pkgsNew.haskell.lib.justStaticExecutables
|
||||
pkgsNew.haskellPackages.nix-serve-ng;
|
||||
};
|
||||
nix-serve-ng =
|
||||
pkgsNew.haskell.lib.justStaticExecutables
|
||||
pkgsNew.haskellPackages.nix-serve-ng;
|
||||
};
|
||||
|
||||
pkgs = import nixpkgs {
|
||||
config = { };
|
||||
in
|
||||
utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
config = { };
|
||||
|
||||
overlays = [ overlay ];
|
||||
overlays = [ overlay ];
|
||||
|
||||
inherit system;
|
||||
};
|
||||
|
||||
inherit (pkgs) nix-serve-ng;
|
||||
|
||||
in
|
||||
rec {
|
||||
packages.default = nix-serve-ng;
|
||||
|
||||
defaultPackage = packages.default;
|
||||
|
||||
apps.default = {
|
||||
type = "app";
|
||||
|
||||
program = "${nix-serve-ng}/bin/nix-serve-ng";
|
||||
inherit system;
|
||||
};
|
||||
|
||||
defaultApp = apps.default;
|
||||
inherit (pkgs) nix-serve-ng;
|
||||
|
||||
devShells.default =
|
||||
(pkgs.haskell.lib.doBenchmark pkgs.haskellPackages.nix-serve-ng).env;
|
||||
in
|
||||
rec {
|
||||
packages.default = nix-serve-ng;
|
||||
|
||||
devShell = devShells.default;
|
||||
});
|
||||
defaultPackage = packages.default;
|
||||
|
||||
apps.default = {
|
||||
type = "app";
|
||||
|
||||
program = "${nix-serve-ng}/bin/nix-serve-ng";
|
||||
};
|
||||
|
||||
defaultApp = apps.default;
|
||||
|
||||
devShells.default =
|
||||
(pkgs.haskell.lib.doBenchmark pkgs.haskellPackages.nix-serve-ng).env;
|
||||
|
||||
devShell = devShells.default;
|
||||
}) // rec {
|
||||
overlays = {
|
||||
# The default overlay only adds the exports for
|
||||
# `pkgs.haskellPackages.nix-serve-ng` and `pkgs.nix-serve-ng`
|
||||
default = [ overlay ];
|
||||
|
||||
# This overlay additionally overrides `pkgs.nix-serve` to refer to
|
||||
# `pkgs.nix-serve-ng`
|
||||
override =
|
||||
let
|
||||
replace = pkgsNew: pkgsOld: {
|
||||
nix-serve = pkgsNew.nix-serve-ng;
|
||||
};
|
||||
|
||||
in
|
||||
[ overlay replace ];
|
||||
};
|
||||
|
||||
# The NixOS module is a thin wrapper around the overlay to replace
|
||||
# `nix-serve` with `nix-serve-ng`
|
||||
#
|
||||
# You can continue to use the old `services.nix-serve` NixOS options.
|
||||
nixosModules.default = {
|
||||
nixpkgs.overlays = overlays.default;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user