Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to install PostGIS within a Nix environment

Tags:

nix

I have the following shell.nix (to setup my development environment, no NixOS):

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "my-shiny-project";
    buildInputs = [
        jq
        nodejs-6_x
        #postgis {version="2.3.1";}
        #postgis ("2.3.1")
        #postgis "2.3.1"
        postgresql96
        zsh
    ];
    shellHook = ''
        export SHELL=zsh
        export PATH="$PWD/node_modules/.bin/:$PATH"
    '';
}

PostGIS expects a version parameter. I'm not sure how to pass that parameter along. Whether I use postgis{version="2.3.1";}, postgis("2.3.1") or postgis "2.3.1", I receive the following error:

error: cannot coerce a set to a string, at /nix/store/0rj9y7gvzzahp93cvdmrwc2v2aznh61p-nixpkgs-18.03pre118061.69607d7662/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:98:11

In the Nameless and single parameter section of functions and imports Nix pill, I see the syntax for calling a function is simply NAME PARAM.

What do I have to add to buildInputs to get PostGIS installed for that specific version of PostgreSQL?

like image 934
François Beausoleil Avatar asked Oct 18 '17 13:10

François Beausoleil


2 Answers

Recently it became possible to use postgresql.withPackages:

with import <nixpkgs> {};

mkShell {
    buildInputs = [
        jq
        nodejs
        ( postgresql11.withPackages (p: [ p.postgis ]) )
        zsh
    ];
    shellHook = ''
        export SHELL=${zsh}/bin/zsh
        export PATH="${builtins.toPath ./.}/node_modules/.bin/:$PATH"
        export PGDATA=${builtins.toPath ./.}/pg
        export PGHOST=$PGDATA

        pg_ctl initdb
        pg_ctl -o "-p 5555 -k $PGDATA" start
        psql -p 5555 postgres -c 'create extension postgis' || true
    '';
}
like image 74
danbst Avatar answered Sep 21 '22 17:09

danbst


This is truly a stab in the dark given that postgresql is designed to be used as a service, but it's only available to you as a package since you're not on NixOS. But try this:

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "my-shiny-project";
    buildInputs = [
        jq
        nodejs-6_x
        postgis.v_2_3_1
        postgresql96
        zsh
    ];
    shellHook = ''
        export SHELL=zsh
        export PATH="$PWD/node_modules/.bin/:$PATH"
    '';
}

Explanation

The postgis package doesn't produce a derivation, so it's output cannot be used directly. Instead it produces a set with attributes for two versions: 2.3.1 and 2.4.0.

Caveat

The above may not work at all. The issue is that postgis is normally provided to postgresql via the extraPlugins attribute like so:

services.postgresql.extraPlugins = [ (pkgs.postgis.override { postgresql = pkgs.postgresql95; }).v_2_3_1 ];

This causes postgresql to be installed in such a way that it can see the postgis library. However, this is done at the service level, not the package leve, and services are only available to NixOS. So if the above doesn't work, try this hunk of code:

with import <nixpkgs> {};
let
   pg = postgresql96;

   postgresqlWithPlugins =
     buildEnv {
      name = "postgresql-and-plugins-${(builtins.parseDrvName pg.name).version}";
      paths = [ pg pg.lib (postgis.override { postgresql = pg; }).v_2_3_1) ];
      buildInputs = [ makeWrapper ];
      postBuild =
        ''
          mkdir -p $out/bin
          rm $out/bin/{pg_config,postgres,pg_ctl}
          cp --target-directory=$out/bin ${pg}/bin/{postgres,pg_config,pg_ctl}
          wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
        '';
};
in
stdenv.mkDerivation {
    name = "my-shiny-project";
    buildInputs = [
        jq
        nodejs-6_x
        postgresqlWithPlugins
        zsh
    ];
    shellHook = ''
        export SHELL=zsh
        export PATH="$PWD/node_modules/.bin/:$PATH"
    '';
}

Basically, this is an untested port of the extraPlugins implementation.

like image 44
Emmanuel Rosa Avatar answered Sep 22 '22 17:09

Emmanuel Rosa