Security
Image verification, runtime hardening, and authentication.
Image verification
Every published image is signed with Cosign using keyless GitHub OIDC. Verify before deploying to confirm the image was built by the Elevarq GitHub Actions workflow and has not been tampered with.
cosign verify elevarq/pgagroal:1.0.0 \
--certificate-identity-regexp "https://github.com/Elevarq/pgAgroal/.*" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"A successful verification confirms:
- --The image was built by GitHub Actions from the Elevarq/pgAgroal repository
- --The signature is tied to a specific commit and workflow run
- --The image has not been modified since signing
Supply chain attestations
Each image includes two attestations attached at build time:
| Attestation | What it provides |
|---|---|
| SBOM | Software bill of materials — lists every package in the image |
| SLSA Provenance | Build metadata — source repo, commit, workflow, builder identity |
Inspect attestations:
docker buildx imagetools inspect elevarq/pgagroal:1.0.0The output shows image manifests for each platform (amd64, arm64) plus attestation manifests containing the SBOM and provenance data.
Runtime hardening
The container is hardened by default. These protections are built into the image and the Helm chart — no configuration needed.
- --Non-root execution — runs as UID 1000, never root
- --No capabilities — all Linux capabilities dropped
- --No privilege escalation —
allowPrivilegeEscalation: false - --Read-only root filesystem — only
/tmpand/etc/pgagroalare writable (via emptyDir in K8s) - --Seccomp profile — RuntimeDefault restricts system calls
- --Multi-stage build — compilers and build tools are not present in the runtime image
Authentication
Passthrough (default)
The container ships with allow_unknown_users = true. Any client credentials are forwarded to PostgreSQL for validation. The pooler does not store or manage passwords in this mode.
This is the simplest and most common setup. PostgreSQL controls who can connect — pgagroal only pools the connections.
Registered users
Set PG_USERNAME and PG_PASSWORD to register a user at startup. The entrypoint writes a hashed credential file that pgagroal uses for initial authentication before forwarding to the backend.
In Kubernetes, always pass credentials via a Secret. The Helm chart supports credentials.existingSecret for this purpose.
Network considerations
pgagroal speaks the PostgreSQL wire protocol. Anything that can connect to PostgreSQL can connect to pgagroal. This also means pgagroal inherits the same exposure risks.
- --Do not expose to the public internet. pgagroal should only be reachable from application networks. Use Kubernetes NetworkPolicies, security groups, or firewall rules.
- --Use ClusterIP services in Kubernetes. The Helm chart defaults to ClusterIP. Do not change this to LoadBalancer or NodePort unless you have a specific reason and additional access controls.
- --Restrict backend connectivity. The pooler needs to reach PostgreSQL on port 5432. It does not need outbound internet access.
- --TLS to the backend. If your PostgreSQL server requires TLS, configure it in pgagroal. The container supports TLS via pgagroal's built-in TLS settings.
Compliance alignment
The build and release process is aligned with SOC 2 and ISO 27001 expectations: CI-only publishing, signed images, SBOM and provenance attestations, non-root execution, and auditable build-to-deployment traceability.
Elevarq does not claim SOC 2 or ISO 27001 certification. These practices support compliance readiness and auditability.