arion
arion copied to clipboard
Improved flake support
I recently came across Arion and it's been fantastic. Thanks for making this package!
The only thing I've come across that's a bit awkward is the need to have arion-compose.nix and arion-pkgs.nix when using nixUnstable/flakes. Currently I have a dozen arion-{compose,pkgs}.nix scattered about that only contain a single line:
arion-pkgs.nix:
(builtins.getFlake (toString ./.)).legacyPackages.x86_64-linux
arion-compose.nix
(builtins.getFlake (toString ./.)).packages.x86_64-linux.arion-compose
Instead, it would be awesome if the following was possible:
arion --flake .#arion --flake /home/colinxs/fooflake#arion-foo up
This mimics the flake interface for nixos-rebuild
, home-manager
, and other tools in the Nix ecosystem.
Each flake.nix would look something like:
{
inputs.nixpkgs.url = "nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
let pkgs = nixpkgs.legacyPackages."${system}";
in
{
packages.arion = {
inherit pkgs;
config = { pkgs, ... }: {
config.services = {
webserver = {
service.useHostStore = true;
service.command = [
"sh"
"-c"
''
cd "$$WEB_ROOT"
${pkgs.python3}/bin/python -m http.server
''
];
service.ports = [
"8000:8000" # host:container
];
service.environment.WEB_ROOT =
"${pkgs.nix.doc}/share/doc/nix/manual";
};
};
};
};
});
}
Now everything is fully contained in the flake.nix without having to have arion-{compose,pkgs}.nix and you could do cool things like:
arion --flake github:colinxs/arion#arion-foo up
I tried to implement this myself and got about halfway there, but I know nothing about Haskell lol. If someone could help on the Haskell side I'd be happy to pitch in elsewhere.
Yes, this needs to be done. My thoughts so far:
We should use a new top-level flake attribute though, because arion projects aren't packages, and shouldn't even be derivations. There's a parallel with nixosConfigurations
, but it's better to omit the "lib.nixosSystem" equivalent, because I don't consider the compose file derivation to be a sufficiently stable interface. There's no real need for it to be a derivation in the first place and it only complicates cross-system
deployments.
Something like arionConfigurations.${system}.${projectName}
makes sense for local development, but for real-world deployments, the user's "choice" of system
should have no effect on what's deployed, so it should be a flat flake attr like arionConfigurations.${projectName}
.
These can't coexist in the same attr, so we can change the first one to localArionConfigurations.${system}.${projectName}
.
Arion modules can be imported at the project, service or NixOS level. The latter isn't arion-specific, so for reusable arion modules in flakes we only need arionProjectModules
and arionServiceModules
, analogous to nixosModules
, which we'll also reuse.
I did think about putting the derivation in a flake attribute anyway, but I just don't think it's constant enough. It'd break uid
and therefore cause issues with user volume mounts. I'd also like to implement setting config values via the command line, like an improved docker-compose --env
, which makes the arion projects even more like functions and less like enumerable derivations.
Just a tip for anyone who stumbles across this: since builtins.getFlake
copies the whole repository into the nix store, it is not an acceptable solution for me due to performance reasons. flake-compat
can be used to achieve the same result without the copying:
arion-compose.nix
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).defaultNix.packages.x86_64-linux.arion-compose
builtins.getFlake
copies the whole repository in to the nix store
It seems that https://github.com/NixOS/nix/pull/6530 may solve this.
My thoughts so far:
We might actually skip the arionConfigurations
attr and work with arionModules
instead. arionConfiguration
would only serve to finalize and instantiate configurations, which can be done equally well at the use site, such as the arion program, an Hercules CI effect, a deploy script in packages
or apps
, or a flake-parts
module. This avoids the issues in my previous comment by promoting interaction with the modules, which are composable.