quarkus-doctor

Java CLI + Maven plugin · JDK 11+ · no Node · no cluster

Catch Quarkus config bugs that Kubernetes linters never open.

quarkus-doctor compares application.properties / application.yaml with Kubernetes, Helm, and Kustomize manifests in CI. KubeLinter, Checkov, and Trivy never read Quarkus config. Quarkus itself only fails at startup.

Guidelines

  1. Run it before the image ships. Bind the Maven goal to verify (or run the CLI in CI). The point is to fail the build, not the pod.
  2. This is not a replacement for KubeLinter or Trivy. Those tools own CIS, RBAC, and CVE scans. This tool owns Quarkus config × this repo’s YAML × JVM/native facts.
  3. Green is not an audit. If a class of bug is not in the rule table below, it will not fail the scan.
  4. GitOps in another repo is normal. When this module has no Deployment/Helm/Kustomize, missing env is info, not a warning. If YAML exists here but env is injected elsewhere, ignore ENV_VAR_NOT_IN_MANIFEST.
  5. Do not treat --fix as a formatter. It applies a small set of safe manifest edits and skips Helm templates.
  6. Secrets in Git stay in Git. ${OIDC_SECRET:the-real-value} is still a secret in history. Use a Kubernetes Secret and ${OIDC_SECRET} with no default.

Install from source

Requires JDK 11+ and Maven 3.9+. Clone the source, install once into your local .m2:

git clone https://github.com/fsmutimeer/quarkus-doctor.git
cd quarkus-doctor
mvn install

Source: github.com/fsmutimeer/quarkus-doctor. The plugin is not published to Maven Central yet.

Usage

Maven plugin (recommended)

Add this to the application pom.xml after mvn install:

<plugin>
  <groupId>io.quarkusdoctor</groupId>
  <artifactId>quarkus-doctor-maven-plugin</artifactId>
  <version>1.0.0</version>
  <executions>
    <execution>
      <phase>verify</phase>
      <goals><goal>scan</goal></goals>
    </execution>
  </executions>
</plugin>

One-shot, no binding:

mvn io.quarkusdoctor:quarkus-doctor-maven-plugin:1.0.0:scan

Options (also -Dquarkus.doctor.*): failOnError (default true), failOnWarning (default false), fix (default false), ignore. The plugin writes target/quarkus-doctor.json.

CLI

mvn -pl core -am package
java -jar core/target/quarkus-doctor-core-1.0.0.jar /path/to/quarkus-project
java -jar core/target/quarkus-doctor-core-1.0.0.jar . --ci

GitHub Action

After the repo is public, point a workflow at it. The action builds the CLI from source, then scans path.

- uses: fsmutimeer/quarkus-doctor@main
  with:
    path: .
    fail-on-warning: "false"

What it flags

Errors fail the build by default. Warnings do not, unless you pass --ci / failOnWarning.

Errors

CodeWhen it fires
BUILD_TIME_NULL_ENVBuild-time property uses ${VAR} with no default. Quarkus can silently resolve it to null at package time.
SECRET_IN_ENV_DEFAULTA secret key uses ${VAR:literal} — the default is the credential.
PLAINTEXT_DB_PASSWORDPassword (or similar) is a literal in config, not an env/secret reference.
LOCALHOST_JDBC_IN_K8S / LOCALHOST_IN_K8SJDBC, Mongo, Redis, Kafka, or REST client URL is localhost / 127.0.0.1 (literal or default).
TLS_VERIFICATION_DISABLEDtrust-all=true or tls.verification=none.
CORS_WILDCARD_WITH_CREDENTIALSCORS origins include * and credentials are enabled.
SWAGGER_IN_PRODquarkus.swagger-ui.always-include=true (or %prod enable).
METRICS_PORT_NOT_EXPOSEDManagement interface is on a separate port that the container spec does not expose. Skipped when there are no containers.

Warnings and info

CodeLevelWhen it fires
ENV_VAR_NOT_IN_MANIFESTwarn / info${VAR} is not in this repo’s YAML. Info when there is no local manifest.
MISSING_RESOURCE_LIMITSwarnContainer has no cpu/memory requests or limits.
MISSING_LIVENESS_PROBE / MISSING_READINESS_PROBEwarnQuarkus already ships /q/health/*.
HEALTH_PATH_WRONGwarnProbe is not SmallRye Health (for example /actuator/health).
IMAGE_MISMATCHwarnquarkus.container-image.* does not match the manifest image.
NATIVE_RESOURCES_PADDEDwarnNative image requesting ≥ 1Gi.
SSL_REDIRECT_IN_PODwarnquarkus.http.insecure-requests breaks HTTP probes behind an ingress.
MISSING_STARTUP_PROBEinfoNative image + liveness, no startupProbe.
HARDCODED_NODEPORTinfoPinned nodePort; common “port already allocated” on redeploy.

Build-time keys are a prefix list, not Quarkus’s official lock-icon catalog. quarkus.swagger-ui.path is not treated as build-time.

Ignoring a rule

Create .quarkus-doctor.yml in the module root:

ignore:
  - ENV_VAR_NOT_IN_MANIFEST

Same thing from the CLI or Maven: --ignore ENV_VAR_NOT_IN_MANIFEST / -Dquarkus.doctor.ignore=ENV_VAR_NOT_IN_MANIFEST.

Known limits