Add basic Prometheus/Grafana setup for local development observability
and as a starting point for building custom production monitoring.
Usage: ./pgconfig -f monitoring.yml up -d
- Grafana at http://localhost:3000 (admin/admin)
- Prometheus at http://localhost:9091 with Eureka service discovery
Includes basic dashboard showing JVM metrics, HTTP rates, service health,
and resource usage. Intentionally kept simple - users should customize for
production with alerting, persistence, security, and integration with
existing observability platforms.
Features:
- Auto-discovery of scaled replicas via Eureka
- Comprehensive monitoring guide
- Example queries and dashboard customization tips
This is a development tool and foundation, not production-ready monitoring.
Use separate bind mount directory for acceptance tests
Configure catalog-datadir bind mount path via environment variable to
isolate acceptance test data from development data.
- catalog-datadir.yml: Use ${CATALOG_DATADIR_PATH:-$PWD/catalog-datadir}
- acceptance_datadir: Use catalog-datadir_acceptance directory
- compose/.gitignore: Ignore catalog-datadir_acceptance/
This prevents acceptance tests from failing when the development datadir
contains non-empty data, while preserving development data across runs.
- Add comprehensive ImageMosaic test coverage: direct directory, manual granules,
empty store workflows, and XML-based store creation
- Fix file path handling: use direct paths instead of file:// URLs for local files
- Update documentation to mention shared mount volume at /mnt/geoserver_data
- Add version testing examples (TAG=2.27.1.0, TAG=2.26.2.0) to README
Tests pass with datadir backend but show limitations with pgconfig backend.
Provides comprehensive test coverage for realistic ImageMosaic workflows.
This commit adds support for filtering GeoTools DataAccessFactory and
GridFormatFactorySpi implementations available in GeoServer Cloud, providing
fine-grained control through YAML configuration.
Key features:
- Control which vector and raster data source formats are available through configuration
- Configuration uses user-friendly display names with placeholder resolution
- Auto-configuration runs before catalog initialization
- Vector formats filtered by deregistering DataAccessFactory instances
- Raster formats filtered using a custom FilteringFactoryCreator
- Format filtering persists even when formats are reloaded via scanForPlugins()
Configuration example:
Documentation has been added to:
- src/starters/vector-formats/README.md
- src/starters/raster-formats/README.md
- docs/configuration/index.md
This commit fixes an issue where GeoServer Cloud's LDAP authentication
was failing due to the JNDI context builder not correctly handling a
parameterized `java.naming.factory.initial` value.
- **Fixed `SimpleNamingContextBuilder` to respect a provided `INITIAL_CONTEXT_FACTORY` parameter**:
- If a JNDI environment specifies `java.naming.factory.initial`,
the builder now correctly instantiates and returns the corresponding `InitialContextFactory`.
- Previously, the builder ignored the parameter, always returning the default
`SimpleNamingContextFactory`, preventing external JNDI implementations (such as LDAP) from being used.
- Refactored logic into `createFromEnvironment()` for better readability and maintainability.
- **Enhanced tests for `SimpleNamingContextBuilder`**:
- Added a test case to verify that a custom JNDI factory (e.g., `com.sun.jndi.ldap.LdapCtxFactory`)
is instantiated when specified.
- Ensured incorrect values (e.g., non-class types, invalid class names) trigger expected exceptions.
- Refactored test class to use `@TestMethodOrder` to ensure execution order consistency.
- **Added a sample OpenLDAP service to `infra.yml`**:
- Provides a test LDAP server for validating authentication against GeoServer Cloud.
- Includes setup instructions for configuring LDAP authentication in GeoServer.
1. Run the updated GeoServer Cloud stack with the new LDAP service:
```
cd compose/
./datadir up -d
./datadir scale ldap=1
```
(or `./pgconfig` instead of `./datadir`)
2. Configure LDAP authentication in GeoServer:
- Go to **Authentication → Authentication Providers → Add new → LDAP**.
- Set **Server URL**: `ldap://ldap:389/dc=georchestra,dc=org`.
- Configure:
- **User lookup pattern**: `uid={0},ou=users`
- **Enable LDAP groups for authorization**: check
- **Enable Hierarchical groups search**: check
- **Nested group search filter**: `member={0}`
3. Save and add the new LDAP provider to the authentication chain.
4. Test authentication using:
- Username: `testadmin`, Password: `testadmin`
- Username: `testuser`, Password: `testuser`
5. Check the logs to ensure no `NotContextException` errors occur.
- Fixes LDAP authentication issues when running GeoServer Cloud with JNDI-based user authentication.
- Improves modularity and correctness of JNDI context initialization.
- Allows external authentication providers to function as expected.
Refactor the Docker Compose configurations to improve maintainability, reduce
duplication, and ensure consistent environment variable management across all services.
- **Extracted reusable volume and environment variable definitions** using YAML anchors:
- `&geoserver_environment`: Defines common environment variables for GeoServer services.
- `&geoserver_volumes`: Standardizes shared volume mounts.
- `&gs-dependencies`: Centralized service dependencies.
- **Standardized environment variables** across all services:
- Replaced repetitive `SPRING_PROFILES_ACTIVE` definitions with a shared `x-geoserver-env` anchor.
- Removed redundant service-specific `JAVA_OPTS` definitions, replacing them with `JAVA_OPTS_DEFAULT`.
- **Updated `.env` file**:
- Consolidated logging and default profile variables.
- Cleaned up and reordered variables for clarity.
- Removed unused `GATEWAY_SHARED_AUTH` and per-service `JAVA_OPTS_*` entries.
- **Refactored service definitions**:
- Applied `x-geoserver-env` to all GeoServer services.
- Applied `x-geoserver-volumes` to services requiring volume mounts.
- Applied `x-gs-dependencies` to all dependent services.
- **Improved volume handling**:
- Unified the `data_directory` and `geowebcache_data` volumes.
- Ensured volumes are correctly referenced in all catalog configurations (`datadir`, `jdbcconfig`, `pgconfig`).
- **Reduces duplication**: Less repetition in `compose.yml` files.
- **Improves maintainability**: Easier to modify environment variables and dependencies in one place.
- **Ensures consistency**: All services use the same configuration structure.
- **Enhances readability**: More structured and understandable YAML files.
This refactor does not introduce functional changes but significantly improves configuration management.
This commit updates the **catalog-datadir** development environment
to use a **Docker-managed volume** instead of a bind mount.
This improves portability, simplifies volume management, and avoids
potential permission issues when running on different environments.
---
- **Replaced `datadir` bind-mounted volume** with a **Docker-managed volume (`data_directory`)**.
- **Updated `Makefile` cleanup process**:
- Removed manual deletion of `compose/catalog-datadir/*` to prevent conflicts with Docker-managed volumes.
- Deleted the `.keep` file since the directory is now managed by Docker.
- **Updated all services (`wfs`, `wms`, `wcs`, `wps`, `rest`, `webui`, `gwc`)** to use `data_directory` instead of `datadir`.
---
✅ **Improves portability** – Works across environments without needing to manually create `catalog-datadir/`.
✅ **Fixes permission issues** – Avoids bind-mounting a directory owned by the host, which could cause write issues inside containers.
✅ **Simplifies cleanup** – No need to manually delete files; Docker handles volume persistence.
Introduce an `AccessLogFilter` to log incoming requests based on
the following configuration in `geoserver_logging.yml`, allowing
to enable/disable the access log, and define which URIs to log
when the `logging.level.org.geoserver.cloud.accesslog` logging
topic is set to different levels:
```yaml
logging:
# Control behavior of the org.geoserver.cloud.accesslog logging topic. When enabled, the request logs will include the URI's that match
# the following regular expressions at the spefified level. The defafult level is info (see logging.level.org.geoserver.cloud.accesslog below)
# Additionally, if the json-logs spring profile is enabled, the log entries will include MDC attributes configured in the logging.mdc.include.* properties bellow
accesslog:
enabled: true
# A list of java regular expressions applied to the request URL for logging at info level
# The default behavior is to log all requests to the REST API
info:
- .*\/(rest|gwc\/rest)(\/.*|\?.*)?$
# A list of java regular expressions applied to the request URL for logging at debug level
# The default behavior is to log OWS requests
debug:
- .*\/(ows|ogc|wms|wfs|wcs|wps)(\/.*|\?.*)?$
# A list of java regular expressions applied to the request URL for logging at trace level
# The default behavior is to EXCLUDE only webui's static resources and known image extensions
trace:
- ^(?!.*\/web\/wicket\/resource\/)(?!.*\.(png|jpg|jpeg|gif|svg|webp|ico)(\\?.*)?$).*$
```
For example, the following request:
```shell
curl -u admin:geoserver -X POST -H "Content-Type: application/xml" \
http://localhost:9090/geoserver/cloud/rest/workspaces \
-d '<workspace><name>testws</name></workspace>'
```
Will produce a log entry like this (except the JSON formatting, which is
added for clarity):
```json
{
"@timestamp": "2024-12-16T04:51:11.229-03:00",
"@version": "1",
"message": "POST 201 /geoserver/cloud/rest/workspaces ",
"logger_name": "org.geoserver.cloud.accesslog",
"thread_name": "http-nio-9105-exec-2",
"level": "INFO",
"level_value": 20000,
"enduser.authenticated": "true",
"application.instance.id": "restconfig-v1:192.168.86.128:9105",
"enduser.id": "admin",
"http.request.method": "POST",
"application.version": "1.10-SNAPSHOT",
"http.request.id": "01jf9sjy4ndynkd2bq7g6qx6x7",
"http.request.url": "/geoserver/cloud/rest/workspaces",
"application.name": "restconfig-v1"
}
```
* Prevent double event dispatching. Reload implies reset, avoid
sending both events on reload().
* Revert changes to GeoServerImpl (overloading of resert() and reload()
with a bolean `silent` argument). It doesn't prevent that once the
Catalog and/or the GeoServer are reloaded, while the newly loaded
objects are sync'ed to the in-memory one, CatalogInfoAdded and
ConfigInfoAdded events are sent to all pods, and these ones in turn
also do so, resulting in an explosion of events.
Instead, disable event publishing completely while reload() and
reset() are being processed:
* `CatalogApplicationEventPublisher` gets new methods:
`disable()`, `enable()`, and `enabled():boolean`.
* `GeoServerLifecycleEventPublisher.beforeReload()` sends the
`ReloadEvent` and disables event publishing while `reload()` is
processed locally.
* `GeoServerLifecycleEventPublisher.reloaded()` re-enables event
publishing.
`:z` tells Docker to label the volume for shared access among multiple containers.
Turns out to be important when there's for example a geopackage
in a shared data directory.
Add `-XX:MaxRAMPercentage=80 -XX:InitialRAMPercentage=30` to the
`DEFAULT_JAVA_TOOL_OPTIONS` env var in the base JRE docker image
as they're good defaults so people doesn't need to be figuring
it out themselves.
Saving the workspace services not working with pgconfig when
caching is enabled. `CachingGeoServerFacade` assumed there's
nothing to do when a `ServiceInfo` is added for a workspace,
but it was caching the `null` value, which is expected to save
db roundtrips.
- Add missing treatment of `ServiceInfoAdded` and `SettingInfoAdded`
to `CachingGeoServerFacade`.
- Add referential integrity for settingsinfo and serviceinfo
Now the flyway migration will add referential integrity for:
- `settingsinfo(workspace) -> workspaceindo(id)`
- `serviceinfo(workspace) -> workspaceinfo(id)`
And unique indexes for:
- `settingsinfo(workspace)`
- `serviceinfo("@type", workspace)`
As a side effect of the caching facade returning null once a
`ServiceInfo` as added, you could add multiple services of the
same kind for a workspace. The referential integrity checks will
avoid that, and the FlyWay migration will delete existing duplicates.
AppCDS (Application Class Data Sharing) is a JVM feature that allows preloading
and sharing class metadata across JVM instances. This can significantly improve
startup time and reduce memory usage, especially for large applications with
many dependencies.
This patch launches the applications during the Docker image build process for a
short period of time (until the spring context is first refreshed) to build the
AppCDS archive, and introduces an `AutoConfiguration` that:
- Allows passing a JVM argument (`-Dspring.context.exit=<event>`) to terminate
the application upon specific Spring `ApplicationContextEvent` events.
- Facilitates starting the application during Docker image builds to create the
AppCDS archive, improving startup performance.
Supported events include:
- `onPrepared`
- `onRefreshed`
- `onStarted`
- `onReady`
Note: Spring Boot 3.2+ natively supports `spring.context.exit=onRefresh` as of
[this commit](eb3982b6c2),
so this feature may not be necessary post-upgrade from Spring Boot 2.7.
Additional events are included for cases where certain applications may require
different startup stages for proper initialization. The new `offline` embedded
Spring profile should also facilitate starting without Spring Cloud Bus, ACL,
etc.