Kernel-Independent FIPS Architecture
Technical deep-dive into Chainguard's kernel-independent FIPS implementation using userspace entropy sources
Before starting, you’ll need:
FIPS containers work on any recent Linux kernel, including:
Chainguard offers 400+ FIPS image variants. Choose based on your use case:
Language runtime images if you’re building applications:
go-fips - For building Go applicationspython-fips - For Python applicationsnode-fips - For Node.js applicationsjdk-fips or jre-fips - For Java applicationsdotnet-runtime-fips - For .NET applicationsApplication images if you need a specific tool or service:
nginx-fips - Web serverpostgres-fips - Databaseprometheus-fips - MonitoringBase images for minimal runtime environments:
glibc-openssl-fips - Minimal glibc-based runtimebusybox-fips - Minimal BusyBox environmentBrowse the complete catalog at images.chainguard.dev/?category=fips.
Let’s start with a Python example to verify FIPS is working.
Replace ORGANIZATION with your organization name in the Chainguard Registry:
docker pull cgr.dev/ORGANIZATION/python-fips:latestCreate a Python script that uses cryptography:
cat > test_fips.py << 'EOF'
import hashlib
import ssl
# Test that we can use cryptographic functions
data = b"Hello, FIPS!"
hash_result = hashlib.sha256(data).hexdigest()
print(f"SHA-256 hash: {hash_result}")
# Check SSL/TLS configuration
print(f"OpenSSL version: {ssl.OPENSSL_VERSION}")
print("FIPS cryptography is active")
EOFRun the script in the FIPS container:
docker run --rm -v $(pwd):/work -w /work \
  cgr.dev/ORGANIZATION/python-fips:latest \
  python test_fips.pyYou should see output like:
SHA-256 hash: 4a1e3b5c7d9f2a8c6b0e4f3a9d8c7b6a5e4d3c2b1a0f9e8d7c6b5a4e3d2c1b0a
OpenSSL version: OpenSSL 3.4.0 5 Aug 2025
FIPS cryptography is activeThis confirms the container is using OpenSSL for cryptographic operations.
Every Chainguard image includes a Software Bill of Materials (SBOM). Verify FIPS-required packages:
cosign download sbom cgr.dev/ORGANIZATION/python-fips:latest | grep -E "libcrypto|openssl-config"Look for:
libcrypto3 version 3.4.0-r2 or higheropenssl-config-fipshardened version 3.4.0-r3 or higherThese packages indicate kernel-independent FIPS configuration.
Run a container interactively to check OpenSSL configuration:
docker run --rm -it cgr.dev/ORGANIZATION/python-fips:latest shInside the container, verify the FIPS module:
cat /etc/ssl/fipsmodule.cnfYou should see configuration for the FIPS provider. This file’s presence and validity are essential for FIPS operation.
The recommended pattern is to build with a FIPS SDK image and run with a minimal FIPS runtime image.
Example Dockerfile for a Go application:
# Build stage
FROM cgr.dev/ORGANIZATION/go-fips:latest AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o myapp
# Runtime stage
FROM cgr.dev/ORGANIZATION/glibc-openssl-fips:latest
COPY --from=builder /app/myapp /usr/bin/myapp
ENTRYPOINT ["/usr/bin/myapp"]This pattern:
docker build -t myapp-fips .
docker run --rm myapp-fipsThe resulting container runs on any Linux kernel and maintains FIPS validation.
FROM cgr.dev/ORGANIZATION/python-fips:latest
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]FROM cgr.dev/ORGANIZATION/node-fips:latest AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
# Use multi-stage if you want a smaller runtime
FROM cgr.dev/ORGANIZATION/node-fips:latest
WORKDIR /app
COPY --from=builder /app .
CMD ["node", "server.js"]FROM cgr.dev/ORGANIZATION/jdk-fips:latest AS builder
WORKDIR /app
COPY . .
RUN javac MyApp.java
FROM cgr.dev/ORGANIZATION/jre-fips:latest
WORKDIR /app
COPY --from=builder /app/*.class .
CMD ["java", "MyApp"]To verify that FIPS mode is enforced, you can intentionally break the FIPS configuration and confirm the application fails.
Warning: This test should only be done in development environments.
Run a container with access to modify system files:
docker run --rm -it --user root \
  cgr.dev/ORGANIZATION/python-fips:latest shInside the container, break the FIPS configuration:
# Backup the config
cp /etc/ssl/fipsmodule.cnf /tmp/fipsmodule.cnf.bak
# Invalidate it
ln -sf /dev/null /etc/ssl/fipsmodule.cnf
# Try to use crypto
python3 -c "import hashlib; print(hashlib.sha256(b'test').hexdigest())"You should see an error indicating FIPS is required but not available. This proves the container enforces FIPS mode and won’t fall back to non-validated cryptography.
Restore the config to fix:
cp /tmp/fipsmodule.cnf.bak /etc/ssl/fipsmodule.cnfFIPS containers work on any kernel, so you can develop and test locally:
Example for Python development:
docker run --rm -it \
  -v $(pwd):/app \
  -w /app \
  -p 8000:8000 \
  cgr.dev/ORGANIZATION/python-fips:latest \
  bashInside, install development dependencies and run your app.
FIPS containers work in standard CI/CD pipelines without special infrastructure.
GitHub Actions example:
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Pull FIPS image
        run: docker pull cgr.dev/ORGANIZATION/python-fips:latest
      - name: Run tests
        run: |
          docker run --rm -v $(pwd):/app -w /app \
            cgr.dev/ORGANIZATION/python-fips:latest \
            python -m pytestNo special runners or kernel configurations required.
Cause: The FIPS provider configuration is missing or invalid.
Solution: Verify you’re using a FIPS-tagged image (e.g., python-fips, not python). Check the SBOM contains required packages.
Cause: The application may be using a cryptographic library that doesn’t support FIPS.
Solution: Ensure your application uses OpenSSL-backed cryptography.
Cause: Likely not FIPS-related. Profile your application first.
Solution: Use standard profiling tools to identify bottlenecks. FIPS cryptography typically adds minimal overhead.
Cause: FIPS images require account access.
Solution: Verify your organization has FIPS access. Contact support if needed.
Now that you’ve deployed your first FIPS container:
Last updated: 2025-10-16 08:00