Greenbone 社群版(OpenVAS) 使用 docker-compose + cron 排程每日自動更新 feed

以前裝過無數次OpenVAS,不論是否使用Docker,一天到晚就卡更新feed,常更新不完,每次要掃描時,就要開始擔心feed更新不完,這次改使用 docker-compose.yml + cron排程使用shell script方式進行每日自動更新 (排除 watchtower 自動更新,用watchtower更新會只有部份image更新重啟,有時就會造成錯誤)

執行環境:Rocky Linux 9 or 10 + Docker CE + docker compose plugin
路徑: /docker/openvas
GVM http port: 9392 (如果額外需要https,可配合nginx proxymanager或haproxy+certbot等)

mkdir -p /docker/openvas
cd /docker/openvas

新增 docker-compose.yml (2026/01/14更新,新增pg-gvm-migrator,避免 DB schema 升級失敗造成 pg-gvm 起不來。此範例基於官方 Greenbone Community Containers compose 調整)

name: greenbone-community-edition

services:
  vulnerability-tests:
    image: registry.community.greenbone.net/community/vulnerability-tests
    environment:
      FEED_RELEASE: "24.10"
      KEEP_ALIVE: 1
    volumes:
      - vt_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  notus-data:
    image: registry.community.greenbone.net/community/notus-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - notus_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  scap-data:
    image: registry.community.greenbone.net/community/scap-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - scap_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  cert-bund-data:
    image: registry.community.greenbone.net/community/cert-bund-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - cert_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  dfn-cert-data:
    image: registry.community.greenbone.net/community/dfn-cert-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - cert_data_vol:/mnt
    depends_on:
      cert-bund-data:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  data-objects:
    image: registry.community.greenbone.net/community/data-objects
    environment:
      FEED_RELEASE: "24.10"
      KEEP_ALIVE: 1
    volumes:
      - data_objects_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  report-formats:
    image: registry.community.greenbone.net/community/report-formats
    environment:
      FEED_RELEASE: "24.10"
      KEEP_ALIVE: 1
    volumes:
      - data_objects_vol:/mnt
    depends_on:
      data-objects:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  gpg-data:
    image: registry.community.greenbone.net/community/gpg-data
    volumes:
      - gpg_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  redis-server:
    image: registry.community.greenbone.net/community/redis-server
    restart: on-failure
    volumes:
      - redis_socket_vol:/run/redis/
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  pg-gvm:
    image: registry.community.greenbone.net/community/pg-gvm:stable
    restart: on-failure:10
    volumes:
      - psql_data_vol:/var/lib/postgresql
      - psql_socket_vol:/var/run/postgresql
    depends_on:
      pg-gvm-migrator:
        condition: service_completed_successfully
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  pg-gvm-migrator:
    image: registry.community.greenbone.net/community/pg-gvm-migrator:stable
    restart: no
    volumes:
      - psql_data_vol:/var/lib/postgresql
      - psql_socket_vol:/var/run/postgresql

  gvmd:
    image: registry.community.greenbone.net/community/gvmd:stable
    restart: on-failure
    environment:
      MTA_HOST: ${MAIL_HOST}
      MTA_PORT: ${MAIL_PORT}
      MTA_TLS: ${MAIL_TLS}
      MTA_STARTTLS: ${MAIL_STARTTLS}
      MTA_AUTH: ${MAIL_AUTH}
      MTA_USER: ${MAIL_USER}
      MTA_FROM: ${MAIL_FROM}
      MTA_PASSWORD: ${MAIL_PASSWORD}
    volumes:
      - gvmd_data_vol:/var/lib/gvm
      - scap_data_vol:/var/lib/gvm/scap-data/
      - cert_data_vol:/var/lib/gvm/cert-data
      - data_objects_vol:/var/lib/gvm/data-objects/gvmd
      - vt_data_vol:/var/lib/openvas/plugins
      - psql_data_vol:/var/lib/postgresql
      - gvmd_socket_vol:/run/gvmd
      - ospd_openvas_socket_vol:/run/ospd
      - psql_socket_vol:/var/run/postgresql
    depends_on:
      pg-gvm:
        condition: service_started
      scap-data:
        condition: service_healthy
      cert-bund-data:
        condition: service_healthy
      dfn-cert-data:
        condition: service_healthy
      data-objects:
        condition: service_healthy
      report-formats:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  gsa:
    image: registry.community.greenbone.net/community/gsa:stable
    restart: on-failure
    ports:
      - 9392:80
    volumes:
      - gvmd_socket_vol:/run/gvmd
    depends_on:
      gvmd:
        condition: service_started
  # Sets log level of openvas to the set LOG_LEVEL within the env
  # and changes log output to /var/log/openvas instead /var/log/gvm
  # to reduce likelyhood of unwanted log interferences
  configure-openvas:
    image: registry.community.greenbone.net/community/openvas-scanner:stable
    volumes:
      - openvas_data_vol:/mnt
      - openvas_log_data_vol:/var/log/openvas
    command:
      - /bin/sh
      - -c
      - |
        printf "table_driven_lsc = yes\nopenvasd_server = http://openvasd:80\n" > /mnt/openvas.conf
        sed "s/127/128/" /etc/openvas/openvas_log.conf | sed 's/gvm/openvas/' > /mnt/openvas_log.conf
        chmod 644 /mnt/openvas.conf
        chmod 644 /mnt/openvas_log.conf
        touch /var/log/openvas/openvas.log
        chmod 666 /var/log/openvas/openvas.log
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  # shows logs of openvas
  openvas:
    image: registry.community.greenbone.net/community/openvas-scanner:stable
    restart: on-failure
    volumes:
      - openvas_data_vol:/etc/openvas
      - openvas_log_data_vol:/var/log/openvas
    command:
      - /bin/sh
      - -c
      - |
        cat /etc/openvas/openvas.conf
        tail -f /var/log/openvas/openvas.log
    depends_on:
      configure-openvas:
        condition: service_completed_successfully
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  openvasd:
    image: registry.community.greenbone.net/community/openvas-scanner:stable
    restart: on-failure
    environment:
      # `service_notus` is set to disable everything but notus,
      # if you want to utilize openvasd directly removed `OPENVASD_MODE`
      OPENVASD_MODE: service_notus
      GNUPGHOME: /etc/openvas/gnupg
      LISTENING: 0.0.0.0:80
    volumes:
      - openvas_data_vol:/etc/openvas
      - openvas_log_data_vol:/var/log/openvas
      - gpg_data_vol:/etc/openvas/gnupg
      - notus_data_vol:/var/lib/notus
    # enable port forwarding when you want to use the http api from your host machine
    # ports:
    #   - 127.0.0.1:3000:80
    depends_on:
      vulnerability-tests:
        condition: service_healthy
      notus-data:
        condition: service_healthy
      configure-openvas:
        condition: service_completed_successfully
      gpg-data:
        condition: service_completed_successfully
    networks:
      default:
        aliases:
          - openvasd
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  ospd-openvas:
    image: registry.community.greenbone.net/community/ospd-openvas:stable
    restart: on-failure
    hostname: ospd-openvas.local
    cap_add:
      - NET_ADMIN # for capturing packages in promiscuous mode
      - NET_RAW # for raw sockets e.g. used for the boreas alive detection
    security_opt:
      - seccomp=unconfined
      - apparmor=unconfined
    command:
      [
        "ospd-openvas",
        "-f",
        "--config",
        "/etc/gvm/ospd-openvas.conf",
        "--notus-feed-dir",
        "/var/lib/notus/advisories",
        "-m",
        "666",
      ]
    volumes:
      - gpg_data_vol:/etc/openvas/gnupg
      - vt_data_vol:/var/lib/openvas/plugins
      - notus_data_vol:/var/lib/notus
      - ospd_openvas_socket_vol:/run/ospd
      - redis_socket_vol:/run/redis/
      - openvas_data_vol:/etc/openvas/
      - openvas_log_data_vol:/var/log/openvas
    depends_on:
      redis-server:
        condition: service_started
      gpg-data:
        condition: service_completed_successfully
      configure-openvas:
        condition: service_completed_successfully
      vulnerability-tests:
        condition: service_healthy
      notus-data:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  gvm-tools:
    image: registry.community.greenbone.net/community/gvm-tools
    volumes:
      - gvmd_socket_vol:/run/gvmd
      - ospd_openvas_socket_vol:/run/ospd
    depends_on:
      - gvmd
      - ospd-openvas
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

volumes:
  gpg_data_vol:
  scap_data_vol:
  cert_data_vol:
  data_objects_vol:
  gvmd_data_vol:
  psql_data_vol:
  vt_data_vol:
  notus_data_vol:
  psql_socket_vol:
  gvmd_socket_vol:
  ospd_openvas_socket_vol:
  redis_socket_vol:
  openvas_data_vol:
  openvas_log_data_vol:

新增檔案 .env (如果需要發通知信的話,否則docker-compose.yml中,gvmd:的environment相對應的參數設定可移除)

# SMTP Settings
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_TLS=on
MAIL_STARTTLS=on
MAIL_AUTH=on
MAIL_USER=your_google_account
MAIL_FROM=your@gmail.com
MAIL_PASSWORD=your_google_app_password

新增檔案 update.sh (記得要chmod +x update.sh)

#!/bin/bash

# 設定目錄
OPENVAS_DIR="/docker/openvas"
cd "$OPENVAS_DIR" || exit 1

echo "--- [$(date)] 開始執行維護任務 ---"

# 1. 預先清空應用程式日誌
echo "正在清理 Volume 內的應用程式日誌..."
find /var/lib/docker/volumes/greenbone-community-edition_openvas_log_data_vol/_data -name "*.log" -exec truncate -s 0 {} +

# 2. 下載影像並包含重試機制 (解決 TLS Timeout 問題)
echo "正在下載最新影像..."
MAX_RETRIES=5
COUNT=0
while [ $COUNT -lt $MAX_RETRIES ]; do
    /usr/bin/docker compose pull -q && break
    COUNT=$((COUNT + 1))
    echo "下載失敗,10 秒後進行第 $COUNT 次重試..."
    sleep 10
done

# 3. 重新啟動服務以套用新影像與 Logging 限制
echo "正在重啟容器..."
/usr/bin/docker compose up -d

# 4. 深度清理磁碟
echo "正在清理過期影像與快取..."
# 清理未使用且超過 30 天的 image
/usr/bin/docker image prune -f --filter "until=720h"
/usr/bin/docker system prune -f

echo "--- [$(date)] 維護完成,剩餘空間:$(df -h / | awk 'NR==2 {print $4}') ---"

在 /etc/crontab 加入 (每天 04:00 自動執行,可自行調整)

0 4 * * * root /docker/openvas/update.sh >> /var/log/openvas_update.log 2>&1

首次部署時,請先在 /docker/openvas 目錄手動執行一次 docker compose pull && docker compose up -d,確認 GVM 初始化與 feed 首次同步完成後,再交給 crontab 例行更新。

Reference: Greenbone Community Documentation – Containers

發佈留言