Point nix module to nixpkgs

Points the nix bundle to nixpkgs.
This removes any redundancies, all nix code
is now in nixpkgs.
This commit is contained in:
Jappie Klooster 2022-12-14 09:37:40 -04:00
parent 662cabbd81
commit b4f42ad5c2
4 changed files with 2 additions and 260 deletions

View File

@ -174,54 +174,10 @@ Finally, start the job for the first time:
### NixOS
Add a nix file `keter.nix` that fetches this repository and imports
the module file:
```nix
let
owner = "snoyberg";
repo = "keter";
rev = "be4e3132e988519dacd0f9b40a47e23d33865b76";
src = builtins.fetchTarball {
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz";
};
in
import "${src}/nix/module.nix"
```
Make sure to update rev to the latest commit!
Now you can import this as an ordinary module
in your `configuration.nix`:
```nix
imports = [
./keter.nix
];
```
Keter is integrated within nixos:
Now you can configure keter in the same `configuration.nix`:
```nix
services.keter = {
enable = true;
keterPackage = pkgs.keter;
bundle = {
domain = "example.com";
secretScript = env.secretScript;
publicScript = env.publicScript;
package = myWebAppDerivation;
executable = "exe";
};
};
```
secretScript is used to load environment varialbes, for example:
```
MY_AWS_KEY=$(cat /run/keys/AWS_ACCESS_KEY_ID)
```
Public script does the same but emits the loading to the logs.
which isn't good for secrets.
For the full option list available see `nix/module.nix`.
This should load most webapps but PR's for improved support are welcome.
Note that the default expects keter to be run behind nginx.
https://search.nixos.org/options?channel=22.11&show=services.keter.keterPackage&from=0&size=50&sort=relevance&type=packages&query=keter
## Bundles

View File

@ -1,35 +0,0 @@
/* This makes a keter bundle as described on the github page:
https://github.com/snoyberg/keter#bundling-your-app-for-keter
Note that we're not actually putting in the app into the bundle,
we already can use the nix store for copying, so we just
symlink to the app.
*/
{ domain,
exePkg,
executable, gnutar, writeTextFile, lib, stdenv, ... }:
let
str.stanzas = [{
# we just use nix as an absolute path so we're not bundling any binaries
type = "webapp";
exec = "${exePkg}/bin/${executable}";
host = "${domain}";
}];
configFile = writeTextFile {
name = "keter.yml";
text = (lib.generators.toYAML { } str);
};
in stdenv.mkDerivation {
name = lib.strings.sanitizeDerivationName "keter-bundle";
buildCommand = ''
mkdir -p config
cp ${configFile} config/keter.yaml
echo 'create a gzipped tarball'
mkdir -p $out
tar -zcvf $out/bundle.tar.gz.keter ./.
'';
buildInputs = [ gnutar ];
}

View File

@ -1,74 +0,0 @@
{ globalketerConfig, keterRoot, writeShellScriptBin,
writeTextFile, lib, bundleCfg, callPackage, coreutils
, keter, ...
}:
let
incoming = "${keterRoot}/incoming";
globalKeterConfigFile = writeTextFile {
name = "keter-config.yml";
text = (lib.generators.toYAML { } globalketerConfig);
};
# If things are expected to change often, put it in the bundle!
bundle = callPackage ./bundle.nix
(bundleCfg // { exePkg = executable; });
executable = writeShellScriptBin "${bundleCfg.executable}" ''
#!/usr/bin/env bash
export PATH=$PATH:${lib.makeBinPath [ coreutils ]}
set -e
${bundleCfg.secretScript}
set -xe
${bundleCfg.publicScript}
exec ${bundleCfg.package}/bin/${bundleCfg.executable}
'';
in {
# This is keter, which loads our app on deploy, and checks if it is healthy
# be very careful putting anything in here that changes,
# any change to the systemd unit can cause brief windows of downtime
# because nixos has to restart the unit.
keter = {
description = "keter app loader";
script = ''
set -xe
mkdir -p ${incoming}
{ tail -F /opt/keter/log/keter/current.log -n 0 & ${keter}/bin/keter ${globalKeterConfigFile}; }
'';
wantedBy = [ "multi-user.target" "nginx.service" ];
serviceConfig = {
Restart="always";
RestartSec="10s";
};
after = [
"network.target"
"local-fs.target"
"postgresql.service"
"redis.service"
];
};
# On deploy this will load our app, by moving it into the incoming dir
# If the bundle content changes, this will run again.
# Because the bundle content contains the nix path to the exectuable,
# we inherit nix based cache busting.
load-keter-bundle = {
description = "load keter bundle into incoming folder";
after = [ "keter.service" ];
wantedBy = [ "multi-user.target" ];
# we can't override keter bundles because it'll stop the previous app
# https://github.com/snoyberg/keter#deploying
script = ''
set -xe
cp ${bundle}/bundle.tar.gz.keter ${incoming}/supercede.keter
'';
path = [
executable
]; # this is a hack to get the executable copied over to the machine.
};
}

View File

@ -1,105 +0,0 @@
# https://nixos.wiki/wiki/Module
{ config, pkgs, bash, lib, ... }:
let
cfg = config.services.keter;
keterConfig = pkgs.callPackage ./config.nix {
globalketerConfig = cfg.globalKeterConfig // { root = cfg.keterRoot; };
keterRoot = cfg.keterRoot;
bundleCfg = cfg.bundle;
keter = cfg.keterPackage;
};
in
{
options.services.keter = {
enable = lib.mkEnableOption "keter service";
keterRoot = lib.mkOption {
type = lib.types.str;
default = "/opt/keter";
description = ''Mutable state folder for keter. In here the bundles get extracted,
logs get written and the app's work folder is set to'';
};
keterPackage = lib.mkOption {
type = lib.types.package;
default = null;
description = ''set the keter package to be used, usually pkgs.haskellPackages.keter'';
};
globalKeterConfig = lib.mkOption {
type = lib.types.attrs;
default = {
ip-from-header = true;
listeners = [{
host = "*4";
port = 81;
}];
};
description = ''root is required to function in nixos .
port 81 is set to default to allow nginx to reverse proxy into keter,
so that nginx can do ssl management.
You want that ip-from-header in the nginx setup case
so it's not set to 127.0.0.1.
Keep in mind root is overwritten by keterRoot.
which is required for the nix derivation.
'';
};
bundle = {
executable = lib.mkOption {
type = lib.types.str;
default = "bash";
description = ''The executable to be run in the bin folder of the package'';
};
domain = lib.mkOption {
type = lib.types.str;
default = "example.com";
description = ''The domain keter will bind to'';
};
# these won't work with standard nix options because they have
# to be put in a tarball, so we use a runtime script to load settings.
publicScript = lib.mkOption {
type = lib.types.str;
default = "";
description = ''
Allows loading of public environment variables,
these are emitted to the log so it shouldn't contain secrets.
For example:
```
ADMIN_EMAIL=hi@example.com
```
'';
};
secretScript = lib.mkOption {
type = lib.types.str;
default = "";
description = ''
Allows loading of private environment variables,
for example:
```
MY_AWS_KEY=$(cat /run/keys/AWS_ACCESS_KEY_ID)
```
'';
};
# This indirection is required to ensure the nix path
# gets copied over to the target machine in remote deployments.
# Furthermore, it's important that we use exec to
# run the binary otherwise we get process leakage.
package = lib.mkOption {
type = lib.types.package;
default = bash;
description = ''The package which will be copied over to the nixos configuration,
from which executable name runs.
'';
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.keter = keterConfig.keter;
systemd.services.keter-load-bundle = keterConfig.load-keter-bundle;
};
}