Skip to content

Sample Compose Files

Docker-Compose

A quick tour of the Compose file:

  • Some of these settings need to be coordinated with anything else that might be running on your host server
    • The network named “shield_net” is fairly unique but could theoretically conflict with other settings
    • Restart policies should be coordinated with your container orchestration
    • Listening ports (especially 80 and 443) should be checked to ensure that they don’t conflict with other running services
  • The volumes 'nullafi-activity' and 'cache' will be managed by Docker and are mapped to the Activity and Redis containers, respectively. They provide persistent storage for Shield’s configuration files and Activity log.
  • Environment variables
    • The sample Compose file uses environment variables to ensure that certain re-used items match each other (Hostname, for example). These also help make the Compose file more portable across systems to allow for re-use across multiple deployments.
    • There are multiple ways to pass environment variables to Docker Compose, but an easy method is to create a file named .env (mind the leading dot) in the same directory as the docker-compose.yml file
  • The &all-shields YAML block serves a similar purpose to the environment variables, ensuring that multiple Shield instances use the same settings so that they can communicate with each other, and enhancing the readability of the overall docker-compose.yml file.
  • Services
    • Shield instances
      • Multiple instances
        • The sample Compose file demonstrates that Shield instances can split duties. NULLAFI_SERVERMODE = "both" would allow a single instance to be both the Admin interface and the ICAP server at the same time.
        • A single Admin interface instance (NULLAFI_SERVERMODE = "web") can support many ICAP instances. In a geographically distributed deployment, an organization might have many proxies. In that case, it would be wise to deploy ICAP instances nearby to the proxies to reduce latency. A single Web instance can be used to configure policy and collect Activity data from all of the ICAP instances.
        • Dedicated ICAP instances (NULLAFI_SERVERMODE = "icap") only need to have access to the configuration and activitiy databases in order to serve as remote policy enforcement nodes.
      • shield-web-ui -- This is the Shield instance serving as the Admin interface
        • Ports 80 and 443 are exposed to the internet for Administrators to access the interface using their browsers.
        • When using a license key file rather than just the raw value, the volume mount method is used to pass the file to the container
        • NULLAFI_PROXY_CERT_FILE and NULLAFI_PROXY_URL are used to define behavior of the automatically-generated PAC file (see Configuration >> ICAP)
        • NULLAFI_HTTPS_ENABLE_ACME tells the Admin server to use Let's Encrypt to obtain valid SSL certificates for the HTTPS interface. This requires both ports 80 and 443.
      • shield-icap -- This is the Shield instance that will be the proxy's ICAP server
        • Port 1344 is the standard ICAP port. Port 11344 is used for Secure ICAP connections (ICAP over SSL)
        • The NULLAFI_ICAP_NAME appears in the Admin interface to identify this ICAP server (useful when there are multiple ICAP servers, and for when you wish to write policy that only applies to certain ICAP servers)
    • Other container instances
      • squid -- The sample Compose file brings up a Squid instance for testing convenience.
        • It requires a port to be exposed to the internet in order to accept client connections. This file uses the environment variable ${PROXY_PORT}.
        • The sample Squid proxy is configured to accept HTTPS connections and to use the MITM_CERT and MITM_KEY to sign the emulated certificates
      • activity -- Nullafi Shield uses an Elasticsearch database to store and search Activity log records. Shield instances can be pointed to any existing Elasticsearch database, but this sample Compose file creates a new one here.
      • redis -- Nullafi Shield uses Redis to store configuration data (Rules, ICAP configuration, directory integrations, etc.). This sample Compose file creates a redis database here.

Example Compose File

docker-compose.yml
version: "3.7"

# This file relies on the presence of the ${HOST_NAME} environment variable,
# among others. These can be created when running the docker compose command, or
# by placing a .env file in the same directory as the docker-compose.yml flie.


networks:
  shield_net:
    name:                          shield_net
    driver:                        bridge

volumes:
  nullafi-activity:                # Activity Database
  cache:                           # Redis Cache


x-environment: &all-shields
  NULLAFI_HTTP_CUSTOM_DOMAIN:     "${HOST_NAME:?err}"
  NULLAFI_WEB_SERVER_URL:         "https://${HOST_NAME}"
  # License Key -- use only one of either 'file' or 'value'
  NULLAFI_LICENSE_KEY_FILE:       "/nullafi/license.key"
#  NULLAFI_LICENSE_KEY_VALUE:      "${NULLAFI_LICENSE_KEY:?err}"
  NULLAFI_ACTIVITY_DATABASE_URL:   "http://elastic:elastic@activity:9200"
  NULLAFI_REDIS_URI:               "redis://redis:6379/0"



services:

  shield-web-ui:
    image:                         "${SHIELD_IMAGE:?err}"
    container_name:                shield-web-ui
    restart:                       "${RESTART_POLICY:?err}"
    networks:
      shield_net:
        aliases:
          -                        "${HOST_NAME}"
    depends_on:
      -                            redis
      -                            activity
    ports:
      -                            "80:8080"
      -                            "443:443"
    volumes:
      -                            "${NULLAFI_LICENSE_KEY_FILE:?err}:/nullafi/license.key:ro"
      -                            "${PROXY_MITM_CERT:?err}:/apps/nullafi/user-data/nullafi.crt:ro"
    environment:
      <<: *all-shields
      NULLAFI_SERVERMODE:           "web"
      NULLAFI_PROXY_CERT_FILE:      "/apps/nullafi/user-data/nullafi.crt"
      NULLAFI_PROXY_URL:            "${HOST_NAME}:${PROXY_PORT}"
      NULLAFI_HTTPS_PORT:           443
      NULLAFI_HTTPS_ENABLED:        "true"
      NULLAFI_HTTPS_ENABLE_ACME:    "true"


  shield-icap:
    image:                         "${SHIELD_IMAGE}"
    container_name:                policy1
    hostname:                      policy1                        # this hostname is used by the proxy (service ‘squid’ defined below)
    restart:                       "${RESTART_POLICY}"
    networks:
      -                            shield_net
    depends_on:
      -                            shield-web-ui
    ports:
      -                            "1344:1344"
      -                            "11344:11344"
    volumes:                                                      # comment this out if using License Key Value
      -                            "${NULLAFI_LICENSE_KEY_FILE:?err}:/nullafi/license.key:ro"  # comment this out if using License Key Value
    environment:
      <<: *all-shields
      NULLAFI_SERVERMODE:          "icap"
      NULLAFI_ICAP_NAME:           "Policy 1"


  squid:
    image:                         "${SQUID_IMAGE:?err}"
    container_name:                squid
    hostname:                      squid
    restart:                       "${RESTART_POLICY}"
    networks:
      -                            shield_net
    depends_on:
      -                            shield-web-ui
    mem_limit:                     400m
    ports:
      -                            "${PROXY_PORT}:44509"
#    volumes:                                                                        # To use a non-Nullafi signing certificate, make it available with
#      -                           "${PROXY_MITM_CERT:?err}:/etc/squid5/custom.crt"   # these volume mounts and set the environment values for MITM_CERT
#      -                           "${PROXY_MITM_KEY:?err}:/etc/squid5/custom.pem"    # and MITM_KEY by un-commenting the lines below
    environment:
#      MITM_CERT:                   "/etc/squid5/custom.crt"
#      MITM_KEY:                    "/etc/squid5/custom.pem"
      ICAP_URL:                    "icap://policy1:1344"
      ENABLE_ICAP:                 "yes"
#      ENABLE_ICAPS:                "yes"


  activity:
    image:                         "${ELASTIC_IMAGE:?err}"
    container_name:                activity
    hostname:                      activity
    restart:                       "${RESTART_POLICY}"
    networks:
      -                            shield_net
    mem_limit:                     2g
    ulimits:
      memlock:
        soft:                      -1
        hard:                      -1
    volumes:
      -                            nullafi-activity:/usr/share/elasticsearch/data
    environment:
      -                            node.name=es01
      -                            cluster.name=activity
      -                            cluster.initial_master_nodes=es01
      -                            ELASTIC_PASSWORD=elastic
      -                            bootstrap.memory_lock=true
      -                            xpack.security.enabled=false


  redis:
    image:                         "${REDIS_IMAGE:?err}"
    container_name:                redis
    hostname:                      redis
    restart:                       "${RESTART_POLICY}"
    networks:
      -                            shield_net
    command:                       redis-server --save 20 1 --loglevel warning
    mem_limit:                     300m
    volumes:
      -                            cache:/data

Example environment variable File

.env
# Shield hostname
  HOST_NAME=test.host.name

# Shield license
  # for license key file (env variable value should be the path to the file)
  NULLAFI_LICENSE_KEY_FILE=./license.file
#  # for license key value ( env variable value should be the raw license key)
#  NULLAFI_LICENSE_KEY=IDAECEIYLUM*VERY_LONG_STRING_HERE*AL7YMAAAAD7ACBH7QIA77


# Docker images
  # Nullafi Shield
  SHIELD_IMAGE=public.ecr.aws/c9g3b3w9/shield:v2.4.11
  # Squid proxy image
  SQUID_IMAGE=public.ecr.aws/c9g3b3w9/proxy:5.0
  # Elasticsearch container
  ELASTIC_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:8.7.0
  # Redis container
  REDIS_IMAGE=redis:6.2-alpine


# Squid Certificates
  PROXY_MITM_CERT=./my.cert.file
  PROXY_MITM_KEY=./my.cert.key

# Proxy port
  PROXY_PORT=44509

# Restart Policy
  RESTART_POLICY="unless-stopped"
#  RESTART_POLICY="always"