Welcome to CX’s Blog

Hugo 使用指南

Hugo 使用指南 适用版本:Hugo v0.168.0(Extended)。命令以 macOS/Linux 的 shell 为例。根据 Hugo 官方文档整理,主题私有配置以实际主题仓库为准。 1. 安装与版本检查 macOS(Homebrew): brew install hugo hugo version hugo env Linux 可使用对应发行版软件包或 Hugo 官方发布的二进制文件。使用 SCSS/Sass 或某些主题资产管道时,需要确认安装版本包含 Extended 功能。 2. 创建项目 hugo new project myblog cd myblog git init 典型目录结构: myblog/ ├── archetypes/ # 新文章模板 ├── assets/ # 需通过资源管道处理的资源 ├── content/ # Markdown 内容 ├── data/ # 数据文件 ├── i18n/ # 主题界面翻译 ├── layouts/ # 自定义模板,可覆盖主题模板 ├── static/ # 原样复制到网站根路径 ├── themes/ # 本地主题或 Git 子模块 ├── hugo.toml # 网站配置(也可使用 YAML 等格式) └── public/ # 构建产物(运行 hugo 后生成) Hugo 本体不附带完整博客外观。若没有可用主题或自定义布局,可能出现 found no layout file for "html" 的警告。 ...

October 17, 2026 · 3 min

在 Debian 上部署 LibreSpeed 并用 Caddy 反向代理

LibreSpeed 的 Go 后端内置 Web 界面,提供测量下载、上传和延迟的 HTTP 接口。本文用 systemd 在 Debian 上以非 root 身份运行后端,由同一台主机上的 Caddy 提供公网 HTTPS 入口。 安装 Debian 预编译二进制 本文固定使用 LibreSpeed speedtest-go v1.1.6,命令适用于 Debian amd64 和 arm64。发布包中的 speedtest-backend 已内置默认前端资源。其他架构可查看官方发布页。 sudo apt update sudo apt install curl ca-certificates ( set -eu version=1.1.6 arch=$(dpkg --print-architecture) case "$arch" in amd64|arm64) ;; *) printf 'Select a release archive for %s\n' "$arch" >&2; exit 1 ;; esac archive="speedtest-go_${version}_linux_${arch}.tar.gz" release="https://github.com/librespeed/speedtest-go/releases/download/v${version}" workdir=$(mktemp -d) trap 'rm -rf -- "$workdir"' EXIT cd "$workdir" curl -fsSL -o "$archive" "$release/$archive" curl -fsSL -o checksums.txt "$release/checksums.txt" awk -v file="$archive" '$2 == file || $2 == "*" file' checksums.txt > archive.sha256 sha256sum -c archive.sha256 tar -xzf "$archive" sudo install -d -m 0755 /usr/local/bin sudo install -m 0755 speedtest-backend /usr/local/bin/speedtest-backend ) 配置 systemd 服务 后端监听本机回环地址,由 Caddy 终止 TLS。database_type = "none" 关闭测速结果和统计记录。参见上游的 TOML 示例和 systemd unit。 ...

November 13, 2026 · 3 min

使用 systemd-resolved 为 WireGuard 配置按域名分流的 DNS

连接 WireGuard 后,有时只希望内网域名通过隧道中的 DNS 查询,其他域名仍使用公共 DNS。对于已经使用 systemd-resolved 的 Linux 系统,可以直接配置 DNS 路由域,再通过 wg-quick 的 PostUp 自动应用,无须额外安装 DNS 转发服务。 ...

November 12, 2026 · 4 min

小内存 Debian 服务器防护改造:从 CrowdSec 迁移到 Caddy GeoIP 与 Fail2ban

在一台内存较小的 Debian 服务器上,我原先使用 CrowdSec 分析 SSH 和 Web 日志,再通过 Firewall Bouncer 将封禁决策同步到 nftables。 这套方案能够根据攻击行为动态封禁 IP,但对于只有数百 MiB 内存、运行多个个人服务的服务器,资源开销需要重新权衡。最终我采用了以下组合: 网站:Caddy GeoIP 与手动 IP 白名单,按站点选择是否允许 CDN 回源豁免。 SSH:Fail2ban 读取 systemd journal,通过 nftables 封禁异常来源。 本文记录完整改造方法,以及部署过程中遇到的日志来源和启动时序问题。所有域名、地址和主机标识均已替换为示例。命令按 root 用户执行。 一、先明确防护能力的变化 项目 原方案 新方案 Web 访问控制 CrowdSec 分析日志并生成封禁决策 Caddy 按来源地区或 IP 放行 SSH 异常登录 CrowdSec SSH 场景 Fail2ban SSH jail Web 行为检测 取决于安装的 Collection 和 Scenario 本文没有保留 社区威胁情报 可使用 CrowdSec 社区名单 本文没有接入 Web 拒绝位置 Firewall Bouncer 的防火墙规则 Caddy HTTP 请求处理阶段 地区白名单不能等价替代行为检测。允许地区内的恶意请求仍可能到达应用,Caddy 的 GeoIP 规则也不会覆盖没有经过它的其他公网端口。 ...

November 10, 2026 · 7 min

Tobita Guide

初探、一見 1-進店篇 2-妹子篇 3-服務篇 4-感謝篇

November 3, 2026 · 1 min

Mac 与 iPhone 使用客户端证书访问 mTLS 网站

Mac 与 iPhone 使用客户端证书访问 mTLS 网站 本文记录在 macOS 和 iPhone 上使用客户端证书访问内网 mTLS 网站的方法,涉及 CanoKey PIV、step-ca、Nginx 和 iOS 系统证书安装。 1. 环境与认证流程 当前环境: CA:已有的 CX-Homelab-CA Root CA 和 CX-Homelab-CA Intermediate CA。 证书签发:step-ca。 Web 服务器:Nginx 1.25.0。 测试站点:https://www.home.arpa。 Mac 客户端:CanoKey PIV 9A。 iPhone 客户端:通过 PKCS#12 文件导入客户端证书及私钥。 mTLS 与普通 HTTPS 的区别是:服务器验证客户端证书,客户端也需要验证服务器证书。客户端证书必须包含对应的私钥,单独安装 .crt 文件通常不足以完成客户端身份认证。 基本流程如下: 客户端访问 HTTPS 站点。 Nginx 请求客户端证书。 浏览器或系统选择客户端身份,并使用对应私钥完成 TLS 握手。 Nginx 验证客户端证书的有效性、证书链和用途。 验证通过后,服务器允许访问受保护的资源。 需要注意,客户端证书和服务器 CA 信任是两个不同的问题。安装客户端身份,并不意味着设备已经信任签发网站服务器证书的私有 CA。 2. Mac:使用 CanoKey PIV 9A 2.1 当前方案 Mac 使用 CanoKey 的 PIV 9A 槽保存客户端身份。macOS 通过智能卡相关机制识别证书和私钥,浏览器在 TLS 握手时使用该身份。 ...

October 26, 2026 · 3 min

macOS 与 iOS 使用客户端证书访问 mTLS 网站

macOS 与 iOS 使用客户端证书访问 mTLS 网站 本文介绍如何在 macOS 和 iOS 设备上配置客户端证书,以访问启用双向 TLS(mTLS)的 HTTPS 网站。示例使用私有 CA、step-ca、Nginx、PKCS#12 和 PIV 智能卡。文中的域名、证书名称、文件名和 IP 地址均为示例,请替换为自己的实际值。 1. mTLS 认证流程 普通 HTTPS 主要由客户端验证服务器证书;mTLS 还要求服务器验证客户端证书。 基本流程: 客户端访问 HTTPS 站点。 Nginx 在 TLS 握手期间请求客户端证书。 浏览器或系统选择客户端身份,并使用对应私钥完成签名。 Nginx 根据配置验证客户端证书、证书链和有效期。 验证通过后,连接进入 HTTP 层,由站点策略决定是否允许访问。 客户端身份和服务器 CA 信任是两个独立配置: 客户端身份:客户端证书及与之匹配的私钥,用于向服务器证明身份。 服务器 CA 信任:客户端信任签发网站服务器证书的 CA,用于验证 HTTPS 服务器身份。 安装客户端证书不会自动让设备信任私有 CA。 2. macOS:使用 PIV 硬件密钥 如果客户端私钥保存在支持 PIV 的硬件密钥中,可以让私钥留在硬件设备内,避免导出私钥文件。浏览器是否能使用该身份,取决于 macOS、智能卡中间件、密钥设备和浏览器的支持情况。 一般检查步骤: 插入 PIV 硬件密钥。 确认 macOS 能识别智能卡及其证书。 打开浏览器并访问 mTLS 网站。 如果浏览器请求客户端证书,选择对应的身份。 按提示输入 PIN 或完成硬件操作。 结合页面结果和服务器日志确认认证是否成功。 可用以下命令检查系统状态: ...

October 26, 2026 · 4 min

用 YubiKey 保护 Git:FIDO2 SSH 认证与提交签名

Git 的仓库认证与提交签名是两个独立环节:前者决定能否拉取、推送代码,后者让接收者验证提交由哪把密钥签署。本文使用两对独立的 FIDO2 SSH 密钥,将这两个用途分开管理。 Git 支持使用 SSH 密钥签署 Commit 和 Tag,因此只围绕 Git 开发时,可以直接使用 YubiKey 的 FIDO2 功能,无须额外部署 GnuPG。需要遵循 OpenPGP 验签流程的项目,则应按项目要求选择 GPG 签名。 ...

October 25, 2026 · 5 min

OpenWrt IPv6 有地址却提示网络不可达:一次 mwan3 策略路由排查

WAN6 已拿到 IPv6 地址,但在 OpenWrt 上 ping 公网 IPv6 时,立即返回: ping: sendto: Network unreachable 最后发现,现场存在一条与 mwan3 一致的带标记不可达规则。删除它后,IPv6 恢复。这个案例说明:看到了默认路由,也不代表实际流量一定会使用它。 本文记录一次实际排查。公网源地址已替换为文档示例地址;设备名、规则优先级和 mark 应以自己的设备为准。卸载命令适用于使用 opkg 的 OpenWrt。 默认路由存在,为什么仍然不可达 最初排查时怀疑默认路由缺失,随后输出已经能看到带源地址条件的默认路由: default from 2001:db8:1234:5600::4 via fe80::1 dev eth1 proto static metric 512 pref medium default from 2001:db8:1234:5600::/64 via fe80::1 dev eth1 proto static metric 512 pref medium 排查中还临时补了一条普通默认路由: ip -6 route add default via fe80::1 dev eth1 metric 1024 但 ping 仍立即返回 Network unreachable。此时继续叠加默认路由已经没有帮助,需要检查实际选路和策略规则。 先确认上游网关可达 ping -6 -I eth1 -c 3 fe80::1 三次请求全部收到回复,说明 OpenWrt 到上游网关的链路本地通信正常。IPv6 使用 fe80:: 开头的链路本地地址作为下一跳是正常现象;这里指定设备,是为了确定该地址属于哪条链路。 ...

October 24, 2026 · 2 min

OpenList 夸克 WebDAV 上传内存过高:原因与优化

使用 rclone 将本地文件通过 OpenList 的 WebDAV 接口上传到夸克网盘时,OpenList 的内存占用可能明显增长,甚至触发容器 OOM。排查后发现,关键在于夸克驱动上传前的整文件缓存,以及容器统计中包含的文件页缓存。 本文分析针对 OpenList v4.2.7、普通夸克驱动、Docker 和 cgroup v2。其他驱动、其他版本应重新核对实现。 夸克上传为什么需要缓存 OpenList 的 WebDAV 入口把 HTTP 请求体包装成文件流,再交给目标存储驱动。这一步本身不统一将整个文件读入内存。 但普通夸克驱动会先取得文件的 MD5 和 SHA1。WebDAV 上传路径没有向文件对象提供这两个哈希,因此驱动调用: stream.CacheFullAndWriter(&up, io.MultiWriter(writers...)) 这个调用在计算哈希的同时,缓存完整文件。随后,驱动向夸克提交预上传和哈希请求;如果不能秒传,再从缓存中读取数据、分片上传。 哈希计算可以使用很小的内存,真正占空间的是为后续回读而保留的文件内容。 即使夸克支持分片上传,也不代表前面的整文件缓存不存在。 v4.2.7 的 HybridCache 有内存和文件两类后备方式。允许使用内存时,会尝试扩充缓存,分配受限后再切换至文件;其中部分内存通过匿名 mmap 管理。因此不能仅靠调整 Go GC 参数约束所有缓存占用。 rclone 的 --transfers 控制同时传输的文件数。两个文件并发上传,意味着两份整文件缓存可能同时存在。降低 rclone 自身的 --buffer-size 并不能直接限制 OpenList 进程中的这部分缓存。 为什么有临时目录仍占用内存 例如: "temp_dir": "data/temp" 这只指定临时文件保存位置,不强制每次缓存都写入磁盘。该相对路径还要结合 OpenList 的工作目录、Docker 挂载判断实际位置。 此外,v4.2.7 的缓存扩容检查使用系统可用内存统计,没有在该检查中直接读取容器的 memory.max 和 memory.current。这使得宿主机尚有空闲内存时,容器仍可能先撞上自己的内存限额。 改用磁盘临时文件 先暂停上传并备份配置,在 config.json 顶层设置: "min_free_memory": -1 这是字段片段,不是完整配置文件,修改时应保留其他内容和合法的 JSON 结构。 ...

October 24, 2026 · 2 min