# Podman Deploy Neuvector AllInOne
## Deploy allinone (NO privileged mode) with podman
### 1. 準備環境
1. 建立 NeuVector 用於持久化儲存設定檔的目錄
```
sudo mkdir /var/neuvector
```
2. 設定開機自動啟動並立即啟動 Podman socket
```
sudo systemctl enable --now podman.socket
```
3. 建立一個 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
```
4. 設定開機自動啟動並立即啟動建立 symlink 的服務
```
sudo systemctl enable --now podman-docker-symlink.service
```
### 2. 建立 NeuVector 內部元件 (Controller, Enforcer, Scanner) 之間加密通訊所需的 TLS 憑證
1. 建立存放憑證的目錄,並進入該目錄
```
sudo mkdir -p /etc/neuvector/certs/internal; cd /etc/neuvector/certs/internal
```
2. 建立 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
```
3. 產生 CA (憑證頒發機構) 的私鑰
```
sudo openssl genrsa -out ca.key 2048
```
4. 使用 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
```
5. 產生給服務使用的私鑰
```
sudo openssl genrsa -out cert.key 2048
```
6. 產生憑證簽署請求 (CSR)
```
sudo openssl req -new -key cert.key -sha256 -out cert.csr -config ca.cfg
```
7. 使用 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
1. 動態獲取主機指定網路介面 (此處為 ens18) 的 IP 位址,並存入變數 `IP`,這個 IP 將用來告訴 NeuVector 元件如何互相連線
```
NIC='ens18' && \
IP=$(ip -4 -o addr show ${NIC} | awk '{print $4}' | cut -d/ -f1)
```
2. 啟動 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.5
```
> - `--pid=host, --cap-add=...` 等參數是為了賦予 container 足夠的權限來監控主機的程序與網路活動
> - `-e CLUSTER_JOIN_ADDR=${IP}` 設定叢集加入位址
> - `-v 掛載主機路徑`,讓 container 能存取 Docker socket、主機核心模組、cgroup 及程序資訊,並持久化設定與讀取憑證
3. 啟動 NeuVector 的 Scanner container,專門用於執行映像檔弱點掃描,它會透過 `CLUSTER_JOIN_ADDR` 連接到 All-in-One Neuvector Controller
```
sudo 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 開機自動啟動
1. 建立環境變數檔
```
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
```
2. 建立 Quadlet `.container` 檔案
```bash
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.5
ContainerName=allinone
# Namespaces / 安全性(等同你原本的 --pid/--cap-add/--security-opt)
PodmanArgs=--pid=host --security-opt apparmor=unconfined
AddCapability=SYS_ADMIN
AddCapability=NET_ADMIN
AddCapability=SYS_PTRACE
AddCapability=IPC_LOCK
SecurityLabelDisable=true # --security-opt label=disable
SeccompProfile=unconfined # --security-opt seccomp=unconfined
# 環境變數
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
```
2. 重載 systemd daemon:
```
sudo systemctl daemon-reload
```
3. 啟用並立即啟動服務:
```
sudo systemctl start allinone.service
```
> 如果噴錯代表 podman Quadlet 的設定檔有寫錯,請執行以下命令確認設定檔哪裡有錯
> `sudo /usr/libexec/podman/quadlet -dryrun`
4. 檢查 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
...以下省略
```
5. 使用 podman 確認容器狀態:
```bash
sudo podman ps -a --filter name=allinone
```
正確執行結果:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e11bf0e3b2f7 docker.io/neuvector/allinone:5.4.5 5 minutes ago Up 5 minutes 0.0.0.0:8443->8443/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 開機自動啟動
1. 建立環境變數檔
```
sudo tee /etc/neuvector/scanner.env >/dev/null <<'EOF'
# 請把下行改成你的 IP
CLUSTER_JOIN_ADDR=192.168.11.131
NV_PLATFORM_INFO=platform=Docker
EOF
```
2. 建立 Quadlet `.container` 檔案
```bash
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
RestartPolicy=always
[Install]
WantedBy=multi-user.target
```
2. 重載 systemd daemon:
```
sudo systemctl daemon-reload
```
3. 啟用並立即啟動服務:
```
sudo systemctl start scanner.service
```
> 如果噴錯代表 podman Quadlet 的設定檔有寫錯,請執行以下命令確認設定檔哪裡有錯
> ```
> sudo /usr/libexec/podman/quadlet -dryrun
> ```
4. 檢查 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
...以下省略
```
5. 使用 podman 確認容器狀態:
```bash
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. 重新開機測試
1. 將主機重開
```
sudo reboot
```
2. 開機後,檢查 container 狀態
```
sudo podman ps -a --filter name=scanner --filter name=allinone
```
正確執行結果:
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cde263d10568 docker.io/neuvector/scanner:latest 2 minutes ago Up 2 minutes 0.0.0.0:18402->18402/tcp scanner
69e22d0b9ae1 harbor.antony.com/neuvector/allinone:5.4.5 2 minutes ago Up 2 minutes 0.0.0.0:8443->8443/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
```
3. 打開瀏覽器,確認 Neuvector Web Console 是否正常

4. 登入管理網站
- 帳號 : `admin`
- 密碼 : `admin`

## 參考網站
- [Deploy allinone (NO privileged mode) with docker run - SUSE Security Docs](https://documentation.suse.com/cloudnative/security/5.4/en/docker.html#_deploy_allinone_no_privileged_mode_with_docker_run)
- [安裝 Neuvector all-in-one (Docker、Podman)](https://hackmd.io/@7vxmAdNPTmmlYGSRMuvbmw/SJ4nTdzRC)