# Sonatype Nexus 建置
Sonatype Nexus 是用來集中管理、快取與分發二進位套件(artifacts)的伺服器。它不是存放原始碼,而是存放編譯後的元件(像 JAR、npm 套件、Docker image、PyPI 套件、NuGet 等)。
## 透過 podman 安裝 Nexus
### 安裝 podman
```
$ curl -fsSL -o podman-linux-amd64.tar.gz https://github.com/mgoltzsche/podman-static/releases/latest/download/podman-linux-amd64.tar.gz
$ tar -zxvf podman-linux-amd64.tar.gz;cd podman-linux-amd64
```
* 使用 rsync 複製 podman 執行檔案,並且會把原本會被覆寫的檔案移到備份目錄
```
$ sudo rsync -aHAX --numeric-ids --info=progress2 \
--backup --backup-dir="/root/usr-backup-$(date +%F_%H%M%S)" \
./usr/ /usr/
```
```
$ sudo mkdir -p /etc/containers
$ sudo rsync -aHAX --no-o --no-g --info=progress2 \
--backup --backup-dir="/root/etc-containers-backup-$(date +%F_%H%M%S)}" \
./etc/containers/ /etc/containers/
```
```
$ which podman
/usr/local/bin/podman
$ sudo podman version
Client: Podman Engine
Version: 5.6.0
API Version: 5.6.0
Go Version: go1.24.6
Built: Thu Jan 1 08:00:00 1970
OS/Arch: linux/amd64
```
* 如果 podman 需要使用 rootless ,還要安裝以下套件
```
$ sudo apt install -y uidmap
```
### 安裝 Nexus
```
$ sudo mkdir -p /nexus/nexus-data
$ sudo chown -R 200 /nexus/nexus-data
$ sudo podman run -d -p 8081:8081 -p 8082:8082 --privileged --name nexus -v /nexus/nexus-data:/nexus-data --ulimit nofile=65536:65536 docker.io/sonatype/nexus3
```
* 如果離線環境需做以下設定
```
$ sudo mkdir -p /nexus/nexus-data/etc
$ sudo nano /nexus/nexus-data/etc/nexus.properties
# 停用建立預設儲存庫
nexus.skipDefaultRepositories=true
# 停用OSS索引漏洞檢查
nexus.ossindex.plugin.enabled=false
$ sudo chown -R 200:200 /nexus/nexus-data
$ sudo podman run -d -p 8081:8081 -p 8082:8082 --privileged --name nexus -v /nexus/nexus-data:/nexus-data --ulimit nofile=65536:65536 docker.io/sonatype/nexus3
```
* 檢視 admin 帳號密碼
```
$ cat /nexus/nexus-data/admin.password
ab81e52a-d923-462a-9a7b-225166e20c67
```
## 登入 Nexus
* 右上角登入

* 設定新密碼

* 允許匿名者登入

## 建立 Blob Stores
Nexus 的 Blob Stores 是用來保存「原始二進位檔案」(artifact binaries / blobs)的儲存池,也就是所有套件檔案(jar、tar、docker layer、npm package 等)實際的位元組內容都放在 blob store;Repository 則是指向這些 blob 的索引與 metadata。
* 創建一個名稱為 `apt` 的 Blob Stores


## 新增 apt proxy 倉庫
透過 nexus 當 ubuntu 的 proxy 倉庫來源,ubuntu 只要安裝套件就會從 nexus 下載,並提供套件。



> 使用 `http://tw.archive.ubuntu.com/ubuntu` 位置
* Blob Stores 選擇我們剛剛創建的 `apt` Blob Stores


* 複製連結

* 修改 ubuntu24.04 的更新套件清單來源
```
# 修改前先備份
$ sudo cp /etc/apt/sources.list.d/ubuntu.sources ubuntu.sources
$ sudo nano /etc/apt/sources.list.d/ubuntu.sources
Types: deb
URIs: http://10.10.7.20:8081/repository/apt-proxy/ # 修改
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://10.10.7.20:8081/repository/apt-proxy/ # 修改
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
```
* 更新套件清單
```
$ sudo apt update
```
* 可以看到 Nexus 正在「對外提供」Ubuntu 釋出的 metadata(索引)與對應的套件內容(.deb 的索引/檔案位置)。

### 透過 Nexus 安裝套件
* 列出 net-tools 套件來源,可以看到都是從 Nexus 提供
```
$ sudo apt-cache madison net-tools
net-tools | 2.10-0.1ubuntu4.4 | http://10.10.7.20:8081/repository/apt-proxy noble-updates/main amd64 Packages
net-tools | 2.10-0.1ubuntu4.4 | http://10.10.7.20:8081/repository/apt-proxy noble-security/main amd64 Packages
net-tools | 2.10-0.1ubuntu4 | http://10.10.7.20:8081/repository/apt-proxy noble/main amd64 Packages
```
* 安裝套件
```
$ sudo apt-get install net-tools
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
net-tools
0 upgraded, 1 newly installed, 0 to remove and 185 not upgraded.
Need to get 204 kB of archives.
After this operation, 811 kB of additional disk space will be used.
Get:1 http://10.10.7.20:8081/repository/apt-proxy noble-updates/main amd64 net-tools amd64 2.10-0.1ubuntu4.4 [204 kB]
......
```
* 可以看到 `apt-proxy` Browse 多了 net-tools 套件包,之後只要 ubuntu 指向到 Nexus 就可以透過 Nexus 安裝套件

## 新增 apt host 倉庫
手動上傳 deb 檔案到 nexus,並且透過 nexus 安裝套件
* 在 nexus 主機上執行
```
# 執行後輸入密碼
$ sudo gpg --gen-key
gpg (GnuPG) 2.4.4; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.
GnuPG needs to construct a user ID to identify your key.
Real name: nexus
Email address:
You selected this USER-ID:
"nexus"
Change (N)ame, (E)mail, or (O)kay/(Q)uit? o
......
```
* 匯出公鑰
```
$ sudo gpg -a -o nexus_pub.asc --export nexus
$ ls -l nexus_pub.asc
-rw-r--r-- 1 root root 624 Sep 23 23:04 nexus_pub.asc
```
* 匯出私鑰,並輸入創建時的密碼
```
$ sudo gpg -a -o nexus_pri.asc --export-secret-key nexus
$ ls -l nexus_pri.asc
-rw------- 1 root root 849 Sep 23 23:05 nexus_pri.asc
```
* 創建 apt host 倉庫


* 輸入私鑰以及密碼


### 手動上傳 deb 檔案
* 上傳 `net-tools_2.10-0.1ubuntu4.4_amd64.deb` 檔案


* 在 `apt-host` Browse 可以看到上傳的檔案

### 客戶端安裝自己上傳到 nexus 的套件
* 到客戶端將公鑰放到 `/etc/apt/trusted.gpg.d/` 目錄下
```
$ sudo cp nexus_pub.asc /etc/apt/trusted.gpg.d/
```

* 新增套件清單來源
```
# 修改前先備份
$ sudo cp /etc/apt/sources.list.d/ubuntu.sources ubuntu.sources
$ sudo nano /etc/apt/sources.list.d/ubuntu.sources
Types: deb
URIs: http://10.10.7.20:8081/repository/apt-host/
Suites: noble
Components: main restricted universe multiverse
Signed-By: /etc/apt/trusted.gpg.d/nexus_pub.asc
Types: deb
URIs: http://tw.archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://security.ubuntu.com/ubuntu/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
```
> 或是使用舊的方式修改套件來源,修改 `/etc/apt/sources.list`
```
$ sudo nano /etc/apt/sources.list
# Ubuntu sources have moved to /etc/apt/sources.list.d/ubuntu.sources
deb [trusted=yes] http://10.10.7.20:8081/repository/apt-host/ noble main
```
* 更新套件清單
```
$ sudo apt update
Hit:1 http://10.10.7.20:8081/repository/apt-host noble InRelease
Hit:2 https://download.docker.com/linux/ubuntu noble InRelease
Hit:3 http://tw.archive.ubuntu.com/ubuntu noble InRelease
Hit:4 http://tw.archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:5 http://tw.archive.ubuntu.com/ubuntu noble-backports InRelease
Hit:6 http://security.ubuntu.com/ubuntu noble-security InRelease
......
```
* 列出 `net-tools` 套件清單來源
```
$ sudo apt-cache madison net-tools
net-tools | 2.10-0.1ubuntu4.4 | http://10.10.7.20:8081/repository/apt-host noble/main amd64 Packages
net-tools | 2.10-0.1ubuntu4.4 | http://tw.archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
net-tools | 2.10-0.1ubuntu4.4 | http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages
net-tools | 2.10-0.1ubuntu4 | http://tw.archive.ubuntu.com/ubuntu noble/main amd64 Packages
```
* 指定安裝`net-tools` 套件的版本號,並且可以看到套件來源是從 nexus 來的
```
$ sudo apt install net-tools=2.10-0.1ubuntu4.4
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
net-tools
0 upgraded, 1 newly installed, 0 to remove and 185 not upgraded.
Need to get 204 kB of archives.
After this operation, 811 kB of additional disk space will be used.
Get:1 http://10.10.7.20:8081/repository/apt-host noble/main amd64 net-tools amd64 2.10-0.1ubuntu4.4 [204 kB]
Fetched 204 kB in 0s (6,507 kB/s)
.....
```
* 檢查版本與 apt 認到的來源
```
$ sudo apt-cache policy net-tools
net-tools:
Installed: 2.10-0.1ubuntu4.4
Candidate: 2.10-0.1ubuntu4.4
Version table:
*** 2.10-0.1ubuntu4.4 500
500 http://10.10.7.20:8081/repository/apt-host noble/main amd64 Packages
500 http://tw.archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
500 http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages
100 /var/lib/dpkg/status
2.10-0.1ubuntu4 500
500 http://tw.archive.ubuntu.com/ubuntu noble/main amd64 Packages
```
## 新增 docker host 倉庫
透過 nexus 可以當 image registry,提供 container image 下載
* 創建 docker host 的 Blob Stores


* 創建 docker host 倉庫


* 開放 `8082` port 提供上傳跟下載 image

* Nexus UI → Security → Realms : `Docker Bearer Token Realm` 移至右側

### 設定 docker client
```
$ sudo nano /etc/docker/daemon.json
{
"log-level": "warn",
"log-driver": "json-file",
"insecure-registries": ["10.10.7.20:8082"], # 新增 nexus 位置
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
```
```
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```
* 成功登入
```
$ sudo docker login 10.10.7.20:8082
Username: admin
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
```
* 上傳 image 到 nexus
```
$ sudo docker push 10.10.7.20:8082/nginx:latest
```
* 在 nexus 上可以看到這張 image

* 在別台機器可以成功 pull 這張 image
```
$ sudo docker pull 10.10.7.20:8082/nginx:latest
```
## 參考
https://help.sonatype.com/en/sonatype-product-overview.html
https://support.sonatype.com/hc/en-us/articles/360049884673-Considerations-For-NXRM-3-Inside-Air-Gapped-Restricted-Firewalled-and-DMZ-Networks