Skip to main content

What you need for Unomi 3.1

  • Docker (recommended path) — or Java 17+ for a manual install
  • Elasticsearch 9.x (e.g. 9.4.3) or OpenSearch 3.x
  • After startup you create a tenant and use its public / private API keys for API calls

What is Apache Unomi?

Apache Unomi is a REST server that manages user profiles and events. It integrates personalization and profile management into any system — CMS, CRM, mobile apps, custom platforms, or AI agents.

  • Tracks users via cookies or custom identifiers and builds rich profiles over time
  • Multi-tenancy (Unomi 3.1) — isolate profiles, events, segments, rules, and schemas per tenant
  • Built-in rule engine, dynamic segmentation, and privacy / GDPR APIs
  • OSGi plugin architecture on Apache Karaf — Elasticsearch or OpenSearch backend
  • Reference implementation of the OASIS CDP specification
How Apache Unomi works: sources via REST into profiles, segments, rules, and outputs

Privacy as a First-Class Feature

Unomi’s privacy REST API lets you build user-facing UIs where visitors can manage their profile, control tracking, view collected data, anonymize past data, or fully delete their profile. Built for a world where GDPR and privacy legislation matter.

Run Unomi 3.1 with Docker

The fastest way to try Apache Unomi. Only Docker is required. Choose Elasticsearch or OpenSearch.

1

Create a docker-compose.yml

Pick one backend. Image tag matches the current stable release (3.1.0).

Option A — Elasticsearch 9.4.3

version: '3.8'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:9.4.3
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - 9200:9200
  unomi:
    image: apache/unomi:3.1.0
    environment:
      - UNOMI_ELASTICSEARCH_ADDRESSES=elasticsearch:9200
      - UNOMI_THIRDPARTY_PROVIDER1_IPADDRESSES=0.0.0.0/0,::1,127.0.0.1
    ports:
      - 8181:8181
      - 9443:9443
      - 8102:8102
    depends_on:
      - elasticsearch

Option B — OpenSearch 3.x

version: '3.8'
services:
  opensearch-node1:
    image: opensearchproject/opensearch:3
    environment:
      - cluster.name=opensearch-cluster
      - node.name=opensearch-node1
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD:-admin}
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - opensearch-data1:/usr/share/opensearch/data
    ports:
      - 9200:9200
      - 9600:9600

  unomi:
    image: apache/unomi:3.1.0
    environment:
      - UNOMI_DISTRIBUTION=unomi-distribution-opensearch
      - UNOMI_OPENSEARCH_ADDRESSES=opensearch-node1:9200
      - UNOMI_OPENSEARCH_USERNAME=admin
      - UNOMI_OPENSEARCH_PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD:-admin}
      - UNOMI_HEALTHCHECK_PROVIDERS=cluster,opensearch,unomi,persistence
    ports:
      - 8181:8181
      - 9443:9443
      - 8102:8102
    depends_on:
      - opensearch-node1

volumes:
  opensearch-data1:
2

Start the environment

docker compose up

Wait for startup to complete (usually 1–2 minutes).

3

Create a tenant (required in 3.1)

System admin credentials create tenants. Creation stores hashed keys only (maskedKey in the response) — regenerate each key once and save plainTextKey immediately.

curl -X POST http://localhost:8181/cxs/tenants \
  --user karaf:karaf \
  -H "Content-Type: application/json" \
  -d '{
    "requestedId": "default",
    "properties": {
      "name": "Default Tenant",
      "description": "Default tenant for quick start"
    }
  }'

# One-time plaintext secrets (replaces any existing key of that type)
curl -X POST 'http://localhost:8181/cxs/tenants/default/apikeys?type=PUBLIC' \
  --user karaf:karaf
curl -X POST 'http://localhost:8181/cxs/tenants/default/apikeys?type=PRIVATE' \
  --user karaf:karaf
  • PUBLIC plainTextKey — use as X-Unomi-Api-Key on /cxs/context.json and /cxs/eventcollector
  • PRIVATE plainTextKey — basic auth default:<private-key> for admin APIs (scopes, rules, schemas, …)
4

Verify cluster & request context

Cluster (system admin):

curl -k https://localhost:9443/cxs/cluster -u karaf:karaf

Create a scope before context or events (schema validation rejects unknown scopes):

curl -X POST http://localhost:8181/cxs/scopes \
  -u "default:YOUR_PRIVATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "itemId": "default",
    "itemType": "scope",
    "metadata": { "id": "default", "name": "Default scope" }
  }'

First context request (public API key required):

curl -X POST "http://localhost:8181/cxs/context.json?sessionId=1234" \
  -H "Content-Type: application/json" \
  -H "X-Unomi-Api-Key: YOUR_PUBLIC_API_KEY" \
  -d '{
    "source": {
      "itemId": "homepage",
      "itemType": "page",
      "scope": "default"
    }
  }'

Default system credentials: karaf / karaf. Certificate warnings on port 9443 are expected in development.

Production note: This configuration is for development only. See the production security guide before deploying.

Manual install? Java 17+, Elasticsearch 9.4.3 or OpenSearch 3.x — follow the manual quick start (same tenant + API key steps).

Upgrading from 2.x? See Migrating to Unomi 3 and optional V2 compatibility mode.

How API access works

Audience Credential Typical use
System admin karaf:karaf (basic) Create / list tenants, cluster ops
Tenant admin tenantId:privateApiKey (basic) Scopes, rules, schemas, searches
Public apps / trackers X-Unomi-Api-Key: <public> /cxs/context.json, /cxs/eventcollector

Details: Multi-tenancy in Unomi 3 · Manual — Multi-tenancy