This deployment uses Docker Engine and Docker Compose yaml file to deploy RSTUF.


  • There are limitations to scaling this deployment strategy, as all nodes are running in the same host.

  • This deployment is recommended for Tests, Development, POC and POV.

  • This deployment does not use secrets for sensitive credentials.


See the complete Deployment Configuration for in-depth details.


Software and tools

  • Docker Engine (with docker-compose)

  • Python >= 3.10

  • pip

Online Key

This deployment requires the Online Key. See the chapter Signing Keys

Skip this section if an online key has already been generated.

RSTUF Command Line Interface (CLI) provides a feature for Key Generation (generate)

This command will generate cryptographic keys using the securesystemslib library. The user is requested to provide:

  1. the key type, from the supported list of encryption algorithms

  2. the key’s filename, whose path will be the current working directory

  3. a password, to encrypt the private key file

After the above procedure, two files, the private and public key (e.g., id_ed25519 and, will be generated in the current working directory.

The generated keys may be used in the Repository Service for TUF Ceremony process, for the online key or the TUF roles’ keys (root, targets, etc. keys).

❯ rstuf key generate

Choose key type [ed25519/ecdsa/rsa] (ed25519): ed25519
Enter the key's filename: (id_ed25519): id_ed25519
Enter password to encrypt private key file 'id_ed25519':

┃                   Key ID                   ┃ Key Type ┃                Public Key                 ┃
│ f2f9f111b4a8dfb3766c8066628c81bd3aef42b34… │ ed25519  │ bb713c55bbf9b13ff7f92193af55b2f65ae15e55… │


  1. Create a folder local-keyvault and add the online key

$ mkdir local-keyvault
$ cp path/my/online.key local-keyvault/
  1. Create a Docker Compose (functional example below)


     1version: "3.7"
     4  rstuf-api-data:
     5  rstuf-mq-data:
     6  rstuf-storage:
     7  rstuf-redis-data:
     8  rstuf-pgsql-data:
    11  redis:
    12    image: redis:4.0
    13    volumes:
    14      - rstuf-redis-data:/data
    15    healthcheck:
    16      test: "exit 0"
    17    restart: always
    18    tty: true
    20  postgres:
    21    image: postgres:15.1
    22    ports:
    23      - "5433:5432"
    24    # DO NOT USE IT IN PRODUCTION. Check the Postgres best practices
    25    environment:
    26      - POSTGRES_PASSWORD=secret
    27    volumes:
    28      - "rstuf-pgsql-data:/var/lib/postgresql/data"
    29    healthcheck:
    30      test: ["CMD", "pg_isready", "-U", "postgres", "-d", "postgres"]
    31      interval: 1s
    33  rstuf-worker:
    34    image:
    35    volumes:
    36      - rstuf-storage:/var/opt/repository-service-tuf/storage
    37      - ./local-keyvault/:/var/opt/repository-service-tuf/keyvault/ # map the path where is your key
    38    environment:
    39      RSTUF_STORAGE_BACKEND: LocalStorage
    40      RSTUF_LOCAL_STORAGE_BACKEND_PATH: /var/opt/repository-service-tuf/storage
    41      RSTUF_KEYVAULT_BACKEND: LocalKeyVault
    42      RSTUF_LOCAL_KEYVAULT_PATH: /var/opt/repository-service-tuf/keyvault
    43      RSTUF_LOCAL_KEYVAULT_KEYS: online.key,strongPass
    44      RSTUF_BROKER_SERVER: redis://redis
    45      RSTUF_REDIS_SERVER: redis://redis
    46      RSTUF_SQL_SERVER: postgresql://postgres:secret@postgres:5432
    48    depends_on:
    49      - postgres
    50      - redis
    51    healthcheck:
    52      test: "exit 0"
    53    restart: always
    54    tty: true
    56  web-server:
    57    image: python:3.10-slim-buster
    58    command: python -m http.server -d /www 8080
    59    volumes:
    60      - rstuf-storage:/www
    61    ports:
    62      - "8080:8080"
    64  rstuf-api:
    65    image:
    66    volumes:
    67      - rstuf-api-data:/data
    68    ports:
    69      - 80:80
    70      - 443:443
    71    environment:
    72      RSTUF_BROKER_SERVER: redis://redis
    73      RSTUF_REDIS_SERVER: redis://redis
    74    depends_on:
    75      - rstuf-worker

The general explanation about this Docker Compose yaml file:

  • It uses Docker Volume for the persistent data and Volumes

  • rstuf-storage: public TUF Metadata. Using RSTUF Worker with LocalKeyVault storage backend.

  • rstuf-redis-data: Persistent Redis data

  • rstuf-pgsql-data: Persistent PostgresSQL data

  • It uses Redis for the task results and RSTUF configuration.

  • It uses a simple python container as the webserver to expose the public TUF metadata from rstuf-storage volume

  • It provisions the repository-service-tuf-api configuration as environment variables: - Broker Server: RSTUF_BROKER_SERVER - Redis Server: RSTUF_REDIS_SERVER

  • It provisions the repository-service-tuf-worker configuration as environment variables:



    • Broker Server: RSTUF_BROKER_SERVER

    • Redis Server: RSTUF_REDIS_SERVER

    • SQL (Postgres) Server: RSTUF_SQL_SERVER

  1. Run using Docker stack

    $ docker stack deploy -c docker-compose.yml rstuf
    Ignoring unsupported options: restart
    Creating network rstuf_default
    Creating service rstuf_redis
    Creating service rstuf_postgres
    Creating service rstuf_rstuf-worker
    Creating service rstuf_web-server
    Creating service rstuf_rstuf-api
  2. Check if all services are running and health

$ docker ps -a
CONTAINER ID   IMAGE                                                                 COMMAND                  CREATED              STATUS                        PORTS                                                                  NAMES
f3eb8e38c244   postgres:15.1                                                         "docker-entrypoint.s…"   59 seconds ago       Up 58 seconds (healthy)       5432/tcp                                                               rstuf_postgres.1.n9bculkxiikst502oneq2y1tl
00831512a35d   redis:4.0                                                             "docker-entrypoint.s…"   About a minute ago   Up About a minute (healthy)   6379/tcp                                                               rstuf_redis.1.gy8owq16qa0fbgyklr6ji1hyy
a15dc8f6f3c9      "bash"     About a minute ago   Up About a minute                                                                                    rstuf_rstuf-api.1.o8zmoccz2n4vnxemczlrrg3o9
40d410b9c6ff   python:3.10-slim-buster                                               "python -m http.serv…"   About a minute ago   Up About a minute                                                                                    rstuf_web-server.1.s29tparemtrj5tut6l41in8ah
5762860c1ccc   "bash"     About a minute ago   Up About a minute (healthy)                                                                          rstuf_rstuf-worker.1.aq20wunul0z9lla0nkpo303zn

Verify rstuf_rstuf-worker logs

docker service logs rstuf_rstuf-worker --raw
  1. RSTUF Ceremony and Bootstrap

Repository Service for TUF (RSTUF) has two specific processes as part of the initial setup: Ceremony and Bootstrap.


  • The setup and configuration requirements:

    • Set of root key(s) and online key for signing

    • RSTUF service deployed


  • It is a one-time process to setup the RSTUF service. If this process is completed during the deployment do not run it again.

RSTUF Command Line Interface provides a guided process for the Ceremony and Bootstrap.

To make this process easier, the Repository Service for TUF CLI provides an interactive guided process to perform the Ceremony.


Required RSTUF CLI installed (See Installation)

❯ rstuf admin ceremony -h

A video demonstrating this process is available.

The Ceremony defines the RSTUF settings/configuration and generates the initial signed TUF root metadata.

It does not activate the RSTUF service. It generates the required JSON payload to bootstrap the RSTUF service.

The Ceremony can be done Connected as a specific step or Disconnected, combined with Bootstrap.

This process generates the initial metadata and defines some settings of the TUF service.

See settings details
  • Root metadata expiration policy

    Defines how long this metadata is valid, for example, 365 days (year). This metadata is invalid when it expires.

  • Root number of keys

    It is the total number of root keys (offline keys) used by the TUF Root metadata. The number of keys implies that the number of identities is the TUF Metadata’s top-level administrator.


    • Updating the Root metadata with new expiration, changing/updating keys or the number of keys, threshold, or rotating a new online key and sign requires following the Metadata Update process.


    RSTUF requires all Root key(s) during the Ceremony.


    RSTUF requires at least the threshold number of Root key(s) for Metadata Update.

  • Root key threshold

    The minimum number of keys required to update and sign the TUF Root metadata.

  • Targets, BINS, Snapshot, and Timestamp metadata expiration policy

    Defines how long this metadata is valid. The metadata is invalid when it expires.

  • Targets number of delegated hash bin roles

    The target metadata file might contain a large number of artifacts. The target role delegates trust to the hash bin roles to reduce the metadata overhead for clients.

  • Targets base URL

    The base URL path for downloading all artifacts. Example:

  • Signing

    This process will also require the Online Key and Root Key(s) (offline) for signing the initial root TUF metadata.

The settings are guided during Ceremony.

The disconnected Ceremony will only generate the required JSON payload (payload.json) file. The Bootstrap requires the payload.


The payload (payload.json) contains only public data, it does not contain private keys.

This process is appropriate when performing the Ceremony on a disconnected computer to RSTUF API to perform the Bootstrap later as a separate step.

❯ rstuf admin ceremony

The connected Ceremony generates the JSON payload file and run the Bootstrap request to RSTUF API.

This process is appropriate when performing the Ceremony on a computer connected to RSTUF API. It does not require a Bootstrap step.

❯ rstuf admin ceremony -b

If a Ceremony Connected is complete, skip this, as the RSTUF service is ready.

If a Ceremony Disconnected is complete, it requires running the Bootstrap from a computer connected to the RSTUF API.

❯ rstuf admin ceremony -b -u

Remove RSTUF deployment

Remove the Stack

$ docker stack rm rstuf
Removing service rstuf_rstuf-worker
Removing service rstuf_rstuf-api
Removing service rstuf_redis
Removing service rstuf_web-server
Removing network rstuf_default

Remove all data

$ docker volume rm rstuf_repository-service-tuf-worker-data \
  rstuf_rstuf-storage \
  rstuf_rstuf-keystorage \
  rstuf_rstuf-redis-data \