️ This flake exposes:
- A
datomic-pro
nix package (andconsole
, andpeer
) - ❄ NixOS modules for running Datomic Pro on NixOS
- 🐋 A container image that you can use to run Datomic Pro (no nix required!)
All of the above are end-to-end tested by the CI suite in this repo!
Project status: Experimental but ready for testing. Breaking changes may occur until version 1.0. The 1.0 release will be considered production-ready.
Table of Contents
pkgs.datomic-pro
will always be the latest release, but the following specific versions are also available:
pkgs.datomic-pro_1_0_7387
(latest)pkgs.datomic-pro_1_0_7364
pkgs.datomic-pro_1_0_7277
And for peer:
pkgs.datomic-pro-peer_1_0_7387
(latest)pkgs.datomic-pro-peer_1_0_7364
pkgs.datomic-pro-peer_1_0_7277
{
inputs.
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Check https://github.com/outskirtslabs/datomic-pro-flake/releases for the latest release tag
datomic-pro.url = "https://flakehub.com/f/Ramblurr/datomic-pro/0.7.0.tar.gz";
datomic-pro.nixpkgs = "nixpkgs";
};
outputs = { nixpkgs, datomic-pro, ... }@attrs: {
nixosConfigurations.machine = nixpksg.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
datomic-pro.nixosModules.${system}.datomic-pro
];
};
};
}
I wouldn't really do this in production I would use a tool like agenix or sops-nix.
Important
Whatever you do, do not use
environment.etc
to create the secret files! That will write the secrets into the globally
readable nix store, and could end up on a nix cache somewhere. Bad news!
# in `/etc/datomic-pro/secrets.properties`
storage-admin-password=changeme
storage-datomic-password=changeme
# set permissions carefully, it just needs to be root owned
# even though datomic doesn't run as root (thanks systemd!)
chown root:root /etc/datomic-pro/secrets.properties
chmod 0600 /etc/datomic-pro/secrets.properties
A basic dev-mode datomic that stores its state in /var/lib/datomic-pro
:
{
services.datomic-pro = {
enable = true;
package = pkgs.datomic-pro_1_0_7387;
secretsFile = "/etc/datomic-pro/secrets.properties";
settings = {
# no secrets in here!
enable = true;
host = "localhost";
port = 4334;
memory-index-max = "256m";
memory-index-threshold = "32m";
object-cache-max = "128m";
protocol = "dev";
storage-access = "remote";
};
}
# optionally add the console
services.datomic-console = {
enable = true;
port = 8080;
dbUriFile = ..path to secret file containing something like datomic:dev://localhost:4334/.....
};
# ... the rest of your owl ...
}
This flake also provides a container image for Datomic Pro that can be driven entirely with environment variables or _FILE
style secrets.
If you don't want to build the container image yourself with nix, you can get the latest image with:
docker/podman pull ghcr.io/outskirtslabs/datomic-pro:1.0.7387
The available tags you can find here: https://github.com/orgs/outskirtslabs/packages/datomic-pro-flake/package/datomic-pro
Runs a Datomic Transactor. This is the default mode when the container is run with no command.
- The default port is
4334
. - A rw volume of
/config
is required. - Configure with env vars (see below) or add
/config/transactor.properties
to supply a config to the transactor. - A rw volume of
/data
is optional (for use in H2 mode). - Postgresql, MySQL, and sqlite JDBC drivers are included by default.
Important
All env vars can be passed with _FILE
to read the value from a file
(e.g, when using secrets). Example: DATOMIC_STORAGE_ADMIN_PASSWORD
can be
passed as DATOMIC_STORAGE_ADMIN_PASSWORD_FILE=/run/secrets/admin-password
and
the value from that file will be used as the admin password.
DATOMIC_TRANSACTOR_PROPERTIES_PATH
- The path to the properties file for the transactor. Defaults to/config/transactor.properties
The following environment vars configure the properties, refer to the Datomic documentation for more information:
DATOMIC_ALT_HOST
-alt-host
DATOMIC_DATA_DIR
-data-dir
(default: /data)DATOMIC_ENCRYPT_CHANNEL
-encrypt-channel
DATOMIC_HEARTBEAT_INTERVAL_MSEC
-heartbeat-interval-msec
DATOMIC_HOST
-host
(default: 0.0.0.0)DATOMIC_MEMCACHED
-memcached
DATOMIC_MEMCACHED_AUTO_DISCOVERY
-memcached-auto-discovery
DATOMIC_MEMCACHED_CONFIG_TIMEOUT_MSEC
-memcached-config-timeout-msec
DATOMIC_MEMCACHED_PASSWORD
-memcached-password
DATOMIC_MEMCACHED_USERNAME
-memcached-username
DATOMIC_MEMORY_INDEX_MAX
-memory-index-max
(default: 256m)DATOMIC_MEMORY_INDEX_THRESHOLD
-memory-index-threshold
(default: 32m)DATOMIC_OBJECT_CACHE_MAX
-object-cache-max
(default: 128m)DATOMIC_PID_FILE
-pid-file
DATOMIC_HEALTHCHECK_CONCURRENCY
-ping-concurrency
DATOMIC_HEALTHCHECK_HOST
-ping-host
DATOMIC_HEALTHCHECK_PORT
-ping-port
DATOMIC_PORT
-port
(default: 4334)DATOMIC_PROTOCOL
-protocol
(default: dev)DATOMIC_READ_CONCURRENCY
-read-concurrency
DATOMIC_SQL_DRIVER_CLASS
-sql-driver-class
DATOMIC_SQL_URL
-sql-url
DATOMIC_STORAGE_ACCESS
-storage-access
(default: remote)DATOMIC_STORAGE_ADMIN_PASSWORD
-storage-admin-password
DATOMIC_STORAGE_DATOMIC_PASSWORD
-storage-datomic-password
DATOMIC_VALCACHE_MAX_GB
-valcache-max-gb
DATOMIC_VALCACHE_PATH
-valcache-path
DATOMIC_WRITE_CONCURRENCY
-write-concurrency
If you want to provide your own transactor.properties
, you can opt out of all of the above by:
- Placing your properties file into a location such that
/config/transactor.properties
will exist when the container runs. - Set the env variable
DOCKER_DATOMIC_GENERATE_PROPERTIES_SKIP
to anything except an empty string.
Runs the Datomic Console.
- Run this mode by passing the
console
as the first and only argument to the container. - The default port is
8080
.
DB_URI
- the database connection URI that console uses to connect to datomicDB_URI_FILE
- will read the connection URI from the file specified by this env var
Be sure to mkdir data/ config/
before running this.
---
services:
datomic-transactor:
image: ghcr.io/outskirtslabs/datomic-pro:1.0.7387
environment:
DATOMIC_STORAGE_ADMIN_PASSWORD: unsafe
DATOMIC_STORAGE_DATOMIC_PASSWORD: unsafe
volumes:
- ./data:/data
ports:
- 127.0.0.1:4334:4334
#user: 1000:1000 # if using rootful containers uncomment this
datomic-console:
image: ghcr.io/outskirtslabs/datomic-pro:1.0.7387
command: console
environment:
DB_URI: datomic:dev://datomic-transactor:4334/?password=unsafe
ports:
- 127.0.0.1:8081:8080
#user: 1000:1000 # if using rootful containers uncomment this
mkdir data config
- Prepare an empty SQLite database:
mkdir -p data/ config/
sqlite3 data/datomic-sqlite.db "
-- Tuning for SQLite in production - same as Rails 8.0
PRAGMA foreign_keys = ON;
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA mmap_size = 134217728; -- 128 megabytes
PRAGMA journal_size_limit = 67108864; -- 64 megabytes
PRAGMA cache_size = 2000;
-- Datomic's Schema
CREATE TABLE datomic_kvs (
id TEXT NOT NULL,
rev INTEGER,
map TEXT,
val BYTEA,
CONSTRAINT pk_id PRIMARY KEY (id)
);"
- Use this compose (or pick and choose what you need)
---
services:
datomic-transactor:
image: ghcr.io/outskirtslabs/datomic-pro:unstable
environment:
DATOMIC_PROTOCOL: sql
DATOMIC_SQL_URL: jdbc:sqlite:/data/datomic-sqlite.db
DATOMIC_SQL_DRIVER_CLASS: org.sqlite.JDBC
DATOMIC_JAVA_OPTS: -Dlogback.configurationFile=/config/logback.xml
DATOMIC_HOST: datomic-transactor # this value is so sibling compose containers can connect by DNS name
DATOMIC_ALT_HOST: "127.0.0.1" # this value is so apps running on the container's host
volumes:
- "./data:/data:z"
- "./config:/config:z"
ports:
- 127.0.0.1:4334:4334
datomic-console:
image: ghcr.io/outskirtslabs/datomic-pro:unstable
command: console
environment:
# you don’t specify the db name in the uri (because console can access all dbs)
DB_URI: "datomic:sql://?jdbc:sqlite:/data/datomic-sqlite.db"
volumes:
- "./data:/data:z"
ports:
- 127.0.0.1:8081:8080
This compose file is near-production ready. But you shouldn't manage the lifecycle of the postgres schema this way. How you do it depends on your environment.
Be sure to mkdir data/ config/
before running this.
---
services:
datomic-memcached:
image: docker.io/memcached:latest
command: memcached -m 1024
ports:
- 127.0.0.1:11211:11211
restart: always
healthcheck:
test:
[
"CMD-SHELL",
'bash -c ''echo "version" | (exec 3<>/dev/tcp/localhost/11211; cat >&3; timeout 0.1 cat <&3; exec 3<&-)''',
]
interval: 5s
retries: 60
datomic-storage:
image: docker.io/library/postgres:latest
environment:
POSTGRES_PASSWORD: unsafe
command: postgres -c 'max_connections=1024'
volumes:
- ./data:/var/lib/postgresql/data
ports:
- 127.0.0.1:5432:5432
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 30
datomic-storage-migrator:
image: ghcr.io/outskirtslabs/datomic-pro:1.0.7387
environment:
PGUSER: postgres
PGPASSWORD: unsafe
volumes:
- "./postgres-migrations:/migrations"
entrypoint: /bin/sh
command: >
-c '(psql -h datomic-storage -lqt | cut -d \| -f 1 | grep -qw "datomic" || psql -h datomic-storage -f /opt/datomic-pro/bin/sql/postgres-db.sql) &&
(psql -h datomic-storage -d datomic -c "\dt" | grep -q "datomic_kvs" || psql -h datomic-storage -d datomic -f /opt/datomic-pro/bin/sql/postgres-table.sql) &&
(psql -h datomic-storage -d datomic -c "\du" | cut -d \| -f 1 | grep -qw "datomic" || psql -h datomic-storage -d datomic -f /opt/datomic-pro/bin/sql/postgres-user.sql)'
depends_on:
datomic-storage:
condition: service_healthy
datomic-transactor:
image: ghcr.io/outskirtslabs/datomic-pro:1.0.7387
environment:
DATOMIC_STORAGE_ADMIN_PASSWORD: unsafe
DATOMIC_STORAGE_DATOMIC_PASSWORD: unsafe
DATOMIC_PROTOCOL: sql
DATOMIC_SQL_URL: jdbc:postgresql://datomic-storage:5432/datomic?user=datomic&password=datomic
DATOMIC_HEALTHCHECK_HOST: 127.0.0.1
DATOMIC_HEALTHCHECK_PORT: 9999
DATOMIC_MEMCACHED: datomic-memcached:11211
ports:
- 127.0.0.1:4334:4334
#user: 1000:1000 # if using rootful containers uncomment this
restart: always
healthcheck:
test:
[
"CMD-SHELL",
'if [[ $(curl -s -o /dev/null -w "%{http_code}" -X GET http://127.0.0.1:9999/health) = "200" ]]; then echo 0; else echo 1; fi',
]
interval: 10s
timeout: 3s
retries: 30
depends_on:
datomic-storage:
condition: service_healthy
datomic-memcached:
condition: service_healthy
datomic-storage-migrator:
condition: service_completed_successfully
datomic-console:
image: ghcr.io/outskirtslabs/datomic-pro:1.0.7387
command: console
environment:
DB_URI: datomic:sql://?jdbc:postgresql://datomic-storage:5432/datomic?user=datomic&password=datomic
ports:
- 127.0.0.1:8081:8080
#user: 1000:1000 # if using rootful containers uncomment this
Feel free to open an issue or reach out to me on the Clojurians slack (@Ramblurr).
See here for security advisories or to report a security vulnerability.
Copyright © 2025 Casey Link [email protected]
Distributed under the Apache-2.0, just like Datomic Pro itself.