# initdb options reference

> Supported pgrust initdb argv: -D/--pgdata, -U/--username, -L, -E/--encoding, locale flags, --wal-segsize; space-separated parsing; unsupported options that error.

- Repository: malisper/pgrust
- GitHub: https://github.com/malisper/pgrust
- Human docs: https://grok-wiki.com/public/docs/malisper-pgrust-7e0c8e82bc21
- Complete Markdown: https://grok-wiki.com/public/docs/malisper-pgrust-7e0c8e82bc21/llms-full.txt

## Source Files

- `crates/backend/main/initdb/src/lib.rs`
- `docker/entrypoint.sh`
- `README.md`
- `crates/backend/main/main_main/src/lib.rs`
- `crates/_support/seam/init/src/bin/postgres.rs`

---

---
title: "initdb options reference"
description: "Supported pgrust initdb argv: -D/--pgdata, -U/--username, -L, -E/--encoding, locale flags, --wal-segsize; space-separated parsing; unsupported options that error."
---

pgrust clusters the initdb surface inside the single `postgres` binary: when `argv[1]` is `initdb` or `--initdb`, `pg_main` returns `MainOutcome::Initdb` and the binary shell runs `initdb::initdb_main`. That driver is a port of C `src/bin/initdb/initdb.c` options and scaffolding; it is **not** a separate `initdb` executable and is **not** a PostgreSQL must-be-first `DispatchOption`. Argument parsing lives in `parse_args` and accepts only a small, explicit subset of C initdb flags. Anything else fails with `unrecognized initdb option "…"`.

<Warning>
pgrust initdb is a **subset** of C PostgreSQL 18 initdb. Options common in Docker/`POSTGRES_INITDB_ARGS` recipes (`-A`/`--auth`, `--data-checksums`, `--pwfile`, `--waldir`, and many others) are **not** accepted and abort the run.
</Warning>

## Invocation

| Form | Notes |
|------|--------|
| `postgres --initdb …` | Canonical form used in README and Docker |
| `postgres initdb …` | Same dispatch (`argv[1] == "initdb"`) |
| `pgrust initdb …` | Same when the binary is named `pgrust` |

`argv[0]` is the program name; `argv[1]` must be `initdb` or `--initdb`; options start at `argv[2]`.

```bash
target/release/postgres --initdb \
  -D /tmp/pgrust-data \
  -L "$PWD/vendor/postgres-18.3/share" \
  --no-locale \
  --encoding UTF8 \
  -U postgres
```

On success the driver prints:

```text
Success. You can now start the database server using pgrust/postgres -D <pgdata>
```

and the process exits `0`. Failures print `initdb: error: <message>` on stderr and exit `1`.

<Note>
Initdb is not built for wasm targets (`target_family = "wasm"` exits `1` without running the driver). Native builds re-exec the same binary for internal `--boot` and `--single` phases.
</Note>

## Argument parsing rules

| Rule | Behavior |
|------|----------|
| Space-separated values | Required: `--pgdata /path`, `-E UTF8`, `--wal-segsize 16` |
| `=` forms | **Not** accepted — e.g. `--pgdata=/path` is treated as an unknown option string |
| Glued short form | **Only** `-D<path>` is accepted (e.g. `-D/tmp/data`). Other shorts need a following token (`-U postgres`) |
| Order | Options may appear in any order after `initdb`/`--initdb` |
| Missing value | `option <flag> requires an argument` |
| Unknown token | `unrecognized initdb option "<token>"` |

Docker documents the same contract: `pgrust initdb parses --opt value (space-separated), not --opt=value`.

## Supported options

### Data directory and identity

<ParamField body="-D / --pgdata" type="path" required>
Target `PGDATA` path. Required. Missing value yields `no data directory specified (use -D / --pgdata)`. Directory must not exist, or must exist and be empty; otherwise `directory "<path>" exists but is not empty`. Created with mode `0700` on Unix.
</ParamField>

<ParamField body="-U / --username" type="string" default="$USER or postgres">
Bootstrap superuser name. Default is `$USER` when set and non-empty, else `postgres`. Substituted into the BKI as the `POSTGRES` token (superuser role name). Does not consult `/etc/passwd` for the name (Docker relies on `--username` only).
</ParamField>

### Share directory

<ParamField body="-L" type="path">
Share-directory override (bootstrap templates: `postgres.bki`, `*.conf.sample`, system SQL, etc.). If omitted, derived via `common_path_seams::get_share_path` from the executable path. Docker always passes `-L "$PG_SHAREDIR"` because the binary may not sit next to a PGDG-style share tree.
</ParamField>

### Encoding

<ParamField body="-E / --encoding" type="string" default="UTF8">
Server encoding name. Normalized by uppercasing and stripping `-`/`_`, then mapped to a numeric encoding id for BKI substitution.
</ParamField>

| Accepted name (after normalize) | Encoding id |
|---------------------------------|-------------|
| `SQLASCII` | `0` |
| `UTF8`, `UNICODE` | `6` (default) |
| `LATIN1` | `8` |

Any other name fails: `unsupported encoding "<name>"`.

### Locale

| Flag | Behavior |
|------|----------|
| Default | `locale_collate = "C"`, `locale_ctype = "C"` |
| `--lc-collate <value>` | Stores value; substituted into BKI as `LC_COLLATE` |
| `--lc-ctype <value>` | Stores value; substituted into BKI as `LC_CTYPE` |
| `--locale <value>` | Value is **accepted and consumed**, but not applied to collate/ctype — only `"C"` is effectively honored for cluster locale messaging |
| `--no-locale` | Forces both collate and ctype to `"C"` |

Startup still prints `The database cluster will be initialized with locale "C".` regardless of stored collate/ctype strings. BKI also sets `DATLOCALE`/`ICU_RULES` to `_null_` and `LOCALE_PROVIDER` to `c` (libc).

### WAL segment size

<ParamField body="--wal-segsize" type="integer (MB)" default="16">
WAL segment size in **megabytes**. Parsed as `u64`; stored as `mb * 1024 * 1024` bytes and passed to the bootstrap backend as `-X <bytes>`. Non-integer values fail: `invalid --wal-segsize`.
</ParamField>

## Defaults summary

| Field | Default |
|-------|---------|
| `pgdata` | empty (error if still empty after parse) |
| `username` | `$USER` or `postgres` |
| `sharedir` | derived from executable unless `-L` |
| `encoding_id` | `6` (UTF8) |
| `wal_segment_size` | `16 * 1024 * 1024` bytes |
| `locale_collate` / `locale_ctype` | `"C"` / `"C"` |
| Auth in generated `pg_hba.conf` | `trust` (host and local); no `-A` support |

## Unsupported options (error)

Any argv token not listed above is rejected:

```text
initdb: error: unrecognized initdb option "<token>"
```

Documented or commonly attempted gaps include:

| Option / area | Status in pgrust |
|---------------|------------------|
| `-A` / `--auth` / `--auth-host` / `--auth-local` | Unrecognized |
| `--data-checksums` | Unrecognized |
| `--pwfile` / `-W` / `--pwprompt` | Unrecognized (Docker sets password later via `ALTER ROLE`) |
| `--waldir` / `POSTGRES_INITDB_WALDIR` path | Unrecognized if passed through to `--initdb` |
| `--locale=…` / `--encoding=…` (`=` form) | Unrecognized whole token |
| Other C initdb flags (`-k`, `--set`, `--sync-only`, …) | Unrecognized |

Docker still wires `POSTGRES_INITDB_ARGS` into the same driver. Only space-separated supported flags are safe there; unsupported args fail first boot.

## Error catalog

| Condition | Message (approx.) | Exit |
|-----------|-------------------|------|
| No `-D`/`--pgdata` | `no data directory specified (use -D / --pgdata)` | 1 |
| Option without value | `option <flag> requires an argument` | 1 |
| Unknown flag | `unrecognized initdb option "<a>"` | 1 |
| Bad encoding name | `unsupported encoding "<name>"` | 1 |
| Bad `--wal-segsize` | `invalid --wal-segsize` | 1 |
| Non-empty PGDATA | `directory "<pgdata>" exists but is not empty` | 1 |
| Cannot create/read paths | `could not create/read/write "…"` | 1 |
| BKI major mismatch | `input file "…/postgres.bki" does not belong to PostgreSQL 18` | 1 |
| Bootstrap/post-bootstrap backend failure | `bootstrap backend exited with …` / `post-bootstrap backend exited with …` | 1 |

All messages are prefixed with `initdb: error: ` by the binary shell.

## How options flow into bootstrap

```text
argv: postgres --initdb [options...]
              │
              ▼
        parse_args  ──► Options { pgdata, username, sharedir, encoding_id,
                                  wal_segment_size, locale_* }
              │
              ├─ create PGDATA tree + PG_VERSION ("18")
              ├─ setup_config from sharedir samples (hba = trust)
              ├─ substitute_bki (POSTGRES, ENCODING, LC_*)
              ├─ re-exec: postgres --boot -X <wal_bytes> -D <pgdata>  ← BKI stdin
              └─ re-exec: postgres --single … template1               ← post-bootstrap SQL
```

Relevant option effects:

- **username** → BKI `POSTGRES` token; privilege SQL uses the same name  
- **encoding_id** → BKI `ENCODING`  
- **locale_*** → BKI `LC_COLLATE` / `LC_CTYPE`  
- **wal_segment_size** → `--boot -X`  
- **-L / sharedir** → location of `postgres.bki`, conf samples, and post-bootstrap SQL files  

Auth-method flags are not parsed; generated `pg_hba.conf` always uses `trust` with the standard caution comment.

## Docker mapping

`docker_init_database_dir` runs approximately:

```bash
"$PGRUST_BIN" --initdb \
  -D "$PGDATA" \
  -L "$PG_SHAREDIR" \
  --username "$POSTGRES_USER" \
  $POSTGRES_INITDB_ARGS \
  "$@"
```

| Docker input | Effect |
|--------------|--------|
| `POSTGRES_USER` | Always passed as `--username` |
| `POSTGRES_INITDB_ARGS` | Appended as extra initdb argv (must be space-separated supported flags only) |
| `POSTGRES_PASSWORD` | **Not** an initdb flag; applied after temp server start via `ALTER ROLE` (no `--pwfile`) |
| Share path | Always `-L` (binary not in a classic bindir layout) |

See the Docker environment reference for full env var behavior.

## Minimal and extended examples

<CodeGroup>

```bash title="Minimal (required -D)"
postgres --initdb -D /tmp/pgrust-data -L /path/to/share
```

```bash title="README-shaped cluster"
postgres --initdb \
  -D /tmp/pgrust-data \
  -L "$PWD/vendor/postgres-18.3/share" \
  --no-locale \
  --encoding UTF8 \
  -U postgres
```

```bash title="Encoding + WAL size"
postgres --initdb \
  -D /tmp/pgrust-data \
  -L /path/to/share \
  -E LATIN1 \
  --wal-segsize 32 \
  -U app
```

```bash title="Invalid (will error)"
# equals form
postgres --initdb --pgdata=/tmp/pgrust-data

# C-only flags
postgres --initdb -D /tmp/pgrust-data -A trust --data-checksums
```

</CodeGroup>

## Related pages

<CardGroup>
  <Card title="Initialize a cluster" href="/init-cluster">
    End-to-end --initdb flow: directory layout, bootstrap phases, success text.
  </Card>
  <Card title="Process modes and dispatch" href="/process-modes">
    How argv[1] routes to initdb, --boot, --single, and postmaster.
  </Card>
  <Card title="Install paths and share directory" href="/install-paths">
    -L, PGRUST_PGSHAREDIR, and why a wrong share tree breaks initdb.
  </Card>
  <Card title="Docker environment reference" href="/docker-reference">
    POSTGRES_INITDB_ARGS, POSTGRES_USER, and entrypoint password handling.
  </Card>
  <Card title="postgres CLI reference" href="/cli-reference">
    Non-initdb flags: --help, --version, -c GUC overrides, dispatch options.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Initdb option gaps and other common boot failures.
  </Card>
</CardGroup>
