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
-
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. - 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.
- Green is not an audit. If a class of bug is not in the rule table below, it will not fail the scan.
-
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. -
Do not treat
--fixas a formatter. It applies a small set of safe manifest edits and skips Helm templates. -
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
--ci— also fail on warnings--json— print findings as JSON--fix— apply safe manifest edits (skips Helm)--ignore CODE,CODE— skip rules--report path— write a JSON report
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
| Code | When it fires |
|---|---|
BUILD_TIME_NULL_ENV | Build-time property uses ${VAR} with no default. Quarkus can silently resolve it to null at package time. |
SECRET_IN_ENV_DEFAULT | A secret key uses ${VAR:literal} — the default is the credential. |
PLAINTEXT_DB_PASSWORD | Password (or similar) is a literal in config, not an env/secret reference. |
LOCALHOST_JDBC_IN_K8S / LOCALHOST_IN_K8S | JDBC, Mongo, Redis, Kafka, or REST client URL is localhost / 127.0.0.1 (literal or default). |
TLS_VERIFICATION_DISABLED | trust-all=true or tls.verification=none. |
CORS_WILDCARD_WITH_CREDENTIALS | CORS origins include * and credentials are enabled. |
SWAGGER_IN_PROD | quarkus.swagger-ui.always-include=true (or %prod enable). |
METRICS_PORT_NOT_EXPOSED | Management interface is on a separate port that the container spec does not expose. Skipped when there are no containers. |
Warnings and info
| Code | Level | When it fires |
|---|---|---|
ENV_VAR_NOT_IN_MANIFEST | warn / info | ${VAR} is not in this repo’s YAML. Info when there is no local manifest. |
MISSING_RESOURCE_LIMITS | warn | Container has no cpu/memory requests or limits. |
MISSING_LIVENESS_PROBE / MISSING_READINESS_PROBE | warn | Quarkus already ships /q/health/*. |
HEALTH_PATH_WRONG | warn | Probe is not SmallRye Health (for example /actuator/health). |
IMAGE_MISMATCH | warn | quarkus.container-image.* does not match the manifest image. |
NATIVE_RESOURCES_PADDED | warn | Native image requesting ≥ 1Gi. |
SSL_REDIRECT_IN_POD | warn | quarkus.http.insecure-requests breaks HTTP probes behind an ingress. |
MISSING_STARTUP_PROBE | info | Native image + liveness, no startupProbe. |
HARDCODED_NODEPORT | info | Pinned 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
- If YAML exists in this repo but env is injected by another chart, ignore
ENV_VAR_NOT_IN_MANIFEST. - Build-time detection is still a prefix list, not the lock-icon catalog.
- It never talks to a cluster and does not scan running pods.