pg_embedded_setup_unpriv
pg_embedded_setup_unpriv prepares a postgresql_embedded data directory
while you are running as root, dropping privileges to nobody only for the
filesystem mutations that must occur as the target user. The binary is useful
when you need to initialize PostgreSQL assets inside build pipelines or CI
images where direct access to the nobody account is required.
Prerequisites
- Linux host with
sudoor directrootaccess. - Rust toolchain (matching
rust-toolchain.toml) andcargoinstalled. - Ability to download crates from crates.io.
Configuration model
Configuration is discovered via environment variables, files, and CLI arguments
thanks to ortho_config. All fields are optional; when omitted the defaults
from postgresql_embedded::Settings::default() are used.
PG_VERSION_REQ– SemVer requirement such as^17or=16.4.0.PG_PORT– TCP port for the server to listen on. Defaults to5432.PG_SUPERUSER– Administrator account name.PG_PASSWORD– Password for the superuser.PG_DATA_DIR– Directory where PostgreSQL data files should live.PG_RUNTIME_DIR– Directory for the downloaded distribution and binaries.PG_LOCALE– Locale passed toinitdb.PG_ENCODING– Cluster encoding (for exampleUTF8).PG_SHUTDOWN_TIMEOUT_SECS– Optional number of seconds to wait for PostgreSQL to stop during teardown. Defaults to15seconds and accepts values between1and600.
You may also provide these values through a configuration file named pg.toml,
pg.yaml, or pg.json5 (depending on enabled features) located in any path
recognised by ortho_config, or through CLI flags if you wrap the binary
inside your own launcher.
Running the setup helper
-
Ensure the desired directories exist or can be created. They will be owned by
nobodyafter the tool completes. -
Export any configuration overrides, for example:
-
Execute the binary as
rootso it can chown the directories before dropping privileges:The
-Eflag preserves any exportedPG_*variables for the run. -
On success the command exits with status
0. The PostgreSQL payload is downloaded intoPG_RUNTIME_DIR, initialized intoPG_DATA_DIR, and both paths are owned bynobody. Any failure emits a structured error viacolor-eyreto standard error and the process exits with status1.
Troubleshooting
- Must be run as root – The helper aborts when the effective UID is not
0. Re-run the command usingsudoor inside arootshell. - Directory permission errors – Confirm the paths specified in
PG_DATA_DIRandPG_RUNTIME_DIRare writable byrootso ownership can be transferred tonobody. - PostgreSQL download issues – Ensure outbound network access is available
to fetch the PostgreSQL distribution used by
postgresql_embedded. - Invalid
TimeZoneparameter – The embedded cluster requires access to the system timezone database. Install your distribution'stzdata(or equivalent) package inside the container or VM running the tool.
Integration testing with rstest
The crate ships an rstest fixture, test_support::test_cluster, so test
modules can request a ready TestCluster without invoking constructors
manually. Bring the fixture into scope and declare a parameter named
test_cluster to opt into automatic setup and teardown.
use ;
use rstest;
Because the fixture handles environment preparation, tests stay declarative and
can focus on behaviours instead of bootstrap plumbing. When a bootstrap failure
occurs the fixture panics with a SKIP-TEST-CLUSTER prefix, so higher-level
behaviour tests can convert known transient errors into soft skips.
Fast test isolation with template databases
For test suites where per-test cluster bootstrap is too slow, use
shared_test_cluster to share a single cluster across all tests and clone
template databases for isolation:
use ;
use rstest;
Key features:
shared_cluster()– process-global cluster initialized once per binarycreate_database_from_template()– clone databases via PostgreSQL'sTEMPLATEclause (filesystem copy, completes in milliseconds)ensure_template_exists()– concurrency-safe template creation with per-template lockinghash_directory()– generate content-based template names that auto-invalidate when migrations change
See docs/users-guide.md for complete examples and
performance guidance.
Behaviour-driven diagnostics
Behavioural coverage relies on rstest-bdd (Behaviour-Driven Development, BDD)
v0.1.0, which now bundles Fluent localization files. The test suite includes
tests/localized_diagnostics.rs, a Dutch Gherkin scenario that switches
diagnostics to French via rstest_bdd::select_localizations and fails if the
embedded assets are missing. Run make test (or the focused
cargo test localized_diagnostics) in CI to ensure every target platform loads
the lazy localization payload correctly.
Next steps
After the bootstrap completes you can start PostgreSQL with
postgresql_embedded (or another supervisor of your choice) using the same
directories and superuser credentials established by the helper.