从 1Password 迁移到 Vaultwarden

背景 1Password 不再有跨区订阅优惠,Family Annual ¥498/年 还是有些肉疼。同事们都推荐 Vaultwarden,正好有空闲的 VPS,干脆自建。 Vaultwarden 是 Bitwarden 服务端的 Rust 重写实现,协议完全兼容官方客户端(桌面 / 移动端 / 浏览器扩展),但资源占用极低,1C/1G 的小机器跑得很轻松。 前置准备 一台 Debian 12 VPS(1C/1G 起步即可,家用绰绰有余) 一个域名,例如 vault.example.com,在 DNS 服务商把 A 记录指向 VPS 公网 IP 一个 SMTP 邮箱(用于邀请家人、找回密码),推荐 Resend 环境初始化 apt update && apt upgrade -y && apt install -y curl ca-certificates timedatectl set-timezone Asia/Shanghai adduser evan usermod -aG sudo evan curl -fsSL https://get.docker.com | sh systemctl enable --now docker usermod -aG docker evan 部署 Vaultwarden + Caddy 切到普通用户,建立工作目录: ...

April 23, 2026 · 4 min · 643 words · Me, LLM

自建代理订阅管理

背景 挂着两三家机场 + 一台自建节点,每家命名规则不一样、节点重复、规则集要在每个客户端各贴一份。机场换链接、加节点、改分流,所有设备都要重订阅一轮。 要的是:所有原始订阅塞进一个聚合器,自动去重 / 改名 / 分组 / 套规则,输出一条稳定 URL,客户端只订阅这条。本文用 Sub-Store + subconverter + Docker Compose 实现。 架构与暴露策略 三层各暴露一个稳定 URL,上下游互不影响。链路单向:客户端 → subconverter 公网 URL → 容器内拉 Sub-Store → Sub-Store 拉机场。中间任一层挂掉只影响下次订阅刷新,已下载的配置继续可用。 机场订阅 · 自建节点 ↓ Sub-Store · 合并 / 去重 / 改名 / 过滤 / 分组 ↓ 纯节点订阅 subconverter (+ sub-web GUI) · 套 ACL4SSR · 转目标格式 ↓ 客户端 · Mihomo / Surge / sing-box 只有 subconverter 必须公网(客户端要拉订阅),其余关进 SSH 隧道: ...

December 23, 2025 · 5 min · 1033 words · Me, LLM

NGINX 启用 HTTP/3

简介 HTTP/2 解决了"多路复用、头部压缩、优先级"等 HTTP/1.x 的瓶颈,但仍受 TCP 先天限制。 HTTP/3 则把同样的语义搬到 QUIC。Quick UDP Internet Connections 是 Google 设计的一种基于 UDP 的多路复用安全传输层协议。标准化后,HTTP/3 = HTTP over QUIC。 层级 HTTP/2 HTTP/3 传输 TCP(必)+ TLS 1.2/1.3(多数场景) QUIC(UDP 之上)+ TLS 1.3(强制) 流(Stream) Mux 在 TCP 里的逻辑流 Mux 在 QUIC 原生流 头压缩 HPACK QPACK(避免队头阻塞) HTTP/2 浏览器要求必须跑在 TLS 之上(ALPN=“h2”)。栈变为 HTTP/2 → TLS → TCP → IP。 HTTP/3 使用 QUIC 替换 TCP,栈变为 HTTP/3 → QUIC(拥塞/重传)→ UDP → IP,加密集成在 QUIC(基于 TLS 1.3)。 Mux 即 multiplex,多路复用。 HTTP/2 必须顺序传输,而 HTTP/3 支持乱序。 如果沿用 HPACK,丢一个 UDP 包就会让所有流的头部解码卡住,因此 IETF 为 HTTP/3 设计了 QPACK 来"避开队头阻塞(Head-of-Line Blocking, HoL)"。 连接迁移:通过 Connection ID 识别会话,IP 或端口改变(如移动网络/Wi-Fi 切换)无需重新建立连接。 使用 HTTP/3 的网站: ...

June 27, 2025 · 2 min · 413 words · Me, LLM

在本地环境使用 HTTPS

公网环境使用 HTTPS 参考:使用 Certbot 获取 Let’s Encrypt 颁发的 TLS 证书 | ZYF.IM。 简介 HTTPS(HyperText Transfer Protocol Secure)是在 HTTP 之上通过 TLS/SSL 实现加密的安全通信协议,用来保护浏览器与服务器之间的数据机密性、完整性与身份可信性。 开始实验 mkcert 会在本地生成一套根 CA(包含根证书和私钥),并把根证书导入系统/浏览器的信任列表。随后,它用这套 CA 的私钥为 localhost 等域名签发服务器证书;因为根证书已被信任,浏览器访问时就会把服务器证书视为可信。 brew install mkcert mkcert -install mkcert localhost # The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅ # vi default.conf server { listen 443 ssl; server_name localhost; ssl_certificate /etc/ssl/certs/localhost.pem; ssl_certificate_key /etc/ssl/certs/localhost-key.pem; # 只允许 TLSv1.2 和 TLSv1.3 协议,显式禁止 TLSv1.0 和 TLSv1.1 协议 ssl_protocols TLSv1.2 TLSv1.3; # 只保留高强度、带身份验证、且不使用 MD5 的 TLS 1.2(及以下)套件 ssl_ciphers HIGH:!aNULL:!MD5; # 优先使用服务器端加密套件 ssl_prefer_server_ciphers on; location / { root /usr/share/nginx/html; index index.html index.htm; } } docker run -d --name nginx-ssl \ -p 8443:443 \ -v ./default.conf:/etc/nginx/conf.d/default.conf:ro \ -v ./localhost.pem:/etc/ssl/certs/localhost.pem:ro \ -v ./localhost-key.pem:/etc/ssl/certs/localhost-key.pem:ro \ nginx:alpine # docker rm -f nginx-ssl # docker container restart nginx-ssl 测试 浏览器 浏览器访问 https://localhost:8443/,如果证书是绿色的,说明成功了。 ...

June 26, 2025 · 4 min · 669 words · Me, LLM

MongoDB 高手课

04 特色及优势 维度 能力 数据模型 多形性(同集合不同字段)、动态性(在线改模式)、JSONSchema 治理 开发体验 单存储区读写、反范式 + 无关联优化、API 自然 高可用 Replica Set(2~50 节点,建议奇数)、自恢复、多中心容灾、滚动维护 横向扩展 无缝扩容、应用透明、多种数据分布策略,可达 TB-PB 06 基本操作 环境与样本数据: cloud.mongodb.com 云服务 样本数据 dump.tar.gz tar -xvf dump.tar.gz mongorestore --uri="mongodb://root:root@10.130.0.12/?&authMechanism=SCRAM-SHA-1" CRUD // 插入 db.fruit.insertOne({ name: "apple" }) db.fruit.insertMany([{ name: "apple" }, { name: "pear" }, { name: "orange" }]) // 查询 db.customers.find({ username: "fmiller", name: "Elizabeth Ray" }) db.customers.find({ username: /^f/ }) db.customers.find({ $or: [{ username: /^f/ }, { name: /^E/ }] }) // 投影(projection) db.customers.find({ username: /^f/ }, { name: 0, email: 0 }) // 排除 db.customers.find({ username: /^f/ }, { _id: 1, name: 1 }) // 仅返回 // 删除 db.customers.remove({ username: "abrown" }) // 更新 db.customers.updateOne({ username: "fmiller" }, { $set: { from: "China" } }) db.customers.updateMany({ username: "fmiller" }, { $set: { from: "China" } }) // 表 / 库管理 db.fruit.drop() show collections db.dropDatabase() show dbs SQL ↔ Mongo 操作符对照 SQL Mongo a <> 1 {a: {$ne: 1}} a > 1 / >= {a: {$gt: 1}} / {$gte: 1} a < 1 / <= {a: {$lt: 1}} / {$lte: 1} a = 1 OR b = 1 {$or: [{a: 1}, {b: 1}]} a IS NULL {a: {$exists: false}} a IN (1, 2, 3) {a: {$in: [1, 2, 3]}} 同时满足子文档条件 {$elemMatch: {city: "Rome", country: "USA"}} 常用更新操作符 操作 含义 $set / $unset 设置 / 移除字段 $push / $pop 数组追加 / 弹出 $pull / $pullAll 按匹配从数组中删除 $addToSet 不存在则添加,去重 08 聚合查询 Aggregation Framework: ...

April 19, 2023 · 7 min · 1471 words · Me, LLM

Kubernetes 入门实战 Part3

24 PersistentVolume 数据持久化 PersistentVolume 属于集群的系统资源,是和 Node 平级的一种对象,Pod 对它没有管理权,只有使用权。 StorageClass 它抽象了特定类型的存储系统(比如 Ceph、NFS),在 PVC 和 PV 之间充当“协调人”的角色,帮助 PVC 找到合适的 PV。 # vim host-path-pv-pvc.yml apiVersion: v1 kind: PersistentVolume metadata: # 只有 10MB 容量的存储设备 name: host-10m-pv spec: # kubectl explain PersistentVolume.spec.storageClassName storageClassName: host-vol # kubectl explain PersistentVolume.spec.accessModes accessModes: # ReadWriteOnce:存储卷可读可写,但只能被一个节点上的 Pod 挂载。 # ReadOnlyMany:存储卷只读不可写,可以被任意节点上的 Pod 多次挂载。 # ReadWriteMany:存储卷可读可写,也可以被任意节点上的 Pod 多次挂载。 - ReadWriteOnce capacity: # Ki/Mi/Gi storage: 10Mi hostPath: path: /tmp/host-10m-pv/ --- # PVC 不表示实际的存储,而是一个“申请”或者“声明” apiVersion: v1 kind: PersistentVolumeClaim metadata: name: host-5m-pvc spec: storageClassName: host-vol accessModes: - ReadWriteOnce resources: requests: storage: 5Mi mkdir /tmp/host-10m-pv kubectl apply -f host-path-pv-pvc.yml kubectl get pv # NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE # host-10m-pv 10Mi RWO Retain Bound default/host-5m-pvc host-vol 4s kubectl get pvc # NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE # host-5m-pvc Bound host-10m-pv 10Mi RWO host-vol 6s # vim host-pvc-pod.yml apiVersion: v1 kind: Pod metadata: name: host-pvc-pod spec: volumes: - name: host-pvc-vol persistentVolumeClaim: claimName: host-5m-pvc containers: - name: ngx-pvc-pod image: nginx:alpine ports: - containerPort: 80 volumeMounts: - name: host-pvc-vol mountPath: /tmp kubectl apply -f host-pvc-pod.yml kubectl get pod -o wide kubectl exec -it host-pvc-pod -- sh cd /tmp && touch a.md # check in worker node /tmp/host-10m-pv/ 25 NFS 网络共享存储 … ...

February 24, 2023 · 1 min · 205 words · Me

Kubernetes 入门实战 Part2

17 多节点的 Kubernetes 集群 在腾讯云 TencentOS Server 3.1 (TK4) 下测试: master SA3.MEDIUM4 2 核 4GB 5Mbps worker S5.SMALL2 1 核 2GB 1Mbps worker S5.SMALL2 1 核 2GB 1Mbps # 修改源 https://mirrors.cloud.tencent.com/ mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.tencent.com/repo/centos7_base.repo yum clean all yum makecache # install docker yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine yum install -y yum-utils yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl start docker docker -v docker run hello-world 一些准备工作: ...

February 22, 2023 · 13 min · 2610 words · Me

Kubernetes 入门实战 Part1

01 初识 Docker https://docs.docker.com/get-started/overview/ curl -fsSL https://get.docker.com | sudo sh # sudo usermod -aG docker $USER # newgrp docker dockerd-rootless-setuptool.sh install docker version docker info docker ps docker pull busybox # show all images docker images 02 被隔离的进程 # 拉取轻量级 Alpine Linux 镜像 docker pull alpine # 以交互模式运行容器并进入 shell docker run -it alpine sh # 查看容器内的操作系统信息 cat /etc/os-release Docker 实现资源隔离的三种核心技术: namespace:隔离进程、网络、文件系统等资源视图 cgroup:限制和监控资源使用(CPU、内存、磁盘 I/O 等) chroot/pivot_root:改变进程的根目录,实现文件系统隔离 03 容器化的应用 Build once, Run anywhere. ...

February 15, 2023 · 9 min · 1873 words · Me

Go 语言第一课

本文是 2023 年学习 Tony Bai《Go 语言第一课》的章节笔记整理,对应 Go 1.17 时代。2026 主流 Go 版本已到 1.22+,泛型(1.18)、go.work 工作区(1.18)、slog(1.21)、slices / maps 标准库(1.21)等新内容本文未覆盖,读到 module / vendor 等命令前请先看官方最新文档。 02 设计哲学 设计哲学之于编程语言,就好比一个人的价值观之于这个人的行为。 简单:Go 生产力的源泉。 显式:Go 希望开发人员 明确知道自己在做什么;显式的基于值比较的错误处理方案。 组合:类型嵌入 (Type Embedding)。 并发:面向多核、原生支持并发、用户层轻量级线程 goroutine。 面向工程:将解决工程问题作为 Go 的 设计原则之一,这些问题包括:程序构建慢、依赖管理失控、代码难于理 解、跨语言构建难等。 03 配好环境 https://go.dev/doc/devel/release https://golang.google.cn/dl/ 安装多个 Go 版本 # Go 1.17+ 安装 binary 用 go install(go get 已废弃) go install golang.org/dl/go1.21.5@latest go1.21.5 download go1.21.5 version 配置 Go go env go help environment 04 Go 程序的结构 import "fmt" 一行中 fmt 代表的是包的导入路径 (Import),它表示的是标准库下的 fmt 目录,整个 import 声明语句的含义是导入标准库 fmt 目录下的包 fmt.Println 函数调用一行中的 fmt 代表的则是包名。 通常导入路径的最后一个分段名与包名是相同的,这也很容易让人误解 import 声明语句中的 fmt 指的是包名,其实并不是这样的。 gofmt main.go Go module go mod init go mod tidy 05 Go 项目的布局标准 loccount 工具 ...

February 1, 2023 · 6 min · 1201 words · Me, LLM

MySQL 实战 45 讲

MySQL 实战 45 讲 | 林晓斌 01 | 基础架构:一条 SQL 查询语句是如何执行的? 请求自上而下经过 Server 层 → Engine 层。Server 层承担连接、解析、优化、执行,所有引擎共享;Engine 层负责数据存取,可插拔。 组件 职责 备注 连接器 建立 / 鉴权 / 维持连接 长短连接由客户端控制,服务端 wait_timeout 兜底 查询缓存 命中即直接返回 8.0 已移除;表一更新整张缓存失效,不建议用 分析器 词法 + 语法 + 预处理;列 / 表名校验在此发生 报 Unknown column 'k' in 'field list' 就在此 优化器 选索引、决定 join 顺序 执行器 鉴权后调引擎接口;返回结果集 引擎扫描行数 ≠ rows_examined(见 §05) 常用查询 SHOW PROCESSLIST; -- 当前连接 SELECT @@wait_timeout; -- 28800s = 8h SHOW VARIABLES LIKE 'wait_timeout'; SELECT @@query_cache_type; -- 8.0 之前可观察是否开启 清理连接占用的资源但保留连接:调接口函数 mysql_reset_connection(),不是 SQL 语句。 ...

August 14, 2022 · 5 min · 991 words · Me, LLM