-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proof Of Concept Repl Bots via nix-shell #32
base: main
Are you sure you want to change the base?
Conversation
nodeBot = replBot "node: " | ||
|
||
nodeConfig :: ProcessConfig Handle Handle () | ||
nodeConfig = replConfig "nix-shell -p nodejs --run 'node -i' 2>&1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i need to get this command running in a docker container.
ghci = mkImage pkgs.ghc [ "ghci" ]; | ||
}; | ||
in | ||
pkgs.runCommand "repls" { } (mkPath images) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JonathanLorimer for REPL bots I am building docker images with nix. Do you have any thoughts on how we can design this derivation to be more scalable for adding more languages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly think these could all just be systemd jobs inside nix shells though...
systemd.services.python-repl = {
description = "Python repl";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "notify";
ExecStart = "nix-shell -p python3 --command "python -iq"";
};
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could abstract the python specific stuff in a nix module and then your nixos configuration would just do this:
sercives.language-repls = [
{name = "python"; package = pkgs.python3; binName = "python3"; opts = "-iq";}
...
];
you wouldn't even need the nix shell bit above if you did direct interpolation:
ExecStart = "${package}/bin/${binName} ${opts}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JonathanLorimer I don't think that's a good idea. The point of containerization is to isolate the server from untrusted code execution, so that if someone runs rm -rf /
as a joke it doesn't actually nuke the entire server. You can increase the isolation of the server from these untrusted REPLs by using Linux namespacing stuff, but the more of that you do, the more of existing containerization solutions you reinvent.
deploy-bot = | ||
pkgs.writeScript "deploy-bot" | ||
'' | ||
#!${pkgs.bash}/bin/bash | ||
set -euxo pipefail | ||
|
||
image=$(${pkgs.docker}/bin/docker load -i ${bot-image} | sed -n 's#^Loaded image: \([a-zA-Z0-9\.\/\-\:]*\)#\1#p') | ||
${pkgs.docker}/bin/docker push $image | ||
|
||
for x in ${repls}/*; do | ||
image=$(${pkgs.docker}/bin/docker load -i $x | sed -n 's#^Loaded image: \([a-zA-Z0-9\.\/\-\:]*\)#\1#p') | ||
${pkgs.docker}/bin/docker push $image | ||
done | ||
''; | ||
|
||
deploy-repls = | ||
pkgs.writeScript "deploy-bot" | ||
'' | ||
#!${pkgs.bash}/bin/bash | ||
set -euxo pipefail | ||
for x in ${repls}/*; do | ||
${pkgs.docker}/bin/docker load -i $x | ||
done | ||
''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JonathanLorimer We are building these scripts for building deploy scripts for the bot and the repl images. We tried to make these apps rather then packages with pkgs.runCommand
but werent able to run docker load
. Do you know of any tricks to perform side effects in a flake output or is that off the table?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we need to get these images onto the server and loaded into docker. I don't want to put them on the github docker hub because they are going to take up too much space as we add more images. Can we modify our github deploy action to sync them onto the server directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the scripts, I would suggest moving them to a separate file parameterized by their dependencies.
I would also suggest using writeShellApplication
https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix#L274-L305 it will set a bunch of sane defaults as well as the shebang, and you can specify sed
as a runtime input. It will also run shellcheck in the check phase.
images = | ||
{ | ||
python = mkImage pkgs.python3 [ "python" "-iq" ]; | ||
node = mkImage pkgs.nodejs [ "node" "-i" ]; | ||
ghci = mkImage pkgs.ghc [ "ghci" ]; | ||
mitScheme = mkImage pkgs.mitscheme [ "mit-scheme" ]; | ||
sbcl = mkImage pkgs.sbcl [ "sbcl" ]; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
images = | |
{ | |
python = mkImage pkgs.python3 [ "python" "-iq" ]; | |
node = mkImage pkgs.nodejs [ "node" "-i" ]; | |
ghci = mkImage pkgs.ghc [ "ghci" ]; | |
mitScheme = mkImage pkgs.mitscheme [ "mit-scheme" ]; | |
sbcl = mkImage pkgs.sbcl [ "sbcl" ]; | |
}; | |
images = | |
foldl' (acc {name, package, cmd}: acc // { "${name}" = mkImage package cmd }) {} supportedLanguages; | |
supportedLanguages = | |
[ { name = "python"; package = pkgs.python3; cmd = [ "python" "-iq" ]} | |
{ name = "node"; package = pkgs.nodejs; cmd = [ "node" "-i]} | |
{ name = "ghci"; package = pgks.ghc; cmd = [ "ghci"]} | |
{ name = "mitScheme"; package = pkgs.mitscheme; cmd = [ "mit-scheme ] | |
{ name = "sbcl"; package = pkgs.sbcl; cmd = [ "sbcl"]} | |
]; |
By more scalable do you mean something like this (like easier to add, although I am not sure this is an improvement). Or do you mean that a lot of docker containers is expensive.
ghci = mkImage pkgs.ghc [ "ghci" ]; | ||
}; | ||
in | ||
pkgs.runCommand "repls" { } (mkPath images) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly think these could all just be systemd jobs inside nix shells though...
systemd.services.python-repl = {
description = "Python repl";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "notify";
ExecStart = "nix-shell -p python3 --command "python -iq"";
};
};
ghci = mkImage pkgs.ghc [ "ghci" ]; | ||
}; | ||
in | ||
pkgs.runCommand "repls" { } (mkPath images) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could abstract the python specific stuff in a nix module and then your nixos configuration would just do this:
sercives.language-repls = [
{name = "python"; package = pkgs.python3; binName = "python3"; opts = "-iq";}
...
];
you wouldn't even need the nix shell bit above if you did direct interpolation:
ExecStart = "${package}/bin/${binName} ${opts}"
deploy-bot = | ||
pkgs.writeScript "deploy-bot" | ||
'' | ||
#!${pkgs.bash}/bin/bash | ||
set -euxo pipefail | ||
|
||
image=$(${pkgs.docker}/bin/docker load -i ${bot-image} | sed -n 's#^Loaded image: \([a-zA-Z0-9\.\/\-\:]*\)#\1#p') | ||
${pkgs.docker}/bin/docker push $image | ||
|
||
for x in ${repls}/*; do | ||
image=$(${pkgs.docker}/bin/docker load -i $x | sed -n 's#^Loaded image: \([a-zA-Z0-9\.\/\-\:]*\)#\1#p') | ||
${pkgs.docker}/bin/docker push $image | ||
done | ||
''; | ||
|
||
deploy-repls = | ||
pkgs.writeScript "deploy-bot" | ||
'' | ||
#!${pkgs.bash}/bin/bash | ||
set -euxo pipefail | ||
for x in ${repls}/*; do | ||
${pkgs.docker}/bin/docker load -i $x | ||
done | ||
''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the scripts, I would suggest moving them to a separate file parameterized by their dependencies.
I would also suggest using writeShellApplication
https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix#L274-L305 it will set a bunch of sane defaults as well as the shebang, and you can specify sed
as a runtime input. It will also run shellcheck in the check phase.
Adds python and nodejs repl bots as a proof of concept.