Calling `pg_ctl start` in `shellHook` hangs nix-shell but only via direnv

Context info:

OS: MacOS 13.6.8
Nix version: 2.23.3
Direnv version: 2.34.0 (installed via homebrew), hooked into oh-my-zsh via plugin
Shell: Zsh/oh-my-zsh

I’m attempting to use nix-shell and direnv on MacOS to create a lightweight, reproducible development environment for a Django web application.

The issue I’m having is that:
I want the shell environment to start Postgres when you enter the shell and (in the most ideal situation) have it automatically stop when the shell is exited.

Right now, my shell.nix (see first code snippet below) works great when calling nix-shell directly. But this doesn’t work with direnv / nix-direnv. With direnv, postgres is immediately stopped because the EXIT trap function is immediately triggered OR without the trap function the shell hangs indefintely and my shell prompt isn’t returned.

This is my shell.nix:

let
    nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-24.05";
    pkgs = import nixpkgs { config = {}; overlays = []; };
in
with pkgs;

stdenv.mkDerivation {
    name = "pokegotchi";
    buildInputs = [];
    nativeBuildInputs = [
        nodejs_20
        python312
        postgresql_16
        google-cloud-sdk
        google-cloud-sql-proxy
        firebase-tools
    ];
    
    postgresConf = pkgs.writeText "postgresql.conf" ''
        # Add custom settings
        log_timezone = 'UTC'
        logging_collector = on
        log_directory = 'pg_log'
        log_filename = 'pgsql_%a.log'
        log_truncate_on_rotation = on
        log_rotation_age = 1d
    '';

    # ENV variables
    PGDATA = "${toString ./.data/postgres}";

    shellHook = ''
        export PGHOST="$PGDATA"
        [ ! -d $PGDATA ] && pg_ctl initdb -o "-U postgres" && cat "$postgresConf" >> $PGDATA/postgresql.conf
        pg_ctl -o "-p 5555 -k $PGDATA" start
        function end {
            pg_ctl stop
        }
        trap end EXIT
    '';
}

Using nix-shell directly:
This works perfectly! But this environment isn’t cached because we’re not using nix-direnv.

➜  pokegotchi git:(main) ✗ nix-shell
waiting for server to start....2024-08-02 09:07:13.016 UTC [5623] LOG:  redirecting log output to logging collector process
2024-08-02 09:07:13.016 UTC [5623] HINT:  Future log output will appear in directory "pg_log".
 done
server started

[nix-shell:~/Documents/workspace/pokegotchi]$ psql -p 5555 -U postgres
psql (16.3)
Type "help" for help.

postgres=# q

[nix-shell:~/Documents/workspace/pokegotchi]$ exit
exit
waiting for server to shut down.... done
server stopped
➜  pokegotchi git:(main) ✗

Using direnv with the trap on EXIT function:
Postgres is immediately shut down.

➜  pokegotchi git:(main) ✗ cd ../pokegotchi
direnv: loading ~/Documents/workspace/pokegotchi/.envrc
direnv: loading https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc (sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w=)
direnv: using nix --pure
copying '«unknown»/' to the storedirenv: ([/opt/homebrew/bin/direnv export zsh]) is taking a while to execute. Use CTRL-C to give up.
direnv: nix-direnv: Renewed cache
waiting for server to start....2024-08-02 09:14:55.101 UTC [14121] LOG:  redirecting log output to logging collector process
2024-08-02 09:14:55.101 UTC [14121] HINT:  Future log output will appear in directory "pg_log".
 done
server started
waiting for server to shut down.... done
server stopped
➜  pokegotchi git:(main) ✗

Using direnv without the trap on EXIT function:
Having postgres running seems to hang the process and the shell prompt-doesn’t return. This is is not because pg_ctrl is not returning. E.g. if you put echo "Hello world" on the line below this is also executed.

➜  pokegotchi git:(main) ✗ cd ../pokegotchi
direnv: loading ~/Documents/workspace/pokegotchi/.envrc
direnv: loading https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc (sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w=)
direnv: using nix --pure
copying '«unknown»/' to the storedirenv: ([/opt/homebrew/bin/direnv export zsh]) is taking a while to execute. Use CTRL-C to give up.
direnv: nix-direnv: Renewed cache
waiting for server to start....2024-08-02 09:22:03.458 UTC [22216] LOG:  redirecting log output to logging collector process
2024-08-02 09:22:03.458 UTC [22216] HINT:  Future log output will appear in directory "pg_log".
 done
server started

My .envrc contents:

if ! has nix_direnv_version || ! nix_direnv_version 3.0.5; then
    source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc" "sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w="
fi

use nix --pure

This is less about packaging the Django application for deployment and more about corralling a bunch of development tools: postgres, nodejs/npm, python/pip, firebase CLI (for local emulators), google-cloud-sdk, google-cloud-sql-proxy.

You would otherwise have to install each of these tools at a system level separately, all via different means, all at different versions depending on when you first setup the tools and if you’ve updated them since.

I was originally inspired to try this from the following gist and another article:

https://gist.github.com/gusmacaulay/9dc5793439750912458f3c6a8945de7d

https://zeroes.dev/p/nix-recipe-for-postgresql/

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật