Quick start

Stand up io.sign locally for evaluation with Docker Compose

This guide gets a working io.sign instance running on your machine in a few minutes using Docker Compose. It brings up the service together with its datastore and message bus so you can explore the API and verify the deployment.

For evaluation only. This single-host Compose setup disables authentication and runs the API components in one container alongside Postgres and Redis. It is not a production topology. For a real deployment, see Deploying io.sign and the Configuring io.sign reference.

Prerequisites

  • Docker and the Docker Compose plugin (docker compose version ≥ v2).
  • Access to the io.finnet container registry. Ask your io.finnet contact for the registry URL, the io.sign API and migrations image names, the tag matching your evaluation, and pull credentials.
  • (Optional) A license key issued by io.finnet. Without one, io.sign boots in read-only mode — enough to explore the API surface, but write operations are rejected.

Authenticate to the registry once:

docker login <registry>

Step 1 — Create an environment file

Create a file named .env next to the Compose file below. These values wire the containers together and are safe for local evaluation:

# --- io.finnet image registry (fill these in) ---
IOSIGN_REGISTRY=<registry>
IOSIGN_API_IMAGE=<api-image>
IOSIGN_MIGRATIONS_IMAGE=<migrations-image>
IOSIGN_VERSION=<tag>

# --- Runtime ---
NODE_ENV=production
STAGE=local
ENV=local

# --- Components (run everything in one container for evaluation) ---
ENABLE_ORPC=true
ENABLE_GRPC=true
ENABLE_GRPC_STREAM=true
ENABLE_ORCHESTRATOR=true
ENABLE_CRON_TASKS=true
ENABLE_REDIS=true

# --- Ports ---
API_PORT=3000
GRPC_PORT=50051

# --- Database ---
DB_NAME=io_sign
DB_USER=io_sign
DB_PASSWORD=io_sign

# --- Auth: disabled for local evaluation only ---
# In any real deployment set JWT_ENABLED=true and configure JWT_PROVIDERS.
JWT_ENABLED=false

# --- License (optional for evaluation; omit to run in read-only mode) ---
# LICENSE_KEY=<base64-license-issued-by-iofinnet>

# --- Logging ---
LOG_LEVEL=info
LOG_PRETTY=true

Step 2 — Create the Compose file

Save this as docker-compose.yml:

name: io-sign-quickstart

services:
  postgres:
    image: postgres:17-alpine
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 10

  migrations:
    image: ${IOSIGN_REGISTRY}/${IOSIGN_MIGRATIONS_IMAGE}:${IOSIGN_VERSION}
    env_file: .env
    environment:
      DB_HOST: postgres
    depends_on:
      postgres:
        condition: service_healthy

  api:
    image: ${IOSIGN_REGISTRY}/${IOSIGN_API_IMAGE}:${IOSIGN_VERSION}
    env_file: .env
    environment:
      DB_HOST: postgres
      REDIS_HOST: redis
    ports:
      - "127.0.0.1:${API_PORT}:${API_PORT}"
      - "127.0.0.1:${GRPC_PORT}:${GRPC_PORT}"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      migrations:
        condition: service_completed_successfully

volumes:
  postgres_data:
  redis_data:

The migrations service is a one-shot container: it applies the database schema and exits before the api service starts.

Step 3 — Start io.sign

docker compose config --quiet
docker compose up

Compose pulls the images, starts Postgres and Redis, runs migrations, then launches the API. The service is ready when the logs show the REST and gRPC servers listening on ports 3000 and 50051.

Step 4 — Verify

In another terminal:

curl --fail-with-body http://localhost:3000/v2/health/check
curl --fail-with-body --http2-prior-knowledge http://localhost:50051/health

Both should return 200 with JSON reporting a healthy service. The REST response must not be HTML: an unmatched path can return the playground with status 200. The gRPC listener requires HTTP/2; use a curl build with HTTP/2 support (check curl --version). Then open the interactive API playground in your browser:

http://localhost:3000/

The OpenAPI spec is served at http://localhost:3000/spec.json.

Step 5 — Continue to signing or stop the evaluation

To register signers, create a vault, and produce a signature, follow Get started with io.sign. A healthy API alone does not demonstrate a working signing ceremony.

To stop this evaluation:

docker compose down        # stop containers, keep data
docker compose down -v      # stop and wipe the database/Redis volumes

What's next

This evaluation setup intentionally leaves out a few things you need for end-to-end signing:

  • Authentication — re-enable it with JWT_ENABLED=true and point JWT_PROVIDERS at your identity provider. See Authentication.
  • A live license — set LICENSE_KEY to leave read-only mode.
  • An MQTT broker and signer devices — exercising a full signing ceremony requires an EMQX broker plus signer devices (the Virtual Signer and/or the Mobile Signer). See Deploying io.sign.

When you're ready to run io.sign for real, continue to Deploying io.sign and the Configuring io.sign reference.


Did this page help you?