# CouchDB TLS Tutorial Source: https://docs.minimus.io/advanced-guides/couchdb-tls How to deploy a CouchDB server and establish a secure TLS connection with self-signed, locally issued certificates Set up CouchDB using self-signed, locally issued certificates and test that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client. For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA). ## Components * **CouchDB image built by Minimus**: CouchDB listens only on HTTPS (5984); HTTP is disabled. * Dynamic certificate generation via OpenSSL: * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. The test does not persist any certificates on the host machine. ## What this guide demonstrates * TLS handshake validation * Server/client certificate trust * Basic auth and CouchDB operations ## Directory structure ```text theme={null} . ├── certgen.sh # Script to generate CA, server, and client certs ├── create-certs.yml # Compose file to generate certs in a dedicated container ├── couchdb-local.ini # CouchDB configuration with SSL and authentication └── docker-compose.yml # Compose file for CouchDB and test client ``` ## Deploy CouchDB with self-signed TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host. ```powershell certgen.sh expandable theme={null} #!/bin/sh # Company: Minimus set -e cd /certs echo "[INFO] Generating OpenSSL config..." cat > openssl.cnf < server.pem echo "[INFO] Creating client cert..." openssl genrsa -out client-key.pem 2048 openssl req -new -key client-key.pem -out client.csr -subj "/CN=couchdb-client" openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial \ -out client-cert.pem -days 365 -sha256 \ -extfile openssl.cnf -extensions v3_req cat client-cert.pem client-key.pem > client.pem cat server-cert.pem ca.pem > server.pem echo "[INFO] Setting file ownership and permissions..." chown 1000:1000 /certs/*.pem || echo "[WARN] chown failed" chmod 600 /certs/*-key.pem chmod 644 /certs/*.pem echo "[SUCCESS] Certificates successfully created for CouchDB." ``` Save the following YAML configuration to a file named `create-certs.yml`. The configuration uses the [Minimus minidebug image](https://images.minimus.io/images/minidebug/quick-start) to generate the certificates with the `certgen.sh` shell script. Minidebug is a secure Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host. ```yaml create-certs.yml theme={null} services: certgen: image: reg.mini.dev/minidebug:latest container_name: certgen volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: - /bin/sh - /certgen.sh network_mode: none ``` Run the following to generate the certificates: ```shellscript Run command theme={null} docker compose -f create-certs.yml up ``` ```shellscript Expected output theme={null} ✔ Image reg.mini.dev/minidebug:latest Pulled 10.2s ✔ ********* Pull complete 7.9s ✔ Container certgen Created 0.9s Attaching to certgen certgen | [INFO] Generating OpenSSL config... certgen | [INFO] Creating CA cert... certgen | [INFO] Creating server cert... certgen | Certificate request self-signature ok certgen | subject=CN=couchdb certgen | [INFO] Creating client cert... certgen | Certificate request self-signature ok certgen | subject=CN=couchdb-client certgen | [INFO] Setting file ownership and permissions... certgen | [SUCCESS] Certificates successfully created for CouchDB. ``` Congrats! You have just generated the following self-signed certificates: * CA certificate (`ca.pem`) * Server certificates (`server-cert.pem`, `server-key.pem`) * Client certificates (`client.pem`, `client-key.pem`) In the next steps, you will mount these certificates into the CouchDB container and configure them via `local.ini`. ### Step 2: Deploy CouchDB server Save the following configuration to a file named `couchdb-local.ini`: ```bash couchdb-local.ini expandable theme={null} [couchdb] single_node = true [cluster] n = 1 q = 8 [chttpd_auth_lockout] mode = off [chttpd] ; Disable plain HTTP completely by setting an invalid port port = 0 bind_address = 0.0.0.0 require_valid_user = true [daemons] ; Enable only HTTPS daemon httpsd = {couch_httpd, start_link, ["https"]} ; Optionally comment out httpd if not used: ; httpd = {couch_httpd, start_link, ["http"]} [ssl] ; Now safe to bind to 5984 since HTTP is disabled port = 5984 enable = true cert_file = /certs/server-cert.pem key_file = /certs/server-key.pem cacert_file = /certs/ca.pem verify_ssl_certificates = true verify_ssl_peer = true fail_if_no_peer_cert = false [admins] admin = admin [authentication] authentication_handlers = {chttpd_auth, proxy_authentication_handler}, {chttpd_auth, default_authentication_handler} # Use TLS 1.2+ tls_versions = tlsv1.2,tlsv1.3 ``` Save the following Docker Compose script to `docker-compose.yml`. This compose file sets up CouchDB using TLS (HTTPS only), with authentication enabled, mounts the generated certificates, uses the configurations in the local INI file, and exposes CouchDB over [https://localhost:15984](https://localhost:15984). ```yaml docker-compose.yml expandable theme={null} services: couchdb: image: reg.mini.dev/couchdb:latest-dev container_name: couchdb-1 environment: - COUCHDB_USER=admin - COUCHDB_PASSWORD=admin - NODENAME=couchdb - COUCHDB_CLUSTER_SIZE=1 volumes: - ./certs:/certs - ./data:/opt/couchdb/data - ./couchdb-local.ini:/opt/couchdb/etc/local.ini ports: - "15984:5984" ``` If you don't yet have the folder `./data` ready and waiting, create it and give it permissions: ```powershell theme={null} mkdir data sudo chmod -R 777 ./data ``` Start the CouchDB container: ```shellscript theme={null} docker compose -f docker-compose.yml up --build -d ``` ### Step 3: Test your CouchDB server Connect to your database and test its connectivity. For example, here are a few commands you can try out: 1. Check server health: ```bash theme={null} curl --cacert certs/ca.pem -u admin:admin https://localhost:15984/_up ``` You should get the response `{"seeds":{},"status":"ok"}`. 2. Create and delete a database (for example `testdb`): ```bash Create database theme={null} curl --cacert certs/ca.pem \ -u admin:admin \ -X PUT \ https://localhost:15984/testdb ``` ```bash Delete database theme={null} curl --cacert certs/ca.pem \ -u admin:admin \ -X DELETE \ https://localhost:15984/testdb ``` 3. List all databases: ```bash List databases theme={null} curl --cacert certs/ca.pem -u admin:admin https://localhost:15984/_all_dbs ``` ```bash Example response theme={null} ["_replicator","_users","testdb"] ``` You can also pass the request for a JSON format. This option requires the [jq JSON processor](https://jqlang.org/download/). ```With List databases in JSON format theme={null} curl --cacert certs/ca.pem -u admin:admin https://localhost:15984/_all_dbs | jq . ``` ```json Example response theme={null} % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 34 0 34 0 0 1019 0 --:--:-- --:--:-- --:--:-- 1030 [ "_replicator", "_users", "testdb" ] ``` 4. Check if a database exists: ```bash Check for database theme={null} curl --cacert certs/ca.pem \ -u admin:admin https://localhost:15984/testdb ``` ```bash Example response theme={null} { "instance_start_time": "1765789065", "db_name": "testdb", "purge_seq": "0-g1AAAAFDeJzLYWBg4MhgTmHgT84vTc5ISXKA0jlACaY8FiDJ8ABI_QeCrEQGAioPQFTeJ6xyAUTlfsIqGyAq5-NTmZQAJJPqCbgxyQGkKp6QKgWQKnsCqhIZkuQhSrIA1tJnlg", "update_seq": "0-g1AAAAJDeJzLYWBg4MhgTmHgT84vTc5ISXKA0jlACaY8FiDJ8ABI_QeCrAzmRIZcoAC7pYWhmaWBBaYuAiYdgJh0H2FSspFxkkmKMckmLYCYtB9hUoqhWWKqmRHJJjVATJqPMCktzcQy1dSUBJOSEoBkUj1KGJkbmVsYWCSRYooDyJR4FFNSLRNNkkxIcosCyBR7FFNSEg1TDC1MSDAlkSFJHsUIs2SL5DQLM0zlWQBKqLC0", "sizes": { "file": 66784, "external": 0, "active": 0 }, "props": {}, "doc_del_count": 0, "doc_count": 0, "disk_format_version": 8, "compact_running": false, "cluster": { "q": 8, "n": 1, "w": 1, "r": 1 } } ``` 5. Create document: ```bash theme={null} curl --cacert certs/ca.pem \ -u admin:admin \ -X PUT \ -H "Content-Type: application/json" \ -d '{ "test": "Welcome to TLS couchdb running Minimus image", "timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' \ https://localhost:15984/testdb/doc1 ``` # Java FIPS Guidelines Source: https://docs.minimus.io/advanced-guides/java-fips-tutorial How to build Java applications with Minimus FIPS 140-3 validated images To run Java workloads in FIPS-compliant environments, you need to use FIPS-validated build and runtime images and make sure the code is correctly configured. This guide walks through the process of migrating a Java project and building it with Minimus FIPS 140-3 validated images. The guide explains the underlying concepts, image differences, and migration steps. This guide is for: * Application developers migrating Java services from standard OpenJDK images * DevOps and platform teams owning Docker and Kubernetes rollout * Compliance and security teams reviewing migration controls ## Overview Use Minimus images to build a FIPS compliant Java app using FIPS 140-3 validated images. These images are configured with FIPS-validated cryptographic providers and enforce strict FIPS compliance at runtime to ensure cryptographic operations are compliant with Federal Information Processing Standards. To be FIPS-compliant, every cryptographic operation (encryption, hashing, key generation, TLS) must go through a CMVP-certified provider. ### Multi-stage build technique Multi-stage builds are great for keeping the build and runtime environments separate and include only the compiled .class in the final image. The recommended process for all workloads is to build with Maven/Gradle/OpenJDK-FIPS and use OpenJRE-FIPS for the runtime stage. Java development in Minimus typically employs multi-stage Dockerfiles that separate the build/compile and runtime stages by using complementary images: * **OpenJDK (Open Java Development Kit)** is an open-source implementation of the Java Platform, Standard Edition (Java SE). Use it to compile, package, run unit tests, and any step that needs Java build tooling. It includes a Java compiler `javac` and the full JDK. * **OpenJRE (open-source Java Runtime Environment)** is used to run Java applications built with OpenJDK. OpenJRE includes the JVM (Java Virtual Machine) and core libraries needed to run Java applications, without the compiler `javac`. OpenJRE has a smaller footprint than the OpenJDK image and only includes what is needed to run a compiled Java application. See also the [**Minimus tutorial for Java**](https://docs.minimus.io/guides/java) and [**Minimus tips for multi-stage builds**](/guides/multi-stage-build). ### Components | **Component** | **Purpose** | | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | [reg.mini.dev/maven](https://images.minimus.io/images/maven/quick-start) and [reg.mini.dev/gradle](https://images.minimus.io/images/gradle/quick-start) | Build stage images | | [reg.mini.dev/openjdk-fips](https://images.minimus.io/images/openjdk-fips/quick-start) | Minimal OpenJDK image, full JDK toolset, does not include Maven or Gradle | | [reg.mini.dev/openjre-fips](https://images.minimus.io/images/openjre-fips/quick-start) | Production runtime stage, leaner JRE-only image | | Application JAR | Build artifact copied from the build stage into the runtime stage | | Optional BCFKS keystore | Required keystore format for private keys in FIPS deployments | ### Environment variables The images are pre-set with the following environment variables: | **Variable** | **Value** | | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `CLASSPATH` | Includes FIPS libraries from `/usr/share/fips-libs/*` | | `JAVA_FIPS_CLASSPATH` | Explicit FIPS classpath reference | | `JAVA_HOME` | Points to the default JVM installation | | `JDK_JAVA_OPTIONS` | `--add-exports=java.base/sun.security.internal.spec=ALL-UNNAMED --add-exports=java.base/sun.security.provider=ALL-UNNAMED -Djavax.net.ssl.trustStoreType=FIPS` | Never overwrite `JDK_JAVA_OPTIONS`, `CLASSPATH`, or `JAVA_FIPS_CLASSPATH` in your Dockerfile or at runtime. These variables carry the FIPS provider wiring pre-set by the image. Always extend them by referencing the existing value, `${JDK_JAVA_OPTIONS}`, rather than replacing it. Overwriting any of these will silently break FIPS compliance at runtime. ### The critical `java -jar` problem `java -jar` ignores `CLASSPATH` (and any `-cp`/`--class-path` you might pass), so the FIPS provider jars do not get loaded unless they are on the bootstrap classpath. Regardless of whether `-Xbootclasspath/a` is supplied directly in your `ENTRYPOINT` or injected via `JDK_JAVA_OPTIONS`, the CCJ provider jars must be appended to the bootstrap classpath; otherwise the JVM will have no available FIPS ciphers. The symptoms are either an empty cipher list or a `NoSuchAlgorithmException` at startup. The correct way to launch applications from a FIPS image is to use `-Xbootclasspath/a` to append the FIPS jars directly to the bootstrap classloader, which is not bypassed by `java -jar`, for example: ```javascript wrap theme={null} ENTRYPOINT ["java", "-Xbootclasspath/a:/usr/share/fips-libs/ccj.jar:/usr/share/fips-libs/sl-bctls.jar:/usr/share/fips-libs/sl-bcutil.jar:/usr/share/fips-libs/sl-bcpkix.jar:/usr/share/fips-libs/sl-bcpg.jar:/usr/share/fips-libs/sl-bcmail.jar", "-jar", "/app/app.jar"] ``` #### List FIPS jars explicitly The bootstrap classpath (`-Xbootclasspath/a`) does **not** expand `*` wildcards. Wildcard expansion only applies to the application class path (`-cp`/`CLASSPATH`). If a wildcard is used such as `/usr/share/fips-libs/*` , it will load nothing and leave the JVM with no FIPS providers. It is best to reference version-independent symlinks (`ccj.jar`, `sl-bctls.jar`, `sl-bcutil.jar`, `sl-bcpkix.jar`, `sl-bcpg.jar`, `sl-bcmail.jar`) rather than versioned filenames such as `ccj-4.0.0-fips.jar` so the entry survives image updates. ## FIPS approved algorithms FIPS approved-only mode (`com.safelogic.cryptocomply.fips.approved_only=true`) enforces a hard algorithm blocklist. Your application will throw a `NoSuchAlgorithmException` or `GeneralSecurityException` at runtime - not at compile time - if it calls any of the blocked algorithms. Below is a table showing the recommended migration paths: | **Algorithms blocked by FIPS** | **FIPS-approved replacement algorithm** | | ------------------------------- | --------------------------------------- | | MD5 (for any security purpose) | SHA-256 or SHA-3 | | SHA-1 signatures | SHA-256 or stronger | | DES / 3DES | AES-128 or AES-256 | | RC4 | AES-GCM | | TLS 1.0 / TLS 1.1 | TLS 1.2 or TLS 1.3 | | RSA or DH keys under 2048 bits | RSA-2048 minimum, RSA-3072 preferred | | PKCS#12 for private key storage | BCFKS keystore format | To migrate your project to FIPS mode, you will need to audit your codebase, and search for string literals like `"MD5"`, `"SHA1"`, `"DES"`, `"RC4"`, `"TLSv1"`, and `"PKCS12"` in any `getInstance()` or `KeyStore.getInstance()` calls. ## How to deploy Java with the Minimus OpenJRE-FIPS image ### Prerequisites * Docker or Podman available locally * Token to pull images from the Minimus image registry * Existing Java project (Maven or Gradle) * A working test environment for smoke tests and crypto-related checks * Host with FIPS-enabled kernel as listed in the CMVP certificate Minimus Java FIPS images use a kernel-dependent FIPS module. Unlike Minimus OpenSSL-based FIPS images, Java FIPS images require a FIPS-enabled kernel and specialized hardware as listed in CMVP certificate [#4912](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4912). Verify your target environment meets these requirements before deploying. To check whether a specific Minimus image includes the Java FIPS module, look for the package `minimus-java-fips-libs` in the image SBOM. ### Step 1: Pre-flight modifications The first step is to audit your application for non-FIPS algorithm usage. Before changing your Dockerfile, scan your codebase for algorithm strings that FIPS will reject at runtime. Common offenders are `MD5`, `SHA1`, `SHA-1`, `DES`, `RC4`, `TLSv1`, `TLS1.0`, `TLS1.1`, and `PKCS12` used as a keystore type for private keys. Replace any incompatible algorithms found with FIPS-approved equivalents and ensure TLS configuration specifies a minimum of `TLSv1.2`. [See the list of approved algorithms](#fips-approved-algorithms) Run your existing test suite before proceeding. Update your Dockerfile to use Minimus images: 1. Use a build image that includes your build tooling ([Maven ](https://images.minimus.io/images/maven/risk-reduction)or [Gradle](https://images.minimus.io/images/gradle/risk-reduction)).  We need to use Maven or Gradle because the Minimus OpenJDK-FIPS image does not include Maven or Gradle by default.  The Minimus [OpenJDK-FIPS image](https://images.minimus.io/images/openjdk-fips/risk-reduction) is a minimal JDK image that does not include Maven or Gradle by default. Therefore it cannot be used for the build stage. \ You can use the OpenJDK-FIPS image for the build stage if you install Maven in a prior step or supply your own build tool, such as a Maven Wrapper. 2. Copy the produced JAR into the [OpenJRE-FIPS image](https://images.minimus.io/images/openjre-fips/risk-reduction) for the runtime stage. 3. Make sure the ENTRYPOINT includes `-Xbootclasspath/a:/usr/share/fips-libs/ccj.jar:/usr/share/fips-libs/sl-bctls.jar:/usr/share/fips-libs/sl-bcutil.jar:/usr/share/fips-libs/sl-bcpkix.jar:/usr/share/fips-libs/sl-bcpg.jar:/usr/share/fips-libs/sl-bcmail.jar` to load the CCJ FIPS provider. Without this flag, `java -jar` bypasses the image's pre-set `CLASSPATH` (and any `-cp`/`--class-path` you might pass), so the FIPS provider jars are never loaded into the bootstrap classloader and the JVM will have no available FIPS ciphers. 4. List the jars explicitly. The bootstrap classpath does **not** expand `*` wildcards (only `-cp`/`CLASSPATH` does), so `/usr/share/fips-libs/*` would load nothing. Use the version-independent symlinks (`ccj.jar`, `sl-bctls.jar`, `sl-bcutil.jar`, `sl-bcpkix.jar`, `sl-bcpg.jar`, `sl-bcmail.jar`) rather than versioned filenames such as `ccj-4.0.0-fips.jar`, so the entry survives image updates. 5. Set a Main-Class to avoid errors. If your build produces a non-executable JAR (no `Main-Class` manifest entry), `java -jar /app/app.jar` will fail with the error: `no main manifest attribute`. Ways to fix this issue: * Configure Maven or Gradle to produce an executable JAR (set `Main-Class`) * Run the app with an explicit main class, e.g. `java -cp /app/app.jar com.example.App`. ### Step 2: Deploy your Java project You can use the below example Dockerfile with your Java project.  ```dockerfile Dockerfile example using Maven theme={null} # Use the Minimus Maven image for the build stage FROM reg.mini.dev/maven:latest AS builder WORKDIR /workspace COPY pom.xml ./ COPY src ./src RUN mvn -DskipTests package FROM reg.mini.dev/openjre-fips:21 WORKDIR /app COPY --from=builder /workspace/target/*.jar /app/app.jar # Extend existing options, do not replace them ENV JDK_JAVA_OPTIONS="${JDK_JAVA_OPTIONS} -XX:+ExitOnOutOfMemoryError" ENTRYPOINT ["java", "-Xbootclasspath/a:/usr/share/fips-libs/ccj.jar:/usr/share/fips-libs/sl-bctls.jar:/usr/share/fips-libs/sl-bcutil.jar:/usr/share/fips-libs/sl-bcpkix.jar:/usr/share/fips-libs/sl-bcpg.jar:/usr/share/fips-libs/sl-bcmail.jar", "-jar", "/app/app.jar"] ``` Confirm the build image (`openjdk-fips`) has compiler access: ```bash Confirm theme={null} docker run --rm reg.mini.dev/openjdk-fips:21 javac -version ``` Confirm the runtime image (`openjre-fips`) is JRE-only: ```bash Confirm theme={null} docker run --rm reg.mini.dev/openjre-fips:21 java -version ``` If any step in your Dockerfile requires `javac` or other JDK tools, it belongs in the `openjdk-fips` build stage. The `openjre-fips` runtime stage should only execute the already-compiled artifact. Build the image from your Dockerfile: ```bash Build theme={null} docker build -t myapp-fips:latest . ``` Run the application: ```bash Run theme={null} docker run --rm -p 8080:8080 myapp-fips:latest ``` ### Step 3: Verify your app Save the following code as `TestFIPS.java`. We will run it against the image to confirm the CCJ and BCJSSE providers are loaded at the correct positions and that non-FIPS algorithms are blocked: ```java TestFIPS.java expandable theme={null} import java.security.Provider; import java.security.Security; public class TestFIPS { public static void main(String[] args) { System.out.println("=== FIPS Compliance Test ==="); String approvedOnly = Security.getProperty("com.safelogic.cryptocomply.fips.approved_only"); boolean isApprovedOnly = approvedOnly != null && approvedOnly.equals("true"); if (!isApprovedOnly) { System.err.println("[ERROR] SafeLogic CryptoComply FIPS Approved Only Mode is disabled!"); System.exit(1); } Provider[] providers = Security.getProviders(); boolean foundCryptoComply = false; boolean foundBCJSSE = false; int cryptoComplyPosition = -1; int bcjssePosition = -1; for (int i = 0; i < providers.length; i++) { String name = providers[i].getName(); if (name.contains("CCJ") || name.contains("CryptoComply")) { foundCryptoComply = true; cryptoComplyPosition = i + 1; System.out.println("[OK] SafeLogic CryptoComply provider found at position " + cryptoComplyPosition); } if (name.contains("BouncyCastleJsse") || name.contains("BCJSSE")) { foundBCJSSE = true; bcjssePosition = i + 1; System.out.println("[OK] Bouncy Castle JSSE provider found at position " + bcjssePosition); } } if (!foundCryptoComply) { System.err.println("[ERROR] CCJ provider NOT found!"); System.exit(1); } if (!foundBCJSSE) { System.err.println("[ERROR] BCJSSE provider NOT found!"); System.exit(1); } if (cryptoComplyPosition != 1) System.err.println("[WARNING] CCJ should be at position 1"); if (bcjssePosition != 2) System.err.println("[WARNING] BCJSSE should be at position 2"); try { javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding", "CCJ"); System.out.println("[OK] AES algorithm available"); java.security.MessageDigest.getInstance("SHA-256", "CCJ"); System.out.println("[OK] SHA-256 algorithm available"); java.security.KeyPairGenerator.getInstance("RSA", "CCJ"); System.out.println("[OK] RSA algorithm available"); try { java.security.MessageDigest.getInstance("MD5", "CCJ"); System.err.println("[ERROR] MD5 is available — FIPS mode not fully enforced!"); System.exit(1); } catch (Exception e) { System.out.println("[OK] MD5 correctly blocked: " + e.getMessage()); } System.out.println("=== FIPS Compliance Test PASSED ==="); } catch (Exception e) { System.err.println("[ERROR] FIPS algorithm test failed: " + e.getMessage()); System.exit(1); } } } ``` Compile and run: ```bash Run theme={null} docker run --rm -v $(pwd):/home/build reg.mini.dev/openjdk-fips:21 sh -c \ "javac /home/build/TestFIPS.java -d /home/build && java -cp /home/build TestFIPS" ``` Expected output: ```bash Expected theme={null} === FIPS Compliance Test === [OK] SafeLogic CryptoComply provider found at position 1 [OK] Bouncy Castle JSSE provider found at position 2 [OK] AES algorithm available [OK] SHA-256 algorithm available [OK] RSA algorithm available [OK] MD5 correctly blocked: ... === FIPS Compliance Test PASSED === ``` If TLS connections return an empty cipher list or throw `NoSuchAlgorithmException`, the CCJ provider is not being registered. Check that `-Xbootclasspath/a:/usr/share/fips-libs/ccj.jar:/usr/share/fips-libs/sl-bctls.jar:/usr/share/fips-libs/sl-bcutil.jar:/usr/share/fips-libs/sl-bcpkix.jar:/usr/share/fips-libs/sl-bcpg.jar:/usr/share/fips-libs/sl-bcmail.jar` is present in your ENTRYPOINT. Validate the following application paths: * Service startup * Health endpoints * TLS client and server connections * Authentication, token signing, and password hashing paths * Any code paths that invoke cryptographic operations directly For deep provider-level and algorithm-level validation, see [Java FIPS Validated Module](/compliance/java-fips). ### Step 4: Roll out to Kubernetes Create a pull secret for the Minimus registry (first update the command with your Minimus token and the relevant namespace): ```bash Create theme={null} kubectl create secret docker-registry minimus-registry \ --docker-server=reg.mini.dev \ --docker-username=minimus \ --docker-password={token} \ -n my-namespace ``` Update your Deployment to reference `openjre-fips` as the runtime image and add the `imagePullSecrets`: ```yaml Deployment theme={null} apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: imagePullSecrets: - name: minimus-registry containers: - name: myapp image: reg.mini.dev/openjre-fips:21 ports: - containerPort: 8080 ``` ```yaml Helm theme={null} image: repository: reg.mini.dev/openjre-fips tag: "21" pullPolicy: Always imagePullSecrets: - name: minimus-registry ``` Apply the rollout and verify: ```bash Apply theme={null} kubectl apply -f deployment.yaml -n my-namespace kubectl rollout status deployment/myapp -n my-namespace kubectl logs deploy/myapp -n my-namespace --tail=200 ``` FIPS mode restricts the keystore formats allowed for private key storage. For example, FIPS mode bans the standard `JKS` and `PKCS12` formats. The Bouncy Castle FIPS KeyStore format (`BCFKS`) is required instead. | **Use case** | **Allowed formats** | | ---------------------------------- | --------------------------- | | Storing private keys | `bcfks` only | | Truststores (public CA certs only) | `jks`, `pkcs12`, or `bcfks` | If your team needs a complete keystore and certificate generation workflow — including `keytool` commands for BCFKS keystore and truststore creation, CA generation, and certificate signing — see the [Keycloak FIPS Tutorial](/advanced-guides/keycloak-fips). The `keytool` patterns shown there apply directly to any Java application using Minimus FIPS images, not just Keycloak. If your application currently loads a `.jks` or `.p12` file containing a private key at startup and passes it to an `SSLContext`, that will throw a `KeyStoreException` at runtime in FIPS mode. The keystore must be regenerated in `bcfks` format before deploying. FIPS mode enforces a minimum password length of 14 characters (112 bits) for all BCFKS keystores and truststores. Passwords shorter than this will be rejected with the error `password must be at least 112 bits`. Use passwords of 16–24 characters. ## Troubleshooting | **Issue** | **Likely cause** | **Action** | | ---------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Empty cipher list at startup | CCJ provider not registered — `java -jar` bypassed CLASSPATH | Add `-Xbootclasspath/a:/usr/share/fips-libs/ccj.jar:/usr/share/fips-libs/sl-bctls.jar:/usr/share/fips-libs/sl-bcutil.jar:/usr/share/fips-libs/sl-bcpkix.jar:/usr/share/fips-libs/sl-bcpg.jar:/usr/share/fips-libs/sl-bcmail.jar` to ENTRYPOINT | | NoSuchAlgorithmException: RSA KeyFactory | FIPS provider not loaded | Add `-Xbootclasspath/a:/usr/share/fips-libs/ccj.jar:/usr/share/fips-libs/sl-bctls.jar:/usr/share/fips-libs/sl-bcutil.jar:/usr/share/fips-libs/sl-bcpkix.jar:/usr/share/fips-libs/sl-bcpg.jar:/usr/share/fips-libs/sl-bcmail.jar` to ENTRYPOINT | | Runtime algorithm errors | Legacy non-approved algorithm in use | Replace with FIPS-approved algorithms and rerun tests | | App works in build stage but not runtime | Build-only tools expected at runtime | Move compile steps to the `openjdk-fips` stage only | | Unexpected Java option behavior | Default Java options overwritten | Extend `JDK_JAVA_OPTIONS` using `${JDK_JAVA_OPTIONS}` | | Keystore loading errors | Private-key store format mismatch | Convert private key keystores to BCFKS | | Password rejected at keystore creation | Password under 14 characters | Use a password of 16–24 characters (minimum 112 bits) | | Cluster pull failures | Missing or invalid registry secret | Recreate pull secret and verify namespace binding | *** # Keycloak FIPS Tutorial Source: https://docs.minimus.io/advanced-guides/keycloak-fips How to deploy Keycloak FIPS with a FIPS-approved keystore To deploy Keycloak in FIPS mode, you need a FIPS-approved keystore. In this tutorial we will use the Bouncy Castle FIPS KeyStore (termed BCFKS). A BCFKS keystore is a Java KeyStore (JKS) format provided by Bouncy Castle that is specifically designed for FIPS-compliant cryptography. The following guide involves the following components: | **File** | **Purpose** | | ------------------------------- | ---------------------------------------------- | | `server.keystore` (BCFKS) | FIPS-approved keystore (private key + cert) | | `truststore.bcfks` | FIPS-approved truststore (contains CA certs) | | `myCA.crt` / `myCA.key` | Local CA (root) for signing/trusting dev certs | | `keycloak.crt` / `keycloak.key` | Server certificate & key (PEM) for Keycloak | ## Prerequisites * Docker available locally * Token to pull images from the Minimus image registry * A working directory for keystores and certs ## Deploy Keycloak for production The following explains how to deploy Keycloak in either HTTPS mode or HTTP-dev mode. Use `keytool` from the Keycloak FIPS image to generate a BCFKS keystore and keypair (provider **CCJ**): ```bash Create BCFKS keystore expandable theme={null} docker run --rm \ -v "$(pwd)":/tmp/keystore \ --entrypoint keytool \ reg.mini.dev/keycloak-fips \ -J-Djava.security.properties=/usr/share/conf/java.security.append \ -J-cp -J"/opt/keycloak/providers/*" \ -v -keystore /tmp/keystore/server.keystore \ -storetype bcfks \ -providername CCJ \ -alias "localhost" \ -genkeypair \ -sigalg SHA512withRSA \ -keyalg RSA \ -dname CN="localhost" \ -storepass "minimusstoretest2025" \ -keypass "minimusstorekeypass2025" ``` If you encounter a permissions-related error, grant write permissions to your working directory and rerun the above command: ```bash Grant permissions theme={null} sudo chown 1000:1000 "$(pwd)" chmod 700 "$(pwd)" ``` ```bash Permission denied error theme={null} keytool error: java.io.FileNotFoundException: /tmp/keystore/server.keystore (Permission denied) java.io.FileNotFoundException: /tmp/keystore/server.keystore (Permission denied) ``` Verify the BCFKS keystore: ```bash Verify the keystore theme={null} docker run --rm -v "$(pwd)":/tmp/keystore \ --entrypoint keytool \ reg.mini.dev/keycloak-fips \ -J-Djava.security.properties=/usr/share/conf/java.security.append \ -J-cp -J"/opt/keycloak/providers/*" \ -v -keystore /tmp/keystore/server.keystore \ -storetype bcfks \ -list -storepass "minimusstoretest2025" ``` ```bash Sample output theme={null} Keystore type: BCFKS Keystore provider: CCJ Your keystore contains 1 entry Alias name: localhost Creation date: Dec 29, 2025 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=localhost Issuer: CN=localhost Serial number: 7cd23b809f937152 Valid from: Mon Dec 29 15:50:44 GMT 2025 until: Sun Mar 29 15:50:44 GMT 2026 Certificate fingerprints: SHA1: 61:68:A4:62:D0:79:67:9F:35:A4:6A:E5:55:E6:FE:92:B7:22:21:1A SHA256: 66:BF:B2:98:97:BB:53:9F:27:1F:43:FB:C4:E3:5C:40:99:11:98:2B:79:A9:14:62:12:D8:8F:FE:1B:E9:57:7B Signature algorithm name: SHA512WITHRSA Subject Public Key Algorithm: 3072-bit RSA key Version: 3 ******************************************* ``` To set up HTTPS using PEM files (instead of a keystore), follow the steps to create a local CA and sign a server certificate. 1. Generate a private key for the Certificate Authority (CA): ```bash theme={null} openssl genrsa -out myCA.key 4096 # Saves the key to the output file myCA.key # Sets the key size to 4096 bits for extra security ``` 2. Create a root self-signed CA certificate: ```bash theme={null} openssl req -x509 -new -nodes -key myCA.key \ -sha256 -days 3650 -out myCA.crt \ -subj "/C=US/ST=Local/L=Local/O=MyOrg/OU=Dev/CN=MyLocalCA" ``` 3. Generate a Server RSA private key for Keycloak: ```bash theme={null} openssl genrsa -out keycloak.key 2048 # Saves the key to the output file keycloak.key # Sets the key size to 2048 bits for extra security ``` 4. CSR for your Keycloak host (edit CN): ```bash theme={null} openssl req -new -key keycloak.key \ -out keycloak.csr \ -subj "/C=US/ST=Local/L=Local/O=MyOrg/OU=Dev/CN=keycloak.local" ``` 5. Create a file `keycloak.ext` containing certificate extension settings for a TLS certificate: ```bash theme={null} cat > keycloak.ext < ```bash Sign CSR theme={null} openssl x509 -req -in keycloak.csr \ -CA myCA.crt -CAkey myCA.key -CAcreateserial \ -out keycloak.crt -days 825 -sha256 -extfile keycloak.ext ``` ```bash Expected output theme={null} Certificate request self-signature ok subject=C=US, ST=Local, L=Local, O=MyOrg, OU=Dev, CN=keycloak.local ``` 7. Run `ls` to verify that the following certificates were created: * CA: `myCA.crt`, `myCA.key`, `myCA.srl` * Server (PEM): `keycloak.crt`, `keycloak.key`, `keycloak.csr`, `keycloak.ext` Import your CA into a BCFKS truststore: ```bash Import CA into truststore theme={null} docker run --rm -v "$(pwd)":/tmp/keystore \ --entrypoint keytool \ reg.mini.dev/keycloak-fips \ -J-Djava.security.properties=/usr/share/conf/java.security.append \ -J-cp -J"/opt/keycloak/providers/*" \ -v -keystore /tmp/keystore/truststore.bcfks \ -storetype bcfks -providername CCJ \ -import -file /tmp/keystore/myCA.crt \ -storepass "minimusstoretest2025" -trustcacerts -noprompt ``` To run in dev mode, deploy Keycloak in HTTP: ```bash Run Keycloak in HTTP theme={null} docker run -d --rm -p 8080:8080 \ -e KC_BOOTSTRAP_ADMIN_USERNAME=minimusadmin \ -e KC_BOOTSTRAP_ADMIN_PASSWORD=minimusadminpass2025 \ reg.mini.dev/keycloak-fips \ start-dev --features=fips --fips-mode=strict \ --https-key-store-password='minimusstoretest2025' \ --hostname=localhost --log-level='INFO' ``` Visit the Keycloak console (UI) at [http://localhost:8080](http://localhost:8080). Even in HTTP mode, FIPS checks still apply to admin and other passwords so ensure they have at least 14 characters. To run in production, deploy Keycloak with the truststore in HTTPS: ```bash Run Keycloak in HTTPS theme={null} docker run -d --rm -p 8443:8443 \ -v "$(pwd)/keycloak.crt":/opt/keycloak/conf/tls.crt:ro \ -v "$(pwd)/keycloak.key":/opt/keycloak/conf/tls.key:ro \ -e KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/tls.crt \ -e KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/tls.key \ -e KC_BOOTSTRAP_ADMIN_USERNAME=minimusadmin2025 \ -e KC_BOOTSTRAP_ADMIN_PASSWORD=minimusadmin2025 \ reg.mini.dev/keycloak-fips \ start --features=fips --fips-mode=strict \ --https-key-store-password='minimusstoretest2025' \ --hostname=localhost --log-level='INFO' ``` Visit the Keycloak console (UI) in HTTPS at [https://localhost:8443](https://localhost:8443). ```bash theme={null} sudo cp myCA.crt /usr/local/share/ca-certificates/myCA.crt sudo update-ca-certificates ``` Change the file permissions in `server.keystore` so only the file owner has read/write access and nobody else has access: ```bash theme={null} chmod 600 *.key server.keystore *.bcfks || true ``` ## Troubleshooting If you get an error `password must be at least 112 bits`, it means that one or more passwords is under 14 characters long. Passwords should be 16-24 characters. Check the passwords for the following variables: `KC_BOOTSTRAP_ADMIN_PASSWORD`, `KC_HTTPS_KEY_STORE_PASSWORD`, truststore password, etc. *** # MariaDB TLS Tutorial Source: https://docs.minimus.io/advanced-guides/mariadb-tls A guide to setting up MariaDB and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client The following guide will help you deploy the Minimus MariaDB image with self-signed, locally issued certificates to help you get started. Run the code to try it for yourself. For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA). ## Components * **MariaDB image built by Minimus**: MariaDB container configured with the secure configuration for client authentication. * Dynamic certificate generation via OpenSSL: * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. ## What this guide demonstrates * TLS handshake validation * Server/client certificate trust * Basic auth and MariaDB operations * Image compatibility ## Directory Structure ```bash theme={null} . ├── certgen.sh # Certificate generation script ├── create-certs.yml # Compose file to run certgen container └── docker-compose.yml # Compose file to run MariaDB ``` ## Deploy MariaDB with TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host. ```bash certgen.sh expandable theme={null} #!/bin/sh # Company: Minimus set -e cd /certs cat > openssl.cnf < Save the following YAML file to run with Docker Compose. It uses the [**Minimus minidebug image**](https://images.minimus.io/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host. ```yaml create-certs.yml theme={null} services: certgen: image: reg.mini.dev/minidebug:latest container_name: mariadb_certgen volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: - /bin/sh - /certgen.sh network_mode: none ``` Run the following to generate the certificates: ```shellscript theme={null} docker compose -f create-certs.yml up ``` Congrats! You have just generated the following self-signed certificates: * CA certificate (`ca.pem`) * Server certificates (`server-cert.pem`, `server-key.pem`) * Client certificates for `testuser` (`client-cert.pem`, `client-key.pem`, `client.csr`) The permissions for all .pem certificates are set to `644` and owned by UID `1000`. Certificate permissions are adjusted to support non-root containers. In the next steps, you will mount these certificates into the MariaDB container. ### Step 2: Deploy MariaDB server Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the MariaDB service with a healthcheck, mounts a volume with the certificates, and maps port 3307 on the host to port 3306 on the container. ```yaml docker-compose.yml expandable theme={null} services: mariadb: image: reg.mini.dev/mariadb container_name: mariadb-1 environment: MARIADB_ROOT_PASSWORD: rootpass ports: - 3307:3306 volumes: - ./certs:/certs:ro command: - --ssl-ca=/certs/ca.pem - --ssl-cert=/certs/server-cert.pem - --ssl-key=/certs/server-key.pem - --require_secure_transport=ON healthcheck: test: - CMD - mariadb-admin - ping - -prootpass interval: 5s retries: 10 ``` Start the MariaDB container in detached mode: ```shellscript theme={null} docker compose -f docker-compose.yml up -d ``` ### Step 3: Test your MariaDB server Connect to your database to test its connectivity. First, make sure you are in the right folder, where the certs are available: ```typescript theme={null} ls -l ./certs/ ``` You can use mysql or mariadb-client to connect over TLS and run tests. For example, here are a few commands you can try out: 1. Connect to the db: ```bash Connect to DB theme={null} mysql -h 127.0.0.1 -P 3307 -u root -p \ --ssl \ --ssl-ca=./certs/ca.pem \ --ssl-cert=./certs/client-cert.pem \ --ssl-key=./certs/client-key.pem ``` ```bash Expected response theme={null} Enter password: # Type in the password set in the docker-compose.yml: `rootpass` Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 181 Server version: 12.1.2-MariaDB MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> ``` 2. Create and list databases: ```shellscript Create and list databases theme={null} CREATE DATABASE my_new_db; SHOW DATABASES; ``` ```bash Example response theme={null} Query OK, 1 row affected (0.001 sec) MariaDB [(none)]> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | my_new_db | | mysql | | new_db | | performance_schema | | sys | +--------------------+ 6 rows in set (0.001 sec) ``` 3. Show server version: ```bash Show server version theme={null} SELECT version(); ``` ```Example response theme={null} +----------------+ | version() | +----------------+ | 12.1.2-MariaDB | +----------------+ 1 row in set (0.001 sec) ``` 4. Check that TLS is active: ```bash Check TLS theme={null} SHOW VARIABLES LIKE 'have_ssl'; SHOW STATUS LIKE 'Ssl_cipher'; SHOW STATUS LIKE 'Ssl_version'; ``` # Mongo TLS Tutorial Source: https://docs.minimus.io/advanced-guides/mongo-tls A guide to setting up Mongo and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client The following guide will help you deploy the Minimus Mongo image with self-signed, locally issued certificates to help you get started. Run the code to try it for yourself. For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA). ## Components * **Mongo image built by Minimus**: MongoDB container running with `requireTLS` and client authentication. * **mongosh** installed. * Dynamic certificate generation via OpenSSL: * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. ## What this guide demonstrates * TLS handshake validation * Server/client certificate trust * Basic auth and MongoDB operations * Image compatibility ## Directory Structure ```bash theme={null} . ├── certgen.sh # Certificate generation script ├── create-certs.yml # Compose file to run certgen container └── docker-compose.yml # Compose file to run MongoDB ``` ## Deploy Mongo with TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host. ```bash certgen.sh expandable theme={null} #!/bin/sh set -e cd /certs echo "[INFO] Generating OpenSSL config..." cat > openssl.cnf < server.pem echo "[INFO] Creating client certificate..." openssl genrsa -out client-key.pem 2048 openssl req -new -key client-key.pem -out client.csr -subj "/CN=root" openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial \ -out client-cert.pem -days 365 -sha256 \ -extfile openssl.cnf -extensions v3_client cat client-cert.pem client-key.pem > client.pem ls -l /certs/ echo "[INFO] Adjusting permissions..." # Secure private keys [ -f server-key.pem ] && chmod 600 server-key.pem [ -f client-key.pem ] && chmod 600 client-key.pem # Public certs readable chmod 644 ca.pem server-cert.pem client-cert.pem server.pem client.pem # Ownership chown -R 1000:1000 /certs/*.pem || echo "[WARN] chown failed (non-root?)" # Final check for f in ca.pem server.pem client.pem; do [ -f "/certs/$f" ] || { echo "[ERROR] Missing: $f"; exit 1; } done echo "[SUCCESS] Certificates generated for MongoDB." ``` Save the following YAML file to run with Docker Compose. It uses the [**Minimus minidebug image**](https://images.minimus.io/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host. ```yaml create-certs.yml theme={null} services: certgen: image: reg.mini.dev/minidebug:latest container_name: mongo_certgen volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: - /bin/sh - /certgen.sh network_mode: none ``` Run the following to generate the certificates: ```shellscript theme={null} docker compose -f create-certs.yml up ``` Congrats! You have just generated the following self-signed certificates: * CA certificate (`ca.pem`) * Server certificates (`server-cert.pem`, `server-key.pem`) * Client certificates (`client.pem`, `client-key.pem`) The setup ensures: * Proper SANs for `mongo` and `localhost` * Client certs with `clientAuth` * Server certs with `serverAuth` In the next steps, you will mount these certificates into the Mongo container. ### Step 2: Deploy Mongo server Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the Mongo service with a healthcheck, mounts a volume with the certificates, maps port 27017, and connects the container to a custom network. ```yaml docker-compose expandable theme={null} services: mongo: image: reg.mini.dev/mongo:latest container_name: mongo_tls healthcheck: test: ["CMD", "mongosh", "--tls", "--tlsCAFile", "/certs/ca.pem", "--tlsCertificateKeyFile", "/certs/server.pem", "--eval", "db.adminCommand('ping')"] interval: 5s timeout: 3s retries: 10 environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: rootpass MONGO_INITDB_DATABASE: testdb volumes: - ./certs:/certs:ro - mongo_data:/data/db ports: - "27017:27017" command: [ "mongod", "--auth", "--bind_ip_all", "--tlsMode", "requireTLS", "--tlsCertificateKeyFile", "/certs/server.pem", "--tlsCAFile", "/certs/ca.pem" ] volumes: mongo_data: ``` Start the Mongo container: ```shellscript theme={null} docker compose -f docker-compose.yml up ``` ### Step 3: Test your Mongo server We will use mongosh, the mongo shell, to connect over HTTPS and run tests. For example, here are a few commands you can try out: 1. Check db health ```bash theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --eval 'db.adminCommand("ping")' \ --password rootpass ``` You should get the response `{ ok: 1 }`. 2. Create a test database (for example `testdb`): ```shellscript Create database theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' const dbname = "testdb"; const testdb = db.getSiblingDB(dbname); const result = testdb.sample.insertOne({ createdAt: new Date(), msg: "Hello from mongosh over TLS" }); print("✅ Created database:", dbname); printjson(result); ' ``` ```bash Expected response theme={null} ✅ Created database: testdb { acknowledged: true, insertedId: ObjectId('6910880f1508c964cfb69764') } ``` 3. List all databases. ```bash List all databases theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' const res = db.adminCommand({ listDatabases: 1 }); printjson(res); ' ``` 4. Create document in `testdb.docs`: ```bash theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' const now = new Date().toISOString(); const res = db.getSiblingDB("testdb").docs.insertOne({ test: "Welcome to TLS MongoDB running on a Minimus image", timestamp: now }); printjson(res); ' ``` 5. Create a user (for example, `testuser` with `readWrite` role on `testdb`), get user details, and delete the user: ```bash Create user theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile certs/client.pem \ --password rootpass \ --eval ' printjson(db.getSiblingDB("admin").createUser({ user: "testuser", pwd: "testpass", roles: [ { role: "readWrite", db: "testdb" } ] })); ' ``` ```bash Get user details theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' printjson(db.getSiblingDB("admin").getUser("testuser")); ' ``` ```bash Delete user theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' printjson(db.getSiblingDB("admin").dropUser("testuser")); ' ``` 6. Insert a new document: ```bash Insert document theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' const dbname = "testdb"; const coll = db.getSiblingDB(dbname).docs; const doc = { test: "Welcome to TLS MongoDB running Minimus image", timestamp: new Date().toISOString() }; print("✅ Inserting document:"); printjson(doc); printjson(coll.insertOne(doc)); ' ``` 7. Get all documents in a collection: ```bash theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' const dbname = "testdb"; const coll = db.getSiblingDB(dbname).docs; print("📄 All documents in", dbname + ".docs:"); coll.find().forEach(doc => printjson(doc)); ' ``` 8. Delete a database: ```bash Drop database theme={null} mongosh "mongodb://root@localhost:27017/admin?authMechanism=SCRAM-SHA-256" \ --tls \ --tlsCAFile ./certs/ca.pem \ --tlsCertificateKeyFile ./certs/client.pem \ --password rootpass \ --eval ' const dbname = "testdb"; const res = db.getSiblingDB(dbname).dropDatabase(); print("🗑️ Dropped database:", dbname); printjson(res); ' ``` # MySQL TLS Tutorial Source: https://docs.minimus.io/advanced-guides/mysql-tls A guide to setting up MySQL and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client The following guide will help you deploy the Minimus MySQL image with self-signed, locally issued certificates to help you get started. Run the code to try it for yourself. For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA). ## Components * **MySQL image built by Minimus**: MySQL container configured with `--require_secure_transport=ON` for client authentication. * Dynamic certificate generation via OpenSSL: * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. ## What this guide demonstrates * TLS handshake validation * Server/client certificate trust * Basic auth and MySQL operations * Image compatibility ## Directory structure ```bash theme={null} . ├── certgen.sh # Certificate generation script ├── create-certs.yml # Compose file to run certgen container └── docker-compose.yml # Compose file to run MySQLDB ``` ## Deploy MySQL with TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host. It sets UID 1000 as the owner of the certificate files to match the default user of the MySQL process inside the container. ```bash certgen.sh expandable theme={null} #!/bin/sh # Company: Minimus set -e cd /certs echo "[INFO] Generating OpenSSL config..." cat > openssl.cnf < Save the following YAML file to run with Docker Compose. It uses the [**Minimus minidebug image**](https://images.minimus.io/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host. ```yaml create-certs.yml theme={null} services: certgen: image: reg.mini.dev/minidebug:latest container_name: MySQL_certgen volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: - /bin/sh - /certgen.sh network_mode: none ``` Run the following to generate the certificates: ```shellscript theme={null} docker compose -f create-certs.yml up ``` Congrats! You have just generated the following self-signed certificates: * Self-signed CA certificate (`ca.pem`) * Server certificates (`server-cert.pem`, `server-key.pem`, `server.csr`) * Client certificates for `testuser` (`client.csr`, `client.pem`, `client-cert.pem`, `client-key.pem`) Certificate permissions are adjusted to support non-root containers. In the next steps, we will mount these certificates into the MySQL container. ### Step 2: Deploy MySQL server Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the MySQL service with a healthcheck, mounts a volume with the certificates, maps port 3306, and connects the container to a custom network: ```yaml docker-compose.yml expandable theme={null} services: mysql: image: reg.mini.dev/mysql:latest container_name: mysql-1 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: testdb MYSQL_USER: testuser MYSQL_PASSWORD: testpass volumes: - ./certs:/certs:ro ports: - 3306:3306 healthcheck: test: - CMD - mysqladmin - ping - -ptestpass interval: 5s retries: 10 command: - --ssl-ca=/certs/ca.pem - --ssl-cert=/certs/server-cert.pem - --ssl-key=/certs/server-key.pem - --require_secure_transport=ON - --skip-name-resolve ``` Start the MySQL container: ```shellscript theme={null} docker compose -f docker-compose.yml up -d ``` ### Step 3: Test your MySQL server Following are a few commands you can try out: 1. Connect to the database: ```bash theme={null} mysql -h 127.0.0.1 -P 3306 -u root -p \ --ssl \ --ssl-ca=./certs/ca.pem \ --ssl-cert=./certs/client-cert.pem \ --ssl-key=./certs/client-key.pem ``` You should get a response from the server asking to input the password. If you used the compose file from this guide as is, the password is `rootpass`. 2. Create a test database (for example `my_new_db`): ```shellscript Create database theme={null} CREATE DATABASE my_new_db; ``` ```bash Expected response theme={null} MySQL [(none)]> CREATE DATABASE my_new_db; Query OK, 1 row affected (0.010 sec) ``` 3. List all databases: ```bash List all databases theme={null} SHOW DATABASES; ``` ```bash Example response theme={null} MySQL [(none)]> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | my_new_db | | mysql | | performance_schema | | sys | | testdb | +--------------------+ 6 rows in set (0.012 sec) ``` 4. Show server version: ```bash Show server version theme={null} SELECT version(); ``` ```bash Example output theme={null} MySQL [(none)]> SELECT version(); +-----------+ | version() | +-----------+ | 9.5.0 | +-----------+ 1 row in set (0.001 sec) ``` 5. Check that TLS is active: ```bash Check TLS theme={null} SHOW VARIABLES LIKE 'tls_version'; SHOW STATUS LIKE 'Ssl_version'; SHOW STATUS LIKE 'Ssl_cipher'; SHOW VARIABLES LIKE 'ssl_%'; ``` ```bash Example response theme={null} MySQL [(none)]> SHOW VARIABLES LIKE 'tls_version'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tls_version | TLSv1.2,TLSv1.3 | +---------------+-----------------+ 1 row in set (0.004 sec) MySQL [(none)]> SHOW STATUS LIKE 'Ssl_version'; +---------------+---------+ | Variable_name | Value | +---------------+---------+ | Ssl_version | TLSv1.3 | +---------------+---------+ 1 row in set (0.002 sec) MySQL [(none)]> SHOW STATUS LIKE 'Ssl_cipher'; +---------------+------------------------+ | Variable_name | Value | +---------------+------------------------+ | Ssl_cipher | TLS_AES_128_GCM_SHA256 | +---------------+------------------------+ 1 row in set (0.002 sec) MySQL [(none)]> SHOW VARIABLES LIKE 'ssl_%'; +---------------------------+------------------------+ | Variable_name | Value | +---------------------------+------------------------+ | ssl_ca | /certs/ca.pem | | ssl_capath | | | ssl_cert | /certs/server-cert.pem | | ssl_cipher | | | ssl_crl | | | ssl_crlpath | | | ssl_fips_mode | OFF | | ssl_key | /certs/server-key.pem | | ssl_session_cache_mode | ON | | ssl_session_cache_timeout | 300 | +---------------------------+------------------------+ 10 rows in set (0.003 sec) ``` Some server options and system variables were recently deprecated, including `--ssl`, `--skip-ssl`, and `--admin-ssl` server options, and the `have_ssl` and `have_openssl` system variables. [Learn more](https://dev.mysql.com/doc/relnotes/mysql/8.4/en/news-8-4-0.html) # Postgres TLS Tutorial Source: https://docs.minimus.io/advanced-guides/postgres-tls A guide to setting up Postgres and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client The following guide will help you deploy the Minimus Postgres image with self-signed, locally issued certificates to help you get started. Run the code to try it for yourself. For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA). ## Components * **Postgres image built by Minimus**: Postgres container configured with the secure configuration for client authentication. * **psql** installed * Dynamic certificate generation via OpenSSL: * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. ## What this guide demonstrates * TLS handshake validation * Server/client certificate trust * Basic auth and Postgres operations * Image compatibility ## Directory Structure ```bash theme={null} . ├── certgen.sh # Certificate generation script ├── create-certs.yml # Compose file to run certgen container ├── entrypoint.sh # Custom PostgreSQL entrypoint to set permissions ├── pg_hba.conf # Custom pg_hba config to require SSL and client certs └── docker-compose.yml # Compose file to run PostgresDB ``` ## Deploy Postgres with TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host. ```bash certgen.sh expandable theme={null} #!/bin/sh # Company: Minimus # Author: Alexander Haytovich set -e cd /certs echo "[INFO] Creating OpenSSL config for server..." cat > openssl.cnf < client_openssl.cnf < Save the following YAML file to run with Docker Compose. It uses the [**Minimus minidebug image**](https://images.minimus.io/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host. ```yaml create-certs.yml theme={null} services: create_certs: image: reg.mini.dev/minidebug:latest container_name: create_certs volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: - /bin/sh - /certgen.sh network_mode: none ``` Run the following to generate the certificates: ```shellscript theme={null} docker compose -f create-certs.yml up ``` Congrats! You have just generated the following self-signed certificates: * Self-signed CA certificate (`ca.pem`) * Server certificates (`server-cert.pem`, `server-key.pem`) with SANs: `postgres`, `localhost`, `127.0.0.1`, and `192.168.30.3` * Client certificates for `testuser`(`client.pem`, `client-key.pem`) Client private key permissions are set to `0600` and owned by UID `1000`. Certificate permissions are adjusted to support non-root containers. In the next steps, you will mount these certificates into the Postgres container. ### Step 2: Deploy Postgres server ```bash entrypoint.sh theme={null} #!/bin/bash set -e # Fix ownership so postgres can use the private key echo "[INFO] Fixing ownership and permissions of /certs..." chown postgres:postgres /certs/server-key.pem echo "[INFO] Fixing file permissions..." # Restrict private key access chmod 600 /certs/server-key.pem echo "[INFO] Launching PostgreSQL..." exec docker-entrypoint.sh "$@" ``` Make sure the entrypoint script is executable on your host. If necessary, give it execute permissions: ```bash Give file execute permissions theme={null} chmod +x ./entrypoint.sh ``` ```bash Verify execute permissions theme={null} ls -l ./entrypoint.sh ``` PostgreSQL’s default access rules are defined in the file `pg_hba.conf`. Save the following configuration to mount it and customize the Host-Based Authentication rules. ```bash pg_hba.conf theme={null} # Allow local socket connections without SSL (for internal psql commands) local all all trust # Allow readonly_user to connect using password over SSL hostssl all readonly_user 0.0.0.0/0 scram-sha-256 # Allow remote SSL connections with client cert validation hostssl all all 0.0.0.0/0 cert clientcert=verify-full ``` Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the Postgres service with a healthcheck, mounts a volume with the certificates, the custom entrypoint and the custom HBA config, and maps port 5432. ```yaml docker-compose.yml expandable theme={null} services: postgres: image: reg.mini.dev/postgres container_name: pg_ssl environment: POSTGRES_USER: testuser POSTGRES_PASSWORD: testpass POSTGRES_DB: testdb volumes: - pgdata:/var/lib/postgresql/data - ./certs:/certs - ./entrypoint.sh:/entrypoint.sh:ro - ./pg_hba.conf:/etc/postgresql/pg_hba.conf ports: - 5432:5432 healthcheck: test: - CMD - pg_isready - -U - testuser - -d - testdb interval: 5s retries: 10 entrypoint: - /entrypoint.sh command: "postgres\n -c ssl=on\n -c ssl_cert_file=/certs/server-cert.pem\n \ \ -c ssl_key_file=/certs/server-key.pem\n -c ssl_ca_file=/certs/ca.pem\n -c\ \ hba_file=/etc/postgresql/pg_hba.conf\n" volumes: pgdata: null ``` Start the Postgres container: ```shellscript theme={null} docker compose -f docker-compose.yml up ``` ### Step 3: Test your Postgres server You can use psql to connect over TLS and run tests. For example, here are a few commands you can try out: 1. Connect to the db: ```bash Connect to DB theme={null} psql "host=127.0.0.1 \ port=5432 \ dbname=testdb \ user=testuser \ sslmode=verify-ca \ sslrootcert=./certs/ca.pem \ sslcert=./certs/client-cert.pem \ sslkey=./certs/client-key.pem" ``` ```bash Expected response theme={null} psql (15.14 (Debian 15.14-0+deb12u1), server 18.0) WARNING: psql major version 15, server major version 18. Some psql features might not work. SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) Type "help" for help. testdb=# ``` 2. Show all schemas in current database: ```shellscript Create database theme={null} \dn ``` ```bash Example response theme={null} testdb=# \dn List of schemas Name | Owner --------+------------------- public | pg_database_owner (1 row) ``` 3. Show server version: ```bash Show server version theme={null} SELECT version(); ``` ```bash Example response theme={null} ---------------------------------------------------------------------------------------------------------------- PostgreSQL 18.0 on x86_64-pc-linux-gnu, compiled by x86_64-pc-linux-gnu-gcc (MinimOS 15.2.0-r1) 15.2.0, 64-bit (1 row) ``` 4. Check that TLS is active: ```bash Check TLS theme={null} SHOW ssl; SHOW ssl_cert_file; SHOW ssl_key_file; ``` # RabbitMQ TLS Tutorial Source: https://docs.minimus.io/advanced-guides/rabbitmq-tls A guide to setting up RabbitMQ and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client The following guide deploys the Minimus RabbitMQ image together with custom self-signed, locally issued certificates generated with OpenSSL to help you get started. The tutorial is appropriate for local development, internal services, and private clusters. ## What this guide demonstrates * TLS handshake validation * Server certificate trust * Basic auth and RabbitMQ DB operations * Image compatibility ### Components * **RabbitMQ image built by Minimus**: RabbitMQ configured for TLS on both the AMQP port (5671) and the management API port (15671). * **certgen.sh script**: Dynamic certificate generation shell script that uses OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. ### Directory Structure ```bash theme={null} . ├── certgen.sh # Certificate generation script ├── create-certs.yml # Compose file to run certgen container ├── certs/ # Generated certificates (created by certgen.sh) │ ├── ca_certificate.pem │ ├── server_certificate.pem │ └── server_key.pem ├── rabbitmq.conf # RabbitMQ config file for TLS ├── enabled_plugins # Enables the management plugin └── docker-compose.yml # Compose file to run RabbitMQ ``` ### 2 TLS listeners for 2 trust models This setup configures two independent TLS listeners, each with a different trust requirement: * **AMQP (`5671`)** — This is the protocol port your messaging clients connect to. `ssl_options.verify = verify_none` means the server presents its certificate for the client to trust, but never asks the client for one back. Hence, no client certificate is required. * **Management API (`15671`)** — This is used by `rabbitmqadmin`, `curl`, and the management UI. `management.ssl.verify = verify_peer` means the server will validate a client certificate if one is presented, but `fail_if_no_peer_cert = false` makes presenting one optional. For local development and testing, server-side trust is sufficient: the CA certificate alone (`--cacert` / `--ssl-ca-cert-file`) is all a client needs to establish the TLS connections, so this guide skips generating a client certificate. If you later move this setup toward a multi-tenant or zero-trust environment, you can require client certificates on either listener by switching `fail_if_no_peer_cert` to `true`. ## Deploy RabbitMQ with TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the self-signed CA and server certificates and store them in a `certs` folder in a Docker volume. ```bash certgen.sh expandable lines theme={null} #!/bin/sh set -e cd /certs cat > openssl.cnf < Save the following YAML configuration to a file named `create-certs.yml`. The configuration uses the [**Minimus minidebug image**](https://images.minimus.io/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. ```yaml create-certs.yml theme={null} services: create_certs: image: reg.mini.dev/minidebug:latest container_name: rabbit_certs volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: - /bin/sh - /certgen.sh network_mode: none ``` Run the following to generate the certificates: ```shellscript Run command theme={null} docker compose -f create-certs.yml up ``` ```shellscript Expected output theme={null} WARN[0000] No services to build [+] up 1/1 ✔ Container rabbit_certs Created 0.2s Attaching to rabbit_certs rabbit_certs | Certificate request self-signature ok rabbit_certs | subject=CN=rabbitmq rabbit_certs exited with code 0 ``` Congrats! You have just generated the following self-signed certificates: * CA certificate (`ca_certificate.pem`) * Server certificate and key (`server_certificate.pem`, `server_key.pem`) valid for `rabbitmq`, `localhost`, `127.0.0.1`, `192.168.20.0`, `192.168.20.2`, and `192.168.20.3` The setup ensures: * Proper SANs for `rabbitmq` and `localhost` * Server cert with both `serverAuth` and `clientAuth` extended key usage In the next steps, you will mount these certificates into the RabbitMQ container. ### Step 2: Deploy RabbitMQ server Save the configuration to a file named `rabbitmq.conf`. ```bash rabbitmq.conf theme={null} ## AMQP TLS listener listeners.ssl.default = 5671 ssl_options.cacertfile = /certs/ca_certificate.pem ssl_options.certfile = /certs/server_certificate.pem ssl_options.keyfile = /certs/server_key.pem ssl_options.verify = verify_none ssl_options.fail_if_no_peer_cert = false ## Allow remote login for non-guest users loopback_users.guest = false ## Management API over HTTPS management.ssl.port = 15671 management.ssl.cacertfile = /certs/ca_certificate.pem management.ssl.certfile = /certs/server_certificate.pem management.ssl.keyfile = /certs/server_key.pem management.ssl.verify = verify_peer management.ssl.fail_if_no_peer_cert = false ``` Save the enabled plugins file. ```bash enabled_plugins theme={null} [rabbitmq_management]. ``` Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the RabbitMQ service with a healthcheck, mounts a volume with the certificates, maps ports 15671 and 5671. ```yaml docker-compose.yml expandable theme={null} services: rabbitmq: image: reg.mini.dev/rabbitmq:latest-dev container_name: rabbitmq-lts volumes: - ./certs:/certs:ro - ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro - ./enabled_plugins:/etc/rabbitmq/enabled_plugins:ro environment: RABBITMQ_DEFAULT_USER: testuser RABBITMQ_DEFAULT_PASS: testpass ports: - "5671:5671" # AMQP over TLS - "15671:15671" # Management UI over TLS ``` Start the RabbitMQ container: ```text Run command theme={null} docker compose -f docker-compose.yml up -d ``` ```shellscript Expected output theme={null} ✔ Image reg.mini.dev/rabbitmq:latest-dev Pulled 15.1s ... ✔ Network rabbitmq-test_default Created 0.1s ✔ Container rabbitmq-lts Created ``` ### Step 3: Test your RabbitMQ server We will use `rabbitmqadmin`, the RabbitMQ CLI, to connect over TLS and run tests. For example, here are a few commands you can try out: 1. Check db health: ```bash Check status theme={null} docker exec -it rabbitmq-lts rabbitmqctl status curl -u testuser:testpass https://localhost:15671/api/healthchecks/node \ --cacert ./certs/ca_certificate.pem ``` ```yaml Expected output theme={null} Runtime OS PID: 13 OS: Linux Uptime (seconds): 356 Is under maintenance?: false RabbitMQ version: ... RabbitMQ release series support status: see https://www.rabbitmq.com/release-information Node name: rabbit@... Erlang configuration: ... Crypto library: OpenSSL ... Erlang processes: 411 used, 1048576 limit Scheduler run queue: 1 Cluster heartbeat timeout (net_ticktime): 60 Plugins Enabled plugin file: /etc/rabbitmq/enabled_plugins Enabled plugins: * rabbitmq_management * rabbitmq_management_agent * rabbitmq_web_dispatch * amqp_client * cowboy * oauth2_client ... Listeners Interface: [::], port: 15671, protocol: https, purpose: HTTP API over TLS (HTTPS) Interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication Interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0 Interface: [::], port: 5671, protocol: amqp/ssl, purpose: AMQP 0-9-1 and AMQP 1.0 over TLS ``` 2. Verify the AMQP TLS listener itself (port `5671`) with `openssl s_client`. This confirms the handshake and certificate the broker presents to actual messaging clients, independent of the management API tested in the next step: ```bash Check AMQP TLS handshake theme={null} echo | openssl s_client -connect localhost:5671 -CAfile ./certs/ca_certificate.pem ``` ```text Expected output theme={null} CONNECTED(00000003) depth=1 CN = Test CA verify return:1 depth=0 CN = rabbitmq verify return:1 --- Certificate chain 0 s:CN = rabbitmq i:CN = Test CA 1 s:CN = Test CA i:CN = Test CA --- ... subject=CN = rabbitmq issuer=CN = Test CA --- Verification: OK --- New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 ... Verify return code: 0 (ok) --- DONE ``` `openssl s_client` runs on your host machine, not inside the container, so the verify result depends on the OpenSSL build installed there. You may see either `Verify return code: 0 (ok)` or `19 (self-signed certificate in certificate chain)` — both mean the handshake succeeded using the certificate signed by your CA. Messaging client libraries (`pika`, `amqplib`, etc.) that trust the CA connect the same way regardless. 3. Test connectivity using `rabbitmqadmin`. Note that `rabbitmqadmin` talks to the management HTTP API, so it connects on port `15671` (the TLS management port), not the AMQP port `5671`: ```bash Test connectivity theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ list queues ``` ```text Expected output theme={null} No items ``` 4. Create a test vhost (for example `test_vhost`). A vhost is RabbitMQ's equivalent of a database — a logically separate group of queues, exchanges, and permissions: ```bash Create vhost theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ declare vhost name=test_vhost ``` ```bash Expected response theme={null} vhost declared ``` 5. List all vhosts. ```bash List all vhosts theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ list vhosts ``` ```text Expected output theme={null} +------------+----------+ | name | messages | +------------+----------+ | / | | | test_vhost | | +------------+----------+ ``` 6. Declare a durable queue named `docs` in `test_vhost` (the equivalent of creating a collection): ```bash theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ --vhost=test_vhost \ declare queue name=docs durable=true ``` Then publish a message to it: ```bash theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ --vhost=test_vhost \ publish exchange=amq.default routing_key=docs payload="Welcome to TLS RabbitMQ running on a Minimus image" ``` 7. Create a user (for example, `appuser` with read/write/configure permissions on `test_vhost`), get the user's permission details, and delete the user: ```bash Create user theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ declare user name=appuser password=apppass tags=management rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ declare permission vhost=test_vhost user=appuser configure=.* write=.* read=.* ``` ```bash Get user details theme={null} docker exec -it rabbitmq-lts rabbitmqctl list_user_permissions appuser ``` ```text Expected output theme={null} Listing permissions for user "appuser" ... vhost configure write read test_vhost .* .* .* ``` ```bash Delete user theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ delete user name=appuser ``` 8. Publish a new message to the queue: ```bash Publish message theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ --vhost=test_vhost \ publish exchange=amq.default routing_key=docs payload="Welcome to TLS RabbitMQ running Minimus image" ``` ```bash Expected response theme={null} Message published ``` 9. Get all messages from the queue: ```bash theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ --vhost=test_vhost \ get queue=docs count=10 ackmode=ack_requeue_false ``` 10. Delete the vhost: ```bash Delete vhost theme={null} rabbitmqadmin \ --host=localhost \ --port=15671 \ --username=testuser \ --password=testpass \ --ssl \ --ssl-ca-cert-file=./certs/ca_certificate.pem \ delete vhost name=test_vhost ``` ```bash Expected response theme={null} vhost deleted ``` # Redis TLS Tutorial Source: https://docs.minimus.io/advanced-guides/redis-tls A guide to setting up Redis and testing that it accepts TLS connections, enforces authentication, and allows secure read/write operations from a test client The following guide will help you deploy the Minimus Redis image with self-signed, locally issued certificates to help you get started. Run the code to try it for yourself. For production purposes, we recommend using publicly trusted certificates issued by a Certificate Authority (CA). ## Components * **Redis image built by Minimus**: Redis container configured to require secure connections via TLS. * Dynamic certificate generation via OpenSSL: * **certgen.sh script**: Shell script that generates a custom CA, server, and client certificates using OpenSSL. * **minidebug image**: A Minimus dev toolkit that provides a shell, OpenSSL, and other utilities used to generate the certificates. ## What this guide demonstrates * TLS handshake validation * Server/client certificate trust * Basic auth and Redis operations * Image compatibility ## Directory structure ```bash theme={null} . ├── certgen.sh # Certificate generation script ├── create-certs.yml # Compose file to run certgen container └── docker-compose.yml # Compose file to run Redis ``` ## Deploy Redis with TLS certificates ### Step 1: Generate TLS certificates Save the following script to a file named `certgen.sh`. The script is used to generate the TLS certificates and store them in a `certs` folder on the host. ```bash certgen.sh expandable theme={null} #!/bin/sh set -e cd /certs cat > openssl.cnf < Save the following YAML file to run with Docker Compose. It uses the [**Minimus minidebug image**](https://images.minimus.io/images/minidebug/quick-start?__hstc=180987128.11065ee83c8bdcec1851176c12d849d3.1762436227738.1762436227738.1762436227738.1&__hssc=180987128.1.1762436227739&__hsfp=2666866004) to generate the certificates with the `certgen.sh` shell script. Minidebug is a Minimus dev toolkit that provides a shell, OpenSSL, and other utilities. The certificates will be persisted in the `certs` volume on the host. ```yaml create-certs.yml theme={null} services: certgen: image: reg.mini.dev/minidebug:latest container_name: redis_certgen volumes: - ./certs:/certs - ./certgen.sh:/certgen.sh:ro entrypoint: ["/bin/sh", "/certgen.sh"] ``` Run the following to generate the certificates: ```shellscript theme={null} docker compose -f create-certs.yml up ``` Congrats! You have just generated the following self-signed certificates: * Self-signed CA certificate (`ca.pem`) * Server certificates (`server-cert.pem`, `server-key.pem`) with SANs: `Redis`, `localhost`, and `192.168.20.3` * Client certificates for `testuser`(`client.csr`, `client-key.pem`) Certificate permissions are adjusted to support non-root containers. In the next steps, you will mount these certificates into the Redis container. ### Step 2: Deploy Redis server Save the following Docker Compose script to a file named `docker-compose.yml`. This script sets up the Redis service with a healthcheck, mounts a volume with the certificates, and maps port 6379. The container is configured with `"--tls-auth-clients", "yes"` to require client certificates. ```yaml docker-compose.yml expandable theme={null} services: redis: image: reg.mini.dev/redis:latest command: [ "redis-server", "--tls-port", "6379", "--port", "0", "--tls-cert-file", "/certs/server-cert.pem", "--tls-key-file", "/certs/server-key.pem", "--tls-ca-cert-file", "/certs/ca.pem", "--requirepass", "testpass", "--tls-auth-clients", "yes" ] volumes: - ./certs:/certs:ro ports: - "6379:6379" ``` Start the Redis container: ```shellscript theme={null} docker compose -f docker-compose.yml up ``` ### Step 3: Test your Redis server We will use redis-cli to connect over TLS and run tests. For example, here are a few commands you can try out: 1. Check server info and health: ```bash Check info over TLS theme={null} redis-cli \ -h 127.0.0.1 \ -p 6379 \ --tls \ --cacert ./certs/ca.pem \ --cert ./certs/client-cert.pem \ --key ./certs/client-key.pem \ -a testpass \ info ``` ```bash Expected response theme={null} Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Server redis_version:8.2.3 redis_git_sha1:ceb01e15 redis_git_dirty:1 redis_build_id:7fe6dd1915e7cd11 redis_mode:standalone os:Linux 6.1.0-29-cloud-amd64 x86_64 arch_bits:64 monotonic_clock:POSIX clock_gettime multiplexing_api:epoll atomicvar_api:c11-builtin gcc_version:15.2.0 process_id:1 ... ``` 2. Add test key to a database: ```bash Set key theme={null} redis-cli \ -h 127.0.0.1 \ -p 6379 \ --tls \ --cacert ./certs/ca.pem \ --cert ./certs/client-cert.pem \ --key ./certs/client-key.pem \ -a testpass \ -n 1 \ set mykey "Hello from Minimus" ``` ```bash Expected response theme={null} Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK ``` Redis has numbered logical databases (default 0–15) rather than named databases. Verify the key: ```bash Verify key theme={null} redis-cli \ -h 127.0.0.1 \ -p 6379 \ --tls \ --cacert ./certs/ca.pem \ --cert ./certs/client-cert.pem \ --key ./certs/client-key.pem \ -a testpass \ -n 1 \ get mykey ``` ```bash Expected response theme={null} Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. "Hello from Minimus" ``` 3. Test data persistence: ```bash Save data theme={null} redis-cli \ -h 127.0.0.1 \ -p 6379 \ --tls \ --cacert ./certs/ca.pem \ --cert ./certs/client-cert.pem \ --key ./certs/client-key.pem \ -a testpass \ save ``` Stop the container, then restart it: ```bash theme={null} docker ps docker stop {Redis container ID} docker restart {Redis container ID} ``` Check the key you added in the previous step: ```bash Get key theme={null} redis-cli \ -h 127.0.0.1 \ -p 6379 \ --tls \ --cacert ./certs/ca.pem \ --cert ./certs/client-cert.pem \ --key ./certs/client-key.pem \ -a testpass \ -n 1 \ get mykey ``` 4. Delete the key: ```bash Delete key theme={null} redis-cli \ -h 127.0.0.1 \ -p 6379 \ --tls \ --cacert ./certs/ca.pem \ --cert ./certs/client-cert.pem \ --key ./certs/client-key.pem \ -a testpass \ -n 1 \ del mykey ``` # Hardening Compiler Flags for C/C++ Source: https://docs.minimus.io/basics/compiler-options Understand how Minimus implements OpenSSF hardening recommendations for compiling packages dependent on GCC and Clang Minimus images are built for security. One of the ways Minimus increases security is by compiling its packages using stricter compiler flags that mitigate some of the risks associated with compiled binaries. Hardening compiler flags help to ensure the packages are better protected against common memory safety issues. Many Minimus images are built using C/C++ components such as GCC (GNU Compiler Collection) and Clang. The hardening compiler flags ensure that apps built with Minimus images produce the most secure binaries (executables) and protect against potential attacks from memory-unsafe code. See the [OpenSSF guide](https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++) for an extended discussion and in-depth reasoning about the recommended compiler flags for C/C++ sources. ## Understanding the risk Many common packages written in the C and C++ programming languages are prone to memory safety errors, including stack-based buffer overflow, heap corruption, dereferencing a null pointer, and use-after-free errors. Memory errors are known to be a leading source for vulnerabilities. An OpenSSF report found that 70% of vulnerabilities identified by the Chrome and Microsoft teams were attributed to memory safety failures. If exploited, memory errors can allow threat actors to gain unauthorized access through runtime attacks. Hardening compiler flags are enabled in order to protect packages from such vulnerabilities and increase the overall protection of Minimus images. ## Summary of OpenSSF recommendations * OpenSSF recommends that certain flags are always turned on to detect vulnerabilities at compile time and enable runtime protection mechanisms. For example: `-Wall -Wformat`\ `-fstack-clash-protection -fstack-protector-strong -Wl`. [For the full list, refer to the OpenSSF guide](https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++#tldr-what-compiler-options-should-i-use). * The flag `-fhardened` is used for GCC v14.0.0 or newer to enable a pre-determined set of hardening options in GCC. * Production code should specifically be protected by certain flags, including: `-fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -ftrivial-auto-var-init=zero`. * To protect against obsolete C constructs, the following flags are used: `-Werror=implicit -Werror=incompatible-pointer-types -Werror=int-conversion`. * OpenSSF also lists several scenario dependent flags that should be enabled as relevant. Minimus implements these flags as applicable. For example, the flag `-fcf-protection=full` is used for x86\_64 builds and `-mbranch-protection=standard` is used for amd64. ## Deeper look into specific examples Following are a few examples of flags recommended by OpenSSF and the reasoning for enabling them: * Minimus uses the compiler flags `-fstack-protector-strong` and `-fcf-protection=full` flags to mitigate against stack-based buffer overflow vulnerabilities and prevent attackers from running malicious code. * The flag `-D_FORTIFY_SOURCE=3` is used to protect against unsafe memory usage. * The flag `-fstack-clash-protection` enables runtime checks for variable-size stack allocation validity to prevent stack clash attacks and stack pointer manipulation, where attackers overwrite adjacent memory regions such as the heap, memory-mapped files, or guard pages. * The flags `-fstack-protector-strong`, `-fstack-protector-all`, and `-fstack-protector --param=ssp-buffer-size=` enable runtime checks for stack-based buffer overflows. These flags mitigate stack smashing attacks and potential control-flow hijacking attacks that may lead to arbitrary code execution. ## What this means for the security of apps built with Minimus images All images offered by Minimus are built using the most stringent compiler flags to ensure that the internal packages are hardened, secure, and more resistant to attacks than upstream project sources. # Image Entrypoint Source: https://docs.minimus.io/basics/entrypoint About image entrypoints in Minimus and how to work with them The image's `ENTRYPOINT` specifies the container's default executable. Many Minimus images use a different entrypoint from what is commonly found in their Docker Hub alternatives. Where relevant, the entrypoint was modified to enhance security and/or to enforce an EXEC-form entrypoint, which is more secure than a shell entrypoint. For example, a Minimus Node image will start up in node rather than in a shell script. This is true for both the dev and non-dev variants of the Minimus Node image. Minimus modified the entrypoint in the production (non-dev) Node.js image because it doesn't include a shell. To guarantee compatibility and maintain consistency between the two image variants, the development Node image's entrypoint is aligned and shares the same entrypoint instruction. ```json Minimus Node Image theme={null} "Entrypoint": [ "/usr/bin/node" ], "Cmd": [ "--help" ], ``` ```json Public Node Image theme={null} "Entrypoint": [ "docker-entrypoint.sh" ], "Cmd": [ "node" ], ``` As a result, you may need to adjust your code when migrating to Minimus images to handle the entrypoint modifications. ## Example: How to adapt to the Minimus entrypoint Changes in the entrypoint will often dictate changes to the starting command. For example, the Minimus Node image starts directly as a node interpreter (`/usr/bin/node` entrypoint) rather than starting in a subshell. This has a direct impact on the `CMD` instruction. If you were previously using an image with a `sh` entrypoint, your CMD instruction needed to explicitly invoke node: ``` CMD ["node", "myProgram.js"] ``` But this won't work with the Minimus Node image. If you try to build and run your Node app using the Minimus Node image without changing the command, you will probably encounter this error: ``` Error: Cannot find module '/app/node' at Function._resolveFilename (node:internal/modules/cjs/loader:1249:15) ... at node:internal/main/run_main_module:36:49 { code: 'MODULE_NOT_FOUND' } ``` To fix the error, you need to drop the redundant node invocation. Since the entrypoint is already set to execute the command using Node.js, you only need to provide the script name in the CMD. ``` CMD ["myProgram.js"] ``` After the change, your Node app should run as expected. ## Why Exec-form entrypoints are more secure There are two types of entrypoints: exec-form and shell-form. The exec form entrypoint is considered more secure because it ensures that the container can stop, restart, and handle interruptions more smoothly. The security advantage of an exec form entrypoint stems from the concept of PID1. The first process started during system boot is named PID1. According to the process tree model, PID1 is known as the parent process or init process. It is responsible for starting and managing all processes inside the container. PID1 is also responsible for handling signals from the Docker host. An exec form entrypoint ensures that the first command runs directly as PID1 without involving a shell. This allows it to receive and handle signals directly from the host. Beyond the obvious risk of shell injection vulnerabilities, a shell form entrypoint results in a shell process becoming PID1. The shell process doesn't always handle signals from the Docker host properly, which can potentially lead to unclean shutdowns of the container. For example, if the Docker `SIGTERM` signal for graceful shutdown is received by a shell instead of the intended process, the results may be unpredictable. Using a shell-form entrypoint should therefore be avoided on principle. You may want to verify the PID1 for yourself, especially if you were previously working in a default subshell and want to better understand how the EXEC entrypoint is different. #### `docker top` Most Minimus images don't include the `ps` utility so instead you can run `docker top` from the host to check the processes running inside a container. The first process in the output corresponds to PID 1. ``` docker top {container-name} ``` The process IDs (PIDs) you see in `docker top` are the host's PID numbers for the container processes so they will be high. The same processes have different, lower PIDs inside the container (starting with 1 for the `init` process). #### `docker inspect --format='{{.State.Pid}}'` You can run `docker inspect` to print the PID of the init process (PID 1) for a container: ``` docker inspect --format='{{.State.Pid}}' {container name or ID} ``` Example of the output: ``` UID PID PPID C STIME TTY TIME CMD ubuntu 434767 434743 0 Jan23 ? 00:00:02 /usr/bin/node server.js ``` ## Adapting to Minimus image entrypoints The Minimus Image Gallery lists the default entrypoint for each image directly in the UI under the **details tab** to help with the migration. If you prefer, you can also run `docker inspect {image}` to look up the entrypoint and CMD instruction directly in the CLI. ## Working with exec form entrypoints Exec form entrypoints are written as a JSON array, with the terms wrapped in double-quotes (") and square brackets. Exec form is also known as vector form. For example: ```Dockerfile theme={null} ENTRYPOINT ["executable", "param1", "param2"] ``` Exec form entrypoints can be combined with the CMD instruction to specify default commands. [Learn more from Docker](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) ``` ENTRYPOINT ["echo", "Hello"] CMD ["World!"] ``` ### Overriding entrypoints You can override the container entrypoint at runtime by passing a new entrypoint to the container. Add the `--entrypoint` flag to the docker run command to replace the default entrypoint specified in the Dockerfile. For example, you can start a dev container in a subshell: ``` docker run -it --entrypoint /bin/bash {.../reg.mini.dev/nginx:1.26-dev} ``` ### Overriding default arguments An exec form entrypoint can be combined with the CMD instruction to provide default arguments. You can supply ad-hoc arguments at runtime to override the defaults in the Dockerfile. Add the arguments after the image name in the docker run command. For example: ``` docker run -v "$(pwd)":/app -w {go image} run main.go ``` ### Empty vector You can disable the default entrypoint by specifying an empty vector. Alternatively, if the default entrypoint is an empty vector, a CMD command can be added in vector form. ```bash docker run theme={null} docker run --entrypoint "" my-image sh # overrides the entrypoint and starts a shell ``` ```bash docker compose theme={null} services: my-container: image: my-image entrypoint: [] # Empty vector disables any predefined entrypoint command: ["sh"] # Custom command ``` ```bash Dockerfile theme={null} ENTRYPOINT [] CMD ["echo", "Hello World!"] ``` # glibc Source: https://docs.minimus.io/basics/glibc Why Minimus uses glibc over musl and how it benefits security, DNS resolution, and compatibility Minimus, like most popular Linux distributions, uses GNU C Library [glibc](https://www.gnu.org/software/libc/) as its standard C library. This places Minimus alongside many mainstream distros, including Ubuntu, Debian, Fedora, RHEL, CentOS, and others. The use of glibc is not entirely universal but it has its advantages, as explained below. In contrast, Google's Distroless images and Alpine Linux use [musl](https://musl.libc.org/) as the C library, instead of glibc. Both glibc and musl are implementations of the standard C library, but glibc is substantially more predictable and easier to work with. While musl is said to be more lightweight, its tradeoffs are heavy. Here's why Minimus favors glibc: ## 1. Security awareness glibc has more sanity checks and is generally considered more secure and less prone to exploitation. For example, glibc has built-in stack smashing to protect against buffer overflows, whereas musl will allow vulnerable programs to run without warning. ## 2. DNS resolution By design, musl doesn't support DNS-over-TCP. This alone is responsible for many Alpine DNS issues including host resolution failures. The DNS resolution failure is only manifest in Kubernetes, not a Docker container. This means everything will work as expected when you test locally, so you'll only discover the issue once you deploy the application to a cluster. ## 3. Compatibility Compatibility issues are significantly reduced with glibc, compared with musl. For example, glibc supports Node.js by default, dynamic-linking, and multithreading. As a result, images using glibc are more portable and will work on a greater range of hardware and environments. ## 4. Performance While musl does show a slight advantage in compilation time, glibc shows significantly shorter build times, especially with Python. ## 5. Memory usage Runtime performance for glibc is far superior to musl. The advantage is particularly prominent when large memory allocations are required. glibc is the library of choice for memory-intensive applications and will greatly reduce the risk of performance issues. # Public Package Access Source: https://docs.minimus.io/basics/package-manager-access Install Minimus packages directly in Minimus images using a package manager to experiment with options and extend images Installing packages in Minimus images is a great way to customize them on the fly for your exact requirements. ## Prerequisites When installing packages, make sure to use Minimus containers that meet both conditions: 1. Can run `apk` commands - Minimus `dev` images fit the bill 2. Run as root - usually this is not the default in Minimus images so you'll need to [switch to a root user](/basics/user#switch-users-in-the-dockerfile) Keep in mind that Minimus production images are usually not a good fit because they are distroless. This means they don't include the necessary packages. You can always check the image's [SBOM](/foundations/image-card) to be sure. ### Install packages during runtime (inside a running container) 1. Run a Minimus docker container as root and make sure the container includes `apk`. For example, you can run the Bash image with the `latest-dev` tag: ```shellscript theme={null} docker run -it -u root reg.mini.dev/bash:latest-dev ``` 2. Add packages as usual. For example, you can add `git`: ```text theme={null} apk add --no-cache git ``` Since Minimus images point `/etc/apk/repositories` at `packages.mini.dev/os` by default, there's no need to explicitly point at the MinimOS package repository. This is an example of redundant code that isn't recommended: ```text theme={null} apk add --no-cache --repository=https://packages.mini.dev/os git ``` ### In a Dockerfile You can install MinimOS packages directly within your Dockerfile during the image build. Since the MinimOS package repository is open to all, there is no need to pass credentials unless you require them. Below is an example of the code to be added to your Dockerfile: ```dockerfile Dockerfile code snippet that installs MinimOS public packages theme={null} ... USER root # Update APK and install packages RUN apk update && \ apk add --no-cache \ \ ... ``` For example, you might add the following code to your Dockerfile to install curl and jq: ```text filename highlight={1} theme={null} FROM reg.mini.dev/python:3.13 RUN apk add --no-cache curl jq ``` ## Python tutorial example (multi-stage build) The following example builds on the multi-stage pattern from the Minimus [Python guide](/guides/python). We will follow the steps in the original guide, replacing only the Dockerfile and build command. The Dockerfile uses a `latest-dev` builder for package installation and Python dependencies and switches to the minimal Python image at runtime. ```python Dockerfile with apk add steps theme={null} # === Build Stage === FROM reg.mini.dev/python:latest-dev AS builder WORKDIR /app # Install system packages from the MinimOS package repository USER root RUN apk update && \ apk add --no-cache \ build-base \ libffi-dev RUN python -m venv /app/venv ENV PATH="/app/venv/bin:$PATH" COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # === Runtime Stage === FROM reg.mini.dev/python:latest WORKDIR /app COPY main.py . COPY --from=builder /app/venv /app/venv ENV PATH="/app/venv/bin:$PATH" ENTRYPOINT ["python", "main.py"] ``` Note that all `apk` commands stay in the `latest-dev` build stage and are executed as `USER root` to avoid `Unable to lock database: Permission denied`. The runtime image `reg.mini.dev/python:latest` is distroless and does not include `/bin/sh`, so `RUN apk ...` is not supported there. Run the build command as usual: ```shellscript build command theme={null} docker compose build ``` # Tags & Digests Source: https://docs.minimus.io/basics/tags-and-digests Understand the differences between image tags and digests and know when each are recommended An image is identified by its name, tags and digest. An image reference takes the following format: `image:tag@sha256:{digestValue}`. For example, `python:3.14.4@sha256:98706f040021993a82d2f70451a73698315370ae8615cc468ac0f213dbd46624` As a security expert, it is important to understand the differences between the image tags and image digest and know when each of them are recommended. ## Image version tag Image version tags describe the software version. For example, the Python image version 3.14.4 contains the package for [Python v3.14.4](https://www.python.org/downloads/release/python-3144/) with other required packages. Similarly, the Postgres image version 18.3 contains the package for Postgres v18.3 with other required packages and so forth. Image version tags help you determine what software you are currently running and whether you should pull a new version when it becomes available. Note that image tags are **mutable**, meaning that the same tag can point to a different image build at different times. That is, an image can be built several times yet always assigned the same tag. In that sense, the image version tag does not guarantee that the code hasn't changed. ### Major and minor version tags Minimus organizes each image by image lines and versions within each line. The latest version will often carry several tags, as shown below. | Python Version | Tags | | -------------- | ----------------------- | | 3.14.4 | latest, 3.14.4, 3.14, 3 | | 3.14.3 | 3.14.3 | | 3.14.2 | 3.14.2 | In the above example, the tags `python:3`, `python:3.14`, and `python:3.14.4` all resolve to the exact same image. However, as new versions are released, these tags behave differently: * `3.14.4` is locked permanently to this exact version. * `3.14` automatically updates to future patches (e.g., `3.14.5`), but stops before `3.15.0`. * `3` automatically updates to all future minor and patch releases within Python 3, but will not point to Python 4. This behavior allows users the flexibility to balance stability with freshness. You can lock into a specific release line or use a broader tag to inherit patches automatically. ## Image digest An image digest is the SHA-256 hash of the image manifest - a JSON document detailing the configuration objects, file system layers, and other optional metadata of an image build. The digest is automatically generated at build time and is unique to every build. If you build the exact same image twice, each build will produce a different digest. With the image digest, you enjoy the certainty that it will always point to the same exact image in the registry. In other words, the image digest is **immutable**. The image digest is the most reliable identifier of any image. Unlike image tags, the digest is fixed and always points to the same exact image, guaranteed. On the flip side, the image digest can be cumbersome to work with. Pulling an image by digest isn't practical or common but it is important to scan by image digest. ### Look up the digest In the Minimus console, all the digests created for a specific version are listed in the Changelog and the Digest History tabs. To look up an image digest in your CLI, run: ```text look up digest theme={null} docker images --digests # Look up all digests # Look up digest for specific image docker images --digests {image path} ``` ```text example output theme={null} docker images --digests reg.mini.dev/rabbitmq REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE reg.mini.dev/rabbitmq latest-dev sha256:0b9ac999b1017ba494e0f00043d8cdb9eec38b4f642b3f3b70dba3d3f63e655c ``` ### Look up *by* digest In the Minimus console, you can search the Changelog by digest (or a fragment of the digest). The result will be returned with the relevant change information and a direct link to compare the available digests for the version. Changelog Search By Digest ## Comparing digests to tags The image digest is immutable, meaning that it does not change over time and will always point to the same image build. If you know the image digest, you have a way to identify a particular image with certainty. The exact image identified by the digest is fixed and does not change over time. When it comes to security scans and SBOM attestations, it is important to rely on the image digest. In contrast, the image tag describes the software version. Whenever an update is released under the same image tag, the tag starts pointing to the newest build, but without a clear indication that the build has changed. Hence, the image tag does not necessarily provide a clear indication of changes and can be misleading. Image tags are useful when the focus is on the software version when pulling and building, but are not recommended for scanning. Minimus offers a hybrid option known as the **unique timestamp tag**. The unique timestamp tag is assigned during image build time, and it is immutable. Essentially the timestamp tag functions like the image digest. ## Considerations Pulling images requires balancing compatibility and stability concerns with the ability to automate updates as much as possible. There is a wide array of approaches: * Pulling the most up-to-date version by the `latest` tag prioritizes security over stability. It is a common approach in development and testing environments, but certainly has its drawbacks when it comes to production environments. * Pulling by the image version (e.g. `reg.mini.dev/nginx:1.27`) using the version line tag offers a balanced approach. It offers some compatibility control without requiring the team to update deployment artifacts for every image update. * Pulling by digest is the most conservative approach. It guarantees reproducibility but comes at the cost of convenience. This approach requires weekly if not daily updates, following every image security update. # Default User Source: https://docs.minimus.io/basics/user Why Minimus containers usually default to an unprivileged user and how to work around user permissions Running as root has many security disadvantages so it's best avoided. Whenever possible, Minimus images default to a non-root user in keeping with the principle of least privilege. Minimus images will only default to root if there are constraints that require it. In contrast, many popular open source images default to root even when it isn't required, so you may need to adjust to the change by changing directory permissions, etc. ## Why default to an unprivileged user To help protect against privilege abuse, Minimus images are built to default to an unprivileged user. Defaulting to an unprivileged user helps to limit what processes inside the container can do, preventing them from accessing sensitive files or performing privileged operations. Minimus images will only default to root when required due to technical constraints. Running processes as the root user (UID 0) can lead to security concerns if an attacker gains control over the container. Once attackers gain root privileges inside the container, they can potentially gain access to the host system as well. Therefore, running processes as unprivileged users is key to minimizing the attack surface on the container. The Linux kernel on the host is responsible for managing the UID and GID space, with kernel-level syscalls determining requested privileges. For example, when a process attempts to write to a file, the UID and GID that created the process are examined by the kernel to determine if it has enough privileges to modify the file. Because the user privileges for all of the containers are controlled by a single kernel, you can’t have different privileges for the same UID/GID inside different containers. ## Adapt to the default user in Minimus images The Minimus Image Gallery lists the default user for each image directly in the UI under the **details tab** to help with the migration. If you prefer, you can also run `docker inspect {image}` to look up the default user directly in the CLI. You can override the default user or change directory permissions as necessary. ### Switch users in the Dockerfile Most Minimus images default to a non-root user (often UID `1000`) so they will be limited by their default user permissions. It will be necessary to escalate privileges temporarily before installing packages, changing ownership (`chown`), modifying protected paths, creating directories in some filesystem locations, etc. Afterwards, privileges can be dropped back down to the container's non-root default user. [Learn more about Minimus compatibility defaults](/introduction/compatibility) It is common to switch users in the Dockerfile as part of the build process. For example, see the quick start guide for [dotnet-aspnet](https://images.minimus.io/images/dotnet-aspnet/quick-start). The build stage switches to root to perform privileged setup and create the application directory and assign ownership to user UID 1000 so the non-root default user can write to it later. ```Dockerfile example with user changes expandable theme={null} # -------- Build Stage -------- FROM reg.mini.dev/dotnet-sdk:latest AS build USER root RUN mkdir -p /dotnetapp && chown -R 1000:1000 /dotnetapp USER 1000 WORKDIR /dotnetapp COPY --link --chown=1000:1000 ./dotnetapp.csproj . COPY --link --chown=1000:1000 ./Program.cs . RUN dotnet publish --no-self-contained -c Release -o /dotnetapp/dist # -------- Runtime Stage -------- FROM reg.mini.dev/dotnet-aspnet:latest WORKDIR /dotnetapp # Copy the published app from the build stage COPY --from=build /dotnetapp/dist . # Set the container’s entrypoint to run the web app CMD ["dotnetapp.dll"] ``` ### Override the default user to run as root Minimus images usually default to a non-privileged user, so you will need to explicitly run the image as root to perform tasks that require elevated privileges, such as debugging, especially when diagnosing issues related to permissions, file access, or network configurations. You can use the `--user root` flag to run the container as root. For example, run an nginx container as root to bind it to port 80. (Running a service on a port below 1024 or binding to privileged ports requires elevated privileges.) ``` docker run --user root -p 80:80 reg.mini.dev/nginx ``` ### Change directory permissions When working with Minimus images, you'll frequently want to bind a volume to persist data on the host. However, since the container isn't running as root, you may run into permission issues. The simplest solution is to change the user permissions for the target host directory. For example, the Elasticsearch process runs as UID 1000 by default. If you try to mount a volume, you need to change the permissions to give the target host directory read and write permissions (where `/target/path` represents your directory): ``` sudo chown -R 1000:1000 /target/path sudo chmod -R 775 /target/path ``` * `1000:1000` refers to the default UID (User ID) and GID (Group ID) for the Elasticsearch process. * The command `sudo chown -R 1000:1000 /target/path` gives the process ownership of the directory and its subdirectories. (The `-R` flag is for recursive). * The command `sudo chmod -R 775 /target/path` sets the permissions for the directory and its content, giving the Elasticsearch user and group read and write permissions. Once the directory permissions are granted for the process, the directory can be mounted. In Elasticsearch, the run command might look like this: ``` docker run -it --name minimus-elasticsearch-example \ -p 9200:9200 \ -e "discovery.type=single-node" \ -v /target/path:/usr/share/elasticsearch/data \ reg.mini.dev/elasticsearch ``` This command will run the container and mount the target directory to the default Elasticsearch path to persist the data, so it's not lost when the container exits. # FIPS 140-3 Cryptography Source: https://docs.minimus.io/compliance/fips About FIPS 140-3 validated Minimus images, kernel independence, FIPS validation, and more FIPS 140-3 Color Logo ## Overview FIPS, short for the [Federal Information Processing Standards](https://www.nist.gov/itl/publications-0/federal-information-processing-standards-fips), is a federal cryptography compliance framework. FIPS validated cryptography is required by FedRAMP and is mandatory for non-military federal government agencies, contractors, and vendors. It is often voluntarily adopted by private sector companies. ## CMVP certifications FIPS 140-3 validation ensures that cryptographic security services in applications adhere to rigorous standards for security and integrity and that they are correctly implemented. Validation is regulated by the NIST Cryptographic Module Validation Program (CMVP) which certifies cryptographic modules that meet FIPS 140‑3 security standards. Modules are tested by a certified lab for proper implementation of encryption algorithms, secure key management, and tamper resistance. CMVP certification provides assurance that the module adheres to recognized NIST cryptographic security requirements. Minimus FIPS validated images use FIPS 140-3 cryptographic modules with the following certificates: * [**Certificate #5177**](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5177) - Minimus Cryptographic Module (OpenSSL FIPS 140-3 provider) * [**Certificate #E241**](https://csrc.nist.gov/projects/cryptographic-module-validation-program/entropy-validations/certificate/241) - OpenSSL-compatible entropy provider (CryptoComply Entropy Provider) * [**Certificate #5142**](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5142) - Minimus Cryptographic Module for Java * [**Certificate #5104**](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5104) - BoringCrypto module Each certificate lists the testing lab, validation history, approved algorithms, sunset date, and a link to a full security policy with additional implementation details. The exact modules included in each image depend on the image and technology. ## Minimus FIPS validated images Minimus FIPS images utilize only FIPS-validated cryptographic modules as listed above and are configured to enforce approved algorithms and communication protocols. The FIPS packages used in a Minimus image are listed in the SBOM in the [image version card](/foundations/image-version). Minimus FIPS images can be divided into 3 groups: * C-based images using OpenSSL and an OpenSSL-compatible entropy provider * Go-based images using OpenSSL and an OpenSSL-compatible entropy provider * Java-based images using SafeLogic CryptoComply FIPS Provider (CCJ) as the primary FIPS 140-3 validated provider and Bouncy Castle JSSE as the TLS/SSL provider that delegates to CCJ ### FIPS module packages in the SBOM The relevant FIPS packages listed in the SBOM depend on which FIPS modules are present in the image. For example, the SBOM of an image using the OpenSSL FIPS module such as nginx-fips would list the following packages: * minimus-cryptographic-module * openssl-fips-config (FIPS-relevant configuration files located in `/etc/ssl/`) * openssl-fips-test (a tool for validating that the FIPS provider is correctly configured) ## More about Minimus FIPS images * [About the FIPS entropy provider](/compliance/fips-entropy-provider) * [OpenSSL FIPS module](/compliance/fips-images) * [Java FIPS module](/compliance/java-fips) * [OpenSSL FIPS validations](/compliance/fips-validations) * [Tutorial for Keycloak FIPS](/advanced-guides/keycloak-fips) # OpenSSL FIPS Entropy Provider Source: https://docs.minimus.io/compliance/fips-entropy-provider Understand why the OpenSSL FIPS validated module is hardware agnostic FIPS approved cryptography requires a strong entropy source to provide cryptographic protection using NIST-trusted algorithms. The entropy source is responsible for providing secure random bit generators whose output cannot be predicted and without it FIPS cryptography standards cannot be satisfied. ## What is a kernel independent FIPS module Generally, there are two approaches to providing a FIPS validated entropy source: The entropy source may depend on specialized hardware with a certified kernel configured in FIPS mode, or it may be kernel-independent, with no hardware dependencies. This is termed a **kernel-independent** FIPS entropy source. * Kernel-independent FIPS validated images can run on any standard hardware. A self-contained FIPS 140-3 validated cryptographic module eliminates cryptographic dependency on underlying OS kernel, hypervisor, and hardware. A kernel-independent FIPS module relies on a **userspace entropy source** so it does not need to run on a host with a certified FIPS-enabled kernel. * In contrast, kernel-dependent FIPS images must be run on specialized hardware approved by the NIST CMVP program with kernel-level FIPS mode enabled. In other words, the kernel must be configured in FIPS mode. This approach is highly dependent on the underlying operating system and other environment configurations. ## OpenSSL FIPS 140-3 module Minimus FIPS images that rely on OpenSSL come with an OpenSSL-compatible entropy provider that is kernel independent. These images have been certified by the NIST CMVP program and are approved to run on any hardware with confidence that they comply with FIPS security standards, regardless of the underlying OS kernel, hypervisor, and hardware. The OpenSSL FIPS validated module is used in many Minimus FIPS images including, C-based and Go-based images as well as Python, Node.js, PHP, and other language ecosystems. ## Is my app FIPS 140-3 compliant? Minimus FIPS validated images undergo testing and validation by an independent laboratory according to the CMVP. This validation ensures a certain level of security assurance and compliance with a set of NIST cryptographic standards. Importantly, this validation is independent of the underlying operating system, hypervisor, and hardware. The CMVP certificate specifies the operational environment in which the cryptographic module was tested and any external dependencies, such as a validated entropy source.  As a user of the FIPS validated image, you are responsible to ensure the FIPS-validated cryptographic module is used with the correct configuration that meets CMVP requirements and tested by an independent laboratory. Since all cryptographic operations occur within a FIPS 140-validated cryptographic module in the image and have no direct cryptographic dependency on the host OS, hypervisor, or hardware, this has been tested and validated by the cryptographic module developer under various operational environments captured in the associated CMVP certificate or asserted by the cryptographic module developer for the module bundled and configured properly in the image. When it comes to non-dev images, including applications, utilities, infra, etc., you can rely on the Minimus FIPS validated image to deliver compliance. The image is already pre-configured with the necessary protections to prevent non-FIPS approved algorithms and protocols. ## Do I need FIPS-certified hardware? No special hardware is required for Minimus FIPS images that rely on the OpenSSL FIPS module. This has the advantage of greatly lowering costs in cloud environments. These images can run in any environment, including local developer machines, existing CI/CD pipelines, and standard managed cloud services. | Requirements | Minimus OpenSSL FIPS module | | :----------------------------- | :-------------------------- | | Hardware requirements | None, any host kernel | | Cloud environment requirements | None, any cloud environment | | Entropy source | Userspace entropy | ## Requesting FIPS 140-3 assistance Particularly with Java FIPS images, compliance depends on the underlying OS, hypervisor, and hardware to also be correctly configured in FIPS mode. There is a risk that some lower layer in the stack or a malicious admin could alter the settings such that the image or application would not run in FIPS mode. Please get in touch with us directly if you would like to request guidance with FIPS related issues. [Contact us directly](https://support.minimus.io/support/home) ### References: FIPS 140-3 entropy requirements FIPS compliance depends on an entropy source for secure key generation. Acceptable entropy sources and seeding behavior is detailed in the following: * [NIST publication FIPS 140-3: Security Requirements for Cryptographic Modules](https://csrc.nist.gov/publications/detail/fips/140/3/final) * NIST SP 800-90 Series * SP 800-90A: [Recommendation for Random Number Generation Using Deterministic Random Bit Generators](https://csrc.nist.gov/pubs/sp/800/90/a/r1/final)\ Details DRBG types, seeding methods, and reseeding requirements. * SP 800-90B: [Recommendation for the Entropy Sources Used for Random Bit Generation](https://csrc.nist.gov/publications/detail/sp/800-90b/final)\ Considered to be the most detailed source for acceptable entropy sources under FIPS requirements. * SP 800-90C: [Recommendation for Random Bit Generator (RBG) Constructions](https://csrc.nist.gov/publications/detail/sp/800-90c/final)\ Discusses how to combine entropy sources and DRBGs in FIPS-compliant ways. # OpenSSL FIPS Validated Module Source: https://docs.minimus.io/compliance/fips-images Understand how Minimus implements the OpenSSL FIPS 140-3 module Minimus FIPS images are built from the ground up to ensure that all cryptographic operations use modules that are certified by the **NIST Cryptographic Module Validation Program (CMVP)**. This article explains how Minimus builds FIPS-validated images with the OpenSSL FIPS 140-3 module and why you can trust these images to meet strict compliance requirements. ## The foundation The module uses two key FIPS components: * **fips.so** – The FIPS 140-3 validated module. * **cryptocomply-entropy.so** – The entropy provider, ensuring high-quality randomness without relying on hardware or kernel-specific entropy sources. The modules were independently tested by certified labs and hold the NIST CMVP certificates [certificate 5177](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5177) and [entropy certificate #E241](https://csrc.nist.gov/projects/cryptographic-module-validation-program/entropy-validations/certificate/241) providing the compliance baseline. Since these images include a kernel-independent entropy-provider, they are portable across environments and do not require specialized hardware to run. [Learn more](/compliance/fips-entropy-provider) ## C-based images C-based images include nginx, Redis, MySQL and more. The `minimus-cryptographic-module` provides the necessary components to make these images FIPS-validated. About this module: * Includes Minimus FIPS components: `fips.so`, `cryptocomply-entropy.so` * Versioned to track changes * Marked as PROPRIETARY in the SBOM * Declares a dependency on `openssl-dev` since the modules require OpenSSL libraries at runtime In addition, the image also includes the `openssl-fips-config` subpackage. This subpackage holds all FIPS-relevant configuration files, including: * `openssl.cnf` – the OpenSSL configuration tuned for FIPS mode. * `cryptocomply-entropy.cnf` – to enable the Minimus entropy provider. * `fipsmodule.cnf` – module configuration. The `openssl-fips-config` package has a runtime dependency on the `minimus-cryptographic-module`, ensuring both packages are used together. OpenSSL is configured to use `fips.so` as the provider for all cryptographic operations. This ensures that configuration and validated binaries are always deployed together. ## Go-based images Go-based images include Datadog, Istio-Pilot, Grafana, Loki, Promtail, Prometheus and more. To be FIPS-validated, they must circumvent and block the native BoringCrypto module normally used by Go. Minimus Go-based images ensure that Go applications inherit the same validated cryptographic boundary by directing Go’s crypto to OpenSSL (the Minimus FIPS provider) instead of the native BoringCrypto. Minimus provides a dedicated toolchain that produces Go-based apps in the following manner: * Source & Versioning Minimus builds `go-fips` from the community project at [microsoft/go toolchain](https://github.com/microsoft/go) starting with go version 1.25.x. (Version 1.24.x has reached its end-of-life, and was built from [golang-fips/go project](https://github.com/golang-fips/go).) The images are built by cloning the matching Go release and applying the repo’s patches. The patches re-route Go’s standard-library crypto (e.g., `crypto/tls`, `crypto/x509`, `crypto/aes`, etc.) to use OpenSSL through CGO, replacing calls that would otherwise use the native BoringCrypto path. * Minimus applies an additional patch to force Go applications built with go-fips to always operate in FIPS mode. This ensures that cryptographic operations use the validated OpenSSL provider by default, regardless of whether the underlying host system is itself configured for FIPS. ### How Minimus enforces FIPS at runtime in Go-based images The `minimus-cryptographic-module` together with the `openssl-fips-config` package ensure that the module always operates with the right FIPS configuration. The `openssl-fips-config` package does the following: * Activates the FIPS provider `fips.so` and the entropy provider `cryptocomply-entropy.so` by default. * Sets FIPS-only defaults (`default_properties = fips=yes`) so applications cannot silently fall back to non-FIPS algorithms. * Restricts TLS key exchange to NIST-approved curves (`secp256r1:secp384r1:secp521r1`) and sources entropy via `cryptocomply-entropy.so` (`CRYPTOCOMPLY-ENTROPY-SEED-SRC`) for kernel-independent, portable FIPS operation. ### How to ship a FIPS-validated Go app with Minimus tooling 1. Build your Go code with the Minimus image [go-fips](https://images.minimus.io/images/go-fips/quick-start) so your app’s crypto uses a FIPS 140-3 validated OpenSSL module rather than the native BoringCrypto. 2. Run the app on a Minimus FIPS-validated runtime image (for example [glibc-dynamic-fips](https://images.minimus.io/images/glibc-dynamic-fips/quick-start)). The runtime must include the `openssl-fips-config` package and the Minimus entropy provider module. Together, the combination of go-fips, `openssl-fips-config` and the Minimus entropy provider `cryptocomply-entropy.so` ensures that your Go app operates inside the CMVP-validated cryptographic boundary. # Custom FIPS Testing Source: https://docs.minimus.io/compliance/fips-testing How to test your private images for FIPS compliance Starting from a Minimus FIPS-validated image is a great way to create a private image. However, it does not guarantee that the resulting image remains FIPS-validated. Only testing can confirm this. ## FIPS cryptography must be enforced To be FIPS-compliant, the image must use cryptographic modules that conform to the FIPS 140-3 requirements, ensuring that all encryption, decryption, hashing, and digital signing operations meet strict security standards. A FIPS image must be restricted to use only approved algorithms (such as AES, SHA-256, or RSA with approved key lengths), manage cryptographic keys securely, and rely on a CMVP-validated cryptographic boundary. Furthermore, the image must enforce proper configuration of the relevant modules to prevent weak or unauthorized cryptographic operations and ensure that all non-compliant cryptography is disabled. When you add packages to a FIPS-validated image, you run the risk of introducing conflicts that could potentially undermine, override, or undo FIPS configurations. For example, Go (golang) has a default cryptographic module BoringCrypto that must be disabled and replaced with the FIPS-validated Minimus Cryptographic Module. If you introduce a Go package into another FIPS-validated starter image, you will undermine the FIPS module. ## OpenSSL FIPS integrity tests Testing a standard Minimus image for FIPS is fairly straightforward. You run the pre-configured command to test that the OpenSSL FIPS provider module is configured on the image. However, when you use FIPS validated images to compile and build an application, it can be trickier to validate FIPS compatibility. The simplest approach is proof by contrapositive - showing that if an image is not FIPS validated it will not run. ## Example for testing a custom FIPS image In this example, we will invalidate the `openssl-fips` module and attempt to run the app. 1. Delete a file to modify the module-mac portion of the FIPS provider to invalidate it: ``` sudo rm /etc/ssl/fipsmodule.cnf ``` 2. Try to re-run the application server: ``` go/bin/helloserver ``` We expect the app to abort because it does not satisfy the OpenSSL FIPS provider requirements. 3. The app should not run with the following error: ``` panic: opensslcrypto: can't enable FIPS mode for OpenSSL 3.4.0 22 Oct 2024: OSSL_PROVIDER_try_load openssl error(s): error:1C8000D4:Provider routines::invalid state providers/fips/self_test.c:262 ``` 4. Any software that uses OpenSSL should exit as `segfault` (segmentation fault). A segmentation fault is a failure condition raised by hardware with memory protection, notifying an operating system that the software has attempted to access a restricted area of memory. \ \ Examples include `apk update`. 5. Restore the fipsmodule.cnf file to fix the problem. The image should run as expected. # OpenSSL FIPS Verifications Source: https://docs.minimus.io/compliance/fips-validations Run a script to examine the ciphers in your Minimus FIPS image and verify the OpenSSL FIPS module ## Examine ciphers First run the FIPS container so it is listening to a port for an SSL connection. To view the ciphers used by the container, run the following from the host: ``` # update {port} with the port exposed by the image nmap -sV --script ssl-enum-ciphers -p {port} localhost ``` The response should print the ciphers and their version. For example: ``` PORT STATE SERVICE VERSION 9443/tcp open ssl/http nginx 1.27.4 |_http-server-header: nginx/1.27.4 | ssl-enum-ciphers: | TLSv1.2: | ciphers: | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_128_CCM (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CCM (secp256r1) - A | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A | compressors: | NULL | cipher preference: client |_ least strength: A ``` ## FIPS module verification To test that the OpenSSL FIPS provider module is configured, you will need to run the container as root and override the entrypoint at runtime. For example, for the Minimus FIPS NGINX image, the run command looks like this: ``` docker run -it --rm \ --user root --entrypoint openssl-fips-test \ reg.mini.dev/nginx-fips ``` The test results will print to the terminal for you to review. For example: ``` Checking OpenSSL lifecycle assurance. ✓ Self-test KAT_Integrity HMAC_Verify, 256 ... passed. ✓ Self-test KAT_Module_Integrity HMAC_Verify, 256, Module Integrity ... passed. ✓ Self-test KAT_Cipher AES_GCM_Encrypt, 256 ... passed. ✓ Self-test KAT_Cipher AES_GCM_Decrypt, 256 ... passed. ✓ Self-test KAT_Cipher AES_ECB_Decrypt, 256 ... passed. ✓ Self-test KAT_Cipher TDES_Decrypt, CBC ... passed. ✓ Self-test KAT_DRBG CTR, 128 ... passed. ✓ Self-test KAT_DRBG HASH, SHA-256 ... passed. ✓ Self-test KAT_DRBG HMAC, SHA-1 ... passed. ✓ Self-test KAT_KDF X942KDF, SHA-1 ... passed. ✓ Self-test KAT_KDF X963KDF, SHA-256 ... passed. ✓ Self-test KAT_KDF SSHKDF, SHA-1 ... passed. ✓ Self-test KAT_KDF TLS12_PRF, SHA-256 ... passed. ✓ Self-test KAT_KDF TLS13_KDF_EXTRACT, SHA-256 ... passed. ✓ Self-test KAT_KDF TLS13_KDF_EXPAND, SHA-256 ... passed. ✓ Self-test Continuous_RNG_Test RNG ... passed. ✓ Self-test KAT_Signature DSA_Verify, SHA-256 ... passed. ✓ Self-test KAT_Signature ECDSA_Prime_Sign, P-224 ... passed. ✓ Self-test KAT_Signature ECDSA_Prime_Verify, P-224 ... passed. ✓ Self-test KAT_Signature ECDSA_Binary_Sign, K-233 ... passed. ✓ Self-test KAT_Signature ECDSA_Binary_Verify, K-233 ... passed. ✓ Self-test KAT_Signature ECDSA_Brainpool_Sign, Brainpool ... passed. ✓ Self-test KAT_Signature ECDSA_Brainpool_Verify, Brainpool ... passed. ✓ Self-test Conditional_PCT ED448 ... passed. ✓ Self-test KAT_Signature EDDSA_Sign, Ed448 ... passed. ✓ Self-test Conditional_PCT ED448 ... passed. ✓ Self-test KAT_Signature EDDSA_Verify, Ed448 ... passed. ✓ Self-test Conditional_PCT ED25519 ... passed. ✓ Self-test KAT_Signature EDDSA_Sign, Ed25519 ... passed. ✓ Self-test Conditional_PCT ED25519 ... passed. ✓ Self-test KAT_Signature EDDSA_Verify, Ed25519 ... passed. ✓ Self-test Conditional_PCT RSA ... passed. ✓ Self-test KAT_Signature RSA_Sign, SHA-256 ... passed. ✓ Self-test Conditional_PCT RSA ... passed. ✓ Self-test KAT_Signature RSA_Verify, SHA-256 ... passed. ✓ Self-test KAT_KA KAS-ECC-SSC, P-256 ... passed. ✓ Self-test Conditional_PCT DH ... passed. ✓ Self-test KAT_KA KAS-FFC-SSC, FB (2048, 224) ... passed. ✓ Self-test KAT_KDF KDA HKDF, SHA-256 ... passed. ✓ Self-test KAT_KDF KDA OneStep, SHA-224 ... passed. ✓ Self-test KAT_KDF KBKDF, HMAC SHA-256 ... passed. ✓ Self-test KAT_KDF PBKDF2, SHA-256 ... passed. ✓ Self-test KAT_AsymmetricCipher KTS_RSA_Encrypt, KTS-OAEP 2048bit ... passed. ✓ Self-test Conditional_PCT RSA ... passed. ✓ Self-test KAT_AsymmetricCipher KTS_RSA_Decrypt, KTS-OAEP 2048bit ... passed. ✓ Self-test Conditional_PCT RSA ... passed. ✓ Self-test KAT_AsymmetricCipher KTS_RSA_Decrypt, CRT 2048bit ... passed. ✓ Self-test KAT_KEM KAS_RSA_SSC, 2048bit ... passed. ✓ Self-test KAT_Digest SHA3, 256 ... passed. ✓ Self-test KAT_Digest SHA2, 512 ... passed. ✓ Self-test KAT_Digest SHA1, SHA-1 ... passed. ✓ 51 out of 51 self-tests passed. ✓ Check FIPS cryptographic module is available... passed. ✓ Check FIPS approved only mode (EVP_default_properties_is_fips_enabled)... passed. ✓ Check non-approved algorithm blocked (HMAC-MD5)... passed. Digests available for non-security use as per FIPS 140-3 I.G. 2.4.A (fips=no): ✓ MD5 ✓ SHA1 Available approved algorithms for security purposes (fips=yes): ✗ MD5 ✓ SHA-1 ✓ SHA-2 ✓ SHA-3 ✓ DSA ✓ RSA ✓ ECDSA ✓ Ed25519 ✗ DetECDSA ✗ ML-DSA ✗ SLH-DSA ✗ ML-KEM ✗ X25519MLKEM768 ✗ SecP256r1MLKEM768 Public OpenSSL API (libssl.so & libcrypto.so): name: OpenSSL 3.5.4 30 Sep 2025 version: 3.5.4 FIPS cryptographic module provider details (fips.so): name: 140-3 FIPS Provider version: 3.0.0-FIPS 140-3 build: 3.0.0-FIPS 140-3 Locate applicable CMVP certificate(s) at: CMVP Search ``` # Compliance Source: https://docs.minimus.io/compliance/image-compliance How to verify that your Minimus container images meet security, licensing, and regulatory requirements ## CIS Review a summary report detailing how the image complies with the [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker). For every relevant CIS ID, the image status shows if the image passed along with a note explaining the decision. Minimus CIS Report ## NIST Review a summary report detailing how the image complies with the [NIST-800-190 Section 3.1 Benchmark](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf). For every relevant NIST ID, the image status shows if the image passed along with a note explaining the decision. Minimus NIST Report ## FIPS Minimus offers many FIPS validated images built with the Minimus Cryptographic Module to comply with the [FIPS 140-3 standard](https://csrc.nist.gov/pubs/fips/140-3/final). For FIPS validated images, run the command provided to test the module. The command overrides the default entrypoint to run a built-in `openssl-fips-test`. Minimus FIPS Report ## STIG Minimus images that are FIPS validated are also STIG compliant. Switch to the STIG tab to preview the STIG Evaluation Report. Download the HTML report to drill down on the full details. [Learn more](/compliance/stig) STIG stands for Security Technical Implementation Guides (STIGs). STIGs are published by DISA, the Defense Information Systems Agency of the U.S. Department of Defense (DoD). Minimus STIG Report ## Image Signature The image signature tab provides the commands for verifying the `latest` and `latest-dev` images with Cosign. See our [**verification guide**](https://docs.minimus.io/integrity/verify) for additional information about verification with Cosign. ## SBOM Signature The SBOM signature tab provides the commands for verifying the SBOM attestation for the `latest` image with Cosign. The Cosign command uses an architecture-specific digest ID and is provided for amd64 and arm64. SBOM Signature # Java FIPS Validated Module Source: https://docs.minimus.io/compliance/java-fips Understand how Minimus implements the FIPS 140-3 validated Java module in its images including OpenJDK, OpenJRE, and Amazon-Corretto ## What FIPS means for Java FIPS (Federal Information Processing Standards) 140-3 is a federal cryptography compliance framework. FIPS validated cryptography is required by FedRAMP and is mandatory for non-military federal government agencies, contractors, and vendors. Validation is regulated by the NIST Cryptographic Module Validation Program (CMVP), which certifies cryptographic modules that meet FIPS 140-3 security standards. Standard OpenJDK ships with built-in cryptographic providers (`SunJCE`, `SunJSSE`, `SunRsaSign`, `SunEC`) that have not been through the CMVP validation process. To be FIPS-compliant, every cryptographic operation (encryption, hashing, key generation, TLS) must go through a CMVP-certified provider. ### FIPS 140-3 certificate Minimus Java FIPS images use the **Minimus Cryptographic Module for Java** module, validated under [CMVP **certificate #5142**](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5142). This certificate covers the CCJ Provider and defines the approved algorithms, operational environments, and hardware requirements under which the module is validated. ## Available Java FIPS images Minimus provides the following Java FIPS validated images: | **Image** | **Base** | Description | **Use** | | --------------------------------------- | --------------- | --------------------------------- | ----------------------- | | `reg.mini.dev/openjdk-fips` | Eclipse Temurin | OpenJDK Development Kit (JDK) | Build and compile stage | | `reg.mini.dev/openjre-fips` | Eclipse Temurin | OpenJDK Runtime Environment (JRE) | Production runtime | | `reg.mini.dev/amazon-corretto-jdk-fips` | Amazon Corretto | Amazon Corretto JDK | Build and compile stage | | `reg.mini.dev/amazon-corretto-jre-fips` | Amazon Corretto | Amazon Corretto JRE | Production runtime | ## Supported Java versions Supported Java versions: **26, 25, 21, 17, 8**. Java 24 and 11 have reached end-of-life but are available. ## Cryptographic providers Minimus Java FIPS images are configured with the following security providers, in priority order: | **Position** | **Provider** | **Role** | | ------------ | ---------------------------------------------------- | ---------------------------------------------------------------------- | | 1 | SafeLogic CryptoComply (CCJ) | Primary FIPS 140-3 validated provider for all cryptographic operations | | 2 | Bouncy Castle JSSE (BCJSSE) | FIPS-compliant TLS/SSL — delegates all crypto to CCJ | | 3 | SUN | Loaded at lowest priority for CCJ JAR signature validation only | | 4+ | SunJGSS, SunSASL, XMLDSig, SunPCSC, JdkLDAP, JdkSASL | Infrastructure providers delegate crypto operations to CCJ/BCJSSE | The following providers are explicitly removed from the image and are not available at runtime: `SunRsaSign`, `SunEC`, `SunJCE`, `SunJSSE`. ### FIPS 140-3 libraries The CryptoComply and SafeLogic Bouncy Castle jars are located at `/usr/share/fips-libs/` inside the image: | **JAR** | **Purpose** | | --------------------- | ------------------------------------------------ | | `ccj-4.0.0-fips.jar` | SafeLogic CryptoComply FIPS 140-3 provider (CCJ) | | `sl-bcutil-2.0.3.jar` | SafeLogic Bouncy Castle utilities | | `sl-bctls-2.0.21.jar` | SafeLogic Bouncy Castle TLS/SSL (JSSE) | | `sl-bcpkix-2.0.8.jar` | SafeLogic Bouncy Castle PKIX/X.509 | | `sl-bcmail-2.0.5.jar` | SafeLogic Bouncy Castle S/MIME | | `sl-bcpg-2.0.12.jar` | SafeLogic Bouncy Castle OpenPGP | ### What FIPS blocks at runtime FIPS approved-only mode (`com.safelogic.cryptocomply.fips.approved_only=true`) enforces a hard algorithm blocklist. Your application will throw a `NoSuchAlgorithmException` or `GeneralSecurityException` at runtime, not at compile time if it calls any of the following: | **Blocked** | **FIPS-approved replacement** | | ------------------------------- | ------------------------------------ | | MD5 (for any security purpose) | SHA-256 or SHA-3 | | SHA-1 signatures | SHA-256 or stronger | | DES / 3DES | AES-128 or AES-256 | | RC4 | AES-GCM | | TLS 1.0 / TLS 1.1 | TLS 1.2 or TLS 1.3 | | RSA or DH keys under 2048 bits | RSA-2048 minimum, RSA-3072 preferred | | PKCS#12 for private key storage | BCFKS keystore format | Audit your codebase to search for string literals like "MD5", "SHA1", "DES", "RC4", "TLSv1", and "PKCS12" in any `getInstance()` or `KeyStore.getInstance()` calls. ## Security configuration The images enforce FIPS 140-3 compliance through: * **Approved-only mode**: `com.safelogic.cryptocomply.fips.approved_only=true` * **Non-FIPS providers disabled**: SunRsaSign, SunEC, SunJCE, and SunJSSE are omitted * **FIPS-approved algorithms only**: Non-FIPS algorithms are blocked (e.g., MD5) * **BCFKS keystore type**: Required for private keys (Bouncy Castle FIPS KeyStore is a FIPS-compliant keystore format) * **Trust store types**: JKS, PKCS12, and BCFKS supported for truststores ## Environment variables Minimus Java FIPS images set the following environment variables by default: * `JAVA_HOME`: Points to the default JVM installation * `CLASSPATH`: Includes FIPS libraries from `/usr/share/fips-libs/*` * `JAVA_FIPS_CLASSPATH`: Explicit FIPS classpath reference * `JDK_JAVA_OPTIONS`: Includes the required exports and FIPS trust store configuration: ```text theme={null} --add-exports=java.base/sun.security.internal.spec=ALL-UNNAMED --add-exports=java.base/sun.security.provider=ALL-UNNAMED -Djavax.net.ssl.trustStoreType=FIPS ``` ## Verifying the Java FIPS 140-3 module Each Java FIPS image includes automated tests that verify: 1. **Java version** - Confirms that the correct Java version is installed 2. **FIPS provider availability** - Verifies that SafeLogic CryptoComply and Bouncy Castle JSSE providers are loaded 3. **Provider priority** - Ensures providers are in the correct order (CCJ at position 1, BCJSSE at position 2) 4. **FIPS-approved algorithms** - Tests that FIPS-approved algorithms (AES, SHA-256, RSA) are available 5. **Non-FIPS algorithm blocking** - Confirms non-FIPS algorithms (e.g., MD5) are correctly blocked ### Basic verification ```bash theme={null} # Run a Java application with FIPS compliance docker run --rm reg.mini.dev/openjdk-fips:21 java -version # Compile and run Java code docker run --rm -v $(pwd):/home/build reg.mini.dev/openjdk-fips:21 \ javac MyApp.java && java MyApp ``` ### FIPS compliance test You can verify FIPS compliance by creating a test program. For example, save the following code as the file `TestFIPS.java`: ```java TestFIPS.java expandable theme={null} import java.security.Provider; import java.security.Security; public class TestFIPS { public static void main(String[] args) { System.out.println("=== FIPS Compliance Test ==="); // Check that FIPS approved only mode is enabled String approvedOnly = Security.getProperty("com.safelogic.cryptocomply.fips.approved_only"); boolean isApprovedOnly = approvedOnly != null && approvedOnly.equals("true"); if (!isApprovedOnly) { System.err.println("[ERROR] SafeLogic CryptoComply FIPS Approved Only Mode is disabled!"); System.exit(1); } // Check that providers are loaded Provider[] providers = Security.getProviders(); boolean foundCryptoComply = false; boolean foundBCJSSE = false; int cryptoComplyPosition = -1; int bcjssePosition = -1; for (int i = 0; i < providers.length; i++) { Provider provider = providers[i]; String name = provider.getName(); if (name.contains("CCJ") || name.contains("CryptoComply")) { foundCryptoComply = true; cryptoComplyPosition = i + 1; System.out.println("[OK] SafeLogic CryptoComply provider found at position " + cryptoComplyPosition); } if (name.contains("BouncyCastleJsse") || name.contains("BCJSSE")) { foundBCJSSE = true; bcjssePosition = i + 1; System.out.println("[OK] Bouncy Castle JSSE provider found at position " + bcjssePosition); } } if (!foundCryptoComply) { System.err.println("[ERROR] SafeLogic CryptoComply provider NOT found!"); System.exit(1); } if (!foundBCJSSE) { System.err.println("[ERROR] Bouncy Castle JSSE provider NOT found!"); System.exit(1); } // Check provider positions if (cryptoComplyPosition != 1) { System.err.println("[WARNING] SafeLogic CryptoComply provider is at position " + cryptoComplyPosition + ", expected position 1"); } else { System.out.println("[OK] SafeLogic CryptoComply provider is at correct position (1)"); } if (bcjssePosition != 2) { System.err.println("[WARNING] Bouncy Castle JSSE provider is at position " + bcjssePosition + ", expected position 2"); } else { System.out.println("[OK] Bouncy Castle JSSE provider is at correct position (2)"); } // Test FIPS-approved algorithms try { // Test AES (FIPS-approved) javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding", "CCJ"); System.out.println("[OK] AES algorithm available"); // Test SHA-256 (FIPS-approved) java.security.MessageDigest.getInstance("SHA-256", "CCJ"); System.out.println("[OK] SHA-256 algorithm available"); // Test RSA (FIPS-approved) java.security.KeyPairGenerator.getInstance("RSA", "CCJ"); System.out.println("[OK] RSA algorithm available"); // Test that MD5 is correctly blocked (non-FIPS) try { java.security.MessageDigest md5 = java.security.MessageDigest.getInstance("MD5", "CCJ"); System.err.println("[ERROR] MD5 is available (provider: " + md5.getProvider().getName() + ")"); System.err.println("[ERROR] FIPS mode is not fully enforced - MD5 should be blocked!"); System.exit(1); } catch (Exception e) { System.out.println("[OK] MD5 correctly blocked by FIPS compliance: " + e.getMessage()); } System.out.println("=== FIPS Compliance Test PASSED ==="); } catch (Exception e) { System.err.println("[ERROR] FIPS algorithm test failed: " + e.getMessage()); e.printStackTrace(); System.exit(1); } } } ``` Compile and run the FIPS test: ```bash theme={null} docker run --rm -v $(pwd):/home/build minimus/openjdk-fips:21 sh -c \ "javac TestFIPS.java && java TestFIPS" ``` Expected output: ```bash theme={null} === FIPS Compliance Test === [OK] SafeLogic CryptoComply provider found at position 1 [OK] Bouncy Castle JSSE provider found at position 2 [OK] SafeLogic CryptoComply provider is at correct position (1) [OK] Bouncy Castle JSSE provider is at correct position (2) [OK] AES algorithm available [OK] SHA-256 algorithm available [OK] RSA algorithm available [OK] MD5 correctly blocked by FIPS compliance: ... === FIPS Compliance Test PASSED === ``` ## Notes * FIPS compliance is enforced at runtime via Java security configurations * Applications must use FIPS-approved algorithms and keystore formats (BCFKS) * The Sun provider is included only for JAR signature validation and does not perform cryptographic operations * All cryptographic operations are routed through FIPS-validated providers (CCJ and BCJSSE) * The Java FIPS module requires specialized hardware. [Learn more](/advanced-guides/java-fips-tutorial) # SLSA L3 Source: https://docs.minimus.io/compliance/slsa Understand how Minimus adheres to the SLSA L3 standard for assuring software supply chain security At Minimus, we see ourselves as a principal agent in promoting software supply chain security. To uphold this standard, Minimus package and image build environments follow the strictest procedures to ensure integrity of the software we provide. Externally, Minimus helps users verify Minimus images by providing the image and SBOM provenance signatures directly in the Minimus console in the [compliance tab](/compliance/image-compliance). ## About SLSA SLSA, pronounced salsa, stands for Supply-chain Levels for Software Artifacts. SLSA is a set of industry guidelines for safeguarding artifact integrity across the software supply chain. SLSA standards and controls are designed to prevent tampering, improve integrity, and secure packages and infrastructure. SLSA guidelines are set forth by a cross-organization, vendor-neutral steering group under the auspices of the Open Source Security Foundation (OpenSSF). Minimus complies with SLSA L3, the highest level of supply chain security. This is to guarantee that Minimus software hasn’t been tampered with and can be securely traced back to its source. By verifying Minimus image signatures, users can verify that the source code packaged and delivered by Minimus is the same code they are actually using. ## SLSA L3 Overview The SLSA framework defines 3 levels of requirements that mitigate supply-chain attacks, with SLSA L3 being the highest level of assurance: artifacts must be built in isolated, verifiable, and tamper-resistant environments with non-falsifiable provenance with immutable attestations. The following table is provided in the official SLSA site ([ref](https://slsa.dev/spec/v1.1/levels)): | **Level** | **Requirements** | **Focus** | | :-------- | :------------------------------------------------------ | :------------------------- | | Build L0 | (none) | (n/a) | | Build L1 | Provenance showing how the package was built | Mistakes, documentation | | Build L2 | Signed provenance, generated by a hosted build platform | Tampering after the build | | Build L3 | Hardened build platform | Tampering during the build | SLSA L3 offers robust enforcement of build integrity: * **Verified provenance:** Provenance must be authenticated and non-falsifiable. * **Build isolation:** Each build is hermetically sealed to prevent cross-build contamination. * **Controlled secrets and inputs:** Build secrets are managed by the platform, not user code. * **Auditable source and build systems:** Source and build platforms must enforce versioned, tamper-evident change tracking. A build environment that meets the above requirements can produce reproducible artifacts whose entire lineage can be verified cryptographically from the source commit to the image manifest. ## How Minimus Images Achieve SLSA Level 3 Compliance Users can rely on Minimus images and packages with confidence because Minimus takes every precaution when building its artifacts. Following is the list of protections in place. **1. Authenticated Provenance Generation** The Minimus build service automatically generates provenance metadata for every image build. This metadata includes commit hashes, dependency manifests, environment hashes, and builder identity. Provenance is signed by the Minimus attestation service using the Sigstore toolchain to guarantee authenticity. **2. Isolated, Ephemeral Build Environments** Each build runs in a disposable, isolated sandbox provisioned via Minimus’ internal CI orchestrator. Environments are short-lived and immutable: once the build completes, the runner and its intermediate data are destroyed. This architecture ensures no state persists across builds, satisfying SLSA L3 isolation requirements. **3. Controlled Secrets and Build Inputs** Build secrets such as signing credentials and deployment tokens are injected only at runtime and are unavailable to user-defined steps. Inputs such as source and dependencies are pulled from verified registries using pinned references, preventing substitution attacks. **4. Auditable Build and Source Systems** All repositories in the Minimus source control are versioned and protected by mandatory code-review policies. Build definitions including pipelines are also version-controlled, and every pipeline execution is logged and stored immutably for post-build verification. **5. Provenance Verification and Policy Enforcement** Users can verify the provenance of Minimus images by validating image signatures and SBOM signatures using Cosign. ## Summary Table: Minimus Implementation of SLSA L3 Guidelines | **SLSA L3 Objective** | **Requirement** | **Minimus Implementation** | | :------------------------------- | :--------------------------------------------------- | :------------------------------------------------------- | | Authenticated provenance | Non-falsifiable provenance signed by trusted builder | Sigstore provenance generated per build | | Build isolation | No shared state between builds | Ephemeral sandbox runners with immutable environments | | Secret protection | Build secrets not accessible to user code | Secrets injected at runtime and isolated from user logic | | Verified inputs | Dependencies must be versioned and verified | Commit-pinned sources and dependency registries | | Auditable source & build systems | Controlled, versioned, and monitored | Mandatory code reviews, immutable CI logs | | Provenance verification | Allow users to verify artifacts | Image and SBOM signature provided for every image build | # Security Technical Implementation Guides (STIG) Source: https://docs.minimus.io/compliance/stig About STIG guidelines for enhanced security and how to verify them in Minimus images using the Minimus OpenSCAP image Minimus offers hardened images following STIG guidelines for enhanced security. STIGs are Security Technical Implementation Guides published by the Defense Information Systems Agency (DISA). You can filter for STIG compliant containers in the Minimus gallery. ## Verify Security Content Automation Protocol (SCAP) [OpenSCAP tools](https://www.open-scap.org/tools/) are the recommended toolset for validating the configuration of container images and reviewing the configuration of an image file system. For ease of use, Minimus provides a hardened [OpenSCAP image](https://images.minimus.io/images/openscap/quick-start) that always includes the most up-to-date package version for all of the included packages and dependencies. Use the Minimus OpenSCAP image to scan your Docker images and containers without the need to install OpenSCAP locally. This image comes preloaded with a Minimus STIG file for security and compliance assessments. ## How to verify STIG compliance for Minimus images To test the Minimus OpenSCAP image, follow the steps below to scan an image using its file system. Docker runtime is required as a pre-requisite for running the Minimus OpenSCAP docker image. Pull the OpenSCAP latest image from the Minimus registry: ```bash theme={null} docker pull reg.mini.dev/openscap:latest ``` The data stream module (ds) is provided by Minimus and used to automatically validate the image or container. Download the file [ssg-minimus-gpos-ds.xml](https://raw.githubusercontent.com/minimusio/examples/main/STIG/ssg-minimus-gpos-ds.xml) from the Minimus public GitHub repo. To pull the file locally: ```bash curl example theme={null} curl -O https://raw.githubusercontent.com/minimusio/examples/main/STIG/ssg-minimus-gpos-ds.xml ``` ```bash wget example theme={null} wget -O ssg-minimus-gpos-ds.xml https://raw.githubusercontent.com/minimusio/examples/main/STIG/ssg-minimus-gpos-ds.xml ``` For good measure, verify the file: ```bash theme={null} docker run --user root \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$PWD/ssg-minimus-gpos-ds.xml:/ssg-minimus-gpos-ds.xml:ro" \ --entrypoint "" \ reg.mini.dev/openscap \ /usr/bin/oscap info ssg-minimus-gpos-ds.xml ``` You should see a printout of file details, beginning with `Document type: Source Data Stream` and version information. ```bash theme={null} mkdir -p "$PWD/openscap_results" ``` Change the directory ownership to match the container's UID to grant the OpenSCAP container write access: ```bash theme={null} sudo chown 1000:1000 "$PWD/openscap_results" ``` Pull the image you plan to scan from the Minimus registry, for example: ```bash theme={null} docker pull reg.mini.dev/nginx-fips:latest ``` Use the oscap-docker tool to perform offline scanning from the Minimus provided image: ```bash Specific example theme={null} docker run --user root \ -v "$PWD/ssg-minimus-gpos-ds.xml:/ssg-minimus-gpos-ds.xml:ro" \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$PWD/openscap_results:/output" \ --entrypoint "" \ reg.mini.dev/openscap \ /usr/bin/oscap-docker image reg.mini.dev/nginx-fips:latest -- \ xccdf eval \ --profile "xccdf_basic_profile_.check" \ --results /output/scan-results.xml \ --report /output/report.html \ /ssg-minimus-gpos-ds.xml ``` ```bash General command theme={null} docker run --user root \ -v "$PWD/ssg-minimus-gpos-ds.xml:/ssg-minimus-gpos-ds.xml:ro" \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$PWD/openscap_results:/output" \ --entrypoint "" \ reg.mini.dev/openscap \ /usr/bin/oscap-docker image {IMAGE_TO_SCAN} -- \ xccdf eval \ --profile "xccdf_basic_profile_.check" \ --results {path to scan results in XML} \ --report {path to scan results in HTML} \ {path to data stream file} ``` * `--results` indicates where to place the XML formatted report * `--report` indicates where to place the HTML report * The data stream location points to the location of the SCAP source data stream file The test outputs two files: An XML report and an HTML page. You can use either to review your results. ### XCCDF Format The eXtensible Configuration Checklist Description Format is part of the SCAP standard. OpenSCAP tooling uses XCCDF to automate compliance and configuration remediation. XCCDF STIG reports can be viewed in dedicated viewing tools endorsed by the DoD. Currently, STIG Viewer 3 is the most up to date. The relevant style sheet is bundled with the STIG. ([Link to download the STIG Viewer](https://public.cyber.mil/stigs/srg-stig-tools/).) ## Convert DISA STIG XML to other formats You can convert DISA STIG XML reports into other formats, as required, using a popular open-source tool from MITRE. This tutorial showcases examples using the [heimdall-lite](https://saf.mitre.org/docs) utility made available by the MITRE [**Security Automation Framework (SAF)**](https://saf.mitre.org/). This guide explains how to run the utility as a container in order to convert a DISA STIG XML report provided by Minimus into other common formats, including JSON, CSV, HTML, DISA Checklist, etc. MITRE Heimdall ([https://github.com/mitre/heimdall2](https://github.com/mitre/heimdall2)) is a suite of tools that provide a centralized visualization and reporting solution for automated security scan results. ### Pre-requisites 1. Scan results obtained in XML format by running the Minimus OpenSCAP image. See the [quick start guide](https://images.minimus.io/images/openscap/quick-start) 2. Container runtime environment (such as Podman or Docker) 3. Ability to pull in the heimdall-lite docker image to its execution location 4. The heimdall-lite docker image currently ships for amd64 images only. If needed, you can use emulation as a workaround for other architectures such as macOS Darwin. ### Run Heimdall Lite locally on macOS Since Heimdall Lite only ships in amd64 formats, the container image will either need to run on an x86 architecture or be passed through an emulator. This can be achieved on macOS Darwin by installing an emulator to pass through this image with an option such as `qemu`. `qemu` may be installed locally with Homebrew: ```shellscript theme={null} brew install qemu ``` ```shellscript wrap theme={null} docker pull docker.io/mitre/heimdall-lite:release-latest --platform linux/amd64 ``` Note - this pull will fail locally on Darwin if the platform flag is not included. ```shellscript wrap theme={null} docker run --platform=linux/amd64 -d -p 8080:80 mitre/heimdall-lite:release-latest ``` Open your local web browser to point at `localhost:8080` (This example assumes you bound port 8080 but you should use the port you bound in the run command). Heimdall Macos Connect Select **Choose files to upload** and select your XML file (that is the report generated using OpenSCAP). Heimdall Local Step6 Checks2 You will see the same matching checks previously noted from running OpenSCAP. You will now be able to export the report into various formats as desired by selecting the **Export** button at the top right. Heimdall Local Export Darwin3 You can use the above process to export the report as a DISA checklist and download it locally. To do so, select the option **Export as a DISA Checklist**. You can download the resulting file when prompted. Heimdall Local Export Darwinchecks4 ### Run Heimdall Lite on a Cloud VM This example showcases running Heimdall Lite on a GCP VM but the concept is the same for other cloud providers. Create a VM with Docker or Podman installed to execute the runtime of a container image that is x86-64 or amd64 based. ```shellscript theme={null} docker pull docker.io/mitre/heimdall-lite:release-latest ``` ```shellscript theme={null} docker run -d -p 8080:80 mitre/heimdall-lite:release-latest ``` To run the browser locally, you must now create an SSH tunnel to the instance and map it to the respective port the container is listening on. This can be done by using the Google Cloud CLI (`gcloud` CLI) and then authenticating to your respective project where the VM is running. 1. Authenticate to your GCP project via CLI: ```shellscript theme={null} gcloud auth login ``` Heimdall Gcp Vm Auth Gcloud3 2. Authenticate via web browser: You may need to allow permissions from GCP. If successful, you will see the same success message in your local terminal: `Your browser has been opened to visit`. Heimdall Gcp Vm Allowgcppermissions4 3. Create your SSH tunnel using gcloud:  ```shellscript wrap theme={null} gcloud compute ssh [VM_NAME] --project=[PROJECT_ID] --zone=[ZONE] -- -N -L [LOCAL_PORT]:localhost:[REMOTE_PORT] ``` You will need to update the command with the following: * LOCAL\_PORT - Use the port you enter in your local browser on your machine * REMOTE\_PORT - Use the port the Heimdall Lite container is bound to listen on in the cloud VM. 4. If run for the first time, you may be prompted to generate SSH keys locally. When successful, you will have an active process with this open tunnel and the cursor will be active. Heimdall Gcp Vm Opentunnel6 Access the Heimdall Lite container from your local browser by typing in `localhost:LOCAL_PORT`, for example, `localhost:9080`. Heimdall Gcp Vm Connecttoheimdall7 Heimdall Gcp Vm Checks8 Use the **Export** button on the top right to export your report to your format of choice. Heimdall Gcp Vm Exportchecks9 # Check if Your Container Has a Shell Source: https://docs.minimus.io/debugging/debug How to check if a Docker or Kubernetes container has a shell and what to do when it does not Minimus images are built for security around the paradigm that production images, on principle, should not include a shell whenever possible. This paradigm requires a different approach when debugging. The solution will depend on your environment, whether Kubernetes or Docker, as detailed below. ## Kubernetes environment ### When there's no shell... ``` kubectl exec -it {container name} -- sh ``` The error indicates that the executable file was not found. ```[expandable] theme={null} error: Internal error occurred: error executing command in container: failed to exec in container: failed to start exec "{container ID}": OCI runtime exec failed: exec failed: unable to start container process: exec: "sh": executable file not found in $PATH: unknown ``` The error indicates that your container does not have a shell. ### Debugging with ephemeral containers Ephemeral debug containers are the recommended method for debugging distroless containers in production. Ephemeral debug containers are used to temporarily attach to an existing Pod in order to troubleshoot and inspect running services. [Learn more](/debugging/ephemeral-container) ## Docker environment ### When there's no shell... ``` docker exec -it {container ID} /bin/bash ``` The error indicates that no such file or directory exists. ``` OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown ``` The error indicates that the container does not have a shell. ### Mount a debugging container You can mount debugging tools and take advantage of shared namespaces to use a `docker exec` command. [Learn more](/debugging/mount-debugger) Another option is to use the Docker Debug utility. Docker Debug is available for signed-in Docker users with a paid, Pro, Team, or Business subscription ([ref](https://docs.docker.com/reference/cli/docker/debug/)). # Debug in Kubernetes Source: https://docs.minimus.io/debugging/ephemeral-container Using ephemeral containers to interactively troubleshoot Kubernetes production environments For your Kubernetes deployment, you can use ephemeral debug containers to debug distroless Minimus images. Ephemeral debug containers can be temporarily attached to existing Pods to troubleshoot and inspect running services and are commonly used to inspect and troubleshoot running services. Ephemeral debug containers may be necessary, since copying debugging tools into running containers on-demand with `kubectl cp` is not possible for Minimus production images without `tar` included. ## Process namespace sharing The ephemeral container needs to connect to the namespace of the Minimus container in order to sideload debugging tools that aren't available in the Minimus container itself. To simplify the debugging process, it is recommended customers enable process namespace sharing in your Pod settings. If enabled, you will be able to access processes running in other containers on the Pod without having to specify a target. Access to the filesystem may also be affected, due to default user permissions. The attribute `ephemeralContainers` in the Pod spec can also be modified for existing Pod instances. [Learn more from Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/) ## Nginx example In this example we have an Nginx container in a Kubernetes cluster: ```bash theme={null} kubectl run nginx --image=minimus/nginx:latest ``` ``` # output pod/nginx created ``` The Minimus Nginx production image is distroless, and does not contain troubleshooting tools to limit the attack surface, including a shell - so you can't use `kubectl exec` to troubleshoot the container. The solution is to add a debugging sidecar. The Minimus **generic base image** is designed just for that purpose, and is ideal for running as an ephemeral debug container along with another Minimus container. Run the following to add the image as an ephemeral container and connect it to the namespaces of your already-running nginx container: ```bash theme={null} kubectl debug -it nginx --image=minimus/{minimus-base} --target=nginx ``` ``` # output Targeting container "nginx". If you don't see processes from this container it may be because the container runtime doesn't support this feature. Defaulting debug container name to debugger-87792. If you don't see a command prompt, try pressing enter. nginx:/# ``` You can now inspect the container and its open ports: ```bash Inspect container theme={null} ps aux ``` ```bash Inspect open ports theme={null} netstat -lntu ``` You are now ready to sideload debugging tools and get to work. # Mount a Debugger Source: https://docs.minimus.io/debugging/mount-debugger How to debug a Minimus container by mounting debug tools Most production Minimus container images do not include a shell. While we recommend use of the `dev` tagged Minimus images for troubleshooting whenever possible, sometimes it may be necessary to mount a debugger on a production container. We can use the [Minimus BusyBox](https://images.minimus.io/images/busybox/lines/latest) image as our debugger container. We will first create the container (without running it), extract its filesystem, and place it in a local directory. ```bash theme={null} # Create a container from the Minimus BusyBox image docker create --name debugger \ reg.mini.dev/busybox:latest-dev # Create a local directory to store the filesystem mkdir debugger # Export the root filesystem and save it to the local directory docker export debugger | sudo tar -xC debugger ``` * `docker export` saves the root filesystem of the container to a tar archive * `|` (the pipe) passes the output directly into the next command to avoid creating an intermediate tar file * `tar -xC debugger` extracts the archive files and saves them to the local directory ```bash theme={null} docker run -d --rm \ -v $(pwd)/debugger:/.debugger \ --name my-image {your production Minimus image} ``` Exec into the target container to start a debug session. This is possible because the debugger container and target container (`my-image`) share namespaces and cgroups. ```bash theme={null} docker exec -it my-image /.debugger/bin/sh ``` Now that we've mounted the BusyBox toolkit, we need to add the directory `/.debugger/bin` to the current shell's path environment variable to make the tools executable from anywhere. This works because the BusyBox toolkit in the mounted volume is statically linked. ```bash Append Debugger theme={null} export PATH=${PATH}:/.debugger/bin # The target container takes precedence ``` ```bash Prepend Debugger theme={null} export PATH=/.debugger/bin:${PATH} # The debugger container takes precedence ``` You can either prepend or append the debug tools. In the case of a name collision: * If the debugger was appended, the binaries from the target container will take precedence. * If the debugger was prepended, the binaries from the debugger container will take precedence. Note that this change only affects the current shell session. That's it. You are now ready to use the BusyBox toolkit as if it were natively part of the target container. For example, you can explore the filesystem of the target container and list the running processes and network interfaces: ```bash theme={null} # List files and directories in long format ls -l # List all running processes on the system in full detail ps -ef # List IP addresses for all network interfaces ip addr ``` The output should show you the information for your target Minimus container as if you were running the command directly inside it. This article was inspired by [Ivan Velichko's blog](https://iximiuz.com/en/posts/docker-debug-slim-containers/). # Authenticated Package Access Source: https://docs.minimus.io/enterprise-edition/authenticated-package-access Install Minimus packages directly in Minimus images using a package manager to experiment with options and extend images Image Creator is usually the optimal way to add packages to Minimus images, but when you need the extra freedom to test out options and decide which packages you will need, direct package access is available. Package access allows you to add Minimus packages directly in your Dockerfile or install them in a running container so you can experiment within the Minimus ecosystem. ## Creator vs. package access [Image Creator](https://images.minimus.io/creator) is the standard choice when working with Minimus because it allows Minimus to handle all of the following for you: * Package version updates. [See advisories](/remediate/advisories) * Image updates. [See daily builds](/foundations/daily-updates) * Vulnerability reports. [See image version card](/foundations/image-version) * Changelog. [See image card](/foundations/image-card#changelog) * Builds of all versions. [See versions](/introduction/versions) When using package access to install packages ad-hoc, you (or someone on your team) will need to manually handle the above tasks. That said, package access is a common choice and is fully supported by Minimus. ## Authenticate to packages.mini.dev Learn how to authenticate to the Minimus Package Repository both at runtime and during the Docker build process. ### Prerequisites When installing packages, make sure to use Minimus containers that meet both conditions: 1. Can run `apk` commands - Minimus `dev` images fit the bill 2. Run as root - usually this is not the default in Minimus images so you'll need to [switch to a root user](/basics/user#switch-users-in-the-dockerfile) Keep in mind that Minimus production images are usually not a good fit because they are distroless. This means they don't include the necessary packages. You can always check the image's [SBOM](/foundations/image-card) to be sure. ### During runtime (inside a container) 1. Create a token with **package access scope**. See [tokens](/manage/token) Package Access Token 2. Run a Minimus docker container as root and make sure the container includes `apk`. For example, you can run the Bash image with the `latest-dev` tag: ```shellscript theme={null} docker run -it -u root reg.mini.dev/bash:latest-dev ``` 3. In the container, authenticate to the Minimus package registry: ```shell package access command wrap theme={null} export HTTP_AUTH="basic:packages.mini.dev:minimus:mini_dkj***" apk update ``` Once authenticated, the session will remain active until the token expires. 4. Add packages as usual. For example, you can add `git`: ```text theme={null} apk add --no-cache --repository=https://packages.mini.dev/os git ``` ### In a Dockerfile You can install packages directly within your Dockerfile by authenticating during the image build. As is standard practice in CI pipelines, this approach uses a build variable like `${REPO_PASS}` to securely handle credentials. Below is an example of the code to be added to your Dockerfile: ```dockerfile Dockerfile HTTP_AUTH code theme={null} ... ARG REPO_PASS ENV HTTP_AUTH="basic:packages.mini.dev:minimus:${REPO_PASS}" USER root # Update APK and install packages RUN apk update && \ apk add --no-cache \ \ ... ``` Build with a Minimus token that has [package access](/manage/token): ```shellscript docker build command theme={null} docker build --build-arg REPO_PASS={token} -t my-minimus-image:local . ``` ```text example theme={null} docker build --build-arg REPO_PASS=mini_dkj*** -t my-minimus-image:local . ``` ## Python tutorial example (multi-stage build) The following example builds on the multi-stage pattern from the Minimus [Python guide](/guides/python). We will follow the steps in the original guide, replacing only the Dockerfile and build command. The Dockerfile uses a `latest-dev` builder for package installation and Python dependencies and switches to the minimal Python image at runtime. ```python Dockerfile with apk add steps theme={null} # === Build Stage === FROM reg.mini.dev/python:latest-dev AS builder ARG REPO_PASS ENV HTTP_AUTH="basic:packages.mini.dev:minimus:${REPO_PASS}" WORKDIR /app # Install system packages from the Minimus package repository USER root RUN apk update && \ apk add --no-cache \ build-base \ libffi-dev RUN python -m venv /app/venv ENV PATH="/app/venv/bin:$PATH" COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # === Runtime Stage === FROM reg.mini.dev/python:latest WORKDIR /app COPY main.py . COPY --from=builder /app/venv /app/venv ENV PATH="/app/venv/bin:$PATH" ENTRYPOINT ["python", "main.py"] ``` Note that all `apk` commands stay in the `latest-dev` build stage and are executed as `USER root` to avoid `Unable to lock database: Permission denied`. The runtime image `reg.mini.dev/python:latest` is distroless and does not include `/bin/sh`, so `RUN apk ...` is not supported there. Add your Minimus token to the build command: ```shellscript build command theme={null} docker compose build --build-arg REPO_PASS={token} ``` ```shellscript expected output theme={null} ... => [builder 3/6] RUN apk update && apk add --no-cache build-base libffi-dev 5.0s => CACHED [stage-1 2/4] WORKDIR /app 0.0s => CACHED [stage-1 3/4] COPY main.py . 0.0s ... 0.0s [+] build 1/1 ✔ Image python-apk-flask-app Built ``` ## Runtime Troubleshooting ### Auth error If the remote server returns an error, most likely authentication failed because your token doesn't include package access. For example: `WARNING: updating and opening https://packages.mini.dev/os: remote server returned error (try 'apk update')` To fix the issue, edit your token or create a new one with package access scope. See [tokens](https://docs.minimus.io/manage/token) ### Permission denied If you get an error that permission was denied, most likely you are running as a non-root user and can't modify system files. For example: `ERROR: Unable to lock database: Permission denied` `ERROR: Failed to open apk database: Permission denied` To fix the issue, run the container with `-u root` to [override the default user at runtime](/basics/user#override-the-default-user-to-run-as-root). ### APK not found If you try to run `HTTP_AUTH="basic:packages.mini.dev:token"` and get an error `bash: apk: command not found`, this means you are using a Minimus image that is not able to run apk commands. To fix the issue, run a [Minimus dev image](/introduction/image-variants) so it includes dev tools. ## Dockerfile Troubleshooting ### Auth error If you get an error that ends with `exit code: 2`, most likely authentication failed because your token doesn't include package access. For example: `failed to solve: process "/bin/sh -c apk update && apk add --no-cache " did not complete successfully: exit code: 2` To fix the issue, edit your token or create a new one with package access scope. See [tokens](/manage/token) ### Permission denied If you get an error that ends with `exit code: 99`, most likely you are running as a non-root user and can't modify system files. For example: `failed to solve: process "/bin/sh -c apk update && apk add --no-cache " did not complete successfully: exit code: 99` To fix the issue, edit your Dockerfile to [switch to the root user](https://docs.minimus.io/basics/user#switch-users-in-the-dockerfile) before running the apk commands. # Authenticating to the Minimus Registry Source: https://docs.minimus.io/enterprise-edition/authentication How to log into the Minimus registry to pull and verify images An active token is required to pull your private images from Minimus. Standard Minimus images can be pulled without authentication with any tag or digest. A token is a type of secret so, like with all secrets, you should ensure that the token isn't stored where it can be leaked. ## Overview The following article details different methods of authenticating to the Minimus registry in Docker, Kubernetes, and with Helm charts. Visit the [token page](https://images.minimus.io/manage/tokens) in your Minimus console to copy a few useful authentication commands: * `docker login` * `kubectl create secret` (Creates K8s secret) * Package access [Learn more about managing tokens](/manage/token) ## Docker environment ### Insert token inline (on-demand authentication) Insert your Minimus token directly in the `docker pull` / `docker run` command to login to the Minimus registry on demand. The token isn’t persisted in Docker’s credential store. This approach works well for ad-hoc testing. ```shellscript inline token format theme={null} # reg.mini.dev is the minimus registry docker pull reg.mini.dev/{token}/{image name} docker run reg.mini.dev/{token}/{image name} ``` ```shellscript example theme={null} docker pull reg.mini.dev/{token}/nginx-fips:latest docker run reg.mini.dev/{token}/nginx-fips:latest ``` When you copy the pull command from the [gallery](https://images.minimus.io/), it will contain an inline token. ### `docker login` command (persistent authentication) Authenticate to the Minimus registry using the docker login command to keep your session active until the token expires. This way you will not need to use an inline token. ```shellscript stdin (recommended) theme={null} echo "{token}" | docker login reg.mini.dev -u minimus --password-stdin ``` ```shellscript shortform theme={null} docker login reg.mini.dev -u minimus -p {token} # The username is always minimus ``` ```shellscript longform theme={null} docker login reg.mini.dev # Username: minimus # Password: {token} ``` It's a security best practice to pass the token via stdin because it avoids exposing the token in the command history, process lists, and logs. Once authenticated to the Minimus registry, you can pull any image included in your subscription (and any image tag that doesn't require a subscription). For example: ```shellscript theme={null} docker pull reg.mini.dev/nginx:latest docker pull reg.mini.dev/nginx:latest-dev ``` Once your token expires, you will need to run `docker login` again with an active token to continue working. A valid inline token will not work since `docker login` takes priority. You can run `docker logout reg.mini.dev` to reset your access if you prefer to work with an inline token. ### Using a credential store You have the option to use a credential store for additional security. [Learn more from Docker](https://docs.docker.com/reference/cli/docker/login/) ## Kubernetes environment ### Create Kubernetes Secret (K8s Secret) To avoid embedding tokens in Kubernetes files or Helm charts, we can reference a Kubernetes Secret. The Kubernetes Secret must be created in the same namespace as the deployment. Run the following to create a Kubernetes Secret of type `docker-registry`. Once created, you can reference this Secret to let Kubernetes pull images from the Minimus registry automatically. Throughout the Minimus documentation, we assume the K8s Secret is named `minimus-registry`. ```shellscript general format theme={null} kubectl create secret docker-registry minimus-registry \ --docker-server=reg.mini.dev \ --docker-username=minimus \ --docker-password={token} \ --namespace={same namespace as your helm chart} ``` ```shellscript create kubernetes secret named minimus-registry theme={null} kubectl create secret docker-registry minimus-registry \ --docker-server=reg.mini.dev \ --docker-username=minimus \ --docker-password={token} \ --namespace=default ``` ### Create Kubernetes Secret using an encoded file After logging in using the `docker login` steps above, we can create an encoded `config.json` file locally with the value necessary to generate the Kubernetes Secret. 1. Login to `reg.mini.dev` using the steps above. 2. Execute `cat ~/.docker/config.json | base64 -w 0` to base64 encode the credentials. 3. Create a Kubernetes YAML file named `minimus-registry.yaml`. ```yaml minimus-registry.yaml theme={null} apiVersion: v1 kind: Secret metadata: name: minimus-registry data: .dockerconfigjson: {paste your base64 encoded string} type: kubernetes.io/dockerconfigjson ``` 4. Create the K8s Secret in the application namespace: ```powershell theme={null} kubectl apply -n {namespace} -f minimus-registry.yaml ``` 5. Add the `ImagePullSecret` parameter to your deployment by changing the spec as shown in the snippet below and redeploy: ```yaml theme={null} spec: containers: - name: nginx image: reg.mini.dev/nginx:latest # add the next two lines imagePullSecrets: - name: minimus-registry ``` ## Helm charts ### Insert token inline (on-demand) You can insert the token directly in the `helm install` command. The token can either be inserted as part of the registry, or image, depending on the structure of the Helm chart. See the following examples. ```powershell example 1 theme={null} # token prepended to image in image.repository helm install mongodb bitnami/mongodb \ --set image.registry=reg.mini.dev \ --set image.repository={token}/mongo-advanced \ --set image.tag=latest \ --set global.security.allowInsecureImages=true ``` ```powershell example 2 theme={null} # token added after image.registry helm install linkerd-viz linkerd/linkerd-viz \ --set tap.image.registry=reg.mini.dev/{token} \ --set tap.image.tag=latest \ --set tap.image.name=linkerd-tap-fips ``` ```powershell example 3 theme={null} # token inserted in image.repository helm install solr-operator apache-solr/solr-operator \ --set image.repository=reg.mini.dev/{token}/solr-operator \ --set image.tag=latest ``` ### Reference Kubernetes Secret on-demand Assuming your Kubernetes secret is named `minimus-registry` as in the above example, you can add the following flag to your Helm install/upgrade commands: `--set=global.imagePullSecrets[0].name=minimus-registry`. ```yaml flag theme={null} --set=global.imagePullSecrets[0].name={K8s secret} ``` ```shellscript example in context theme={null} # using existing Kubernetes Secret `minimus-registry` helm install prometheus-stack prometheus-community/kube-prometheus-stack \ --set=prometheusOperator.image.registry=reg.mini.dev \ --set=prometheusOperator.image.repository=prometheus-operator \ --set=prometheusOperator.image.tag=latest \ --set=global.imagePullSecrets[0].name=minimus-registry ``` The flag overrides the value in the chart without editing the `values.yaml`. ### Add `imagePullSecrets` to `values.yaml` You can edit the `values.yaml` file to override the values in the chart. To deploy Minimus images to a Kubernetes cluster, add the `ImagePullSecrets` parameter to point to the `minimus-registry` K8s Secret: ```yaml example of values.yaml theme={null} spec: containers: - name: nginx image: reg.mini.dev/nginx:1.29.0 # add the next two lines imagePullSecrets: - name: minimus-registry ``` ## Troubleshooting ### Valid inline token returned unauthorized error **To fix the problem**: Run `docker logout reg.mini.dev` to reset your access and try the pull command again. **Explanation**: Most likely, you previously authenticated with the `docker login` command and the token has since expired or been deleted. The token from the `docker login` command takes precedence over the inline token and this is causing the error. # File Bundles Source: https://docs.minimus.io/enterprise-edition/file-bundles Centrally manage file bundles and certificates for your private images in Minimus File bundles are used to include public keys for internal PKIs (Public Key Infrastructure certificates) and override configuration files. File bundles are always centrally managed and automatically versioned. If certificates are included, they are implicitly trusted by the image without any need to perform any additional actions after pulling the image. File Repository ## Upload new bundle There are two ways to upload a new file bundle: * You can add a new file bundle directly to the file repository when you are not actively creating or editing a private image. * You can upload a new file bundle directly to a private image as part of the Creator flow. The file bundle will be added to the central file repository automatically and will be available for selection for other private images as well. ### Upload from file repository 1. Select [Creator](https://images.minimus.io/creator) in the main menu. 2. Select the option to **Manage Files**. Manage Files 3. The file repository will be listed with your existing file bundles. You can search the list by bundle name or description and filter by bundle type: certificates or other. 4. Select the option to **upload new bundle**. 5. Fill out the form: 1. Provide a name and description (The description is optional but recommended for search purposes). 2. Select the bundle type and path: **Certificates** or **Other**. Note that certificates must be uploaded to a file bundle type of **Certificates**. They cannot be uploaded to the bundle type **Other**. 3. If you select **Certificates**, the folder path is hardcoded: `/usr/local/share/ca-certificates/` 4. If you select **Other**, the folder path is configurable. Specify an absolute Linux path starting with `/` and without backslashes (`\`). 6. Upload valid files. 1. A maximum of 20 files can be uploaded per file bundle. 2. File size is limited to 1 MB per file. 7. Save your changes. The new file bundle will be added to the list in your file repository. ### Upload directly to private image 1. Select [Creator](https://images.minimus.io/creator) in the main menu. 2. Select the option to **Create private image**. 3. Follow the wizard to the fourth step - **Upload files**. 4. Select **Add File Bundle > Upload New**. 5. Continue from step 5 above to fill out the form. ## Upload certificates 1. In Creator, select the base image and follow the wizard to the relevant step - upload files. Select **Add File Bundle > Upload New**. 2. Fill out the form: 1. Provide a name and description for the custom configuration file. Adding a description is recommended as it is visible in the file bundle summary page. 2. Select **Type: Certificates**. 3. The file path is hardcoded and cannot be changed. 4. Upload the certificate files. 5. Save your changes. Upload certificate ## Override configuration file 1. Before you begin, look up the default path to the configuration file in the base image. It may be listed in the specification tab in the Minimus console or you may need to run `docker inspect` on the image. 2. Save your custom configuration file and name it, preferably with a name that will help teammates understand its purpose. Validate that the files you plan to upload are not executable: `chmod -x path/to/file` 3. In Creator, select the base image and follow the wizard to the relevant step - upload files. Select **Add File Bundle > Upload New**. 4. Fill out the form: 1. Provide a name and description for the custom configuration file. Adding a description is recommended as it is visible in the file bundle summary page. 2. Select **Type: Other**. 3. Provide the exact path you would mount the config file onto. For example in nginx, the path would be `/etc/nginx`. See also our [nginx tutorial](/guides/nginx) 4. Upload the file. 5. Save your changes. Override Config ## Edit file bundle Go to your [file repository](https://images.minimus.io/creator/files), hover over a file bundle card to select the edit option. * Once the bundle is updated, Minimus will automatically build new versions of all private images that include the file bundle. * Visit the image changelog to view the new image digest in context. ## Remove or delete file bundle * To remove a file bundle from a private image, go to [Creator](https://images.minimus.io/creator) to edit the private image. Once saved, the private image will be rebuilt with the relevant changes. * To delete a file bundle from the file repository, first remove it from all private images. A file bundle cannot be deleted as long as it is referenced by a private image. ## Limitations * The maximum number of file bundles allowed by the file repository is 50. * The maximum number of file bundles allowed per private image is 10. * The maximum number of files per bundle is 20. * The maximum file size is 1 MB per file. # Image Creator Source: https://docs.minimus.io/enterprise-edition/image-creator Create your own private image by customizing a standard Minimus image Customize Minimus standard images using [Creator](https://images.minimus.io/creator) to meet your team's exact needs. Minimus private images can help you simplify Dockerfiles, install private certificate bundles, and more to reduce overhead for dev teams and streamline processes. Minimus maintains a private image as any standard Minimus image with daily builds and package updates, to keep the private image fresh and free of vulnerabilities (whenever patches and updates are available). ## Creating a private image Select any image from your Minimus subscription to begin. Only images listed in [your Minimus subscription](https://images.minimus.io/manage/subscription) will be shown. Select Starter Image You can add any number of packages to your starter image. All packages maintained in the Minimus package repository are available, including the Minimus Cryptographic Module for FIPS images.  The recommended process is as follows: 1. Review the SBOM of your starter image - expand the folder **starter image packages** in the right preview panel. Packages included in the latest production version are marked and listed. Generally, other image lines of the starter image are already using other versions of these same packages.  2. Search the list of available add-on packages by name, description or version. For Python and PHP packages, you can select `auto` packages for Minimus to automatically pair versions and ensure package version compatibility. [Learn more](#auto-versioning-python-and-php-packages)  3. Select packages to add them.  For a FIPS-validated starter image, select FIPS-validated packages whenever available. Note that some packages are FIPS-neutral and are not offered in a FIPS-validated format. \ \ [Please contact our support team with any questions.](https://support.minimus.io/support/home) We're happy to walk you through the process. 4. Review the added packages in the right preview panel under the folder **added packages**. 5. In the right-panel preview, fine-tune your selection and remove packages, as needed. Starter Image SBOM The final number of packages added will depend on the package dependencies. Dependencies are detected at the build stage and will be listed in the private image SBOM.\ \ A maximum of 100 added packages are allowed. You can add custom env variables (short for environment variables) to pass configuration settings into the container at runtime without hardcoding them in the image. These may include ports, credentials, modes, etc. * Avoid duplicate keys as they will cause the build to fail. This is to protect against overrides that can interfere with the starter image configurations. * You can add key-value pairs. Key-only variables (also, empty environment variables) are not accepted. * Once you make your updates, your custom env variables are shown in the right preview panel, where you can review them and remove them if needed. You can upload a new file bundle or add an existing file bundle from the file repository. File bundles are used to include public keys for internal PKIs (Public Key Infrastructure certificates), override default configuration files, and more. * Once you add your file bundles, they will be shown in the right preview panel for review. * [Learn more about managing your file bundles](/enterprise-edition/file-bundles) The next step is to give your private image a name and optionally, provide a description. Your organization's tenant ID will be prepended to the image name to clearly indicate that it is private to your organization. Your image will also be marked with the label **private image**. The image name must be 2–40 characters long and begin and end with a lowercase letter. Only lowercase letters, numbers, and hyphens are accepted. Read the testing recommendations then save your image. The following build & testing notes appear in the Minimus console: * Your private image will only include image lines that build successfully. Image lines that run into package conflicts will be skipped to keep your private image error-free. * Minimus recommends testing your private image thoroughly to ensure its functionality. Testing the image is needed to confirm that added packages and other changes did not introduce conflicts or other unexpected errors. * Private images built from FIPS-validated starter images or using the FIPS module package add-on may not be FIPS compliant. Testing is required to confirm that the end result does not conflict with FIPS OpenSSL modules. While the image is being built, its card will be shown in the Image Creator gallery with a status label - **in progress**. The build generally takes under 15 minutes, depending on the components. When the image is ready, it will appear with the label **created** and will show a timestamp of when it was first created. Click the button **view image** to dive into the image card. Testing your private image for functionality is the next step. Minimus standard images undergo strict unit testing as described in our [architecture article](/introduction/architecture). Since testing is particular to the exact components of the image, Minimus is not able to cover all testing requirements for private images. ## Package compatibility in private images ### Auto-versioning packages for Ruby, Python & PHP Pairing the right package version with the image version can potentially get tricky. To save you the trouble, Minimus offers auto-versioning packages. Auto-versioning packages automatically detect and install a package version compatible with each of the starter image lines during the build of the private image. Minimus currently offers Ruby, Python, and PHP auto-versioning packages. All auto-versioning package names end with the suffix `-auto` and their description has a fixed format: ```json General format theme={null} Universal package for {package name} - automatically detects and installs a compatible version ``` ```json Example theme={null} Universal package for PHP XML extension - automatically detects and installs a compatible version ``` Examples of auto-versioning package names: * PHP package names: `php-curl-auto`, `php-openssl-auto`, `php-zip-auto` * Python package names: `py3-rsa-auto`, `py3-babel-auto`, `py3-extras-auto` * Ruby package names: `ruby-securerandom-auto`, `ruby-swd-auto`, `ruby-timeout-auto` Each package family appears together as a group to help users select the relevant version or the auto-package. Package Family ### Auto-version logic The general logic of the auto-version packages is as follows: 1. If there is no conflict with the starter image, the auto package will select the `latest` package version for all private image lines. The `latest` version will progress as new package versions are released. 2. If the package is a dependency of another popular package, it will not offer an auto-version since it is not expected to be added directly. For example, `php-posix-config` is considered a dependency of `php-posix-auto`. Therefore there is no `php-posix-config-auto` option. 3. If a version of the package is already in use, the entire package family will be blocked. The package version used by the starter image's `latest` line will be indicated. Starter Image Package Blocked 4. If the auto-package is selected but a compatible version is not found, Minimus Creator will skip it. The SBOM will still show the auto-package but not any specific version, to indicate that the package was skipped. For example, the PHP Imagick extension only has versions for `php-8.4-imagick` or higher. If it is added to a PHP starter image, image line 8.5 will be built with the matching version `php-8.5-imagick`, and image line 8.4 will be built with the matching version `php-8.4-imagick`. Auto Version Package Example Image lines 8.3 and 8.2 will skip the package and their SBOM will only show the `php-imagick-auto` package without any specific version to indicate that the package was skipped. Auto Versionpackageskipped ### Handling package version conflicts Minimus will attempt to build a private image for the newest version of each image line. If a particular image line runs into version conflicts with added packages, Minimus will skip it. The final private image will only include image lines that build successfully without errors. To avoid broken builds, Minimus handles potential package version conflicts in private images automatically: Minimus will attempt to build a private image for every maintained image line of the starter image and skip image lines that don't build successfully. ### Mutable tags Mutable tags (aka floating tags) refer to tags like `latest` that reference a different image over time. The version tagged as `latest` in the private image might not be the same as the starter image, as a consequence of the private image skipping image lines due to conflicts. The general rule is the most advanced version available is tagged as `latest`. For example, the `latest` tag may refer to version `8.3` for a private image and version `8.4` for the starter image. This would happen if the private image skipped `8.4` due to compatibility issues. In this case, the mutable tag `8` would also refer to different image lines, and so forth. ## Managing private images ### Viewing your private images To view a gallery of all your private images, go to [Image Creator](https://images.minimus.io/creator). Here you can create a new private image and edit and manage your existing private images. Private images are also easy to identify in the image gallery: * Private images are labeled as private images * Private images always have a name that begins with the tenant ID, for example, `53/image-name`. Private Image Label ### Editing a private image You can update the added packages and env variables for your private images. The starter image and image name are fixed and cannot be changed. Once updated, the private image will be rebuilt. To edit a private image, go to [Image Creator](https://images.minimus.io/creator) and select **Edit** in the image menu. ### Deleting a private image Private images are all about experimentation. Easily remove outdated or unhelpful private images from your Minimus console. To delete a private image, go to [Image Creator](https://images.minimus.io/creator) and select **Delete** in the image menu. ## Troubleshooting failed builds To view the build status for your private image, go to [Image Creator](https://images.minimus.io/creator). The image card will show the build status on the bottom left. If there were errors, click the status to view more details. Creator Build Status Creator reports build errors with a granularity level of the image line. If only some lines failed, the build status will be shown as **some lines created**. Expand the error message to view more specific details. Image Line Error If all image lines failed, the build status will be shown as **image build failed**. Expand the error message to view more specific details per line. Creator Image Build Failed Whatever the cause of the error, the status message will show the **trace ID** so you can [contact our team for assistance](https://support.minimus.io/support/home). The private image build may fail due to conflicts or incompatible components or another issue. Our team is at your service to help resolve the issues. ## Actions for private images Minimus fully supports actions for private images created by Creator. [Learn more about actions](/remediate/actions) # minicli Source: https://docs.minimus.io/enterprise-edition/minicli Use the minicli command-line tool to define, build, and manage private Minimus images from your terminal or CI/CD pipeline. minicli is the Minimus command-line tool for managing private images. Use it to define, build, and manage private images as code directly from your terminal or CI/CD pipeline. minicli is also natively **AI-agent ready**. With the `generate-skills` command, you can equip AI coding assistants such as Cursor, Claude Code, Windsurf, or GitHub Copilot to create, configure, and inspect your Minimus private images using natural language prompts. ## Installation & authentication Download the latest binary and authenticate to minicli. See [minicli installation](/manage/minicli) ## Commands ### 1. version Display the current version of the minicli binary. Does not require authentication. ```text minicli version lookup theme={null} minicli version ``` ```text output example theme={null} minicli version 1.0.5 ``` ### 2. generate-skills `minicli` is designed to be natively **AI-agent ready**. You can empower your favorite AI coding assistants (such as Cursor, Windsurf, GitHub Copilot, or other local LLM tools) to natively understand and interact with `minicli`. Because different AI tools look for project instructions in different directories, use the `--output` flag to add the skills in the appropriate folder for your specific assistant. ```bash theme={null} minicli generate-skills --output {path-to-your-ai-context-folder} ``` | Flag | Shorthand | Description | | ---------- | --------- | ------------------------------------------------------------------------- | | `--output` | `-o` | Path to the AI assistant's context folder where skills should be written. | | `--help` | `-h` | Prints the help menu and available flags | #### Example: Equipping Cursor Cursor looks for custom skills in the `.cursor/skills` directory of your project. ```bash theme={null} minicli generate-skills --output /.cursor/skills # example minicli generate-skills --output ~/GolandProjects/awesomeProject/.cursor/skills ``` Once generated in the correct folder, your AI agent will automatically pick up these skills, allowing it to act as an expert Minimus assistant within your project. #### Example AI workflows with minicli Once the skills have been generated, you can open your AI chat interface and start prompting. Here are a few ways to interact with your agent: Ask the agent to scaffold a completely new image using a specific starter image and inject environment variables and packages. > "Using minicli skills, create a new private image called `my-test-image-skills` based on the `go` starter image, with packages `curl` and `git`, and environment variable `ENV=production`. Walk me through the steps." The agent can read your existing image recipes, update them, and re-apply the changes without you needing to manually edit the YAML or run the CLI commands yourself. > "I have an existing private image called `demo-image`. Export its config, add the `agetty` and `agetty-openrc` packages to it, as well as the env var `SOMETHING=INBAR` and the file bundle `bb-2`, and re-apply." Let the agent do the querying for you when you need to check what's currently running or inspect the exact configuration of a specific image. > "Ok, now list the images, then get all details on the `demo-image` image and print them to me." ### 3. image init Create a local YAML template with all supported image fields, pre-populated with empty values for you to fill in. ```text image init theme={null} minicli image init ``` ```text custom path theme={null} minicli image init --output path/custom.yaml ``` ```text default output theme={null} YAML template successfully created! Saved to: image.yaml ``` | Flag | Shorthand | Description | | ---------- | --------- | ----------------------------------------------------- | | `--output` | `-o` | File path to save the template. Default: `image.yaml` | | `--help` | `-h` | Prints the help menu and available flags | The generated file will include notes to help clarify its use. Below is the default output and the bare structure stripped of the notes: ```text default image.yaml expandable lines theme={null} schemaVersion: v1 # Required. The private image Unique name is used as the remote identifier. name: "" # Required. The private image builds on a starter image from your organization's subscribed images. starterImage: "" # Optional. List of additional packages to install in the private image alongside the starter image packages. For example: # additionalPackages: # - pkg1 # - pkg2 additionalPackages: # Optional. Environment variables to set in the private image (map of KEY: VALUE). String values only. For example: # envVars: # Key1: "value1" # key2: "value2" envVars: # Optional. File bundles to include in the private image (list of file bundle IDs). For example: # fileBundles: # - bundle-id1 # - bundle-id2 fileBundles: # Optional. Free-text description of the private image to be shown in the gallery UI. description: "" ``` ```text bare structure (without notes) lines theme={null} schemaVersion: v1 name: starterImage: additionalPackages: envVars: fileBundles: description: ``` Once you fill in an image recipe, it might look like this: ```text image recipe example lines theme={null} schemaVersion: v1 name: trino-plugins starterImage: trino additionalPackages: - trino-plugin-mysql - trino-plugin-cassandra - trino-plugin-ai-functions envVars: {} fileBundles: [] description: added trino-plugin-ai-functions trino-plugin-cassandra trino-plugin-mysql ``` ### 4. image apply Create or update a private image recipe from a local YAML file. Follow up with the command `image build submit` to trigger a build of your updated image. ```bash apply a private image recipe theme={null} minicli image apply --file images/custom.yaml ``` ```text output example wrap theme={null} Success! Applied updates to the private image recipe! Image name: my-image Run 'minicli image build submit --name img' to trigger an image build using the updated recipe. ``` | Flag | Shorthand | Description | | -------- | --------- | ---------------------------------------- | | `--file` | `-f` | Required. Path to the YAML file | | `--help` | `-h` | Prints the help menu and available flags | If the YAML is invalid, minicli returns a detailed list of errors, for example: ```text theme={null} ✗ YAML file validation failed: - envVars: "INVALID_KEY" is not a valid key=value format. - other: invalid field (doesn't exist). ``` ### 5. image build submit Trigger an asynchronous build for a private image. Returns immediately without waiting for the build to complete. ```text image build submit theme={null} minicli image build submit --name my-image ``` ```text output example theme={null} Success! Private image build was triggered! Run 'minicli image build status --name trino-plugins' to track progress. ``` * You can run `minicli image build status --name {private-image-name}`to track progress. * Once the build is complete, you can view the image's detailed build report in the Creator UI. This is particularly helpful if the build did not succeed. The image build report will show you which packages were incompatible. [Learn more](/enterprise-edition/image-creator) | Flag | Shorthand | Description | | -------- | --------- | ---------------------------------------- | | `--name` | `-n` | Name of the private image to build | | `--help` | `-h` | Prints the help menu and available flags | ### 6. image build status Look up the current status of a private image build. ```text image build status theme={null} minicli image build status --name my-image ``` ```text command example theme={null} minicli image build status --name trino-plugins ``` ```text output example theme={null} Build Status: BUILDING Last updated: 2026-06-02 14:25:12 ``` | Flag | Shorthand | Description | | -------- | --------- | ---------------------------------------- | | `--name` | `-n` | Name of the private image | | `--help` | `-h` | Prints the help menu and available flags | ### 7. image export Retrieve the configuration of a remote private image and output it in YAML file. You can export private image recipes to track changes in git. ```text image export theme={null} minicli image export --name my-image minicli image export --name my-image --output export.yaml ``` ```text output example theme={null} Success! Image recipe exported for private image: my-nginx ``` | Flag | Shorthand | Description | | ---------- | --------- | ----------------------------------------------------- | | `--name` | `-n` | Name of the private image to export | | `--output` | `-o` | File path to write to. If omitted, prints to terminal | | `--help` | `-h` | Prints the help menu and available flags | YAML output example: ```yaml theme={null} schemaVersion: v1 name: test starterImage: go additionalPackages: - 7zip envVars: {} fileBundles: [] description: "Test private image" ``` ### 8. image list List your Minimus private images: ```text list private images theme={null} minicli image list ``` ```text table output example (default) theme={null} PRIVATE IMAGES ID NAME STARTER IMAGE STATUS CREATED UPDATED 289 trino-plugins trino COMPLETE 2026-05-03 14:15:06 2026-06-02 14:35:58 244 rabbitmq-cert rabbitmq COMPLETE 2026-04-12 13:27:21 2026-06-01 12:24:08 245 mongo-cert mongo COMPLETE 2026-04-12 13:43:15 2026-05-31 03:23:58 ``` ```json json output example theme={null} ~$ minicli image list -o json [ { "additionalPackages": [ "trino-plugin-mysql", "trino-plugin-cassandra", "trino-plugin-ai-functions" ], "buildStatus": "COMPLETE", "createdAt": "2026-05-03T14:15:06.946784Z", "description": "added trino-plugin-ai-functions trino-plugin-cassandra trino-plugin-mysql", "id": 289, "name": "trino-plugins", "starterImage": "trino", "updatedAt": "2026-06-02T14:35:58.035916Z" }, { "additionalPackages": [ "go-1.22", "7zip-doc" ], "buildStatus": "COMPLETE", "createdAt": "2025-11-23T14:48:00.376719Z", "description": "Some description", "id": 79, "name": "test-elasticsearch", "starterImage": "elasticsearch", "updatedAt": "2026-06-02T13:00:04.655249Z" } ``` | Flag | Shorthand | Description | | ----------- | --------- | ---------------------------------------------------- | | `--private` | `-p` | List private images. Default: `true` | | `--starter` | `-s` | List starter images available in your license | | `--output` | `-o` | `table` (default) or `json`. Prints to the terminal. | | `--help` | `-h` | Prints the help menu and available flags | You can also list the starter images available in your license for building private images: ```bash list starter images theme={null} minicli image list -s ``` ```json table output example theme={null} STARTER IMAGES The following images are included in your account license: nginx postgres cassandra ``` ```json json output example theme={null} ~$ minicli image list -s -o json { "allImagesEnabled": true, "images": [] } ``` ### 9. image get Get the full details of a private image. ```bash image get theme={null} minicli image get --name my-image ``` ```text table output example (default) theme={null} Image Details: ----------------------------------- ID: 289 Name: trino-plugins Starter Image: trino Additional Packages: trino-plugin-mysql, trino-plugin-cassandra, trino-plugin-ai-functions Env vars: Build Status: COMPLETE Created At: 2026-05-03 14:15:06 Updated At: 2026-06-02 14:35:58 Description: added trino-plugin-ai-functions trino-plugin-cassandra trino-plugin-mysql File Bundles: ``` ```json json output example theme={null} minicli image get --name trino-plugins -o json { "additionalPackages": [ "trino-plugin-mysql", "trino-plugin-cassandra", "trino-plugin-ai-functions" ], "buildStatus": "COMPLETE", "createdAt": "2026-05-03T14:15:06.946784Z", "description": "added trino-plugin-ai-functions trino-plugin-cassandra trino-plugin-mysql", "id": 289, "name": "trino-plugins", "starterImage": "trino", "updatedAt": "2026-06-02T14:35:58.035916Z" } ``` | Flag | Shorthand | Description | | ---------- | --------- | --------------------------------------------------- | | `--name` | `-n` | Name of the private image | | `--output` | `-o` | `table` (default) or `json`. Prints to the terminal | | `--help` | `-h` | Prints the help menu and available flags | ### 10. bundle list List all file bundles in your account. File bundles are used to include public keys for internal PKIs (Public Key Infrastructure certificates) and override configuration files and more. [Learn more](/enterprise-edition/file-bundles) ```bash list file bundles theme={null} minicli bundle list ``` ```bash table output example (default) theme={null} ID NAME DESCRIPTION TYPE FILES PATH CREATED UPDATED 46 nginx.conf generic [nginx.conf (0 KB)] /etc/nginx 2026-02-17 13:51:54 2026-05-26 09:09:26 224 mongo-client-cert certs [cert-test.cert (2 KB)] /usr/local/share/ca-certificates/ 2026-04-12 13:48:59 2026-04-12 14:30:46 223 mongo-cert certs [client.pem (3 KB)] /usr/local/share/ca-certificates/ 2026-04-12 13:43:02 2026-04-12 13:43:02 222 RabbitMQ-certs certs [ca_certificate.pem (1 KB)] /usr/local/share/ca-certificates/ 2026-04-12 13:26:52 2026-04-12 13:26:52 ``` ```text json output example theme={null} ~$ minicli bundle list --output json [ { "createdAt": "2026-02-17T13:51:54.803871Z", "files": [ { "name": "nginx.conf", "sizeBytes": 105 } ], "id": 46, "name": "nginx.conf again and again", "path": "/etc/nginx", "type": "generic", "updatedAt": "2026-05-26T09:09:26.297413Z" }, { "createdAt": "2026-04-12T13:48:59.213012Z", "files": [ { "name": "cert-test.cert", "sizeBytes": 2010 } ], "id": 224, "name": "mongo-client-cert", "path": "/usr/local/share/ca-certificates/", "type": "certs", "updatedAt": "2026-04-12T14:30:46.213012Z" } ``` | Flag | Shorthand | Description | | :--------- | :-------- | :--------------------------------------------------- | | `--output` | `-o` | `table` (default) or `json`. Prints to the terminal. | | `--help` | `-h` | Prints the help menu and available flags | ### 11. image delete Delete a private image from your account. Prompts for confirmation unless `--force` is passed. The image will also be removed from Creator and will no longer be available for use. ```bash image delete theme={null} minicli image delete --name my-image ``` ```bash skip confirmation theme={null} minicli image delete --name my-image --force ``` ```text output example theme={null} Are you sure you want to delete "test"? This action cannot be undone. [y/N]: y Image "test" successfully deleted! ``` | Flag | Shorthand | Description | | --------- | --------- | ---------------------------------------- | | `--name` | `-n` | Name of the private image to delete | | `--force` | `-f` | Skip the confirmation prompt | | `--help` | `-h` | Prints the help menu and available flags | # Supply Chain Protection Source: https://docs.minimus.io/enterprise-edition/supply-chain Set up guardrails to prevent malicious package uploads based on age, download reputation and more using Minimus supply chain policies Use Minimus supply chain protection to govern package installations and enforce stronger security standards. Public repositories such as npm and pip are frequent targets for malicious package uploads and Minimus supply chain policies can help mitigate the risks with minimal setup. Supply Chain Policy 1 ## Supported environments Currently the following ecosystems are supported: * Node * Python Minimus is actively working on adding support for additional environments to supply chain policies. ## Create a Minimus supply chain policy Policies are activated via an environment variable added to a Dockerfile or during runtime with any Minimus images. It's standard practice to set up stricter policies for production and relax controls for dev environments. You can select a policy from the provided templates or create one from scratch. Provide a name and description to identify the purpose of the policy and help your teammates understand its intended purpose. Decide if the policy should block suspicious packages or alert on them: * If you select block, the policy will prevent installation of packages that trigger the policy guardrails and will fail builds.    * If you select alert, the policy will generate security alerts in the Minimus Audit Log.  Set the policy's risk thresholds and trust requirements. A violation of any of these rules will activate the policy. * **Cooling-off period** - Protects against package versions that haven't been out long enough to be vetted by the community. It sets a minimum number of days since the version's release.  * **Popularity** - Protects against packages that haven't yet been vetted by the community. It sets a minimum number of monthly downloads across all versions.  * **Typosquatting risk** - Toggle this setting on to enable it. It protects against packages with suspicious names, misspellings, or look-alikes of popular packages. * **Suspicious version release** - Toggle this setting on to enable it. It protects against package versions present on a registry that lack a corresponding tag, release, or entry in the project's GitHub repository. Add packages to the allowlist or blocklist to bypass the policy.  The policy will be added the list with its name and environment variable. ## Activate Minimus supply chain policy for npm Once the policy is ready add the environment variable to your Dockerfile or runtime command to activate the policy and protect your supply chain. Currently the policy protects npm and should be activated for Minimus images that include npm. These may be Node-based images or private images that include npm. Format of the environment variable: `-e NPM_CONFIG_REGISTRY="https://-${IMAGE_NAME}.supplychain.mini.dev` Example of a Minimus supply chain policy activated in a Docker run command: ```text Run command example wrap theme={null} docker run -e NPM_CONFIG_REGISTRY="https://157-5-${IMAGE_NAME}.supplychain.mini.dev" \ ``` Example of a Minimus supply chain policy activated via a Dockerfile: ```text Dockerfile example with Minimus supply chain policy theme={null} FROM reg.mini.dev/node ENV NPM_CONFIG_REGISTRY="https://153-8-${IMAGE_NAME}.supplychain.mini.dev" COPY package.json ./ RUN npm install ``` You can add the environment variable to any of your Minimus Node environments. For example, if you want to try out the [quick start example](https://images.minimus.io/images/node/quick-start) for the Minimus Node image with the supply chain policy, adjust the run command to include the policy environment variable `-e NPM_CONFIG_REGISTRY`: ```text Example of run command with supply chain policy activated theme={null} docker run -e NPM_CONFIG_REGISTRY="https://153-8-${IMAGE_NAME}.supplychain.mini.dev" \ -p 3000:3000 -d --name minimus-node \ -v $(pwd)/hello-minimus-node.js:/home/hello_world/hello-minimus-node.js \ reg.mini.dev/node:latest \ /home/hello_world/hello-minimus-node.js ``` You can exec into your running containers to test package installs manually. The following command assumes your container name is `minimus-node`: ```text theme={null} docker exec -it minimus-node bash ``` ## Test your supply chain policy For testing purposes, we will run`reg.mini.dev/node:latest-dev` with a Minimus supply chain policy set to alert and open a shell: ```text Test supply chain policy with node:latest-dev theme={null} docker run -it -e NPM_CONFIG_REGISTRY="https://153-8-node.supplychain.mini.dev" \ reg.mini.dev/node:latest-dev /bin/sh # Replace `153-8` with your policy ID ``` Inside the running container, verify npm is pointed at your policy: ```text confirm policy theme={null} npm config get registry ``` ```text expected output theme={null} https://.supplychain.mini.dev # example: https://1257-node.supplychain.mini.dev ``` Install a well-known, high-download package — it should pass without issue: ```bash theme={null} npm install lodash ``` Test the **cooling-off period** guardrail by finding and installing a recently published package version:  First, check when recent versions of a package were published. (This command works best when the policy is in alert mode. In block mode, the policy will only fetch packages that aren't blocked): ```text command template theme={null} npm view time --json | tail -5 ``` ```text react package example theme={null} npm view react time --json | tail -5 ``` Install a version published within your cooling-off window so it triggers the policy: ```text command template theme={null} npm install @ ``` ```text block package example wrap theme={null} bash-5.3$ npm install react@19.2.7 npm error code ETARGET npm error notarget No matching version found for react@19.2.7. npm error notarget In most cases you or one of your dependencies are requesting a package version that doesn't exist. npm error A complete log of this run can be found in: /home/node/.npm/_logs/2026-06-03T12_54_53_799Z-debug-0.log ``` ```text alert package example theme={null} bash-5.3$ npm install react@19.2.7 changed 1 package, and audited 4 packages in 1s found 0 vulnerabilities ``` * If your policy is set to **block**, the install will return an error and an alert is generated in the Minimus Audit Log. * If your policy is set to **alert**, the install will succeed and an alert is generated in the Minimus Audit Log. Try installing a package with a suspicious name to test the typosquatting guardrail: ```text test a typosquatted package theme={null} npm install expres ``` ```text block package example wrap theme={null} bash-5.3$ npm install expres npm error code E403 npm error 403 403 Forbidden - GET https://1257-node.supplychain.mini.dev/expres npm error 403 In most cases, you or one of your dependencies are requesting a package version that is forbidden by your security policy, or on a server you do not have access to. ``` * If your policy is set to **block**, the install will return a 403 error and an alert is generated in the Minimus Audit Log. * If your policy is set to **alert**, the install will succeed and an alert is generated in the Minimus Audit Log. Open the **Audit Log** in Minimus to review policy activity from your test run, including any blocked installs or alerts ([direct link](https://images.minimus.io/manage/logs/audit-log)).  ## Summary You can test each guardrail individually using these tips: | Guardrail | How to trigger it | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Cooling-off period | Install a package version published within the last N days | | Popularity | Install an obscure package with very few weekly pulls | | Typosquatting | Try a common misspelling like `expres`. Keep in mind that detection is heuristic and depends on the policy's algorithm so it may not trigger | | Suspicious version | Install a version that exists on npm but lacks a corresponding GitHub release tag | # Daily security updates Source: https://docs.minimus.io/foundations/daily-updates Understand the Minimus release cycle for images and packages ## Daily security updates For every image line, the most recent version is actively maintained by Minimus. This means Minimus builds the most recent image version within every image line every time there is an update in any of the internal packages or their dependencies. [See architecture](/introduction/architecture) Once a new version is published in an image line, active maintenance is transferred to the new version. For example, nginx is typically released every 2 months ([ref](https://nginx.org/en/CHANGES)). Between these version releases, vulnerabilities are discovered and fixed in different packages that make up the image. Minimus builds all packages from source daily and then rebuilds the images from the most recent packages every day. This process ensures that Minimus delivers the most secure images available to its users as soon as possible. ### Package release cycle Minimus builds packages on a rolling basis, as soon as an update is available upstream. If a new package version fixes a vulnerability, the advisory status will be changed to fixed as soon as the package is fixed. Affected images will show as **pending image build** until the daily image build cycle completes and the new fixed version is released by Minimus. [Learn more](/remediate/fix-date#package-fixed-but-pending-image-build) ### Image release cycle Minimus builds fresh images once a day from the latest packages. The images that Minimus actively maintains are always the **last version in every image line**. Older versions in every image line will begin to accrue vulnerabilities once they are no longer actively maintained. This will become clear from the vulnerability count and severity distribution. This is a good indication that you should upgrade to a newer version as soon as possible. Python Image In the above example, Python version `3.14.6`, the latest version in the image line, is actively maintained with new daily builds and package updates. Previous versions are not being rebuilt and will quickly accrue vulnerabilities. ## Internal package updates Minimus maintains the most recent version in each image line on a daily basis. Image versions that are actively receiving updates will be rebuilt whenever there are packages to update. These internal updates will not affect the image version, but will be recorded in the image [Changelog](/foundations/image-card#changelog) and the [Digest History](/foundations/image-version#digest-history). ### Same image version tag, different SBOM The image version can be rebuilt without a change in the image version tag. The image version tag will stay the same, but the image will have a different SBOM, digest, and timestamp tag. The vulnerability status may be different too. The image is functionally the same, but packages under the hood have changed. The image **version tag** is determined by the version of the primary package (e.g. package `nginx` in the nginx image, package `python-x.xx` in the Python image, and so forth). Other packages in the image are updated by Minimus on a daily basis, in keeping with the package and image release cycle. ### Unique timestamp tag Minimus uses a unique timestamp tag to identify its images in addition to the digest. The timestamp tag is a human-readable alternative to the image digest developed by Minimus. The unique timestamp tag can help you easily tell apart different builds for the same image version and reliably pull the most recent build for a specific version. Python Timestamp Tag The timestamp tag indicates when the build was published, for example: * `elasticsearch:8.17.2-dev-202503040032` is the tag for the Elasticsearch image version `8.17.2` built on March 4, 2025 at 00:32 UTC. * `nginx:1.27.4-202503070038` is the tag for the NGINX image version `1.27.4` built on March 7, 2025 at 00:38 UTC. ## Example Let's look at an example to see how the image build cycle is reflected in the Minimus console. Consider Zookeeper's latest image. On July 1, 2026, it was version `3.9.5`. When this screenshot was taken, the version had been out for over 3 months ([link to image](https://images.minimus.io/images/zookeeper/lines/3.9)). Latest Zookeeper Example Upon closer inspection, you will notice the Minimus image was built the same day. This follows the Minimus image release cycle: the most recent version in every image line is continuously being rebuilt with the latest packages whenever there are package updates to deliver. Next, visit the [**image changelog**](https://images.minimus.io/images/zookeeper/changelog/3.9) to view all of the times that Zookeeper version `3.9.5` was updated by Minimus. The changelog shows there are 57 different digests for the same image version. This means that Minimus published the Zookeeper image version `3.9.5` 57 times since the version was first released. The changelog lists all of these updates and shown which package updates were delivered and which CVEs were fixed. Zookeeper Changelog Digest Count In the changelog, click **compare digests** to view the [Digest History](https://images.minimus.io/images/zookeeper/changelog/3.9/versions/3.9.5-dev/digest-history), a condensed list of all of the builds for the selected image version. The Digest History view focuses on the current vulnerability count and severity for each of the image builds. You can copy the pull command for each digest and unique timestamp tag. Zookeeper Digest History ## Pull specific build by digest or unique timestamp tag You can use the respective copy buttons in the Minimus **Digest History** tab to pull the specific build of an image version by either the digest or unique timestamp tag. ```text Example pull by digest theme={null} docker pull reg.mini.dev/zookeeper@sha256:2a6f56d49d1e8300... ``` ```text Example pull by timestamp tag theme={null} docker pull reg.mini.dev/zookeeper:3.9.4-202602070044 ``` ## Avoiding cached images To get the most secure image, it's important to pull a fresh Minimus image every time. Docker, Kubernetes, and Helm will often default to using a cached image unless explicitly directed to pull a fresh image. [Learn how to force a fresh image pull](/foundations/pull-policy) # Going Distroless with Minimus Source: https://docs.minimus.io/foundations/going-distroless How Minimus helps teams migrate from traditional distribution-based images to distroless images with ease ## Distroless explained Distroless container images are minimal container images without a traditional Linux distribution such as Alpine, Red Hat UBI, Debian, Ubuntu, and Fedora. Distroless images are greatly slimmed down so they contain only the essential runtime dependencies required for an application to run and exclude package managers, shells, and debugging tools. ### Faster pace of release Since Minimus images are built directly from source, they are not dependent on a third-party operating system like Alpine or Debian. As a result, Minimus is able to release the updated packages within hours of the change in the upstream code and build images with the updated packages on a daily basis. ### Reduced attack surface Container images built on traditional Linux distributions carry significant security and operational overhead. They include package managers, shells, and numerous other utilities that expand the attack surface and increase image size. By removing everything except the runtime requirements and direct dependencies, distroless container images drastically reduce their package count and thereby their attack surface. Without shells, package managers, or development utilities, distroless images provide a minimal, hardened foundation for production workloads that align with security best practices: the less code in your production image, the fewer vulnerabilities now and in the foreseeable future. ## The Minimus distroless solution ### The challenge: building without traditional tools The primary challenge when adopting distroless images is the build process itself. Traditional Dockerfiles rely on distribution package managers like `apt-get`, `yum`, or `dnf` to install dependencies during image construction. A pure distroless image cannot accommodate these commands, creating a migration barrier. ### The Minimus solution: production & dev image pairs The packages necessary to *build* an app often differ from the packages necessary to *run* the app. This understanding led Minimus to solve the distroless challenge through the complementary image pair strategy. Every Minimus image version comes in two variants: a production image and a dev image. The production image is lean and distroless, containing only runtime essentials. The dev variant includes development tools, a shell, a package manager, and anything else needed to build and test applications using familiar workflows. [Learn more about Minimus dev images](/introduction/image-variants) ### General process adjustments Adopting the Minimus solution can help you drastically improve your security posture. The distroless approach also involves the following practices: * Moving out dev libraries from the production image. [Learn more](/introduction/image-variants) * Separating the build stage from the runtime final build using multi-stage builds. [Learn more](/guides/multi-stage-build) * Escalating privileges temporarily in the Dockerfile build stage to compensate for the non-root default user. [Learn more](/basics/user) * Using Python virtual environments (venv) and other similar options. [See example](/guides/aws-lambda-deployment) * Switching to sidecar debugging tools so the production image doesn't always include the extra packages. [Learn more](/debugging/ephemeral-container) ## What's included in a distroless image? A Minimus production image, like any distroless image, contains only the essentials to run: * The application binary and its required dependencies * Core runtime libraries (e.g., glibc) * Certificates (for TLS) * Language runtimes, if required (e.g., Python, Java, Node.js) Since the fully distroless image is often too slim to work with during development, every Minimus production image has a complementary dev image variant that includes required developer tools, such as a package manager, shell, etc. ### Package count comparisons The SBOM of Minimus production images will (almost) always show a drastic reduction in the number of packages compared to the equivalent Ubuntu, Debian, and even Alpine image. | **Image Type** | **Typical Package Count** | | :--------------------------- | :------------------------ | | Ubuntu-based image | \~200–400+ packages | | Alpine image | \~50–100 packages | | **Minimus production image** | **\~10–30 packages** | Minimus production images are that much slimmer because they exclude the following: * Shells (/bin/sh, bash) * Package managers (apt, apk, yum) * Core utilities (ls, cat, cp, etc.) * Compilers and interpreters (unless essential for the application) * System services or init systems Minimus dev images will include these tools to allow users to keep their workflows and leverage multi-stage build techniques to produce more secure apps. [Multi-stage builds with Minimus](/guides/multi-stage-build) ### nginx example The nginx image is an interesting case in point. The [standard image on Docker Hub](https://hub.docker.com/_/nginx) has over 240 packages. The Minimus nginx image has 15 packages. That's well over a 90% reduction in the number of packages. The [SBOM for the nginx latest image](https://images.minimus.io/images/nginx/lines/1.29/versions/1.29.0/sbom) shows the packages in the image include `nginx-{version}` and associated packages, `ca-certificates-bundle`, the core runtime library `glibc` and associated packages, and `zlib` for compression. ## Migrating to distroless images with Minimus ### Using multi-stage builds You can instantly benefit from Minimus distroless images while still maintaining your existing build processes by adopting multi-stage builds and leveraging Minimus production-dev image pairs. In a multi-stage Dockerfile, you use the `dev` image (for example, `dotnet-sdk:latest-dev`) for the build stage which requires a package manager and development tools. Then you copy your artifacts and use the production image for the final runtime stage (for example, `dotnet-sdk:latest`). [See multi-stage build tutorials for go](/guides/golang) This approach will allow you to maintain your existing build processes. You can continue using `apt-get`, `curl`, and other familiar commands in your build stages, while your final image remains minimal and secure. ### Experimenting with direct package access If you prefer, you can install Minimus packages directly using a package manager with Minimus images. Package access allows you to add Minimus packages directly in your Dockerfile. With direct package access, you’ll be responsible for rebuilding when packages are updated to fix CVEs. Image Creator - available with Enterprise Edition - automates this process, which is why it’s recommended. [Learn more](/basics/package-manager-access) ### Customizing private images (Enterprise Edition) Once comfortable with Minimus images, you can move security forward with the [Minimus Image Creator](https://docs.minimus.io/enterprise-edition/image-creator). Instead of installing packages at build time, you can pre-configure your private image with exactly what you need. This simplifies Dockerfiles, reduces build complexity, and further optimizes your container security posture. [Image Creator](https://images.minimus.io/creator) enables you to customize Minimus images to meet your application requirements by adding specific packages, defining custom environment variables and more. Private images built with the Image Creator are actively maintained by Minimus just like any standard Minimus image, including daily updates, continuous vulnerability scanning, compliance reports, signatures, and a complete SBOM (Software Bill of Materials) report. ### Building off static (Enterprise Edition) If you are used to building an image from scratch by pulling a starter base image from Alpine or another distribution on Docker Hub and adding your own packages, Minimus Creator offers an optimal solution. Here's how it works: If you are starting from a language framework, you can select the relevant image as your starter image, whether it is Ruby, Golang, etc. Otherwise, you can build off of [Static](https://images.minimus.io/images/static/lines/latest), [Glibc-Dynamic](https://images.minimus.io/images/glibc-dynamic/lines/latest), [Glibc-Dynamic-FIPS](https://images.minimus.io/images/glibc-dynamic-fips/lines/latest) or another [base image](https://images.minimus.io/?category=base) from the Minimus gallery. As the next stage, you can add any number of packages as suits your needs. The package selector offers every package available from the MinimOS distro, including FIPS alternatives. You can build anything you set your mind to. The Minimus build pipelines take care of building the image and maintaining and updating it daily, and will alert you of any conflicts or other issues if encountered. Building your private distroless image from scratch is truly effortless with Minimus Creator. As an added benefit, Creator also supports bundling certificate files and custom configuration files, and managing environment variables as part of the build. Minimus Creator outputs a single-layer image which has the advantage of being smaller and faster to pull than an image built with Dockerfile. # Helm Charts Source: https://docs.minimus.io/foundations/helm-charts Deploy secure apps faster with Minimus Helm charts for Minimus images Helm is the package manager for Kubernetes. It contains all the necessary resource definitions (YAML files) to run an application, tool, or service inside a Kubernetes cluster. Minimus Helm charts complement Minimus images and offer a one-stop shop for setting up a deployment workflow for secure Minimus images. Helm Charts Gallery ## Helm chart versions Select a Helm chart from the list to view available chart versions. Each chart version deploys a specific app version, as listed. The current known vulnerability count is shown as well. Chart Version ### Chart version Chart versions match the upstream open source chart. You can view the upstream chart in the Chart tab. For example, the [Minimus cert-manager chart](https://images.minimus.io/charts/cert-manager/v1.20.3/chart) tracks the upstream chart [https://charts.jetstack.io](https://charts.jetstack.io). ### App version The application version reflects the version of the primary image deployed by the chart. The image version included in every Helm chart is listed in the Helm chart card along with a shortcut link to view the image card directly. ## Chart card Select the relevant chart version to view the chart guide and default values. The chart version card lists all of the Minimus images deployed by the chart and their respective versions. Chart Details The chart version card includes the following: * **Chart Guide** - The quick start guide provides the commands for deploying the chart version. * **Chart** - The default configurations in the `Chart.yaml` file. * **Values** - The defaults in the `values.yaml` file. It points the chart to Minimus images. * **Chart Signature** - This tab provides the command used to verify the Helm chart using Cosign to confirm it was published by Minimus and was not modified post-publication. Chart Tabs ## Risk reduction The risk reduction tab helps you understand the security benefits of deploying a Minimus Helm chart over the equivalent public chart. Because a chart deploys a set of images rather than a single image, the comparison focuses on the overall vulnerability reduction across the images the chart deploys directly. The risk reduction data is compiled once a day (the time of the report is indicated). For the most recent vulnerability report of an individual image, see its [image card](/foundations/image-card#risk-reduction). * The **Vulnerabilities Comparison** graph shows the sum of confirmed vulnerabilities impacting all of the images deployed by each Helm chart, over the previous 30 days. Some vulnerabilities may impact multiple images and/or packages. The count is broken down by severity, so you can toggle between **Total**, **Critical**, **High**, **Medium**, **Low**, and **Unknown** and see the reduction for each. The comparison covers the images deployed directly by the chart; images deployed by any subcharts, if present, are not included. * The **Detailed Vulnerability Comparison** table lists all of the CVEs impacting the images deployed by each chart. Toggle between the Minimus chart and the public chart to review each list. * Click an item in the table to open the vulnerability card with further information about the CVSS severity score, exploitability, references, and a direct link to the NVD listing. ## Request a Helm chart The Minimus Helm chart gallery is growing, with new charts added regularly. As we continue working to expand our offering, we also gladly accept requests. [Contact us](https://www.minimus.io/contact) to submit your request. ## Unauthenticated deployment You can deploy Minimus Helm charts with Community Edition. The pod will write a warning log which can be safely ignored: ```text wrap theme={null} Warning FailedToRetrieveImagePullSecret 5s (x9 over s) kubelet Unable to retrieve some image pull secrets (minimus-registry); attempting to pull the image may not succeed. ``` To view the warning log, run the `kubectl describe pod` command, for example: ```text theme={null} kubectl describe pod my-rabbitmq-advanced-0 -n rabbitmq-advanced ``` ## Helm chart revamp Minimus Helm charts are being migrated to track upstream chart versioning, replacing proprietary charts that were previously versioned independently starting at 0.1.0. During the transition, both versions may appear in the gallery. Deprecated chart versions will be removed over the coming weeks. # Image Card Source: https://docs.minimus.io/foundations/image-card Explore the information for every type of image, including available image versions, versioned vulnerability reports, SBOM, and risk reduction comparison ## Tabs ### Versions The versions tab is a visual display of the images in the Minimus repository. The display includes 2 components: * The left minimap lists the image lines for quick navigation. * The main display shows all of the versions available for a selected image line. The image lines are arranged by their support timeline to help users understand which versions will be available the longest. [Learn more](#eol-details) Example Image Line Order Select an image line to view all of the versions available from Minimus, arranged chronologically. Image Line Internal Display Images are shown in pairs: a production version alongside a dev version. The dev version is fitted with a few extra developer tools intended for specific use-cases. [About image variants](/introduction/image-variants) For every image version the following is shown: * The recommended tag with the option to copy the pull command in one-click with an embedded active token. A tally shows the number of alternative tags available. Click the version to drill down on it and see the full list of available tags. [About the image version card](/foundations/image-version) * A summary of the number of vulnerabilities currently impacting the image version broken down by severity categories. Vulnerability data shown on this page is current and updated often. An indication is shown if there are new vulnerabilities under review that have not yet been confirmed. * An exploitability label shows if the image is currently affected by an active or likely exploit. [Learn more](/remediate/threat-intel#exploitability-label) * A pull counter shows the number of times the image version was pulled by the organization (or by you, if you are on a personal account). To lookup which exact digest was pulled, dive into the digest history. [Learn more](/foundations/image-version#digest-history) * The compressed image size for the amd64 architecture is listed. ### Quick start The quick start guide offers a few simple commands to help get started with the Minimus image, along with some pointers on how it is different from the public image. For in-depth instructions, refer to the documentation provided by the source project. ### Risk reduction The risk reduction tab offers a security posture summary report and compares the vulnerability report and package composition between the Minimus `latest` and `latest-dev` versions and the `latest` public image. Toggle the view between `latest` and `latest-dev` to review the relevant comparison. Vulnerabilities Comparison * The **Vulnerabilities Comparison** graph shows a comparison of the unique CVE count over the previous 30 days. Vulnerabilities detected and fixed on the same day are not included. If you're interested in all fixes reported for a Minimus image, visit the [image changelog](/foundations/image-card#changelog) instead. * The **Detailed Vulnerability Comparison** table lists all of the CVEs impacting each of the images: the latest Minimus image and the public image. * For each vulnerability, the full list of impacted packages is provided. * Click an item in the table to open the vulnerability card with further information about the CVSS severity score, exploitability, references and a direct link to the NVD listing. * The **Size Comparison** widget compares the compressed image sizes for amd64. Note that the data for the risk reduction comparison is compiled once a day (The time of the report is indicated). For the most recent vulnerability report for the latest image, see the [image version card](/foundations/image-version). The **Package Count & Risk Comparison** graph illustrates the difference in the number of packages used by each. The **Detailed Package Comparison** table provides an SBOM comparison detailing which packages are used in the Minimus latest image versus the public image, and shares key information about each of the packages including the version in use, license type, and number of vulnerabilities currently affecting the package. Note that the package comparison graphs respond to the top toggle between `latest` and `latest-dev` to show the respective report. Package Count Risk Comparison ### Compliance The compliance tab demonstrates how the Minimus image meets security, licensing, and regulatory requirements. The information is organized in the following tabs: CIS, NIST, FIPS, STIG, image signature, and SBOM signature. [Learn more](/compliance/image-compliance) Compliance Tab ### Changelog A comprehensive changelog maps the image by image line and version, detailing every digest built by Minimus and the changes delivered by every image build. The data is organized by image line and image version as usual. Use the filtering options and search bar to easily track vulnerability fixes, package version updates, packages added or removed, maintenance updates and more. Expand an entry in the changelog to view more details such as which CVE was fixed and what packages it affected, which packages were updated to what version, etc. Hover over an entry to select the option to **compare digests**. This button will open the **Digest History** tab within the image version card. The digest history view shows the latest number of vulnerabilities reported for each image digest and their severity. [Learn more about the Minimus image update policy](/foundations/daily-updates) Changelog Filtering * Toggle between **Prod** and **Dev** images. Production and development image lines are shown separately. * Expand any fixed vulnerability entry to drill down on the details. The expanded view offers a shortcut link to open the full advisory listing in another browser tab. * Search the list by a digest to understand if newer builds have since been released for the same image version and whether they fix vulnerabilities. * EOL indications and dates are provided in the changelog tab. [Learn more](#eol-details) ### Related charts Images that can be deployed using Minimus curated Helm charts include a tab showing related charts. Select a chart from the list to be redirected to the relevant Helm chart page where you can look up version details and deployment instructions. [Learn more](/foundations/helm-charts) Related Charts ## LTS & EOL indications Minimus provides information about end-of-life dates for image lines, whenever possible, and alerts when they are approaching. Image lines that are considered LTS (long term support) by the upstream project are also labeled. LTS and EOL indications are shown in both the **Versions** and **Changelog** tabs. EOL indications in the image line minimap involve several aspects: * Image lines are arranged by their support schedule. Lines with the longest support schedule and the farthest end-of-life (EOL) date appear first. * Lines that have already reached end-of-life are shown separately under a clear header: **EOL**. * Hover over any image line in the minimap to view the exact EOL date. * Once the EOL date is under 3 months, Minimus will show a countdown in the minimap to alert users that the EOL is fast approaching. Once an image line is selected, information about the end of life will appear in the header. Hover over the element to view the exact scheduled EOL date. Image Line Ordering EOL dates and indications are also shown when configuring actions. [Learn more](/remediate/create-action) ## Drill down Select any version to drill down on the image version's details, including the image's specifications, SBOM, current vulnerability report, and digest history. [About the image version card](/foundations/image-version) ## Private images The image card for private images includes the following tabs: * Versions - complete with a vulnerability report for every version, SBOM, and digest history. * The image lines and versions of the private image match those of the starter image. * Private images have `prod` and `dev` tags. * Private images provide the EOL dates for the starter image. * Compliance - includes full CIS and NIST compliance reports, image signature and SBOM signature. * STIG and FIPS need to be validated independently. * Changelog - complete with all vulnerability fix announcements and related advisories. The risk reduction tab is hidden for private images. # Image Options Source: https://docs.minimus.io/foundations/image-types Understand your options for each image type to decide between the standard, advanced, FIPS validated, or hardened options Any given image may be offered by Minimus in several options to meet various compliance or deployment requirements. For example, Postgres is offered as the following different images: * Standard * FIPS validated * Hardened / Hardened and FIPS validated * Advanced / Advanced and FIPS validated Postgres Options 1 ## General compliance standards All Minimus images, regardless of their category, provide compliance with the CIS Docker Benchmark and NIST-800-190 Standards. Each image offers a dedicated compliance report for CIS Docker and NIST-800-190. [Learn more](/compliance/image-compliance) ## Standard images The standard image offered by Minimus is a minimal image that is closely aligned with the standard public offering. It will generally have fewer packages than the standard image and will deliver an extremely reduced vulnerability count if not zero vulnerabilities, in keeping with our strict package update policy. [Learn more](/foundations/daily-updates) The standard image is a good place to get started with Minimus if you don't have particular regulatory requirements to meet. ## FIPS validated images The FIPS validated image is similar to the standard image, but it replaces standard cryptography packages with proprietary, CMVP validated FIPS 140-3 packages that satisfy FedRAMP and other regulatory requirements. Transitioning to FIPS validated images may require changes to your application code depending on the specifics of your use case. The FIPS validated image is an excellent option if you seek to meet regulatory requirements that require FIPS 140-3 cryptography and NIST CMVP certification. Our support team is always available to assist. [Learn more](/compliance/fips) ## Hardened images Minimus Hardened images provide secure by default configurations that comply with CIS Benchmarks for the app within the image. This is in addition to - not instead of - the CIS Docker Benchmark which applies to all Minimus images. For example, the Postgres-Hardened image is configured to comply with the **[CIS Benchmark for PostgreSQL](https://www.cisecurity.org/benchmark/postgresql),** a consensus-based security hardening guide that is aligned with industry standards and defines recommended configuration settings, access controls, and operational practices to reduce the attack surface. Minimus Hardened images offer a special dedicated **compliance report** for the CIS benchmark. See the [Postgres-Hardened CIS Compliance report](https://images.minimus.io/images/postgres-hardened/compliance/cis-postgres) for example. Notes: * The image’s default configuration file enforces many CIS PostgreSQL hardening controls. Exercise caution when overriding this file, as custom configurations may inadvertently weaken or negate CIS compliance. * Full CIS benchmark compliance requires additional post-deployment runtime validations that are out of scope for Minimus. ## Advanced images Minimus Advanced images are designed to be deployed in Kubernetes, often with Helm charts. Advanced images add operational tooling including pre-configured environment variables, lifecycle hooks (pre-start, post-start, shutdown), and helper scripts, so you can deploy and manage applications with minimal manual setup. Minimus Advanced images can be used as drop-in replacements in Bitnami charts and often support OpenShift restricted-v2 security context constraints (SCCs) to control Pod permissions. Minimus Advanced images are recommended if you are looking for images that are compatible with Bitnami Helm charts. # Image Version Card Source: https://docs.minimus.io/foundations/image-version Dive into the image version card for a detailed vulnerability report, digest history, SBOM, and detailed specification ## General information Click any image version in the image line to view its details. Postgres Version * Version metadata shows: * Last update time - this is the most recent build for the image version * Image size for the amd64 and arm64 architectures * Current known vulnerabilities report for the most recent image digest * Full list of tags for the image version * Enterprise Edition users will also see the aggregate pull stats to date showing how many times the image version was pulled by the organization and when it was last pulled ## Tabs ### Specification The specification tab provides technical specs in a convenient format to save you time. It lists: * Default user * Default ports (listening or exposed) * Environment variables. Note that most Minimus images include the certificate variable `SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt` * Entrypoint and default command * Default volumes * Default working directory * Stop signal The manifest in JSON format is provided as well. ### SBOM The software bill of materials lists all component packages by version and license per architecture. * Toggle the view between **amd64** and **arm64**. * You can search the list by package name, version, and license. * Click the **Download Information** button to grab the relevant Cosign command for downloading the signed SBOM. You will need Cosign and jq locally installed. [About verification](/integrity/verify) Learn more [about SBOMs](/integrity/sbom) and why SBOMs are now mandatory by executive order for all U.S. government agencies. #### Download SBOM Click the button **Download Information** in the SBOM tab to grab the relevant Cosign command. For example: ```bash theme={null} cosign download attestation \ --predicate-type=https://spdx.dev/Document \ --platform linux/amd64 \ reg.mini.dev/haproxy:latest | jq '.payload | @base64d | fromjson | .predicate' ``` The command includes a variable specifying the relevant architecture. If you toggle between the options for amd64 and arm64, the command will change accordingly. ### Vulnerabilities The version vulnerabilities report lists all vulnerabilities currently flagged in the version, by origin package. The report is compiled from data collected from package scanners that are run on a frequent basis several times a day. * Note that the report is for the most recent build for the version. Check the **Digest History** tab to see if previous builds have vulnerabilities. * You can search the list by CVE ID or package name. * The exploitability label marks vulnerabilities at high risk: * A vulnerability listed in the CISA KEV catalog is marked as an **active exploit**. * A vulnerability with a high EPSS score (over 60%) that is not in the CISA KEV catalog is marked as a **Likely exploit**. * Expand a vulnerability to see when it was published, its description, and a link to the advisory listing. * Expand a vulnerability to see the derived package and version. For example:
**Origin > Package (version)**
openssl > libcrypto3 (3.5.0-r0) Postgres Vulnerabilities Report #### Vulnerabilities under review Vulnerabilities still under review are grouped separately, while they await analysis by the Minimus security team. Expand the category to see the list of vulnerabilities still under review. Version Card Vulnerabilities Under Review An indication is also provided at the top level, directly in the vulnerability report summary. Under Review #### Download VEX Use the OpenVEX document to filter out false positives from vulnerability scan results. Minimus generates an `openvex.json` file for each image digest. The file lists all vulnerabilities detected for that image (based on its SBOM) and their status. A typical workflow is: * Obtain your vulnerability scan results in **SARIF** format. * Download the VEX document for the matching image digest. * Use `vexctl` to filter the scan results using the VEX document. For example: ```bash theme={null} vexctl filter scan_results.sarif openvex.json ``` #### VEX statement structure VEX statements are structured as follows: * Vulnerability ID and aliases * Product and subcomponents (affected image and origin packages and their versions) * Status (such as `fixed` or `not affected`) * Justification and impact statement. The justification for unaffected images is often `vulnerable_code_not_present` or `component_not_present` and the impact statement provides more specific details for the decision. ```json Example of VEX statement for CVE expandable theme={null} { "vulnerability": { "name": "MINI-jmmw-4597-rmjp", "aliases": [ "CVE-2019-1010023" ] }, "products": [ { "@id": "pkg:oci/bash-fips", "hashes": { "sha-256": "sha256:538f9c203cb04e29a5236d566ad20e8a82fc3c65b39493bd3c68ad58bd1c180f" }, "subcomponents": [ { "@id": "pkg:apk/minimos/glibc@2.41-r0" }, { "@id": "pkg:apk/minimos/glibc-locale-posix@2.41-r0" }, { "@id": "pkg:apk/minimos/ld-linux@2.41-r0" } ] } ], "status": "not_affected", "justification": "vulnerable_code_not_present", "impact_statement": "The CVE is disputed and the upstream project has determined it does not pose a risk." } ``` ### Digest History The digest history shows current and previous builds of the image version, shown with their current vulnerability count. The chronological timeline shows when every digest was published and how many vulnerabilities it currently has. It also details which build was pulled. Both the timestamp tag and its equivalent digest ID are shown. [Learn more about the timestamp tag](/foundations/daily-updates#unique-timestamp-tag) Postgres Digest History #### Build retention policy Minimus images are continuously being maintained and rebuilt with the freshest packages and updates. As a result, an image version may have numerous digests corresponding to the number of times the image was built by Minimus. As a user, you should always use the last available digest for your version of choice. The digest history shows all historical builds, but earlier image builds will no longer be available to pull after their retention period has ended. Image builds are retained for 180 days for production images and 30 days for dev images. Outdated image builds are removed from the registry: * After 180 days for Minimus production images * After 30 days for Minimus dev images The build retention policy will only remove older builds for versions that have multiple digests. The most recent build for every minor version of each image is always retained. If you prefer to pin to digest or require longer retention, we recommend syncing the relevant images to your company registry, such as [Google Artifact Registry](/manage/mirror-to-gcp-artifact-registry), [JFrog Artifactory](/manage/sync-with-jfrog-artifactory), etc. # Pull Always Source: https://docs.minimus.io/foundations/pull-policy Why you should always pull fresh Minimus images and how to configure pull policies in Docker, Kubernetes, and Helm ## Why avoid cached images It's advised to pull a fresh image even if an image with the same tag already exists locally. This is because Minimus often delivers vulnerability fixes without a change in the image version tag. To get a sense of the number of times the same image version can be rebuilt, consider the [digest history for python version 3.13.5](https://images.minimus.io/images/python/lines/3.13/versions/3.13.5/digest-history). The same image version tag will often have many image digests, but if you don't force a fresh pull, a cached image will be used. This can expose you to unnecessary risks. [Learn about the digest history in Minimus](/foundations/image-version#digest-history) ## Force a fresh pull Here's how to pull the latest version of the image from the registry, even if a local copy of the image already exists. The particular instructions depend on whether you are working in Docker, Kubernetes, or Helm charts: * Docker: * docker run: use `--pull always` ```text theme={null} docker run --pull always {image} ``` * docker build: add `--pull` to pull the latest version of the base images in your FROM statements before building, even if a local copy already exists. ```text theme={null} docker build --pull -t {app_name}:{tag} . ``` * docker compose: add `--pull always` to pull the latest version of the images. ```text pull always for docker compose theme={null} docker compose -f compose.yaml up -d --pull always ``` ```text with build flag theme={null} docker compose -f compose.yaml up -d --build --pull always ``` * Kubernetes: set `imagePullPolicy: Always` * Helm charts: * For `deployment.yaml` set: `image.pullPolicy: Always` * For `values.yaml` set: ```yaml pullPolicy theme={null} image: pullPolicy: Always ``` ```yaml values.yaml example theme={null} eck-operator: image: repository: reg.mini.dev/eck-operator tag: 3.1.0 pullPolicy: Always imagePullSecrets: - name: minimus-registry ``` ## Keeping up to date You can use [actions](/remediate/actions) to be notified when a new image version is released and when important fixes are shipped. You can configure the action as per your preferences to help you match your notification policy to updates that you think justify moving to a new image version. # Image and Chart Gallery Source: https://docs.minimus.io/gallery Browse the Minimus gallery of images and Helm charts to find the right assets for your project. The Minimus gallery lists all the images and Helm charts available from Minimus. Minimus offers a wide range of images for popular open-source projects, services, and applications and Helm charts to automate their deployment. Minimus Gallery ## At a glance The gallery provides a summary of key details: * Last updated - shows when the `latest` (and/or `latest-dev`) image version or the most recent Helm chart version was last updated. * Vulnerability reduction for images - shows the overall risk reduction relative to the public image calculated in percentages. ## Pulling an image The gallery is the visual interface for the Minimus container registry located at: `reg.mini.dev`. You can pull any image using any tag, digest, or unique-timestamp tag. This includes FIPS validated images and CIS Hardened images. ## Sort the gallery Toggle the view by: * Most popular (default view) * Name (leading with your [private images](/enterprise-edition/image-creator)) * Recently added (shows when each image and chart was first added to the Minimus gallery) ## Search the gallery Search the Minimus gallery by names and related terms. For example, if you search for `gitops` you will see related images and Helm charts. New Search Enter a search term and press **Enter** to return all results, including related images and charts. Note that the search corrects for typos and similar spelling so you may see more than just exact matches. ## Filter the gallery Quick filters help you find the images and charts you are looking for. Use the filter **My Images** to see your subscribed images. You can filter by categories: * AI * Apps * Base * Data (as in databases) * Dev * Infra (as in infrastructure) * Utils (as in utilities) You can also filter by compliance standards: * FIPS - FIPS 140-3 validated images are CMVP certified and comply with the relevant Federal Information Processing Standards for cryptography. [Learn more](/compliance/fips) * STIG - STIG compliant images follow the technical testing and hardening frameworks required by the DoD and the Defense Information Systems Agency (DISA) under STIGs, [Security Technical Implementation Guides](https://public.cyber.mil/stigs/). * Advanced - Advanced images are compatible with Bitnami Helm charts. [Learn more](/foundations/image-types) * Hardened - Images hardened to meet CIS app benchmarks. [Learn more](/foundations/image-types) ## Request an image The Minimus image gallery is growing fast as new images are added on a rolling basis. As we continue working to expand our offering, we also gladly accept requests. Please use the link from the gallery to contact us with your request. # AWS Lambda Tutorial Source: https://docs.minimus.io/guides/aws-lambda-deployment Build applications using Minimus container images to run on AWS Lambda AWS Lambda supports deploying functions as Docker container images via Amazon ECR. Container images allow richer dependency management and a higher size limit (10 GB) than zip-based deployments, but Lambda requires images to conform to a specific format. [See AWS docs](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html) This tutorial builds a Python Lambda function using a multi-stage Dockerfile: the build stage uses `reg.mini.dev/python:latest-dev` for access to `pip`, and the runtime stage uses the fully distroless production image for a minimal, secure final artifact. [Learn more about multi-stage builds](https://docs.minimus.io/guides/multi-stage-build) ## What this guide demonstrates * Minimus Python images can run on AWS Lambda * Amazon Linux is not required * Non-root execution is supported * Buildx defaults must be overridden ## Prerequisites * Access to an AWS account * Permission to: * Create ECR repositories * Push images to ECR * Create and invoke Lambda functions * Access to create or use a role for the function * Read CloudWatch logs ## Process Create a Python app `app.py`: ```python app.py theme={null} import sys import os def handler(event, context): return { "ok": True, "python": sys.version, "cwd": os.getcwd(), "uid": os.getuid(), "event": event, } ``` Save the following Dockerfile. The build stage creates an isolated `venv` (virtual environment) so runtime dependencies can be copied cleanly to the production image: ```shellscript Dockerfile expandable lines theme={null} # === Build Stage === FROM reg.mini.dev/python:latest-dev AS builder WORKDIR /var/task # Create an isolated venv for runtime dependencies (including awslambdaric) RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:\$PATH" # Install the Lambda Runtime Interface Client (RIC) into the venv # Add other dependencies if relevant (requirements.txt) RUN pip install --no-cache-dir awslambdaric # === Runtime Stage === FROM reg.mini.dev/python:latest # Lambda expects code in /var/task WORKDIR /var/task COPY app.py . # Copy the pre-built venv from the builder stage COPY --from=builder /opt/venv /opt/venv # Use venv python and packages at runtime ENV PATH="/opt/venv/bin:\$PATH" ENV HOME=/home/python USER 1000 # Lambda container contract: # ENTRYPOINT starts the runtime interface client # CMD names the handler ENTRYPOINT ["python", "-m", "awslambdaric"] CMD ["app.handler"] ``` Create an ECR repository. [See AWS docs](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-create-repository)   In the AWS Console: 1. Go to Elastic Container Registry (ECR) 2. Create a private repository. For this guide, we assume you named it: `minimus-lambda-example` 3. Note the full repository URI, for example: `123456789012.dkr.ecr.eu-north-1.amazonaws.com/minimus-lambda-example` Authenticate the Docker CLI to your default registry so the **docker** command can push and pull images with Amazon ECR. [See AWS docs](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-authenticate-registry) ```shellscript theme={null} aws ecr get-login-password --region eu-north-1 \ | docker login --username AWS --password-stdin \ 123456789012.dkr.ecr.eu-north-1.amazonaws.com ``` Replace the example URI in the above command with your own before running the command. Build the image using buildx. Buildx is an extended Docker build command that uses BuildKit under the hood, handling multi-architecture builds, remote push, and more. ```shellscript theme={null} docker buildx build \ --platform linux/arm64 \ --provenance=false \ --sbom=false \ -t 123456789012.dkr.ecr.eu-north-1.amazonaws.com/minimus-lambda-example:lambda-arm64 \ --push \ . ``` In the AWS Console: 1. Go to Lambda 2. Click **Create function** 3. Select container image 4. Select `minimus-lambda-example:lambda-arm64` 5. Set Architecture to `arm64` 6. Create or select an execution role 7. Create the function Create a test event: ```shellscript theme={null} echo '{"hello":"lambda"}' > event.json ``` Invoke the function: ```shellscript theme={null} aws lambda invoke \ --function-name minimus-lambda-example \ --payload file://event.json \ --cli-binary-format raw-in-base64-out \ --region eu-north-1 \ response.json ``` View the response: ```shellscript theme={null} cat response.json ``` ```json Expected output theme={null} {"ok": true, "python": "3.14.2 (tags/v3.14.2-0-gdf79316-dirty:df79316, Dec 5 2025, 20:23:01) [GCC 15.2.0]", "cwd": "/var/task", "uid": 993, "event": {"hello": "lambda"}}% ``` 1. Open the Lambda function 2. Click **Test** 3. Create a new test event: ```json theme={null} {   "hello": "lambda" } ``` 4. Invocation type: **Synchronous** 5. Click **Test** ## Required Buildx flags Lambda requires a single-architecture image manifest, not an OCI index with attestations. Docker Buildx adds provenance and SBOM attestations by default, which results in the pushed image becoming an OCI image index containing an extra attestation manifest (often shown as `unknown/unknown` platform). Since AWS Lambda does not support this image format, it is necessary to add the following Buildx flags: * `--provenance=false` * `--sbom=false` If the above flags are omitted, Lambda creation fails with the error: `The image manifest, config or layer media type is not supported`. # Flyway Database Migration Source: https://docs.minimus.io/guides/flyway-migration Run Flyway database migrations using the Minimus Flyway image [Flyway](https://flywaydb.org/) is an open-source database migration tool that tracks, versions, and applies schema changes using plain SQL scripts. This guide walks through running a Flyway migration against a PostgreSQL database using the [Minimus Flyway image](https://images.minimus.io/images/flyway/lines/latest). ## Flyway migration conventions Flyway uses the naming convention `V{version}__{description}.sql`: * Version number sets the execution order * Double underscore separates the version number from the description. Up until Flyway version 11, there was auto-scanning of the `sql/` directory. Starting with Flyway version 12 an explicit location must be configured instead. Each migration runs exactly once. Flyway tracks applied versions in a `flyway_schema_history` table it creates in your database, and skips script versions that are already recorded there. ## Run your first migration Start a PostgreSQL container on a shared Docker network to perform your testing on. Flyway will later use the database name, user, and password set here to connect to PostgreSQL: ```bash theme={null} docker network create flyway-net docker run -d \ --name db \ --network flyway-net \ -e POSTGRES_DB=demo \ -e POSTGRES_USER=demo \ -e POSTGRES_PASSWORD=demo \ reg.mini.dev/postgres:18 ``` This example does not mount a volume so data will be lost when the container is removed. For a persistent setup, add `-v pgdata:/var/lib/postgresql/data` to the `docker run` command. Create a working directory with a `sql` subdirectory. Next we will configure Flyway to look for migration scripts there: ```bash theme={null} mkdir -p flyway-demo/sql ``` Create `flyway-demo/flyway.conf` with the connection details matching the container above: ```text flyway-demo/flyway.conf theme={null} flyway.url=jdbc:postgresql://db:5432/demo flyway.user=demo flyway.password=demo flyway.locations=filesystem:/flyway/sql ``` JDBC (Java Database Connectivity) is Java's standard API for database connections. The JDBC URL specifies the driver, host, port, and database name. Create the first migration script at `flyway-demo/sql/V1__Create_orders_table.sql`: ```sql flyway-demo/sql/V1__Create_orders_table.sql theme={null} CREATE TABLE orders ( id SERIAL PRIMARY KEY, reference VARCHAR(50) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', created_at TIMESTAMP NOT NULL DEFAULT NOW() ); ``` Run the migration using Flyway: ```bash Run migration with Flyway theme={null} docker run --rm \ --network flyway-net \ -v $(pwd)/flyway-demo/sql:/flyway/sql \ -v $(pwd)/flyway-demo/flyway.conf:/flyway/conf/flyway.conf \ reg.mini.dev/flyway migrate ``` ```shellscript Expected output theme={null} Flyway OSS Edition 12.x.x by Redgate Database: jdbc:postgresql://db:5432/demo (PostgreSQL 18.x) Schema history table "public"."flyway_schema_history" does not exist yet Successfully validated 1 migration (execution time 00:00.068s) Creating Schema History table "public"."flyway_schema_history" ... Current version of schema "public": << Empty Schema >> Migrating schema "public" to version "1 - Create orders table" Successfully applied 1 migration to schema "public", now at version v1 (execution time 00:00.024s) ``` ## Fix a PostgreSQL collation version mismatch with Flyway When a PostgreSQL image is upgraded to a version built with a newer glibc collation library, Postgres may log a collation version mismatch warning. Flyway wraps the fix commands in a versioned migration for a tracked, auditable record that runs exactly once per environment. See [Collation version mismatch in Postgres](/troubleshooting/troubleshooting-images#collation-version-mismatch-in-postgres) for background on the warning and what causes it. ### Overview The fix requires two commands handled separately: 1. `ALTER DATABASE demo REFRESH COLLATION VERSION` updates the collation version in PostgreSQL's internal metadata to match the OS. This clears the warning but does not fix index ordering issues. 2. `REINDEX DATABASE demo` rebuilds the indexes to match the new collation, completing the fix. \ \ `REINDEX DATABASE` is not compatible with transactions so it cannot be put in a regular Flyway migration file. Instead, it needs to run separately, either in a different migration marked as non-transactional or manually outside of Flyway entirely. ### Steps Save the following to `flyway-demo/sql/V2__Fix_collation_version.sql`: ```sql theme={null} ALTER DATABASE demo REFRESH COLLATION VERSION; ``` Number the version as appropriate for your environment (`V2` is just an example). ```bash theme={null} docker run --rm \ --network flyway-net \ -v $(pwd)/flyway-demo/sql:/flyway/sql \ -v $(pwd)/flyway-demo/flyway.conf:/flyway/conf/flyway.conf \ reg.mini.dev/flyway migrate ``` Run `REINDEX DATABASE` manually during a maintenance window using the `psql` command-line client. First, open a psql session: ```bash theme={null} psql -h localhost -U demo -d demo ``` Once connected, run: ```sql theme={null} REINDEX DATABASE demo; ``` `REINDEX DATABASE` locks the database. Plan a maintenance window before running this command in production. ## JDK compatibility The Minimus Flyway image is built on JDK 21. JDK 21 is an LTS release and is suitable for production deployments. JDK 21 sets the compatibility floor for this image. Ensure your application runtime targets JDK 21 or is compatible with it. If your app is built for an older JDK (e.g. JDK 11 or 17), it may not be compatible with this image. # Slim Down an App Using a Runtime Base Source: https://docs.minimus.io/guides/golang How to build more secure apps using multi-stage builds with a runtime base image Some images will allow you to separate the build stages such that you can compile the app with one image and then copy the final binary onto a minimal runtime base image such as [static](https://images.minimus.io/images/static) or [glibc-dynamic](https://images.minimus.io/images/glibc-dynamic) to significantly reduce the size of the final container image. This technique produces images that are ultra-light, hardened, performant, and secure. ## Example with Go Go is a great test case to demonstrate the value of using a multi-stage build to slim down the final app. Go is a compiled language that is not optimized for use as a runtime. For this reason, it is recommended to use a multi-stage build. We will compile the binary using the Go image, then copy the binary into a minimal runtime base image. Knowing which runtime base image to use depends on how your Go project was compiled: * If compiled as a static app, use the [static Go image](https://images.minimus.io/images/go). * If compiled as a dynamically linked app, use the [Glibc-Dynamic image](https://images.minimus.io/images/glibc-dynamic). ## Static runtime ### About static Go applications Static binaries are self-contained and do not rely on shared system libraries or runtime dependencies on the host system. As such, they are fully portable and avoid compatibility issues with C libraries. If the static Go binary is mounted on a static base image, it will produce a tiny image, that is as minimal as it gets. In the example below, the flag `CGO_ENABLED=0` is added to the Dockerfile to ensure that the compiled binary is statically linked. CGO is a Go tool that enables the creation of Go packages that call C code. When CGO is disabled, the resulting binary is statically linked. ### Example 1. In your project directory, save the code below to a Dockerfile: ```dockerfile Dockerfile example expandable lines theme={null} # Pull Go image and set it as builder FROM reg.mini.dev/go:latest AS builder # Set CGO_ENABLED to 0 to create a static binary ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 # Copy project directory content to app directory in the container COPY . /app # Compile your Go app RUN cd /app && go build -o go-minimus . # Pull static image to use as a runtime base image FROM reg.mini.dev/static:latest # Copy go-minimus binary from the /app directory in the builder container to /usr/bin/ in the final static container COPY --from=builder /app/go-minimus /usr/bin/ # Set the container entrypoint to run the go-minimus binary when the container is started ENTRYPOINT ["/usr/bin/go-minimus"] ``` 2. In your project directory, save the code below to a file and name it `hello-minimus.go`. This is a very simple script which prints "Hello from Minimus!" to the terminal. You can use your own script instead. ``` package main import "fmt" func main() { fmt.Println("Hello from Minimus!") } ``` 3. In your project directory, create a `go.mod` file. This file declares the modules and dependencies required by the project. In our case, the module set is only needed for testing purposes, so it's very simple. ``` module minimus.dev/hello_minimus go 1.19 ``` 4. Your project directory should now contain 3 files: 1. `Dockerfile` 2. `hello-minimus.go` 3. `go.mod` 5. From your project directory run the following command to build the custom image `hello-go`: ``` docker build -t hello-go . ``` The period `.` specifies the current directory as the build context. 6. Spin up the image just created with this command: ``` docker run hello-go ``` ## Dynamic runtime ### About dynamic Go applications If your Go app needs to link to database drivers or other C integrations, you can compile a dynamically linked binary by setting the `CGO_ENABLED=1` flag. Make sure the required C libraries are available in both your build and runtime environments. In the example below, we will use the Minimus Glibc-Dynamic image as a runtime base for a simple web application. ### Example 1. In a new project directory, save the code below to a new Dockerfile: ```docker Dockerfile example expandable lines theme={null} # Pull Go image and set it as builder FROM reg.mini.dev/go AS builder # Set CGO_ENABLED=1 to compile a dynamically linked binary ENV CGO_ENABLED=1 GOOS=linux GOARCH=amd64 # Copy the project directory content to app directory in the container COPY . /app # Compile Go application RUN cd /app && go build -o Hello-Minimus-Web . # Pull dynamic image to use as a runtime base FROM reg.mini.dev/glibc-dynamic:latest # Copy Go binary from the /app directory in the builder container to /usr/bin/ in the final dynamic container COPY --from=builder /app/Hello-Minimus-Web /usr/bin/ EXPOSE 8080 # Set entrypoint to run the binary when the container is started ENTRYPOINT ["/usr/bin/Hello-Minimus-Web"] ``` 2. [Download the example file](https://github.com/minimusio/examples/blob/main/golang/hello-minimus-web.go) `hello-minimus-web.go` and save it to your project directory. This is a very simple script that creates a webpage with several tabs so you can navigate between them. 3. In your project directory, create a `go.mod` file. This file declares the modules and dependencies required by the project. In our case, the module set is only needed for testing purposes, so it's very simple. ``` module minimus.dev/hello_minimus go 1.19 ``` 4. Your project directory should now contain 3 files: 1. `Dockerfile` 2. `hello-minimus-web.go` 3. `go.mod` 5. From your project directory run the following command to build the image: ```bash theme={null} docker build -t hello-go-web . ``` The period `.` specifies the current directory as the build context. 6. Spin up the image we just created with this command: ```bash theme={null} docker run -p 8080:8080 hello-go-web ``` 7. Open your browser and go to [http://localhost:8080/](http://localhost:8080/) to see the default welcome page. # Deploy Ingress-NGINX-controller over Kubernetes Source: https://docs.minimus.io/guides/ingress-nginx-controller Get started with the Minimus Ingress-NGINX-controller image in minikube This guide walks you through the steps to deploy Ingress-NGINX-controller over Kubernetes in a minikube environment. Minikube is a local Kubernetes setup that requires only Docker or a Virtual Machine environment and is ideal for testing. Use this guide as a reference for deploying any Minimus image over Kubernetes. If you already have a Kubernetes cluster available, you can skip ahead to the next step. If not, you can install a single node cluster using minikube to set up a testing environment. Follow the [minikube get started guide](https://minikube.sigs.k8s.io/docs/start/?arch=%2Fwindows%2Fx86-64%2Fstable%2F.exe+download) to deploy a cluster, install kubectl, and test that everything is working. The instructions are platform-specific and provided for Windows, MacOS, and Linux. The configurations are based on the changes described in our general [NGINX guide](/guides/nginx). To simplify the process we provide example configuration files in our [GitHub repo](https://github.com/minimusio/examples/tree/main/ingress-nginx-controller). Save the example yaml files to your project folder: * [deployment.yaml](https://github.com/minimusio/examples/blob/main/ingress-nginx-controller/deployment.yaml) * [ingress.yaml](https://github.com/minimusio/examples/blob/main/ingress-nginx-controller/ingress.yaml) * [service.yaml](https://github.com/minimusio/examples/blob/main/ingress-nginx-controller/service.yaml) * [values.yaml](https://github.com/minimusio/examples/blob/main/ingress-nginx-controller/values.yaml) * [pullsecret.yaml](https://github.com/minimusio/examples/blob/main/ingress-nginx-controller/pullsecret.yaml) To avoid using a Minimus token in plaintext, we will create a Kubernetes Secret containing the credentials needed to pull images from the Minimus registry. 1. Copy a token from your [console](https://images.minimus.io/manage/tokens). 2. Create a Docker auth JSON by executing the following command. Use the token from step 1 as the password when prompted: ```bash theme={null} docker login -u minimus reg.mini.dev ``` 3. Base64 encode the auth JSON, by running: ```bash theme={null} cat ~/.docker/config.json | base64 -w 0 ``` 4. Edit the `pullsecret.yaml` file, to include your base64 encoded auth JSON. Under the `data` section, update the `dockerconfigjson` with the base64 encoded auth JSON and save your changes. Run the following command from the project directory to deploy your Ingress NGINX controller. ```bash theme={null} helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx -f values.yaml ``` Run the following command from the project directory to deploy your NGINX ingress controller. The command applies all YAML files in the current directory (`.`). ```bash theme={null} kubectl apply -f . ``` To check that all pods are ready and running, run: ```bash theme={null} kubectl get pods -A ``` You should receive a pod status check (also known as, pod readiness verification) such as `hello-nginx-55bd9b99f4-bgxpd` verifying the status of the pod is up and running. If you're new to Kubernetes, you can learn more about the ReplicaSet hash and random suffix in the [official Kubernetes guide](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/). To look up which external IP address was set for Ingress NGINX controller web access, run: ```bash theme={null} kubectl get svc -A ``` The response should print the address along with the port, for example, `http://192.168.49.2:8080`. Open this address in your browser to see the NGINX welcome page. For other Kubernetes clusters, run this command to proxy access from your local machine to the service running in your cluster: # Deploy Istio over Kubernetes Source: https://docs.minimus.io/guides/istio Deploy Istio Pilot and Istio Proxy over Kubernetes using Minimus images in a minikube environment This guide walks you through the steps to deploy Istio Pilot and Istio Proxy over Kubernetes in a minikube environment. Minikube is a local Kubernetes setup that requires only Docker or a Virtual Machine environment which makes it ideal for testing. This setup automatically injects Istio sidecars into application pods, enabling service mesh features like traffic management, security, and observability. For the backend, we will use the [Minimus Darkhttpd image](https://images.minimus.io/images/darkhttpd/lines/latest) to deploy a simple HTTP server. For the frontend, we will use the [Minimus BusyBox image](https://images.minimus.io/images/busybox/lines/latest) to call the backend every 10 seconds. If you already have a Kubernetes cluster available, you can skip this step. Otherwise, install a single node cluster using minikube to set up a testing environment. Follow the [minikube get started guide](https://minikube.sigs.k8s.io/docs/start/?arch=%2Fwindows%2Fx86-64%2Fstable%2F.exe+download) to deploy a cluster, install kubectl, and test that everything is working. The instructions are platform-specific and provided for Windows, MacOS, and Linux. The configurations are based on our general [NGINX guide](/guides/nginx). To simplify the process we provide example configuration files in our [GitHub repo](https://github.com/minimusio/examples/tree/main/nginx-k8s). Save the example yaml files to your project folder: * [backend.yaml](https://github.com/minimusio/examples/blob/main/istio/backend.yaml) * [frontend.yaml](https://github.com/minimusio/examples/blob/main/istio/frontend.yaml) To avoid using a Minimus token in plaintext, we will create a Kubernetes Secret containing the credentials needed to pull images from the Minimus registry. 1. Copy a token from your [Minimus console](https://images.minimus.io/manage/tokens). 2. Create a Docker auth JSON by executing the following command. Add the token from the previous step as your password: ```bash theme={null} kubectl -n istio-system create secret docker-registry my-registry-secret \ --docker-server=reg.mini.dev \ --docker-username=minimus \ --docker-password={minimus_token} ``` 3. Check that the secret with the name `my-registry-secret` was successfully created: ```bash theme={null} kubectl -n istio-system get secrets ``` Run the following command from the project directory to deploy your NGINX container: ```bash theme={null} helm install istiod istio/istiod -n istio-system \ --set global.proxy.image=istio-proxy \ --set pilot.image=istio-pilot \ --set global.hub=reg.mini.dev \ --set global.tag=latest \ --set global.imagePullSecrets[0]=my-registry-secret ``` Run the following command from the project directory to deploy the frontend and backend apps. The period at the end of the command applies all YAML files in the current directory: ```bash theme={null} kubectl apply -f . ``` Run the following command to check the logs: ```bash theme={null} kubectl -n istio-system istiod-pod-number logs -f ``` Look for the string below to make sure that the two endpoints were created: `XDS: Pushing Services:19 ConnectedEndpoints:2 Version:2025-08-10T07:38:55Z/6` Check the frontend logs: ```bash theme={null} kubectl -n istio-system frontend-pod-number logs -f ``` You should see calls to the backend pod: ``` Calling backend... Hello World - Sun Aug 10 07:38:39 UTC 2025 ``` # Java Tutorial Source: https://docs.minimus.io/guides/java How to build more secure Java apps using OpenJDK and OpenJRE This project provides a test framework for validating a multi-stage build for a Java application with TLS enabled. The setup includes the creation of self-signed certificates and has the Java container run an application server over HTTPS. Save these files to your project folder: * [certgen.sh](https://github.com/minimusio/examples/blob/main/jdk-jre/certgen.sh) * [create-certs.yml](https://github.com/minimusio/examples/blob/main/jdk-jre/create-certs.yml) * [docker-compose.yml](https://github.com/minimusio/examples/blob/main/jdk-jre/docker-compose.yml) * [Dockerfile.app](https://github.com/minimusio/examples/blob/main/jdk-jre/Dockerfile.app) * [Server.java](https://github.com/minimusio/examples/blob/main/jdk-jre/Server.java) Run the following command to generate the certificates. ``` docker compose -f create-certs.yml up --abort-on-container-exit ``` This will run the Java server and map port 5001 on your host to 5001 in the container. ``` docker compose up --build app ``` You need to place the server certificate (https.crt) on your host so you can communicate with curl. Copy it from the container Docker volume to your host (The container name in our example is `jdk-jre-tls-test-app-1`): ``` docker cp jdk-jre-tls-test-app-1:/certs/https.crt ./https.crt ``` Now you can send curl requests to your Java server. * Send a curl command to the default endpoint to get a text response: ```bash theme={null} curl --cacert ./https.crt https://localhost:5001/ ``` You should get the following response: ``` ✅ Hello over HTTPS from Java TLS Server running minimus images! ``` * Send a curl command to the JSON endpoint: ```bash theme={null} curl --cacert ./https.crt https://localhost:5001/data ``` You should get the following response: ```json theme={null} { "message": "Hello from the server running minimus image and using json format!", "status": "success" } ``` # Deploy NGINX over Kubernetes Source: https://docs.minimus.io/guides/k8s-nginx Get started with the Minimus Nginx image in minikube This guide walks you through the steps to deploy NGINX over Kubernetes in a minikube environment. Minikube is a local Kubernetes setup that requires only Docker or a Virtual Machine environment and is ideal for testing. Use this guide as a reference for deploying any Minimus image over Kubernetes. If you already have a Kubernetes cluster available, you can skip ahead to the next step. If not, you can install a single node cluster using minikube to set up a testing environment. Follow the [minikube get started guide](https://minikube.sigs.k8s.io/docs/start/?arch=%2Fwindows%2Fx86-64%2Fstable%2F.exe+download) to deploy a cluster, install kubectl, and test that everything is working. The instructions are platform-specific and provided for Windows, MacOS, and Linux. The configurations are based on the changes described in our general [NGINX guide](/guides/nginx). To simplify the process we provide example configuration files in our [GitHub repo](https://github.com/minimusio/examples/tree/main/nginx-k8s). Save the example yaml files to your project folder: * [deployment.yaml](https://github.com/minimusio/examples/blob/main/nginx-k8s/deployment.yaml) * [configmap.yaml](https://github.com/minimusio/examples/blob/main/nginx-k8s/configmap.yaml) * [service.yaml](https://github.com/minimusio/examples/blob/main/nginx-k8s/service.yaml) * [pullsecret.yaml](https://github.com/minimusio/examples/blob/main/nginx-k8s/pullsecret.yaml) To avoid using a Minimus token in plaintext, we will create a Kubernetes Secret containing the credentials needed to pull images from the Minimus registry. 1. Copy a token from your [console](https://images.minimus.io/manage/tokens). 2. Create a Docker auth JSON by executing the following command. Use the token from step 1 as the password when prompted: ```bash theme={null} docker login -u minimus reg.mini.dev ``` 3. Base64 encode the auth JSON, by running: ```bash theme={null} cat ~/.docker/config.json | base64 -w 0 ``` 4. Edit the `pullsecret.yaml` file, to include your base64 encoded auth JSON. Under the `data` section, update the `dockerconfigjson` with the base64 encoded auth JSON and save your changes. ```bash pullsecret.yaml theme={null} yaml pullsecret.yaml apiVersion: v1 kind: Secret metadata: name: minimus-pull-secret data: .dockerconfigjson: {paste your base64 encoded auth JSON} type: kubernetes.io/dockerconfigjson ``` Run the following command from the project directory to deploy your NGINX container. The period at the end of the command applies all YAML files in the current directory: ```bash theme={null} kubectl apply -f . ``` To check that all pods are ready and running, run: ```bash theme={null} kubectl get pods -A ``` You should receive a pod status check (also known as, pod readiness verification) such as `hello-nginx-55bd9b99f4-bgxpd` verifying the status of the pod is up and running. If you're new to Kubernetes, you can learn more about the ReplicaSet hash and random suffix in the [official Kubernetes guide](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/). To look up which external IP address was set for NGINX web access, run: ```bash theme={null} minikube service hello-nginx --url ``` The response should print the address along with the port, for example, `http://192.168.49.2:30001`. Open this address in your browser to see the NGINX welcome page. For other Kubernetes clusters, run this command to proxy access from your local machine to the service running in your cluster: ```bash theme={null} kubectl port-forward service/hello-nginx 30001:8080 ``` Connect to `http://localhost:30001` to see the NGINX welcome page. Hit CTRL-C in your terminal window to end the port forwarding. # Secure an App Using a Multi-Stage Build Source: https://docs.minimus.io/guides/multi-stage-build How to build more secure apps using a dev image for the builder stage in a multi-stage build Minimus images come in pairs — the fully distroless image with the smallest attack surface and a dev variant that includes more developer-relevant tools such as package managers, a shell, and more. When you build an app using a multi-stage build, you can take advantage of an image pair to create a more secure final result. In the Dockerfile, you can use the dev image in the builder stage and switch to the production image for the final stage. This way, the build process can discard all the unnecessary tools and produce a cleaner, more minimal and secure artifact. If your app can run on a runtime base after it's compiled, you can make the app even smaller and more secure. Go (golang) is a great example. See our article on [how to use a runtime base](/guides/golang). ## Examples Minimus images are often used in multi-stage builds. Below are a list of recommended tutorials to help you get started: * [Python tutorial](/guides/python) * [Java tutorial](/guides/java) * [DotNet (.Net) tutorial](https://images.minimus.io/images/dotnet-aspnet/quick-start) * [Go tutorial using a runtime base](/guides/golang) ## Advantages of a multi-stage build Using a different base image for the builder stage and the runtime stage has several advantages: * The dev image contains more packages and is therefore more likely to contain more vulnerabilities. For example, we can see that the Python production image has fewer vulnerabilities than the Python dev image. This behavior is consistent across all images, where many times the production image is completely free of vulnerabilities but the dev image might have a few. Compare Vulnerabilities * When building an app, there is no advantage to including dev packages that increase the attack surface and are not required to run the app. It is preferable to build the application in stages and reduce the final image in size and attack surface. As a result, the final image will have a small attack surface and fewer vulnerabilities, if any.\ \ Just to get a sense of the size differences, the compressed size of the python image is just over 22 MB - compared to 218 MB for the python dev image. Similarly, the SBOM for the Python production image lists 23 packages while the Python dev image lists 73 packages. | | python:3.13.5 | python:3.13.5-dev | | --------------- | ------------- | ----------------- | | Compressed size | 22 MB | 218 MB | | SBOM packages | 23 | 73 | ## When to use a multi-stage build Basically, you should use a multi-stage build whenever the opportunity presents itself. * Any compiled or interpreted language is a good candidate for a multi-stage build. This includes (but is not limited to): Python, NodeJS, Rust, PHP, Ruby, etc. * Go is a special case as you can run the compiled binary on a minimal runtime base. [Learn how to run a Go app on a runtime base](/guides/golang) * Some images come in building pairs that have different names. For example: * The [Dotnet SDK image](https://images.minimus.io/images/dotnet-sdk/lines/9) is often used as the builder in combination with the [ASP.NET image](https://images.minimus.io/images/dotnet-aspnet/lines/9) for the runtime stage. * OpenJDK is often used for building Java applications while OpenJRE (open-source Java Runtime Environment) is used to run them. [See our Java quick start tutorial](https://images.minimus.io/images/openjre/quick-start) # NGINX Tutorial Source: https://docs.minimus.io/guides/nginx Deploy a secure and minimal NGINX container image built by Minimus to optimize security Getting started with the Minimus NGINX image is quick and simple, with optimal compatibility with the public NGINX image. As with any NGINX image, you can use it as an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server. ## Why make the switch? The NGINX container image offered by Minimus is more secure, delivers daily package updates, and is drop-in ready. Visit the [risk reduction dashboard](https://images.minimus.io/images/nginx/risk-reduction) for the NGINX image to see the current vulnerability report. The image is shell-less and hardened and runs as non-root to keep your perimeter safer. ## Highlights Here's what's special about the Minimus NGINX image: * Runs as a non-root, unprivileged user, by default. * Defaults to port 8080 for HTTP (instead of port 80). This change was needed for compatibility with Kubernetes when running rootless. \ Kubernetes prevents a container running as a non-root user from binding to privileged ports (ports between 0–1023) unless explicitly allowed via security configurations. * The Minimus NGINX image is hardened and does not include a shell so you can't simply add or edit files on the container. Instead, you can bind mount files from the host to override the default configuration file, mount static content, and more. In the example below, we show how to bind mount the `index.html` file to override the default directory. Using a bind mount makes your changes persistent so they aren't lost when the container is relaunched on the same host. ## Deploy an NGINX server Serving static content with NGINX as an HTTP server is simple using bind mounts and port mappings. For starters, you can run the NGINX server in detached mode (`-d`): ```bash theme={null} docker run -d --name minimus-nginx / -p 80:8080 / -v /home/me/site/static:/usr/share/nginx/html:ro / -v /home/me/nginx.conf:/etc/nginx/nginx.conf:ro / reg.mini.dev/nginx:latest ``` Let's review the parameters in this command. The `-p` flag maps port 80 on the host machine to port 8080 on your container. Minimus NGINX defaults to port 8080 so it can run as an unprivileged process anywhere, even Kubernetes. Here's the general command for mapping the host port to the container port: ```bash theme={null} docker run -d -p {host_port}:{container_port} {image} ``` Given that the container does not have a shell, editing the `html.dir` file directly in the container would require copying it back and forth and would be unnecessarily tedious. Instead of directly editing the directory file, it is simpler to copy the desired directory file to the host and map it to the default directory path in the NGINX configuration. See the detailed instructions below. You can skip this step unless you need to change any additional configurations. For example, if you want to change the default listening port from 8080 to something else. ### Replacing the default directory file To replace the default directory file, we'll want to place the new file on the host so that the change is persistent. Then, we'll map it to the default directory path. The default directory path (`/usr/share/nginx/html`) is specified by the root directive in the NGINX configuration file (`nginx.conf`): ```text theme={null} location / { root /usr/share/nginx/html; index index.html; } ``` First, create the new directory on your host. In this example, we'll create the `static` folder and nest it under `site`. The `-p` flag creates all the directories in the path, so it's useful for setting up nested directory structures in a single step. ```bash theme={null} mkdir -p ~/site/static ``` Next, copy (or move) the `index.html` file to the new directory. ```bash copy_file theme={null} cp index.html /path/to/destination/ ``` ```bash move_file theme={null} mv ~/index.html /path/to/destination/ ``` When you run the container, map the `index.html` file from the host to the default directory path in the configuration file. For our example, we'll add the following parameter when running the NGINX container: ```bash theme={null} -v /home/me/site/static:/usr/share/nginx/html:ro ``` The read-only flag `:ro` is a standard best practice for protecting the container from accidentally or maliciously modifying host data. ## Docker Compose While Docker Compose usually isn't used in production, it's a useful development and testing tool. Make sure you have the [Docker Compose plugin](https://docs.docker.com/compose/install/linux/#install-using-the-repository) installed. If you have the legacy standalone Docker Compose binary, you'll need to update it. Check your version: ```bash theme={null} docker compose version ``` Create a `compose.yaml` file that defines the NGINX service with the appropriate configurations. The configuration details are explained below. Run the Docker Compose command to start the container. Make sure you run it from the same directory where the `compose.yaml` file is located. ```bash theme={null} docker compose up -d ``` The `-d` flag is for detached mode, so your terminal stays free. Run `docker ps` to confirm that the container is running. You can run `docker inspect` to review the container's settings and status. Now that the container is running, you can visit your NGINX site. You should see a greeting from Minimus. ### Docker Compose file example We can use Docker Compose to create a YAML template for running our Nginx container with the appropriate bind mounts and port mapping. For our example, we'll create a `compose.yaml` file with the following code: ```text theme={null} services: nginx: image: reg.mini.dev/nginx container_name: myNginxContainer ports: - "80:8080" volumes: - /home/me/site/static:/usr/share/nginx/html:ro - /home/me/nginx.conf:/etc/nginx/nginx.conf:ro restart: always ``` * services: defines the services to be managed by Docker Compose (`nginx` in our example). * image: specifies the path to pull the image from. * container\_name: sets the container's name (`myNginxContainer`). * ports: maps port 80 on the host to port 8080 in the container (`80:8080`). * volumes: * `/home/me/site/static:/usr/share/nginx/html`: mounts your static file directory to the container's HTML directory. * `/home/me/nginx.conf:/etc/nginx/nginx.conf`: mounts your custom NGINX configuration file to the container's config directory. * restart: ensures the container restarts automatically if it stops. # PHP-FPM Tutorial Source: https://docs.minimus.io/guides/php-fpm Deploy a secure and minimal PHP-FPM container image built by Minimus to optimize security PHP-FPM (FastCGI Process Manager) is an alternative FastCGI daemon for PHP that optimizes performance and scalability and can support strenuous loads by managing a pool of PHP worker processes. While PHP is tightly coupled with Apache, PHP-FPM has its own process manager and is typically coupled with a web server like NGINX or Nginx Proxy Manager. ## Deploy a PHP-FPM server The following tutorial will guide you through the first steps of deploying the Minimus PHP-FPM container image. In this scenario, we will run the PHP-FPM server with Nginx Proxy Manager for SSL certificates. In your project folder, save the following code to a new Docker Compose file `compose.yaml`: ```yaml compose.yaml expandable theme={null} services: app: build: context: . dockerfile: php/Dockerfile restart: unless-stopped working_dir: /app volumes: - ./src:/var/www/html - ./data:/data nginx: build: context: . dockerfile: nginx/Dockerfile restart: unless-stopped ports: - "8080:80" volumes: - ./src:/var/www/html - ./nginx.conf:/etc/nginx/nginx.conf - ./data:/data - ./letsencrypt:/etc/letsencrypt depends_on: - app ``` In the same directory, save the following code to a new file `nginx.conf`: ```bash nginx.conf expandable theme={null} events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; # Add fastcgi settings fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; # Path to SSL certificates ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; server { listen 80; server_name localhost; root /var/www/html; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass app:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; # Basic fastcgi parameters fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; } } } ``` Create a `php` folder and save the following code to a Dockerfile in the `/php` directory: ```docker Dockerfile theme={null} FROM reg.mini.dev/php:fpm # Install any PHP extensions if needed # Set working directory WORKDIR /app # Copy application files COPY ./src /var/www/html ``` If you want to enable additional extensions then you can create a private image in Image Creator with the appropriate additional extensions. Create an `nginx` folder and save the following code to a Dockerfile in the `/nginx` directory: ```docker Dockerfile theme={null} FROM reg.mini.dev/nginx-proxy-manager:latest # Copy nginx configuration COPY nginx.conf /etc/nginx/nginx.conf ``` Create a `src` folder and save the following code to a new file `index.php` under the `/src` directory: ```php index.php expandable theme={null} PHP-FPM Welcome
Welcome to PHP-FPM - Built by Minimus!"; echo "

👍 Looking great!

"; echo "

Your PHP-FPM server is up and running.

"; $currentTime = date("Y-m-d H:i:s"); echo "

Current time: $currentTime

"; ?>
``` Create a directory `/letsencrypt`. Your project directory should now look like this: ```text theme={null} project-root/ ├── compose.yaml ├── nginx.conf ├── letsencrypt/ ├── nginx/ ├ └── Dockerfile ├── php/ ├ └── Dockerfile └── src/ └── index.php ``` Run the app: ```bash theme={null} docker compose up -d ``` Open your web browser to view the welcome page at: `http://localhost:8080`. You should see a Minimus greeting with the current time. Once ready to clean up, run the following command to remove the containers and their associated volumes: ```bash theme={null} docker compose down -v ``` # Python Tutorial Source: https://docs.minimus.io/guides/python Build a secure and minimal python app using the Minimus python image In this tutorial, we will build a custom Python app using Docker Compose and a multi-stage Dockerfile. The build stage uses `latest-dev` because it requires the package installer `pip`. The runtime stage uses the fully distroless image to achieve the most secure app. Create a project directory and save the code below to a new `docker-compose.yml` file: ```yaml theme={null} services: flask-app: build: ./app ports: - "5000:5000" ``` Create a subdirectory and name it `app`. Add the following to it: * Save the following sample script as a new `main.py` file. ```python expandable theme={null} from flask import Flask from datetime import datetime app = Flask(__name__) @app.route("/") def show_time(): now = datetime.now() return f"Current date and time: {now.strftime('%Y-%m-%d %H:%M:%S')}" if __name__ == "__main__": app.run(host='0.0.0.0', port=5000) ``` * Save a `requirements.txt` file to list the Python packages that the project depends on. Python’s default package installer `pip` uses it. For our simple example, save only: ```markdown theme={null} flask>=3.1.1 ``` In the same directory, save the code below to a new `Dockerfile`: ```dockerfile expandable theme={null} # === Build Stage === FROM reg.mini.dev/python:latest-dev as builder WORKDIR /app RUN python -m venv venv ENV PATH="/app/venv/bin":$PATH COPY requirements.txt requirements.txt RUN pip install -r requirements.txt # === Runtime Stage === FROM reg.mini.dev/python:latest WORKDIR /app COPY main.py main.py COPY --from=builder /app/venv /app/venv ENV PATH="/app/venv/bin:$PATH" ENTRYPOINT ["python", "main.py"] ``` Note that the builder stage uses `reg.mini.dev/python:latest-dev` so it can utilize PIP. The runtime stage uses the fully distroless production image - `reg.mini.dev/python:latest`. Your project directory should now look like this: ```text theme={null} your-project-root/ ├── docker-compose.yml └── app/ ├── Dockerfile ├── main.py └── requirements.txt ``` You are now ready to build the app using Docker Compose: ```bash theme={null} docker compose build ``` Docker Compose will build the app from the `app` folder. Once built, you will see a confirmation: ```text theme={null} ✔ flask-app Built ``` Run the app: ```text theme={null} docker compose up ``` Test the app by sending it a request: ```text theme={null} curl http://127.0.0.1:5000 ``` You should get a response with the current date and time. Once ready to clean up, run the following command to remove the container: ```text theme={null} docker compose down ``` # Trino Plugins Source: https://docs.minimus.io/guides/trino-plugins Add and configure Trino plugins in Minimus Trino images using Creator, including FIPS-compatible plugins and catalog setup examples. For security reasons, Trino built by Minimus includes only 5 of the 54 plugins in the public image: * Only plugins that operate entirely within the Trino JVM or use the local filesystem are included by default in the Minimus Trino image. * Plugins that require external databases, cloud SDKs, or network endpoints to function are excluded by default. To add more plugins, create a private image using Creator to install the plugins. The trino plugins are packaged by Minimus and have the same names as the original public plugins. For example: `trino-plugin-cassandra`, `trino-plugin-hive`, etc. If you're working with a Trino-FIPS image, install the Trino FIPS compatible plugins, for example `trino-fips-plugin-cassandra`. Trino plugins are tightly coupled to the exact server build. Creator handles these compatibility issues automatically. ## Install Plugins with Creator The standard way to install Trino plugins when working with a Minimus Trino image is to create a private image using Creator. 1. Go to [Creator](https://images.minimus.io/creator/) 2. Select the Minimus Trino image as your starter image 3. Select the relevant packages. They're named `trino-plugin-{name}`. 4. Finish configuring your private image, adding env variables, certificates, etc. If you're using a Trino-FIPS starter image, install the FIPS plugins (their name takes the format: `trino-fips-plugin-{plugin-name}`). 5. Save and build the private image. Creator will build your custom Trino image in all available versions with the plugins of your choice and maintain it for you. ## Example: Configuring the MySQL Catalog for Trino The following example uses a private Trino image with the MySQL connector plugin baked in. To query a MySQL database through Trino, you need to register it as a catalog. This tutorial walks through the setup using Docker. We will deploy a custom Trino image alongside a MySQL instance and run a federated query across MySQL and Trino's built-in sample data. ### Prerequisites * Docker installed and running ### Step 1: Start MySQL Create a Docker network and start a MySQL container with a sample database: ```shellscript theme={null} docker network create trino-test docker run -d --rm --name mysql --network trino-test \ -e MYSQL_ROOT_PASSWORD=demo \ -e MYSQL_DATABASE=shop \ reg.mini.dev/mysql:8 ``` Wait a few seconds for MySQL to initialize, then seed a sample table: ```sql theme={null} docker exec -i mysql mysql -uroot -pdemo shop <<'SQL' CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(100), price DECIMAL(10,2) ); INSERT INTO products VALUES (1, 'Keyboard', 49.99), (2, 'Monitor', 299.99), (3, 'Mouse', 24.99); SQL ``` ### Step 2: Write the Catalog Properties Create a file called `mysql.properties` in your working directory: ```text theme={null} connector.name=mysql connection-url=jdbc:mysql://mysql:3306 connection-user=root connection-password=demo ``` This tells Trino how to connect to the MySQL instance. The hostname `mysql` matches the container name on the Docker network. ### Step 3: Start Trino Use Creator to build a private image with the package `trino-plugin-mysql` and name it `trino-mysql`. Run the Trino-MySQL image and mount the catalog file (replace the `{id}` with your own tenant ID before running the command): ```text theme={null} docker run -d --rm --name trino --network trino-test \ -p 8080:8080 \ -v $(pwd)/mysql.properties:/etc/trino/catalog/mysql.properties \ reg.mini.dev/{id}/trino-mysql:latest ``` Wait for Trino to finish starting up (about 30 seconds), then confirm the MySQL catalog is registered: ```shellscript command theme={null} docker exec trino trino --execute "SHOW CATALOGS" ``` ```text expected output theme={null} "jmx" "memory" "mysql" "system" "tpcds" "tpch" ``` You should see `mysql` in the output alongside the default catalogs (`system`, `tpch`, etc.). ### Step 4: Query MySQL through Trino List the tables in the `shop` database: ```shellscript theme={null} docker exec trino trino --execute "SHOW TABLES FROM mysql.shop" ``` Query the products table: ```shellscript query command theme={null} docker exec trino trino --execute "SELECT * FROM mysql.shop.products" ``` ```text expected output theme={null} "1","Keyboard","49.99" "2","Monitor","299.99" "3","Mouse","24.99" ``` You should see the three rows inserted earlier. ### Step 5: Run a Federated Query One of Trino's strengths is querying across multiple data sources in a single statement. Join the MySQL table with the built-in `tpch` sample data: ```text theme={null} docker exec trino trino --execute " SELECT p.name, p.price, n.name AS nation FROM mysql.shop.products p CROSS JOIN tpch.tiny.nation n WHERE n.nationkey < 3 ORDER BY p.name, n.name " ``` This query pulls products from MySQL and nations from the in-memory `tpch` catalog, all in one pass. ### Clean Up Remove the containers and network: ```text theme={null} docker rm -f trino mysql && docker network rm trino-test ``` ## Catalog Reference ### How catalogs work Trino uses catalog properties files to register data sources. Each `.properties` file placed in `/etc/trino/catalog/` becomes a catalog with the filename as its name (e.g., `mysql.properties` registers a catalog called `mysql`). Queries follow a three-part naming convention: `catalog.schema.table`. ### Mounting catalogs in Kubernetes When deploying with the Trino Helm chart, add catalogs through the `additionalCatalogs` field in your `values.yaml`: ```yaml theme={null} additionalCatalogs: mysql: | connector.name=mysql connection-url=jdbc:mysql://mysql-host:3306 connection-user=trino connection-password=secret ``` Each key becomes a catalog name and the value is the contents of the properties file. See the [Trino Helm chart documentation](https://trino.io/docs/current/installation/kubernetes.html) for the full set of options. ### Connection properties | Property | Description | | --------------------- | --------------------------------------------- | | `connector.name` | Always `mysql` for the MySQL connector | | `connection-url` | JDBC URL in the form `jdbc:mysql://host:port` | | `connection-user` | MySQL user for Trino to authenticate as | | `connection-password` | Password for the MySQL user | For the full list of tuning and security options, see the [Trino MySQL connector docs](https://trino.io/docs/current/connector/mysql.html). # About SBOMs Source: https://docs.minimus.io/integrity/sbom Understand what's included in the SBOM provided for every Minimus image version A Software Bill of Materials (SBOM) is a structured list of the components, libraries, and versions that make up a software product. The SBOM is used by vulnerability scanners to issue advisories of vulnerable components and is therefore key to vulnerability management. The quality and accuracy of the image SBOM is considered to be critical to the completeness of the vulnerability report (and advisories) issued for the image. Minimus images carry signed SBOMs that adhere to the latest best practices with dependency scanning and provenance tracking. ## Minimus SBOMs Minimus creates its image SBOMs during the build process to ensure the SBOMs are accurate, complete, comprehensive, and fully transparent. Generating the SBOM at the post-build stage can miss locally built components, leading to incomplete inventories. ### Inspect image SBOM Minimus offers signed SBOMs for download for all of its images. SBOM details are also provided in a convenient table format with quick filtering options directly in the Minimus Gallery in the [image version card](/foundations/image-version). Note that the SBOM is specific to the image build (this can be identified by the image digest). The image version card shows the SBOM of the latest digest. The composition of packages can differ between image versions and even digests for the same image version. ### Inspect container SBOM The SBOM is listed under the static path `/var/lib/db/sbom/` in every Minimus image. The path includes an SPDX file for every package contained in the image. For example, here is one method for directly inspecting the SBOM of an image. For simplicity, the example is provided for a Minimus dev image that contains a shell, but production images have the same folder: 1. Run the dev image you wish to inspect. For example: ```bash theme={null} docker run --name minimus-nginx reg.mini.dev/nginx:latest-dev ``` 2. Open a shell in the running container: ```bash theme={null} docker exec -it minimus-nginx sh ``` 3. List the directory contents for `/var/lib/db/sbom/`: ```bash theme={null} ls /var/lib/db/sbom/ ``` 4. The SBOM SPDX files will be listed, by package name and version with the file ending `.spdx.json`: ```Example SBOM SPDX files theme={null} apk-tools-2.14.10-r0.spdx.json libgcc-15-15.2.0-r2.spdx.json bash-5.3-r0.spdx.json libidn2-2.3.8-r0.spdx.json busybox-1.37.0-r6.spdx.json libldap-2.6.10-r0.spdx.json ca-certificates-20251003-r0.spdx.json libnghttp2-14-1.68.0-r0.spdx.json ca-certificates-bundle-20251003-r0.spdx.json libpcre2-8-0-10.47-r0.spdx.json cyrus-sasl-2.1.28-r3.spdx.json libpsl-0.21.5-r1.spdx.json ``` ### Direct and indirect dependencies Minimus SBOMs include all transitive dependencies. Transitive dependencies include both: * Direct dependencies that are explicitly declared in the project * Indirect dependencies which are dependencies of your dependencies. That is, they are second order dependencies. Minimus reduces complex dependency trees that can be difficult to graph and track into a flat, straight-forward list that ensures that security scanners don't miss any vulnerabilities and cause false-negatives (unreported vulnerabilities that present risk but go undetected). ## Understand why SBOMs are key to software supply chain security SBOMs became mandatory by executive order for all U.S. government agencies in 2021 following the SolarWinds attack. Revisiting key points about the attack is helpful in understanding why SBOMs are crucial to ensuring software supply chain security in any organization of any size. ### The SolarWinds attack The SolarWinds 2020 attack, arguably the biggest cybersecurity breach of the 21st century to date, marked a turning point for software supply chain management, and particularly, led to SBOMs becoming ubiquitous. SolarWinds Orion, was an IT performance monitoring system with privileged access to IT systems to obtain log and system performance data. The attack introduced a backdoor by injecting malicious code known as *Sunburst* (hence the alternate name for the attack). SolarWinds inadvertently delivered the backdoor malware as an update to the Orion software. The hack compromised the data, networks and systems of thousands of organizations, including the US departments of Homeland Security, State, Commerce and Treasury and a long list of Tech giants, including Microsoft, Intel, Cisco, and Deloitte. In total, 18k of Orion's 30k customers had installed the compromised upgrade. The fallout was exponential, exposing not only SolarWinds Orion direct users but also their customers and partners. FireEye analysis determined that the attack was rolled out between September 2019 and March 2020, but wasn't discovered until December 2020, meaning the attack dwell time was well over a year! The attack was clearly led by a nation-state, with Russia being the prime suspect, but China involvement suggested as well. ### The aftermath SolarWinds was a catalyst for rapid, broad change in the cybersecurity industry and spurred vast regulatory changes: * An [executive order was issued mandating the use of software SBOMs](https://www.govinfo.gov/content/pkg/DCPD-202100401/pdf/DCPD-202100401.pdf) by all U.S. government agencies * A new [cybersecurity position in the National Security Council](https://www.politico.com/news/2021/01/06/biden-white-house-cybersecurity-neuberger-455508) was established * For the first time, the SEC sued the *victim* of a cyberattack [(October 2023)](https://www.techtarget.com/whatis/feature/SolarWinds-hack-explained-Everything-you-need-to-know) # About Software Integrity Source: https://docs.minimus.io/integrity/sigstore Learn how software integrity and trustworthiness can be ensured with the Sigstore toolchain Minimus uses the Sigstore architecture to sign and verify images and their contents. Sigstore is a collection of open-source projects backed by [OpenSSF](https://openssf.org/about/) (The Open Source Security Foundation) that includes several technologies: Cosign, Rekor, and Fulcio. The Sigstore toolchain is used to ensure that all build artifacts are cryptographically signed and tamper-proof. As the software provider, Minimus uses Cosign to sign the code artifacts in order to confirm that the software is trustworthy and comes from a known source. As an end-user, you can use Cosign verify commands to confirm that an image was properly signed by Minimus and to verify that the artifact was not tampered with after it was signed. Implementing software signature verification as part of your development process is key to following best practices for software supply chain security. ## Overview The following is a general overview of the process used to verify the integrity of software artifacts using the Cosign keyless signing process. The developer requests a certificate from the Fulcio certificate authority. The developer authenticates using Open ID Connect and Fulcio returns the signing key pair. Cosign orchestrates the signing and publishes the public key to the Rekor transparency log. The developer uses the private keys to sign the artifact, then publishes the signed artifact to end users. The private key is deleted. End users download the signed artifact and verify both aspects: * Check the signature in the Rekor transparency log using the public keys generated with Cosign (from step 1). * Check that the signing party is in the trust root. ## Signing public and private key pair Fulcio generates a key pair that includes: * **Private key** for signing data. The signing key is private and extremely short-lived so it doesn't need to be stored. * **Public key** for verifying the signature. The verification key is public and openly distributed so anyone can use it to verify the signature. ### Keyless signing increases trust To protect against forgery, the private signing key is extremely short-lived, which minimizes its risk of being hijacked or stolen. This technology is known as **keyless signing**, not as an overstatement, but to emphasize the fact that the keys do not need to be stored. The signing keys, which expire immediately after the artifact is signed, are said to be **ephemeral**. The signing key pair is only generated once the user authenticates via OpenID Connect (OIDC), such as Google, GitHub, or Microsoft. This process confirms the identity of the signing party and also ensures that the private key was valid at the time of signing. ## Fulcio certificate authority Fulcio is a certificate authority for developer signatories, inspired by the public certificate authority revolution for SSL certificates led by [Let's Encrypt](https://letsencrypt.org/). Fulcio binds the public verification keys provided by Cosign to the signer's OIDC token thereby allowing others to look up the identity of the party that signed off on the software. OIDC tokens can be generated using email, GitHub or GitLab workflows, etc. [Learn more about OIDC tokens](https://docs.sigstore.dev/certificate_authority/oidc-in-fulcio/) Fulcio acts as a trusted party that verifies the identity of the signer. You can trust the signature of the image (or SBOM or any other signed code artifact) because you trust Fulcio, the certificate authority. ## Rekor log Rekor is Sigstore's signature transparency log, where each entry in the log provides auditability for a signed artifact. A public instance of Rekor is maintained by the Sigstore community. Rekor provides an immutable transaction log enabling users to verify the integrity of their downloaded software artifacts. Rekor stores records of artifact metadata, providing transparency for signatures so users can monitor and detect any tampering of the software supply chain. # Trust Center Source: https://docs.minimus.io/integrity/trust Minimus commitments on service availability, vulnerability remediation, certifications, and data confidentiality Trust is at the heart of security. Following are our promises to you. ## Service availability (Enterprise Edition) Minimus maintains a service availability target of 99.9% uptime. You can see real time and historical availability on our [status page](https://docs.minimus.io/status). ## Vulnerability remediation policy (Enterprise Edition) Minimus Enterprise Edition commits to vulnerability patching within set timeframes, excluding only rare and extraordinary exceptions. **CISA KEV Active Exploits** * Any active exploit vulnerability affecting a Minimus image will be remediated within 1 calendar day from the time a new release is available from the upstream project that fixes the vulnerability. An active exploit is a vulnerability listed in the CISA Known Exploited Vulnerabilities Catalog. [See how Minimus clearly marks active exploits in image cards and advisories](/remediate/threat-intel) **SLAs set by vulnerability severity** * A critical or high severity vulnerability will be remediated within 2 calendar days from the time a new release is available from the upstream project that fixes the vulnerability. * All other vulnerabilities (Medium, and Low severity) will be remediated within 14 calendar days from the date a new release is available from the upstream project that fixes the vulnerability. The above targets are provided under the applicable Minimus Vulnerability Remediation Policy. [**Contact us for further information**](https://support.minimus.io/support/home) See also our [supplementary remediation policies](/remediate/policies/remediation-policy) and [cherry picking policy](/remediate/policies/cherry-pick-patches) ## New version SLA (Enterprise Edition) New upstream version releases are incorporated into Minimus images within **7 calendar days** of their original release. This timeline may be extended when significant upstream defects, breaking changes, or exceptional conditions necessitate additional validation. This target is provided under the applicable Minimus Policy. [**Contact us for further information**](https://support.minimus.io/support/home) ## Certification Minimus has secured [SOC 2](https://www.aicpa-cima.com/topic/audit-assurance/audit-and-assurance-greater-than-soc-2) and [ISO 27001](https://www.iso.org/standard/27001) certification. * SOC 2® accreditation is SOC for Service Organizations: Trust Services Criteria. * ISO/IEC 27001 is the golden standard for information security management systems (ISMS). The accreditation covers information security, cybersecurity and privacy protection. ## Cookies Minimus uses [Cookiebot](https://www.cookiebot.com/) to manage cookie consent on this site. You can review all cookies in use, including their names, purposes, and retention periods, and manage your personal consent preferences in our [Cookie Declaration](/cookie-declaration). # Verifying Images & SBOMs Source: https://docs.minimus.io/integrity/verify Use Cosign to verify image signatures and SBOM attestations for Minimus images Minimus uses the [Sigstore](https://www.sigstore.dev/) toolkit to sign its images to allow end-users to verify image provenance. Cosign is the Sigstore tool for signing and verifying container images. If you're new to Sigstore, take a minute to [learn the basics](/integrity/sigstore). ## Prerequisites Before you can begin, you'll need to install the following: * [Cosign](https://docs.sigstore.dev/cosign/overview/) - needed to verify and download image signatures and attestations * [jq](https://stedolan.github.io/jq/) - a JSON processor needed to format the attestations ## Verify image Use Cosign to verify the signature of a Minimus image by running one of the below commands. ```bash General command theme={null} # verify an image cosign verify \ --certificate-oidc-issuer=https://accounts.google.com \ --certificate-identity=minimus-images-sa@prod-375107.iam.gserviceaccount.com \ reg.mini.dev/{image}:{tag} | jq ``` ```bash Example with image tag theme={null} # verify an image cosign verify \ --certificate-oidc-issuer=https://accounts.google.com \ --certificate-identity=minimus-images-sa@prod-375107.iam.gserviceaccount.com \ reg.mini.dev/go:latest | jq ``` ```bash Example with image digest theme={null} # verify an image cosign verify \ --certificate-oidc-issuer=https://accounts.google.com \ --certificate-identity=minimus-images-sa@prod-375107.iam.gserviceaccount.com \ reg.mini.dev/go@sha256:c85345b30f809b53361880e2c84766d808f166c9820d41c98207f340f1efdeaf | jq ``` The command validates that the container image is cryptographically signed by a trusted Google service account with a certificate issued by Google’s OIDC provider. If the verification is successful, you will receive a JSON with information about the signature. Explanation: * `cosign verify` instructs Cosign to verify the cryptographic signature of the specified container image. * `--certificate-oidc-issuer=https://accounts.google.com` is used for images signed by a Google Cloud service account. * `--certificate-identity=minimus-images-sa@prod-375107.iam.gserviceaccount.com` defines the Minimus build process as the expected identity. * `| jq` formats the output in a human-readable JSON structure using the JQ JSON processor. ## Verify image SBOM Use the `cosign verify-attestation` command to verify the image SBOM. The SBOM is created and signed during the image build workflow and is stored along with the image in the registry. You will need to specify the architecture-specific image digest. ```bash General command theme={null} cosign verify-attestation \ --type https://spdx.dev/Document \ --certificate-oidc-issuer=https://accounts.google.com \ --certificate-identity=minimus-images-sa@prod-375107.iam.gserviceaccount.com \ reg.mini.dev/mini_2lg***/{image}@sha256:****** ``` ```bash Example theme={null} cosign verify-attestation \ --type https://spdx.dev/Document \ --certificate-oidc-issuer=https://accounts.google.com \ --certificate-identity=minimus-images-sa@prod-375107.iam.gserviceaccount.com \ reg.mini.dev/mini_***/go@sha256:c3b0414330d5be44cc079ae9152ca6ce5b327182309b6ada91451351b70216c5 ``` To learn more about the flags used in this command, visit Cosign documentation for [Verify Attestation](https://github.com/sigstore/cosign/blob/main/doc/cosign_verify-attestation.md) in GitHub. ## Download image SBOM Use the `cosign download attestation` command to print the SBOM attestation directly to the terminal. The SBOM is created and signed during the image build workflow and is stored along with the image in the registry. You will need to specify the image architecture, for example `linux/amd64`. ```bash General command theme={null} cosign download attestation \ --platform linux/amd64 \ --predicate-type=https://spdx.dev/Document \ reg.mini.dev/{image:tag} | \ jq '.payload | @base64d | fromjson | .predicate' ``` ```bash Example theme={null} cosign download attestation \ --platform linux/amd64 \ --predicate-type=https://spdx.dev/Document \ reg.mini.dev/mini_ftwgvii4jko2qkz3brp6mrcmgjzukfdl/go:latest | \ jq '.payload | @base64d | fromjson | .predicate' ``` To learn more about the flags used in this command, visit Cosign documentation for [Download Attestation](https://github.com/sigstore/cosign/blob/main/doc/cosign_download_attestation.md) in GitHub. ### SPDX format When downloading the signed SBOM from Minimus, it will be downloaded in the SPDX format. SPDX, short for Software Package Data Exchange, is the most popular SBOM format. SPDX is an open standard for communicating SBOM information developed by the Linux Foundation. Learn more about the [SPDX spec](https://spdx.github.io/spdx-spec/v2.3/) ## Print package license info You can use a CLI command to print the package license information from the SBOM attestation. The information includes the URLs to view the original license agreements, where available. Packages without standard SPDX license identifiers such as FIPS packages marked as PROPRIETARY will not include the URL to the license agreement. For example, here's the command to print the licenses used by the Minimus nginx image: ```shellscript Command to print package license info expandable theme={null} cosign download attestation \ --predicate-type=https://spdx.dev/Document \ --platform linux/amd64 \ reg.mini.dev/nginx:latest \ | jq -r ' .payload | @base64d | fromjson | .predicate.packages | map(select(any(.externalRefs[]?; (.referenceLocator // "") | contains("pkg:apk/")))) | unique_by(.name) | .[] | . as $p | "Package: \($p.name)\nVersion: \($p.versionInfo // "unknown")\nLicense: \($p.licenseDeclared // "UNKNOWN")" + ( if (($p.licenseDeclared // "UNKNOWN") | test("^(NOASSERTION|UNKNOWN|NONE)$")) then "\nLicense URL: Not available\n" else "\nLicense URL(s):\n" + ( ($p.licenseDeclared | gsub(" AND | OR | WITH "; ",") | split(",") | map(select(. != "" and . != "NOASSERTION" and . != "UNKNOWN" and . != "NONE")) | map(" https://spdx.org/licenses/\(.).html") | join("\n") ) + "\n" ) end ) ' ``` The output will print out the SBOM information as follows: * Package name * Package version * License name * License URLs ```yaml Example from the license printout for the Minimus nginx image expandable lines theme={null} Package: ca-certificates-bundle Version: 20251003-r0 License: MPL-2.0 AND MIT License URL(s): https://spdx.org/licenses/MPL-2.0.html https://spdx.org/licenses/MIT.html Package: glibc Version: 2.43-r0 License: LGPL-2.1-or-later License URL(s): https://spdx.org/licenses/LGPL-2.1-or-later.html Package: glibc-locale-posix Version: 2.43-r0 License: LGPL-2.1-or-later License URL(s): https://spdx.org/licenses/LGPL-2.1-or-later.html ... ``` # Introduction Source: https://docs.minimus.io/introduction Get started with Minimus secure container images and Helm charts Built from source, scanned for vulnerabilities around the clock, signed with SBOMs, and tested for build integrity and Kubernetes readiness. ## Getting Started The first step to more secure applications begins with more secure images. Discover the images and Helm charts you need Pull any image, any version, any tag to get started Verify signatures with Cosign Always pull fresh images to stay protected ## Staying Secure Always patched, every single day. Fresh images released daily Ongoing vulnerability scans and reports Validate CIS and NIST compliance Keep up with all updates ## Switch to Distroless Build leaner, run safer. Migrate from Alpine, Debian, or Ubuntu Being selective about dev tools Debug without a shell Default to an unprivileged user ## Level Up More secure apps require more secure techniques. Build secure Python apps with Minimus Deploy a distroless Python app on AWS Lambda Test out a slimmer runtime base Minimize the attack surface with multi-stage builds ## Power Your AI Agents Harness AI skills. Extend images with MinimOS packages. Skill your agents to work with Minimus Directly install Minimus packages ## The Minimus Software Supply Chain From source to signed image. Security you can trust and verify. The Minimus build pipeline explained Safeguarding artifact integrity ## FIPS for FedRAMP FIPS 140-3 verified images for day-one compliance. Minimus CMVP certificates and cryptographic modules Deploy kernel-independent OpenSSL FIPS 140-3 on any hardware Build FIPS 140-3 validated Java apps Deploy a FIPS-compliant Keycloak instance ## Enterprise Edition Unlock the full Minimus developer experience. Create your golden images Secure your software supply chain from malicious packages Discover more Minimus features Manage private images as code # Why Minimus Source: https://docs.minimus.io/introduction/about-minimus A short introduction to Minimus explaining how Minimus images can radically reduce the amount of vulnerabilities that impact your cloud environment Minimus is a repository of lightweight images designed to drastically reduce your attack surface. Minimus reduces vulnerabilities by trimming out software bloat and publishing patched versions as soon as upstream releases a fix. Minimus builds its images from scratch, directly from upstream project sources, with only the minimal software needed to run the app. As a result, many Minimus images have 0 vulnerabilities at their time of release and accumulate fewer vulnerabilities at a slower rate compared to comparable standard images, all helping to reduce your attack surface over time. Safeguarding against vulnerabilities in cloud environments is faster, easier, and better with Minimus. Give Minimus images a quick try to see the immediate vulnerability reduction in your own environment. [Get Started](https://images.minimus.io/) ## About Minimus Minimus images help keep you safer because they are: * **Secure** - Experience a reduction of up to 100% in vulnerabilities. Minimus images have few to no vulnerabilities at their time of release and accumulate vulnerabilities at a slower rate. * **Lightweight** - Software bloat is meticulously removed to keep the image minimal, more secure, and more performant with quicker load times. * **Authenticated & Verifiable** - All software artifacts are signed to ensure integrity & authenticity. Software artifacts can be verified through build and SBOM attestations. * **Fresh** - Daily builds ensure the freshest upgrades are available as soon as possible. * **Cloud-focused** - Designed to run natively on any cloud infrastructure and Kubernetes. * **Distroless** - Containers run on the host kernel. * **OCI compliant** - Minimus images adhere to the OCI specification for promoting vendor-neutral and portable images and containers. ## Minimus Community Edition Community Edition includes: * [Fresh daily image builds](/foundations/daily-updates) * [Image compliance reports](/foundations/image-card#compliance) * Comprehensive [image changelog](/foundations/image-card#changelog) detailing what's changed with every digest in every version * Image, SBOM, and Helm chart [signatures & verification](/integrity/verify) * [Compatible package repository](/basics/package-manager-access) * [Minimus Helm charts](/foundations/helm-charts) for orchestrated deployment of Minimus secure images * Security advisories enriched with severity analysis, EPSS exploitability, and CISA KEV information, reviewed by the Minimus security team for accurate dependency detection and to eliminate false positives and false negatives * [Cherry pick patches](/remediate/policies/cherry-pick-patches) offer even faster remediation when possible ## Managing security with Minimus images Relying on OSS infrastructure comes with the responsibility of maintaining software provided “as is”, with no liability. Switching to Minimus images provides an improved experience with advanced source, build, and dependency integrity and a dependable advisory and patching service that will save your organization thousands of hours detecting, triaging, and patching vulnerabilities. The Minimus threat intel dashboard will help you stay informed of the most critical updates and threats, and track the security advantage of your Minimus images over their comparable OSS options. # Architecture Source: https://docs.minimus.io/introduction/architecture Understand the Minimus pipeline for building and testing secure packages and images Minimus builds its images directly from source and manages its own internal CI/CD pipelines. The following diagram describes the process. Minimus Architecture ## The Minimus build pipeline Minimus monitors all upstream projects to detect updates on a continuous basis. The pipeline involves standardized build processes and automated workflows as follows: 1. Minimus continuously monitors open source projects and triggers a new package build every time there is an update to a package from the package maintainers in the form of a package "release" in the upstream package source. Every package build receives a new package version. For example - the `foo` package maintainers have released a new minor version - going from 1.2.3 to 1.2.4, in this case Minimus will detect the new package release and it will follow the process outlined. In a counter example, the `foo` source code repository has received new commits, however there is no new formal release from the maintainers, in this case Minimus will not build a new version of the `foo` package. For rare exceptions to this process, please see the [ Minimus cherry-picking policy](https://docs.minimus.io/remediate/policies/cherry-pick-patches#cherry-picking-patches). 2. Once a day, Minimus builds every image version awaiting package updates. This ensures that new updates and vulnerability fixes are delivered daily. 1. The daily image build is skipped if no package updates are available. 2. Image builds take into account package version constraints. 3. Minimus tests the new packages and images, and runs vulnerability scans and other compliance checks. See a discussion of the Minimus testing methodology below. 4. Minimus signs images and their SBOMs and publishes them to the Minimus registry. Users are encouraged to verify Minimus images and SBOMs. See [verifying images](/integrity/verify) 5. The Minimus Console shows current vulnerability reports for all of its images, across all available versions. To achieve this transparency, Minimus continuously scans all of its packages and image versions for new vulnerabilities. See [vulnerabilities report in the image card](/foundations/image-version#vulnerabilities) 6. You can easily see detailed information about every update to every component in every build in the image [changelog](https://docs.minimus.io/foundations/image-card#changelog). ### Understanding image versioning An image can be rebuilt without a change to the version tag. It depends on which packages were updated: 1. If the primary package was updated, the image will receive a new version tag. For example, an updated `mysql` package in the MySQL image or a new `elasticsearch` package in the Elasticsearch image. The primary package version matches the version tag of the image. 2. If other non-primary packages were updated, the new image will have the same version tag but a new image digest and timestamp tag. See [Minimus timestamp tag](/foundations/daily-updates#unique-timestamp-tag) and [digest history](/foundations/image-version#digest-history) ## Unit testing A daily image build and validation cycle is triggered following any change to either the configuration files or any of the included packages. Minimus image testing is designed to test build integrity, runtime correctness, and Kubernetes readiness. Extensive unit testing is performed to ensure that the image behaves as expected before it is published to the Minimus registry. Tests are fully automated and run in a controlled environment to check that required packages are present, entrypoint behavior is as expected, environment variables and file permissions are correctly set, relevant ports are listening and/or exposed, etc. ### Build integrity testing Build integrity testing checks for SBOM completeness, image structure (tags, entrypoint, etc.) and to confirm that the builds are reproducible. ### Runtime correctness Minimus images that are not expected to be run in Kubernetes undergo testing using Docker Compose and a Python `TestClient` for testing Python web app endpoints directly in code without starting a web server. A Python runner is used to iterate on tested images and replace a version variable with all available version tags in a Dockerfile or directly in Docker Compose. Testing also covers multi-architecture compatibility to ensure that the images can be run in both `amd64` and `arm64` environments. ### Kubernetes readiness For images expected to be deployed with Kubernetes and Helm charts, additional testing procedures are in place. Tests are automated within the CI/CD pipeline so that any changes to the image trigger validation to provide fast feedback and prevent regressions. Images expected to be deployed in Kubernetes are tested in Kubernetes using a python setup tool that configures the cluster and installs necessary services and/or images using Helm where applicable. Testing is performed with Bash and/or Python to test service functionality by running tasks in the cluster. ## The Minimus advisory pipeline ### Publishing package advisories Minimus scans all of its packages for vulnerabilities every few hours. Every time a new vulnerability is detected, the vulnerability advisory is published to the Minimus advisory list and initiates the Minimus review process. [About advisories](/remediate/advisories) ### Publishing image vulnerability reports Minimus offers an up-to-date vulnerability report for every image version in its registry. The vulnerability report for every image version is based on the SBOM and package vulnerability scans and is updated several times a day. [About vulnerability reports](/foundations/image-version#vulnerabilities) ## Minimus software supply chain security The Minimus build environment adheres to software supply chain security practices including: * **CI/CD hardening** - Minimus uses a secure build pipeline with strict access controls so all packages and images are built in a protected, trustworthy environment. * **Provenance tracking** - Minimus verifies the source and authenticity of open source code used in its pipeline. ## Beyond the Minimus Registry * The user-friendly Minimus Console is your primary gateway to the Minimus Registry. Use the console to navigate the gallery of images, understand which versions are available, and learn about any new relevant threat intel and updates. [About the image gallery](/gallery) * You can configure Minimus actions for the registry to push alerts using dedicated webhooks. [About actions](/remediate/actions) * You can also mirror images in your Minimus subscription to your private registry. [About self-hosting](/manage/self-hosted-registry) Serving Users # Compatibility Source: https://docs.minimus.io/introduction/compatibility Minimus images prioritize compatibility to minimize migration overhead and potential errors Minimus images are designed to easily replace open source images without encountering compatibility issues as much as possible. As a rule, Minimus images will match the security context and default entrypoint unless there are security considerations to address. ## Default user Minimus aligns the security context so that container runs by default with a UID that allows file permissions, volumes, and security policies to work together. There are several scenarios: * Non-root images: * If the public image runs as non-root, the Minimus image will match the user for compatibility reasons. For example, [Velero](https://images.minimus.io/images/velero/lines/latest/versions/1.17.1/specification) runs as user 1002, [ClickHouse-Operator](https://images.minimus.io/images/clickhouse-operator/lines/latest/versions/0.25.6/specification) runs as user 65534, [Argo CD](https://images.minimus.io/images/argocd/lines/3.2/versions/3.2.4/specification) runs as user 999. * If the public image runs as root but can also run as non-root, Minimus will set the default user to 65532 or 1000. For example: * [nginx](https://images.minimus.io/images/nginx/lines/1.29/versions/1.29.4/specification), [Node](https://images.minimus.io/images/node/lines/25/versions/25.3.0/specification), [Kibana](https://images.minimus.io/images/kibana/lines/9.2/versions/9.2.3/specification) run as user 1000 by default. * [Keda](https://images.minimus.io/images/keda/lines/2.18/versions/2.18.3/specification) and [AWS-Load-Balancer-Controller](https://images.minimus.io/images/aws-load-balancer-controller/lines/latest/versions/2.17.1/specification) run as user 65532 by default. * Root requirement: * If the image must run as root to support required functions, the Minimus image will default to root as expected. For example, [Go](https://images.minimus.io/images/go/lines/1.25/versions/1.25.5/specification), [Perl](https://images.minimus.io/images/perl/lines/5.42/versions/5.42.0/specification), [aws-for-fluent-bit](https://images.minimus.io/images/aws-for-fluent-bit/lines/latest/versions/3.2.0/specification) run as root. * Helm chart requirement: * If the image is designed to run with a Bitnami Helm chart, the image will run as user 1001 by default. Minimus Advanced images are designed to be deployed with Bitnami charts and therefore usually run as user 1001. [Learn more](/foundations/image-types) Below is the typical securityContext for Bitnami compatibility: ``` securityContext: runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 ``` The Minimus default user policy recently changed. Therefore, some Minimus images may have a default user that does not align with the above stated policy. [Please contact support for any questions or requests.](https://support.minimus.io/support/home) ### Look up the default user The [specification tab](https://docs.minimus.io/foundations/image-version#specification) in the image version card always lists the default user set by Minimus. If the default user changed between versions, the [changelog](https://docs.minimus.io/foundations/image-card#changelog) will show a configuration change ([example in the Minimus console](https://images.minimus.io/images/velero/changelog/latest?change=configuration-updated)). ## Entrypoint and default CMD Minimus images try to match the entrypoint of the public image whenever possible. However, this is not always possible. For example, if the public image uses an entrypoint script but the Minimus image does not include a shell, the entrypoint and default CMD will be different. For example, the Minimus images for [OpenJDK](https://images.minimus.io/images/openjdk/lines/25/versions/25.0.1/specification), [OpenJRE](https://images.minimus.io/images/openjre/lines/25/versions/25.0.1/specification) and [Fluentd](https://images.minimus.io/images/fluentd/lines/1.19/versions/1.19.1/specification) use an EXEC-form entrypoint instead of an entrypoint script. [Learn more](/basics/entrypoint) ### Look up the entrypoint and default command The [specification tab](https://docs.minimus.io/foundations/image-version#specification) in the image version card always lists the default entrypoint and default command set by Minimus. If the entrypoint or default command change between versions, the [changelog](https://docs.minimus.io/foundations/image-card#changelog) will show a configuration change. ## Default working directory Minimus aims to match the default working directory of the public image, unless there is a reason to diverge. Since Minimus images run as non-root in most cases, the working directory is often different from the public image to ensure it is writable by the default container user. Another reason why the working directory might differ is that Minimus images are optimized for [multi-stage build](/guides/multi-stage-build) workflows. Unlike many public images which include enough tooling to support building and running the application in the same image, Minimus images embrace the distroless approach. Consequently, many Minimus images are optimized for the build stage by setting the working directory to `home/build`. The Minimus images for [OpenJDK](https://images.minimus.io/images/openjdk/lines/25/versions/25.0.1/specification) and [OpenJRE](https://images.minimus.io/images/openjre/lines/25/versions/25.0.1/specification) are good examples. ### Look up the default working directory The [specification tab](https://docs.minimus.io/foundations/image-version#specification) in the image version card always lists the default working directory set by Minimus. If the working directory changes between versions, the [changelog](https://docs.minimus.io/foundations/image-card#changelog) will show a configuration change. ## Default volumes Minimus images often run as non-root, and are configured to permit write access to the UID (or GID) the container process runs as. To avoid filesystem permission mismatches, writable volumes may be placed on a different path than the public image. ### Look up the default volumes The [specification tab](https://docs.minimus.io/foundations/image-version#specification) in the image version card always lists the default volumes mounted by Minimus. If the volume mounts change between versions, the [changelog](https://docs.minimus.io/foundations/image-card#changelog) will show a configuration change. # Elevate security with Enterprise Edition Source: https://docs.minimus.io/introduction/enterprise-edition-member Set up advanced Minimus features with Enterprise Edition With a Minimus account, you can get more out of Minimus: 1. Create [private images](/enterprise-edition/image-creator) with a custom list of packages, certificates, env vars, and more. 2. Adapt private images to your CI/CD pipelines using [minicli](/enterprise-edition/minicli) 3. Set up [actions](/remediate/actions) 4. Sync Minimus images to your [private registry](/manage/self-hosted-registry) 5. Set up user management and SSO for the team ### **1. Create your first private image** If you would like to customize a Minimus image by adding packages, configuration files, certificates, or environment variables, you can use Minimus [Creator](/enterprise-edition/image-creator) to build your own private image. Minimus will maintain, update, and scan your private images just as if they were public images. If you are migrating from Alpine, Debian, or other distro-based images, you can learn more about how to build a custom image off Static with only the packages of your choice. You can also see our recommendations for adjusting Dockerfiles in more complex scenarios by temporarily escalating privileges, using Python virtual environments (venv), etc. See [Going Distroless](/foundations/going-distroless) ### **2. Connect your registry and pipelines** You'll want to check that you [meet the networking requirements](/manage/network). If you prefer to pull Minimus images through a third-party registry, you can set up syncing with [Google Artifact Registry](/manage/mirror-to-gcp-artifact-registry) or [JFrog Artifactory](/manage/sync-with-jfrog-artifactory). With a Minimus image subscription, you will also be able to [sync images to a self-hosted private registry](/manage/self-hosted-registry), even if it is air-gapped. ### **3. Enable supply chain protection** Minimus [supply chain protection](/enterprise-edition/supply-chain) guards against malicious packages and tampered dependencies in your private images. Once enabled, every package included in a private image is verified against the Minimus supply chain policy before the image is built. # Let's Get Started Source: https://docs.minimus.io/introduction/get-started Step-by-step guide to pulling your first images and deploying them in your environment using Minimus Helm charts Welcome to Minimus! Make the switch to Minimus images without breaking a sweat. The level of effort required to migrate depends on the application and environment, but in most cases it is extremely low or nearly effortless. ## First steps Get to know the Minimus platform: 1. [Explore the image gallery](/gallery) to see our full catalog, including FIPS 140-3 validated images, Hardened images for CIS app compliance, and Advanced images for Bitnami compatibility 2. [Review image vulnerability reports and risk reduction comparisons](/foundations/image-card) 3. Review image [compliance reports](/foundations/image-card#compliance) 4. [Understand daily security updates](/foundations/daily-updates) and image changelog 5. Pull any Minimus image - any version tag, any digest, any timestamp-tag. Swap images to get started! All image tags and digests are available in the Community Edition. ## Introducing Minimus ### 1. Discover the gallery Take a minute to orient yourself with the UI and learn about the display of [Minimus image cards](/foundations/image-card) and [version information](/foundations/image-version). ### 2. Pull your first image You can pull any Minimus image from the registry using any tag or digest. All Minimus images and versions are included in the Minimus Community Edition. Feel free to experiment with different images. ### 3. Deploy a Helm chart Deploy Minimus images using Minimus Helm charts. The process is quick and easy. ### 4. Plan your migration with your AI agent Uncover hidden issues and plan your migration with our AI prompt. Save time and surface required changes before you start. ### 5. Avoid stale images Keep in mind that Minimus images are updated regularly so even within the span of a few days you will want to [avoid using cached images](/foundations/pull-policy). ### 6. Next steps Minimus provides many in-depth guides to help you learn how to optimize your apps using [multi-stage builds](/guides/golang), [AWS Lambda](/guides/aws-lambda-deployment), configure [databases with secure TLS](/advanced-guides/mongo-tls), and more. Retention policy: Previous builds are retained for 180 days for production images, and 30 days for dev images. # Enterprise Edition Source: https://docs.minimus.io/introduction/highlights Make the most of Minimus with special features reserved for Enterprise Edition We want your Minimus experience to be exceptional. Here's how Minimus stands out: * [Creator](/enterprise-edition/image-creator) to customize private images * Central management of [certificates and other file bundles](/enterprise-edition/file-bundles) for private images * [Supply chain protection](/enterprise-edition/supply-chain) against malicious packages and tampered dependencies * FIPS 140-3 implementation support to meet FedRAMP and compliance requirements * [Actions](/remediate/actions) to trigger webhooks and notifications following image updates * Sync images to a [self-hosted registry](/manage/self-hosted-registry) * [Activity log](/manage/activity-log) for admin audits * SSO login with [SAML](/sso/saml) * [User groups](/manage/user-groups) for SAML group-based role assignments (RBAC) across identity providers * Configurable [tokens](/manage/token) * [minicli](/enterprise-edition/minicli) to define and manage private images as code from your terminal or CI/CD pipeline * [JFrog Artifactory sync](/manage/sync-with-jfrog-artifactory) and [GCP Artifact Registry mirroring](/manage/mirror-to-gcp-artifact-registry) for registry mirroring * The Minimus support team can help you meet regulatory requirements, comply with FIPS 140-3 cryptography standards, update your Dockerfiles, simplify the adoption process, and more. Don't hesitate to get in touch! ## Data confidentiality and segregation Minimus is committed to data confidentiality. Enterprise Edition Minimus accounts reside on a private tenant to ensure data isolation and to prevent any data leakage. No information is collected beyond the image pull count metrics which are presented in the UI in the subscription page and image card pages. ## Requesting new images Contact us to request a new type of image or to inquire about altering the packages in an existing image. # Dev vs. Prod Images Source: https://docs.minimus.io/introduction/image-variants Why Minimus offers dev images with dev tools alongside more minimal production images Every Minimus image comes in two variants: a production image and a dev image. Both are minimal, secure, and updated daily — but they serve different purposes. * The production variant is the most minimal build: no shell, no package manager, no development utilities. Just the runtime and its direct dependencies. * The dev variant includes standard tooling and at least one shell, making it suitable for building, testing, and debugging. Visit the **Risk Reduction** tab on any image page to compare vulnerability reports for both variants. ## Why production images exclude developer tooling Security requirements differ by context. In production, a smaller attack surface matters more than convenience. In development, speed and tooling matter more. Minimus lets you optimize for both without compromise. Every Minimus image version ships as a complementary pair: * Production image — e.g. `nginx:latest` * Dev image — e.g. `nginx:latest-dev` Production images contain only what's needed to run the application. Less code means fewer vulnerabilities, fewer attack vectors, and a smaller blast radius if something goes wrong. Dev images are built for the inner loop — building, testing, and debugging. They include a shell, a package manager, and common development utilities. They're slightly larger than their production counterpart, but still far leaner and more secure than the official upstream image. ## Using dev images in multi-stage builds The prod/dev pair is designed for multi-stage workflows. Use the dev image for intermediate build steps — compiling, testing, installing dependencies — then switch to the production image for the final stage. The result is a lean, secure artifact with no build tooling included. # Image Tags Source: https://docs.minimus.io/introduction/offering Pull any Minimus image version by any tag The Minimus gallery for Community Edition users shows every image version by all of its available tags. You can pull any supported image version by any available image tag. ## Image tag types | Tag | Example | Behavior | | ----------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `latest` | `nginx-fips:latest` | Always resolves to the most recently published image. Pulling this tag again in the future may give you a different image than today. | | Stable line | `nginx-fips:stable` | Tracks the current stable release line. Updates automatically to the newest stable patch but never jumps to a new major or minor version without your input. | | Image line | `nginx-fips:1.26` | Pins to a specific minor version. You will receive patch updates automatically, but your image will not advance to 1.27. | | Version | `nginx-fips:1.26.3` | Pins to an exact version. You can receive vulnerability patches and stay protected by making sure to [pull fresh images](/foundations/pull-policy) | | Timestamp | `nginx-fips:1.26.3-202504300027` | Pins to a specific build of a specific version. The timestamp tag is equivalent to the image digest. It is useful for full reproducibility in air-gapped or compliance-sensitive environments. | For example, if you want to pull to the NGINX-FIPS image, you can pull by any of the image tags: ```bash latest theme={null} docker pull reg.mini.dev/nginx-fips:latest ``` ```bash by stable line theme={null} docker pull reg.mini.dev/nginx-fips:stable ``` ```bash by image line theme={null} docker pull reg.mini.dev/nginx-fips:1.26 ``` ```bash by version theme={null} docker pull reg.mini.dev/nginx-fips:1.26.3 ``` ```bash by timestamp tag theme={null} docker pull reg.mini.dev/nginx-fips:1.26.3-202504300027 ``` To learn more, see [tags and digests](/basics/tags-and-digests). # Image Lines & Versions Source: https://docs.minimus.io/introduction/versions Understand how Minimus images are organized by image lines and versions The Minimus [gallery](/gallery) offers a convenient, intuitive display of image versions that match the release branches and version numbers used by the respective upstream projects. Minimus uses the following terminology to describe its images: * **Images** - Refers to the image type, as in Nginx, Python, Go, PHP, Redis, etc. Some images come in several options, such as `FIPS` for FIPS 140-3 verified images, `advanced` for Bitnami compatibility, and `hardened` for CIS app compliance. [Learn more](/foundations/image-types) * **Image lines** - Refers to the release branch. Minimus image lines match the upstream's maintained release lines. * **Versions** - Refers to the exact version number or release number. Image versions are placed under the appropriate image line (aka, release branch). Redis Versions Updated ## About image lines Minimus maintains release branches that are being actively supported by their upstream projects. Most projects maintain at least 2 image lines, but some maintain many more. For example, Postgres maintains 5 release lines ([ref](https://www.postgresql.org/support/versioning/)). Some projects use name tags in addition to the version number, for example nginx has `mainline` and `stable` image lines ([ref](https://nginx.org/en/download.html)). Support dates: * Images that are officially considered LTS (long term support) by the upstream project are marked as such. * Image lines that have reached end-of-life (EOL) or are near-EOL are shown at the bottom of the list in a separate category. ## About image versions Minimus follows the release schedule of the upstream projects. In other words, every time a new version is released by the upstream project, Minimus builds an image of the new version. The version numbers are identical to the upstream project and are shown in the relevant image line. [Learn more about the Minimus new version SLA](/integrity/trust#new-version-sla) The image version typically follows semantic versioning conventions in X.Y.Z format ([ref](https://semver.org/)). For example, an nginx image is tagged `mainline` and version `1.29.5` (on March 9, 2026). ### Daily image builds The `latest` tag may appear static but it is continuously being updated by Minimus to incorporate package updates as they are made available. This is true not only for `latest`, but also for the most recent version in every image line. While the image version didn't change, new digests indicate that the image was rebuilt with updated packages. The updates are listed in the [image changelog](/foundations/image-card#changelog) and [digest history](/foundations/image-version#digest-history). Every image build receives a new digest and a new unique timestamp tag. [Learn more](/foundations/daily-updates) ### Digest retention policy Minimus images are continuously being maintained and rebuilt with the freshest packages and updates. As a result, an image version may have numerous digests corresponding to the number of times the image was built by Minimus. As a user, you should always use the last available digest for your version of choice. For transparency, the Minimus image gallery displays a complete history of all previous builds, even after they have been removed from the registry. #### Retention schedule for historical digests Older image digests remain available to pull from the registry for a limited time: * **Production images:** Retained for **180 days** * **Dev images:** Retained for **30 days** Once the retention period expires, these outdated digests are permanently removed from the registry and can no longer be pulled. The most recent build for *every* minor version is **always retained**. This retention policy only removes older, redundant builds for versions that have multiple digests. ## LTS and EOL labels Minimus aims to provide accurate and complete information about support timelines and expected end of life dates for image lines. ### Long term support (LTS) Official long term support image lines are indicated in the Minimus console along with the set end-of-life date (if available). ### End of life (EOL) Scheduled end-of-life dates are provided, where available. This can save you the trouble of having to look them up in the upstream project. [Learn more](/foundations/image-card#versions) Eol Labels Updated ### Active support vs. security support Many open source projects offer two or more support phases. For example, Python and Node offer active support followed by security support ([Python ref](https://devguide.python.org/versions/), [Node ref](https://nodejs.org/en/about/eol)). MySQL offers premier support followed by extended support ([ref](https://www.mysql.com/support/)). In Minimus, end of life is indicated when the image line no longer receives any kind of support or updates upstream. [See Image Card](https://docs.minimus.io/foundations/image-card) ### When EOL date is unknown Some upstream projects do not provide EOL dates at all. Other projects only announce the EOL date for the latest image line only after the subsequent release is out. In such cases Minimus will mark the EOL as unavailable. You can reference the popular site [https://endoflife.date/](https://endoflife.date/) to quickly look up information about support schedules for most projects. ## Selecting the right image line If you're not already committed to a particular image version, you may be asking yourself which image line you should use? Minimus can help you decide based on your requirements: * As a general recommendation, unless you have constraints such as app compatibility issues, you should always use the latest version. This ensures that you are using the most up-to-date version and can benefit from security updates more completely. * If your testing cycle is relatively longer, you may be forced to use a previous version line. You should still opt for the most recent version within the line to benefit from daily security updates. * If you have constraints that require you to use an older image version, note that the version will not receive security updates. Minimus images are minimal and hardened from the start and so accumulate vulnerabilities more slowly, thereby staying more secure for a relatively longer period of time. * Visit the Minimus gallery to view a current vulnerability report for any image version. The report provides an up-to-date status on the vulnerabilities detected in the version. [Learn more about image vulnerability reports](/foundations/image-version#vulnerabilities) ## Multi-architecture images Minimus images are built to support multiple CPU architectures (amd64 and arm64) and can run on different hardware platforms without requiring separate images. When you run the `docker pull` command to get an image from the Minimus gallery, it will automatically pull the correct architecture for your system. You can toggle between the amd64 and arm64 image to view the relevant SBOM and SBOM signature. See for example the [Redis arm64 SBOM](https://images.minimus.io/images/redis/lines/8.8/versions/8.8.0/sbom?sbomArch=arm64) and [SBOM signature](https://images.minimus.io/images/redis/compliance/sbom-signature?arch=arm64). # Logs Source: https://docs.minimus.io/manage/activity-log Audit user actions and system events for complete visibility and accountability Minimus logs user and system activity for complete visibility and accountability. The logs are split into two tabs: * **Activity logs** - Logs events related to user management and user logins, tokens, Minimus actions, minicli, private image management via Creator or minicli, and file bundles. * **Audit logs** - Logs events related to supply chain policies. To view Minimus activity and audit logs, select **Manage > Logs** ([direct link](https://images.minimus.io/manage/logs)). ## Activity logs Check the activity log to audit user and system activity for any reason. The data can be filtered by date, user, and event type. Expand any row to see additional details. Activity Log The system logs the following activity and organizes by category: 1. Users 1. Added user 2. Deleted user 3. Updated user 2. Groups (for SAML/SSO) 1. Create group 2. Deleted group 3. Updated group 3. SAML 1. Updated SAML (This log can also refer to SAML enabled or disabled. Expand the log to view its details.) 4. Tokens 1. Created token 2. Deleted token 3. Updated token 5. Actions 1. Created action 2. Deleted action 3. Updated action 6. Image Creator 1. Launched private image build 2. Deleted private image 3. Updated private image 7. File bundles 1. Created file bundle 2. Deleted file bundle 3. Updated file bundle 8. Login/Logout 1. User login 2. User logout 9. minicli\ The performer listed for minicli events is the token used to authenticate the session. 1. Launched build via minicli (Logged for the command `minicli image build submit`) 2. Deleted private image via minicli 3. Saved private image via minicli (Logged for the command `minicli image apply`) ## Audit logs Audit logs list events related to Minimus supply chain policies. The data can be filtered by the following: * Date * Event type (supply chain policy alert or block) * Entity (policy name) * Resource (package that triggered the policy and the image). Expand any row to see additional details including the policy violation. Supply Chain Policy Audit Logs # Sync with Hauler for Air-Gapped Kubernetes Source: https://docs.minimus.io/manage/hauler-airgap Use Hauler to pull Minimus images into an air-gapped Kubernetes cluster, and avoid a known image-export defect This guide walks through pulling Minimus container images into an air-gapped Kubernetes cluster using [Hauler](https://hauler.dev). Hauler is commonly used to mirror images (and their attached artifacts) from a connected registry into an air-gapped one. Testing is recommended before running this in production. Minimus images are signed with [Cosign](https://github.com/sigstore/cosign) and published with attached signature and SBOM artifacts alongside the image itself (`sha256-.sig` and `sha256-.sbom` tags). This is standard Cosign tag-based discovery and is how most signed-image registries operate. However, because Minimus images carry these extra signed artifacts they are sensitive to Hauler's export method, as explained below. ## Prerequisites * Network access from a "jump" or "transfer" host to `reg.mini.dev` (or your Minimus registry endpoint) * If the image is part of a private/subscription set, a valid Minimus [pull token](/manage/network) for that transfer host to authenticate to the registry (standard Minimus images can be pulled anonymously) * Hauler **v2.0.3 or later** installed on that transfer host (`hauler version` to check) * A way to move the resulting Hauler store/bundle into the air-gapped environment (removable media, one-way transfer proxy, etc.) * `containerd`/`ctr` or registry access on the air-gapped side, depending on which import method you use (see [Import into the air-gapped cluster](#import-into-the-air-gapped-cluster)) **Before you start: version requirement** To avoid a container startup failure, use **Hauler v2.0.3 or later**, and pass **`--exclude-extras`** to `hauler store sync`. For a detailed explanation, see the [known issue](#known-issue-images-fail-with-no-command-specified) below, and steps for [verifying the fix](#verifying-the-fix) to confirm your setup is not affected. ## Building the manifest and syncing images ### Write a Hauler manifest Create a `hauler-manifest.yaml` listing the Minimus images you need. For Hauler v2, the manifest must use the v2 API version: ```yaml hauler-manifest.yaml theme={null} apiVersion: content.hauler.cattle.io/v1 kind: Images metadata: name: minimus-images spec: images: - name: reg.mini.dev/postgres:v16.14 ``` Hauler v1's `v1alpha1` manifests are **silently skipped** by Hauler v2 — you will get no error, but nothing will be synced. If you are upgrading an existing manifest from Hauler 1.x, update the `apiVersion` field or your sync will silently fail. ### Pin to an immutable reference (recommended) Minimus rebuilds tags regularly, so note that the tag is mutable. For a reproducible air-gap bundle, pin to either: * Image digest (`reg.mini.dev/postgres@sha256:`) * Minimus timestamp tag (e.g. `reg.mini.dev/postgres:18.6-202608130124`) [Learn more](/foundations/daily-updates#unique-timestamp-tag) ### Sync the store ```bash theme={null} hauler store sync --files hauler-manifest.yaml --exclude-extras ``` The `--exclude-extras` flag tells Hauler to skip pulling the cosign `.sig`/`.sbom` artifacts into the store. This flag is required. ## Import into the air-gapped cluster You have two supported paths. Prefer Option A when possible. ### Option A — `hauler store serve registry` (recommended, safest even with extras) Move the resulting store/bundle to the air-gapped node. ```bash theme={null} hauler store load .tar.zst ``` ```bash theme={null} hauler store serve registry ``` For example, for RKE2, add a `registries.yaml` mirror entry targeting the address `hauler store serve registry` is listening on. This approach resolves tags correctly (the served registry keeps signatures and SBOMs under their own `sha256-*.sig` / `.sbom` tags rather than colliding with the image tag), so it works even if `--exclude-extras` was not used during sync. ### Option B — `ctr images import` Move the store/bundle to the air-gapped node. ```bash theme={null} hauler store save --filename bundle.tar ``` ```bash theme={null} ctr -n k8s.io images import --no-unpack bundle.tar ``` This path is only safe if the store was synced with the flag `--exclude-extras` (see [Known issue](#known-issue-images-fail-with-no-command-specified)). Without it, the imported tag can silently point at the wrong artifact. ## Known issue: images fail with "no command specified" **Symptom:** A pod using a Minimus image fails to start with kubelet events such as: ```bash wrap theme={null} Warning Failed ... Error: failed to generate container spec: failed to apply OCI options: no command specified ``` Inspecting the image config on the air-gapped node shows an empty `Entrypoint`/`Cmd`, even though the same tag has the correct entrypoint in the source registry. **Root cause:** This is a Hauler export defect, not a problem with the Minimus image. When Hauler exports an OCI layout, it labels the Cosign signature and SBOM artifacts with the same `io.containerd.image.name` annotation as the image itself. `ctr images import` binds a tag on a "last-entry-wins" basis, so if the SBOM or signature artifact is written last in the index, the local tag ends up pointing at that artifact — which has an empty config (`{"config":{}}`) — instead of the actual image manifest. As a result, Kubelet has no `Entrypoint`/`Cmd` to build a container spec from, and the pod fails every time it's created. A related symptom (mismatched image rootfs and manifest layers on `ctr images import`, without `--no-unpack`) has the same root cause: the SBOM's "layer" is an SPDX JSON document, not an actual filesystem layer, so unpacking it fails. **Fix:** Use Hauler **≥ v2.0.3** and pass **`--exclude-extras`** to `hauler store sync`. Note that simply upgrading Hauler's version without adding the flag does not fix the issue. Alternatively, use the `hauler store serve registry` workflow described in Option A above, which works correctly without the additional flag. **Non-Hauler alternatives:** Tools like `crane copy` or `skopeo copy` copy only the image itself, not the attached signature/SBOM artifacts, so they are not affected by this issue. ## Verifying the fix After importing on the air-gapped node, confirm the entrypoint survived the transfer before deploying workloads against it: ```bash wrap theme={null} ctr -n k8s.io images ls | grep postgres # confirm the tag is present ctr -n k8s.io content ls # sanity check content store crictl inspecti reg.mini.dev/postgres:v16.14 | grep -A3 Entrypoint ``` You should see the original `Entrypoint`/`Cmd` from the source image (e.g. `/usr/bin/docker-entrypoint.sh postgres`), not an empty array. ## Do not remove signatures/SBOMs to work around this It may be tempting to ask for an unsigned "air-gap tag" without attached artifacts but this is not recommended. `--exclude-extras` (or `crane copy`/`skopeo copy`) already produces exactly that from the existing tag on demand, without requiring Minimus to stop publishing signatures and SBOMs, which would remove supply-chain verification for every other consumer of the image. If you hit this issue, fix the Hauler workflow. ## References * [Hauler documentation](https://hauler.dev) * Hauler `--exclude-extras` flag: [hauler-dev/hauler#541](https://github.com/hauler-dev/hauler/issues/541) # Install minicli Source: https://docs.minimus.io/manage/minicli Install the Minimus command-line tool to manage Image Creator as code and more The Minimus command-line tool **minicli** allows you to embed your custom-built Minimus images in your CI/CD workflows. To begin, you will need to install minicli locally on your workstation. To view the minicli installation page, select **Manage > minicli** ([direct link](https://images.minimus.io/manage/minicli)). * minicli can be installed on macOS or Linux systems. * Both amd64 and arm64 are supported. * Choose between direct installation via `curl`, `wget`, or downloading the file and running it locally. * The relevant installation commands are provided directly in the minicli page ([direct link](https://images.minimus.io/manage/minicli)). ## Authenticate to minicli Generate a token from the [**tokens** page](/manage/token) in the Minimus console and give it minicli access. Then authenticate using one of the following methods: **Option 1 — environment variable** (recommended for CI/CD): ```bash theme={null} export MINICLI_TOKEN={token} ``` **Option 2 — login command** (recommended for local use): ```shellscript theme={null} echo "{token}" | minicli login ``` All commands require `MINICLI_TOKEN` to be set. If the token is missing, minicli returns an error: ```text wrap theme={null} Error: Authentication token not found. Please export your token: export MINICLI_TOKEN={token}. ``` ## Working with minicli Once you have minicli installed and authenticated, you can equip your AI agent with minicli skills and get started. See [minicli commands](/enterprise-edition/minicli) ## Troubleshooting ### Apple could not verify "minicli" is free of malware Minimus is in the process of obtaining Apple developer verification. In the meanwhile, the browser download may attach a hidden quarantine flag that triggers a warning that minicli could not be verified if other commands are performed pre-installation. Macos minicli not verified warning **To fix the problem**: Download the minicli installation package and follow the instructions on the minicli installation page in the Minimus console ([direct link](https://images.minimus.io/manage/minicli)) without running any other commands in between. For example, avoid `chmod +x`. # Sync with Google Artifact Registry Source: https://docs.minimus.io/manage/mirror-to-gcp-artifact-registry Set up pull through to mirror Minimus images to Google Artifact Registry If your organization uses the Google Artifact Registry as the source of truth, you can set up a pull-through cache for your Minimus container images. This option allows you to benefit from the Minimus security advantage while keeping your current processes. Refer to Google Cloud's Artifact Registry guide for [remote repositories](https://docs.cloud.google.com/artifact-registry/docs/repositories/remote-overview) for further information. ## Prerequisites 1. Google Cloud project access: * Permissions to access and create registries in Artifact Registry * Permissions to create secrets in Google Secret Manager  * [Artifact Registry API](https://docs.cloud.google.com/artifact-registry/docs/reference/rest) must be enabled in your Google project 2. Access to Docker or Podman to execute an image pull. This may be done locally or within a Google Cloud Shell. ## Set up a remote repository in Google Cloud In this step, we will set up the Minimus registry as a remote repository in the Google Cloud Artifact Registry to enable pull through. Save your Minimus token to the Google Secret Manager. 1. Visit the Google Artifact Registry Secret Manager ([direct link](https://console.cloud.google.com/security/secret-manager)).  2. Select **+ Create secret** (top banner): GCP Create Secret 3. Fill in the form: 1. **Name** your secret, for example, `minimus-image-pull-token-secret`. 2. **Secret Value:** Paste your Minimus token as the value.  3. Configure the rest of the options, including encryption and rotation periods. You can keep the defaults but we recommend that you align with your organizational policies. 4. Select **Create Secret** to confirm and save the secret. GCP Save Token As Secret Now that the Minimus token is saved in the Google Secret Manager, you are ready to configure Minimus as a remote repository. 1. Visit the [Google Artifact Registry landing page](https://console.cloud.google.com/artifacts) 2. Select **+ Create repository** (top banner): Create Repository 3. Fill in the form: 1. **Name** the repository, for example, `reg-mini-dev-remote`. 2. **Format**: Select **Docker** as the format. 3. **Mode**: Select **Remote** from the available options. 4. **Remote repository source**: Select **Custom**. 5. Type in `https://reg.mini.dev` as the custom repository URL. Create Repository Configs 1. Still in the same form, under the section **Remote repository authentication mode**, select **Authenticated**. 2. Fill out the form: 1. **Username for the upstream registry**: Enter the username `minimus` 2. **Secret**: Select the name of the secret created in the previous step.  3. **Location type**: Select **Region** 4. Select the region from the list. 5. Configure the rest of the options, including encryption, cleanup policies, artifact analysis, etc. You can keep the defaults but we recommend that you align with your organizational policies. GCP Repo Region Select **Create** at the bottom of the form. If successful, a success message will appear and you will be able to view the remote repository details. ## Pulling Minimus images into Artifact Registry Now that you've set up the Minimus registry as a remote repository, you are ready to pull Minimus images into your Google Cloud Artifact Registry. You can either trigger image pulls locally or via Google cloud shell with relative docker access to the Google registry. For purposes of this guide we will show how to use Google Cloud Shell from the Google Cloud Console. 1. Authenticate to Google Cloud Shell from your Google Console. You should see a welcome message such as `Welcome to Cloud Shell!...`. Welcome Google Cloud Shell 2. Validate that Docker access is configured locally: ```shellscript Command template theme={null} #command format gcloud auth configure-docker {your-region} #example gcloud auth configure-docker us-central1-docker.pkg.dev ``` Image5 3. Execute a Docker or Podman pull command: ```shellscript Docker Pull Command wrap theme={null} #docker command format docker pull {your registry region}/{google-project-id}/{remote-repository-name}/{desired-minimus-image} #example docker pull us-central1-docker.pkg.dev/acme-project/reg-mini-dev-remote/python:latest ``` ```shellscript Podman Pull Command theme={null} #podman command format podman pull {your registry region}/{google-project-id}/{remote-repository-name}/{desired-minimus-image} #example podman pull us-central1-docker.pkg.dev/acme-project/reg-mini-dev-remote/python:latest ``` Image10 4. That's it! You have validated that you can pull Minimus images into your Google Cloud Artifact Registry. # Network Requirements Source: https://docs.minimus.io/manage/network Firewall rules, DNS endpoints, and port requirements for connecting to the Minimus registry and console Your firewall must allow access to the endpoints listed below. Without these rules configured, your systems cannot authenticate with the Minimus registry or pull images. ## Connectivity requirements ### Outbound traffic You'll need to open your firewall to allow outbound traffic to the Minimus gallery and registry. These are the requirements: | | DNS Names | Ports | Protocols | | :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---- | :-------- | | Minimus Console | [https://images.minimus.io/](https://images.minimus.io/) | 443 | TCP | | Minimus registry | reg.mini.dev | 443 | TCP | | Alternate registry address (for pulling image layers) | [https://us-east1-docker.pkg.dev/artifacts-downloads/namespaces/prod-375107/repositories/minimus/](https://us-east1-docker.pkg.dev/artifacts-downloads/namespaces/prod-375107/repositories/minimus/downloads/AI3WYFbL2K4e0BSPS73oTNOg1) | 443 | TCP | | Authentication service | [auth.mini.dev](http://auth.mini.dev) | 443 | TCP | | Google Artifact Registry | \*.pkg.dev | 443 | TCP | ### Inbound traffic If you are using Minimus [actions](/remediate/actions), you'll need to open your firewall to allow inbound traffic from the following IP addresses: * 34.139.95.89 * 34.74.18.163 * 34.73.139.186 The TCP port will depend on your webhook, for example: 443/TCP. ### Pull token Pulling images from the Minimus registry requires authentication with a valid pull token. [Learn more](/enterprise-edition/authentication) ## Supported regions Minimus is hosted on GCP us-east1 (South Carolina). [About Google Cloud regions](https://cloud.google.com/compute/docs/regions-zones). ## Sync to self-hosted registry If you want your teams to continue pulling images from your private, self-hosted registry, this can be done. Set up the sync service between Minimus and your private registry to give your team access to the latest updates without leaving your private registry and without changing internal processes. [Learn more](/manage/self-hosted-registry) ## IP Addresses Used Minimus uses Google Cloud as our cloud provider, which may allocate IPs dynamically for the Google APIs and Services. Customers who need to track the IPs used by Google services can leverage the scripts provided by Google in the [Google Cloud Platform Documentation](https://cloud.google.com/vpc/docs/access-apis-external-ip?utm_source=chatgpt.com#ip-addr-defaults). # Sync to Self-hosted Private Registry Source: https://docs.minimus.io/manage/self-hosted-registry Sync your Minimus images to your self-hosted private registry using the Minimus service If your organization hosts a private registry as a source of truth, you can set up a pull-through cache for your Minimus container images. This option allows you to benefit from the Minimus security advantage while keeping your current processes. Setting up the Minimus sync service may be required if you already have a private registry (either connected to the Web or air-gapped), or if your team is required to store container images in a private registry to meet regulatory requirements. To view the service configuration page, select **Manage > Self-hosting** ([direct link](https://images.minimus.io/manage/self-hosting)). Minimus Self Hosting ## Which images are synced by default The service will sync all Minimus images included in your subscription. For every image type (for example, Node, Python, etc.), all image versions available from Minimus will be synced. ## Online vs. air-gapped The process supports syncing to any private registry, whether it is connected to the Web or air-gapped. Below is a brief comparison of the processes depending on registry connectivity. ### Online registry syncs automatically If your private registry is online and supports external connections, the sync service can be fully automated using a scheduled cron job. * Review the Minimus [networking requirements](/manage/network) to ensure your firewall is configured correctly. * Once you set up the service, it will run automatically and keep your private registry up to date. ### Sync to air-gapped registry is partially automated If your registry is air-gapped (aka offline), the sync service can be partially automated using a scheduled cron job. A manual step will be needed to connect to the air-gapped registry and upload the images. See more details below. ### Comparison summary | Registry Connectivity | External Connectivity | Automation | Frequency | Time investment | | --------------------- | --------------------- | :-------------------------------------------- | :----------------------------------- | :------------------------------ | | Online registry | Supported | Fully supported using cron job scheduling | Daily using cron job scheduling | One time set up | | Air-gapped registry | Not supported | Partially supported using cron job scheduling | Varies (depends on the organization) | Repeated manual effort involved | ## Tracking image updates You can set up [actions](/remediate/actions) to receive important security updates. This is particularly recommended if your team pulls images from a private registry, and are less likely to follow updates in the Minimus gallery. We recommend that you continue to visit the Minimus gallery regularly to receive updates and helpful information about image versions, advisories, and vulnerability fixes. ## Set up syncing to an online private registry Before you begin, install Skopeo on the target host. **Skopeo version 1.12 or higher is required.** [Installation instructions](https://github.com/containers/skopeo/blob/main/install.md) 1. From the left menu, select **Manage > Self-hosting**. (Or use this [direct link](https://images.minimus.io/manage/self-hosting).) 2. Select the tab: **Registry with internet connectivity**. A form with 3 parts will appear: 1. Destination details 2. Sync images 3. Set up automation 1. Specify your **registry URL.** 2. How will you authenticate to the registry? Decide between **username & password** and an **authentication file path**. 1. If you selected **username & password**, provide them. 2. If you selected an **authentication file path**, select the relevant option: 1. **Default file path**. Select this option if the path matches one of the defaults:\ `${XDG_RUNTIME_DIR}/containers/auth.json`\ `$HOME/.docker/config.json` 2. **Other file path**. Select this option and provide the path. 3. Select the relevant **image architecture**: amd64, arm64, or both. 4. Select **Next** to continue. 1. Download the provided YAML file and save it on a machine where Skopeo is installed. 2. (Optional) Specify the path to the YAML file to update the placeholder in the code snippet below. 3. Copy the provided code snippet and run it on your target host. Example command: ```bash theme={null} skopeo sync --src yaml --dest docker \ --override-arch amd64 \ {PATH TO YAML} \ https://registry.minime.com ``` 4. The first time sync should now be done. Your private registry should have copies of all of the images included in your Minimus subscription. 5. Click **Next** to set up automation. This step is recommended but not strictly required. 1. Open the crontab file on the target host to edit it: ```bash theme={null} crontab -e ``` 2. Add the provided cron job entry to run the command every day at midnight. For example: ```bash theme={null} 0 0 * * * skopeo sync --src yaml --dest docker --override-arch amd64 {REPLACE WITH PATH TO YAML} https://registry.minime.com ``` Your private registry should now sync on a regular schedule and receive Minimus image updates and releases. ## Set up syncing for an air-gapped private registry Before you begin, install Skopeo on your internet-connected machine and the target host in your air-gapped environment. **Skopeo version 1.12 or higher is required.** [Installation instructions](https://github.com/containers/skopeo/blob/main/install.md) 1. From the left menu, select **Manage > Self-hosting**. (Or use this [direct link](https://images.minimus.io/manage/self-hosting).) 2. Select the tab: **Air-gapped registry (no internet)**. A form with 3 parts will appear: 1. Destination details 2. Sync images 3. Set up automation 1. Specify the path to your **Removable drive**. The process assumes you will use a removable drive to store the images temporarily. 2. **Air-gapped registry details** - Specify the details for Minimus to configure the Skopeo commands for you. Otherwise, you can toggle off this option to skip this step and configure the Skopeo commands independently. 1. **Air-gapped registry URL** - Specify the URL for the destination registry. 2. How will you authenticate to the registry? Decide between **username & password** and an **authentication file path**. 1. If you selected **username & password**, provide them. 2. If you selected an **authentication file path**, select the relevant option: 1. **Default file path**. Select this option if the path matches one of the defaults:\ `${XDG_RUNTIME_DIR}/containers/auth.json`\ `$HOME/.docker/config.json` 2. **Other file path**. Select this option and provide the path. 3. Select the relevant **image architecture**: amd64, arm64, or both. 4. Select **Next** to continue. 1. Download the provided YAML file and save it on a machine where Skopeo is installed. Connect the removable drive to the machine. 2. (Optional) Specify the path to the YAML file to update the placeholder in the code snippet below. 3. Copy the provided code snippet and run it on your target host. Example command: ```bash theme={null} skopeo sync --src yaml --dest dir \ --override-arch amd64 \ {PATH TO YAML} \ {PATH TO REMOVABLE DRIVE} ``` 4. The images should now be on the removable drive, waiting to be transferred to the air-gapped registry. 1. Move the removable drive to a machine in the air-gapped network. 2. Copy the provided code snippet and run it on the machine. The command will sync the images from the removable drive to your private registry. Example command: ```bash theme={null} skopeo sync --src dir --dest docker \ {PATH TO REMOVABLE DRIVE} \ {URL TO PRIVATE REGISTRY} ``` 3. The images should now be synced to your air-gapped registry. 4. Click **Next** to set up automation. This step is recommended but not required. It can automate the sync to a storage directory on your internet-connected machine. The sync from the removable disk remains manual. 1. Open the crontab file on the host to edit it: ```bash theme={null} crontab -e ``` 2. Add the provided cron job entry to run the command every day at midnight. For example: ```bash theme={null} 0 0 * * * skopeo sync --src yaml --dest dir --override-arch amd64 {PATH TO YAML FILE} {PATH TO REMOVABLE DRIVE} ``` Minimus image versions and updates should now sync on a regular schedule to a storage directory, ready to be moved to your private air-gapped registry. Repeat the above steps to move the images to your removable drive and copy them to your registry. This step is manual and cannot be automated. # Sync with JFrog Artifactory Source: https://docs.minimus.io/manage/sync-with-jfrog-artifactory Set up pull through to mirror Minimus images to JFrog Artifactory If your organization uses the JFrog Artifactory as the source of truth, you can set up a pull-through cache for your Minimus container images. This option allows you to benefit from the Minimus security advantage while keeping your current processes. Refer to JFrog's Artifactory guide for [remote repositories](https://jfrog.com/help/r/jfrog-artifactory-documentation/configure-a-remote-repository) for further information. ## Prerequisites 1. JFrog Artifactory administrative privileges with an Artifactory instance 2. Access to Docker or Podman to execute an image pull. This may be done locally or from a virtual machine that has a routable network path to your Artifactory instance. ## Set up a remote repository in Artifactory In this step, we will set up the Minimus registry as a remote repository in JFrog Artifactory to enable pull through. 1. Log into your JFrog Artifactory console.  2. Navigate to **Administration > Repositories** (The URL will look like this `https://***.jfrog.io/ui/admin/repositories` ). 3. Select **Create a Repository > Remote**. Create Repo 4. Select **Docker**. Select Docker 5. Fill in the form: 1. **Repository Key**: Name your remote-repository, for example, `remote-minimus-registry`. 2. **URL**: Type in `https://reg.mini.dev`. 3. **User Name**: Type in `minimus` (The username for authenticating to the Minimus registry) 4. **Password / Access Token**: Paste your Minimus token as the value. (You can use this [direct link](https://images.minimus.io/manage/tokens) to fetch your Minimus token). 5. For all other fields, you can keep the defaults but we recommend that you align with your organizational policies. 6. Click **Create Remote Repository** to complete the form.  Configure Remote Repository 7. You should see the following success window. Select the option **Set Up Docker Client** to continue.  Set Up Docker Client ## Pulling Minimus images into Artifactory Now that you've set up the Minimus registry as a remote repository in Artifactory, you are ready to pull Minimus images into your JFrog Artifactory instance. 1. If you didn't select **Set Up Docker Client** in the previous step, you can navigate to it directly: 1. Select **Repositories** from the left menu. 2. Hover over your repository, click the right menu (3 dots), and select **Set Me Up**. Set Me Up 2. Authenticate to the remote registry. 1. Enter your Artifactory tenant password. 2. Select **Generate Token & Create Instructions**. Set Up Docker Client 2 3. The instructions and commands will be provided in the JFrog UI.  Authenticate Remote Repository 4. In your CLI, log in to your JFrog instance, for example:  ```shellscript theme={null} docker login example123456789.jfrog.io Username: example@minimus.io Password: WARNING! Your credentials are stored unencrypted in '/home/example/.docker/config.json'. Configure a credential helper to remove this warning. See https://docs.docker.com/go/credential-store/ Login Succeeded ``` 5. Execute a Docker or Podman pull command: ```shellscript Docker Pull Command theme={null} #docker command format docker pull {your artifactory instance}/{remote repository name}/{IMAGE}:{TAG} #example docker pull example123456789.jfrog.io/remote-minimus-registry/python:latest ``` ```shellscript Podman Pull Command theme={null} #podman command format podman pull {your artifactory instance}/{remote repository name}/{IMAGE}:{TAG} #example podman pull example123456789.jfrog.io/remote-minimus-registry/python:latest ``` 6. That's it! You have validated that you can pull a Minimus image into your JFrog Artifactory repository. ## Troubleshooting ### Artifactory remote repository sync When setting up a self-hosted registry with JFrog Artifactory, you may encounter a 401 or 403 error response when testing the connection in the Artifactory UI. **Explanation**: This is a known UI issue reported by JFrog and it can be safely ignored. The sync functionality will work correctly, and you will be able to pull images from the Minimus registry into your own registry without any problems. [Refer to the original report by JFrog for more details](https://jfrog.com/help/r/artifactory-what-it-looks-like-a-ghcr-io-repository-in-artifactory/artifactory-what-it-looks-like-a-ghcr.io-repository-in-artifactory) # Managing Tokens Source: https://docs.minimus.io/manage/token Manage your tokens to authenticate to the Minimus Registry and pull Minimus images and/or packages An active token is required to pull and verify images from the Minimus registry. Visit the [tokens page](https://images.minimus.io/manage/tokens) in the Minimus console to manage your Minimus tokens. You have extensive control over your account's tokens to: * Create and revoke registry tokens as needed, up to a maximum of 100 tokens * Set token expiration * Set token scope ## Token scope A Minimus token can unlock access to several Minimus services, depending on your needs: * **Image access** (default) - Pull Minimus secure images from the Minimus registry with Enterprise Edition commitments. * **Package access** - Install packages built by MinimOS in Minimus images for a comprehensive build experience. [Learn more](/basics/package-manager-access) * **minicli access** - Use the Minimus CLI to embed Minimus in your CI/CD processes. Currently minicli is used to manage Minimus Creator and private images with more capabilities to follow. [Learn more](/basics/package-manager-access) ### Restricting minicli access Tokens with minicli scope are hidden from Viewers by default, giving admins control over who can connect via minicli. To restrict access, create a dedicated token with minicli scope — it will only be visible to admins and editors. The default token is an exception: it remains visible to all users, including Viewers. Minimus Token Scope ## Managing tokens ### Default token A default token is automatically generated when you sign up for Minimus. You can edit its expiration date, name it, and add a description. ### Creating a token When creating a token: 1. Provide its name and description to help you keep track of its purpose. The description is optional. 2. Set the token scope: image access, package access, minicli access. 3. Set the expiration date using the calendar date picker. Leave empty for no expiration (lifetime validity). ### Editing a token All fields can be edited for an existing token. ### Token expiration Control your token expiration dates or set your tokens to never expire - the choice is fully yours. A calendar date picker makes the configuration simple and quick. * If an expiration date is not selected, the token will not expire. In other words, it will remain active for the duration of your membership. * You can extend the lifetime of an already expired token to reactivate it. ## Token list Your tokens are listed in collapsed cards. * In collapsed mode, the token card shows the token name, description, and creation and expiration dates. Token scope is indicated by the colorful badges.\\ Token Scope Badges * Expand the token card to view the token itself and useful authentication commands for different common use-cases.\\ Token Display ## Authenticating with your token Expand your token card to view the token and copy the provided authentication commands: * Docker login * Create K8s secret * Package access * minicli login [Learn more about Minimus authentication](/enterprise-edition/authentication) # User Groups Source: https://docs.minimus.io/manage/user-groups Configure SAML group-based role assignments in Minimus for Azure, Okta, Google, and other identity providers Add groups to control role-based access for SAML users (users who sign in with SSO). Groups are supported for Azure, Okta, Google and more. ## Overview The process is simple: 1. In the Minimus console, configure SSO and enable SAML. [Learn more](/sso/saml) Make sure to configure the **groups mapping attribute** in the Minimus SAML form. 2. In your identity provider, assign the relevant groups to the Minimus application. [See the Okta example](https://docs.minimus.io/sso/okta#assign-access-in-okta) 3. In the Minimus console, add the groups and set their role. [Learn about user roles](/manage/user-roles) That's it. Permissions will automatically take effect the next time group members log into Minimus. ## Add groups (Okta, Google, other) SSO must be configured and enabled before you can manage groups in Minimus. 1. In the Minimus SAML form ([direct link](https://images.minimus.io/manage/access/users?saml=open)): 1. Enable **Step 4: Group Mapping**. 2. Keep the default selection: **Google / Okta / Other** 3. Enter the group mapping: `groups` 2. Next, go to **Manage > Users & Groups** ([direct link](https://images.minimus.io/manage/access/groups)). 3. Click **Add Group** (top right). 4. Fill in the form: 1. Specify the **group name** (or group ID) as listed in the identity provider. 2. The provider will be set to SAML. This setting is hardcoded. 3. Select the **role**: viewer, operator, admin. [Comparison of roles](/manage/user-roles) 1. **Viewer** is the default role. If no role is assigned, viewer will be automatically assigned. 2. **Operator** role. 3. **Admin** role. 5. Save your changes. Changes will apply the next time a group member logs in with SSO. Add Group ## Configure Azure groups There are 2 different ways to map Azure groups to Minimus. The Minimus SAML form is configured differently for each. ### Azure group names 1. Open the Minimus SAML form ([direct link](https://images.minimus.io/manage/access/users?saml=open)): 1. Enable **Step 4: Group Mapping**. 2. Select: **Azure** 3. Fill out the following Azure parameters: * **Application ID** (also shown as **Application (client) ID** depending on where you look it up in Azure) * **Client Secret** Minimus Form Azure Groups 2. In Azure, look up your Azure groups. You can search for "groups" in the top searchbar. Azure Group Names 3. In the Minimus Groups form ([direct link](https://images.minimus.io/manage/access/groups)), add the groups by group name. ### Azure group IDs 1. Open the Minimus SAML form ([direct link](https://images.minimus.io/manage/access/users?saml=open)): 1. Enable **Step 4: Group Mapping**. 2. Keep the default selection: **Google / Okta / Other** 3. Enter the Azure group mapping: ```shellscript theme={null} http://schemas.xmlsoap.org/ws/2008/06/identity/claims/groups ``` Azure Groups Enabled 2. In Azure, look up your Azure groups. You can search for "groups" in the top searchbar. Azure Groups Ids 3. In the Minimus Groups form ([direct link](https://images.minimus.io/manage/access/groups)), add the groups by Azure group ID. Azure Group Ids # User Roles Source: https://docs.minimus.io/manage/user-roles Roles define and manage user access permissions for Minimus users Roles are used to control user access permissions. The following table shows a comparison of Minimus user roles. | **Feature** | **Viewer** | **Operator** | **Admin** | | :--------------------------------------------------- | :--------- | :----------- | :-------- | | [Image Gallery](/gallery) | ✅ | ✅ | ✅ | | [Image Creator](/enterprise-edition/image-creator) | RO | RW | RW | | [Supply Chain](/enterprise-edition/supply-chain) | ⛔ | ✅ | ✅ | | [Actions](/remediate/actions) | RO | RW | RW | | [Self-hosted Registry](/manage/self-hosted-registry) | ⛔ | ✅ | ✅ | | [User Management](/manage/users) + [SAML](/sso/saml) | ⛔ | ⛔ | RW | | [Token Management](/manage/token) | RO | RW | RW | | [Helm Charts](/foundations/helm-charts) | ✅ | ✅ | ✅ | | [Activity Logs](/manage/activity-log) | ⛔ | ⛔ | ✅ | | [Audit Logs](/manage/activity-log#audit-logs) | ⛔ | ✅ | ✅ | * RO stands for Read-only * RW stands for Read and Write ## Highest role "wins" If a SAML user belongs to multiple groups with competing roles, Minimus will assign the highest available role. The calculation is done at runtime. Assigning the highest role provides a clear and predictable method for resolving overlapping permissions. This approach prevents accidental loss of required access and avoids ambiguity. It also simplifies permission evaluation and makes access configurations easier for administrators and users to understand. ## New group assignment Group membership cannot reduce a user’s permissions. You can be confident that adding an existing SAML user to another group will not unintentionally reduce their role. ## SAML user role Typically, SAML user roles are managed via groups. However, you have the option to elevate a specific user's role independently of any group. [Instructions](/manage/users#elevate-user-role) ## Troubleshooting SAML user permissions 1. In case of recent SAML changes, ask the user to log out then log back in. SAML changes only take effect when the user logs in. SSO Sign In 2. Make sure the group is correctly configured in the Minimus SAML form. [Learn more](/sso/okta) Configure SAML Groups 3. Check for a SAML user role override in the users page. [Learn more](/manage/users#elevate-user-role) SAML User Rule Override # User Management Source: https://docs.minimus.io/manage/users Add, remove, and manage team members and their roles in the Minimus console using GitHub, Google, Microsoft, or SAML Add users to invite team members to join you in Minimus. When you add users, you will decide how you want them to authenticate: by GitHub, Google, Microsoft, or SAML (Single-Sign On, SSO). ## Users table The users table includes the following information: * Users that have active accounts will appear as **active**. * Users that have been invited to join the platform will appear as **pending login**. Note the identity provider for every user account is listed. It may be Google, GitHub, Microsoft, or SAML. ## Non-SAML users ### Add users You can add as many users as you like. There are no limits on the number of seats. 1. Click **add user** (top right). 2. Select the identity provider: Google, GitHub, or Microsoft. 3. Add the Google email address, GitHub username, or Microsoft email address, as appropriate. 4. Select the role: viewer, operator, or admin. 5. Send a message to the invited user to let them know they've been invited. \ The new user will show as **pending login** until they log in for the first time. If a user is set to log in with a specific identity provider (Google, GitHub, or Microsoft), they cannot log in using a different provider. When using Microsoft authentication, the end user may need to request admin approval from their organization before they can access Minimus. ### Delete & remove users You can delete non-SAML users. This will revoke their access to your Minimus account. ## SAML users ### Add users You can add as many users as you like. There are no limits on the number of seats. SAML users are managed directly in your identity provider. ### Elevate user role You can elevate the role of a single SAML user account directly in Minimus, independently of their group assignments. 1. Click **add user** (top right). 2. Select the identity provider: SAML. 3. Select the role: viewer, operator, or admin. Minimus automatically assigns every user the highest privileges assigned to them. For example, if the user belongs to a group with viewer role but is also added as an admin user directly in Minimus, they will log in as Minimus admins. ### Delete & remove users SAML users log in with SSO. You must remove access privileges directly in the identity provider as they are controlled by the external SAML provider. You can clean up outdated SAML users from the users table in Minimus to remove obsolete accounts. This action does not impact access. # What's New Source: https://docs.minimus.io/release-notes Stay in the know about recent Minimus releases and updates ## August 9, 2026 ## Set up AI Integrations once for your whole organization The new Global tab on the AI Integrations page installs the Minimus rules once so every repo picks them up — no per-repo files to add. Choose organization scope to roll the rules out to every developer through managed settings, or machine scope to apply them to every repo you open locally. New repositories are covered automatically, and Claude Code, Cursor, and OpenAI Codex are all supported. ## See which versions failed the cooling-off period Supply chain policy alerts and blocks in the Audit Log now show exactly which package versions didn't meet the cooling-off period. [Learn more](/manage/activity-log#audit-logs) ## Clearer reasons when a package install is blocked Supply chain violation messages have been extended to explain which guardrail was triggered and why. Currently supported for npm. [Learn more](/enterprise-edition/supply-chain) ## August 2, 2026 ## Track vulnerabilities still under review Vulnerabilities awaiting analysis by the Minimus security team are now grouped separately in the version vulnerabilities report, so they're never mixed in with confirmed findings. An indication also appears at the top level of the vulnerability report summary. [Learn more](/foundations/image-version#vulnerabilities) ## Popularity threshold now based on monthly Minimus downloads The popularity control in supply chain policies moved from weekly downloads per package version to total monthly Minimus downloads across all versions, giving a more stable signal for vetting new packages. [Learn more](/enterprise-edition/supply-chain) * New and returning Enterprise Edition users are now asked to accept a license agreement before continuing their work. ## July 26, 2026 ## Risk reduction for Helm charts See how much risk a Minimus Helm chart removes. The new Risk Reduction tab compares the confirmed vulnerabilities across all images deployed by the Minimus chart against the equivalent public chart, broken down by severity. A daily comparison report quantifies the reduction so you can see the security benefit at a glance. [Browse the Helm chart gallery](https://images.minimus.io/?type=helmChart) ## More agents, more migrations AI Integrations now covers Cursor and OpenAI Codex alongside Claude Code, so more of your team's coding agents can build and migrate with secure Minimus images by default. Each agent can also migrate Helm charts and Kubernetes manifests, in addition to Dockerfiles. Add the rules to your repo so your agents follow them in every session. * Improved the Image Creator image cards so image names are easier to read. Previously, longer names could be truncated and hard to glance at; the refreshed card design fixes this. ## July 21, 2026 ## Run minicli without installing it locally minicli is now available as a container image, so you can run it directly without a local install. Mount a local directory to persist login credentials across runs, or pass a token at invocation for one-off use. Either way, it's ready to drop into a CI/CD pipeline. [Learn more](https://images.minimus.io/images/minicli) ## July 19, 2026 ## Python supply chain protection Protect your Python package installations against typosquatting risks and suspicious version releases, with a cooling-off period and popularity threshold for new releases. Python and Node libraries are currently supported with more planned. [Learn more](/enterprise-edition/supply-chain) ## Navigation improvements Share Minimus image URLs with style. Image URLs were updated to make them shorter and simpler and the default changed from the image versions to the image overview. For example, [https://images.minimus.io/gallery/images/openclaw/quick-start](https://images.minimus.io/gallery/images/openclaw/quick-start) moved to [https://images.minimus.io/images/openclaw](https://images.minimus.io/images/openclaw) ## Browse Minimus images on the go Mobile view improvements let you explore Minimus secure container images anytime, anywhere. Visit the Minimus image catalog at [https://images.minimus.io/images/](https://images.minimus.io/images/) and share it with your team to shift left and get started with best-in-class secure open source container images. * Improved Minimus Helm chart guides for simpler copy-paste deployment. The Helm install commands now include the exact chart version across all versions. * Removed AI migration tab from the image card, following its replacement by the new AI Integrations menu item. ## July 12, 2026 ## Agent native integration Give your AI coding agents native access to Minimus. Point them at our prompt to pull in secure images and Helm charts from day one. Enterprise Edition users can take the integration further with a permanent connection. ## Get notified when your private image is ready Get notified by email the moment your private image is ready in the gallery. Add teammates to keep your whole team in sync. [Learn more](/enterprise-edition/image-creator) ## Restrict access to minicli tokens Take control of who can connect via minicli. Tokens with minicli scope are now hidden from Viewers by default, with a simple path to restrict access further. Only the default token remains accessible to all users. [Learn more](/manage/token) * Removed obsolete package versions from the Image Creator viewer to protect against failed builds * Refined the display of private image cards and their tenant ID * Improved site performance and fixed issues impacting proper session termination ## July 08 2026 ## Helm chart version changes Minimus Helm charts have been migrated to track upstream chart versions. Charts that were previously versioned independently starting at 0.1.0 have been deprecated and will be removed over the coming weeks. [Browse the Helm chart gallery](https://images.minimus.io/?type=helmChart) ## June 23 2026 ## Enterprise Edition updates Minimus Enterprise Edition now includes full access to the Minimus image gallery right out of the box. Enjoy this new addition alongside all of the robust features you already rely on: Image Creator, minicli, Minimus actions, supply chain policies, logs, SSO, and more. [Browse the image gallery](https://images.minimus.io/) ## New! Minimus Community Edition is now available Minimus Community Edition gives developers access to the Minimus image gallery to drive security in production. Images come with daily builds, compliance reports, signed artifacts, and security advisories — everything your team needs to stay ahead of vulnerabilities, at no cost. [Get started](/gallery) ## Search images and Helm charts in one place The gallery search now covers both images and Helm charts to help you find what you need faster. [Browse the image gallery](https://images.minimus.io/) ## June 14 2026 ## Supply chain policy updates Supply chain policies can now be applied universally across any Minimus image to protect your npm environment without restrictions. As part of this update, the environment variable has been updated and the typosquatting control has been changed to a simple on/off toggle. [Learn more](/enterprise-edition/supply-chain) ## June 7 2026 ## Comply with the CIS MariaDB Benchmark Our new [MariaDB-Hardened image](https://images.minimus.io/images/mariadb-hardened/quick-start) complies with the app-specific [CIS benchmark](https://www.cisecurity.org/benchmark/mariadb), making it easier to deploy CIS compliant MariaDB clusters. ## Set up actions for Helm chart version updates Trigger webhooks, GitHub actions, or notifications in response to Helm chart version releases. The new action trigger will help you automate deployments and stay up to date. [Learn more](/remediate/create-action) ## Smarter Go dependency scanning Introduced better CPE matching for specific golang modules to correct for scanner false negatives. [Learn more](/remediate/advisories) ## STIG update Updated the Datastream XCCDF Checklist for GPOS (General Purpose Operating System) to v3r2p2 (patch 2). This includes updated Rule IDs and OVAL Definition IDs, and the addition of CCI codes (Control Correlation Identifiers). [Learn more](/compliance/stig) * Fixed a usability issue affecting date filters in the logs view * Improved site performance for an even smoother user experience ## May 31 2026 ## Manage private images as code with minicli **minicli** is the new Minimus CLI for defining, building, and managing private image configurations as code, directly from your terminal or CI/CD pipeline. It ships with built-in AI agent skills, so you can use tools like Cursor or Claude Code to manage your images with natural language. [Learn more](/enterprise-edition/minicli) ## Granular control over supply chain policies We've added granular policy controls to the Minimus supply chain, giving you finer-tuned guardrails over package installations. Configure individual thresholds for cooling-off periods, popularity, typosquatting risk, and suspicious version releases, and manage allow and block lists. [Learn more](/enterprise-edition/supply-chain) ## May 24 2026 ## Enhanced gallery search We've upgraded the image gallery search to support more complex and multi-term queries, giving you more precise results in fewer keystrokes. ## New default view for advisories We’ve reworked the **Affected Images** filter within advisories to give you more granular control. By default, the page now filters by **My Images** (your subscribed and private images). You can clear this filter to view advisories that are still under review or not yet linked to specific Minimus images, or adjust the selection to filter by all or specific images instead. [Learn more](/remediate/advisories) * Added backlink support for multi-license packages in the image SBOM * Fixed the backlinks in email notifications pointing to private images. ## May 10 2026 ## EOL managed: guard against end-of-life image pulls We've added a new action to trigger when EOL images are pulled from the Minimus registry. EOL actions are designed to help your team safeguard its operations against the use of unsupported image versions. [Learn more](/remediate/create-action) Fixed the backlinks in email notifications pointing to private images. ## April 23 2026 ## Generate a custom migration plan with AI We've added a complex prompt designed for use with local AI agents with terminal access, such as Cursor, Cline, Claude Desktop, and others. Run the prompt to generate a custom migration plan tailored to your existing Dockerfile to help swap out the existing base and runtime images with Minimus images. ## April 19 2026 ## Never miss an image update We've added a new action that triggers with every new image digest. Trigger webhooks, GitHub Actions, and notifications following any image update, whether a vulnerability fix, package update, configuration change, and more. Every change in the image [Changelog](/foundations/image-card#changelog) reflects a new image build with a new digest, so you can use the new action to stay on top of all image updates. [Learn more](/remediate/create-action) ## Comply with the CIS Apache Cassandra Benchmark Our new [Cassandra-Hardened image](https://images.minimus.io/images/cassandra-hardened/quick-start) complies with the app-specific [CIS benchmark](https://www.cisecurity.org/benchmark/apache_cassandra), making it easier to deploy CIS compliant Cassandra clusters. ## New Minimus Helm charts We've added new Helm charts to help you deploy Minimus secure images quickly and effortlessly, with many more charts expected soon. Look for the [Related Charts tab](/foundations/image-card#related-charts) in the image card to quickly identify relevant Helm charts available from Minimus. ## Quick reference package licenses View official SPDX package license documents directly from the [image SBOM](/foundations/image-version#sbom). We've added reference links to the license details to cut out extra steps. * Improved the certificate management page in Creator to address edge-cases. * Updated the package comparison display in the Risk Reduction report. ## April 12 2026 ## Advanced certificate management with Minimus Creator View certificate details directly in Creator and the associated File Management space. Certificate details include the Common Name (CN), organization, type, validity period, signature algorithm, SHA-256 fingerprint and more. The certificate validity status is clearly labeled to indicate whether it is valid, expired, or not yet valid. You can also download copies of your certificates directly from file bundles. ## Proactively replace deprecated image versions using Minimus Actions We've added new triggers to activate Minimus Actions when an image line is nearing or has reached EOL. The new EOL action triggers are part of a general effort to add support indications to Minimus, including EOL, near EOL, and LTS indications. EOL-related actions can be used to send out notifications over Slack or email or trigger GitHub Actions and webhooks. ## Get current vulnerability distribution information directly from Minimus Actions Minimus Actions now include vulnerability distribution information in notifications announcing new image versions and vulnerability fixes. The change currently includes GitHub Actions and webhooks, and will soon extend to email alerts and Slack notifications as well. * Added option to **View in GHSA** for advisories of vulnerabilities that have not yet been listed by NVD. * Consecutive file bundle updates now seamlessly trigger corresponding rebuilds of linked images, ensuring every change is reliably reflected in your private image. ## March 29 2026 ## Comply with the CIS NGINX Benchmark We've added a new NGINX-Hardened image to the list of Minimus Hardened Images. The new [NGINX-Hardened image](https://images.minimus.io/images/nginx-hardened/quick-start) complies with app-specific CIS benchmarks and is also offered as a FIPS-validated option - [NGINX-Hardened-FIPS image](https://images.minimus.io/images/nginx-hardened-fips/quick-start). ## View default ports in the image specification tab We've added a list of the default listening and exposed ports in the image version specification tab. [Learn more](/foundations/image-version#specification) ## March 22 2026 ## Plan version upgrades with Minimus support indications Don't let end-of-life announcements catch you by surprise. The Minimus console redesigned the display of EOL, near EOL, and LTS indications to help teams plan their deployments and maintenance. [Learn more](/foundations/image-card) ## New FIPS 140-3 certificate for OpenSSL The Minimus Cryptographic Module has acquired a new CMVP certificate - [certificate 5177](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5177). The Minimus Cryptographic Module is a FIPS validated OpenSSL module used in many Minimus FIPS validated images. [Learn more](/compliance/fips-images) ## OCI labels We've updated image labels to use the standard OCI format. OCI labels hold metadata that makes images transparent, traceable, and auditable. You will see the change when you run `docker inspect`. ```json OCI labels example theme={null} "Labels": { "io.minimus.images.line": "1.29", "org.opencontainers.image.created": "2026-03-19T17:13:28Z", "org.opencontainers.image.url": "https://images.minimus.io/images/nginx", "org.opencontainers.image.version": "1.29.6" }, ``` * Private images previously created with internal Python packages were automatically migrated to the equivalent auto-versioning Python packages. For example, if the package `py3-babel` was previously selected, it was migrated to `py3-babel-auto`. [Learn more](/enterprise-edition/image-creator#auto-versioning-packages-for-ruby-python-%26-php) * Improved the performance of the advisories page and the advisories search and filtering functions ## March 15 2026 ## Plan for Long-Term-Support with Minimus Know which image lines offer long-term-support (LTS) by the upstream project directly within Minimus. In addition to End of life (EOL) indications, image lines with official LTS status are now labeled in Minimus to help teams plan their deployments for long-term success and optimal maintenance. [Learn more](/foundations/image-card) ## Minimus Creator promotes auto-packages Minimus Creator already supports auto-versioning for Ruby, Python, and PHP packages. Now the package selector display also groups together package families leading with the auto-version option to help users when creating private images. [Learn more](/enterprise-edition/image-creator#package-compatibility-in-private-images) Fixed an issue where the Changelog was not displayed for Dev variants of private images. ## March 8 2026 ## Compare package composition between Minimus images and their public counterparts Get an immediate sense of the SBOM size and risk differences between a Minimus image and its public equivalent with a new graph in the **Risk Reduction** tab. Dive deeper into the comparison with a detailed breakdown of the packages used by each image and their version, license, and risk posture. As always, you can toggle the view between `latest` and `latest-dev` to view the relevant report. [Learn more](/foundations/image-card#risk-reduction) ## March 1 2026 ## Plan for the image line end-of-life with Minimus Know when upstream support for the image line is scheduled to end directly within Minimus. End of life (EOL) indications are provided in both the image line menu and the changelog view. Hover over the line to see the exact EOL date. [Learn more](/foundations/image-card) ## Understand build status and errors for your private images Deep dive into your private image build statuses directly from the Creator space. You will be able to see exactly which image lines succeeded and which failed and why. As always, share the trace ID with our support team so we can assist you as soon as possible. [Learn more](/enterprise-edition/image-creator#troubleshooting-failed-builds) ## Comply with the CIS MongoDB Benchmark We've added a new Mongo-Hardened image to the list of Minimus Hardened Images. The new [Mongo-Hardened image](https://images.minimus.io/images/mongo-hardened/quick-start) complies with app-specific CIS benchmarks and is also offered as a FIPS-validated option - [Mongo-Hardened-FIPS image](https://images.minimus.io/images/mongo-hardened-fips/quick-start). ## Build-time auto-versioning for Ruby packages We've expanded support for auto-versioning packages to include Ruby packages. Currently, Ruby, Python, and PHP auto-versioning packages are available in Creator to auto-match the starter image version at build time. [Learn more](/enterprise-edition/image-creator#package-compatibility-in-private-images) ## Stand-alone risk reduction reports Benefit from a stand-alone risk reduction report even when there is no comparison image. Whether it is the [static](https://images.minimus.io/images/static/risk-reduction) or [glibc-dynamic](https://images.minimus.io/images/glibc-dynamic/risk-reduction) images or something else, you will now be able to track the vulnerabilities trend over the past 30 days directly from the usual risk reduction tab. * Remove recent search results in the image gallery to keep only the ones you want. ## February 22 2026 ## Helm chart signatures Verify Minimus Helm charts using the Cosign signature. Simple step-by-step instructions were added in a dedicated tab in Minimus Helm charts. [Learn more](/foundations/helm-charts) ## Enhance your private gallery with image descriptions Add descriptions to your private images to stay organized, capture image context, note usage details, or leave the team reminders for future reference. Descriptions can be added during image creation or updated anytime. To view a private image description, hover over the image in the [gallery](/gallery). [Learn more](/enterprise-edition/image-creator) ## SAML role management Managing SAML roles can get confusing when users belong to multiple groups or have individual role assignments. To help simplify the task, we've added helpful hints along the user configuration pages to guide admins more closely. [Learn more](/manage/user-groups) ## Official logo for FIPS 140-3 validated images FIPS 140-3 validated images from Minimus get yet another boost with the adoption of the official NIST logo. The FIPS 140-3 logo is a certification mark of NIST. FIPS 140-3 Color Logo ## February 18 2026 ## Build-time auto-versioning for Python and PHP packages When creating private images with Image Creator, pairing the right package version with the starter image version can potentially get tricky. To save you the trouble, Minimus added auto-versioning Python and PHP packages to auto-match the starter image version at build time. [Learn more](/enterprise-edition/image-creator#auto-versioning-python-and-php-packages) ## February 15 2026 ## Recent searches at your fingertips Dive back into your recent image searches at any time, even between sessions. Your last 10 searches are available from the search bar so you can freely explore the Minimus gallery without fear of losing your context. ## Discover when images were first added Easily see when images were first added to the Minimus image gallery. Switch to the **recently added** sorting option to see the exact date when the image first became available by Minimus. ## February 8 2026 ## Actions for private images Trigger webhooks and get alerted when a new version or vulnerability fix is out for your private images. Actions help teams deploy images smoothly and reliably. ## File bundle usability enhancements Usability enhancements for file bundles improve the configuration experience. A status label "new" was added to mark bundles created inside the Creator wizard. Validations were added to protect against edge cases, check file format, and more. Bundles show which images they are used in to further simplify bundle management. ## February 1 2026 ## Sort images by popularity, recently added, or name Sort the gallery to easily see which images were recently added or which images are most popular. As part of the change, your private images have been moved to the **my images** category and will no longer appear at the top of the general gallery. ## Expanded gallery search results with related images Enter a search term in the gallery to view direct results and related images. Related images are shown under a separate header to clearly indicate their secondary relevance. For example, search for `grafana` to return other images in the Grafana family as related images. ## Added support for SAML groups for Azure and Google providers SAML groups for role-based access control now support all identity providers, including Okta, Azure, Google and others. [Learn more](/manage/user-groups) ## Enhanced the SAML configuration form Configuring SAML groups for Minimus is now simpler with a toggle to enable the option when relevant. ## New FIPS 140-3 modules Minimus has acquired a new FIPS CMVP certificate for Java - [certificate 5142](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5142). In addition, Minimus utilizes a new FIPS module for BoringCrypto - [certificate 5104](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5104). ## Improved FIPS 140-3 testing instructions The compliance FIPS display has been enhanced for clarity. Certificate and testing information for the OpenSSL and Java FIPS modules is shown separately for better understanding. * Improved the advisories search and filtering functions * Enhanced file bundles' usability ## January 25 2026 ## Filter by Advanced images and Helm charts Easily identify Minimus images that support Bitnami Helm charts with a quick filter. Related charts and images cross-reference each other to enhance findability. * Improved configuration overrides with file bundles * Added support for file bundle events in activity logs ## January 18 2026 ## Comprehensive changelog offers complete visibility Easily see which packages were added, updated, or removed or which CVEs were fixed. We've expanded the changelog to reflect all changes without exception. The new comprehensive changelog makes it easier than ever to compare digests within the same image version and to understand what changed in every digest. Filter the list by a change category or search the log by specific package names and versions, the data is at your fingertips. [Learn more](/foundations/image-card#changelog) ## Centrally manage certificates and other file bundles for private images Centrally manage certificates and other file bundles for private images. Use the new file repository to update certificates for all your private images in one go. File bundles are versioned and automatically trigger a private image build upon update. [Learn more](/enterprise-edition/file-bundles) ## Control user access levels We've added user roles to support RBAC (Role-Based Access Control). Roles provide control over who has access to create and edit private images, manage users, and more. Assign viewer, operator, and admin roles as appropriate. [Learn more](/manage/users) ## Audit changes in the activity log Monitor your team's activity in the Minimus activity log. See when users logged in or out of the system, when a private image was first created or updated, when users were added or removed from the system, and more. [Learn more](/manage/activity-log) ## Comply with the CIS Postgres Benchmark We've added a new category of Minimus Hardened Images that comply with specific CIS benchmarks. The first image to be released is [Postgres-Hardened](https://images.minimus.io/images/postgres-hardened/) and [Postgres-Hardened-FIPS](https://images.minimus.io/images/postgres-hardened-fips/compliance/fips). ## Manage SSO users with SAML groups We've added support for SAML groups to simplify identity management. [Learn more](/manage/user-groups) ## Enhanced image gallery search Search the Minimus gallery of images by image name or related terms. Search by related terms provides helpful suggestions so you can explore your options effortlessly. For example, search results will include related images in the same family or images with a similar function. [Learn more](/gallery#search-the-gallery) ## Related Helm charts Easily discover images that can be deployed by Minimus Helm charts. When present, the image card will include an additional tab to list **related charts** and offer direct navigation to them. [Learn more](/foundations/image-card#related-charts) # What's New 2025 Source: https://docs.minimus.io/release-notes-2025 See previous Minimus releases and updates to understand how the product has evolved ## November 2025 ## NIST compliance report We've added a compliance report for NIST-800-190 Section 3.1. [Learn more](/compliance/image-compliance#nist) ## New Helm charts added * The **Postgresql-Advanced** chart deploys Postgresql-Advanced with Prometheus-Postgres-Exporter-Advanced. * The **Keycloak-Advanced** chart deploys keycloak, a high performance Java-based identity and access management solution. * The **Zookeeper-Advanced** chart deploys Zookeeper, a centralized coordination service for distributed systems. * The **etcd-Advanced** chart deploys etcd, a distributed key-value store used to coordinate and manage configuration data for distributed systems such as Kubernetes. * 3 charts were added for **External-DNS**, **External-DNS-FIPS**, and **External-DNS-Advanced**. ## Introducing better package incompatibility handling We've taken the guesswork out of package compatibility. A new package incompatibility handler automatically identifies and skips image lines that run into version conflicts with added packages, to keep your private images building smoothly and error-free. Only image lines of your private image that build successfully are published. [Learn more](/enterprise-edition/image-creator) ## Added supply chain protection for Python Set up guardrails when installing packages based on age, download reputation and more. [Learn more](/enterprise-edition/supply-chain) ## October 2025 ## Image Creator is here! Create a private Minimus image that meets your requirements and simplifies your operations. Make your private image your own, with added packages and custom environment variables. Minimus handles all maintenance - complete with daily builds, vulnerability fixes and reports, advisories, a changelog, and more. [Learn more](/enterprise-edition/image-creator)\ \ Access to the Image Creator is available upon request. ## Supply chain protection preview Set up guardrails when installing packages based on age, download reputation and more. The feature is introduced with Node and the npm package repository, with Python and others to follow soon. [Learn more](/enterprise-edition/supply-chain) ## New Helm charts added * The **prometheus** chart deploys custom Minimus images for the Prometheus server, Node Exporter, Alertmanager, Pushgateway, and Kube State Metrics. * The **rabbitmq-advanced** chart for the RabbitMQ message broker automates the deployment and configuration of RabbitMQ in Kubernetes clusters with TLS encryption and init container support. ## Easily create a K8s secret The tokens page was enhanced to offer more useful authentication commands: * Create a K8s Secret * Authenticate to the Minimus package repository Visit our comprehensive authentication guide to review all of your options. [Learn more](/enterprise-edition/authentication) ## Extend Minimus images with Minimus packages Install Minimus packages directly in Minimus images using a package manager. We've introduced the option to work directly with the full catalog of Minimus packages. Create a token with package access scope to begin. [Learn more](/basics/package-manager-access) Access to Minimus packages is available upon request. ## Sign-up form for new Minimus accounts We've added a form for new users to request a Minimus account. Self-sign up has been discontinued to allow Minimus to provide a superb onboarding experience for every new member. [Learn more](/introduction/default-account) ## Native support for AWS and Snyk scanners Secure your Minimus container resources with Amazon Inspector and Snyk to simplify operations. [View the full list of supported scanners](/scanning/scanner-support) Built-in support for Minimus images means Minimus advisories are automatically synced so the scanners filter out false positives. [Learn more](/scanning/advisories-feed) ## September 2025 ## Image Creator preview We released an early version of our upcoming Image Creator. Use the Image Creator to create custom private images based on your subscribed Minimus images to meet security, licensing, and regulatory requirements. The preview offers a limited, preliminary version of the forthcoming feature. Check back soon to experience the full Image Creator. ## CIS compliance report display We've improved the display of the CIS Docker Section 4 report to make it clearer and friendlier. * Fixed case sensitivity issues impacting user signup with Gmail * Fixed bug affecting Helm chart image version updates ## August 2025 ## Image compliance tab Verify that your Minimus container image meets security, licensing, and regulatory requirements. The image compliance tab is a single point of reference for CIS Docker Benchmarks, FIPS and STIG verification, and Cosign commands to verify the image signature and SBOM attestation. [Learn more](/foundations/image-card#compliance) ## Helm charts Minimus now offers a gallery of signed Helm charts for faster app deployment. Minimus Helm charts use Minimus secure images to streamline adoption and upgrades. [Learn more](/foundations/helm-charts) ## Integrate with scanners using OpenVEX Minimus offers built-in support for Grype, Trivy, and other scanners, but when you need it, Minimus also offers an OpenVEX document to support any scanner. Download the OpenVEX document for any image version to filter out false positives. [Learn more](/foundations/image-version#download-vex) ## Private images Whatever custom image you need, Minimus can build it for you! You can now special-order a custom image with a unique combination of packages. Private images are fully maintained by Minimus - just like any other Minimus image - including daily updates and vulnerability fixes, compliance benchmarks, changelog, image digest history, and more. ## Sign up with your Microsoft account We've added support for login with Microsoft accounts. You can now create a Minimus account with Google, GitHub, or Microsoft. ## June 2025 ## Slack, email & GitHub action providers Respond to image version updates and vulnerability fixes with the help of new actions. You can now trigger Slack and email notifications and GitHub Actions. [Learn more](/remediate/create-action) ## Affected images Advisories now list affected images and image fix versions. Filter by affected images to quickly locate what matters to your environment. [Learn more](/remediate/advisories) ## Changelog tab View vulnerability fixes by image line in the new Changelog tab. Filter and search the list and drill down for further details. [Learn more](/foundations/image-card#changelog) ## Native support for Trivy and Grype scanners Secure your Minimus container resources with Trivy and Grype vulnerability scanners. [View the full list of supported scanners](/scanning/scanner-support) Built-in support for Minimus images means Minimus advisories are automatically synced so the scanners filter out false positives. [Learn more](/scanning/advisories-feed) ## Exploitability threat intel Instantly know which versions are currently vulnerable to active or likely exploits directly from the image line view. # Actions Source: https://docs.minimus.io/remediate/actions Proactively respond to security updates related to your Minimus images using Minimus Actions Minimus Actions help you effortlessly keep up with security updates related to your Minimus images - including private images created with [Creator](/enterprise-edition/image-creator). You can set up Minimus Actions to trigger webhooks, GitHub Actions, and alerts for new image versions/digests, security updates, EOL notifications, and more. Minimus Actions ## Why Minimus Actions matter Keeping up with security patching can be intense unless you establish a reliable routine. While Minimus images are typically clean of any vulnerabilities when you first deploy them, the images will eventually accrue vulnerabilities and require security updates on an ongoing basis. Minimus Actions notify you when fixes and other updates are available so that you can expedite testing and deploy version updates sooner. [Learn more](/foundations/daily-updates) ## Action triggers Actions boost your security posture by ensuring that you can respond proactively whenever: * New image version/digest is released * New helm chart version released * Vulnerability fix is shipped * Image line nearing EOL * Image line reached EOL * EOL image was pulled You can always add filters to alert on specific images or specific image lines, or filter by FIPS, STIG, and an image category. For vulnerability-related actions, you can also filter to focus on active exploits, likely exploits, or CVSS severity. ## Action responses Minimus supports several action responses: webhooks, GitHub Actions, email notifications, and Slack alerts. See [how to create actions](/remediate/create-action) ## Recommended actions Suggestions for recommended actions are included to help you get started. As your first action, you can set up a Slack or email notification to trigger after a fix is released for active or likely exploits in an image line you are currently using. * Active exploits are vulnerabilities known to be exploited in the wild that have been added to the CISA KEV catalog. * Likely exploits are vulnerabilities with an extremely high EPSS score that are statistically likely targets for exploitation. ## Your actions list You can search the list of actions by any attribute, including the action name, state, and trigger. The table includes the following: * Action name * Trigger * Action (Webhook) * Enabled/Disabled state. Hover over a line to toggle the state and disable or enable an action. ## Edit an action Hover over an action in the table and select the edit button (). You can edit all fields in the action form and save your changes. # Security Advisories Source: https://docs.minimus.io/remediate/advisories Keeping up with vulnerability reports for your Minimus images Minimus publishes security advisories for vulnerabilities affecting Minimus images and their dependencies. The information complements the vulnerability report provided for every image version. Select **Advisories** from the left menu to visit the list of advisories published for Minimus images (or use the [direct link](https://images.minimus.io/advisories)). Advisories Affected images only refer to production images. Development image variants (for example, an image tagged `latest-dev`) are excluded by default. Refer to version-specific vulnerability reports for information about vulnerabilities affecting development images. [Learn more](/foundations/image-card#versions) ## Overview Before you dive into the details, examine the metrics in the top section: * Total number of new vulnerabilities detected in the past 7 days in Minimus packages * Total number of vulnerabilities detected over the past year in Minimus packages that are currently known as **active exploits** (i.e. they are on the CISA KEV list) * Total number of vulnerabilities detected over the past year in Minimus images that are currently labeled as **likely exploits** (i.e. they have a high EPSS probability score and are likely targets for exploitation). * Total number of critical severity vulnerabilities detected over the past year in Minimus images. ## Advisories table The advisories table lists all affected packages. Some vulnerabilities affect multiple packages, so you will notice the same vulnerability listed on a separate line for each impacted package. When the affected package is mapped to a Minimus image, the image information and fixed version will appear as well. The advisories table shows the following: * Vulnerability ID - either a CVE ID or a GHSA (GitHub Security Advisory) ID * Origin package affected by the vulnerability. Note that affected secondary packages are detailed in the vulnerability report for specific image versions. * Affected images (Only showing production images. Dev images are excluded.) * Severity (CVSS score listed by NVD from registered CNAs, CISA ADP, or NIST. Where there are multiple severity analyses with different scores, Minimus favors the most recent CVSS vector and the most reputable vendor). [Learn more about competing CVSS severity scores](/remediate/priorities/cvss) * Exploitability, as determined by Minimus [based on CISA KEV or EPSS predictions](/remediate/threat-intel#exploitability-label). * Status * Date published ([Note that an image may be fixed before the advisory was published](/remediate/fix-date).) * Detected - When the scanner first flagged the vulnerability. This may be **after** the package was already fixed, as in a [silent fix](/remediate/fix-date). * Last update - When the advisory was last updated. [Note the difference between package fix date, image build date, and the advisory fix notification](/remediate/fix-date). ### Filtering, searching, and sorting advisories 1. **Filtering options** You can filter the advisories list by affected images, severity, exploitability, status, detection date and last update. The filters are friendly UI elements, and do not require complex syntax. The **Affected Images** filter has the following options: 1. My images (Default) 2. Any 3. Specific images (Searchable list of images) 4. Remove this filter to include also advisories for packages that are not mapped to any image. 2. **Search options** You can search the advisories by a full or partial vulnerability ID and/or a package and image name. You can combine search terms with filtering criteria. 3. **Sorting options** You may sort the advisories by their severity and last update. Advisories are not mapped to affected images if their status is **under review** or **unaffected**. ## Drill down on an advisory Click on an advisory in the table to view its detailed listing. When drilling down from the advisories table, a filter is applied by default for the specific origin package. Filtered By Package Expand the card to view the full advisory details with detailed information listing all affected images, the current status, fixed package and image version information (if available), and the status history. [Learn more](/remediate/cve-advisory) Advisory Details Expanded View ## Advisory status | Status | Description | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | Under review | Minimus is following up on the vulnerability report to confirm the report and determine if the vulnerable code affects the package. | | Affected | The vulnerability was confirmed by the Minimus team to be affecting the package. | | Unaffected | The vulnerability was determined to be a false-positive by Minimus. Reasoning is provided in a note. | | Pending upstream fix | Minimus is waiting for the source repo to publish a fix for the package. The image will be patched as soon as the fix becomes available. | | Fixed | A patch was applied to remediate the vulnerability. | | Fix not planned | Usually a fix is not planned for package versions that have reached their end of life (EOL). Reasoning is provided in a note. | # Create Action Source: https://docs.minimus.io/remediate/create-action Set up webhooks, GitHub Actions, email, and Slack alerts for when a vulnerability is fixed or a new version is released You can set actions to automatically pull the new image version/digest or notify you of its release. The actions can be tailored to specific image lines or to respond to vulnerabilities of certain severity or exploitability labels. Private images created by [Creator](/enterprise-edition/image-creator) are fully supported by Minimus actions. ## Overview As a rule, actions only apply to images included in your Minimus subscription. There are 2 steps to configuring an action: 1. Decide when to set off the action, that is, what the action should respond to. The following triggers are supported: 1. New image version/digest released 2. New Helm chart version released 3. Vulnerability fix 4. Image line nearing EOL 5. Image line reached EOL 6. EOL image was pulled 2. Decide what the response should be, that is, what the action should do. The following responses are supported: 1. Trigger a webhook 2. Send email 3. Send Slack alert 4. Trigger GitHub Action ## When to trigger the action ### By new Helm chart version release You can set an action to trigger in response to a new version release for Helm charts published by Minimus. 1. Select **Actions** in the left menu. Then select **Create Action** and fill out the form as follows. 2. **Name** the action. 3. **When -** Select **New Helm chart version released**. 4. **If** - Add your filters. You can filter by Helm chart name or select categories, for example FIPS or STIG.\\ Helm Chart Version Action 5. **Then** - select the action and proceed as explained below. ### By new version/digest release You can set an action to trigger in response to a new version release or a new image digest (that is, a new image build following an update as shown in the [image changelog](/foundations/image-card)). 1. Select **Actions** in the left menu. Then select **Create Action** and fill out the form as follows. 2. **Name** the action. 3. **When -** Select **New image version is released**. If you prefer, toggle on the option to **Alert for every new digest of the same version**. When enabled, the action will trigger every time there is a new image build for the relevant image lines. See also [digest history](https://docs.minimus.io/foundations/image-version#digest-history) and [image changelog](https://docs.minimus.io/foundations/image-card#changelog). Action Trigger Every New Digest 4. **If** - Add your filters. You can filter by image properties and combine as many filters as relevant: 1. Select images by name from the list. Only images included in your subscription will be shown. 2. Select image lines from the list. End of life (EOL) indications and dates will be shown on lines reaching or post-EOL. Action Eol Indications 3. Instead of selecting specific images by name, you can instead select relevant filters from the **image category & compliance**. Compliance may be FIPS or STIG compatibility. 5. **Then** - select the action and proceed as explained below. ### By vulnerability fix You can set an action to trigger in response to a vulnerability fix. 1. Select **Actions** in the left menu. Then select **Create Action** and fill out the form as follows. 2. **Name** the action. 3. **When -** Select **Vulnerability is fixed** 4. **If** - Add your filters. You can combine filters for image and vulnerability properties: 1. Select images by name from the list. Only images included in your subscription will be shown. 2. Select image lines from the list. End of life (EOL) indications and dates will be shown on lines reaching or post-EOL. Actions Image Line Eol Labels 3. Instead of selecting specific images by name, you can instead select relevant filters from the **image category & compliance**. Compliance may be FIPS or STIG compatibility. 4. Select vulnerability **Severity**. You can select unknown, low, medium, high, critical. 5. Select **Exploitability** is either **Active exploit, Likely to be exploited**, or both. 5. **Then** - select the action and proceed as explained below. ### By EOL date EOL notifications run once daily and only alert once per image line to avoid duplicates. 1. Select **Actions** in the left menu. Then select **Create Action** and fill out the form as follows. 2. **Name** the action. 3. **When** - Select one of the following: 1. Select **Image line nearing EOL**. Then decide how many weeks of advance notice you want (1–12 weeks). Saving the action adds it to the daily queue. The first alert will be sent during the next scheduled notification window, and will list all relevant image lines that have already passed the notification threshold. For example, if you set a 2 week notice, the first alert will notify you of any images that have less than 2 weeks remaining until EOL. 2. Select **Image line reached EOL**. Saving the action adds it to the daily queue. The first alert will be sent during the next scheduled notification window, and will list all relevant image lines that have reached EOL in the past 90 days. 4. **If** - Add your filters. You can filter by image properties and combine as many filters as relevant: 1. Select images by name from the list. Only images included in your subscription will be shown. 2. Select image lines from the list. End of life (EOL) indications and dates will be shown on lines reaching or post-EOL. 3. Instead of selecting specific images by name, you can instead select relevant filters from the **image category & compliance**. Compliance may be FIPS or STIG compatibility. 5. **Then** - select the action and proceed as explained below. ### By EOL image pull Configure actions to trigger when images that have passed end-of-life are pulled. 1. Select **Actions** in the left menu. Then select **Create Action** and fill out the form as follows. 2. **Name** the action. 3. **When** - Select **EOL image was pulled** 4. **If** - Add your filters. You can filter by image properties and combine as many filters as relevant: 1. Select images by name from the list. Only images included in your subscription will be shown. 2. Select image lines from the list. End of life (EOL) indications and dates will be shown on lines reaching or post-EOL. 3. Instead of selecting specific images by name, you can instead select relevant filters from the **image category & compliance**. Compliance may be FIPS or STIG compatibility. 5. **Then** - select the action and proceed as explained below. ## Trigger a webhook 1. Select the action **Trigger webhook** 2. Add your webhook URL. The webhook client is a simple HTTP client that sends POST requests to the endpoint. 3. **Test** the action. 4. If the test is successful, select **Create Action** to save and enable the action. ### About action webhooks * The webhook provider receives a single event for each alert. Aggregation is not currently supported. * Here’s an example of the JSON payload schema sent by the action: ```json JSON payload schema example expandable lines theme={null} { "actionName": "Example Alert", "eventType": "newImageVersion", "eventTime": "2025-04-10T00:28:59.037085531Z", "imageDetails": { "name": "mongo", "tags": [ "7.0.18-dev-202504100027", "7-dev", "7.0.18-dev", "7.0-dev" ], "digest": "sha256:9c45497ff4b8217571e8ae5298719b4912b304617dc6f28db5a4053d3bdc44dc", "labels": [ "databases" ], "link": "images.minimus.io/images/mongo/lines/7.0/versions/7.0.18-dev/specification" } } ``` ## Send email notifications Minimus will send an email notification for every relevant update. 1. Select the action **Send email**. 1. List recipients (using commas as separators). You can add CC recipients as well. 2. Optionally, you can add a custom note. The note will be appended to the default messages. 2. **Test** the action. 3. If the test is successful, select **Create Action** to save and enable the action. ## Send Slack alerts 1. Select the action **Send Slack Alert**. 1. Click the button **Connect to Slack**. 2. **Allow** the permissions requested in the popup window. If you are connected to several Slack workspaces, you can select the relevant one from the top right corner. 3. The form will now show the **connected workspace**. 4. List the channels to be notified. The Minimus app can send messages to public channels by default. For private channels, you will need to add the Minimus app to the channel in advance. 5. **Test** the action. 2. If the test is successful, select **Create Action** to enable it. ### Add the Minimus App to a private Slack channel If you don't give the Minimus App permissions to message your private Slack channel, the test will fail with the message "not in channel". 1. In your private Slack channel, click the kebab menu in the top right corner. 2. Select **Edit settings**. 3. Select the **Integrations** tab. Slack Private Channel Add App 4. Add the Minimus App. 5. That's it. Minimus can now notify the channel. ## Trigger GitHub Actions 1. Select the action **Trigger GitHub Actions**. 1. Click the button **Connect to GitHub**. 2. Select the relevant GitHub owner or organization. Connect GitHub to Minimus 2. Specify the **Owner** and **Repository**. For example, if your organization's GitHub URL looks like `https://github.com/myorganization/myproject/` - the owner is `myorganization` and the repository is `myproject`. 3. **Test** the connection. 4. If the test is successful, select **Create Action** to enable it. ### Troubleshooting the connection to GitHub * **Scroll down if necessary**\ If you previously created an action that connected to your GitHub repo, the popup approval window will open in your general GitHub settings menu - [https://github.com/settings/profile](https://github.com/settings/profile). * Scroll down until you see the section for configuring **Repository access**. * Select the relevant owner and repo as usual and save your selection. Git Hubactionrepositoryaccess * **Reset repository selection if necessary**\ Sometimes, if you previously created an action that connected to a private GitHub repo, the popup approval window will apply your previous selection. In this case, the **Repository access** section will appear to be "locked" on your previous selection with the **Save** button disabled. * To activate the **Save** button, first change the selection to **All repositories**. * Next, select the relevant owner and repository and save your selection. Note that the relevant configuration is also found in your GitHub settings under [https://github.com/settings/installations](https://github.com/settings/installations). Connect Github Specific Repo # Advisory Drill-Down Source: https://docs.minimus.io/remediate/cve-advisory Drill down on a specific advisory to learn more about the risk and the affected images Drill down on a specific advisory to see the following details: * Overview of the severity, exploitability label, date published, and last update * Description of the vulnerability quoted from NVD or GitHub advisories with a link to view the CVE listing directly in the NVD database ## Internal advisory tabs Advisory data is organized internally by tabs to make the information easy to interpret. ### Origin packages Each advisory describes one origin package impacted by a single vulnerability. Minimus groups advisories together by vulnerability to simplify the display. Package-specific information for each of the affected origin packages is shown in expandable cards. Expand each card to see the advisory status, version information, fixed image version and more. Grouped By Vulnerability When drilling down from the advisories table, a filter is applied by default for the specific origin package. Clear the filter to see all packages affected by the same vulnerability. Filter the advisory by the origin package to see more details. Every origin package card shows: * Affected images * The current advisory status (fixed, unaffected, pending upstream fix, etc.) * Fixed package version (if available) * Fixed image version (if available) with a direct link to view the [image version card](/foundations/image-version) * Date when the advisory was last updated ### Fix version information If the package and associated images have already been fixed, the fixed image versions will be provided with direct links to view the image cards. Links Fixed Images If the package was already fixed, but the fixed image is still pending the build, the **fixed image version** will clearly state that it is **pending image build**. Pending Image Build ### Severity The Severity tab shows severity details with the CVSS vector details and CVSS version information. ### Exploitability The exploitability tab shows details about CISA KEV and EPSS probability and percentile rank scores. ### References The references tab shows links to recommended reference material. ## Status history For every affected package, expand the listing to view a history of the advisory statuses. You will see when the advisory came under review and the different updates provided with the rationale, when applicable. Examples for status notes: * If a package is listed as unaffected by the CVE, it will explain why the advisory is a false-positive. For example, the vulnerable code may not be present in the Minimus package. * If a fix is not planned, the note will explain why. For example the package may have reached its end-of-life (EOL). # Fix Dates Source: https://docs.minimus.io/remediate/fix-date Understand the difference between the advisory fix date and image fix date In Minimus, the package update process is independent of the vulnerability patching process. A new package is built as soon as an update is detected upstream in the source code. Once a day, all of the images in the Minimus repository awaiting package updates are built with the latest packages available. This process is designed to ensure that all new features, vulnerability patches, and bug fixes are available on a daily basis to Minimus users. [Learn more about Minimus architecture](/introduction/architecture) ## Scanner detection limitations Sometimes, you will see a detection lag between when the vulnerability was first published and until it is detected in the package. This behavior may be confusing at first since a CVE may even be published weeks before it is first detected in an image. The key is to understand that delays in scanner detection are most often caused by missing data in the CVE listing itself. Since this limitation is general, it is not attributable to any specific scanner and it will impact all scanners equally. A CVE ID may be reserved and listed by NVD with minimal data that is not usable by scanners, effectively rendering the CVE listing not actionable. A scanner cannot flag a CVE in an image until **affected versions, package data, and CPEs (Common Platform Enumeration)** are defined. This means a CVE may be listed long before it can be detected by scanners. For example, the [advisory for CVE-2025-60876](https://images.minimus.io/advisories/CVE-2025-60876/packages/busybox?search=CVE-2025-60876) shows a scanner lag from the original publishing date. The change history in the [NIST listing for CVE-2025-60876](https://nvd.nist.gov/vuln/detail/CVE-2025-60876) clarifies the cause is a CVE enrichment lag, not a scanning failure. CVE-2025-60876 was not detectable by vulnerability scanners until the BusyBox CPE and version constraints were added to the NVD record. Prior to CPE data enrichment, the CVE lacked machine-readable product metadata, which prevented reliable scanner matching. This explains the delay observed by scanners. Since this is a general limitation, it is not attributable to any specific scanner. ## Advisory fix date vs. image fix date The advisory fix date is based on the package fix date and it can differ from the image fix date. This can happen for several reasons. Below are a few examples of typical cases. ### Package fixed but pending image build Minimus packages are updated on a continuous basis that is independent from the vulnerability remediation process. As a result, package updates are published as soon as an update is available upstream. New images, on the other hand, are published on a daily basis. Consequently, an advisory may show the fixed status when the fixed package is already available but before the fixed image is released. Pending Image Build Once the fixed image is released, the advisory and changelog are updated accordingly. The advisory provides direct links to view the fixed image versions. Links Fixed Images ### Image fixed before advisory was published (silent fix) You might wonder how an image could be fixed before the advisory was ever published? This is known as coordinated disclosure and silent patching, or a **silent fix**. In coordinated disclosure, the vulnerability is discreetly reported and is not publicly announced until after the fix is made available. Usually, the patch is released before the vulnerability is announced to allow users time to deploy the fix and minimize the window of opportunity for exploitation by bad actors. Since Minimus builds updated packages and images on an ongoing basis, Minimus guarantees that you will always have the most secure images available to you, even before word of the vulnerability reaches your scanners, vulnerability management platforms, CNAPP and SIEM. ## Display of silent fixes in Minimus Silent fixes describe cases where the fix is released *before* the vulnerability is publicly disclosed. CVE-2025-68119 is a good example of how Minimus displays silent fixes. The [advisories for CVE-2025-68119](https://images.minimus.io/advisories/CVE-2025-68119/packages/logstash-8.18?) were published on Jan 28, 2026 and show that the vulnerability impacted nearly 400 packages and required fixing hundreds of images. Some of the affected packages were fixed before the vulnerability was published - that is, they were silently fixed. For example, the [Logstash image changelog](https://images.minimus.io/images/logstash/changelog/9.2?search=68119) shows that an image version that fixes this vulnerability was published on Jan 6, 2026. Silent Fix Changelog The [advisory](https://images.minimus.io/advisories/CVE-2025-68119/packages/logstash-8.18?filterPackage=logstash-8.18) for the same vulnerability shows that the advisory status was only marked as fixed on Feb 1, 2026 - long after the fixed image was actually published. Silent Fix Advisory The apparent discrepancy between these dates can be easily explained: * The advisory fix date shows when the scanner recognized the fix. The advisory does not show when the fixed image version became available. * The changelog fix date shows when the fixed image version was published by Minimus. In summary, the advisory fix date is dependent on the scanner database and is unconnected to Minimus build data. The changelog is true to the Minimus build data and is fully independent of the advisory or scanner updates. # Cherry Picking Patches Source: https://docs.minimus.io/remediate/policies/cherry-pick-patches Understand the Minimus approach to cherry-picking vulnerability fixes before they are officially committed to the upstream ## What does it mean to cherry-pick a vulnerability fix? In Git, `cherry-pick` means taking a specific commit from one branch and applying it to another branch without merging any of the other changes on that branch. It is possible to use a git cherry-pick to apply a security patch (commit) from one branch or version to another. However, this means the change is committed before it has been officially merged or approved. ## How to tell if an advisory was fixed by a cherry-pick It's not always possible to tell, but typically, when a package is manually fixed via a git cherry-pick, the security advisory will note the package version epoch. For example, [CVE-2025-11495 for binutils](https://images.minimus.io/advisories/CVE-2025-11495/packages/binutils?search=binutils\&filterPackage=binutils) which was fixed by package version epoch `2.45-r2`. The package version epoch is a version that incorporates alphabetical characters that cannot always be compared reliably. It is typically used to resolve an upgrade ordering issue as a result of upstream changes, as in the case of cherry-picked commits. ## Why cherry-pick vulnerability fixes Sometimes, a fix may become available in a yet-unreleased commit to the project’s source or via an external patch (from a mailing list or another equivalent source) before it is officially accepted. In such cases, there is some potential benefit to be gained from resolving the vulnerability earlier, but it must be balanced with the risk of introducing fixes that have not been sufficiently tested. ## Balancing risk and benefit At Minimus, we aim to balance these competing considerations according to our understanding of security principles. Vulnerability and exploit intelligence always drive our decisions. In such cases, our goal at Minimus is to balance the risk of leaving vulnerabilities unpatched with the risk of incorporating fixes that haven’t been extensively tested and could introduce regressions or worse. ## Our policy Minimus will only consider patching a vulnerability via a `git cherry-pick` if the patch does not present the risk of introducing a regression greater than the potential impact of exploitation. That is, the potential risk of exploitation must justify the risk of committing the fix before it has been fully tested. This efficacy criterion supersedes all other criteria stated below. When an effective patch is available, Minimus will patch a vulnerability via a cherry-pick fix in the following cases: * If a vulnerability is labeled as an **Active Exploit** in the Minimus console, regardless of severity. * If a vulnerability is labeled as a **Likely Exploit** in the Minimus console, and the vulnerability is of **critical or high severity**. The Likely Exploit label is applied to vulnerabilities with an exploitability probability score above 60%.\ \ An EPSS probability score of 60% is in the 98th percentile. In other words, fewer than 2% of vulnerabilities have an EPSS probability score of 60% or higher. [Learn more](/remediate/priorities/epss) Minimus may choose to address vulnerabilities that don't meet the above criteria when the team determines that the benefits outweigh the potential risks. Minimus reserves the right, at its discretion, to apply a cherry-picked fix to vulnerabilities that are below the EPSS threshold to be considered a **Likely Exploit** by Minimus. The higher the severity, the more likely that Minimus will choose to apply the cherry-picked patch. ### Requesting a cherry-pick patch Please get in touch with us directly if you would like to submit a request to have us address a specific vulnerability via a cherry-pick. [Contact us directly](https://support.minimus.io/support/home) Please provide a business impact statement with your request to help us better understand your needs. # Vulnerability Remediation Policy Source: https://docs.minimus.io/remediate/policies/remediation-policy Understand the Minimus vulnerability patching policy Minimus is committed to patching vulnerabilities in its images within the following timeframes: * A critical or high severity vulnerability will be remediated within 48 hours from the time a new release is available from the upstream project that fixes the vulnerability. * All other vulnerabilities (medium and low severity) will be remediated within 14 calendar days from the date a new release is available from the upstream project that fixes the vulnerability. The above targets are provided under the applicable Minimus Vulnerability Remediation Policy. [Contact us for further information](https://support.minimus.io/support/home) ### Supplementary remediation policies * In the event of high-profile CVEs that impact low-level, widely used packages, Minimus will take commercially reasonable efforts to rebuild all images promptly. * Backporting security fixes - Under certain conditions, Minimus may backport select fixes. [See below](#backporting-fixes) * Cherry-pick vulnerability fixes - Under certain conditions, Minimus may patch a vulnerability before the fix is officially committed to the project’s upstream. [Learn more](/remediate/policies/cherry-pick-patches) ## Backporting fixes Backporting a fix is the concept of applying a fix from a newer version to an older version. In rare circumstances, Minimus may backport select fixes from upstream packages and libraries into Minimus images. Minimus is focused on maintaining 100% compatibility with upstream sources. However, there are circumstances where the security needs of our customers or the risk associated with a vulnerability in a specific package require more aggressive attention from the Minimus security and engineering teams. In these instances, while Minimus waits for an upstream fix, it may backport a patch to mitigate the risk for users until the fix is available upstream. ## Package rebuilds following compiler updates Minimus automatically rebuilds packages whenever there is a change to the code in the upstream. In contrast, compiler updates will only trigger a package rebuild if it will patch vulnerabilities. That is, a package will be rebuilt following a compiler update only if the new compiler version will impact the security posture of the package. For example, the mongo-tools package is compiled with Go. If Go releases a new version, the existing mongo-tools package will only be rebuilt if the Go compiler version delivers vulnerability fixes. # CVSS Severity Source: https://docs.minimus.io/remediate/priorities/cvss About CVSS severity classifications in Minimus advisories CVSS, the Common Vulnerability Scoring System, is the most established prioritization method, dating back some 20 years. CVSS severity scores are calculated on a scale of 0 to 10, with anything over 9.0 considered critical, and anything over 7.0 considered high severity. CVSS scores are version dependent. The most recent version, CVSSv4 was released in Nov. 2023, though CVSSv3.1 remains more prevalent for now. Minimus gives preference to the latest version, so that if a CVE has been evaluated for both CVSSv4 and CVSSv3.1, only the v4 vector will be shown. ## Severity score disputes The same CVE may be assigned different CVSS scores by different vendors. For example, [CVE-2024-25110](https://nvd.nist.gov/vuln/detail/CVE-2024-25110) was assigned a staggering CVSS score of 9.8 by GitHub, but only 8.1 by NVD. There isn't as much of a consensus as one might expect. Severity score disputes reflect different environmental assumptions (for example, comparing a publicly exposed server to an internal system behind a firewall) and different assessments of the potential impact, a factor considered to be highly subjective. The timing of the analysis is also significant, with the most recent analysis likely to be the best informed. In general, CVSS scores are rarely revisited or updated. ## CNA ranking Vendors officially authorized to publish CVSS scores are known as CNAs, [CVE Numbering Authorities](https://www.cve.org/programorganization/cnas). CNAs are evaluated by NVD on an ongoing basis and the CVSS vectors they publish are regularly audited. NVD ranks CNAs according to a measure known as acceptance level ([ref](https://nvd.nist.gov/vuln/cvmap/Understanding-Acceptance-Levels)). There are 3 acceptance levels, ranked from lowest to highest: * Reference - under evaluation * Contributor - on track to become a Provider CNA * Provider - highest confidence, on par with NVD analysts CNA Acceptance Level by NVD ## Recommended severity score When a CVE has been evaluated by more than one authority, Minimus will show the primary CVSS score and vector, as determined by the NVD API. The primary severity score is not explicitly marked in the NVD CVE listing, but it plays an important role in the NVD API. The recommended severity score is determined using this logic: * CVSSv4 is always favored over CVSSv3.1, regardless of the CNA's authority. * Provider CNA analysis takes priority over NVD analysis. * NVD analysis takes priority over Contributor or Reference CNAs (if they are in the same CVSS version). * If NVD or Provider CNA analysis is not available, Contributor or Reference CNA analysis is shown. CVSS Score Selection Flow PNG ### Examples [CVE-2025-12383](https://nvd.nist.gov/vuln/detail/CVE-2025-12383) has a Reference CNA CVSSv4 score of 9.4 and an NVD CVSSv3.x score of 7.4. The [Minimus advisory](https://images.minimus.io/advisories/CVE-2025-12383/severity?) lists the Reference CNA's score despite it being from a lesser authority because it uses the newer CVSS version. [CVE-2025-66516](https://nvd.nist.gov/vuln/detail/CVE-2025-66516) has two competing CVSSv3 scores. The [Minimus advisory](https://images.minimus.io/advisories/CVE-2025-66516/severity?) lists the NVD score of 9.8 since it takes precedence over Contributor CNA analysis. CVSSv3 Competing Scores [CVE-2025-66506](https://nvd.nist.gov/vuln/detail/CVE-2025-66506) only offers a Contributor CNA score. This is also the severity listed in the [Minimus advisory](https://images.minimus.io/advisories/CVE-2025-66506/severity?). CVSSv3 Contributor Score ## Unknown severity Vulnerabilities may be published in the NVD database before their official severity score is determined. In such cases, the severity is marked as unknown while the vulnerability awaits further analysis. It's crucial to note that vulnerabilities awaiting severity analysis have not necessarily been determined minor or unimportant during initial triage. Some vulnerabilities will be evaluated by a Reference or Contributor CNA before they receive an official NVD score. In such cases, the CVE will still show an unknown score until an official severity score and vector are published by NVD (or a Provider CNA). Over 2024, NVD reported a chronic backlog in severity assessments and took several steps to close the gap but the issue is not yet resolved. This situation only complicates the matter of vulnerability prioritization. * [NVD Dashboard showing the number of vulnerabilities reported and awaiting analysis](https://nvd.nist.gov/general/nvd-dashboard) * [NVD program announcement, April 2024](https://nvd.nist.gov/general/news/nvd-program-transition-announcement) * [CVE announcement authorizing vendors to publish CVSS scores under the CISA ADP program (CVE Authorized Data Publisher), June 2024](https://www.cve.org/Media/News/item/blog/2024/06/04/CISA-Added-as-CVE-Authorized-Data-Publisher) # EPSS Exploitability Metrics Source: https://docs.minimus.io/remediate/priorities/epss About EPSS exploitability metrics in Minimus advisories EPSS, the Exploit Prediction Scoring System, is a daily estimate of the probability that a vulnerability will be exploited in the wild over the next 30 days. An EPSS probability score is given on a scale of 0% to 100%, where the higher the EPSS score, the higher the probability of exploitation in the wild. ## EPSS probability score & rank Only around 5% of all vulnerabilities are ever exploited in the wild. This can make it hard to interpret EPSS scores, since seemingly low probability scores will have a high rank. About 88% of vulnerabilities have an EPSS probability score of 10% or lower. An EPSS probability of 25% puts the vulnerability in the 95th percentile, and a probability of 50% is in the 98th percentile ([ref](https://www.first.org/epss/articles/prob_percentile_bins)). The distribution of EPSS scores can help convey this information more intuitively. EPSS probability distribution ## Exploitability label In Minimus, vulnerabilities with an EPSS score above 60% are labeled as **Likely exploit**. If a CVE is both on the CISA KEV list and also has a high EPSS score, it will only show the **active exploit** label. # CISA KEV Source: https://docs.minimus.io/remediate/priorities/kev How Minimus uses the CISA Known Exploited Vulnerabilities catalog to label and prioritize active exploits The [Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) published by CISA is an authoritative list of vulnerabilities that have been exploited in the wild. All the vulnerabilities on this list should be prioritized as top threats. CISA KEV currently includes around 1300 vulnerabilities, most of which are vendor specific. Surprisingly, even older vulnerabilities can land the list long after their original publication date. For example, [CVE-2022-2586](https://nvd.nist.gov/vuln/detail/cve-2022-2586), first published in August 2022, was only added to the CISA KEV list in June 2024. ## Exploitability label In Minimus, vulnerabilities on the CISA KEV catalog are labeled as **active exploits**. ## Remediation due dates Federal agencies are required to patch vulnerabilities that appear in the CISA KEV list within a certain time frame. The due date is published for every vulnerability on the list. Generally, everyone is encouraged to follow the same due dates, even if not required by law. # Prioritizing Vulnerabilities Source: https://docs.minimus.io/remediate/prioritize Risk based vulnerability prioritization based on EPSS, CVSS severity, and CISA KEV for your Minimus container images ## Why vulnerability remediation prioritization still matters In theory, vulnerability prioritization tools should no longer be required now that anyone can upgrade container images daily using Minimus secure container images. Just pull a fresh build for your image to get the cleanest and most secure image possible. So why should we still be talking about how to prioritize vulnerability remediation? In practice, frequent upgrades are considered to increase instability and are often delayed or even blocked to allow for testing to complete. Teams need to balance security updates with app stability, which reintroduces the need to prioritize vulnerabilities, especially taking into consideration their exploitability. This is where Minimus threat intel comes into play, making it simple to evaluate vulnerability risk directly from the Minimus console. ## Minimus threat intel Minimus enriches every vulnerability advisory with data from 3 risk assessment systems: * [CISA KEV](/remediate/priorities/kev) * [EPSS](/remediate/priorities/epss) * [CVSS](/remediate/priorities/cvss) Minimus threat intel can direct your team's vulnerability remediation prioritization and ensure that images affected by vulnerabilities flagged as active exploits (CISA KEV) or likely exploits (high EPSS) are moved to the top of the remediation queue. Minimus actions, provided as part of the Minimus Enterprise Edition, can be used to automate workflows and notifications for establishing a robust vulnerability risk management system. [Learn more about Minimus actions](/remediate/actions) > *There’s no inherent correlation between the vulnerability and if threat actors are exploiting them in terms of those severity ratings.* [Gartner Analyst, Mitchell Schneider](https://securityintelligence.com/articles/cve-backlog-update-nvd-struggles-attackers-change-tactics/) # Accelerate Remediation with Minimus Source: https://docs.minimus.io/remediate/remediate Understand how Minimus images help your team keep your cloud perimeter secure with less effort With Minimus images drastically reducing the number of vulnerabilities to deal with, your risk and the effort required to mitigate it is also drastically reduced. Minimus images offer a comprehensive solution for optimizing the security of your images. With Minimus, you'll have the means to keep your stack almost entirely free of vulnerabilities for the long term thanks to the following: * **Clean Start** With Minimus, you'll start off with a pristine image with few, if any, vulnerabilities. Visit any image in our Minimus Gallery to see the risk reduction comparison data to see the benefit in hard numbers. * **Lean & Minimal** Unnecessary packages and utilities simply aren't in Minimus images so they have the smallest possible attack surface. Less bulk and less code translate into fewer packages, which in turn means that images accumulate new vulnerabilities at a slower rate. Minimus' purposeful minimalism translates into an inherent security advantage. * **Daily Updates** Minimus automatically builds every image daily whenever there are packages to update. The complete history of builds is available in the **Digest History** tab in the image version card. [Learn more](/foundations/image-version#digest-history) Collective industry experience shows that most vulnerabilities in an app originate in the "upstream". That is, many of the CVEs impacting the typical application are introduced by dependencies, runtimes, and other components they build upon. Historically, the container images available for most apps included many ancillary and supporting components beyond the app itself, expanding your susceptibility to these upstream vulnerabilities. Thus, to actually get ahead on the vulnerability treadmill, you need to both ensure the app itself and all its components are updated while also minimizing unnecessary software in your images. ## Mitigating against Vulnerabilities with Minimus Here's how vulnerabilities are managed with Minimus: * **Advisories for Affected & Fixed Images** Minimus advisories can be filtered by affected images and available fixed versions. You can use the advisories to prioritize deployment of available fixes and assess the need to implement mitigation strategies and update security controls to contain known vulnerabilities while they await a fix upstream. [Learn more](/remediate/advisories) * **Vulnerability Reports for All Versions** The version line in the image card show the current vulnerability status for every image version with the ability to drill down for details and jump to the advisory. [Learn more](/foundations/image-card) * **Version Line Changelog** Every version line has a dedicated view to help you track when fixes were released. [Learn more](/foundations/image-card#changelog) * **Actions** Create actions to trigger webhooks, GitHub Actions, and email and Slack notifications when new image versions or fixes are released. You can fine-tune your actions to trigger only for active or likely exploits or critical severity vulnerability fixes if you prefer. [Learn more](/remediate/actions) # Threat Intel Source: https://docs.minimus.io/remediate/threat-intel Use Minimus threat intel to secure your operations against exploitable vulnerabilities impacting your Minimus images and get notified of fixed versions Never miss a critical upgrade thanks to Minimus threat intelligence. While Minimus images typically have no vulnerabilities at their time of release, staying secure over time depends on upgrading to newer versions. Older versions will inevitably become less secure as new vulnerabilities are published. Minimus threat intel helps you track important upgrades so you can protect your tech stack against active and likely exploits. ## Exploitability label Security guidelines now recommend prioritizing vulnerabilities by exploitability rather than severity. Minimus uses an exploitability label to help your team prioritize the deployment of vulnerability fixes. * Vulnerabilities listed in the CISA KEV catalog are labeled as **active exploits**. * Vulnerabilities with an EPSS probability score above 60% are labeled as **likely exploits**. Advisories Likely Exploits The exploitability label appears in advisories and vulnerability reports for image versions so you can see the risk in all relevant contexts. ### Using the exploitability label The exploitability label is designed to provide a measure of urgency. Vulnerabilities listed in the CISA KEV catalog should be considered top priority. CISA KEV, unlike EPSS and CVSS metrics, deals only with confirmed risks that have gained visibility. These vulnerabilities pose immediate risk and are already actively exploited or attempted by threat actors. It is recommended to upgrade as soon as a fixed version becomes available. EPSS metrics are second only to the CISA KEV list as they provide data-driven threat intelligence. Collective experience has shown that many exploitable vulnerabilities are often ranked as medium or even low severity. Therefore it's important to prioritize upgrades that remediate vulnerabilities with a high EPSS probability over a high severity score. ## Balancing DEV capacity with security requirements Balancing DEV capacity with security requirements is a serious challenge. Minimus threat intel is designed to reduce some of this inherent tension and help improve dev velocity. Managing software security requires striking a delicate balance between frequent security updates and necessary testing. There is no blanket solution for striking this fine balance, and the recommended approach depends on the urgency of the fix and the nature of the application. The following guidelines are a good place to start: * Application images such as Nginx and Prometheus that are deployed as-is without a build or adjustments are relatively easy to test and upgrade. In such cases, we recommend upgrading to latest as soon as possible to benefit from the latest security enhancements. Minimus actions triggered by threat intel can help you stay informed of recent version releases and security patches. * Images that are used as a base layer or middle layer usually require more testing which can delay critical security upgrades in favor of stability concerns. In such cases, we recommend using Minimus threat intel to identify the most critical fixes available and to prioritize their implementation for risky assets, such as production containers or VMs which are external facing. A gradual upgrade schedule will support more rigorous testing and help to balance security and stability concerns. ## Leveraging threat intel with actions Actions can be used to notify your team when likely and confirmed exploit fixes become available so you can upgrade your images to mitigate known risks. [About actions](/remediate/actions) # Minimus Advisories Feed Source: https://docs.minimus.io/scanning/advisories-feed Understand the purpose of the Minimus Advisories Feed and how it is used to improve scanner results and prevent false positives Minimus maintains and regularly publishes security vulnerability information for MinimOS packages - the building blocks used to create Minimus Images. These security updates are published to the Minimus Advisories Feed and can be used to integrate with third-party scanners that don't natively support Minimus. This is important in order to avoid false-positive reports for Minimus Images. Without the integration, the scanner may report false-positives for packages determined to be unaffected. The current guide explains what the Minimus Advisories Feed is, where it is published, and in what formats it is available. As a next step, see [how to connect your scanner to the Minimus Advisories Feed](/scanning/scanner-integration). ## About MinimOS packages A vulnerability advisory is published per origin package, so before we can discuss the Minimus Advisories Feed, we must establish the basics about MinimOS packages. ### MinimOS distro Minimus Images are a collection of private container images hosted by the Minimus registry.\ Minimus images are built using packages built by the Minimus proprietary enterprise package repository known as MinimOS. MinimOS is a contemporary, open-source Linux distribution designed specifically to create secure and minimal container images. It doesn't provide a kernel; instead, it's a curated set of software packages intended for use on Linux environments. MinimOS packages are directly built and maintained by Minimus and frequently scanned for vulnerabilities. ### Packaging format MinimOS packages follow the [APK specification](https://wiki.alpinelinux.org/wiki/Apk_spec). Each package is distributed as an `.apk` file, with installations handled by the `apk` tool or a compatible library. A list of all installed distribution packages can be found on the filesystem at `/lib/apk/db/installed`. ## About the Minimus Advisories Feed Minimus maintains and regularly publishes security vulnerability information for MinimOS packages. ### MinimOS advisory data The Minimus security team thoroughly reviews potential vulnerabilities across packages. The findings are compiled as **advisory data**, which act as the authoritative references for vulnerability assessment. Advisory data is the foundation for producing various types of downstream data, including security feeds consumed by vulnerability scanners. Minimus publishes its advisories feed in 2 formats: * SecDB at `https://packages.mini.dev/advisories/secdb/security.json` * OSV at `https://packages.mini.dev/advisories/osv/all.json` The feeds are public and can be used to integrate with scanners as explained below. ### Update frequency Both SecDB and OSV feeds are updated promptly, often several times a day, as new vulnerability information becomes available. ## SecDB security feed SecDB is a JSON-formatted file aligned with the same schema used by Alpine Linux's security feeds. The MinimOS SecDB feed can be found at:\ `https://packages.mini.dev/advisories/secdb/security.json`. The SecDB JSON contains several properties, but the most relevant for scanners is the `packages` array. Each item describes a package with: * A `name` string (the APK origin package name). * A `secfixes` object mapping versions to the list of vulnerabilities fixed in that version. Below is an example snippet from the MinimOS SecDB. It shows the `caddy` package at version `2.8.4-r1` resolves 4 specific vulnerabilities and version `2.9.0-r0` resolves 2 other vulnerabilities: ```jsonc theme={null} { "apkurl": "{{urlprefix}}/{{reponame}}/{{arch}}/{{pkg.name}}-{{pkg.ver}}.apk", "archs": [ "x86_64", "aarch64" ], "reponame": "os", "urlprefix": "https://packages.mini.dev", "packages": [ { "pkg": { "name": "caddy", "secfixes": { "2.8.4-r1": [ "CVE-2024-45337", "CVE-2024-53259", "GHSA-px8v-pp82-rcvr", "GHSA-v778-237x-gjrc" ], "2.9.0-r0": [ "CVE-2024-45338", "GHSA-w32m-9786-jp63" ] } } }, // ... ``` The MinimOS SecDB feed is licensed under [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)](https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=chooser-v1). ## OSV security feed Minimus also offers an OSV-formatted feed as an alternative. While SecDB is specific to Alpine, OSV is a popular standard, offering richer metadata about vulnerabilities and their impact on artifacts like APKs. [Learn more about OSV](https://ossf.github.io/osv-schema/) The MinimOS OSV feed can be found at:\ `https://packages.mini.dev/advisories/osv/all.json`. The OSV feed lists IDs of advisories and their modification date, for example: ``` { "modified": "2025-02-09T14:09:18Z", "id": "MINI-xxrx-crr8-74g3" }, { "modified": "2025-04-23T06:57:04Z", "id": "MINI-xxvv-4c5g-xvr9" } ``` Each MinimOS advisory is published individually at a stable link `https://packages.mini.dev/advisories/osv/{Advisory ID}.json`. For example:\ `https://packages.mini.dev/advisories/osv/MINI-xxrx-crr8-74g3.json`. The MinimOS OSV feed is licensed under [Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)](https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=chooser-v1). ## Testing To standardize testing, Minimus provides a sample image on [Docker Hub](https://hub.docker.com/r/dimastopelmini/forgrype/tags). # Comparing Vulnerability Scanning Reports Source: https://docs.minimus.io/scanning/compare-scanner-results Understand how the Minimus vulnerability scanner report differs from other vulnerability scanners, including Grype, Trivy, etc. The primary goal and focus of Minimus vulnerability reports is the quality of the results. Minimus emphasizes the accuracy of its vulnerability reports over volume, following the conviction that quantity should not be the primary driver in vulnerability reporting. Vulnerability scanners differ in how they detect, classify, and report issues, which makes comparing results across tools tricky. Understanding the defaults each scanner uses goes a long way toward making sense of the differences. The sections below cover the key things to know when reviewing Minimus vulnerability reports. ## How many vulnerabilities impact my image? This depends on how you count vulnerabilities. There are different methods: * **Unique CVEs** - If a CVE affects more than one package in the image, you still count it as one vulnerability. * **Affected packages** - In this method, you count the number of packages affected by each CVE. This method is also known as counting findings or counting unique issues per dependency path. Minimus vulnerability reports count each unique CVE once, regardless of the number of affected packages. To be clear, the image vulnerability report in Minimus will list all affected packages, it just won't count them separately. ## Which vulnerabilities are impacting my image? This depends on how you identify vulnerabilities. There are different systems for cataloging vulnerabilities, each with their pros and cons. * **Normalizing to CVE ID** - This approach favors the CVE (Common Vulnerabilities and Exposures) database run by the MITRE Corporation. This means the report will identify vulnerabilities by their CVE ID whenever possible. The only times you might identify a vulnerability by another database, is if it was never mapped to a CVE. This method has the advantage of deduplication. * **Original data source feed** - Here vulnerabilities are identified by the original data source. For example, the Grype scanner maps language packages to a GHSA ID (GitHub Security Advisory) by default ([ref](https://oss.anchore.com/docs/guides/vulnerability/interpreting-results/#understanding-vulnerability-ids)). Minimus normalizes its vulnerability reports by CVE ID. You will still see GHSA IDs when they have not yet been mapped to a CVE. ## How can I be sure there are no false positives? This depends on your tolerance for "noise". There are competing approaches: * **Filter out unconfirmed vulnerabilities** - to minimize questionable reports * **Report all programmatic findings** - even if unconfirmed or disputed Minimus vulnerability reports filter out vulnerabilities still under review. The Minimus advisory will show the potentially affected package and the status **under review**, but it will not be mapped to an image until it has been confirmed. This approach suppresses noise and avoids unnecessary strain. ## How is severity assessed? A vulnerability NVD listing may show competing severity scores. In such cases, an "operative" score must be selected. There are different approaches: * **Preferred** - This approach adopts an internal logic for ranking scores by the CVSS version used and the reputation of the reporting CNA - CVE Numbering Authority ([ref](https://nvd.nist.gov/general/cna-counting)). This approach favors CVSS 4 scores over CVSS 3.1 and makes use of NVD's ranking of CNAs based on auditing results. The severity promoted by NVD as most reputable is adopted. * **Highest severity** - This approach ignores the priority of CVSS 4 over CVSS 3 and does not weigh in the ranking of the reporting CNA. * **NVD assigned score** - This approach strictly adheres to the score provided by NVD and disregards scores provided by other recognized CNAs and CISA-ADP scores. This approach may be attributed to FedRAMP's directive to use NVD assigned CVSS scores as the "original risk rating" ([FedRAMP Rev5 Vulnerability Scanning Requirements](https://www.fedramp.gov/docs/rev5/playbook/csp/continuous-monitoring/vulnerability-scanning/#general-scanning-requirements)). However, this approach has not been widely adopted and has the downside of registering many vulnerabilities as having unknown severity unnecessarily. Minimus advisories show the preferred severity as recommended by NVD. This approach has the advantage of suppressing noise, especially when the highest severity score is less trustworthy. ## How many packages were scanned? Minimus only counts OS-level packages (APK format) in its SBOM and vulnerability reports. Some scanners will show a higher package count because they include non-OS dependencies. This explains why the package count may not match between different scanner reports. ## Scanning by image layers Some scanners count the number of different layers a CVE affects. Minimus images are always built as a single layer, without a Dockerfile. Therefore, there should not be variations due to image layers. ## Example To help illustrate the issues, we will compare the Minimus vulnerability report to a Grype report for the same image: [reg.mini.dev/elasticsearch:9.2.0](https://images.minimus.io/images/elasticsearch/lines/9.2/versions/9.2.0/vulnerabilities) (performed January 2026). ```shellscript Grype report for reg.mini.dev/elasticsearch:9.2.0 expandable lines theme={null} docker run -it reg.mini.dev/grype reg.mini.dev/elasticsearch:9.2.0 ✔ Vulnerability DB [updated] ✔ Parsed image sha256:a9814*** ✔ Cataloged contents 2723*** ├── ✔ Packages [817 packages] ├── ✔ Executables [293 executables] ├── ✔ File metadata [2,390 locations] └── ✔ File digests [2,390 files] ✔ Scanned for vulnerabilities [60 vulnerability matches] ├── by severity: 1 critical, 6 high, 30 medium, 2 low, 0 negligible (21 unknown) NAME INSTALLED FIXED IN TYPE VULNERABILITY SEVERITY EPSS RISK libpng 1.6.50-r0 1.6.52-r0 apk CVE-2025-66293 High < 0.1% (25th) < 0.1 elasticsearch-9.2 9.2.0-r0 9.2.2-r0 apk CVE-2025-68390 Medium 0.1% (31st) < 0.1 elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.2-r0 apk CVE-2025-68390 Medium 0.1% (31st) < 0.1 log4j-core 2.19.0 2.25.3 java-archive GHSA-vc5p-v9hr-52mj Medium 0.1% (30th) < 0.1 log4j-core 2.25.0 2.25.3 java-archive GHSA-vc5p-v9hr-52mj Medium 0.1% (30th) < 0.1 reactor-netty-http 1.0.45 1.2.8 java-archive GHSA-4q2v-9p7v-3v22 Medium < 0.1% (26th) < 0.1 libpng 1.6.50-r0 1.6.51-r0 apk CVE-2025-64720 High < 0.1% (19th) < 0.1 elasticsearch-9.2 9.2.0-r0 9.2.4-r0 apk CVE-2025-67735 Medium < 0.1% (17th) < 0.1 elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.4-r0 apk CVE-2025-67735 Medium < 0.1% (17th) < 0.1 netty-codec-http 4.1.126.Final 4.1.129.Final java-archive GHSA-84h7-rjj3-6jx4 Medium < 0.1% (17th) < 0.1 zlib 1.3.1-r2 apk CVE-2026-22184 Critical < 0.1% (11th) < 0.1 busybox 1.37.0-r6 apk CVE-2025-60876 Medium < 0.1% (16th) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk CVE-2025-15224 Low < 0.1% (25th) < 0.1 libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk CVE-2025-15224 Low < 0.1% (25th) < 0.1 libpng 1.6.50-r0 1.6.51-r0 apk CVE-2025-65018 High < 0.1% (9th) < 0.1 elasticsearch-9.2 9.2.0-r0 9.2.2-r0 apk CVE-2025-37731 High < 0.1% (9th) < 0.1 elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.2-r0 apk CVE-2025-37731 High < 0.1% (9th) < 0.1 elasticsearch-9.2 9.2.0-r0 9.2.3-r0 apk CVE-2025-68384 Medium < 0.1% (12th) < 0.1 elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.3-r0 apk CVE-2025-68384 Medium < 0.1% (12th) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk CVE-2025-14819 Medium < 0.1% (9th) < 0.1 libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk CVE-2025-14819 Medium < 0.1% (9th) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk CVE-2025-14524 Medium < 0.1% (7th) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk CVE-2025-15079 Medium < 0.1% (7th) < 0.1 libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk CVE-2025-14524 Medium < 0.1% (7th) < 0.1 libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk CVE-2025-15079 Medium < 0.1% (7th) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk CVE-2025-13034 Medium < 0.1% (4th) < 0.1 libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk CVE-2025-13034 Medium < 0.1% (4th) < 0.1 glibc 2.42-r0 apk CVE-2026-0861 High < 0.1% (1st) < 0.1 commons-lang3 3.9 3.18.0 java-archive GHSA-j288-q9x7-2f5v Medium < 0.1% (2nd) < 0.1 glibc 2.42-r0 apk CVE-2026-0915 Unknown < 0.1% (3rd) < 0.1 libpng 1.6.50-r0 1.6.51-r0 apk CVE-2025-64505 Medium < 0.1% (2nd) < 0.1 libpng 1.6.50-r0 1.6.51-r0 apk CVE-2025-64506 Medium < 0.1% (2nd) < 0.1 libpng 1.6.50-r0 1.6.54-r0 apk CVE-2026-22801 Medium < 0.1% (1st) < 0.1 libpng 1.6.50-r0 1.6.54-r0 apk CVE-2026-22695 Medium < 0.1% (1st) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk CVE-2025-14017 Medium < 0.1% (0th) < 0.1 libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk CVE-2025-14017 Medium < 0.1% (0th) < 0.1 curl 8.16.0-r0 8.18.0-r0 apk GHSA-7q9p-cx8r-rh2q Unknown N/A N/A curl 8.16.0-r0 8.18.0-r0 apk GHSA-9r76-qj98-jfhc Unknown N/A N/A curl 8.16.0-r0 8.18.0-r0 apk GHSA-g897-jvjx-78vg Unknown N/A N/A curl 8.16.0-r0 8.18.0-r0 apk GHSA-hccr-q52r-4w88 Unknown N/A N/A curl 8.16.0-r0 8.18.0-r0 apk GHSA-jh4h-2cg6-889h Unknown N/A N/A curl 8.16.0-r0 8.18.0-r0 apk GHSA-vqhr-m87q-9jqh Unknown N/A N/A elasticsearch-9.2 9.2.0-r0 9.2.4-r0 apk GHSA-84h7-rjj3-6jx4 Unknown N/A N/A elasticsearch-9.2 9.2.0-r0 9.2.2-r0 apk GHSA-gphj-4h6p-37xq Unknown N/A N/A elasticsearch-9.2 9.2.0-r0 9.2.2-r0 apk GHSA-m9gh-789g-q5pv Unknown N/A N/A elasticsearch-9.2 9.2.0-r0 9.2.3-r0 apk GHSA-qf7c-7r9h-mm92 Unknown N/A N/A elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.4-r0 apk GHSA-84h7-rjj3-6jx4 Unknown N/A N/A elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.2-r0 apk GHSA-gphj-4h6p-37xq Unknown N/A N/A elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.2-r0 apk GHSA-m9gh-789g-q5pv Unknown N/A N/A elasticsearch-9.2-oci-entrypoint 9.2.0-r0 9.2.3-r0 apk GHSA-qf7c-7r9h-mm92 Unknown N/A N/A libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk GHSA-7q9p-cx8r-rh2q Unknown N/A N/A libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk GHSA-9r76-qj98-jfhc Unknown N/A N/A libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk GHSA-g897-jvjx-78vg Unknown N/A N/A libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk GHSA-hccr-q52r-4w88 Unknown N/A N/A libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk GHSA-jh4h-2cg6-889h Unknown N/A N/A libcurl-openssl4 8.16.0-r0 8.18.0-r0 apk GHSA-vqhr-m87q-9jqh Unknown N/A N/A ``` ### Package count Minimus counts 71 OS-level packages in the SBOM. Grype detects hundreds more packages because it also inspects dependency manifests and compiled artifacts. ### Unique vulnerabilities The vulnerability count is vastly different. The Minimus report counts the number of unique vulnerabilities and lists all affected packages. The Grype report counts the number of affected packages as the number of vulnerabilities. ### Vulnerabilities under review Vulnerabilities under review are not listed in the Minimus vulnerability report so as to avoid false positives. The Grype scan includes any vulnerabilities that were programmatically detected even if they have not yet been vetted. For example, CVE-2026-22184 affecting zlib was listed by Grype. The Minimus report did not list the vulnerability while it was under review. Later, the Minimus security research team determined that the CVE was a false-positive and that the package was unaffected. (See the [Minimus advisory](https://images.minimus.io/advisories/CVE-2026-22184/packages?search=22184\&filterPackage=zlib) for details.) ### Severity Minimus pulls the preferred severity from NVD. Grype, in turn, prefers the highest severity. For example, [CVE-2026-22184](https://nvd.nist.gov/vuln/detail/CVE-2026-22184) showed up as a critical vulnerability in the Grype report, but as only medium severity in the Minimus advisory. This is because the Minimus algorithm favors CVSSv4 over CVSSv3.1. CVE-2026-22184 also happens to be disputed. It was assigned a critical severity of 9.8 in CVSSv3 but only a medium severity of 4.6 in CVSSv4. [Learn more about how Minimus assesses severity in cases of conflicts](/remediate/priorities/cvss#primary-severity) ### Vulnerability IDs The Minimus report normalizes vulnerabilities by their CVE ID. In other words, where a CVE ID is available, Minimus prefers it over the GHSA ID. For example, the Grype report lists `GHSA-vc5p-v9hr-52mj`, while the Minimus report lists the same vulnerability as CVE-2025-68161. # How to Integrate with Scanners Source: https://docs.minimus.io/scanning/scanner-integration Follow the guide to integrate your scanner with the Minimus Advisories Feed when it isn't natively supported by Minimus This guide outlines the process of integrating the Minimus Advisories Feed with a vulnerability scanner that isn't natively supported by Minimus. Without the integration, the scanner may report false-positives for packages determined to be unaffected. ## Overview Connecting your vulnerability scanner to the Minimus Advisories Feed involves the following steps: 1. Confirming the image uses MinimOS as its distribution 2. Identifying all installed packages 3. Mapping each package to known vulnerabilities ## Before you begin As a first step, check if your scanner is already supported by Minimus, as the list is growing. [View the full list of supported scanners](/scanning/scanner-support) ## Step 1: Identifying the Distribution The first step is to confirm the distribution ID is `minimos`. As with many Linux distributions, distribution info is available under `/etc/os-release`. For MinimOS, a typical `/etc/os-release` file looks like this: ```text theme={null} ID=minimos NAME="MinimOS" PRETTY_NAME="MinimOS" VERSION_ID="20241031" HOME_URL="https://minimus.io" BUG_REPORT_URL="https://support.minimus.io" ``` Scanners should read the `ID` field, expecting it to be `minimos`. Other fields are not relevant. If `ID` is anything else, then the image falls outside the MinimOS scope. ### MinimOS Distro is Unversioned MinimOS is not versioned, which sets it apart from other distributions such as Ubuntu and Debian. Instead, it operates as a continuous, rolling package set. The `VERSION_ID` field doesn't impact vulnerability scanning and should not be shown as the distribution version to scanner users. Technically, `VERSION_ID` corresponds to the version of the package that installed `/etc/os-release` — usually `minimos-baselayout`. It can safely be ignored. ### Detecting the MinimOS Distro via SBOMs If a scanner supports an SBOM (software bill of materials), you can also detect MinimOS based on the distro metadata within the SBOM, provided it identifies the distro as `minimos`. ## Step 2: Identifying Installed Packages Once you've established that the distro is MinimOS, the next step is to catalog all installed distribution packages. Each package record requires: 1. Name 2. Version 3. Origin package You can parse the `/lib/apk/db/installed` database to retrieve this information. Here's an example record: ```text theme={null} P:libcrypto3 V:3.1.1-r2 A:x86_64 L:Apache-2.0 T:OpenSSL libcrypto library o:openssl ``` Where: * `P:` indicates the **package name** * `V:` provides the **package version** * `o:` points to the **origin package** ### What is an Origin Package In APK ecosystems, a package may declare an "origin" different from its "name". For MinimOS, origin packages correspond to build definitions that generate primary packages and any associated subpackages. Subpackages share the version number of their origin. [Refer to APK documentation for further information about the format](https://wiki.alpinelinux.org/wiki/Apk_spec#Installed_Database_V2). ### Detecting Packages via SBOMs If the SBOM already enumerates the installed packages along with name, version, and origin, you can trust it instead of parsing `/lib/apk/db/installed`. ## Step 3: Mapping Installed Packages to Vulnerabilities Finally, the objective is to map all installed packages to known vulnerabilities using the Minimus Advisories Feed using either format: SecDB or OSV. ### Using the SecDB Feed to Identify Vulnerable Packages Let's look at an example package. Here we have the package name, version, and origin package specified: ```json theme={null} { "name": "libcrypto3", "version": "3.1.1-r2", "origin": "openssl" }, ``` In the SecDB feed, vulnerabilities are filed under the **origin package**. For example, below is the SecDB entry for `openssl`: ```json theme={null} { "pkg": { "name": "openssl", "secfixes": { "0": ["CVE-2023-0466", "CVE-2023-4807"], "3.0.8-r0": ["CVE-2022-4203", "CVE-2022-4304"], "3.1.1-r2": ["CVE-2023-2975"], "3.1.1-r3": ["CVE-2023-3446"], "3.1.1-r4": ["CVE-2023-3817"] } } }, ``` Compare your `openssl` version to the versions listed in the SecDB advisory. If your installed version is **less than** the fixed version, then the vulnerabilities apply. In our example, the origin package is version 3.1.1-r2. According to the SecDB feed, version 3.1.1-r2 is vulnerable to CVE-2023-3446 and CVE-2023-3817. #### False Positives are Labeled as Version 0 You'll notice "fixed" versions labeled as `"0"`. This signals vulnerabilities that Minimus staff identified as false positives. These vulnerabilities were determined to not truly impact the package. Since `0` sorts lower than any real version, it allows scanners to filter these out efficiently. ### Using the OSV Feed to Identify Vulnerable Packages In OSV, packages are indexed by purl ([Package URL specification](https://github.com/package-url/purl-spec)). You can look up affected packages by matching the PURL, e.g., `pkg:apk/minimos/mysql-8.4`, and checking the `.ranges` field. For example, the OSV advisory for PURL `pkg:apk/minimos/mysql-8.4` shows that versions older than 8.4.5-r0 are vulnerable to CVE-2025-30685. ```json expandable theme={null} { "modified": "2025-04-23T06:57:04Z", "id": "MINI-xxvv-4c5g-xvr9", "upstream": [ "CVE-2025-30685", "GHSA-7whc-q564-cpc4" ], "affected": [ { "package": { "ecosystem": "MinimOS", "name": "mysql-8.4", "purl": "pkg:apk/minimos/mysql-8.4" }, "ranges": [ { "type": "ECOSYSTEM", "events": [ { "introduced": "0" }, { "fixed": "8.4.5-r0" } ] } ] }, { "package": { "ecosystem": "MinimOS", "name": "mysql-8.4-dev", "purl": "pkg:apk/minimos/mysql-8.4-dev" }, "ranges": [ { "type": "ECOSYSTEM", "events": [ { "introduced": "0" }, { "fixed": "8.4.5-r0" } ] } ] }, { "package": { "ecosystem": "MinimOS", "name": "mysql-8.4-client", "purl": "pkg:apk/minimos/mysql-8.4-client" }, "ranges": [ { "type": "ECOSYSTEM", "events": [ { "introduced": "0" }, { "fixed": "8.4.5-r0" } ] } ] }, { "package": { "ecosystem": "MinimOS", "name": "mysql-8.4-oci-entrypoint", "purl": "pkg:apk/minimos/mysql-8.4-oci-entrypoint" }, "ranges": [ { "type": "ECOSYSTEM", "events": [ { "introduced": "0" }, { "fixed": "8.4.5-r0" } ] } ] }, { "package": { "ecosystem": "MinimOS", "name": "mysql-8.4-oci-entrypoint-compat", "purl": "pkg:apk/minimos/mysql-8.4-oci-entrypoint-compat" }, "ranges": [ { "type": "ECOSYSTEM", "events": [ { "introduced": "0" }, { "fixed": "8.4.5-r0" } ] } ] } ] } ``` ## Additional options ### Import to internal vulnerability database Many scanners prefer to import secdb/OSV data into their own internal database to optimize querying. If you choose this path, we recommend that you sync the database daily or more often since Minimus updates its feeds frequently. ### Supplementing Minimus security data While Minimus data is comprehensive, you may configure your scanner to: 1. Cross-reference installed packages against NVD datasets. 2. Scan for non-distro packages (e.g., Go modules, Ruby Gems). When matching against NVD: * Identify vulnerabilities with your NVD data. * Exclude vulnerabilities known to be false positives based on Minimus data. When detecting non-distro packages: * Track file paths associated with non-distro package evidence. * Check whether these paths are managed by any distro package before treating them as independent packages. *** # Scanner Support Source: https://docs.minimus.io/scanning/scanner-support Know which scanners have built-in support for Minimus images The following vulnerability scanners natively support Minimus: * AWS (Amazon Inspector) * Black Duck * GCP * Grype * Microsoft Azure * Orca * Snyk * Trivy * Wiz ## Working with other scanners If you are using another scanner that isn't yet natively integrated with Minimus, you may be able to connect it to the Minimus Advisories Feed: * About the [Minimus Advisories Feed](/scanning/advisories-feed) * [How to connect your scanner to the Minimus Advisories Feed](/scanning/scanner-integration) # Microsoft Azure SSO Source: https://docs.minimus.io/sso/azure Configure single-sign-on (SSO) for Minimus via Azure Add single-sign-on (SSO) to Minimus in Azure, by configuring Minimus as a custom SAML app. ## Prepare the SSO form in Minimus 1. Go to **Manage** > **Users & Groups** ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Click **Configure SSO** at the top of the page to open the Minimus SSO form. Keep this form open and available in another browser tab as you configure the SAML app in Azure. 3. The form has 4 parts: 1. **Configure Minimus as a custom app in your identity provider** - You will copy these parameters from Minimus to Azure in the next steps. 1. SP Entity ID 2. Reply URL (Callback / ACS URL) 3. Relay State (optional) - If you leave the Relay State blank, users will only be able to login with SSO from the Minimus homepage. 2. **Connect Minimus to your identity provider** - You will fetch these parameters from your Azure custom app and save them to the Minimus form: 1. Login SSO URL 2. IdP Entity ID 3. Certificate 3. **SAML Attribute Mapping** - You will the fetch the Azure claim names for the following parameters and save them to the Minimus form: | Minimus Parameter | Azure Attribute Name | | :---------------- | :--------------------- | | Email | user.mail | | Full Name | user.userprincipalname | 4. **Group Mapping** is optional and can be enabled if you plan to configure user groups. [See the instructions in user groups](/manage/user-groups). ## Add Minimus as a custom app under Azure Enterprise Applications 1. The first step is to create the Minimus App in Azure and link it to your Minimus Console. Go to **Enterprise Applications** to begin. 2. Select the option **New application**. 3. In the top bar, select the option to **Create your own application**. 1. Name the application. (We'll assume the name **Minimus App** was used for the rest of this guide.) 2. Select the option to **Integrate any other application you don't find in the gallery (Non-gallery)**. 3. Click **Create**. 4. Wait for the success confirmation. It may take a minute or so. 1. Select **Set up single sign on**. Azure Set Up Sso 2. Select **SAML**. Azure Select Saml This will open the form **Set up Single Sign-On with SAML**. The form includes numbered steps. 1. Select **Edit** for **Step 1** - **Basic SAML Configuration**. Azure Edit Single Sign On 2. Copy the following from the Minimus SSO form to Azure: | To copy from Minimus form | And paste in Azure form | | :----------------------------- | :----------------------------------------- | | SP Entity ID | Identifier (Entity ID) | | Reply URL (Callback / ACS URL) | Reply URL (Assertion Consumer Service URL) | | Relay State | Relay State (Optional) | 3. **Save** the form. Azure Reply Url 1. You will be automatically navigated to the **Minimus App** overview page. 2. Copy the Azure **Microsoft Entra Identifier** to the **IdP Entity ID** in the Minimus form. Azure Entity Id 1 Copy the relevant schema to the SAML Attribute Mapping section in the Minimus SSO form as shown below. 1. Select **Edit** for **Step 2** - **Attributes & Claims**. Azure Step 2 Entities Claims 2. You will see a table of the default claims. 3. Copy the claim name for the `user.mail` and the `user.userprincipalname` to the Minimus form. | Minimus Parameter | Azure Attribute Name | | ----------------- | :--------------------- | | Email | user.mail | | Full Name | user.userprincipalname | Azure Claims Name 1. In Azure, continue to **Step 3 - SAML Certificates**. 2. Download the **Base64 Certificate**. 3. Open the certificate in notepad or another code viewer, and copy the code (including "-----BEGIN CERTIFICATE... and ...END CERTIFICATE-----"). 4. Copy the certificate to the Minimus SSO form. Azure Download Certificate 1. In Azure, continue to **Step 4 - Set up Minimus**. 2. Copy the Azure **Login URL** to the field **Login SSO URL** in the Minimus SSO form. Azure Login Url * If you aren't interested in group mapping, skip to the next step and save the SSO configuration form in Minimus. You are ready to [add SSO users in Minimus](/manage/users).   * If you want to add group mapping, follow the steps below. You have the option to either manage Azure groups by group name or group ID. The configurations are different for each.  ## Assign user/group access in Azure Grant Azure users and/or groups access to Minimus. 1. In Azure, select **Enterprise Applications**. 2. Select your **Minimus App** to open its details. 3. Select **Users and Groups** from the left menu. 4. Select **Add user/group** and follow the instructions on the page. Azure Add Users ## Manage Azure group names in Minimus The process involves a few extra steps if you plan to manage Azure group names in Minimus. These steps are not relevant if you intend to manage Azure groups by *group ID.* Skip these steps if you plan to manage direct user access or Azure group IDs. ### Enable group mapping in Minimus 1. Open the Minimus SSO form ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Enable **Step 4: Group Mapping**. 3. Select: **Azure** 4. Fill out the following Azure parameters: * **Application ID** (also shown as **Application (client) ID** depending on where you look it up in Azure) * **Client Secret** (see the next steps) 5. Save the Minimus SSO form. Minimus Form Azure Groups ### Configure API permissions 1. In Azure, search for **App Registrations**. 2. Select the enterprise application you created in the previous steps. (We assume you named it **Minimus App**). 3. Authorize your app to call APIs: Azure API Permissions 1. Select **API Permissions** from the left menu. 2. Select **Add a permission.** 3. Select **Microsoft Graph** (It will be the top option under the default tab, **Microsoft APIs**). 4. Select **Application permissions.** 5. Search for "directory" and select **Directory.Read.All.** 6. Click **add permissions** to save your changes. 4. In the same window, select **grant admin consent for Default Directory** and confirm your selection. Azure Grant Admin Consent ### Generate client secret You will need to generate a client secret and save it in the Minimus SSO form. 1. In Azure, search for **App Registrations**. 2. Select the enterprise application you created in the previous steps. (We assume you named it **Minimus App**). 3. Select **certificates & secrets** from the left menu. 4. Select **+ New client secret**. 5. Set the secret's expiration, add a description (optional), and save the secret. 6. Copy the secret's value and save it immediately in the Minimus SSO form. Once the page is refreshed the value will no longer be retrievable. If needed, you can always create a new client secret. Azure Add Client Secret ### Add Azure group names in Minimus 1. In Azure, look up your Azure groups. You can search for "groups" in the top searchbar. Azure Group Names 2. In the Minimus Groups form ([direct link](https://images.minimus.io/manage/access/groups)), add the groups by group name. ## Manage Azure group IDs in Minimus The process involves a few extra steps if you plan to manage Azure group IDs in Minimus. These steps are not relevant if you intend to manage Azure groups by *group name.* Skip these steps if you plan to manage direct user access or Azure group names. ### Add group claim 1. In Azure, search for **Enterprise Applications** 2. Select your app 3. Select **single sign on** from the left menu 4. Select **edit** in **attributes & claims** Azure Attributes Claims 1 5. Select **add a group claim**. A form will appear to the right: 1. Select the relevant groups. You can select **all groups** or another option. There are advanced options as well to filter out specific groups, etc. 2. Save your group claim. Azure Add Group Claim 6. The new group claim will be added to the list. Its format is fixed: `http://schemas.microsoft.com/ws/2008/06/identity/claims/groups` Azure Group Claim Name ### Enable group mapping in Minimus 1. Open the Minimus SSO form ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Enable **Step 4: Group Mapping**. 3. Keep the default selection: **Google / Okta / Other** 4. Paste in the Azure group mapping: ```shellscript theme={null} http://schemas.xmlsoap.org/ws/2008/06/identity/claims/groups ``` 5. Save the Minimus SSO form. Azure Groups Enabled ### Add Azure group IDs in Minimus 1. In Azure, look up your Azure groups. You can search for "groups" in the top searchbar. Azure Groups Ids 2. In the Minimus Groups form ([direct link](https://images.minimus.io/manage/access/groups)), add the groups by Azure group ID. Azure Group Ids ## Troubleshooting SSO access When copying the certificate to Minimus, make sure there is no whitespace before or after the certificate. Also, check that the expected prefix and suffix are included. ```text theme={null} -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- ``` # Google SSO Source: https://docs.minimus.io/sso/google Configure single-sign-on (SSO) for Minimus via Google Add single-sign-on (SSO) to Minimus in Google Workspace Admin Console, by configuring Minimus as a custom SAML app. ## Prepare the SSO form in Minimus 1. Go to **Manage** > **Users & Groups** ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Click **Configure SSO** at the top of the page to open the Minimus SSO form. Keep this form open and available in another browser tab as you configure the SAML app in Azure. 3. The form has 4 parts: 1. **Configure Minimus as a custom app in your identity provider** - You will copy these parameters from Minimus to Google in the next steps. 1. SP Entity ID 2. Reply URL (Callback / ACS URL) 3. Relay State (optional) - If you leave the Relay State blank, users will only be able to login with SSO from the Minimus homepage. 2. **Connect Minimus to your identity provider** - You will fetch these parameters from your Google custom app and save them to the Minimus form. 1. Login SSO URL 2. IdP Entity ID 3. Certificate 3. **SAML Attribute Mapping** - Google uses the standard AD claim formats. 1. **Email** - input `email` (in lowercase). 2. **Full name** **-** input `firstName` (Note the camel case). 4. **Group Mapping** is optional and can be enabled if you plan to configure user groups. [See the instructions in user groups](https://docs.minimus.io/manage/user-groups). ## Add Minimus as a custom app in Google 1. Login to your Google Workspace Admin Console. 2. In the left-menu, go to **Apps > Web and mobile apps** 3. Select the option **+Add app >Add custom SAML app** Add custom SAML app in Google Fill out the **App details**: 1. Name the application. (We'll assume the name **Minimus App** was used for the rest of this guide.) 2. (Optional) Add a description. 3. (Optional) Upload the Minimus logo to help your team identify the app in their app gallery. (This is not required but highly recommended.) 4. **Continue** to the next step. Copy the metadata from Google to Minimus: 1. Open the Minimus SSO form in another browser tab. You can use this [direct link](https://images.minimus.io/manage/access/users?saml=open) or navigate as follows: Go to **Manage** > **Users & Groups**. Then click **Configure SSO** at the top of the page. 2. Copy the following parameters from Google to Minimus: | Copy from Google | Paste in Minimus | | :--------------- | :--------------- | | SSO URL | Login URL | | Entity ID | IdP Entity ID | | Certificate | Certificate | You can also download the details if you prefer. Add entity ID and SSO URL in Google **Continue** to the next step. 1. Copy the following service provider details from Minimus to Google: | Minimus form | Google form | Notes | | :----------- | :---------- | -------------------------------------------------------------------------------------------------------------------------------------- | | Reply URL | ACS URL | - | | SP Entity ID | Entity ID | - | | Relay State | Start URL | Required to enable users to login via Google apps. If left blank, users will only be able to login with SSO from the Minimus homepage. | 2. **Continue** to the next step. Configure custom app in Google 1. Under **SAML Attribute mapping**, map the **Google Directory attributes** to the **Minimus app attributes**: | Google Directory Attribute | App attribute | | ----------------------------------------------- | ----------------- | | Select **Primary email** from the dropdown list | Input `email` | | Select **First name** from the dropdown list | Input `firstName` | 2. Select **Finish** to confirm the configuration. Google Saml Attribute Mapping Back in the Minimus SAML form, fill out the following under **Step 3: SAML Attribute Mapping**: | Minimus Parameter | Input to type in | | :---------------- | :--------------- | | Email | email | | Full name | fullName | If you plan to use groups, enable **Step 4: Group Mapping**. This step is optional. It is only relevant if you intend to configure [group roles](/manage/user-groups). * **Type: Google / Okta / Other** (This should already be selected by default). * **Group Mapping**: Type in `groups` to match the attribute expression from the previous step. Saml Group Configuration You are now ready to save the SSO configuration form in Minimus to complete the configuration. ## Turn on access to the Minimus App In Google Workspace, user access is turned off by default for newly-added apps. Here's how to turn it on. 1. Login to your Google Workspace Admin Console. 2. In the left-menu, go to **Apps > Web and mobile apps**. 3. Select the Minimus App from the list. 4. Expand the **User Access** window. Google Expand User Access 5. Select the state **ON for everyone**. Google On For Users 6. **Save** the changes. That's it. You're all set. Note that changes made in Google Workspace Admin Console usually take a few minutes to take effect. Wait a few minutes before testing access to your newly created Minimus app. ## Troubleshooting SSO access When copying the certificate to Minimus, make sure there is no whitespace before or after the certificate. Also, check that the expected prefix and suffix are included. ```text theme={null} -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- ``` # Keycloak SSO Source: https://docs.minimus.io/sso/keycloak Configure single-sign-on (SSO) for Minimus via Keycloak Configure Minimus as a custom SAML app in Keycloak to enable SSO for Minimus. To get started, [deploy the Minimus Keycloak image](https://images.minimus.io/images/keycloak/quick-start). ## Prepare the SSO form in Minimus 1. Go to **Manage** > **Users & Groups** ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Click **Configure SSO** at the top of the page to open the Minimus SSO form. Keep this form open and available in another browser tab as you configure the SAML app in Keycloak. 3. The form has 4 parts: 1. **Configure Minimus as a custom app in your identity provider** - You will copy these parameters from Minimus to Keycloak in the next steps. 1. SP Entity ID 2. Reply URL (Callback / ACS URL) 3. Relay State (optional) - If you leave the Relay State blank, users will only be able to log in with SSO from the Minimus homepage. 2. **Connect Minimus to your identity provider** - You will fetch these parameters from your Keycloak client and save them to the Minimus form: 1. Login SSO URL 2. IdP Entity ID 3. Certificate 3. **SAML Attribute Mapping** - You will fetch the Keycloak claim names for the following parameters and save them to the Minimus form: | Minimus Parameter | Keycloak Attribute Name | | :---------------- | :---------------------- | | Email | user.mail | | Full Name | user.userprincipalname | 4. **Group Mapping** is optional and can be enabled if you plan to configure user groups. [See the instructions in user groups](/manage/user-groups). ## Add Minimus as a client in Keycloak Create the Minimus client in Keycloak and link it to your Minimus Console. 1. Visit your Keycloak admin center. (URL example [http://address:8080/admin/master/console/](http://address:8080/admin/master/console/))  2. Select **Clients** from the left menu > Select **Create client**. 3. Fill out the form: 1. **Client type** - Change the selection to **SAML**. 2. **Client ID** - Copy & paste the value from **Minimus SP Entity ID** ([link to your Minimus form](https://images.minimus.io/manage/access/users?saml=open)). 3. Name the client and add a description (optional).  4. Select **Next** to proceed. Keycloak Create New Client 1 Configure the client: 1. Set the following as `https://images.minimus.io`: 1. **Root URL** 2. **Home URL** 3. **Valid post logout redirect URIs** 2. **Valid Redirect URI** - Set it to `https://images.minimus.io/*` 3. **IDP-Initiated SSO URL Name** - Set the name as `minimus` 4. **IDP Initiated SSO Relay State** - for example: ```json theme={null} { "tenantName": "My-Org" } ``` 5. **Master SAML Processing URL** - Set it as `https://images.minimus.io/saml/callback` 6. **Save** your changes. Keycloak Configure Client Scroll down to the section **SAML capabilities** and set the following: * **Name ID format** - Select **email** from the dropdown list * **Force name ID format** - ON * **Force POST binding** - ON Scroll down to the section **Signature and Encryption** and set the following: * **Sign documents** - ON * **Sign assertions** - ON Adjust the rest of the optional settings as relevant and save your changes. 2026 05 10 18 03 1 1 1. Navigate to the **Keys** tab 2. The section is named **Signing keys config** 3. Disable **Client signature required**. You will be asked to confirm your change 4. **Save** your changes 1. Navigate to the **Client scopes** tab in the top bar. 2. Select your Client ID in the table 1. Select **Configure a new mapper** 2. Select **User Property** 3. Fill in the mapper attributes: * **Name** - `email` * **Property** - Select `email` from the dropdown list * **Friendly Name** - Optional field * **SAML Attribute Name** - Paste in `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress` * **SAML Attribute NameFormat** - Basic 4. Save your changes Keycloak User Property 1. In the mappers table, select **Add mapper > By configuration** 2. Select **User Property** 3. Fill in the mapper attributes: * **Name** - Type in `fullName` * **Property** - Select `firstName` from the dropdown list * **SAML Attribute Name** - `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name` * **SAML Attribute NameFormat** - Basic 4. **Save** your changes User Property Keycloak Attributes 1. In the left menu, select **Realm settings**. 2. In the **General** tab, select **SAML 2.0 Identity Provider Metadata**. 3. Copy the certificate between `` and ``. Keycloak Saml Certificate 1. In your Minimus console, go to **Manage** > **Users & Groups** > **Configure SSO**. 2. Fill the following fields: * **IdP Entity ID** - `https://YOUR_KEYCLOAK_EXTERNAL_IP_OR_URL/realms/master` * **Login URL** - `https://YOUR_KEYCLOAK_EXTERNAL_IP_OR_URL/realms/master/protocol/saml` * **Certificate** - Paste the certificate you copied in the previous step. 3. Fill in the SAML Attribute Mapping fields: * **Email** - `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress` * **Full Name** - `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name` * **Group Mapping** - `groups` 4. **Save** your changes.  That's it! You should now be able to manage access to Minimus with Keycloak SSO. ## Troubleshooting SSO access When copying the certificate to Minimus, make sure there is no whitespace before or after the certificate. Also, check that the expected prefix and suffix are included. ```text theme={null} -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- ``` # Okta SSO Source: https://docs.minimus.io/sso/okta Configure single-sign-on (SSO) for Minimus via Okta Okta is a popular identity provider that supports SAML. Configure single-sign-on (SSO) to Minimus via Okta. The process is standard for configuring a custom SAML app. ## Prepare the SSO form in Minimus 1. Go to **Manage** > **Users & Groups** ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Click **Configure SSO** at the top of the page to open the Minimus SSO form. Keep this form open and available in another browser tab as you configure the SAML app in Azure. 3. The form has 4 parts: 1. **Configure Minimus as a custom app in your identity provider** - You will need to copy these parameters from Minimus to Okta in the next steps. 1. SP Entity ID 2. Reply URL (Callback / ACS URL) 3. Relay State (optional) - If you leave the Relay State blank, users will only be able to login with SSO from the Minimus homepage. 2. **Connect Minimus to your identity provider** - You will need to fetch these parameters from your Okta custom app and save them in the Minimus form. 1. Login SSO URL 2. IdP Entity ID 3. Certificate 3. **SAML Attribute Mapping** - You will configure matching attributes in both Okta and Minimus. 4. **Group Mapping** is optional and can be enabled if you plan to configure user groups. [See the instructions in user groups](https://docs.minimus.io/manage/user-groups). ## Add Minimus as a custom app in Okta 1. Login to your Okta Admin Console. 2. Create a new SAML application: 1. In the left-menu, go to **Applications > Applications**. 2. Select the option **Create App Integration**. 3. Select **SAML 2.0** as the sign-in method. 1. Fill out the **General Settings**: 1. Name the application. (We'll assume the name **Minimus App** was used for the rest of this guide.) 2. Upload the Minimus logo to help your team identify the app in their app gallery. (This is not required but highly recommended.) 3. Click **Next**. Okta Configure Saml App 1. Open the Minimus SSO form in another browser tab. You can use this [direct link](https://images.minimus.io/manage/access/users?saml=open) or navigate as follows: Go to **Manage** > **Users & Groups**. Then click **Configure SSO** at the top of the page. 2. Copy the following parameters from the Minimus app to Okta. Note that the order of the parameters is different in the apps. The fields are shown according to their order in the Okta form: | Okta Parameter | Minimus Parameter | | --------------------------- | :----------------------------- | | Single sign-on URL | Reply URL (Callback / ACS URL) | | Audience URI (SP Entity ID) | SP Entity ID | | Default RelayState | Relay State | 3. Fill out the rest of the fields in the Okta form: 1. **Name ID Format** - Select **EmailAddress** from the dropdown list. 2. **Application Username** - Select **Email** from the dropdown list. 3. **Update application username on** - Leave the default. (It should be **Create and update**). Only change the two settings explicitly mentioned above (Name ID Format and Application Username). Leave all other Okta configuration settings at their default values. Modifying advanced settings such as Assertion Signature, Response signing, or encryption settings will cause the SSO integration to fail. Still in the same Okta tab, scroll down to the section **Attribute Statements (Optional)**. 1. Select **add expression** 2. Add the following 3 expressions: | Name | Expression | | :----------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- | | email | user.profile.email | | Full Name | user.profile.firstName + user.profile.lastName | | groups | user.getGroups(group1,group2,group3) | | Replace the example `group1,group2,group3` with a comma separated list of your group names, for example, `admin,dev,qa`. | | Okta Group Expression 3. Once done, the Okta attribute statements should look like this: Okta Attribute Expressions If you do not plan to use Okta groups for role-based access control, you can skip the groups expression. However, group roles are recommended for simplifying access control. 1. Click **Next** to continue. 2. Okta will ask for your feedback now that you have configured the custom SAML app. 3. Click **Finish**. 1. In Okta, under your newly created Minimus app: 1. Switch tabs to **Sign On**. (You should be automatically navigated to this tab.) 2. Expand **More details.** 2. Copy the following parameters from Okta to Minimus. Note that the order of the parameters is different in the apps. The fields are shown according to their order in the Okta form: | Okta Parameter | Minimus Parameter | | :------------- | :---------------- | | Sign on URL | Login URL | | Issuer | IdP Entity ID | Okta Sign On Details Pn 1. Still on the same screen, download the signing certificate from Okta to Minimus. 2. Open the certificate in notepad or another code viewer, and copy the code (including \`-----BEGIN CERTIFICATE... and ...END CERTIFICATE-----\`). 3. Copy the certificate to the Minimus form. If you copy the certificate, note that it will not include the opening and closing tags:\ \ \-----BEGIN CERTIFICATE----- \-----END CERTIFICATE----- \ \ You can paste the certificate between the tags provided by the placeholder. Back in the Minimus SAML form, fill out the following under **Step 3: SAML Attribute Mapping**: | Minimus Parameter | Input to type in | | :---------------- | :--------------- | | Email | email | | Full name | fullName | If you plan to use groups, enable **Step 4: Group Mapping**. This step is optional. It is only relevant if you intend to configure [group roles](/manage/user-groups). * **Type: Google / Okta / Other** (This should already be selected by default). * **Group Mapping**: Type in `groups` to match the Okta attribute expression from a previous step. Saml Group Configuration You are now ready to save the SSO configuration form in Minimus. ## Assign access in Okta Grant Okta groups and/or users access to Minimus. 1. Login to your Okta Admin Console. 2. In the left-menu, go to **Applications > Applications**. 3. Select your **Minimus App** to open its details. 4. Select the **Assignments** tab. 5. Select **Assign > Assign to people / groups** and follow the instructions on the page. Okta Assign Users ## Troubleshooting SSO access When copying the certificate to Minimus, make sure there is no whitespace before or after the certificate. Also, check that the expected prefix and suffix are included. ```text theme={null} -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- ``` # Configure SSO (Generic Guide) Source: https://docs.minimus.io/sso/saml Configure single-sign-on (SSO) to Minimus using any SAML 2.0 identity provider This is a generic guide for configuring SSO. If you are using Google, Azure, or Okta as your identity provider, the specialized guide is recommended: * [Configure SSO with Azure](/sso/azure) * [Configure SSO with Google](/sso/google) * [Configure SSO with Okta](/sso/okta) ## Prepare the SSO form in Minimus 1. Go to **Manage** > **Users & Groups** ([direct link](https://images.minimus.io/manage/access/users?saml=open)) 2. Click **Configure SSO** at the top of the page to open the Minimus SSO form. Keep this form open and available in another browser tab as you configure the SAML app in Azure. 3. The form has 4 parts: 1. **Configure Minimus as a custom app in your identity provider** - You will copy these parameters from Minimus to your IdP in the next steps. 1. SP Entity ID 2. Reply URL (Callback / ACS URL) 3. Relay State (optional) - If you leave the Relay State blank, users will only be able to login with SSO from the Minimus homepage. 2. **Connect Minimus to your identity provider** - You will fetch these parameters from your IdP custom app and save them to the Minimus form. 1. Login SSO URL 2. IdP Entity ID 3. Certificate 3. **SAML Attribute Mapping** - You will match these parameters with the attributes defined in your IdP: 1. Email 2. Full name 3. Group Mapping 4. **Group Mapping** is optional and can be enabled if you plan to configure user groups. [See the instructions in user groups](https://docs.minimus.io/manage/user-groups). ## Add Minimus as a custom SAML app in your identity provider The first step is to create a dedicated application for Minimus in your IdP. 1. Login to the IdP Admin Console. You will need sufficient permissions to manage the SAML applications. 2. Create a new SAML application and select **SAML 2.0** as the sign-in method. 3. Name the application. (**Minimus App** is a good example.) The exact path for creating the app will depend on your provider. 1. In another browser window, open your Minimus app and go to **Manage > User Management**. Click **Configure SSO** to open the SSO form (top right corner). 2. Copy the following parameters from the Minimus app to your IdP. | Minimus Parameter | Examples of parameter naming in IdPs | | :---------------------------- | :-------------------------------------------------------------------- | | SP Entity ID | SP Entity ID, Service Provider ID, Audience URI | | Reply URL (also Callback URL) | Single sign-on URL, ACS URL, Callback URL, Service Provider Login URL | | Relay State | Default RelayState | The order of the parameters can be different in your IdP.   In this step, we copy the unique parameters from the custom app in the IdP back to the Minimus SSO form. (This is the second section in the Minimus form: **Connect Minimus to your identity provider**). Once the custom SAML app is created, it usually lists the unique parameters in a SAML section or tab. | Minimus Parameter | Examples of parameter naming in IdPs | Description | | :---------------- | :------------------------------------------------ | --------------------------------------------- | | SSO URL | Sign on URL, Identity provider Single Sign-On URL | The app-specific login URL created by the IdP | | Entity ID | Issuer, Identity Provider Issuer URL or ID | The IdP's unique identifier or issuer ID | The IdP's SAML app will usually provide several certificate options. Copy the Base64 public certificate to the certificate field in the Minimus SSO form. Open the certificate in notepad or another code viewer, and copy the code. Make sure the certificate includes the opening and closing tags. Sometimes, if you copy the certificate instead of downloading it, it may not include the opening and closing tags:\ \ \-----BEGIN CERTIFICATE----- \-----END CERTIFICATE----- \ \ If so, you can paste the certificate between the tags provided by the placeholder. Attribute mapping is necessary to ensure that the values sent from the IdP match Minimus expectations. Many identity providers use the standard schema but some have other formats (See [Okta](/sso/okta) for example). | Minimus Attribute | Standard Schema | | :---------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | | Email | [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress](http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress) | | Full Name | [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name](http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name) | You are now ready to save the SSO configuration form in Minimus. Grant IdP groups and/or users access to Minimus. Usually, you will need to add or assign users to the custom SAML app to give them access. ## Troubleshooting SSO access When copying the certificate to Minimus, make sure there is no whitespace before or after the certificate. Also, check that the expected prefix and suffix are included. ```text theme={null} -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- ``` # Status Page Source: https://docs.minimus.io/status Minimus services status page provides updates on scheduled maintenance, outages, and other service-related events. Minimus scheduled maintenance window is 01:00 - 03:00 US CT on Sundays. During these maintenance windows, some services may be unavailable or have degraded performance. **images.minimus.io is available** **reg.mini.dev is available** Last status change: 06:42 US CT, 21 July 2026 On 21 July 2026, images.minimus.io was unavailable for approximately 25 minutes, from 06:17 to 06:42 US CT. During this window, requests to the service failed or timed out. Service availability has since been fully restored, and our engineering team is investigating the root cause to prevent a recurrence. We are investigating reports of intermittent "stream timeout" errors and slow loading times on images.minimus.io due to an unusually high volume of automated traffic. Our team is actively applying mitigation measures to block this traffic and stabilize the service. On 20 July 2026, images.minimus.io was unavailable for approximately 30 minutes, from 10:22 to 10:52 US CT. During this window, requests to the service failed or timed out. Service availability has since been fully restored, and our engineering team is investigating the root cause to prevent a recurrence. Intermittent availability due to global Google Cloud Platform outage. Launch of Minimus platform and services. # Known Issues Source: https://docs.minimus.io/troubleshooting/known-issues The official listing of Minimus known issues. Thank you for your patience while we investigate and fix the issues. No known issues to report ## Resolved issues * Resolved an issue blocking Minimus actions for private images. # Common Issues Source: https://docs.minimus.io/troubleshooting/troubleshooting Troubleshoot general issues when working with Minimus ## Certificate errors (corporate proxy) If you encounter an SSL/TLS error when trying to pull the image from docker, this may be caused by a corporate proxy on your local network. Popular corporate proxies include Zscaler Secure Internet Access (ZIA), FortiGate, Prisma Access and others. Examples of common errors caused by a corporate proxy: * `x509: certificate signed by unknown authority` * `connection reset by peer` * `TLS handshake timeout` **To fix the problem**: Pull from a cloud VM that isn't impacted by firewall inspection to circumvent the issue. Updating the certificates on your local PC is generally harder because you would need to obtain the custom CA. ## Cached image is out of date **To fix the problem**: Use the `--pull` flag with the `docker build` command or `--pull always` with `docker run` to force Docker to pull the latest image digest even if the version tag is the same. To force Docker to pull the image even if an image with the same tag already exists locally: ```example docker run theme={null} docker run --pull always {image} ``` ```example docker build theme={null} docker build --pull -t {app_name}:{tag} . ``` **Explanation**: Minimus images can potentially be rebuilt every day. As a result, the same image version tag may have numerous image digests. Many times, vulnerability fixes are delivered without the image version tag changing so it's particularly important to always pull the most recent digest. See for example the [Minimus digest-history for python version 3.13.5](https://images.minimus.io/images/python/lines/3.13/versions/3.13.5/digest-history) ## Error logs not returned by grep **To fix the problem**: Add `2>&1` flag to `docker logs` command. For example: ```Example for 2>&1 flag theme={null} docker logs {container_name_or_ID} 2>&1 | grep "{search_term}" ``` **Explanation**: `2>&1` combines the standard error stream and output stream, so both are passed together to the pipe (|) and processed by `grep`. ## Package built by older compiler version The issue may be a false-positive. If the latest package version was built with the most recent compiler version available at the time, the package is up to date. Compiler updates will only trigger a package rebuild if there is an impact to the security posture - that is, if new vulnerabilities are detected in the previous compiler version. **Example**: The `mongo-tools` package is built with Go. If you run a version check it will look like this: ```bash theme={null} / $ mongodump --version mongodump version: 100.13.0 git version: 23008ff975be028544710a5da6ae749dc7e90ab7 Go version: go1.25.1 os: linux arch: amd64 compiler: gc ``` The Go version may not be the latest anymore. At the time that the `mongo-tools` package `version 100.13.0` was built, Go version `go1.25.1` was the latest available. A package build using the latest Go will be manually triggered by the Minimus team when new vulnerability fixes are available for the Go compiler. ## Failed to resolve reference If you try to pull an older image using the digest or timestamp tag and it fails, this may indicate that the image build is no longer within its retention window. The error will read `Error response from daemon: failed to resolve reference... not found`. **To fix the problem**: Pull the image version without pinning the digest or timestamp tag. For example, instead of pulling by digest using `reg.mini.dev/nginx-advanced@sha256:990126f8cc0...`, pull `reg.mini.dev/nginx-advanced:v1.28.0`. Minimus retains redundant digests for production images for 180 days. For dev images, redundant digests are retained for 30 days. [Learn more](/introduction/versions#digest-retention-policy) # Troubleshooting Image Migrations Source: https://docs.minimus.io/troubleshooting/troubleshooting-images A collection of troubleshooting resources and solutions for diverse technical issues ## Postgres ### Collation version mismatch in Postgres You may encounter Postgres warning logs about a collation version mismatch, for example: ```log theme={null} WARNING: database "xyz" has a collation version mismatch DETAIL: The database was created using collation version 2.31, but the operating system provides version 2.42. HINT: Rebuild all objects in this database that use the default collation and run ALTER DATABASE xyz REFRESH COLLATION VERSION, or build PostgreSQL with the right library version. ``` The warning indicates that the OS collation library in the image is newer than the one used when the database was created. The problem does not indicate a data corruption issue. Instead, it is a warning asking to reindex the data so it can be preserved. To fix the problem, update the collation metadata and rebuild the affected indexes: ```shellscript theme={null} ALTER DATABASE xyz REFRESH COLLATION VERSION; REINDEX DATABASE ``` The above Postgres (PostgreSQL) utility command updates the recorded version and reindexes the affected objects. Reindexing locks the database, so it’s best to run this command during a short maintenance window.