Installation
This guide covers how to install and set up Inmor Trust Anchor for development and production use.
Prerequisites
Docker and Docker Compose
Git
justcommand runner (optional but recommended)uvfor Python dependency management (for local development)
Installing just
just is a task runner similar to make. Install it using your package manager:
# macOS
brew install just
# Ubuntu/Debian
sudo apt install just
# Arch Linux
sudo pacman -S just
# Using cargo
cargo install just
Quick Installation
Clone the repository:
git clone https://github.com/SUNET/inmor.git cd inmor
The repository includes development signing keys, so no key generation is needed to get started.
Build the Docker images:
just build
Build binaries:
just build-rs
Start all services:
just up
Initialize the Trust Anchor:
# Create the entity configuration curl -X POST http://localhost:8000/api/v1/server/entity # Create historical keys JWT (if you have any) curl -X POST http://localhost:8000/api/v1/server/historical_keys
The Trust Anchor is now running at http://localhost:8080 and the Admin API at http://localhost:8000.
Note
For production deployments, you should generate your own signing keys. See the Key Generation section below.
Docker Compose Files
The project has two Docker Compose configurations:
docker-compose.yml— Production configuration. Uses baked-in Docker image code, release builds, granian, named volumes, and only exposes the TA port.dev/docker-compose.dev.yml— Development configuration. Mounts source code for live reloading, uses debug builds, exposes all ports, and uses trust auth for PostgreSQL.
The just commands automatically use the development compose file. To use the
production configuration directly:
docker compose up -d
Key Generation
The repository includes development signing keys that are ready to use. These keys are sufficient for development and testing.
For production deployments, you should generate your own keys:
# Remove existing development keys
just clean
# Generate new keys for production
just dev
Inmor generates multiple key types for signing operations, following RFC 9864 Section 2:
RSA keys (RS256, PS256) - 2048 bit
EC keys (ES256, ES384, ES512) - P-256, P-384, P-521 curves
Edwards curve keys (Ed25519, Ed448)
Each key is stored as a JWK JSON file with the key ID (kid) as the thumbprint.
Warning
Regenerating keys will invalidate all existing entity statements and trust marks. Make sure to backup and properly rotate keys in production.
For a production server that only has the Docker image and not this source
tree, generate the signing key with the bundled inmor-keygeneration
binary instead. See Generating the Signing Key in the deployment guide.
Directory Structure
After installation, your directory structure should look like:
inmor/
├── publickeys/ # Public keys (JWK format)
│ └── *.json
├── privatekeys/ # Private keys (JWK format)
│ └── *.json
├── historical_keys/ # Expired/rotated keys
│ └── *.json
├── private.json # TA primary signing key
├── admin/
│ └── private.json # Admin signing key
├── dev/ # Development files
│ ├── docker-compose.dev.yml
│ ├── rootCA.pem # Dev root CA certificate
│ ├── localhost+2.pem # Dev TLS certificate
│ └── localhost+2-key.pem
├── taconfig.toml # TA configuration
└── docker-compose.yml # Production compose
Verifying Installation
Check that all containers are running:
docker compose ps
You should see four containers:
ta,admin,db, andredis.Test the Trust Anchor:
curl http://localhost:8080/.well-known/openid-federation
This should return a signed JWT containing the entity configuration.
Test the Admin API:
curl http://localhost:8000/api/v1/trustmarktypes
This should return an empty list or existing trust mark types.
Stopping Services
To stop all services:
just down
To stop and remove all data (including database):
just down
rm -rf db/ redis/
Development Setup
For local development without Docker:
Install uv (if not already installed):
# macOS/Linux curl -LsSf https://astral.sh/uv/install.sh | sh # Or with pip pip install uv
Set up Python environment:
just venv
This runs
uv syncin the admin directory to create a virtual environment and install all dependencies.Install the development root CA certificate to the system trust store.
The repository includes self-signed TLS certificates for development under the
dev/directory. To allow your system to trust these certificates, install the root CA:Ubuntu/Debian:
sudo cp dev/rootCA.pem /usr/local/share/ca-certificates/rootCA.crt sudo update-ca-certificates
Fedora/RHEL/CentOS:
sudo cp dev/rootCA.pem /etc/pki/ca-trust/source/anchors/rootCA.pem sudo update-ca-trust
macOS:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain dev/rootCA.pem
Arch Linux:
sudo cp dev/rootCA.pem /etc/ca-certificates/trust-source/anchors/rootCA.crt sudo trust extract-compat
Set up Rust environment:
cargo build --release
Start dependencies (Redis and PostgreSQL):
just up
Or start only db and redis with the dev compose file:
docker compose -f dev/docker-compose.dev.yml --project-directory . up -d db redis
Run Django migrations:
cd admin uv run python manage.py migrate
Start the Admin server:
uv run python manage.py runserver
Start the Trust Anchor:
cargo run --release -- -c taconfig.toml
Production Deployment
For production deployments:
Build or pull the Docker images:
docker compose build
Configure
localsettings.pywith production Django settings (SECRET_KEY,ALLOWED_HOSTS,SECURE_SSL_REDIRECT, etc.) and place it in the repository root.Update TLS certificate paths in
docker-compose.ymlto point to your production certificates.Set
POSTGRES_PASSWORDindocker-compose.yml(or use environment variables / Docker secrets).Generate an
MFA_ENCRYPTION_KEYand set it in the admin service environment.Start services:
docker compose up -d
The admin service runs with granian in production (PRODUCTION=true).
Place a reverse proxy (e.g., nginx) in front of the admin and frontend
services.
Troubleshooting
Container won’t start
Check the logs:
docker compose logs ta
docker compose logs admin
Common issues:
Port already in use - stop other services on ports 8000, 8080, 5432
Redis not ready - wait for healthcheck to pass
Database connection errors
Ensure PostgreSQL is running and healthy:
docker compose ps db
If the database is corrupted, remove and recreate:
just down
rm -rf db/
just up
Key file errors
Ensure private.json exists and is valid JSON:
cat private.json | python -m json.tool
If the file is corrupted or missing, restore from git:
git checkout -- private.json admin/private.json publickeys/
TLS certificate errors
If you see SSL/TLS certificate verification errors when running tests or making requests to the Trust Anchor, ensure the root CA is installed:
# Verify the root CA is installed (Ubuntu/Debian)
ls /usr/local/share/ca-certificates/rootCA.crt
# If missing, install it
sudo cp dev/rootCA.pem /usr/local/share/ca-certificates/rootCA.crt
sudo update-ca-certificates
For other operating systems, see the root CA installation steps in the Development Setup section above.