PostgreSQL Configuration
Configure internal PGO-managed or external PostgreSQL for NetBox Enterprise
NetBox Enterprise supports two PostgreSQL deployment modes:
- Internal (default): Managed by the Crunchy Postgres Operator (PGO), installed as a chart dependency
- External: Connect to an existing PostgreSQL instance you manage
Internal PostgreSQL (Default)
When postgresql.external: false (the default), the operator deploys a PostgresCluster resource that PGO manages.
| Key | Type | Default | Description |
|---|---|---|---|
postgresql.external | bool | false | Use internal PostgreSQL |
postgresql.instances | uint8 | 0 | Number of PostgreSQL replicas. 0 auto-scales to min(nodes, 3) (0-255) |
postgresql.version | string | 18 | PostgreSQL major version |
postgresql.storageSize | string | 4Gi | Storage size for each PostgreSQL instance |
postgresql.storageClassName | string | - | Storage class (uses cluster default if not set) |
postgresql.registry | string | - | Container registry override for PGO images |
postgresql.resources.cpu | int | - | CPU request in millicores (optional) |
postgresql.resources.memory | int | - | Memory request in MiB (optional) |
postgresql.limits.cpu | int | - | CPU limit in millicores (optional) |
postgresql.limits.memory | int | - | Memory limit in MiB (optional) |
postgresql.backups | object | see Backups | pgBackRest backup settings |
When resources or limits are not set, no resource requests or limits are applied to PostgreSQL pods, allowing PGO to use Kubernetes defaults. Set limits to prevent PostgreSQL from consuming excessive node resources.
Example with redundancy and resource limits:
netboxEnterprise:
spec:
postgresql:
external: false
instances: 2
version: "18"
storageSize: "20Gi"
resources:
cpu: 500
memory: 1024
limits:
cpu: 2000
memory: 2048PGO automatically handles:
- Database creation (
netbox,diode,hydradatabases) - User management and credential rotation
- Replication between primary and replica instances
- Failover and recovery
The operator detects PGO password rotations automatically using resourceVersion-based change detection and triggers rolling updates without reading sensitive secret data.
Backups
From 2.3.0, pgBackRest makes PostgreSQL backups of the internal database. PGO runs pgBackRest for the operator. PostgreSQL backups are on by default, and they run on a schedule. They stay in the cluster, so you also need disaster recovery backups with Velero. See Backups for disaster recovery backups, and PostgreSQL Backups and Disaster Recovery for the terms, the schedule, the retention, and the restore procedure.
netboxEnterprise:
spec:
postgresql:
backups:
enabled: true
repoStorageSize: 16Gi
retentionFull: 4
fullSchedule: "0 1 * * 0"
incrementalSchedule: "0 1 * * 1-6"| Key | Type | Default | Description |
|---|---|---|---|
postgresql.backups.enabled | bool | true | Whether pgBackRest runs |
postgresql.backups.repoStorageSize | string | 16Gi | Size of the pgBackRest repository PVC |
postgresql.backups.repoStorageClassName | string | - | Storage class for the repository PVC. Falls back to the PostgreSQL data storage class, then to the cluster default. It must not be a hostPath class: a disaster recovery backup gets the database only from the repository, and Velero cannot read a hostPath volume. |
postgresql.backups.retentionFull | int | 4 | Number of full PostgreSQL backups to keep |
postgresql.backups.fullSchedule | string | 0 1 * * 0 | Cron schedule for full PostgreSQL backups. In 2.4.0, an empty string fails validation. |
postgresql.backups.incrementalSchedule | string | 0 1 * * 1-6 | Cron schedule for incremental PostgreSQL backups. In 2.4.0, an empty string fails validation. |
The repository PVC is separate from the PostgreSQL data PVC, and it is larger by default. To size it, see Repository size and retention. For the default size of each volume, the result of a size change, and how to measure the usage, see Volume sizes and disk space.
The operator ignores this section when postgresql.external is true.
An external database has no repository.
enabled: false leaves nothing that backs up the database
Disaster recovery backups exclude the PostgreSQL data volume, also when pgBackRest is off.
enabled: false therefore turns off PostgreSQL disaster recovery.
On a running cluster, it also pauses the PGO reconciliation of the cluster.
See With PostgreSQL backups off, nothing backs up the database.
External PostgreSQL
Set postgresql.external: true to use an externally managed PostgreSQL instance. It must be PostgreSQL 15 or later. The NetBox database role must be able to run CREATE EXTENSION ltree. NetBox 4.7 stores hierarchies, such as regions and locations, in an ltree column. ltree is a trusted extension, so the role does not need superuser permission, but without it the upgrade to 2.4.0 fails.
netboxEnterprise:
spec:
postgresql:
external: trueWhen using an external database, you must provide connection details through netbox.config.postgres:
netboxEnterprise:
spec:
netbox:
config:
postgres:
database: "netbox"
user: "netbox"
password:
name: netbox-db-credentials
key: passwordHost and port are configured via postgresqlProfiles (see below).
You can disable PGO entirely when using an external database:
pgo:
enabled: falseSee the External Database Guide for a complete step-by-step walkthrough.
PostgreSQL Profiles
When multiple components (NetBox, Diode, Hydra) connect to the same PostgreSQL server, define a named profile in postgresqlProfiles so connection details and TLS settings are specified once:
netboxEnterprise:
spec:
postgresqlProfiles:
netbox:
host: "postgres.example.com"
port: 5432
tlsConfig:
sslmode: verify-full
keychainCaCertificates:
- postgres-ca
postgresql:
external: true
postgresqlProfile: netbox
diode:
config:
reconciler:
postgres:
postgresqlProfile: netbox
password:
name: diode-db-credentials
key: password
hydra:
postgresqlProfile: netboxEach component references the profile by name and provides only its own password secret. See the NetBoxEnterprise CRD for the full profile field reference.
TLS Configuration
TLS for PostgreSQL connections is configured through postgresqlProfiles:
| Key | Type | Default | Description |
|---|---|---|---|
postgresqlProfiles.<name>.tlsConfig.sslmode | enum | prefer | SSL mode for connections |
postgresqlProfiles.<name>.tlsConfig.insecureSkipVerify | bool | false | Skip TLS verification (dev only) |
postgresqlProfiles.<name>.tlsConfig.keychainCaCertificates | list | - | CA certificate names from tlsKeychain |
postgresqlProfiles.<name>.tlsConfig.keychainClientCertificate | string | - | Client certificate name from tlsKeychain |
SSL Modes
| Mode | Description |
|---|---|
disable | No SSL |
allow | Try non-SSL first, then SSL |
prefer | Try SSL first, then non-SSL (default) |
require | SSL required, no certificate verification |
verify-ca | SSL required, verify server CA |
verify-full | SSL required, verify CA and hostname |
When CA certificates are configured via keychainCaCertificates, libpq verifies the server certificate even with sslmode: require (effectively upgrading it to verify-ca behavior). This is because the operator sets PGSSLROOTCERT when CA certificates are provided. Ensure the CA certificate matches the server, or omit it to use require without verification.
TLS with CA Verification
netboxEnterprise:
spec:
postgresqlProfiles:
netbox:
host: "postgres.example.com"
port: 5432
tlsConfig:
sslmode: verify-ca
keychainCaCertificates:
- my-postgres-ca
postgresql:
external: true
postgresqlProfile: netbox
tlsKeychain:
caCertificateSecrets:
- name: my-postgres-ca
secret: postgres-ca-secret
key: ca.crtTLS with Client Certificates (mTLS)
netboxEnterprise:
spec:
postgresqlProfiles:
netbox:
host: "postgres.example.com"
port: 5432
tlsConfig:
sslmode: verify-full
keychainCaCertificates:
- my-postgres-ca
keychainClientCertificate: my-client-cert
postgresql:
external: true
postgresqlProfile: netbox
tlsKeychain:
caCertificateSecrets:
- name: my-postgres-ca
secret: postgres-ca-secret
key: ca.crt
clientCertificateSecrets:
- name: my-client-cert
secret: postgres-client-cert
certKey: tls.crt
privateKey: tls.keyDatabase Users
When using internal PostgreSQL, PGO creates the following database users by default:
| User | Database | Purpose |
|---|---|---|
netbox | netbox | NetBox application |
diode | diode | Diode reconciler (if Diode enabled) |
hydra | hydra | Hydra OIDC server (if Diode enabled) |
Next Steps
- External Database Guide - Full walkthrough
- Redis - Cache and queue configuration
- Security - TLS best practices