Skip to main content

Gravitino Server Configuration

Introduction

The Apache Gravitino server reads conf/gravitino.conf at startup. Almost every property has a default, so the server starts with an empty file, and most deployments change only a handful of them. The exception is gravitino.authorization.serviceAdmins, which you must set once you turn authorization on.

This page covers the server itself. Catalog properties, which configure an individual catalog rather than the server, are covered further down. Properties for the auxiliary services live with those services: see Iceberg REST Catalog Service and Security.

Quick Start

Development

The defaults are already right for local work. The server listens on 0.0.0.0:8090 and keeps its metadata in an embedded H2 database, so no configuration is needed:

${GRAVITINO_HOME}/bin/gravitino.sh start

One property is still worth setting. By default, H2 writes its database files to ${GRAVITINO_HOME}/data/jdbc, which is inside the unpacked distribution. Upgrading Gravitino means unpacking a new distribution, so the metadata sits in the very directory you are about to replace or abandon. Move it somewhere the upgrade does not touch:

# conf/gravitino.conf
gravitino.entity.store.relational.storagePath = /var/lib/gravitino/data/jdbc

Nothing here is authenticated. The default simple authenticator takes whatever username the client sends, the server speaks plain HTTP, and authorization is off, so every caller can do everything. Together with H2, for which Gravitino makes no consistency or durability guarantee, that makes this configuration unfit for anything but local work.

Production

A production server keeps metadata in MySQL or PostgreSQL, authenticates its callers, enforces authorization, and writes an audit log:

# conf/gravitino.conf
# Entity store
gravitino.entity.store.relational.jdbcUrl = jdbc:mysql://{db_host}:3306/{database}
gravitino.entity.store.relational.jdbcDriver = com.mysql.cj.jdbc.Driver
gravitino.entity.store.relational.jdbcUser = {username}
gravitino.entity.store.relational.jdbcPassword = {password}

# Transport
gravitino.server.webserver.enableHttps = true
gravitino.server.webserver.keyStorePath = /etc/gravitino/tls/server.jks
gravitino.server.webserver.keyStorePassword = {keystore_password}
gravitino.server.webserver.managerPassword = {manager_password}

# Authentication
gravitino.authenticators = oauth
gravitino.authenticator.oauth.jwksUri = {jwks_uri}
gravitino.authenticator.oauth.tokenValidatorClass = org.apache.gravitino.server.authentication.JwksTokenValidator
gravitino.authenticator.oauth.serviceAudience = {audience}
gravitino.authenticator.oauth.principalFields = preferred_username,email,sub

# Authorization
gravitino.authorization.enable = true
gravitino.authorization.serviceAdmins = {admin_user}

# Audit log
gravitino.audit.enabled = true

# Entity cache
gravitino.cache.enabled = true
gravitino.cache.implementation = caffeine
gravitino.cache.lockSegments = 16
gravitino.cache.enableStats = true

Only gravitino.cache.enableStats changes behavior here; it logs hit count, miss count, and load failures every five minutes, which is what makes a cache problem visible in production. The three lines above it restate defaults, and are spelled out so the cache configuration is reviewable in one place rather than inferred from its absence. Raise lockSegments above the default if the server runs hot enough for cache lock contention to show up in profiles.

Four things this block depends on:

The database schema is not created for you. Initialize it and put the JDBC driver jar in ${GRAVITINO_HOME}/libs/ before the first start. See Relational Backend Storage.

HTTPS replaces HTTP rather than joining it. A server with enableHttps set no longer serves plain HTTP, so clients and the Web UI must move to httpsPort, which defaults to 8433. See HTTPS.

The authenticator is one line, its provider is not. The block above validates JWTs against a JWKS endpoint, which is the common case for an external identity provider. Static sign keys, Kerberos, and the OIDC login flow for the Web UI each take a different set of properties. See How to Authenticate, or Local users and groups to keep users and groups in Gravitino's own metadata store instead of an external provider.

gravitino.authorization.serviceAdmins has no default. It is the one property here that Gravitino will not fill in for you, and enabling authorization without it fails at startup. What those admins and everyone else may then do is the subject of Access Control.

Give the JVM more than the 1 GB it takes by default:

export GRAVITINO_MEM="-Xms4g -Xmx4g -XX:MaxMetaspaceSize=1g"

Docker

The Gravitino image does not simply run the server against the configuration file you give it. At startup the entrypoint rewrites conf/gravitino.conf, applying its own defaults over roughly two dozen properties and then applying any supported environment variables. Configure the container through environment variables:

docker run --rm -d \
-p 8090:8090 \
-e GRAVITINO_ENTITY_STORE_RELATIONAL_JDBC_URL="jdbc:postgresql://{db_host}:5432/{database}" \
-e GRAVITINO_ENTITY_STORE_RELATIONAL_JDBC_DRIVER="org.postgresql.Driver" \
apache/gravitino:{tag}

To supply a configuration file instead, for example from a Kubernetes ConfigMap, disable the rewrite with SKIP_CONFIG_REWRITE=true. See Container Configuration for what the rewrite does and which variables it recognizes.

Running More Than One Server

Servers behind a load balancer share the entity store but keep local caches. Each server polls the entity change log and invalidates entries that another server has modified. The defaults are safe: a three second poll, and a server that cannot keep its caches current exits rather than serving metadata it knows to be stale. Point the load balancer's health check at GET /health/ready so a server that has lost its database stops receiving traffic.

Server Configuration

Every property in this section belongs in ${GRAVITINO_HOME}/conf/gravitino.conf, one property = value pair per line. The server reads the file once, at startup, so a change takes effect on the next restart. A Default Value of (empty) means the property exists with an empty string or list; (none) means it has no default at all.

Serving Requests

HTTP Server

Configuration ItemDescriptionDefault Value
gravitino.server.webserver.hostThe address the server binds to.0.0.0.0
gravitino.server.webserver.httpPortThe port the server listens on.8090
gravitino.server.webserver.minThreadsMinimum threads in the Jetty thread pool. Values below 8 are raised to 8.Twice the processor count, 8 to 100
gravitino.server.webserver.maxThreadsMaximum threads in the Jetty thread pool. Values below 8 are raised to 8, and the value must be at least minThreads.Four times the processor count, min 400
gravitino.server.webserver.threadPoolWorkQueueSizeSize of the Jetty thread pool work queue.100
gravitino.server.webserver.idleTimeoutTimeout in milliseconds for idle connections.30000
gravitino.server.webserver.stopTimeoutTime in milliseconds Jetty waits for a graceful shutdown. See org.eclipse.jetty.server.Server#setStopTimeout.30000
gravitino.server.shutdown.timeoutTime in milliseconds for the Gravitino server itself to shut down gracefully.3000
gravitino.server.webserver.requestHeaderSizeMaximum size in bytes of an HTTP request header.131072
gravitino.server.webserver.responseHeaderSizeMaximum size in bytes of an HTTP response header.131072
gravitino.server.webserver.customFiltersComma-separated list of servlet filter class names to apply to the API.(empty)
gravitino.server.rest.extensionPackagesComma-separated list of packages to scan for additional REST resources.(empty)
gravitino.server.visibleConfigsComma-separated list of extra properties to expose on the unauthenticated GET /configs endpoint, on top of the fixed set it always returns. Additive, so each entry widens what is public.(empty)

Filters named in customFilters must be standard javax.servlet filters. Pass parameters to a filter with properties of the form gravitino.server.webserver.{filter_class_name}.param.{param_name} = {value}.

GET /configs backs the Web UI, so it answers without authentication and always returns gravitino.authenticators, gravitino.authorization.enable, and gravitino.schema.separator. It adds gravitino.authorization.serviceAdmins when authorization is on, and the OAuth client settings when oauth is among the authenticators. Treat anything you add through visibleConfigs as public.

Two further groups of gravitino.server.webserver.* properties are documented elsewhere, because they belong to features rather than to the web server itself. TLS, key stores, trust stores, and client certificate authentication are in HTTPS. The CORS filter and its allowed origins, methods, and headers, needed when a browser client runs on a different origin than the server, are in CORS.

Schema Names

Catalogs that support hierarchical schemas expose the hierarchy as a single delimited name at the API boundary. Internally the levels are stored with ASCII-1 as the physical separator, so the configured separator is an external representation only, and it may be neither blank, nor ., nor ASCII-1.

Configuration ItemDescriptionDefault Value
gravitino.schema.separatorSeparator representing a multi-level schema name at the API boundary, as in A:B:C. See Hierarchical schema.:

Health Check Endpoints

Gravitino exposes three health endpoints following MicroProfile Health semantics. All of them are exempt from authentication, so Kubernetes probes, load balancers, and traffic managers reach them without credentials.

EndpointRoot AliasDescriptionHTTP Status
GET /api/health/liveGET /health/liveLiveness. Returns 200 as long as an HTTP server thread can respond. Use it to decide whether to restart a pod.200
GET /api/health/readyGET /health/readyReadiness. Returns 200 when the entity store answers within the probe timeout, 503 when it is unavailable or slow. Use it to route traffic.200 or 503
GET /api/healthGET /healthAggregate. Returns 200 when both of the above pass. Also aliased as GET /health.html.200 or 503
Configuration ItemDescriptionDefault Value
gravitino.server.health.entityStore.probeTimeoutMsTimeout in milliseconds for the entity store probe behind /ready.2000

Every endpoint returns the same JSON shape, but not the same checks. code is always 0, status is UP or DOWN, and checks carries one entry per component probed. /live reports httpServer alone, /ready reports entityStore alone, and the aggregate endpoint reports both:

{
"code": 0,
"status": "DOWN",
"checks": [
{ "name": "httpServer", "status": "UP", "details": {} },
{ "name": "entityStore", "status": "DOWN", "details": { "reason": "timeout" } }
]
}

A failing entityStore check reports timeout, interrupted, probe-rejected, entity store not initialized, or the simple class name of an unexpected exception.

JVM Memory

GRAVITINO_MEM sets the heap and metaspace flags. The launch scripts append it to JAVA_OPTS, and the Iceberg REST server and Lance REST server launchers read the same variable. Set it in conf/gravitino-env.sh or in the environment before starting the server.

The default, from bin/common.sh, is -Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=512m. Raise it in line with catalog count, plugin count, and query concurrency: -Xms4g -Xmx4g -XX:MaxMetaspaceSize=1g suits a moderate production server, and larger deployments go beyond that.

Metrics

Configuration ItemDescriptionDefault Value
gravitino.metrics.timeSlidingWindowSecsWidth in seconds of the metrics time sliding window.60

Storing Metadata

Storage Backend

Gravitino stores metadata over JDBC. H2 is the default because it is embedded and needs nothing external, which makes it right for local development and wrong for anything else: Gravitino makes no consistency or durability guarantee for metadata held in H2. Production deployments use MySQL or PostgreSQL, and the setup procedure for both is in Relational Backend Storage.

The driver, user, and password properties are required whenever the URL is not jdbc:h2.

Configuration ItemDescriptionDefault Value
gravitino.entity.storeEntity storage implementation. relational is the only supported value.relational
gravitino.entity.store.relationalRelational storage implementation. JDBCBackend is the only supported value, and it covers H2, MySQL, and PostgreSQL.JDBCBackend
gravitino.entity.store.relational.jdbcUrlDatabase URL the backend connects to.jdbc:h2
gravitino.entity.store.relational.jdbcDriverDriver class name. Place the driver jar in ${GRAVITINO_HOME}/libs/.org.h2.Driver
gravitino.entity.store.relational.jdbcUserDatabase username.gravitino
gravitino.entity.store.relational.jdbcPasswordDatabase password.gravitino
gravitino.entity.store.relational.storagePathWhere embedded H2 keeps its files. A relative value resolves against ${GRAVITINO_HOME}. The default sits inside the deployment directory, so an upgrade that replaces that directory discards the data. Change it.${GRAVITINO_HOME}/data/jdbc
gravitino.entity.store.relational.maxConnectionsMaximum size of the JDBC connection pool.100
gravitino.entity.store.relational.maxWaitMillisMaximum wait in milliseconds for a connection from the pool.1000
gravitino.entity.store.maxTransactionSkewTimeMsMaximum transaction skew in milliseconds.2000
gravitino.entity.store.deleteAfterTimeMsHow long in milliseconds deleted and superseded rows are kept. Accepts 10 minutes to 30 days.604800000 (7 days)
gravitino.entity.store.versionRetentionCountNumber of entity versions kept, including the current one. Accepts 1 to 10.1

Caching

The server caches entities in memory to avoid reading the backend on every request. Caching is on by default, and the properties below tune what it holds and how it evicts.

Configuration ItemDescriptionDefault Value
gravitino.cache.enabledWhether to cache entities at all.true
gravitino.cache.implementationCache implementation. Use the short name, not a fully qualified class name.caffeine
gravitino.cache.maxEntriesMaximum number of cached entries. Ignored when enableWeigher is true.10000
gravitino.cache.expireTimeInMsTime to live in milliseconds, measured from entry creation.3600000 (1 hour)
gravitino.cache.enableWeigherWhether to evict by weight rather than by entry count.true
gravitino.cache.enableStatsWhether to log hit count, miss count, and load failures every five minutes at INFO.false
gravitino.cache.lockSegmentsNumber of lock segments used to reduce contention.16

Two eviction limits apply at once. Time to live always applies: an entry older than expireTimeInMs expires and is cleaned up asynchronously. Alongside it, the cache bounds its size either by count or by weight. With enableWeigher disabled, Caffeine's W-TinyLFU policy evicts the least-used entries once maxEntries is reached. With enableWeigher enabled, each entity type carries a weight, larger for entities higher in the hierarchy, and eviction targets a total weight budget instead; maxEntries is ignored, and a single entry heavier than the whole budget is never cached.

Change Log Propagation

Caches are local to each server, so a metalake modified on one server would otherwise stay stale on its neighbors. Every server writes its changes to an entity change log table and polls that table to invalidate what other servers have touched. A separate cleaner trims old rows.

Configuration ItemDescriptionDefault Value
gravitino.entityChangeLog.pollIntervalSecsInterval in seconds between polls. Must be positive.3
gravitino.entityChangeLog.listenerMaxRetriesTimes a batch is retried for a failing listener before listenerFailureAction applies. Must be non-negative.10
gravitino.entityChangeLog.listenerFailureActionWhat happens when a listener exhausts its retries. EXIT stops the server, on the grounds that its caches are known stale; SKIP drops the batch and keeps serving.EXIT
gravitino.entityChangeLog.retentionSecsHow long in seconds change log rows are kept, measured by database time. 0 disables cleanup; otherwise use at least ten times pollIntervalSecs.2592000 (30 days)
gravitino.entityChangeLog.cleanupIntervalSecsInterval in seconds between cleaner runs. Must be positive.86400 (1 day)

Tree Lock

Gravitino serializes conflicting metadata operations with an in-memory tree lock. It is the only lock implementation available, and it is per-server.

Configuration ItemDescriptionDefault Value
gravitino.lock.maxNodesMaximum tree lock nodes held in memory.100000
gravitino.lock.minNodesMinimum tree lock nodes held in memory.1000
gravitino.lock.cleanIntervalInSecsInterval in seconds for reclaiming stale lock nodes.60

Loading Catalogs

These properties govern how the server loads and isolates catalogs. The properties that configure an individual catalog are covered under Catalog Properties.

credential.backfillToProperties below is the escape hatch for connectors that cannot consume vended credentials; the mechanism it opts out of is described in Credential Vending.

Configuration ItemDescriptionDefault Value
gravitino.catalog.cache.evictionIntervalMsInterval in milliseconds before an idle catalog is evicted from the catalog cache.3600000
gravitino.catalog.classloader.isolatedWhether to load each catalog's libraries and configuration in an isolated classloader rather than the application classloader.true
gravitino.catalog.classloader.sharing.enabledWhether catalogs whose isolation-relevant properties match may share one classloader. Sharing reduces Metaspace usage; disabling it gives every catalog its own.true
gravitino.catalog.credential.backfillToPropertiesWhether to return hidden catalog credentials such as jdbc-user and jdbc-password in the catalog properties response, for connectors that cannot consume vended credentials. Anyone who can read catalog properties can then read those credentials. Turn it off once your connectors are upgraded.false

Securing the Server

Authentication

Authentication decides who a caller is. It is off by default: an unconfigured server trusts whatever username the client sends.

Configuration ItemDescriptionDefault Value
gravitino.authenticatorsComma-separated authenticators to enable. Valid values are simple, oauth, kerberos, basic, and none.simple

Naming an authenticator is one line; configuring it is not. Each value reads its own family of gravitino.authenticator.* properties, covered in How to Authenticate. To hold users, password hashes, and group membership in Gravitino's own relational store rather than an external provider, see Local users and groups.

gravitino.authenticator, in the singular, is a deprecated spelling that still works.

Authorization

Authorization decides what an authenticated caller may do. It is also off by default, and turning it on requires naming the service admins, since that property has no default of its own.

Configuration ItemDescriptionDefault Value
gravitino.authorization.enableWhether to enforce privileges on metadata operations.false
gravitino.authorization.serviceAdminsComma-separated users who administer the service. Metalake creation is restricted to them.(none)
gravitino.authorization.implAuthorizer implementation.org.apache.gravitino.server.authorization.jcasbin.JcasbinAuthorizer
gravitino.authorization.threadPoolSizeThreads serving authorization checks.100

The privilege model these properties switch on, roles, grants, ownership, and the gravitino.authorization.jcasbin.* tuning of the default authorizer, is described in Access Control. To push enforcement down into the underlying systems through Apache Ranger or a native permission model, see Authorization Pushdown.

Remote File Fetching

The server fetches files by URI in two situations: staging a job's files, and loading catalog files such as a Kerberos keytab. Both accept remote URIs, so both are a path by which a caller who can create a catalog or submit a job could make the server issue requests of its own.

Configuration ItemDescriptionDefault Value
gravitino.fetchFile.blockUnsafeRemoteUriWhether to refuse remote URIs that resolve to unsafe addresses. Disable only for trusted URIs that need them.true

Audit Logging

The audit log framework has two halves. A formatter turns an Event into an AuditLog, and a writer puts that AuditLog somewhere. Both are interfaces, so a deployment with its own log pipeline can replace either.

Configuration ItemDescriptionDefault Value
gravitino.audit.enabledWhether to write an audit log.false
gravitino.audit.formatter.classNameFormatter class name.org.apache.gravitino.audit.v2.SimpleFormatterV2
gravitino.audit.writer.classNameWriter class name.org.apache.gravitino.audit.FileAuditWriter

SimpleFormatterV2 is the default formatter. JsonAuditFormatter is available where structured output is wanted: it emits one JSON object per line, serializes customInfo, and writes timestamps as ISO 8601 with millisecond precision and a zone offset. Both formatters replace the value of a sensitive customInfo key with ***. The masked keys are authorization, cookie, x-amz-security-token, s3.access-key-id, and jdbc-password.

FileAuditWriter is the default writer, and it manages no files itself. Rotation, compression, and retention are delegated to Log4j2 through a logger named gravitino.audit, configured by the audit_file appender group in conf/log4j2.properties. Out of the box it writes gravitino_audit.log under the log directory, rotates daily and at 256 MB, gzips what it rotates, and deletes anything older than 30 days. Change the path or the retention there:

# conf/log4j2.properties
appender.audit_file.fileName = /var/log/gravitino/my_audit.log
appender.audit_file.filePattern = /var/log/gravitino/my_audit_%d{yyyyMMdd}.%i.log.gz

appender.audit_file.strategy.delete.ifAll.ifLastModified.age = 90d

Earlier releases configured the writer directly through gravitino.audit.writer.file.*. Those properties now do nothing, and FileAuditWriter logs a warning at startup if it finds any of them.

Removed PropertyConfigure Instead In conf/log4j2.properties
gravitino.audit.writer.file.fileNameappender.audit_file.fileName
gravitino.audit.writer.file.appendappender.audit_file.append
gravitino.audit.writer.file.flushIntervalSecsimmediateFlush on the appender, or wrap it in an async appender

Extending the Server

Event Listeners

An event listener receives the events Gravitino emits around metadata operations, which is how external systems observe the catalog without polling it. To use one, implement EventListenerPlugin, put the jar on the server classpath, and name it in gravitino.conf.

Configuration ItemDescriptionDefault Value
gravitino.eventListener.namesComma-separated listener names, as in audit,sync.(empty)
gravitino.eventListener.{name}.classClass name of the listener registered under {name}.(none)
gravitino.eventListener.{name}.{key}Any other property under a listener's name is passed through to that plugin unchanged.(none)

Every name in names needs a matching {name}.class, or the server fails to build that listener.

Each operation emits up to three events: a pre-event before it runs, a post-event after it succeeds, and a failure event after it throws. The names follow the operation, so createTable produces CreateTablePreEvent, CreateTableEvent, and CreateTableFailureEvent. Operations served by the Gravitino IRC endpoint carry an Iceberg prefix, as in IcebergCreateTableEvent. Not every operation defines all three. The full set of classes lives in the org.apache.gravitino.listener.api.event package.

Throwing a ForbiddenException from a pre-event handler stops the operation before it runs, which makes pre-events a veto point rather than a notification.

A plugin declares how its events are dispatched:

ModeBehavior
SYNCProcessed inline, before the operation's result reaches the client. A slow listener slows the request.
ASYNC_SHAREDProcessed on a queue and dispatcher shared with other listeners. One slow listener degrades the rest, and events can be dropped.
ASYNC_ISOLATEDProcessed on a queue and dispatcher of its own. Better isolation, at the cost of a queue and thread per listener.

Auxiliary Services

An auxiliary service runs inside the Gravitino server process on its own port. The property has no default, but the gravitino.conf shipped in the distribution sets it to iceberg-rest,lance-rest, so both start unless you change the line.

Configuration ItemDescriptionDefault Value
gravitino.auxService.namesComma-separated auxiliary services to start. iceberg-rest is the Gravitino IRC server, lance-rest the Lance REST server.(empty)

The rest of the IRC configuration, and the gravitino.lance-rest.* properties of the Lance REST server, are documented with those services. See Iceberg REST Catalog Service.

Jobs

Configuration ItemDescriptionDefault Value
gravitino.job.executorExecutor that runs jobs. Implement your own and name it here to replace the built-in one.local
gravitino.job.stagingDirDirectory holding staging files for running jobs./tmp/gravitino/jobs/staging
gravitino.job.stagingDirKeepTimeInMsHow long in milliseconds a finished job's staging files are kept. Use at least 10 minutes outside testing.604800000 (7 days)
gravitino.job.statusPullIntervalInMsInterval in milliseconds between job status polls. Use at least 1 minute outside testing.300000 (5 minutes)

Catalog Properties

Catalog properties configure one catalog rather than the server. They come from two places: a catalog configuration file supplies defaults for every catalog of that provider, and the properties field on a create-catalog request supplies values for that catalog alone. The request wins. Neither affects schema or table properties.

A catalog property is one of three kinds. Gravitino defines some itself, as the settings a catalog needs to work. Anything prefixed gravitino.bypass. passes straight through to the underlying system untouched. Anything else Gravitino simply stores for you to use as you like.

Passing credentials, tokens, or access keys through gravitino.bypass. exposes them: bypassed properties are not managed by Gravitino and can come back in plaintext from the REST API. Where an underlying system leaves no alternative, restrict access to the catalog APIs accordingly.

These properties apply to every catalog:

Configuration ItemDescriptionDefault Value
packagePath to the catalog package, from which Gravitino loads the catalog's libraries and configuration. It holds a conf directory and a libs directory.(none)
cloud.nameCloud the catalog runs on. One of aws, azure, gcp, on_premise, or other.(none)
cloud.region-codeRegion code within that cloud.(none)

Everything else is per provider. The server adds each configuration directory below to the classpath automatically, which is also where provider-specific files such as hdfs-site.xml go.

Catalog ProviderCatalog PropertiesConfiguration File Path
hiveHive catalog propertiescatalogs/hive/conf/hive.conf
glueAWS Glue catalog propertiescatalogs/glue/conf/glue.conf
lakehouse-icebergLakehouse Iceberg catalog propertiescatalogs/lakehouse-iceberg/conf/lakehouse-iceberg.conf
lakehouse-paimonLakehouse Paimon catalog propertiescatalogs/lakehouse-paimon/conf/lakehouse-paimon.conf
lakehouse-hudiLakehouse Hudi catalog propertiescatalogs/lakehouse-hudi/conf/lakehouse-hudi.conf
lakehouse-genericLakehouse Generic catalog propertiescatalogs/lakehouse-generic/conf/lakehouse-generic.conf
jdbc-mysqlMySQL catalog propertiescatalogs/jdbc-mysql/conf/jdbc-mysql.conf
jdbc-postgresqlPostgreSQL catalog propertiescatalogs/jdbc-postgresql/conf/jdbc-postgresql.conf
jdbc-dorisDoris catalog propertiescatalogs/jdbc-doris/conf/jdbc-doris.conf
jdbc-starrocksStarRocks catalog propertiescatalogs/jdbc-starrocks/conf/jdbc-starrocks.conf
jdbc-clickhouseClickHouse catalog propertiescatalogs/jdbc-clickhouse/conf/jdbc-clickhouse.conf
jdbc-hologresHologres catalog propertiescatalogs/jdbc-hologres/conf/jdbc-hologres.conf
jdbc-oceanbaseOceanBase catalog propertiescatalogs/jdbc-oceanbase/conf/jdbc-oceanbase.conf
kafkaKafka catalog propertiescatalogs/kafka/conf/kafka.conf
filesetFileset catalog propertiescatalogs/fileset/conf/fileset.conf
modelModel catalog propertiescatalogs/model/conf/model.conf

‡ Contributed catalogs, shipped only in the -all distribution package. The standard package does not contain their directories.

Container Configuration

docker run --rm -d -p 8090:8090 apache/gravitino:{tag}

How the Container Builds Its Configuration

The container entrypoint rewrites conf/gravitino.conf before the JVM starts. It works in two passes. First it writes its own defaults, unconditionally, over every property it knows a default for, discarding whatever the file said. Then it applies each supported environment variable that is set. The result is written back over the original file.

Two consequences worth internalizing. A property you baked into conf/gravitino.conf survives only if the container has no default for it, so a value like a custom httpPort in a mounted file is silently replaced. And the container's defaults are not the server's defaults: the container pins minThreads to 24 and maxThreads to 200, where a server started outside a container computes both from the processor count.

Set SKIP_CONFIG_REWRITE=true to disable both passes and run the configuration file exactly as written. Use this when the file comes from a Kubernetes ConfigMap.

Supported Environment Variables

The entrypoint recognizes the variables below and ignores every other GRAVITINO_ variable. The Container Default column gives the value the first pass writes when the variable is unset; (none) means the property is left alone.

Environment VariableConfiguration KeyContainer Default
GRAVITINO_SERVER_SHUTDOWN_TIMEOUTgravitino.server.shutdown.timeout3000
GRAVITINO_SERVER_WEBSERVER_HOSTgravitino.server.webserver.host0.0.0.0
GRAVITINO_SERVER_WEBSERVER_HTTP_PORTgravitino.server.webserver.httpPort8090
GRAVITINO_SERVER_WEBSERVER_MIN_THREADSgravitino.server.webserver.minThreads24
GRAVITINO_SERVER_WEBSERVER_MAX_THREADSgravitino.server.webserver.maxThreads200
GRAVITINO_SERVER_WEBSERVER_STOP_TIMEOUTgravitino.server.webserver.stopTimeout30000
GRAVITINO_SERVER_WEBSERVER_IDLE_TIMEOUTgravitino.server.webserver.idleTimeout30000
GRAVITINO_SERVER_WEBSERVER_THREAD_POOL_WORK_QUEUE_SIZEgravitino.server.webserver.threadPoolWorkQueueSize100
GRAVITINO_SERVER_WEBSERVER_REQUEST_HEADER_SIZEgravitino.server.webserver.requestHeaderSize131072
GRAVITINO_SERVER_WEBSERVER_RESPONSE_HEADER_SIZEgravitino.server.webserver.responseHeaderSize131072
GRAVITINO_ENTITY_STOREgravitino.entity.storerelational
GRAVITINO_ENTITY_STORE_RELATIONALgravitino.entity.store.relationalJDBCBackend
GRAVITINO_ENTITY_STORE_RELATIONAL_JDBC_URLgravitino.entity.store.relational.jdbcUrljdbc:h2
GRAVITINO_ENTITY_STORE_RELATIONAL_JDBC_DRIVERgravitino.entity.store.relational.jdbcDriverorg.h2.Driver
GRAVITINO_ENTITY_STORE_RELATIONAL_JDBC_USERgravitino.entity.store.relational.jdbcUsergravitino
GRAVITINO_ENTITY_STORE_RELATIONAL_JDBC_PASSWORDgravitino.entity.store.relational.jdbcPasswordgravitino
GRAVITINO_CATALOG_CACHE_EVICTION_INTERVAL_MSgravitino.catalog.cache.evictionIntervalMs3600000
GRAVITINO_AUTHORIZATION_ENABLEgravitino.authorization.enablefalse
GRAVITINO_AUTHORIZATION_SERVICE_ADMINSgravitino.authorization.serviceAdminsanonymous
GRAVITINO_AUX_SERVICE_NAMESgravitino.auxService.namesiceberg-rest
GRAVITINO_ICEBERG_REST_HOSTgravitino.iceberg-rest.host0.0.0.0
GRAVITINO_ICEBERG_REST_HTTP_PORTgravitino.iceberg-rest.httpPort9001
GRAVITINO_ICEBERG_REST_URIgravitino.iceberg-rest.uri(none)
GRAVITINO_ICEBERG_REST_CLASSPATHgravitino.iceberg-rest.classpathiceberg-rest-server/libs, iceberg-rest-server/conf
GRAVITINO_ICEBERG_REST_IO_IMPLgravitino.iceberg-rest.io-impl(none)
GRAVITINO_ICEBERG_REST_CATALOG_BACKENDgravitino.iceberg-rest.catalog-backendmemory
GRAVITINO_ICEBERG_REST_JDBC_DRIVERgravitino.iceberg-rest.jdbc-driver(none)
GRAVITINO_ICEBERG_REST_JDBC_USERgravitino.iceberg-rest.jdbc-user(none)
GRAVITINO_ICEBERG_REST_JDBC_PASSWORDgravitino.iceberg-rest.jdbc-password(none)
GRAVITINO_ICEBERG_REST_WAREHOUSEgravitino.iceberg-rest.warehouse/tmp/
GRAVITINO_ICEBERG_REST_CREDENTIAL_PROVIDERSgravitino.iceberg-rest.credential-providers(none)
GRAVITINO_ICEBERG_REST_GCS_SERVICE_ACCOUNT_FILEgravitino.iceberg-rest.gcs-service-account-file(none)
GRAVITINO_ICEBERG_REST_S3_ACCESS_KEYgravitino.iceberg-rest.s3-access-key-id(none)
GRAVITINO_ICEBERG_REST_S3_SECRET_KEYgravitino.iceberg-rest.s3-secret-access-key(none)
GRAVITINO_ICEBERG_REST_S3_ENDPOINTgravitino.iceberg-rest.s3-endpoint(none)
GRAVITINO_ICEBERG_REST_S3_REGIONgravitino.iceberg-rest.s3-region(none)
GRAVITINO_ICEBERG_REST_S3_PATH_STYLE_ACCESSgravitino.iceberg-rest.s3-path-style-access(none)
GRAVITINO_ICEBERG_REST_S3_ROLE_ARNgravitino.iceberg-rest.s3-role-arn(none)
GRAVITINO_ICEBERG_REST_S3_EXTERNAL_IDgravitino.iceberg-rest.s3-external-id(none)
GRAVITINO_ICEBERG_REST_S3_TOKEN_SERVICE_ENDPOINTgravitino.iceberg-rest.s3-token-service-endpoint(none)
GRAVITINO_ICEBERG_REST_AZURE_STORAGE_ACCOUNT_NAMEgravitino.iceberg-rest.azure-storage-account-name(none)
GRAVITINO_ICEBERG_REST_AZURE_STORAGE_ACCOUNT_KEYgravitino.iceberg-rest.azure-storage-account-key(none)
GRAVITINO_ICEBERG_REST_AZURE_TENANT_IDgravitino.iceberg-rest.azure-tenant-id(none)
GRAVITINO_ICEBERG_REST_AZURE_CLIENT_IDgravitino.iceberg-rest.azure-client-id(none)
GRAVITINO_ICEBERG_REST_AZURE_CLIENT_SECRETgravitino.iceberg-rest.azure-client-secret(none)
GRAVITINO_ICEBERG_REST_OSS_ACCESS_KEYgravitino.iceberg-rest.oss-access-key-id(none)
GRAVITINO_ICEBERG_REST_OSS_SECRET_KEYgravitino.iceberg-rest.oss-secret-access-key(none)
GRAVITINO_ICEBERG_REST_OSS_ENDPOINTgravitino.iceberg-rest.oss-endpoint(none)
GRAVITINO_ICEBERG_REST_OSS_REGIONgravitino.iceberg-rest.oss-region(none)
GRAVITINO_ICEBERG_REST_OSS_ROLE_ARNgravitino.iceberg-rest.oss-role-arn(none)
GRAVITINO_ICEBERG_REST_OSS_EXTERNAL_IDgravitino.iceberg-rest.oss-external-id(none)

The image bundles MySQL and PostgreSQL JDBC drivers in jdbc-drivers/ and links them into libs/ and iceberg-rest-server/libs/ at startup. For cloud storage backends, put the matching Iceberg bundle jars in iceberg-bundles/ and they are linked into catalogs/lakehouse-iceberg/libs/ and iceberg-rest-server/libs/ the same way.

Checking What the Container Did

Read back the rewritten file:

docker exec -it {container_id} cat /opt/gravitino/conf/gravitino.conf

Then confirm the server, and the auxiliary IRC service if you started one:

curl http://127.0.0.1:8090/health/ready
curl http://127.0.0.1:9001/iceberg/v1/config

Accessing Apache Hadoop

Gravitino reaches Hadoop as a single operating system user, so that user needs the HDFS and YARN permissions for everything the server will touch. Without them, operations fail with Permission denied. Either grant the user that starts the server the permissions it needs, or set HADOOP_USER_NAME to a user that already has them before starting. For a local deployment, set it in conf/gravitino-env.sh.

  • Relational Backend Storage, for pointing the entity store at MySQL or PostgreSQL, including schema initialization and driver installation
  • Iceberg REST Catalog Service, for the gravitino.iceberg-rest.* properties of the auxiliary service named by gravitino.auxService.names
  • How to Authenticate, for the gravitino.authenticator.* properties behind each value of gravitino.authenticators
  • Local users and groups, for holding users, password hashes, and group membership in Gravitino's own relational store
  • Access Control, for the privilege model the authorizer enforces once gravitino.authorization.enable is set: roles, grants, ownership, and metalake administration
  • Authorization Pushdown, for propagating those privileges into the underlying systems through Apache Ranger or a native permission model
  • Credential Vending, for issuing temporary storage credentials to engines instead of distributing long-lived keys
  • HTTPS, for the gravitino.server.webserver.* key store, trust store, and client certificate properties
  • CORS, for letting browser clients served from another origin call the API
  • Security