Skip to content

Customizing the environment shell hook

This guide uses the environment's shell hooks to set up a PostgreSQL development database.

Create a PostgreSQL environment

Say your project has a variable it expects to be set and you need to generate the value for development. This is a great use for the environment's shell hooks.

Let's set up a Flox environment using the postgresql_15 package in your environment:

$ flox init --name postgres-example

✨ Created environment postgres-example (aarch64-darwin)

Next:
  $ flox search <package>    <- Search for a package
  $ flox install <package>   <- Install a package into an environment
  $ flox activate            <- Enter the environment
$ flox install postgresql_15
✅ 'postgresql_15' installed to environment postgres-example at /Users/youruser

Customize the environment's shell hook

Let's add some properties PostgreSQL needs to run properly in this environment.

$ flox edit

Specifically, let's modify the hook section and create a script in the profile section with environment variables we need for development. It is important to remember that profile scripts are sourced and allow modification of your shell's environment. The hook script is executed in a subshell and therefore cannot modify your environment, like exporting variables or setting aliases.

manifest.toml
[install]
postgresql_15.pkg-path = "postgresql_15"

...

[profile]
common = """
    export PGPORT="${PGPORT:-5432}"

    export PGUSER=pg-example
    export PGPASS=pg-example
    export PGDATABASE=example-database
    export SESSION_SECRET="$USER-session-secret"

    # Postgres environment variables
    export PGDATA=$PWD/postgres_data
    export PGHOST=$PWD/postgres
    export LOG_PATH=$PGHOST/LOG
    export DATABASE_URL="postgresql:///$PGDATABASE?host=$PGHOST&port=$PGPORT"
...

We can also use the script to add initialization logic that runs conditionally.

manifest.toml
[hook]
on-activate = """
...
    mkdir -p $PGHOST
    if [ ! -d $PGDATA ]; then
      echo 'Initializing postgresql database...'
      initdb $PGDATA --username $PGUSER -A md5 --pwfile=<(echo $PGPASS) --auth=trust
      echo "listen_addresses='*'" >> $PGDATA/postgresql.conf
      echo "unix_socket_directories='$PGHOST'" >> $PGDATA/postgresql.conf
      echo "unix_socket_permissions=0700" >> $PGDATA/postgresql.conf
    fi
...
"""

Note

The hook.on-activate is always run in a bash sub-shell.

Save and exit your editor, you should see a confirmation after Flox validates the environment.

✅ Environment successfully updated.

Test the environment

You can now flox activate the environment to see the result of your hard work!

$ flox activate
✅ You are now using the environment postgres-example at /Users/youruser.
To stop using this environment, type 'exit'

Initializing postgresql database...
The files belonging to this database system will be owned by user "youruser".
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.

creating directory /Users/youruser/postgres_data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... America/New_York
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

Success. You can now start the database server using:

    pg_ctl -D /Users/youruser/postgres_data -l logfile start

Where to next?