1 - 开发工具

通用的开发工具,包括 nuxus,sdkman 等

1.1 - Nexus

强大的仓库管理工具,支持多种仓库类型,包括 Maven、go module 等

Nexus Repository Manager 是一个强大的仓库管理工具,支持多种仓库类型,包括 Maven、go module 等。它提供了一个集中的存储库,用于存储和管理软件包,并提供了一个安全的访问控制机制。

备注: 之所以选择 nexus 而不是 artifactory,是因为 nexus 是开源的,而 artifactory 是闭源+收费的。

以下以 nexus 3.85.0-03 为例,介绍如何安装和配置 nexus。

参考官方文档: https://help.sonatype.com/en/sonatype-nexus-repository.html

准备

创建 nexus 目录:

sudo mkdir -p /mnt/data/services/nexus
sudo chown -R nexus:nexus /mnt/data/services/nexus

创建 nexus 用户专门用于运行 nexus:

sudo useradd -M -d /mnt/data/services/nexus -s /bin/zsh -r nexus

下载

从下面地址找到 nexus 安装包:

https://help.sonatype.com/en/download-archives---repository-manager-3.html

从官方下载 nexus 安装包 nexus-3.86.0-08:

cd /mnt/data/services/nexus
# 必要时开启代理,不能可能因为网络原因无法下载
# proxyon
sudo wget https://download.sonatype.com/nexus/3/nexus-3.86.0-08-linux-x86_64.tar.gz

备注: 这个版本是自带 jdk 的,因此不需要单独安装 jdk。自带的 jdk 在 nexus/jdk/temurin_17.0.13_11_linux_x86_64 目录下。

解压安装包:

sudo tar -xzf nexus-3.86.0-08-linux-x86_64.tar.gz -C /mnt/data/services/nexus
#sudo rm -rf nexus-3.86.0-08-linux-x86_64.tar.gz
sudo chown -R nexus:nexus /mnt/data/services/nexus

重命名 nexus 目录去掉版本信息(方便以后升级版本):

sudo mv nexus-3.86.0-08 nexus

得到如下目录:

$ ls -la
drwxr-xr-x 6 nexus nexus      4096 Nov  9 20:25 nexus
drwxr-xr-x 3 nexus nexus      4096 Nov  4 07:12 sonatype-work

安装

参考官方文档:

https://help.sonatype.com/en/install-nexus-repository.html

cd nexus/bin

这个目录下的 nexus 是启动脚本,nexus.vmoptions 是 jvm 配置文件。

查看 nexus.vmoptions 文件,可以看到默认的数据和日志目录:

-XX:LogFile=../sonatype-work/nexus3/log/jvm.log
-Dkaraf.home=.
-Dkaraf.base=.
-Dkaraf.data=../sonatype-work/nexus3
-Dkaraf.log=../sonatype-work/nexus3/log
-Djava.io.tmpdir=../sonatype-work/nexus3/tmp

配置系统服务:

sudo vi /etc/systemd/system/nexus.service

添加如下内容:

[Unit]
Description=Nexus Repository Manager
After=network.target

[Service]
Type=forking
User=nexus
Group=nexus
ExecStart=/mnt/data/services/nexus/nexus/bin/nexus start
ExecStop=/mnt/data/services/nexus/nexus/bin/nexus stop
Restart=on-failure
RestartSec=30
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

启用并启动服务:

sudo systemctl daemon-reload
sudo systemctl enable nexus
sudo systemctl start nexus

检查状态:

$ sudo systemctl status nexus

● nexus.service - Nexus Repository Manager
     Loaded: loaded (/etc/systemd/system/nexus.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-04-07 10:32:27 CST; 4min 7s ago
    Process: 4495 ExecStart=/opt/nexus/nexus/bin/nexus start (code=exited, status=0/SUCCESS)
   Main PID: 4736 (java)
      Tasks: 97 (limit: 38379)
     Memory: 2.1G
        CPU: 1min 34.806s
     CGroup: /system.slice/nexus.service
             └─4736 /opt/nexus/nexus/jdk/temurin_17.0.13_11_linux_x86_64/jdk-17.0.13+11/bin/java -server -XX:+Un>

Apr 07 10:32:26 debian12 systemd[1]: Starting nexus.service - Nexus Repository Manager...
Apr 07 10:32:27 debian12 nexus[4495]: /opt/nexus/nexus/bin/nexus: 155: [[: not found
Apr 07 10:32:27 debian12 nexus[4495]: Starting nexus
Apr 07 10:32:27 debian12 systemd[1]: Started nexus.service - Nexus Repository Manager.

查看 nexus 进程信息:

$ ps -ef | grep nexus

nexus      19863       1 99 15:30 ?        00:01:12 /mnt/data/nexus/nexus/jdk/temurin_17.0.13_11_linux_x86_64/jdk-17.0.13+11/bin/java -server -XX:+UnlockDiagnosticVMOptions -Xms2703m -Xmx2703m -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=../sonatype-work/nexus3/log/jvm.log -XX:-OmitStackTraceInFastThrow -Dkaraf.home=. -Dkaraf.base=. -Djava.util.logging.config.file=etc/spring/java.util.logging.properties -Dkaraf.data=../sonatype-work/nexus3 -Dkaraf.log=../sonatype-work/nexus3/log -Djava.io.tmpdir=../sonatype-work/nexus3/tmp -Djdk.tls.ephemeralDHKeySize=2048 --add-reads=java.xml=java.logging --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.naming/javax.naming.spi=ALL-UNNAMED --add-opens java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED --add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED --add-exports=java.security.sasl/com.sun.security.sasl=ALL-UNNAMED --add-exports=java.base/sun.security.x509=ALL-UNNAMED --add-exports=java.base/sun.security.rsa=ALL-UNNAMED --add-exports=java.base/sun.security.pkcs=ALL-UNNAMED -jar /mnt/data/nexus/nexus/bin/sonatype-nexus-repository-3.79.0-09.jar

访问

访问地址:

http://192.168.3.193:8081/

第一次启动会比较慢,要耐心等待几十秒中。

登录时使用帐号 admin 和初始管理员密码,初始管理员密码位于:

sudo vi /mnt/data/services/nexus/sonatype-work/nexus3/admin.password

初始管理员密码会是一个类似这样的字符串:

16fe9704-fd38-4e4c-8077-51db4b2ab8f2

登录后会有一个引导过程,首先需要修改管理员密码。

注意: 设置密码后,admin.password 文件会被删除。

设置匿名访问,我是给我自己用的,所以设置为允许匿名访问:

anonymous-access

配置

jvm 内存配置

sudo vi /mnt/data/services/nexus/nexus/bin/nexus.vmoptions

修改 nexus.vmoptions 文件,增加如下内容:

# 默认Xms/Xmx是2703m/2703m
-Xms2703m
-Xmx2703m
# 增加直接内存大小
-XX:MaxDirectMemorySize=2g

端口配置

默认端口是 8081,可以

sudo vi /mnt/data/services/nexus/nexus/etc/nexus-default.properties

找到 nexus-default.properties 文件,修改 application-port 端口:

application-port=8081
application-host=0.0.0.0

仓库

nexus 安装后自带的默认仓库:

default-repository

可以看到 maven 和 nuget 都是准备好了的。

maven 仓库

自带的四个 maven 仓库:

  • maven-releases 仓库: 这是一个 hosted 仓库,用于存储发布版本的 jar 包。
  • maven-snapshots 仓库: 这是一个 hosted 仓库,用于存储快照版本的 jar 包。
  • maven-central 仓库: 这是一个 proxy 仓库,代理了 https://repo1.maven.org/maven2/ 仓库
  • maven-public 仓库: 这是一个 group 仓库,将 maven-releases、maven-snapshots 和 maven-central 仓库聚合在一起。

nuget 仓库

自带的三个 nuget 仓库:

  • nuget-hosted 仓库: 这是一个 hosted 仓库,用于存储 nuget 包。
  • nuget-org-proxy 仓库: 这是一个 proxy 仓库,代理了 https://api.nuget.org/v3/index.json 仓库
  • nuget-group 仓库: 这是一个 group 仓库,将 nuget-hosted 和 nuget-org-proxy 仓库聚合在一起。

目前不做 .net 开发,所以 nuget 仓库暂时用不上,都删除。

apt 仓库

nexus 提供对 apt 的支持,可以创建 apt proxy 和 apt host 仓库。

我目前对 apt host 没有需求,就简单的新建一个 apt proxy 仓库即可。

参考官方文档:

https://help.sonatype.com/en/apt-repositories.html

进入 nexus 管理页面,选择 Settings -> Repositories -> Create repository,选择 Apt (Proxy) 类型,然后填写:

创建完成后,修改 debian 的 apt 源,使用 apt-debian13 仓库。

安装之后默认的 /etc/apt/sources.list 为,这里使用 ustc 的镜像源:

#deb cdrom:[Debian GNU/Linux 13.1.0 _Trixie_ - Official amd64 DVD Binary-1 with firmware 20250906-10:24]/ trixie contrib main non-free-firmware

deb http://mirrors.ustc.edu.cn/debian/ trixie main non-free-firmware
deb-src http://mirrors.ustc.edu.cn/debian/ trixie main non-free-firmware

deb http://security.debian.org/debian-security trixie-security main non-free-firmware
deb-src http://security.debian.org/debian-security trixie-security main non-free-firmware

# trixie-updates, to get updates before a point release is made;
# see https://www.debian.org/doc/manuals/debian-reference/ch02.en.html#_updates_and_backports
deb http://mirrors.ustc.edu.cn/debian/ trixie-updates main non-free-firmware
deb-src http://mirrors.ustc.edu.cn/debian/ trixie-updates main non-free-firmware
sudo vi /etc/apt/sources.list

将源替换为:

# Debian 13 (trixie) - Main repository via Nexus
deb [trusted=yes] http://192.168.3.193:8081/repository/apt-debian13/ trixie main contrib non-free non-free-firmware
deb-src [trusted=yes] http://192.168.3.193:8081/repository/apt-debian13/ trixie main contrib non-free non-free-firmware

# no change to Security updates source
deb http://security.debian.org/debian-security trixie-security main non-free-firmware
deb-src http://security.debian.org/debian-security trixie-security main non-free-firmware

# Debian 13 (trixie-updates) - Updates via Nexus
# trixie-updates, to get updates before a point release is made;
# see https://www.debian.org/doc/manuals/debian-reference/ch02.en.html#_updates_and_backports
deb http://192.168.3.193:8081/repository/apt-debian13/ trixie-updates main non-free-firmware
deb-src http://192.168.3.193:8081/repository/apt-debian13/ trixie-updates main non-free-firmware

更新 apt 源:

sudo apt update

输出为:

Hit:1 http://192.168.3.193:8081/repository/apt-debian13 trixie InRelease
Hit:2 http://192.168.3.193:8081/repository/apt-debian13 trixie-updates InRelease              
Hit:3 https://download.docker.com/linux/debian trixie InRelease                               
Hit:4 http://security.debian.org/debian-security trixie-security InRelease
All packages are up to date. 

可以考虑继续用 nexus 来代理 docker 的 apt 源。继续创建一个 docker apt proxy 仓库:

然后修改 docker 的 apt 源,使用 apt-docker 仓库:

sudo vi /etc/apt/sources.list.d/docker.list

将原来的内容:

deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian   trixie stable

替换为:

# offical docker apt source
# deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian   trixie stable
# nexus proxy docker apt source
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] http://192.168.3.193:8081/repository/apt-docker/   trixie stable

更新 apt 源:

sudo apt update

输出为:

Hit:1 http://192.168.3.193:8081/repository/apt-debian13 trixie InRelease
Hit:2 http://192.168.3.193:8081/repository/apt-debian13 trixie-updates InRelease
Hit:3 http://192.168.3.193:8081/repository/apt-docker trixie InRelease
Hit:4 http://security.debian.org/debian-security trixie-security InRelease
All packages are up to date.

其他编程语言仓库

需要自己创建,参见后面各个语言安装和配置的章节。

  • go module 仓库
  • rust cargo 仓库
  • npm 仓库
  • pypi 仓库

准备用户

新建一个 deployment 用户,专门用于部署。

1.2 - 编译工具

常见的编译工具,包括 make / cmake / clang 等

系统类

常用的编译工具:

sudo apt install -y cmake make gcc g++
sudo apt install -y clang libclang-dev

zlib / bzip2 / ncurses / libffi / readline / libssl / sqlite3 / lzma 等依赖库:

sudo apt install zlib1g-dev libbz2-dev libncurses-dev libffi-dev libreadline-dev libssl-dev libsqlite3-dev liblzma-dev

1.3 - sdkman

软件包管理工具,可以管理多个版本的软件包,包括 java,golang,python 等

介绍

sdkman 是一个软件包管理工具,可以管理多个版本的软件包,包括 java,golang,python 等。

官方网站:

https://sdkman.io/

可以将 sdkman 理解为多个平台上可用的工具包以简化多版本的 SDK 管理。

sdkman 支持的 jdk 列表请见: https://sdkman.io/jdks

sdkman 支持的 sdk 列表请见: https://sdkman.io/sdks

安装

安装方法参考官方文档:

https://sdkman.io/install

curl -s "https://get.sdkman.io" | bash

安装完成后,关闭当前终端重新打开新的终端,或者在当前终端中执行下面的命令立即更新:

source ~/.sdkman/bin/sdkman-init.sh

验证一下安装的版本:

$ sdk version  

SDKMAN!
script: 5.22.4
native: 0.7.32 (linux x86_64)

默认情况下,sdkman 安装在 HOME 下的 .sdkman 子目录中:

$ ls ~/.sdkman 
bin  candidates  contrib  etc  ext  libexec  src  tmp  var

使用

参考官方文档:

https://sdkman.io/usage

常用命令:

# 列出所有支持的软件包  
sdk list
# 列出所有支持的 jdk
sdk list java 
# 安装 jdk
sdk install java 17.0.14-zulu
# 卸载 jdk
sdk uninstall java 17.0.14-zulu

# 在当前 shell 中使用特定版本的 jdk
sdk use java 17.0.14-zulu
# 设置 jdk 为默认版本
sdk default java 17.0.14-zulu
# 查看当前使用的 jdk 版本
sdk current java

更新

更新 sdkman 到最新版本:

sdk selfupdate force

更新之后查看版本:

sdk version  

SDKMAN!
script: 5.20.0
native: 0.7.21 (linux x86_64)

1.4 - nginx

nginx web 服务器

安装

sudo apt install nginx

安装之后的几个目录如下:

  • /etc/nginx/nginx.conf 主配置文件
  • /etc/nginx/sites-available/ 存放虚拟主机配置文件
  • /etc/nginx/sites-enabled/ 存放虚拟主机配置文件
  • /etc/nginx/conf.d/ 存放虚拟主机配置文件
  • /etc/nginx/conf.d/ 存放虚拟主机配置文件
  • /etc/nginx/conf.d/ 存放虚拟主机配置文件

ipv6报错

nginx 默认开启 ipv6 监听,但是有时我没有开启 ipv6, 导致启动时报错:

Nov 04 10:30:22 debian13 systemd[1]: Starting nginx.service - A high performance web server
 and a reverse proxy server...
Nov 04 10:30:22 debian13 nginx[3611]: nginx: [emerg] socket() [::]:80 failed (97: Address f
amily not supported by protocol)
Nov 04 10:30:22 debian13 nginx[3611]: nginx: configuration file /etc/nginx/nginx.conf test 
failed
Nov 04 10:30:22 debian13 systemd[1]: nginx.service: Control process exited, code=exited, st
atus=1/FAILURE
Nov 04 10:30:22 debian13 systemd[1]: nginx.service: Failed with result 'exit-code'.
Nov 04 10:30:22 debian13 systemd[1]: Failed to start nginx.service - A high performance web
 server and a reverse proxy server.

关键错误信息是:

[::]:80 failed (97: Address f
amily not supported by protocol)

这个是因为 nginx 自带的默认 default site 的配置文件中设置了监听 ipv6 [::]:80 地址, 去掉就可以了:

sudo vi /etc/nginx/sites-enabled/default

注释掉 ipv6 这一行:

server {
        listen 80 default_server;
#       listen [::]:80 default_server;

再启动 nginx 即可.

sudo systemctl start nginx

1.5 - Code Server

浏览器中的 VS Code

安装

curl -fsSL https://code-server.dev/install.sh | sh

输出:

bian GNU/Linux 13 (trixie)
Installing v4.138.0 of the amd64 deb package from GitHub.

+ mkdir -p ~/.cache/code-server
+ curl -#fL -o ~/.cache/code-server/code-server_4.138.0_amd64.deb.incomplete -C - https://github.com/coder/code-server/releases/download/v4.138.0/code-server_4.138.0_amd64.deb
######################################################################## 100.0%
+ mv ~/.cache/code-server/code-server_4.138.0_amd64.deb.incomplete ~/.cache/code-server/code-server_4.138.0_amd64.deb
+ sudo dpkg -i ~/.cache/code-server/code-server_4.138.0_amd64.deb
[sudo] password for sky: 
Selecting previously unselected package code-server.
(Reading database ... 60228 files and directories currently installed.)
Preparing to unpack .../code-server_4.138.0_amd64.deb ...
Unpacking code-server (4.138.0) ...
Setting up code-server (4.138.0) ...

deb package has been installed.

To have systemd start code-server now and restart on boot:
  sudo systemctl enable --now code-server@$USER
Or, if you don't want/need a background service you can run:
  code-server

Deploy code-server for your team with Coder: https://github.com/coder/coder

也可以先下载下来,再安装:

# curl -fOL https://github.com/coder/code-server/releases/download/v$VERSION/code-server_${VERSION}_amd64.deb
curl -fOL https://github.com/coder/code-server/releases/download/v4.138.0/code-server_4.138.0_amd64.deb
sudo dpkg -i code-server_${VERSION}_amd64.deb

启动并设置为开机启动启动:

sudo systemctl enable --now code-server@$USER

如果不想开机启动,可以通过命令手工启动:

code-server

配置

基本配置

vi ~/.config/code-server/config.yaml

默认内容:

bind-addr: 127.0.0.1:8080
auth: password
password: ae89d22101b5b74bc2f5cbf5
cert: false

修改 build-addr 地址为 0.0.0.0:8080,修改密码,开启 https:

bind-addr: 0.0.0.0:8080
auth: password
password: simple
cert: true

重启:

sudo systemctl restart code-server@sky.service

访问 https://192.168.3.111:8080 输入密码就可以使用了。

安装扩展

安装编程语言的扩展:

编程语言 扩展名 publisher
Golang Go golang
Java Language Support for Java(TM) by Red Hat Red Hat
python Red Hatpython publisher ms-python
Rust rust-analyzer rust-lang
Javasript/Typescript 内置 内置

2 - 编程语言

安装和配置各种编程语言的开发环境: Java,Golang,Rust,Python,Nodejs,Python

2.1 - Java 编程语言

安装和配置 Java 的开发环境: sdkman, JDK, Maven

2.1.1 - 安装JDK

使用 sdkman 安装JDK

强烈建议使用 sdkman 之类的多版本管理方案来安装 jdk。

安装 JDK

列出当前系统中所有可用的 jdk 版本:

sdk list java

我偏好使用 zulu 的 openjdk 版本,所以这里以 zulu 为例。

jdk25(LTS)

追踪一下最新版本的 jdk, 凑巧也是 lts 版本:

sdk install java 25.0.4+1.1-zulu

jdk21(LTS)

上一个版本的 LTS, 虚拟线程正式发布,分代 ZGC、序列集合等新特性。

sdk install java 21.0.12+1.1-zulu

jdk17(LTS)

包含密封类(Sealed Classes)、模式匹配等新特性。

sdk install java 17.0.20+1.1-zulu

jdk11(LTS)

移除 Java EE 模块,引入 HTTP Client API、局部变量类型推断(var)等

sdk install java 11.0.32+1.1-zulu

jdk8(LTS)

jdk8 是最广泛使用的版本,支持 Lambda 表达式、Stream API 等。

sdk install java 8.0.504+1-zulu

使用 jdk

列出目前已经安装的 jdk 版本:

ls ~/.sdkman/candidates/java/

输出如下:

11.0.32+1.1-zulu  21.0.12+1.1-zulu  8.0.504+1-zulu
17.0.20+1.1-zulu  25.0.4+1.1-zulu   current

设置默认的 jdk 版本:

sdk default java 21.0.12+1.1-zulu

在当前 shell 中使用指定版本的 jdk,可覆盖默认设置:

sdk use java 17.0.20+1.1-zulu

查看当前使用的 jdk 版本:

$ sdk current java

Using java version 21.0.12+1.1-zulu

查看 jdk 版本信息:

$ java --version
openjdk 21.0.12.1 2026-08-18 LTS
OpenJDK Runtime Environment Zulu21.52+203-CA (build 21.0.12.1+1-LTS)
OpenJDK 64-Bit Server VM Zulu21.52+203-CA (build 21.0.12.1+1-LTS, mixed mode, sharing)

2.1.2 - 安装 Maven

安装配置 Maven

安装

sdkman 安装

列出当前系统中所有可用的 maven 版本:

sdk list maven

输出为:

Available Maven Versions
     4.0.0-rc-4          3.8.7               3.3.9                              
     3.9.11              3.8.6               3.3.3                              
     3.9.10              3.8.5               3.3.1                              
     3.9.9               3.8.4               3.2.5                              
     3.9.8               3.8.3               3.2.3                              
     3.9.7               3.8.2               3.2.2                              
     3.9.6               3.8.1               3.2.1                              
     3.9.5               3.6.3               3.1.1                              
     3.9.4               3.6.2               3.1.0                              
     3.9.3               3.6.1               3.0.5                              
     3.9.2               3.6.0               3.0.4                              
     3.9.1               3.5.4                                                  
     3.9.0               3.5.3                                                  
     3.8.9               3.5.2                                                  
     3.8.8               3.5.0                                                              

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

安装指定版本的 maven, 4.0 还是 rc 版本, 先用 3.9 系列:

sdk install maven 3.9.14

输出为:

Downloading: maven 3.9.14

In progress...

########################################################################################################################################### 100.0%

Installing: maven 3.9.14
Done installing!

查看安装的版本:

$ ls ~/.sdkman/candidates/maven/

3.9.14

重启 shell 或者执行下列命令重新加载 sdkman :

source ~/.sdkman/bin/sdkman-init.sh

安全起见,明确设置 maven 的默认版本:

sdk default maven 3.9.14

验证 maven 安装版本:

$ mvn --version

Apache Maven 3.9.14 (996c630dbc656c76214ce58821dcc58be960875b)
Maven home: /home/sky/.sdkman/candidates/maven/current
Java version: 21.0.10, vendor: Azul Systems, Inc., runtime: /home/sky/.sdkman/candidates/java/21.0.10-zulu
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.17.0-20-generic", arch: "amd64", family: "unix"

有时候不能直接生效,还是需要重新打开 shell 或者退出后重新 ssh 登录才能生效。

如果遇到类似的命令未找到的报错:

$ mvn deploy 

mvn-or-mvnw:12: command not found: mvn

可以检查 PATH 环境变量中是否包含 sdkman 下 maven 的路径:

$ echo $PATH | grep sdkman 

/home/sky/.sdkman/candidates/java/current/bin:/home/sky/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games ➜ maven-deploy-demo sdk list maven sdk current maven No current version of maven configured.

比如上面这个例子,说明 PATH 环境变量中没有包含 sdkman 下 maven 的路径。导致执行 mvn 命令时无法找到 maven 命令。还是需要执行 sdk default maven 3.9.14 命令来设置默认版本。

sdk default maven 3.9.14

然后重新打开 shell 或者退出后重新 ssh 登录才能生效。

source ~/.sdkman/bin/sdkman-init.sh

配置

配置代理服务器

如有需要,配置代理服务器:

export MAVEN_OPTS="-DsocksProxyHost=192.168.3.1 -DsocksProxyPort=7891"

配置 maven 仓库

maven 的 settings.xml 文件可以在多个地方配置,优先级从高到低依次为:

  1. 用户目录下的 .m2/settings.xml 文件
  2. 项目根目录下的 pom.xml 文件
  3. 全局配置文件, 一般在 maven 安装路径下的 conf/settings.xml 文件

在当前用户目录下创建 .m2 目录:

mkdir -p ~/.m2                   
cd ~/.m2

在 .m2 目录下创建 settings.xml 文件:

vi settings.xml

在 settings.xml 文件中添加如下内容:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">

    <servers>
        <server>
            <id>maven-releases</id>
            <username>deployment</username>
            <password>xxxxxxxx</password>
        </server>
        <server>
            <id>maven-snapshots</id>
            <username>deployment</username>
            <password>xxxxxxxx</password>
        </server>
    </servers>
   
    <mirrors>
        <mirror>
            <id>nexus-mirror</id>
            <name>Nexus Repository</name>
            <url>http://192.168.3.193:8081/repository/maven-public/</url>
            <mirrorOf>*</mirrorOf>
        </mirror>
    </mirrors>
    
    <profiles>
        <profile>
            <id>nexus</id>
            <properties>
                <altSnapshotDeploymentRepository>maven-snapshots::default::http://192.168.3.193:8081/repository/maven-snapshots/</altSnapshotDeploymentRepository>
                <altReleaseDeploymentRepository>maven-releases::default::http://192.168.3.193:8081/repository/maven-releases/</altReleaseDeploymentRepository>
            </properties>
            <repositories>
                <repository>
                    <id>maven-releases</id>
                    <url>http://192.168.3.193:8081/repository/maven-releases/</url>
                    <releases><enabled>true</enabled></releases>
                    <snapshots><enabled>false</enabled></snapshots>
                </repository>
                <repository>
                    <id>maven-snapshots</id>
                    <url>http://192.168.3.193:8081/repository/maven-snapshots/</url>
                    <releases><enabled>false</enabled></releases>
                    <snapshots><enabled>true</enabled></snapshots>
                </repository>
            </repositories>
        </profile>
    </profiles>

    
    <activeProfiles>
        <activeProfile>nexus</activeProfile>
    </activeProfiles>
</settings>

验证

验证 nexus 代理仓库的缓存功能

mkdir -p ~/work/code/temp/java-demo
cd ~/work/code/temp/java-demo

git clone https://github.com/dapr/java-sdk.git
cd java-sdk

mvn install -DskipTests -Djacoco.skip=true

第一次运行时,会因为要下载大量的依赖,速度非常慢。

之后检查 nexus 的 maven-public 和 maven-central 仓库,会发现缓存了很多依赖。

验证 nexus 缓存的效果,可以先删除本地已经下载的 maven 依赖:

rm -rf ~/.m2/repository

然后再次执行 maven 命令,会发现速度非常快。

验证 nexus hosted 仓库的上传功能

指定 maven deploy 时要用的分发仓库的方式有三种:

  1. 在 pom.xml 中配置分发仓库

    <distributionManagement>
    <snapshotRepository>
        <id>maven-snapshots</id>
        <url>http://192.168.3.193:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
    <repository>
        <id>maven-releases</id>
        <url>http://192.168.3.193:8081/repository/maven-releases/</url>
    </repository>
    </distributionManagement>
    

    这个方式要在每个项目的 pom.xml 中配置分发仓库,如果项目很多,配置起来比较麻烦。不推荐。

  2. 在命令行中强制指定仓库

    mvn deploy -DaltDeploymentRepository=maven-snapshots::default::http://192.168.3.193:8081/repository/maven-snapshots/
    

    这个方式每次执行 maven deploy 命令时都要指定仓库,也嫌麻烦。不推荐。

  3. 在 settings.xml 中配置分发仓库

    在配置 profile 时,可以设置 altSnapshotDeploymentRepository 和 altReleaseDeploymentRepository 属性,指定分发仓库。

    <profiles>
        <profile>
            <id>nexus</id>
            <properties>
                <altSnapshotDeploymentRepository>maven-snapshots::default::http://192.168.3.193:8081/repository/maven-snapshots/</altSnapshotDeploymentRepository>
                <altReleaseDeploymentRepository>maven-releases::default::http://192.168.3.193:8081/repository/maven-releases/</altReleaseDeploymentRepository>
            </properties>
            <repositories>
            </repositories>
        </profile>
    </profiles>
    

    这样执行 maven deploy 命令时,会使用配置的分发仓库。非常方便。

注意: 要在项目的 pom.xml 中配置使用 maven-deploy-plugin 插件,不要使用 nexus-staging-maven-plugin。

<project>
    ......
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>3.1.4</version>
            </plugin>
        </plugins>
    </build>
</project>

demo 验证

mkdir -p ~/work/code/temp/java-demo
cd ~/work/code/temp/java-demo


# 直接从 github 下载
wget https://github.com/skyao/learning-debian/raw/refs/heads/main/content/zh-cn/docs/develop/langurage/java/maven/images/maven-deploy-demo.tar

# 先收工下载到本地,再scp 传输文件到 devserver193 机器备用
# scp ./maven-deploy-demo.tar sky@192.168.3.193:/home/sky/work/code/temp/java-demo
# 以后用的时候再从 devserver91 机器下载
scp sky@192.168.3.193:/home/sky/work/code/temp/java-demo/maven-deploy-demo.tar .

tar -xvf maven-deploy-demo.tar
cd maven-deploy-demo

mvn deploy

输出为:

......
Uploading to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/1.0.0-SNAPSHOT/maven-deploy-demo-1.0.0-20250507.023145-1.pom
Uploaded to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/1.0.0-SNAPSHOT/maven-deploy-demo-1.0.0-20250507.023145-1.pom (887 B at 25 kB/s)
Uploading to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/1.0.0-SNAPSHOT/maven-deploy-demo-1.0.0-20250507.023145-1.jar
Uploaded to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/1.0.0-SNAPSHOT/maven-deploy-demo-1.0.0-20250507.023145-1.jar (2.2 kB at 118 kB/s)
Downloading from maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/maven-metadata.xml
Uploading to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/1.0.0-SNAPSHOT/maven-metadata.xml
Uploaded to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/1.0.0-SNAPSHOT/maven-metadata.xml (778 B at 46 kB/s)
Uploading to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/maven-metadata.xml
Uploaded to maven-snapshots: http://192.168.3.193:8081/repository/maven-snapshots/com/example/maven-deploy-demo/maven-metadata.xml (288 B at 19 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  16.809 s
[INFO] Finished at: 2025-05-07T10:32:01+08:00
[INFO] ------------------------------------------------------------------------

在 nexus 的 maven-snapshots 仓库中可以看到刚刚上传的 maven-deploy-demo 的 pom 和 jar 文件:

2.2 - Golang 编程语言

安装和配置 Golang 的开发环境

参考:

https://skyao.net/learning-golang/docs/develop/installation/

包括安装 golang 并配置 nexus 的 golang proxy 仓库来加速构建。

2.3 - Rust编程语言

安装和配置 Rust 的开发环境

参考:

https://skyao.net/learning-rust/docs/installation/linux/

2.4 - Python 编程语言

安装和配置 Python 的开发环境: python / pip

参考:

https://skyao.net/learning-python/docs/installation/linux/

包括使用 pyevn 管理多个 python 版本,配置 pip 镜像源和使用 nexus 代理仓库。

2.5 - Nodejs 编程语言

安装和配置 Nodejs 的开发环境: nodejs / npm

安装

在以下网站下载nodejs的安装包:

https://nodejs.org/en/download

按照提示进行安装即可:

# Download and install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash

# in lieu of restarting the shell
\. "$HOME/.nvm/nvm.sh"

# Download and install Node.js:
nvm install 24

# Verify the Node.js version:
node -v # Should print "v24.11.0".

# Verify npm version:
npm -v # Should print "11.6.1".

安装完成后验证:

$ node -v
v24.11.0

$ nvm current
v24.11.0

$ npm -v 
11.6.1

这里用了 nvm 来进行跨平台的 node 多版本管理。

“nvm” is a cross-platform Node.js version manager

升级 npm

有时会提示 npm 有新版本,可以升级:

npm notice
npm notice New major version of npm available! 10.9.2 -> 11.3.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.3.0
npm notice To update run: npm install -g npm@11.3.0
npm notice

升级:

npm install -g npm@11.3.0

配置 npm 镜像源

查看当前默认的镜像源:

npm config get registry

输出为:

https://registry.npmjs.org/

查看 npm 镜像源的速度

安装 nrm 来测试各源的速度:

npm install -g nrm

列出可用源:

nrm ls

输出为:

  npm ---------- 205 ms
  yarn --------- 296 ms
  tencent ------ 361 ms
  cnpm --------- 474 ms
  taobao ------- 162 ms
  npmMirror ---- 1246 ms (Fetch error, if this is your private registry, please ignore)
  huawei ------- 204 ms

切换源(例如切换到淘宝源):

nrm use taobao

测试各源速度:

nrm test

输出为:

  npm ---------- 171 ms
  yarn --------- 125 ms
  tencent ------ 472 ms
  cnpm --------- 175 ms
  taobao ------- 113 ms
  npmMirror ---- 1516 ms
  huawei ------- 461 ms

可以看到淘宝源的速度最快,切换过去:

nrm use taobao

此时打开文件 ~/.npmrc :

vi ~/.npmrc

可以看到淘宝的 npm 镜像网站 registry.npmmirror.com 已经配置好了:

home=https://npmmirror.com
registry=https://r.cnpmjs.org/

备注: home 现在可以不用设置了。

配置 npm 镜像源

也可以手工修改 ~/.npmrc 文件:

vi ~/.npmrc

添加以下内容:

registry=https://r.cnpmjs.org/

配置 nexus 代理仓库

新建代理仓库

在 nexus 中新建两个 npm proxy 代理仓库:

再新建一个名为 npm-public 的 npm group 仓库,将上面两个仓库加入其中,顺序为:

  • npm-proxy-taobao
  • npm-proxy-cnpm

使用代理仓库

使用代理仓库:

vi ~/.npmrc

设置为以下内容:

registry=http://192.168.3.193:8081/repository/npm-public/

验证代理

安装一些东西:

npm install --save-dev autoprefixer
npm install --save-dev postcss-cli
npm install -D postcss

然后去看 nexus 的代理仓库:

可以看到代理仓库中已经有了这些包。

设置代理

有时需要设置代理,比如在腾讯云国内的服务器上用 npm install,中间会访问 objects.githubusercontent.com, 导致失败。

尝试设置 npm 的代理:

npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890

查看代理设置:

npm config get proxy
npm config get https-proxy

也还是无法访问 objects.githubusercontent.com。莫名其妙不知道为什么。

没办法,只能尝试用 proxychains 强制 npm 走代理。

具体做法参考: clash 科学上网

3 - 构建模板

在 debian 12 上构建用于编程开发相关的模板

3.1 - 构建 basic 模板

构建最基本的 debian 13 系统

https://skyao.net/learning-pve/templates/debian13/basic/

3.1.1 - 构建 basic 模板

创建 debian 13 基础模板

制作过程

参考 debian 学习笔记 的 pve 安装文档, 安装 debian 13 操作系统。

然后完成基本配置,内核配置,并通过 timeshift 进行系统备份。

模板内容

debian 13

  • apt 升级到 debian 13.6.0
  • 更新 apt 到最新内核 6.12.48
  • 安装 timeshift, zsh/ohmyzsh, git, dkms, iperf/iperf3, unzip zip curl
  • 添加 proxyon/proxyoff alias for different locations
  • 修复 path 不足问题,包括用户 root 和 sky
  • 安装 sftp server, nfs server 和 client, samba server

地域迁移

当迁移到其他地域时,需要修改的设置有

  1. proxy 设置

    vi ~/.zshrc
    

    修改 proxyon:

    alias proxyon='proxyon-nansha'
    

3.1.2 - 创建虚拟机

创建使用 debian 13 基础模板的虚拟机

创建虚拟机

临时使用

为了加速创建,可以先将模板克隆到本地,然后从本地的模板中采用 Linked Clone 方式克隆。

这样从模板 clone 虚拟机, 速度会非常快,而且空间占用也非常小。

使用完成后删除即可。因为不需要长期使用和维护,因此不存在多版本问题。每次 Linked Clone 方式克隆最快最不占用磁盘空间。

长期使用

长期使用时,还是采用 full clone 的方式比较好,后续可以单独为这台虚拟机进行 apt upgrade。

Linked Clone 方式克隆最大的麻烦是无法跨 template 升级,因此如果 template 有更新,就会出现版本割裂。

修改虚拟机配置

主要是修改虚拟机的 hostname,以及必要时从使用 dhcp 自动获取 ip 地址修改为使用静态 ip 地址。

3.2 - 构建 dev 模板

构建可快速搭建,可重复使用的编程开发环境

https://skyao.net/learning-pve/templates/debian13/dev/

3.2.1 - 创建模板

创建基于debian12/13 的 dev 开发模板

制作过程

以 debian 13 为例。

准备虚拟机

从模版 template-debian13-basic-vxx (取最新版本) full clone 克隆一个虚拟机,命名为 template-debian13-dev-v01,VM ID 为 990101.

开发需要的 cpu 和内存稍大,修改虚拟机参数,cpu 修改为 8 核,内存 32g(mini 8192,memory 32768)。

准备 ssh 证书

重新生成一份 ssh 证书,这个是要提交给 github 的,单独用一份。

搭建开发环境

安装 docker

安装开发工具

参考本读书笔记中的 开发工具 一节, 安装开发工具:

  • sdkman

语言 sdk 和 nexus 私库

参考本读书笔记中的 编程语言 一节, 安装语言 sdk 和对应的 nexus 私库:

  • Java: 包括 maven
  • golang
  • rust
  • python
  • nodejs

地域迁移

当迁移到其他地域时,需要修改的设置除了有 basic 的改动之外,还有 devserver9x 相关的配置:

  1. docker 使用的 habor 代理 : https://skyao.net/learning-docker/docs/repository/harbor/transparent-proxy/

  2. java 的 maven 配置: https://skyao.net/learning-debian/docs/develop/langurage/java/maven/

  3. golang 的 goproxy 配置: https://skyao.net/learning-golang/docs/develop/installation/settings/

  4. rust 的 cargo 代理源配置: ttps://skyao.net/learning-rust/docs/installation/cargo/

  5. python 的 pip 代理配置: https://skyao.net/learning-python/docs/installation/pip/

  6. nodejs 的 代理配置: https://skyao.net/learning-debian/docs/develop/langurage/nodejs/

3.2.2 - 创建实例

基于模板创建开发环境实例

准备虚拟机

临时使用

为了加速创建,可以先将模板克隆到本地,然后从本地的模板中采用 Linked Clone 方式克隆。

这样从模板 clone 虚拟机, 速度会非常快,而且空间占用也非常小。

使用完成后删除即可。因为不需要长期使用和维护,因此不存在多版本问题。每次 Linked Clone 方式克隆最快最不占用磁盘空间。

长期使用

长期使用时,还是采用 full clone 的方式比较好,后续可以单独为这台虚拟机进行 apt upgrade。

Linked Clone 方式克隆最大的麻烦是无法跨 template 升级,因此如果 template 有更新,就会出现版本割裂。

从模版 template-debian13-dev-vxx 克隆三个虚拟机,命名为 dev111/dev121/dev131,三个开发机备用.

开发需要的 cpu 和内存稍大,修改虚拟机参数,cpu 修改为 16核 (cpu 亲和性设置为 0-15,用大核),内存 32g (8192 MB 到 32768)。

基本配置修改

修改 hostname 和 使用静态 IP 地址。

理论上应该就可以直接拿来用了。后续如果发现有需要修改的地方,再记录下来。

3.3 - 构建 devserver 模板

构建用于编程开发的服务器模板

https://skyao.net/learning-pve/templates/debian13/devserver/

3.3.1 - 创建模板(debian13)

创建 debian 13 开发服务器模板

准备工作

以 debian 13 为例,debian13 后开发服务器不再是一台独立服务器和两块单独的 ssd 硬盘。所有构建方式和之前的有比较大的差异。

准备虚拟机

从模版 template-debian13-basic-v01 (取最新版本) full clone 克隆一个虚拟机,命名为 template-debian13-devserver-v01,VM ID 为 990201.

开发需要的 cpu 和内存稍大,修改虚拟机参数,cpu 修改为 8 核,内存 16g(mini 8192,memory 16384)。

准备磁盘

devserver 预计会有两台实例,用于两个异地的开发环境。

为每台实例准备了 2 块两块额外的磁盘,一块用于应用(如数据库,redis,queue等),一块用于数据(如pve需要的nfs,habor / nexus 代理仓库等)。在虚拟机硬件中,增加两块 hard disk,大小为 1024g,scsi 类型,virtIO scsi 控制器。注意把 backup 选项勾选去掉。

在 pve 中,将两块 hard disk 磁盘添加到虚拟机:

在虚拟机中可以看到这两块磁盘:

lspci | grep storage
09:01.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
09:02.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
09:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI

参考本读书笔记中的 devserver193 一节, 配置好磁盘并进行分区,并挂载到 /mnt/data 和 /mnt/app 目录, 然后安装 nfs server。

搭建开发环境

安装 docker 和 habor

安装开发工具

参考本读书笔记中的 开发工具 一节, 安装开发工具:

  • sdkman
  • nexus

语言 sdk 和 nexus 私库

参考本读书笔记中的 编程语言 一节, 安装语言 sdk 和对应的 nexus 私库:

  • Java: 包括 maven
  • golang
  • rust
  • python
  • nodejs

3.3.2 - 创建虚拟机

创建使用 devserver 模板的开发服务器虚拟机

创建虚拟机

devserver 模板实际只会有两个虚拟机实例:

  • devserver91: ip 192.168.3.91, 用于苏州汾湖的开发环境
  • devserver92: ip 192.168.0.92, 用于广州南沙的开发环境

由于两个虚拟机都使用到直通的两块 900g 三星 pm983a ssd,因此无法简单的从模板克隆就能自动恢复所有的数据。

实践中,先按照 devserver91 的配置搭建好虚拟机,然后直接使用直通的 ssd 就能正常工作了。

devserver92 是将模板(去除直通的两块 ssd)传送到广州南沙,然后从模板克隆虚拟机,再直通两块空的 ssd 硬盘。

配置 devserver91

几乎不需要配置。

配置 devserver92

原则上需要按照搭建模板的方式, 重头走一遍所有流程来完成 devserver92 的配置。

中间很多步骤是可以重用之前已有的资料和信息,但是需要检查每一个步骤,看是否有需要改动的地方,最重要的改动就是这个机器的 ip 地址从 devserver91 的 192.168.3.91 修改为 devserver92 的 192.168.0.92。

而这个 ip 地址的修改,散落在很多地方, 为了不疏漏,只能重新走一遍完成的流程,好在大部分操作都还继续有效,只是修改个别配置文件更改 ip 地址即可。

3.4 - 构建 docker 模板

构建可快速搭建,可重复使用的 docker 运行环境

https://skyao.net/learning-pve/templates/debian13/docker/

3.4.1 - 创建模板

创建基于 debian13 的 docker 模板

制作过程

准备虚拟机

从模版 template-debian13-basic-vxx (取最新版本) full clone 克隆一个虚拟机,命名为 template-debian13-docker-vxx,VM ID 为 9903xx.

搭建开发环境

安装 docker

地域迁移

当迁移到其他地域时,需要修改的设置除了有 basic 的改动之外,还有 devserver9x 相关的配置:

  1. docker 使用的 habor 代理 : https://skyao.net/learning-docker/docs/repository/harbor/transparent-proxy/

3.4.2 - 创建实例

基于模板创建 docker 实例

准备虚拟机

临时使用

为了加速创建,可以先将模板克隆到本地,然后从本地的模板中采用 Linked Clone 方式克隆。

这样从模板 clone 虚拟机, 速度会非常快,而且空间占用也非常小。

使用完成后删除即可。因为不需要长期使用和维护,因此不存在多版本问题。每次 Linked Clone 方式克隆最快最不占用磁盘空间。

长期使用

docker 模板貌似没什么长期使用的场景。临时用一下就好了,长期用就换 dev 模板吧。

基本配置修改

修改 hostname 和 使用静态 IP 地址。

3.5 - 构建 k8s 模板

构建用于 k8s 的 pve 模板

https://skyao.net/learning-pve/templates/debian13/k8s/

3.5.1 - 创建模板

创建 debian 12 k8s 模板

准备工作

准备虚拟机

从模版 template-debian12-basic-v03 (取最新版本) 克隆一个虚拟机,命名为 template-debian12-k8s-v01,VM ID 为 990401.

k8s 需要的 cpu 和内存稍大,修改虚拟机参数,cpu 修改为 8 核,内存 16g(mini 8192,memory 16384)。

搭建k8s

目前采用的是预热安装的方式,详细参考:

https://skyao.net/learning-kubernetes/docs/installation/kubeadm/debian12/prewarm/

3.5.2 - 创建虚拟机

创建使用 k8s 模板的虚拟机

创建虚拟机

从模板 template-debian12-k8s-v01 克隆一个虚拟机,命名为 k8sxxx。

配置虚拟机

参考: 克隆后的配置 一节

修改hostname 为 k8sxxx,设置 ip 地址为固定ip。

重启。

搭建k8s

wd k8s

sudo ./install_k8s_prewarm.zsh 192.168.3.112

安装完成之后记得 timeshift 备份:

sudo timeshift --create --comments "setup k8s to be host k8s112"