Skip Navigation

New to NixOS and have a question on Nix Shell

I just switched one of my systems over to NixOS from Arch and so far it seems interesting. One question I had is regarding the nix-shell. So I get the basic concept of it and that it allows creating a shell that has packages installed with that shell making ideal for dev environments. I've even seen talks where the suggest nix-shells over docker/podman, my question is how is persistent data (like databases) handled?

13 comments
  • Nix shell basically just downloads the software (if it's not already downloaded) and then modifies your PATH to include the new software.

    Persistent data stay persistent.

    Nix shell has one use case common with docker (local development), but other than that the solutions are not similar at all.

  • Services like databases that manage runtime information usually store that information in /var or your home directory as usual.

  • In general Nix doesn't manage persistent data. It will be stored in whatever location the tool writes it to.

    nix-shell is a very simple program. Basically it downloads/builds the package you have configured, then sets up environment variables like PATH to include that package. It would be similar to downloading a pre-built tarball run running ./foo inside of that.

    For most built-in modules this will be /var/lib/foo for a service foo. If you run nix-shell the service will write data wherever it would normally write data on any other distribution.

    • Okay, that's good to know. I just wanted to make sure that if I had something like MariaDB or Postgres get installed with nix-shell that I wouldn't lose everything thus having to set everything back up next time I start the shell again.

      • No, you won't lose anything. However do be aware that unless you specifically configure different data directories using the same DBMS in multiple projects will use the same underlying data files.

        Typically this won't be a problem, and you can just create different logical databases if necessary.

  • Okay, hopefully someone here can point out where I am going wrong with setting up my dev shell the way I want. I am currently using direnv and nix-direnv to manage the dev shell, and I found this blog post which shows a way to start and stop MySQL/Mariadb but I am having some weird issues with it.

    Currently my flake looks like this:

     
        
    {
      description = "A basic flake with a shell";
      inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
      inputs.flake-utils.url = "github:numtide/flake-utils";
    
      outputs = { nixpkgs, flake-utils, ... }@inputs:
        flake-utils.lib.eachDefaultSystem (system:
          let
            pkgs = nixpkgs.legacyPackages.${system};
          in
          {
            devShells.default = pkgs.mkShell {
              packages = with pkgs; [
                bashInteractive
                php
              ];
    
              buildInputs = [ pkgs.mariadb ];
    
              shellHook = ''
              export MYSQL_BASEDIR=${pkgs.mariadb}
              export MYSQL_HOME=$PWD/.direnv/mysql
              export MYSQL_DATADIR=$MYSQL_HOME/data
              export MYSQL_UNIX_PORT=$MYSQL_HOME/mysql.sock
              export MYSQL_PID_FILE=$MYSQL_HOME/mysql.pid
              alias mysql='mysql -u root'
    
              if [[ ! -d $MYSQL_HOME ]]; then
                mariadb-install-db --auth-root-authentication-method=normal \
                  --datadir="$MYSQL_DATADIR" --basedir="$MYSQL_BASEDIR" \
                  --pid-file="$MYSQL_PID_FILE"
              fi
    
              mariadbd --datadir=$MYSQL_DATADIR --pid-file=$MYSQL_PID_FILE \
                --socket=$MYSQL_UNIX_PORT --tmpdir='/tmp' 2>/dev/null &
              MYSQL_PID=$!
              '';
            };
          });
    }
    
      

    When I run it like this mariadbd starts just fine, but doesn't get backgrounded dispite the & making that shell session useless which is not what I want as I have to spawn a second shell just to do anything.

    Even weirder is when I add the finish() function and the call to trap like in the blog post then mariadbd doesn't start (or starts and immedently gets killed).

13 comments