Skip to content

fix(geoserver): replace JAVA_OPTS with CATALINA_OPTS - #83

Open
mo3rfan wants to merge 2 commits into
geosolutions-it:mainfrom
mo3rfan:70_fix_javaopts
Open

fix(geoserver): replace JAVA_OPTS with CATALINA_OPTS#83
mo3rfan wants to merge 2 commits into
geosolutions-it:mainfrom
mo3rfan:70_fix_javaopts

Conversation

@mo3rfan

@mo3rfan mo3rfan commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Fixes #70
Fixes https://github.com/geosolutions-it/support/issues/6395

By overwriting what comes from the docker-geoserver image's CATALINA_OPTS, we end up with a cleaner deduplicated JAVA_OPTS in the process listing:

Tested:

Before

kubectl -n pre exec -c geoserver -it geoserver-0 -- sh -c 'ps aux | grep java'
tomcat 17 6.4 5.8 11457312 1831464 ? Sl 13:28 0:36 /opt/java/openjdk/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms4G -Xmx4G -Djava.awt.headless=true -server -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -Duser.timezone=UTC -Dorg.geotools.shapefile.datetime=true -Dorg.geotools.coverage.jaiext.enabled=true -DGEOSERVER_LOG_LOCATION=/var/geoserver/logs/geoserver-0.log -DGEOWEBCACHE_CONFIG_DIR=/var/geoserver/datadir/gwc -DGEOWEBCACHE_CACHE_DIR=/var/geoserver/datadir/gwc_cache_dir -DNETCDF_DATA_DIR=/var/geoserver/netcdf_data_dir -DGRIB_CACHE_DIR=/var/geoserver/grib_cache_dir -DGEOSERVER_CSRF_DISABLED=true -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/geoserver/memory_dumps/geoserver-0.hprof -DGEOSERVER_DATA_DIR=/var/geoserver/datadir -DGEOSERVER_AUDIT_PATH=/var/geoserver/audits -Dpod.hostname=geoserver-0 -DALLOW_ENV_PARAMETRIZATION=true -DPROXY_BASE_URL=${X-Forwarded-Proto}://${X-Forwarded-Host}/geoserver -DPROXY_BASE_URL_HEADERS=true -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dsun.io.useCanonCaches=false -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Xms2G -Xmx4G -Djava.awt.headless=true -server -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -Dorg.geotools.coverage.jaiext.enabled=true -Duser.timezone=UTC -Dorg.geotools.shapefile.datetime=true -DGEOSERVER_LOG_LOCATION=/var/geoserver/logs/geoserver.log -DGEOWEBCACHE_CONFIG_DIR=/var/geoserver/datadir/gwc -DGEOWEBCACHE_CACHE_DIR=/var/geoserver/gwc_cache_dir -DNETCDF_DATA_DIR=/var/geoserver/netcdf_data_dir -DGRIB_CACHE_DIR=/var/geoserver/grib_cache_dir -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

After

kubectl -n post exec -c geoserver -it geoserver-0 -- sh -c 'ps aux | grep java'
tomcat 17 4.1 6.3 11058932 1986692 ? Sl 13:22 0:38 /opt/java/openjdk/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dsun.io.useCanonCaches=false -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Xms4G -Xmx4G -Djava.awt.headless=true -server -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -Duser.timezone=UTC -Dorg.geotools.shapefile.datetime=true -Dorg.geotools.coverage.jaiext.enabled=true -DGEOSERVER_LOG_LOCATION=/var/geoserver/logs/geoserver-0.log -DGEOWEBCACHE_CONFIG_DIR=/var/geoserver/datadir/gwc -DGEOWEBCACHE_CACHE_DIR=/var/geoserver/datadir/gwc_cache_dir -DNETCDF_DATA_DIR=/var/geoserver/netcdf_data_dir -DGRIB_CACHE_DIR=/var/geoserver/grib_cache_dir -DGEOSERVER_CSRF_DISABLED=true -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/geoserver/memory_dumps/geoserver-0.hprof -DGEOSERVER_DATA_DIR=/var/geoserver/datadir -DGEOSERVER_AUDIT_PATH=/var/geoserver/audits -Dpod.hostname=geoserver-0 -DALLOW_ENV_PARAMETRIZATION=true -DPROXY_BASE_URL=${X-Forwarded-Proto}://${X-Forwarded-Host}/geoserver -DPROXY_BASE_URL_HEADERS=true -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

@mo3rfan mo3rfan self-assigned this Jul 28, 2026
@camuffo

camuffo commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Yes, it should work well, but loosing the OPTS from the image might be a downside if someone relies on the custom OPTS in a custom image.
I say "might" because I'm not aware of any deployment where this would really be a problem.
In any case it's potentially a breaking change.

@mo3rfan

mo3rfan commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@camuffo That is true, but the defaults in helm chart do contain all the flags from the defaults of CATALINA_OPS coming from a standard docker-geoserver image. If this was overridden to something else, they will be lost, yes

Perhaps we can have an initContainer check that stops a deployment unless the user explicitly flags it as ok:

kubectl -n post logs geoserver-0 -c compare-catalina-opts
==================================================
  CATALINA_OPTS Comparison Check
==================================================
Docker Image Default CATALINA_OPTS:
  -Xms2G -Xmx4G   -Djava.awt.headless=true -server   -Dfile.encoding=UTF8   -Djavax.servlet.request.encoding=UTF-8   -Djavax.servlet.response.encoding=UTF-8   -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:+UseG1GC   -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5      -Dorg.geotools.coverage.jaiext.enabled=true   -Duser.timezone=UTC   -Dorg.geotools.shapefile.datetime=true   -DGEOSERVER_LOG_LOCATION=/var/geoserver/logs/geoserver.log   -DGEOWEBCACHE_CONFIG_DIR=/var/geoserver/datadir/gwc   -DGEOWEBCACHE_CACHE_DIR=/var/geoserver/gwc_cache_dir   -DNETCDF_DATA_DIR=/var/geoserver/netcdf_data_dir   -DGRIB_CACHE_DIR=/var/geoserver/grib_cache_dir
--------------------------------------------------
Helm Chart Rendered CATALINA_OPTS:
  -Xms4G -Xmx4G -Djava.awt.headless=true -server -Dfile.encoding=UTF8 \
  -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -Duser.timezone=UTC -Dorg.geotools.shapefile.datetime=true \
  -Dorg.geotools.coverage.jaiext.enabled="true" -DGEOSERVER_LOG_LOCATION="/var/geoserver/logs/geoserver-0.log" -DGEOWEBCACHE_CONFIG_DIR="/var/geoserver/datadir/gwc" \
  -DGEOWEBCACHE_CACHE_DIR=/var/geoserver/datadir/gwc_cache_dir -DNETCDF_DATA_DIR=/var/geoserver/netcdf_data_dir -DGRIB_CACHE_DIR=/var/geoserver/grib_cache_dir -DGEOSERVER_CSRF_DISABLED="true" \
  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/geoserver/memory_dumps/geoserver-0.hprof -DGEOSERVER_DATA_DIR="/var/geoserver/datadir" \
  -DGEOSERVER_AUDIT_PATH="/var/geoserver/audits" -Dpod.hostname="geoserver-0" \
  -DALLOW_ENV_PARAMETRIZATION=true -DPROXY_BASE_URL='${X-Forwarded-Proto}://${X-Forwarded-Host}/geoserver' -DPROXY_BASE_URL_HEADERS='true'
==================================================
[ERROR] Mismatch detected: CATALINA_OPTS in Docker image differs from Helm chart configuration!
[ERROR] If this difference is expected/acceptable, please set initContainer.checkCatalinaOpts.failOnMismatch to false (or disable initContainer.checkCatalinaOpts.enabled).

@brynsofz

Copy link
Copy Markdown
Contributor

@mo3rfan

How about we do the migration by renaming chart-rendered JAVA_OPTS to an internal HELM_CATALINA_OPTS, then set final CATALINA_OPTS in the chart startup wrapper before exec /tmp/entrypoint.sh:

# statefulset.yaml

spec:
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          args:
            - |
              sed 's|/"$APP_LOCATION"/|/|g' /usr/local/bin/geoserver-rest-config.sh > /tmp/geoserver-rest-config.sh
              chmod +x /tmp/geoserver-rest-config.sh
              sed 's|/usr/local/bin/geoserver-rest-config.sh|/tmp/geoserver-rest-config.sh|g' /entrypoint.sh > /tmp/entrypoint.sh
              chmod +x /tmp/entrypoint.sh
+             export CATALINA_OPTS="${HELM_CATALINA_OPTS} ${CATALINA_OPTS}"
              exec /tmp/entrypoint.sh
          env:
-           - name: JAVA_OPTS
+           - name: HELM_CATALINA_OPTS
              value: "<chart-rendered JVM opts>"

This preserves current precedence: chart options first, image CATALINA_OPTS after, and geoserver_extra_opts last through the existing entrypoint. It removes chart-provided JAVA_OPTS while keeping custom image options intact. Later, we can add a switch to let chart options win without breaking existing users immediately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[gs] Some JAVA_OPTS set by chart are overridden by CATALINA_OPTS set by Dockerfile

3 participants