Docker

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

Warning

  • 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.

Note

See the complete Deployment Configuration for in-depth details.

Requirements

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.

Steps

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

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

    docker-compose.yml

     1version: "3.7"
     2
     3volumes:
     4  rstuf-api-data:
     5  rstuf-mq-data:
     6  rstuf-storage:
     7  rstuf-redis-data:
     8  rstuf-pgsql-data:
     9
    10services:
    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
    19
    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
    32
    33  rstuf-worker:
    34    image: ghcr.io/repository-service-tuf/repository-service-tuf-worker:latest
    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_ONLINE_KEY_DIR: /var/opt/repository-service-tuf/keyvault
    42      RSTUF_BROKER_SERVER: redis://redis
    43      RSTUF_REDIS_SERVER: redis://redis
    44      RSTUF_SQL_SERVER: postgresql://postgres:secret@postgres:5432
    45
    46    depends_on:
    47      - postgres
    48      - redis
    49    healthcheck:
    50      test: "exit 0"
    51    restart: always
    52    tty: true
    53
    54  web-server:
    55    image: python:3.10-slim-buster
    56    command: python -m http.server -d /www 8080
    57    volumes:
    58      - rstuf-storage:/www
    59    ports:
    60      - "8080:8080"
    61
    62  rstuf-api:
    63    image: ghcr.io/repository-service-tuf/repository-service-tuf-api:latest
    64    volumes:
    65      - rstuf-api-data:/data
    66    ports:
    67      - 80:80
    68      - 443:443
    69    environment:
    70      RSTUF_BROKER_SERVER: redis://redis
    71      RSTUF_REDIS_SERVER: redis://redis
    72    depends_on:
    73      - 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:

    • Storage backend: RSTUF_STORAGE_BACKEND, RSTUF_LOCAL_STORAGE_BACKEND_PATH

    • Online Key directory: RSTUF_ONLINE_KEY_DIR

    • 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   ghcr.io/repository-service-tuf/repository-service-tuf-api:latest      "bash entrypoint.sh"     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   ghcr.io/repository-service-tuf/repository-service-tuf-worker:latest   "bash entrypoint.sh"     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.

Note

  • The setup and configuration requirements:

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

    • RSTUF service deployed

Note

  • 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.

Note

Required RSTUF CLI installed (See Installation)

❯ rstuf admin ceremony -h

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
  • Timestamp, Snapshot, and Targets metadata expiration policy

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

  • Delegations

    • Bins (online key only)

      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.

      This metadata is signed using the online key.

    • Custom Delegations (online/offline keys)

      Allows the RSTUF admin to create custom delegation that can use the online key or offline key(s) to sign the metadata. The custom delegation can be used to define the roles and paths for the target metadata.

  • Root metadata expiration policy

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

  • Root threshold

    It defines the number of keys required to sign the Root metadata before it’s considered trusted and will be published.

    That’s the minimum number of keys required to update and sign the TUF Root metadata. It’s required to be at least 2.

    Note

    • 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.

    Note

    RSTUF requires at least a threshold number of Root key(s) defined to finish the ceremony. The same applies when performing Metadata Update.

  • 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 (ceremony-payload.json) file. The Bootstrap requires the payload.

Note

The payload (ceremony-payload.json) contains only public data, it does not contain any 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 --out
Saved result to 'ceremony-payload.json'

If the Ceremony is done disconnected, the next step is to perform the bootstrap.

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 --api-server https://rstuf-api-url ceremony

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

To perform the boostrap you require the payload generated during the Bootstrap.

You can do it using the rstuf admin-legacy

❯ rstuf admin --api-server http://rstuf-api-url send bootstrap ceremony-payload.json
Starting online bootstrap
Bootstrap status: ACCEPTED (c1d2356d25784ecf90ce373dc65b05c7)
Bootstrap status:  STARTED
Bootstrap status:  SUCCESS
Bootstrap completed using `ceremony-payload.json`. 🔐 🎉

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 \