引言
前几天公司让搭建一个 Nexus 做一个私服。
先简单介绍下为什么要搭建这个服务:
Nexus 是一个强大而灵活的仓库管理工具,广泛应用于 DevOps 和软件开发团队。无论是托管内部构件、代理公共仓库,还是作为 Docker 镜像仓库,Nexus 都能提供高效的解决方案。同时,它与 CI/CD 工具集成良好,是现代软件开发流程中不可或缺的组件。
最主要的是可以将我们开发相关的包放进去。
这边的 Nexus 是使用 Docker-Compose 直接部署了一个。
version: '3'
services:
nexus3:
restart: unless-stopped
image: sonatype/nexus3:latest
build: .
container_name: nexus3
environment:
- TZ=Asia/Shanghai
ports:
- 8081:8081
volumes:
- /data/nexus/data:/nexus-data
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
访问的时候,直接 IP 地址加端口。但是这样的方式在浏览器中不是很友好,于是加上了域名解析,使用域名加端口,哈哈,很有意思吧。但是后面又觉得不安全,决定使用 SSL 证书访问,那就整呗。
开始
决定使用 Yum 在本地安装一个算了,创建一个 /etc/nginx/certs 目录,然后把 SSL 证书放进去。
然后这边主要是说一下 Nginx 的配置:
# /home/user/nginx/conf/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# 启用 Gzip 压缩
gzip on;
gzip_disable "msie6";
# 定义后端服务的 upstream
upstream backend {
server 8.209.247.131:8081; # 后端服务地址
}
# HTTP 服务器 - 处理 ACME Challenge 并重定向到 HTTPS
server {
listen 80;
server_name nexus.test.com;
# 配置 ACME Challenge 的路径
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}
# 将所有其他 HTTP 请求重定向到 HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS 服务器
server {
listen 443 ssl;
server_name nexus.test.com;
# SSL 证书和私钥路径
ssl_certificate /etc/nginx/certs/test.com.pem;
ssl_certificate_key /etc/nginx/certs/test.com.key;
# SSL 协议和加密套件配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
# 启用 HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# SSL 会话缓存和超时
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 日志配置
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# 反向代理设置
location / {
proxy_pass http://backend;
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;
# 支持 WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 可选:额外的安全头部
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
}
# 可选:其他服务器块或配置
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
然后重载上面的配置 :
systemctl reload nginx
- 1.
访问:
图片
看起来是可以访问到,但是没有访问到后端服务 Nexus,这是什么情况呢。
来看下日志吧,看看有什么线索没:
10.23.45.67 - - [31/Dec/2024:10:01:09 +0800] "GET /favicon.ico HTTP/1.1" 502 559 "https://nexus.test.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
12.34.56.78 - - [31/Dec/2024:10:08:38 +0800] "GET /favicon.ico HTTP/1.1" 502 559 "https://nexus.test.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
15.67.89.90 - - [31/Dec/2024:10:13:17 +0800] "GET /favicon.ico HTTP/1.1" 502 559 "https://nexus.test.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
2024/12/31 10:00:37 [error] 24090#0: *23 connect() failed (110: Connection timed out) while connecting to upstream, client: 10.23.45.67, server: nexus.test.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://12.45.67.89:8081/favicon.ico", host: "nexus.test.com", referrer: "https://nexus.test.com/"
2024/12/31 10:08:38 [error] 24226#0: *29 connect() failed (110: Connection timed out) while connecting to upstream, client: 12.34.56.78, server: nexus.test.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://23.56.78.90:8081/favicon.ico", host: "nexus.test.com", referrer: "https://nexus.test.com/"
2024/12/31 10:13:17 [error] 24226#0: *33 connect() failed (110: Connection timed out) while connecting to upstream, client: 15.67.89.90, server: nexus.test.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://34.67.89.12:8081/favicon.ico", host: "nexus.test.com", referrer: "https://nexus.test.com/"
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
还是看不出来具体的错误,大佬们有经验的可以先思考下。
经过一番排查,误以为是和 VPN 有关系,于是,想了半天,要不然试试 127.0.0.1。
试下,我这里选择更改我的 upstream 的地址:
# /home/user/nginx/conf/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# 启用 Gzip 压缩
gzip on;
gzip_disable "msie6";
# 定义后端服务的 upstream
upstream backend {
server 127.0.0.1:8081; # 后端服务地址
}
# HTTP 服务器 - 处理 ACME Challenge 并重定向到 HTTPS
server {
listen 80;
server_name nexus.test.com;
# 配置 ACME Challenge 的路径
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}
# 将所有其他 HTTP 请求重定向到 HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS 服务器
server {
listen 443 ssl;
server_name nexus.test.com;
# SSL 证书和私钥路径
ssl_certificate /etc/nginx/certs/test.com.pem;
ssl_certificate_key /etc/nginx/certs/test.com.key;
# SSL 协议和加密套件配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
# 启用 HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# SSL 会话缓存和超时
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 日志配置
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# 反向代理设置
location / {
proxy_pass http://backend;
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;
# 支持 WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 可选:额外的安全头部
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
}
# 可选:其他服务器块或配置
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
搞笑了,这波操作,属实是给我弄的不想说什么了,哈哈,但是又有新的问题了,我们接着看
又有新的错误了:
图片
排查了会儿,新的问题是 跨域问题(CORS)。
1. "Uncaught SecurityError" 表明浏览器阻止了对 nexus.test.com 的跨域访问。
2. Blocked a frame with origin 表示 Nexus 的前端代码试图访问另一个域或协议(可能是 HTTP 而非 HTTPS,或子域不匹配)。
原因分析
1.协议或域名不一致:
• Nexus 的资源(如静态文件或 API 请求)可能仍指向 HTTP,而您使用的是 HTTPS。
• Nexus 的前端代码试图访问外部的资源,但浏览器将其视为跨域。
2.Nginx 配置问题:
• Nginx 的反向代理可能没有正确设置 CORS 相关头部,导致资源加载失败。
解决方法
更新 Nginx 配置以支持 CORS
为 Nginx 添加 CORS 支持,允许 Nexus 的前端和 API 资源在同一个域下工作。
在 Nginx 的 location / 配置中,添加以下内容:
location / {
·····
# 添加 CORS 头部
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Authorization, Accept, Content-Type";
·····
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
重新加载 Nginx:
systemctl reload nginx
- 1.
再次访问:
图片
可以看到,没有问题了。
结语
经过这一次的故障排查,又加深了我对 Nginx 的学习。
因为啥呢,工作这边很少会有去部署一个 Nginx,然后去配置相应的参数,真的很少。但是当有这种情况,你又不能说不会,或者不干。在这个排查的过程中,当时排查的真的有点泄气,但是总归还是过来了。