Docs
HelmConfiguration

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.

KeyTypeDefaultDescription
postgresql.externalboolfalseUse internal PostgreSQL
postgresql.instancesuint80Number of PostgreSQL replicas. 0 auto-scales to min(nodes, 3) (0-255)
postgresql.versionstring18PostgreSQL major version
postgresql.storageSizestring4GiStorage size for each PostgreSQL instance
postgresql.storageClassNamestring-Storage class (uses cluster default if not set)
postgresql.registrystring-Container registry override for PGO images
postgresql.resources.cpuint-CPU request in millicores (optional)
postgresql.resources.memoryint-Memory request in MiB (optional)
postgresql.limits.cpuint-CPU limit in millicores (optional)
postgresql.limits.memoryint-Memory limit in MiB (optional)
postgresql.backupsobjectsee BackupspgBackRest 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: 2048

PGO automatically handles:

  • Database creation (netbox, diode, hydra databases)
  • 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

New in 2.3.0. The internal database is backed up by pgBackRest, which PGO runs on the operator's behalf. It is on by default, so on a supported storage class a default install has working disaster recovery with no configuration.

Two facts decide whether a restore returns your database

  1. Your storage class must not provision hostPath PersistentVolumes. Velero skips them without an error, so the backup reports Completed holding no volume data. local-path-provisioner — the default in k3s, k3d, and kind — provisions hostPath volumes and gives you no working disaster recovery at all.
  2. A completed Velero restore always leaves the PostgreSQL data volume empty. It is excluded from the backup on purpose. The database is rebuilt from the pgBackRest repository, which is a separate step.

See Storage requirements and Restore procedure.

netboxEnterprise:
  spec:
    postgresql:
      backups:
        enabled: true
        repoStorageSize: 16Gi
        retentionFull: 4
        fullSchedule: "0 1 * * 0"
        incrementalSchedule: "0 1 * * 1-6"
KeyTypeDefaultDescription
postgresql.backups.enabledbooltrueWhether pgBackRest runs
postgresql.backups.repoStorageSizestring16GiSize of the pgBackRest repository PVC
postgresql.backups.repoStorageClassNamestring-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: the repository is the only copy of your database in the Velero archive, and Velero cannot read a hostPath volume.
postgresql.backups.retentionFullint4Number of full backup sets to keep
postgresql.backups.fullSchedulestring0 1 * * 0Cron schedule for full backups. An empty string disables them.
postgresql.backups.incrementalSchedulestring0 1 * * 1-6Cron schedule for incremental backups. An empty string disables them.

The repository PVC is separate from the PostgreSQL data PVC, and it is larger by default. It holds a full backup set plus the write-ahead log archived since that set.

The whole section is ignored when postgresql.external is true. An external database has no operator-managed repository.

enabled: false leaves the database backed up by nothing

Velero's filesystem backup excludes the PostgreSQL data volume, and that exclusion stays in place when pgBackRest is off. A file-by-file copy of a live data directory is a torn copy, and one that looks restorable is worse than none. So this setting is an opt-out from PostgreSQL disaster recovery, not a choice of a different mechanism.

Disabling it on a running cluster also pauses PGO's reconciliation of the cluster, which the operator reports as PostgresReconciliationPaused=True.

See PostgreSQL Backups and Disaster Recovery for verification commands and the restore procedure.

External PostgreSQL

Set postgresql.external: true to use an externally managed PostgreSQL instance.

netboxEnterprise:
  spec:
    postgresql:
      external: true

When 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: password

Host and port are configured via postgresqlProfiles (see below).

You can disable PGO entirely when using an external database:

pgo:
  enabled: false

See 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: netbox

Each 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:

KeyTypeDefaultDescription
postgresqlProfiles.<name>.tlsConfig.sslmodeenumpreferSSL mode for connections
postgresqlProfiles.<name>.tlsConfig.insecureSkipVerifyboolfalseSkip TLS verification (dev only)
postgresqlProfiles.<name>.tlsConfig.keychainCaCertificateslist-CA certificate names from tlsKeychain
postgresqlProfiles.<name>.tlsConfig.keychainClientCertificatestring-Client certificate name from tlsKeychain

SSL Modes

ModeDescription
disableNo SSL
allowTry non-SSL first, then SSL
preferTry SSL first, then non-SSL (default)
requireSSL required, no certificate verification
verify-caSSL required, verify server CA
verify-fullSSL 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.crt

TLS 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.key

Database Users

When using internal PostgreSQL, PGO creates the following database users by default:

UserDatabasePurpose
netboxnetboxNetBox application
diodediodeDiode reconciler (if Diode enabled)
hydrahydraHydra OIDC server (if Diode enabled)

Next Steps

On this page