antony@notes:~/container$ cat "Podman-Deploy-Neuvector-AllInOne.md"
Podman Deploy Neuvector AllInOne
Podman Deploy Neuvector AllInOne
Deploy allinone (NO privileged mode) with podman
1. 準備環境
- 建立 NeuVector 用於持久化儲存設定檔的目錄
sudo mkdir /var/neuvector - 設定開機自動啟動並立即啟動 Podman socket
sudo systemctl enable --now podman.socket - 建立一個 systemd 服務,將 Podman 的 socket 軟連結到傳統 Docker 的 socket 路徑,這是為了讓需要和 Docker API 互動的應用程式 (如此處的 NeuVector) 能無縫地與 Podman 運作
sudo tee /etc/systemd/system/podman-docker-symlink.service <<'EOF' [Unit] Description=Create symlink from docker.sock to podman.sock After=podman.socket [Service] Type=oneshot ExecStart=/bin/ln -sf /run/podman/podman.sock /var/run/docker.sock RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF - 設定開機自動啟動並立即啟動建立 symlink 的服務
sudo systemctl enable --now podman-docker-symlink.service
2. 建立 NeuVector 內部元件 (Controller, Enforcer, Scanner) 之間加密通訊所需的 TLS 憑證
- 建立存放憑證的目錄,並進入該目錄
sudo mkdir -p /etc/neuvector/certs/internal; cd /etc/neuvector/certs/internal - 建立 OpenSSL 設定檔,用於定義憑證的內容 (如國家、組織、SANs 等)
sudo tee /etc/neuvector/certs/internal/ca.cfg <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = TW ST = Taipei L = San Jose O = NeuVector Inc. OU = Neuvector CN = Neuvector [v3_req] keyUsage = digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alt_names [alt_names] DNS.1 = Neuvector EOF - 產生 CA (憑證頒發機構) 的私鑰
sudo openssl genrsa -out ca.key 2048 - 使用 CA 私鑰產生 CA 的根憑證
sudo openssl req -x509 -sha256 -new -nodes -key ca.key -days 3650 -subj "/C=TW/ST=Taipei/L=Taipei/O=NeuVector Inc./OU=Neuvector/CN=Neuvector" -out ca.cert - 產生給服務使用的私鑰
sudo openssl genrsa -out cert.key 2048 - 產生憑證簽署請求 (CSR)
sudo openssl req -new -key cert.key -sha256 -out cert.csr -config ca.cfg - 使用 CA 簽署 CSR,產生最終給服務使用的憑證
sudo openssl x509 -req -sha256 -in cert.csr -CA ca.cert -CAkey ca.key -CAcreateserial -out cert.pem -days 3650 -extensions 'v3_req' -extfile ca.cfg
3. 啟動 NeuVector App Container
動態獲取主機指定網路介面 (此處為 ens18) 的 IP 位址,並存入變數
IP,這個 IP 將用來告訴 NeuVector 元件如何互相連線NIC='ens18' && \ IP=$(ip -4 -o addr show ${NIC} | awk '{print $4}' | cut -d/ -f1)啟動 NeuVector 的 All-in-One main container (包含 Controller, Enforcer, Manager)
sudo podman run -d --name allinone \ --pid=host \ --cap-add=SYS_ADMIN \ --cap-add=NET_ADMIN \ --cap-add=SYS_PTRACE \ --cap-add=IPC_LOCK \ --security-opt label=disable \ --security-opt apparmor=unconfined \ --security-opt seccomp=unconfined \ -e CLUSTER_JOIN_ADDR=${IP} \ -e NV_PLATFORM_INFO=platform=Docker \ -e CTRL_PERSIST_CONFIG=1 \ -p 18300:18300 \ -p 18301:18301 \ -p 18400:18400 \ -p 18401:18401 \ -p 18301:18301/udp \ -p 8443:8443 \ -v /lib/modules:/lib/modules:ro \ -v /var/neuvector:/var/neuvector \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /sys/fs/cgroup:/host/cgroup:ro \ -v /proc:/host/proc:ro \ -v /etc/neuvector/certs/internal:/etc/neuvector/certs/internal/:ro \ docker.io/neuvector/allinone:5.4.9--pid=host, --cap-add=...等參數是為了賦予 container 足夠的權限來監控主機的程序與網路活動-e CLUSTER_JOIN_ADDR=${IP}設定叢集加入位址-v 掛載主機路徑,讓 container 能存取 Docker socket、主機核心模組、cgroup 及程序資訊,並持久化設定與讀取憑證
啟動 NeuVector 的 Scanner container,專門用於執行映像檔弱點掃描,它會透過
CLUSTER_JOIN_ADDR連接到 All-in-One Neuvector Controllersudo podman run -td --name scanner \ -e CLUSTER_JOIN_ADDR=${IP} \ -e NV_PLATFORM_INFO=platform=Docker \ -p 18402:18402 \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /etc/neuvector/certs/internal:/etc/neuvector/certs/internal/:ro \ docker.io/neuvector/scanner:latest
4. 設定 Neuvector Allinone container 開機自動啟動
建立環境變數檔
sudo mkdir -p /etc/neuvector sudo tee /etc/neuvector/allinone.env >/dev/null <<'EOF' # 請把下行改成你的 IP CLUSTER_JOIN_ADDR=192.168.11.131 NV_PLATFORM_INFO=platform=Docker CTRL_PERSIST_CONFIG=1 EOF建立 Quadlet
.container檔案sudo nano /etc/containers/systemd/allinone.container設定內容如下 :
注意,
CLUSTER_JOIN_ADDR的值需依照環境而設定[Unit] Description=NeuVector All-in-One (via Podman Quadlet) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/neuvector /lib/modules /etc/neuvector/certs/internal [Container] Image=docker.io/neuvector/allinone:5.4.9 ContainerName=allinone PodmanArgs=--pid=host --security-opt apparmor=unconfined AddCapability=SYS_ADMIN AddCapability=NET_ADMIN AddCapability=SYS_PTRACE AddCapability=IPC_LOCK # 環境變數 EnvironmentFile=/etc/neuvector/allinone.env # Port 對應(含 UDP) PublishPort=18300:18300 PublishPort=18301:18301 PublishPort=18400:18400 PublishPort=18401:18401 PublishPort=18301:18301/udp PublishPort=8443:8443 # Volume 對應 Volume=/lib/modules:/lib/modules:ro Volume=/var/neuvector:/var/neuvector Volume=/var/run/docker.sock:/var/run/docker.sock:ro Volume=/sys/fs/cgroup:/host/cgroup:ro Volume=/proc:/host/proc:ro Volume=/etc/neuvector/certs/internal:/etc/neuvector/certs/internal:ro # 若希望啟動時一定拉一次映像檔,可取消註解 # Pull=always [Service] Restart=always RestartSec=5s TimeoutStartSec=600 [Install] WantedBy=multi-user.target重載 systemd daemon:
sudo systemctl daemon-reload啟用並立即啟動服務:
sudo systemctl start allinone.service如果噴錯代表 podman Quadlet 的設定檔有寫錯,請執行以下命令確認設定檔哪裡有錯
sudo /usr/libexec/podman/quadlet -dryrun檢查 systemd 服務狀態:
systemctl status allinone.service正確執行結果:
● allinone.service - NeuVector All-in-One (via Podman Quadlet) Loaded: loaded (/etc/containers/systemd/allinone.container; generated) Active: active (running) since Fri 2025-08-15 17:30:42 CST; 9min ago Main PID: 3957 (conmon) Tasks: 83 (limit: 50507) Memory: 897.2M CPU: 13.760s ...以下省略使用 podman 確認容器狀態:
sudo podman ps -a --filter name=allinone正確執行結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7963890f525a docker.io/neuvector/allinone:5.4.9 40 seconds ago Up 41 seconds 0.0.0.0:8443->8443/tcp, 0.0.0.0:10443->10443/tcp, 0.0.0.0:18300-18301->18300-18301/tcp, 0.0.0.0:18400-18401->18400-18401/tcp, 0.0.0.0:18301->18301/udp allinone
5. 設定 Neuvector scanner container 開機自動啟動
建立環境變數檔
sudo tee /etc/neuvector/scanner.env >/dev/null <<'EOF' # 請把下行改成你的 IP CLUSTER_JOIN_ADDR=192.168.11.131 NV_PLATFORM_INFO=platform=Docker EOF建立 Quadlet
.container檔案sudo nano /etc/containers/systemd/scanner.container設定內容如下 :
注意,
CLUSTER_JOIN_ADDR的值需依照環境而設定# /etc/containers/systemd/scanner.container [Unit] Description=NeuVector Scanner (via Podman Quadlet) Wants=network-online.target After=network-online.target [Container] ContainerName=scanner Image=docker.io/neuvector/scanner:latest EnvironmentFile=/etc/neuvector/scanner.env PublishPort=18402:18402 Volume=/var/run/docker.sock:/var/run/docker.sock:ro Volume=/etc/neuvector/certs/internal:/etc/neuvector/certs/internal:ro [Install] WantedBy=multi-user.target重載 systemd daemon:
sudo systemctl daemon-reload啟用並立即啟動服務:
sudo systemctl start scanner.service如果噴錯代表 podman Quadlet 的設定檔有寫錯,請執行以下命令確認設定檔哪裡有錯
sudo /usr/libexec/podman/quadlet -dryrun檢查 systemd 服務狀態:
sudo systemctl status scanner.service正確執行結果:
● scanner.service - NeuVector Scanner (via Podman Quadlet) Loaded: loaded (/etc/containers/systemd/scanner.container; generated) Active: active (running) since Fri 2025-08-15 17:56:43 CST; 6min ago Main PID: 4564 (conmon) Tasks: 12 (limit: 50507) Memory: 1.8G CPU: 20.587s ...以下省略使用 podman 確認 container 狀態:
sudo podman ps -a --filter name=scanner正確執行結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b4fede8ec2ac docker.io/neuvector/scanner:latest 8 minutes ago Up 8 minutes 0.0.0.0:18402->18402/tcp scanner
6. 重新開機測試
- 將主機重開
sudo reboot - 開機後,檢查 container 狀態正確執行結果:
sudo podman ps -a --filter name=scanner --filter name=allinoneCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 78a475cb15a3 docker.io/neuvector/scanner:latest 25 seconds ago Up 26 seconds 0.0.0.0:18402->18402/tcp scanner 10bd318a7f4a docker.io/neuvector/allinone:5.4.9 25 seconds ago Up 26 seconds 0.0.0.0:18301->18301/udp, 0.0.0.0:8443->8443/tcp, 0.0.0.0:10443->10443/tcp, 0.0.0.0:18300-18301->18300-18301/tcp, 0.0.0.0:18400-18401->18400-18401/tcp allinone - 打開瀏覽器,確認 Neuvector Web Console 是否正常

- 登入管理網站
- 帳號 :
admin - 密碼 :
admin
- 帳號 :
7. 暴露 Neuvector Metrics
建立 Podman Secret 儲存 admin 帳號的密碼
printf 'admin' | sudo podman secret create neuvector_pass -啟動 Neuvector Exporter Container
sudo podman run -d \ --name neuvector.prometheus-exporter \ --user 1000:1000 \ -e CTRL_API_SERVICE=192.168.11.131:10443 \ -e CTRL_USERNAME=admin \ --secret neuvector_pass,type=env,target=CTRL_PASSWORD \ -e EXPORTER_PORT=8068 \ --cap-drop=ALL \ --security-opt no-new-privileges:true \ --read-only \ registry.rancher.com/rancher/neuvector-prometheus-exporter:1.0.9確認 Container 運作狀態
sudo podman ps -a --filter name=neuvector.prometheus-exporter執行結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6acc80576905 registry.rancher.com/rancher/neuvector-prometheus-exporter:1.0.9 7 minutes ago Up 7 minutes neuvector.prometheus-exporter獲取 Container IP
sudo podman inspect neuvector.prometheus-exporter --format '{{.NetworkSettings.IPAddress}}'執行結果:
10.88.0.19測試是否可得到 Metrics
curl -s http://10.88.0.19:8068/ | head -n 5執行結果:
# HELP python_gc_objects_collected_total Objects collected during gc # TYPE python_gc_objects_collected_total counter python_gc_objects_collected_total{generation="0"} 368.0 python_gc_objects_collected_total{generation="1"} 0.0 python_gc_objects_collected_total{generation="2"} 0.0建立 Quadlet
.container檔案sudo nano /etc/containers/systemd/neuvector-prometheus-exporter.container設定內容如下 :
注意,
CTRL_API_SERVICE的值需依照環境而設定 如果無 TLS 的需求,可將PublishPort取消註解並跳過第 11 步驟之後的所有步驟。[Unit] Description=NeuVector Prometheus Exporter After=network-online.target Wants=network-online.target [Container] ContainerName=neuvector.prometheus-exporter Image=registry.rancher.com/rancher/neuvector-prometheus-exporter:1.0.9 User=1000 Group=1000 # Environment Environment=CTRL_API_SERVICE=192.168.11.131:10443 Environment=CTRL_USERNAME=admin Environment=EXPORTER_PORT=8068 # Secret (must be pre-created) Secret=neuvector_pass,type=env,target=CTRL_PASSWORD # Security hardening DropCapability=ALL SecurityLabelNested=true NoNewPrivileges=true ReadOnly=true # Publish port if external access is needed (uncomment to enable) # PublishPort=8068:8068 [Service] Restart=on-failure TimeoutStartSec=300 [Install] WantedBy=default.target重載 systemd daemon:
sudo systemctl daemon-reload啟用並立即啟動服務:
sudo systemctl start neuvector-prometheus-exporter.service如果噴錯代表 podman Quadlet 的設定檔有寫錯,請執行以下命令確認設定檔哪裡有錯
sudo /usr/libexec/podman/quadlet -dryrun檢查 systemd 服務狀態:
sudo systemctl status neuvector-prometheus-exporter.service正確執行結果:
● neuvector-prometheus-exporter.service - NeuVector Prometheus Exporter Loaded: loaded (/etc/containers/systemd/neuvector-prometheus-exporter.container; generated) Active: active (running) since Wed 2026-03-04 21:32:32 CST; 18min ago Main PID: 7980 (conmon) Tasks: 4 (limit: 50507) Memory: 23.6M CPU: 387ms ...使用 podman 確認 container 狀態:
sudo podman ps -a --filter name=neuvector.prometheus-exporter正確執行結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6acc80576905 registry.rancher.com/rancher/neuvector-prometheus-exporter:1.0.9 19 minutes ago Up 19 minutes neuvector.prometheus-exporter請參考以下 Git repo 的 README 做出 TLS 自簽憑證
https://github.com/braveantony/mkcert.git建立目錄,並拷貝憑證
mkdir -p ${HOME}/nginx/ cp mkcert/kubeantony.com/kubeantony.com.crt ${HOME}/nginx/server.crt cp mkcert/kubeantony.com/kubeantony.com.key ${HOME}/nginx/server.key chmod 644 ${HOME}/nginx/server.key ls -lZ ${HOME}/nginx/server.*執行結果:
-rw-r--r--. 1 bigred bigred system_u:object_r:container_file_t:s0:c948,c1020 2167 Mar 4 22:39 /home/bigred/nginx/server.crt -rw-r--r--. 1 bigred bigred system_u:object_r:container_file_t:s0:c948,c1020 3272 Mar 4 22:39 /home/bigred/nginx/server.key注意
server.key權限要設為644撰寫
nginx.confnano ${HOME}/nginx/nginx.conf檔案內容如下:
server_name請依序環境設定,記得在環境中的 DNS Server 將之添加為 A Record
error_log /dev/stderr warn; worker_processes 4; worker_rlimit_nofile 40000; pid /var/run/nginx.pid; events { worker_connections 8192; } http { access_log /dev/stdout; server_tokens off; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; client_max_body_size 1m; client_body_timeout 10s; client_header_timeout 10s; send_timeout 10s; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; ssl_prefer_server_ciphers on; # 預設拒絕未匹配的 Host server { listen 8443 ssl default_server; server_name _; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; return 444; } server { listen 8443 ssl; server_name aionv-metrics.kubeantony.com; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; location / { proxy_pass http://neuvector.prometheus-exporter:8068; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 90s; proxy_connect_timeout 10s; proxy_send_timeout 10s; proxy_hide_header X-Powered-By; } location ~* ^/(\.env|\.git|wp-admin|phpMyAdmin) { return 444; } } }設定 Podman Default Network 啟用 DNS
sudo sed -i '/dns_enabled/s/false/true/' /etc/containers/networks/podman.json sudo podman network reload --all建立 Nginx Container
sudo podman run -d --name nginx -p 8068:8443 \ --read-only \ --mount type=tmpfs,destination=/tmp,tmpfs-size=10M,tmpfs-mode=1777,U=true \ --mount type=tmpfs,destination=/var/cache/nginx,tmpfs-size=50M,U=true \ --mount type=tmpfs,destination=/var/run,tmpfs-size=10M,U=true \ --mount type=tmpfs,destination=/var/log/nginx,tmpfs-size=10M,U=true \ --mount type=tmpfs,destination=/var/lib/nginx,tmpfs-size=50M,U=true \ --user $(id -u):$(id -g) \ --cap-drop ALL \ --security-opt no-new-privileges:true \ --pids-limit 100 \ --restart unless-stopped \ -v ${HOME}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro,Z \ -v ${HOME}/nginx/server.crt:/etc/nginx/ssl/server.crt:ro,Z \ -v ${HOME}/nginx/server.key:/etc/nginx/ssl/server.key:ro,Z \ registry.suse.com/suse/nginx:latest檢視 Container 狀態
sudo podman ps -a --filter name=nginx執行結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 041b60ecbc36 registry.suse.com/suse/nginx:latest nginx -g daemon o... 7 seconds ago Up 7 seconds 0.0.0.0:8068->8443/tcp, 80/tcp nginx驗證是否成功能透過 TLS 存取 Neuvector Metrics
curl -sk https://aionv-metrics.kubeantony.com:8068/ | head -n 5執行結果:
# HELP python_gc_objects_collected_total Objects collected during gc # TYPE python_gc_objects_collected_total counter python_gc_objects_collected_total{generation="0"} 368.0 python_gc_objects_collected_total{generation="1"} 0.0 python_gc_objects_collected_total{generation="2"} 0.0建立 Quadlet
.container檔案# 定義變數 CONTAINER_NAME="nginx" IMAGE="registry.suse.com/suse/nginx:latest" HOST_PORT="8068" CONTAINER_PORT="8443" NGINX_CONF_DIR="${HOME}/nginx" QUADLET_DIR="/etc/containers/systemd/" # 建立目錄 sudo mkdir -p "${QUADLET_DIR}"設定內容如下 :
sudo tee "${QUADLET_DIR}/${CONTAINER_NAME}.container" > /dev/null <<EOF [Unit] Description=Nginx Reverse Proxy (Hardened) After=network-online.target Wants=network-online.target [Container] ContainerName=${CONTAINER_NAME} Image=${IMAGE} PublishPort=${HOST_PORT}:${CONTAINER_PORT} ReadOnly=true UserNS=keep-id DropCapability=ALL SecurityLabelDisable=false PidsLimit=100 NoNewPrivileges=true User=$(id -u):$(id -g) Mount=type=tmpfs,destination=/tmp,tmpfs-size=10M,tmpfs-mode=1777,U=true Mount=type=tmpfs,destination=/var/cache/nginx,tmpfs-size=50M,U=true Mount=type=tmpfs,destination=/var/run,tmpfs-size=10M,U=true Mount=type=tmpfs,destination=/var/log/nginx,tmpfs-size=10M,U=true Mount=type=tmpfs,destination=/var/lib/nginx,tmpfs-size=50M,U=true Volume=${NGINX_CONF_DIR}/nginx.conf:/etc/nginx/nginx.conf:ro,Z Volume=${NGINX_CONF_DIR}/server.crt:/etc/nginx/ssl/server.crt:ro,Z Volume=${NGINX_CONF_DIR}/server.key:/etc/nginx/ssl/server.key:ro,Z [Service] Restart=always TimeoutStartSec=30 [Install] WantedBy=default.target EOF重載 systemd daemon:
sudo systemctl daemon-reload啟用並立即啟動服務:
sudo systemctl start nginx.service如果噴錯代表 podman Quadlet 的設定檔有寫錯,請執行以下命令確認設定檔哪裡有錯
sudo /usr/libexec/podman/quadlet -dryrun檢查 systemd 服務狀態:
sudo systemctl status nginx.service正確執行結果:
● nginx.service - Nginx Reverse Proxy (Hardened) Loaded: loaded (/etc/containers/systemd/nginx.container; generated) Active: active (running) since Wed 2026-03-04 23:27:42 CST; 33s ago Main PID: 296160 (conmon) Tasks: 6 (limit: 50507) Memory: 17.2M CPU: 107ms ...使用 podman 確認 container 狀態:
sudo podman ps -a --filter name=nginx正確執行結果:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dde5bc3186e8 registry.suse.com/suse/nginx:latest nginx -g daemon o... About a minute ago Up About a minute 0.0.0.0:8068->8443/tcp, 80/tcp nginx再次測試是否可得到 Metrics
curl -sk https://aionv-metrics.kubeantony.com:8068/ | head -n 5執行結果:
# HELP python_gc_objects_collected_total Objects collected during gc # TYPE python_gc_objects_collected_total counter python_gc_objects_collected_total{generation="0"} 368.0 python_gc_objects_collected_total{generation="1"} 0.0 python_gc_objects_collected_total{generation="2"} 0.0