Hello,
I’m trying for my first time to make a flake on one of my personnal project which is an Elixir discord bot.
The goal is to have a flake at the root of my project to be able to:
- Have a dev shell easy to deploy on my work machines.
- Have a derivation to use my app on some of my nixOs configuration machine and easily deploy my app as a service.
There is my work-in-progress flake:
{
description = "Flake for running a dev env and derivation of the TFT Tracker.";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
};
outputs = { self, nixpkgs, ... }:
let
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
in
{
devShells = forAllSystems (system:
let
pkgs = nixpkgsFor.${system};
in {
default = pkgs.mkShell {
buildInputs = [
pkgs.elixir
];
shellHook = ''
mix local.hex --force
mix local.rebar --force
mix deps.get
'';
};
}
);
packages = forAllSystems (system:
let
pkgs = import nixpkgs { inherit system; };
in {
default = pkgs.stdenv.mkDerivation {
pname = "tft-tracker-bot";
version = "1.0.0";
src = self;
nativeBuildInputs = [ pkgs.cacert ];
buildInputs = [
pkgs.erlang
pkgs.elixir
];
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
buildPhase = ''
export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
mix local.hex --force
mix local.rebar --force
mix deps.get
mix compile
'';
ELIXIR_ERL_OPTIONS = "+fnu";
installPhase = ''
mkdir -p $out/bin
cp -r . $out/bin/
'';
meta = with pkgs.lib; {
description = "TFT Tracker discord bot";
license = licenses.mit;
maintainers = [ maintainers.sailorsnow ];
};
};
}
);
nixosModules.tftTrackerBot = {
options.services.tft-tracker-bot = {
enable = nixpkgs.lib.mkOption {
type = nixpkgs.lib.types.bool;
default = false;
description = "Enable the TFT Tracker discord bot service";
};
redisHost = nixpkgs.lib.mkOption {
type = nixpkgs.lib.types.string;
default = "127.0.0.1";
description = "Address of the redis host server.";
};
redisPort = nixpkgs.lib.mkOption {
type = nixpkgs.lib.types.int;
default = 6379;
description = "Port on which the redis server run.";
};
riotApiKey = nixpkgs.lib.mkOption {
type = nixpkgs.lib.types.string;
default = "";
description = "RIOT API Key to request game data.";
};
discordToken = nixpkgs.lib.mkOption {
type = nixpkgs.lib.types.string;
default = "";
description = "Discord Bot Token to control your bot account.";
};
};
config = { config, pkgs, lib, ... }: {
services.redis.enable = true;
environment.systemPackages = [ self.packages.${pkgs.system} ];
systemd.services.tft-tracker-bot = {
description = "TFT Tracker discord bot";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
WorkingDirectory = "${self.packages.${pkgs.system}}/bin";
ExecStart = "${self.packages.${pkgs.system}}/bin/_build/prod/rel/tft_tracker/ebin/tft_tracker start";
Restart = "always";
User = "username";
Environment = "MIX_ENV=dev";
};
};
networking.firewall.allowedTCPPorts = [ config.services.tft-tracker-bot.port ];
};
};
};
}
The shell environment is working as expected, but trying to build the derivation always result to the following elixir error:
error: builder for '/nix/store/367vl56wb700dgf0kp6z8kaig7yfx2zv-tft-tracker-bot-1.0.0.drv' failed with exit code 1;
last 10 log lines:
> 09:53:19.371 [error] Task #PID<0.109.0> started from #PID<0.94.0> terminating
> ** (MatchError) no match of right hand side value: {:error, :enoent}
> (public_key 1.13.3.4) pubkey_os_cacerts.erl:38: :pubkey_os_cacerts.get/0
> (mix 1.17.3) lib/mix/utils.ex:664: Mix.Utils.read_httpc/1
> (mix 1.17.3) lib/mix/utils.ex:576: anonymous fn/2 in Mix.Utils.read_path/2
> (elixir 1.17.3) lib/task/supervised.ex:101: Task.Supervised.invoke_mfa/2
> (elixir 1.17.3) lib/task/supervised.ex:36: Task.Supervised.reply/4
> Function: #Function<5.19587555/0 in Mix.Utils.read_path/2>
> Args: []
>
For full logs, run 'nix log /nix/store/367vl56wb700dgf0kp6z8kaig7yfx2zv-tft-tracker-bot-1.0.0.drv'.
This seems highly related to cacert
, but I’ve kinda tried everything like export SSL env var required, importing cacert
packages into my derivation, in buildInputs
and nativeBuildInputs
…
There isn’t much documentation on working with Elixir and Nix, but a lot of examples seems to be using mix2nix
for getting the dependencies instead of the mix deps.get
command, is this a no choice for working with an Elixir project right now ? It seems to be a bit overkill as I just want something that work for the moment, but I don’t know…
Thanks for any help !