· via dev.to (home feed)
Postgres MD5-to-SCRAM password migration unblocked FIPS mode on RHEL servers
A team's first try at FIPS mode on RHEL 9.5 database hosts failed because PostgreSQL still used MD5 password hashing, so roles were migrated to SCRAM before FIPS was re-enabled.

What happened
According to a write-up on dev.to, a team's first attempt to switch its UAT database servers into FIPS mode failed to take effect, and the problem was not on the operating-system side. The hosts run Red Hat Enterprise Linux 9.5, and the FIPS requirement came from a Reserve Bank of India audit point, which made it mandatory rather than optional.
After the initial enable attempt, the cause surfaced in the database layer: the PostgreSQL instances were still using the older MD5 password-hashing method, which is not compatible with FIPS mode. Until that mismatch was resolved, the servers would not stay in compliance.
Why the stakes were higher than a config tweak
These are not standalone databases. The team's UAT Keycloak identity provider runs on them, and the author sketches the cascade that follows a database outage: if PostgreSQL is down, Keycloak stops; if Keycloak stops, Superset, the BI layer, stops with it; and if Vault is unavailable, application pods end up stuck in CrashLoopBackOff. A password-hashing change on the database therefore sits upstream of the identity provider, the analytics stack, and the secrets infrastructure that applications need in order to start.
The fix, in the right order
Sequencing turned out to be the critical part, with three steps:
- Switch PostgreSQL's password hashing from MD5 to SCRAM.
- Re-hash the existing passwords and re-add them under the new scheme.
- Enable FIPS again — this time it stuck.
The middle step is the one that bites teams. Changing the hashing configuration only governs passwords set from that point on; every role that still has an MD5 hash stored keeps it until the password is reset. SCRAM-SHA-256 has been available in PostgreSQL since version 10 and has been the default method for new passwords since version 14, but long-lived clusters can carry MD5 hashes indefinitely if nobody forces the reset. The author reports confirming that FIPS mode was active once the migration was done, using the enable command shown in the post (sudo fips enable).
What the author would do differently
Looking back, the author writes that the authentication and crypto settings the host's services depend on should have been checked before enabling FIPS, not after. FIPS is not a single-server change when the server sits upstream of Keycloak, Superset and Vault. Mapping that dependency chain first would have flagged the MD5-to-SCRAM migration as a prerequisite rather than a fix discovered after the fact.
Why it matters
Compliance-driven FIPS enablement is routine in regulated industries, and it strips disallowed algorithms like MD5 out of the system's crypto stack. Any team running PostgreSQL on a FIPS-mode host will eventually hit this wall, and the story doubles as a practical checklist: inventory password hashing before touching FIPS; budget for resetting every role's password, because stored hashes do not migrate themselves; and treat a database authentication change as an infrastructure change, since the blast radius of an upstream database reaches identity, BI and secrets tooling well beyond that one server.
- #postgresql
- #fips
- #red-hat
- #security
- #keycloak