Installing postgresql-client

Hi all,

I’m wondering how to install the psql command on NixOS. To be clear: I’m only interested in the client, not the server.

I’ve looked at the derivation but couldn’t find any pointers.

Is there a way to create a derivation without building from source?

Thanks!

3 Likes

It seems that there is no split in the derivation.
You can just add the postgresql derivation to environment.systemPackages (or wherever you need it) and the psql command should be available.

1 Like
$ nix-shell -p postgresql --command 'psql --version'
psql (PostgreSQL) 9.6.10
1 Like

bump - did anybody solve this?

Does what @Mic92 mentions not work for you?

No as that postgresql package appears to install the server (alongside the client), which I am trying to avoid :slight_smile:

It pulls the binary into path, it doesn’t run it though or configure it.

If you are just annoyed by the binary being visible in your PATH a simple wrapper might solve that:

runCommandNoCC "psql" {} ''
  mkdir -p $out/bin
  ln -s ${postgresql}/bin/psql $out/bin/psql
''

I’m sorry, but I completely fail to see the issue here. Is your concern the fact that the server binaries are present in the path?

When I install postgresql into environment.systemPackages it also starts a postgres server daemon that I don’t want installer nor running since I use containers.

I’d rather just install the postgres-client so that I can connect to my containers etc.

I was hoping that since a couple of years had passed that potentially there was a solution already :smiley:

Nobbz’s looks like the best but was hoping for something as simple as just adding a package like postgresql-client

actually forget that i don’t think it installs it as a daemon!

Correct. Whenever you install anything via environment.systemPackages there is no possible way for a daemon to start. This will never happen and is useful for you to know. Often times people new to NixOS wonder why a service isn’t running after they installed it via environment.systemPackages, not realizing they need to “install” it via services.FOO.enable = true;.

1 Like

The only downside to not having the client and server split is the space used but as postgresql_14 currently takes up around 25mb, that’s really not an issue at all which is why nobody has put in the effort to split the 2.

1 Like

Apologies for the necropoast … but how about the use case where I’m using Nix to build a Docker image and I want to include psql (client) but not the postgres server?

2 Likes

but how about the use case where I’m using Nix to build a Docker image and I want to include psql (client) but not the postgres server?

I’d like to do the same thing. Currently the runtime closure postgresql package is over 300MB, while I can find an pure psql image on docker hub under 10MB

3 Likes

[…] how about the use case where I’m using Nix to build a Docker image and I want to include psql (client) but not the postgres server?

[…] I can find an pure psql image on docker hub under 10MB

Here’s one: https://hub.docker.com/r/jbergknoff/postgresql-client

We can get that image directly in Nix using dockerTools.pullImage:

pkgs.dockerTools.pullImage {
  # variables to update base image found using:
  #   xdg-open https://hub.docker.com/r/jbergknoff/postgresql-client/tags
  #   nix-shell -p nix-prefetch-docker
  #   nix-prefetch-docker --quiet --image-name jbergknoff/postgresql-client --image-tag latest --image-digest sha256:45e175ebb700cfd46e23a610477c3576550055ef40c394e663623946a5eced39
  imageName = "jbergknoff/postgresql-client";
  imageDigest = "sha256:45e175ebb700cfd46e23a610477c3576550055ef40c394e663623946a5eced39";
  finalImageName = "postgresql-client";
  finalImageTag = "latest";
  sha256 = "0vxmbsi725yxa1i8ysl3scbsnf6shqvhf104i3phwnkkqp6sfk68";
  os = "linux";
  arch = "amd64";
};

And it’s extensible!! You can use dockerTools.streamLayeredImage (or some equivalent) to layer images on top of each-other using the baseImage argument.

So in this case:

{
  pkgs ? import <nixpkgs> {},
  name ? "psql-client",
  version ? "0.0.0",
  # TODO supply some derivation that uses `psql` in ./script.nix
  server ? pkgs.callPackage ./script.nix { inherit pkgs; }
}: let
  baseImage = pkgs.dockerTools.pullImage {
    # variables to update base image found using:
    #   xdg-open https://hub.docker.com/r/jbergknoff/postgresql-client/tags
    #   nix-shell -p nix-prefetch-docker
    #   nix-prefetch-docker --quiet --image-name jbergknoff/postgresql-client --image-tag latest --image-digest sha256:45e175ebb700cfd46e23a610477c3576550055ef40c394e663623946a5eced39
    imageName = "jbergknoff/postgresql-client";
    imageDigest = "sha256:45e175ebb700cfd46e23a610477c3576550055ef40c394e663623946a5eced39";
    finalImageName = "postgresql-client";
    finalImageTag = "latest";
    sha256 = "0vxmbsi725yxa1i8ysl3scbsnf6shqvhf104i3phwnkkqp6sfk68";
    os = "linux";
    arch = "amd64";
  };
in pkgs.dockerTools.streamLayeredImage {
  name = "${name}-script-image";
  tag = version;
  inherit tag;
  fromImage = baseImage;
  contents = [ script ];
  config = {
    # your script can call psql
    Cmd = [ "${pkgs.lib.getExe script}" ];
    ExposedPorts = {
      "5432/tcp" = {};
    };
  };
}

See documentation at pkgs.dockerTools | nixpkgs

See more examples at nixpkgs/pkgs/build-support/docker/examples.nix at 21e9e52183fd52452c26a1d7957b0299a37fa83a · NixOS/nixpkgs · GitHub

Note that it may be better to make the Docker image yourself, as that above image with 10M downloads (at the time of writing) was last updated 4 years ago. Here is a Dockerfile example of how to achieve it on StackOverflow: postgresql - Postgres lean Docker image containing only "psql" client - Stack Overflow