jfischoff / tmp-postgres

Create temporary postgres instances
BSD 3-Clause "New" or "Revised" License
53 stars 17 forks source link

Failes with `initdb: error: could not create directory \"/homeless-shelter\": Permission denied`? #280

Open TheOddler opened 1 year ago

TheOddler commented 1 year ago

I'm trying to run my tests as part of my nix flake check, but when I do this tests that use tmp-postgres fail with

InitDbFailed {startErrorStdOut = "The files belonging to this database system will be owned by user \"nixbld\".This user must also own the server process.The database cluster will be initialized with locale \"en_US.UTF-8\".The default database encoding has accordingly been set to \"UTF8\".The default text search configuration will be set to \"english\".Data page checksums are disabled.", startErrorStdErr = "initdb: error: could not create directory \"/homeless-shelter\": Permission denied", startErrorExitCode = ExitFailure 1}

I tried manually setting the cacheTemporaryDirectory and temporaryDirectory to whatever the TMP environment variable is set to (seems to be /build) but that results in the same error, still complaining about homeless-shelter.

What am I missing? Is there a way to make this work inside nix?

(For more code, my project is available at: https://github.com/TheOddler/elmder/tree/pablo/trying-to-fix-backend-nix-build)

jfischoff commented 1 year ago

Fascinating. I've never seen that "homeless-shelter" error before. What version of postgres are you using?

TheOddler commented 1 year ago

At the moment it seems like version 14.8:

❯ postgres --version
postgres (PostgreSQL) 14.8

If you want to investigate further (I'm doing as well when I have time), in the project above, on the linked branch, you should be able to just do nix flake check and it should show you the error.

TheOddler commented 1 year ago

It looks like I was able to fix it by setting the HOME env variable before my tests. Essentially I just run the following before running any test that uses a temp db and everything seems to work:

tmpFolder <- liftIO $  Env.getEnv "TMP"
liftIO $ Env.setEnv "HOME" tmpFolder

I also tried setting this in my flake.nix itself, but couldn't figure out how to set that properly there. So for now my Haskell code does that fix :sweat_smile:

Edit: So looks like it indeed works, in ci as well, so the above branch is no longer broken. If you still want to see it yourself, use this commit for example: 92583670739f58756668b6353b49d9c39170e181

TheOddler commented 1 year ago

I found the following: https://nixos.org/guides/nix-pills/working-derivation.html#id1388

So nix is forcing us not to depend on the home folder. But looks like somewhere postgres still does, apparently when using initdb.

TheOddler commented 1 year ago

I did some more investigation, and found a cleaner fix.

So as I found in my previous comment it looks like nix disallows the use of the home folder. I looked deeper into the tmp-postgres code, and found that the defaultCacheConfig sets cacheDirectoryType to Permanent "~/.tmp-postgres", so that's in the home folder.

So to fix this, I use the following in my nix build:

defaultCacheConfig {cacheDirectoryType = Permanent "/tmp/.tmp-postgres"}

I think the /tmp folder is safe to use? It seems to work in nix at least. Not sure if it would make sense to make this the default for tmp-postgres as well?

noteed commented 6 months ago

The homeless-shelter is the $HOME directory as setup by the Nix build, and doesn't exist. Within a Nix build, you can set it to something else, e.g. with something along the line of:

  testOverrides = self: superh: rec {
    mkDerivation = args: superh.mkDerivation (
      if args.pname == "your-package-name"
      then args // {
        preBuild = ''
          export HOME=$TEMPDIR
          cp -r ${translations}/share .
        '';
      }
      else args);
  };

You can see how it is done in Nixpkgs here: https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/configuration-common.nix#L1204-L1214