Skip to content
IceGuard

IceGuard

A modern web console to manage, inspect and maintain Apache Iceberg™ tables across multiple catalogs.

CI Release GHCR images License Backend Frontend PRs welcome


IceGuard demo — browse catalogs, inspect a table, run Spark maintenance

Browse tagged catalogs → inspect a table's metadata, snapshots, storage & timeline → run a Spark maintenance action and watch its result + logs. ▶ MP4 version

⚠️ Independent community project — not affiliated with or endorsed by the Apache Software Foundation. "Apache", "Apache Iceberg", "Iceberg" and "Apache Polaris" are trademarks of the ASF.


What is IceGuard?

IceGuard is an admin & maintenance console for the Apache Iceberg lakehouse. Point it at one or more catalogs (REST, Nessie, Polaris) and get a single UI to browse namespaces and tables, evolve schemas and partitions, edit properties, sample data, inspect storage layout, view lineage, and run (or schedule) maintenance like snapshot expiration and data-file compaction.

It is not a catalog — it sits on top of your existing Iceberg catalogs.

What IceGuard actually is

IceGuard is two components:

  1. Frontend — the React/TypeScript web UI.
  2. Backend — the Quarkus REST API.

It has one required dependency: a PostgreSQL database (you provide it), where the backend stores IceGuard's own state — registered catalogs, pipelines, schedules, alerts and execution history. Postgres is not part of IceGuard; it's infrastructure IceGuard needs to run, like a JVM.

IceGuard then connects to your own Iceberg catalog(s) and object store.

The docker-compose.yml in this repo (MinIO, an Iceberg REST Catalog, Nessie, Apache Polaris, optionally Spark) is only a local test sandbox so you can try IceGuard end-to-end without bringing your own infrastructure. It is not part of the product — in production you point IceGuard at your existing catalogs and storage.

Features

  • Multi-catalog — register and switch between REST, Nessie, Polaris and Unity Catalog (None/Bearer/OAuth2 supported).
  • Namespaces & tables — browse the tree, create namespaces, create/drop/rename tables, insert sample rows.
  • Schema editor — add / rename / retype / re-doc / drop multiple columns, applied in a single commit.
  • Properties editor — add / update / remove table properties in a single commit.
  • Partition evolution — add or drop partition fields (identity, bucket, truncate, year/month/day/hour).
  • Storage tab — point-in-time storage state: totals, file-size histogram, per-partition aggregates (server-side paginated), and file drill-down.
  • Lineage / history — schema-version history with column diffs, and a visual snapshot-to-snapshot diff.
  • Maintenance — expire snapshots, rewrite data files, rewrite manifests, remove orphan files, rollback. Pluggable executors: a Java API executor (analyse) and a Spark executor (real rewrite_data_files, local local[*] or a remote Spark cluster).
  • Pipelines — chain maintenance actions with per-action parameters and a cron schedule (Airflow-style run view).
  • Alerts — threshold rules on table metrics with optional SMTP email notifications.
  • Timeline — snapshots + executions on one timeline, click any item for its output/logs.

Supported catalogs

Any Iceberg REST-compatible catalog works. The Add Catalog wizard shows a card per engine, and the type is auto-detected from the catalog name/URI:

Catalog Typical URI Auth
Iceberg REST Iceberg REST http://host:8181 None / Bearer
Nessie Nessie http://host:19120/iceberg None
Apache Polaris Apache Polaris http://host:8182/api/catalog OAuth2
Unity Catalog Unity Catalog https://<workspace>/api/2.1/unity-catalog/iceberg-rest Bearer (PAT) / OAuth2

Unity Catalog (Databricks or the OSS unitycatalog.io) is reached through its Iceberg REST Catalog API — browse works today; writes depend on the endpoint (Databricks managed-Iceberg read/write is in preview, requires EXTERNAL USE SCHEMA + a PAT/OAuth token).

Nessie has a few specifics (snapshot history rebuilt from its commit log, S3 region requirement, flaky-remote handling) — see docs/NESSIE.md.

Stack

Layer Tech
Frontend (product) React, TypeScript, Vite, Tailwind CSS, shadcn/ui, TanStack Query, Zustand, Recharts
Backend (product) Java 21, Quarkus 3.17, RESTEasy Reactive, Hibernate Panache, Flyway, Apache Iceberg 1.7
Required dependency PostgreSQL (backend state)
Test sandbox only Docker Compose: MinIO (S3), Iceberg REST Catalog, Nessie, Apache Polaris, (optional) Spark

Quick start

Requirements: Docker + Docker Compose. (For hot-reload development: JDK 21 & Maven, Node 20+.)

The app is two services — frontend + backend — plus a required Postgres. docker-compose.yml bundles them in three tiers via Compose profiles:

Level Command Services When
1 — app (official) docker compose up -d --build frontend + backend Bring your own Postgres (ICEGUARD_DB_URL in .env)
2 — + database docker compose --profile db up -d --build + Postgres Self-contained app + its required DB
3 — + test sandbox docker compose --profile db --profile sandbox up -d --build + MinIO + REST catalog Try everything locally

No local build? Use the published images from GHCR instead — same levels, just point at the images file (no --build):

docker compose -f docker-compose.images.yml --profile db --profile sandbox up -d

Defaults to :latest; pin a release with TAG=0.1.0 docker compose -f docker-compose.images.yml ….

For the quickest tour, use Level 3 and open http://localhost:8090.

Add your first catalog (sandbox)

In the UI, go to Catalogs → Add Catalog and register the bundled Iceberg REST catalog:

Field Value
Catalog type Iceberg REST
URI http://rest-catalog:8181 (Docker service name — not localhost; the backend reaches it over the Compose network)
Warehouse s3://warehouse/rest/
Authentication None
S3 / Storage access Static keys
  • Endpoint http://minio:9000
  • Access key / Secret key minioadmin / minioadmin
  • Region us-east-1
  • Path-style access enabled ✅

The S3 settings let the backend read/write data files on the sandbox MinIO. Once added, create a namespace and a table to see browsing, schema, storage and maintenance in action.

Tear down with docker compose --profile db --profile sandbox down (add -v to wipe data) — use -f docker-compose.images.yml in the same command if you started from the images file.

Service URL Notes
Frontend (UI) http://localhost:8090 nginx; proxies /api to the backend
Backend API http://localhost:8080 Swagger at /q/swagger-ui
MinIO console http://localhost:9001 minioadmin / minioadmin (sandbox profile)
Iceberg REST catalog http://localhost:8181 sandbox profile; register it as http://rest-catalog:8181

Develop (hot reload)

Run the dependencies in Docker and the app from source:

# deps only (Postgres :5433, REST catalog :8181, Nessie :19120, MinIO) — not the backend container
docker compose -f docker-compose.dev.yml up -d postgres rest-catalog nessie minio minio-init
cd backend && mvn quarkus:dev -Dquarkus.profile=docker   # :8080  (Swagger: /q/swagger-ui)
cd frontend && npm install && npm run dev                 # :5173  (proxies /api to :8080)

Advanced: full multi-catalog sandbox

For every catalog type at once (REST + Nessie + Polaris) and real Spark compaction:

docker compose -f docker-compose.dev.yml up -d
./scripts/seed-catalog.sh        # after the backend is up

The REST Catalog and Nessie demo catalogs work out of the box on MinIO. Polaris writes require real AWS S3 — copy .env.example to .env.

Using IceGuard for real

Deploy the frontend and backend, point the backend at a PostgreSQL you provide (QUARKUS_DATASOURCE_JDBC_URL / username / password), then add your own catalog(s) from the UI (Catalogs → Add Catalog): REST / Nessie / Polaris URI, warehouse, auth (None / Bearer / OAuth2) and, if needed, S3 credentials. No MinIO/Spark/sandbox containers required.

Architecture

        IceGuard (the product)            required dep            your existing systems
   ┌───────────────────────────────┐
   │ React + Vite (UI, :5173)       │
   │           │                    │
   │ Quarkus REST API (:8080) ──────┼──> PostgreSQL ─────────┐
   └───────────────────────────────┘   (IceGuard state)     │
                   │                                         │
                   └──────────────────> Iceberg catalogs (REST / Nessie / Polaris)
                                                  └──> S3 / object store (data & metadata)

IceGuard's own state (registered catalogs, pipelines, schedules, alerts, execution history) lives in the PostgreSQL you provide; table data & metadata live in your object store via your Iceberg catalogs.

Project layout

backend/                 Quarkus REST API (com.iceguard.*)
frontend/                React + TypeScript SPA
scripts/                 seed + helper scripts
docker-compose.yml       app stack (frontend + backend; profiles: db / sandbox)
docker-compose.dev.yml   advanced multi-catalog sandbox (Nessie, Polaris, Spark)

Known limitations

  • The Java executor really runs compaction & orphan-removal, but only on small, append-only tables (hard size/file-count limits; refuses above them) — use the Spark executor for large or merge-on-read tables.
  • Polaris + MinIO: browsing works, but writes fail (Polaris ignores the S3-compatible endpoint) — use real AWS S3.
  • Catalog credentials are stored in PostgreSQL (not encrypted at rest) — treat the DB as sensitive.
  • Test coverage is early-stage. Contributions very welcome 🙂

Contributing

Contributions, issues and ideas are welcome! Please read CONTRIBUTING.md and our Code of Conduct. Good first issues are labelled good first issue.

How the pipelines and automation work (CI, releases, Dependabot, CodeQL, Trivy) is documented in docs/CI.md.

License

Apache License 2.0.

About

Open-source web console to browse, maintain and schedule maintenance for Apache Iceberg tables across REST, Nessie, Polaris and Unity catalogs.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages