搭建
搭建
先将域名指定好服务器ip
运行以下脚本安装
curl -L https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/main/install.sh -o nezha.sh && chmod +x nezha.sh && ./nezha.sh
以 Docker 安装为例,安装完成后按提示输入以下信息:
请输入站点标题:
- 自定义站点标题。请输入暴露端口:
- 公开访问端口(默认 8008,可自定义)。请指定后台语言:
- 选择语言偏好。
输入完成后,等待拉取 Docker 镜像。安装结束后,如果一切正常,你可以通过域名和端口号访问 Dashboard,例如: http://dashboard.example.com
宝塔反代:(省略宝塔安装)
创建一个网站,静态解开
打开配置文件菜单,在最后面填上以下代码,然后点保存:(如果在安装哪吒监控时,你自定义了端口,把下面代码中的8008改为你自定义的端口)
upstream dashboard {
keepalive 512;
server 127.0.0.1:8008;
}
关键一步
打开反向代理 —— 添加反向代理,127.0.01:8008,保存.
然后点击上图中添加的反向代理目录中的配置文件,将里面的内容全选删除,并替换为以下代码,然后点保存:(如果在安装哪吒监控时,你自定义了端口,把下面代码中的8008改为你自定义的端口)
location ^~ / {
proxy_pass http://127.0.0.1:8008;
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 REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header nz-realip $http_cf_connecting_ip;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffer_size 128k;
proxy_buffers 4 128k;
proxy_busy_buffers_size 256k;
proxy_max_temp_file_size 0;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
proxy_ssl_server_name off;
proxy_ssl_name $proxy_host;
add_header Strict-Transport-Security "max-age=31536000";
}
underscores_in_headers on;
set_real_ip_from 0.0.0.0/0; # CDN 回源 IP 地址段
real_ip_header CF-Connecting-IP; # CDN 私有 header,此处为 CloudFlare 默认
# gRPC 服务
location ^~ /proto.NezhaService/ {
grpc_set_header Host $host;
grpc_set_header nz-realip $http_CF_Connecting_IP;
grpc_read_timeout 600s;
grpc_send_timeout 600s;
grpc_socket_keepalive on;
client_max_body_size 10m;
grpc_buffer_size 4m;
grpc_pass grpc://dashboard;
}
# WebSocket 服务
location ~* ^/api/v1/ws/(server|terminal|file)(.*)$ {
proxy_set_header Host $host;
proxy_set_header nz-realip $http_cf_connecting_ip;
proxy_set_header Origin https://$host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_pass http://127.0.0.1:8008;
}
然后开启ssl。
关键步骤
更改面板密码后,进入管理后台-系统设置,Agent对接地址【域名/IP:端口】中更改为: dashboard.example.com:8008
,前端真实IP请求头更改为:
CF-Connecting-IP
美化
<script>
window.TrafficScriptConfig = {
showTrafficStats: true, // 显示流量统计
insertAfter: true, // 如果开启总流量卡片, 放置在总流量卡片后面
interval: 60000, // 60秒刷新缓存, 单位毫秒
toggleInterval: 4000, // 4秒切换流量进度条右上角内容, 0秒不切换, 单位毫秒
duration: 500, // 缓进缓出切换时间, 单位毫秒
enableLog: false // 开启日志
};
</script>
<script src="https://cdn.jsdelivr.net/gh/ziwiwiz/nezha-ui@main/traffic-progress.js"></script>
<script>
// window.CustomBackgroundImage = "https://bing.img.run/rand_uhd.php"; /* 页面背景图 */
// window.CustomMobileBackgroundImage = "https://bing.img.run/rand_m.php"; /* 移动端页面背景图 */
/* 关掉人物插图 */
// window.DisableAnimatedMan = "true";
/* 自定义描述 */
window.CustomDesc = " ";
/* 固定顶部服务器名称 */
window.FixedTopServerName = "true";
/* 卡片显示上下行流量 */
// window.ShowNetTransfer = "true";
</script>
哪吒详情页直接展示网络波动卡片
网络波动卡片(网络波动在服务器各项参数下方
)
/* 源自https://www.nodeseek.com/post-349102-1 */
<script src="https://cdn.jsdelivr.net/gh/ziwiwiz/nezha-ui@main/netstatus-autoshow.js"></script>
或(网络波动在服务器各项参数下方
和上述链接的效果一致)
<script>
const selectorButton = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > section > div.flex.justify-center.w-full.max-w-\\[200px\\] > div > div > div.relative.cursor-pointer.rounded-3xl.px-2\\.5.py-\\[8px\\].text-\\[13px\\].font-\\[600\\].transition-all.duration-500.text-stone-400.dark\\:text-stone-500';
const selectorSection = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > section';
const selector3 = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > div:nth-child(3)';
const selector4 = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > div:nth-child(4)';
let hasClicked = false;
let divVisible = false;
function forceBothVisible() {
const div3 = document.querySelector(selector3);
const div4 = document.querySelector(selector4);
if (div3 && div4) {
div3.style.display = 'block';
div4.style.display = 'block';
}
}
function hideSection() {
const section = document.querySelector(selectorSection);
if (section) {
section.style.display = 'none';
}
}
function tryClickButton() {
const btn = document.querySelector(selectorButton);
if (btn && !hasClicked) {
btn.click();
hasClicked = true;
setTimeout(forceBothVisible, 500);
}
}
const observer = new MutationObserver(() => {
const div3 = document.querySelector(selector3);
const div4 = document.querySelector(selector4);
const isDiv3Visible = div3 && getComputedStyle(div3).display !== 'none';
const isDiv4Visible = div4 && getComputedStyle(div4).display !== 'none';
const isAnyDivVisible = isDiv3Visible || isDiv4Visible;
if (isAnyDivVisible && !divVisible) {
hideSection();
tryClickButton();
} else if (!isAnyDivVisible && divVisible) {
hasClicked = false;
}
divVisible = isAnyDivVisible;
if (div3 && div4) {
if (!isDiv3Visible || !isDiv4Visible) {
forceBothVisible();
}
}
});
const root = document.querySelector('#root');
if (root) {
observer.observe(root, {
childList: true,
attributes: true,
subtree: true,
attributeFilter: ['style', 'class']
});
}
</script>
或(网络波动在服务器各项参数上方
)
<script>
const selectorButton = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > section > div.flex.justify-center.w-full.max-w-\\[200px\\] > div > div > div.relative.cursor-pointer.rounded-3xl.px-2\\.5.py-\\[8px\\].text-\\[13px\\].font-\\[600\\].transition-all.duration-500.text-stone-400.dark\\:text-stone-500';
const selectorSection = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > section';
const selector3 = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > div:nth-child(3)';
const selector4 = '#root > div > main > div.mx-auto.w-full.max-w-5xl.px-0.flex.flex-col.gap-4.server-info > div:nth-child(4)';
let hasClicked = false;
let divVisible = false;
let swapping = false;
function forceBothVisible() {
const div3 = document.querySelector(selector3);
const div4 = document.querySelector(selector4);
if (div3 && div4) {
div3.style.display = 'block';
div4.style.display = 'block';
}
}
function hideSection() {
const section = document.querySelector(selectorSection);
if (section) {
section.style.display = 'none';
}
}
function tryClickButton() {
const btn = document.querySelector(selectorButton);
if (btn && !hasClicked) {
btn.click();
hasClicked = true;
setTimeout(forceBothVisible, 500);
}
}
function swapDiv3AndDiv4() {
if (swapping) return;
swapping = true;
const div3 = document.querySelector(selector3);
const div4 = document.querySelector(selector4);
if (!div3 || !div4) {
swapping = false;
return;
}
const parent = div3.parentNode;
if (parent !== div4.parentNode) {
swapping = false;
return;
}
// 交换 div3 和 div4 的位置
parent.insertBefore(div4, div3);
parent.insertBefore(div3, div4.nextSibling);
swapping = false;
}
const observer = new MutationObserver(() => {
const div3 = document.querySelector(selector3);
const div4 = document.querySelector(selector4);
const isDiv3Visible = div3 && getComputedStyle(div3).display !== 'none';
const isDiv4Visible = div4 && getComputedStyle(div4).display !== 'none';
const isAnyDivVisible = isDiv3Visible || isDiv4Visible;
if (isAnyDivVisible && !divVisible) {
hideSection();
tryClickButton();
setTimeout(swapDiv3AndDiv4, 100);
} else if (!isAnyDivVisible && divVisible) {
hasClicked = false;
}
divVisible = isAnyDivVisible;
if (div3 && div4) {
if (!isDiv3Visible || !isDiv4Visible) {
forceBothVisible();
}
}
});
const root = document.querySelector('#root');
if (root) {
observer.observe(root, {
childList: true,
attributes: true,
subtree: true,
attributeFilter: ['style', 'class']
});
}
</script>
本文作者:admin
本文链接:https://zlqwz.com/archives/nezha.html
版权声明:所有文章除特别声明外,均系本人自主创作。转载及引用请联系作者,并注明出处(作者、原文链接等)。