Repository navigation
Expand file tree
/
Copy pathsearch.json
More file actions
1 lines (1 loc) · 71.9 KB
/
Copy pathsearch.json
File metadata and controls
1 lines (1 loc) · 71.9 KB
1
[{"categories":["记录"],"content":" 本文依赖的远程 k3s 集群、kubeconfig 和当时的服务器环境已经不存在,文中的操作无法直接复现,也不构成当前 k3s 集群管理指南。本文正文仅保留作历史参考。\n安装 kubectl\nmacOS 可通过 homebrew 安装:brew install kubernetes-cli 登录进入 k3s 集群的 master 节点所在的机器,并找到 /etc/rancher/k3s/k3s.yaml,这份文件就是 kubeconfig 了,跟本地的~/.kube/config是同一个东西,接下来可以直接替换掉本地的config,也可以把k3s.yaml里的server、context和user加进config,并把current-context改成k3s的context\n用kubectl cluster-info去验证能否正常使用\n","description":"\n","tags":["k3s","kubectl","kubernetes"],"title":"\n【已失效】管理远程k3s集群","uri":"/posts/%E7%AE%A1%E7%90%86%E8%BF%9C%E7%A8%8Bk3s%E9%9B%86%E7%BE%A4/"},{"categories":["记录"],"content":" 更新于 2026-10:GitLab 17 之后 runner 的注册方式改成了「认证令牌(runnerToken)」,旧的 registration token 已弃用;文档地址、values.yaml 的键名和 dind 镜像一并更新。\n参考资料:\nGitLab Runner Helm chart | GitLab Docs Use Docker-in-Docker | GitLab Docs Use Docker to build Docker images | GitLab Docs 安装helm\nmacOS下可通过homebrew安装 brew install helm 添加gitlab的chart库\nhelm repo add gitlab https://charts.gitlab.io helm repo update gitlab 创建并编辑values.yaml\n复制官方提供的示例文件:values.yaml · main · GitLab.org / charts / GitLab Runner\n至少要配上这几项:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 gitlabUrl: https://gitlab.example.com/ # 在 GitLab 的 项目/群组 → Settings → CI/CD → Runners → New project runner 里创建后拿到的认证令牌 runnerToken: \"glrt-xxxxxxxxxxxxxxxxxxxx\" rbac: create: true runners: tags: \"k3s\" config: | [[runners]] [runners.kubernetes] namespace = \"{{.Release.Namespace}}\" image = \"ubuntu:24.04\" privileged = true # 如果要想在runner里构建docker镜像,就要加入以下配置,因为docker的dind镜像自19.03开始就默认使用tls端口 [[runners.kubernetes.volumes.empty_dir]] name = \"docker-certs\" mount_path = \"/certs/client\" medium = \"Memory\" 注意 runnerToken 不要提交到仓库,用 --set 或者加密后的 Secret 注入。\n其他的配置项按需配置即可\n将gitlab runner部署到k3s\nhelm install --namespace {namespace} gitlab-runner -f {path to values.yaml} gitlab/gitlab-runner\n验证\nkubectl -n {namespace} get pods 看到 runner 的 pod 处于 Running,再到 GitLab 的 Runners 页面确认状态是绿色即可。\n额外提醒 假如要使用runner构建docker镜像,请在.gitlab-ci.yml里加入以下内容(镜像记得锁具体版本,用 latest 会随机炸):\n1 2 3 4 5 6 7 8 9 10 11 12 13 default: image: docker:28-cli services: - docker:28-dind variables: # dind 场景下要让 docker 客户端去连 service 容器里那个 daemon, 而不是默认的 /var/run/docker.sock DOCKER_HOST: tcp://docker:2376 # 证书目录, dind 从 19.03 起默认开启 TLS DOCKER_TLS_CERTDIR: \"/certs\" # Kubernetes executor 不会执行镜像的 entrypoint, 这两个变量要自己声明 DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: \"$DOCKER_TLS_CERTDIR/client\" k3s 侧还有两点:一是 runner 的 job pod 需要 privileged,k3s 默认不拦,这一点和标准 k8s 集群(默认 PodSecurity 会拦)不同;二是 k3s 自带 local-path 这个 storageClass,job 里要持久化缓存可以直接用。\n","description":"\n","tags":["gitlab runner","gitlab-ci","k3s","helm","gitlab","kubernetes"],"title":"\n将gitlab-runner部署到k3s集群中","uri":"/posts/%E5%B0%86gitlab-runner%E9%83%A8%E7%BD%B2%E5%88%B0k3s%E9%9B%86%E7%BE%A4%E4%B8%AD/"},{"categories":["记录"],"content":" 更新于 2026-10:这是一份「新机器从上电到能开发」的顺序清单,每个工具的详细说明在我的开发环境之Linux篇里。原文里失效的几条(get.daocloud.io 一键脚本、Linuxbrew 仓库、raw.github.com 域名)已经替换。\n以 Ubuntu 22.04 / 24.04 为例。\n1. 换成国内镜像源 清华、阿里云、中科大等机构都提供 Ubuntu 镜像源。\n22.04 及更早,源列表在 /etc/apt/sources.list:\n1 sudo sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g; s|http://security.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list 24.04 起改用 deb822 格式,源列表在 /etc/apt/sources.list.d/ubuntu.sources,同样的替换:\n1 sudo sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g; s|http://security.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/ubuntu.sources 改完更新索引:sudo apt update\n2. 创建 ssh 密钥 ssh-keygen -t ed25519 然后一路回车,公钥在 ~/.ssh/id_ed25519.pub,把它贴到需要的地方即可。\n3. 安装常用的工具 sudo apt install curl git vim zip autofs cifs-utils net-tools build-essential file -y\n4. 更新并升级系统内的组件和工具 sudo apt update \u0026\u0026 sudo apt upgrade -y \u0026\u0026 sudo apt autoremove -y \u0026\u0026 sudo apt autoclean -y\n5. oh-my-zsh 和 zsh sudo apt install zsh -y\nsh -c \"$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"(原文的 raw.github.com 已不推荐)\n装插件:\n1 2 git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions git clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 修改 .zshrc,把 zsh-autosuggestions 和 zsh-syntax-highlighting 加到 plugins 数组里\n6. docker 原文的一键脚本都不要再用了:\ncurl -sSL https://get.daocloud.io/docker | sh —— DaoCloud 的这个安装脚本服务早已停止(域名还能解析,但连不上) curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun —— 一键脚本官方只推荐用于测试环境,而且 --mirror Aliyun 指向的公共加速器在 2024 年已经关停 正式一点的装法(官方 apt 仓库 + keyring),步骤见我的开发环境之Linux篇;国内拉镜像的现状那里也一并写了。\n7. Homebrew(原 linuxbrew) 1 2 3 4 5 6 7 # 依赖 sudo apt install build-essential procps curl file git -y # 安装(Linuxbrew 的两个仓库都已归档,安装脚本从 Homebrew 官方仓库取) /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\" # 加入 PATH echo 'eval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\"' \u003e\u003e ~/.zshrc eval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\" 8. sdkman curl -s \"https://get.sdkman.io\" | bash,装完执行 source \"$HOME/.sdkman/bin/sdkman-init.sh\" 或新开一个终端。\n","description":"\n","tags":["linux","Ubuntu","apt","ssh","zsh","oh-my-zsh","docker","linuxbrew","sdkman"],"title":"\nUbuntu系统搭建开发环境","uri":"/posts/ubuntu%E7%B3%BB%E7%BB%9F%E6%90%AD%E5%BB%BA%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/"},{"categories":["记录"],"content":" 先查看当前速度: 鼠标双击阈值:defaults read -g com.apple.mouse.doubleClickThreshold 鼠标加速度(即本次我想要改的鼠标移动速度):defaults read -g com.apple.mouse.scaling 鼠标滚轮速度:defaults read -g com.apple.scrollwheel.scaling 修改对应的速度 defaults write -g com.apple.mouse.doubleClickThreshold 0.75 defaults write -g com.apple.mouse.scaling 11 defaults write -g com.apple.scrollwheel.scaling 0.75 ","description":"\n","tags":["macOS","鼠标","移动速度"],"title":"\nMacOS修改鼠标移速","uri":"/posts/macos%E4%BF%AE%E6%94%B9%E9%BC%A0%E6%A0%87%E7%A7%BB%E9%80%9F/"},{"categories":["记录"],"content":"温馨提示:需要安装cifs-utils\n参考链接:Ubuntu 18.04 开机自动挂载NAS\n临时挂载 1 sudo mount -t cifs -o user={username},password={password} //{NAS的主机名或IP}/{共享名} /mnt/nas/ 使用autofs进行自动挂载 安装autofs:sudo apt install autofs -y\n编辑/etc/auto.master,添加/mnt /etc/auto.misc 。前者表示远程目录被挂载的父目录,后者表示要被应用的挂载配置文件\n创建一个记录了账号密码的文件,内里要记录的内容为:\n1 2 username=xxx password=xxx 编辑/etc/auto.misc ,添加nas -fstype=cifs,credentials=/home/alex/credential.txt,uid=1000,gid=1000 ://{NAS的主机名或IP}/{共享名}(原文写的是 freenas.lan,FreeNAS 早就改名 TrueNAS 了,主机名按自己的实际填)\n执行systemctl enable autofs, systemctl restart autofs\n使用ll /mnt/nas去验证是否挂载成功\n","description":"\n","tags":["Ubuntu","cifs-utils","autofs","samba"],"title":"\nUbuntu挂载trueNAS共享的samba","uri":"/posts/ubuntu%E6%8C%82%E8%BD%BDtruenas%E5%85%B1%E4%BA%AB%E7%9A%84samba/"},{"categories":["记录"],"content":" 更新于 2026-10:原文写的是 Ubuntu 20.04,而 20.04 的标准支持已在 2025-05-31 结束;gateway4 这个键在新版 netplan 里也已弃用(会打印告警),本文改成官方推荐的 routes 写法,22.04 / 24.04 通用。\n普通用户执行命令时,请在命令前加上sudo\nnetplan 新版本ubuntu不再使用 etc/network/interfaces 配置本机IP和网关了,而是改用netplan 工具,网络配置文件位于/etc/netplan 文件夹中,格式为.yaml。\n文件名各版本不太一样:Server 安装器生成的一般是 00-installer-config.yaml,云镜像 / 自动安装生成的是 50-cloud-init.yaml,桌面版(23.10 之后)由 NetworkManager 管理、但后端同样是 netplan。如果名字不一致的话请查看文件内容是否相似,配置文件内容如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 network: version: 2 renderer: networkd ethernets: # 以太网卡名称 ens18: # 是否由dhcp服务器提供IP,true为是,false为否。为否时则需要配置静态IP dhcp4: false # 本机静态IP地址 addresses: - 192.168.3.5/24 # 所在局域网的网关。旧的 gateway4 / gateway6 键已弃用,改用 routes 声明默认路由 routes: - to: default via: 192.168.3.1 # DNS服务器 nameservers: addresses: - 192.168.3.1 ens0: dhcp4: true 如果目标机器是云镜像(配置来自 50-cloud-init.yaml),改之前得先禁用 cloud-init 的网络模块,不然重启后配置会被覆盖回去:\n1 echo 'network: {config: disabled}' | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg 生效与检查 先做语法检查,再试应用。netplan try 会在 120 秒内等你按回车确认,没确认就自动回滚,远程改机器的时候可以保命:\n1 2 sudo netplan generate sudo netplan try 确认无误后正式生效:\n1 sudo netplan apply 查看当前网络状态(netplan 0.106 之后提供):\n1 netplan status 验证 IP 和默认路由是否生效:\n1 2 ip a ip route 两点补充:gateway4 / gateway6 现在虽然还能用,但 netplan generate 时会打印弃用告警,建议尽早迁到上面的 routes 写法;netplan 只管网卡和路由,DNS 是写给 systemd-resolved 的,如果 DNS 不生效,可以先用 resolvectl status 看解析器实际拿到的 DNS 是什么。\n","description":"\n","tags":["netplan","Ubuntu","IP","网关","DNS"],"title":"\nUbuntu修改本机IP与网关(netplan)","uri":"/posts/ubuntu-20.04tls%E4%BF%AE%E6%94%B9%E6%9C%AC%E6%9C%BAip%E4%B8%8E%E7%BD%91%E5%85%B3/"},{"categories":["记录"],"content":"参考链接:\n恩山论坛教程\nHomeLede项目主页\n云端编译homelede在内的lede系统(P3TERX的教程)\n修改路由IP(HomeLede wiki)\n补记:原文的参考链接里第3、5条是同一个地址(P3TERX 教程),第4条那篇 CSDN 文章已经 404,这里合并去重了。\n编译 方案一:自己编译 参照项目README.md给出的教程一路往下走,但在第七步配置软件包的时候,在target images选项中找到rootfs并勾选上tar.gz 再往下走就能得到自己需要的PVE的容器模板 编译后的固件在当前目录的子目录./bin/targets/x86/64 里,我们所需要的容器模板的文件叫openwrt-x86-64-generic-rootfs.tar.gz 方案二:云编译(通过GitHub的Actions功能编译) 我已在我的仓库配置好了,不想再动手操作一遍的话可以直接点进去下载最新的workflow编译好的固件 —— 那个个人仓库已经删掉了,链接失效;要用云编译请直接 fork HomeLede 官方仓库,按参考链接3的教程配置 Actions。\n参考参考链接3(当时因为 openethervpn5 的编译有问题,整个 HomeLede 都受影响,建议编译前先看一眼仓库最近的 issue 和 commit;这个项目现在仍在更新。原文在这里分享过我编译好的 CT 模板,那个 Google Drive 分享已经失效,需要同款模板的话按下面步骤自己编一个即可) 因为本身默认的配置并不会包含打包LXC所以要的容器模板,所以需要修改配置以打包出容器模板 参考 HomeLede 仓库里的 .config(我原来放在个人仓库里的那份已经删了),改成自己需要的配置 参考教程中的SSH 连接到 Actions 小节 安装 上传模板到PVE\n因为webUI创建会迷之失败,所以接下来需要通过终端创建\n创建CT容器 pct create {容器的ID} local:vztmpl/{模板名称} --rootfs local-lvm:{分配的系统盘大小} --ostype unmanaged --hostname {容器内外显示的主机名} --arch {系统架构} --cores {线程数} --memory {内存大小,单位是MB} --swap {交换分区大小,单位是MB} -{网络id} bridge={桥接网络},name={网络名称} 将上方命令中必填项按自身需要修改即可,如: pct create 201 local:vztmpl/openwrt-x86-64-generic-rootfs.tar.gz --rootfs local-lvm:1 --ostype unmanaged --hostname homelede --arch amd64 --cores 2 --memory 4096 --swap 512 -net0 bridge=vmbr0,name=eth0\n编辑容器的相关读写权限 将以下内容追加到/etc/pve/lxc/{容器ID}.conf ,如我的即为/etc/pve/lxc/201.conf (注意,以下内容里也有地方要填写容器ID )\nlxc.mount.auto: cgroup:rw lxc.mount.auto: proc:rw lxc.mount.auto: sys:rw lxc.include: /usr/share/lxc/config/openwrt.common.conf lxc.cap.drop: sys_admin lxc.apparmor.profile: unconfined lxc.cgroup.devices.allow: c 108:0 rwm lxc.autodev: 1 lxc.cgroup.devices.allow: c 10:200 rwm lxc.hook.autodev: /var/lib/lxc/{容器id}/device_hook.sh lxc.mount.entry: tmp tmp tmpfs rw,nodev,relatime,mode=1777 0 0 如:\nlxc.mount.auto: cgroup:rw lxc.mount.auto: proc:rw lxc.mount.auto: sys:rw lxc.include: /usr/share/lxc/config/openwrt.common.conf lxc.cap.drop: sys_admin lxc.apparmor.profile: unconfined lxc.cgroup.devices.allow: c 108:0 rwm lxc.autodev: 1 lxc.cgroup.devices.allow: c 10:200 rwm lxc.hook.autodev: /var/lib/lxc/201/device_hook.sh lxc.mount.entry: tmp tmp tmpfs rw,nodev,relatime,mode=1777 0 0 在PVE的webUI上启动openwrt,并在容器内执行mv /sbin/modprobe /sbin/mde\n如果启动失败,请检查 /var/lib/lxc/{容器 ID}/device_hook.sh 是否存在,如果不存在的话,请创建该文件,并写入以下内容:\n1 2 3 mknod /${LXC_ROOTFS_MOUNT}/dev/ppp c 108 0 mkdir -p ${LXC_ROOTFS_MOUNT}/dev/net mknod /${LXC_ROOTFS_MOUNT}/dev/net/tun c 10 200 参考这里修改IP和DNS\n设置为旁路由 进入homelede,默认用户为root,默认密码为password\n去网络-接口,修改lan口\n设置ipv4网关 的值为主路由IP, 如我的是192.168.3.1 DHCP-高级设置里勾选强制 ,DHCP选项 的值设置为6,{homelede的IP} 如我的设置:6,192.168.3.100 如果没有使用ipv6的需求的话就关掉ipv6,因为有的 OpenWrt 版本有 BUG,IPv6 可能影响到无线 AP 或者 DNS 去网络-防火墙-常规设置里取消启用 SYN-flood 防御的勾选\n重启homlede\n找一台设备将网关设置为homelede的IP测试网络访问是否正常\n进入主路由关闭主路由的DHCP功能并重启主路由\n局域网内同一网段的设备重启以更新DHCP服务器为homelede\n","description":"\n","tags":["PVE","CT容器","软路由","homelede"],"title":"\nPVE创建CT容器兼HomeLede尝鲜","uri":"/posts/pve%E6%90%AD%E5%BB%BA%E9%83%A8%E7%BD%B2ct%E5%AE%B9%E5%99%A8%E5%85%BC%E8%BD%AF%E8%B7%AF%E7%94%B1%E5%B0%9D%E9%B2%9C/"},{"categories":["homelab"],"content":" 安装apcupsd\napt install apcupsd -y 配置apcupsd\n编辑 /etc/apcupsd/apcupsd.conf\n配置通信方式\nUPSCABLE usb #usb表示通过USB端口连接 UPSTYPE usb #usb表示通过USB端口通信 DEVICE #留空表示让APCUPSD自行获取UPS串口 配置为断电一定时间后就关机\nTIMEOUT 0 #当值为0时,表示不设置该属性;当值为非零正数N时,表示切换到UPS电池供电N秒后就会通知主机关机 配置为可用电量或可用时间达到指定额度时关机\nBATTERYLEVEL 5 #表示当可用电量为5%时,通知主机关机 MINUTES 3 #表示当UPS电池的可用时间为3分钟时,通知主机关机 TIMEOUT其值非零时,它与BATTERYLEVEL和MINUTES,这仨任意满足一个时就会关机\n编辑 /etc/default/apcupsd\n1 2 3 4 # Defaults for apcupsd initscript (unused with systemd as init). # Set to \"yes\" to enable startup of apcupsd. ISCONFIGURED=yes APCACCESS=/sbin/apcaccess 启动该服务且允许开机自启动\nsystemctl enable apcupsd \u0026\u0026 systemctl restart apcupsd\n测试\n执行 apcaccess status 后有类似如下信息则表示安装配置成功:\n1 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 [root@pve]~❯❯❯ apcaccess status APC : 001,036,0865 DATE : 2021-03-17 00:14:16 +0800 HOSTNAME : pve VERSION : 3.14.14 (31 May 2016) debian UPSNAME : ups CABLE : USB Cable DRIVER : USB UPS Driver UPSMODE : Stand Alone STARTTIME: 2021-03-16 23:51:50 +0800 MODEL : BK650M2-CH STATUS : ONBATT LINEV : 243.0 Volts LOADPCT : 19.0 Percent BCHARGE : 100.0 Percent TIMELEFT : 24.0 Minutes MBATTCHG : 10 Percent MINTIMEL : 5 Minutes MAXTIME : 0 Seconds SENSE : Low LOTRANS : 160.0 Volts HITRANS : 278.0 Volts ALARMDEL : 30 Seconds BATTV : 13.5 Volts LASTXFER : Automatic or explicit self test NUMXFERS : 1 XONBATT : 2021-03-17 00:10:06 +0800 TONBATT : 255 Seconds CUMONBATT: 255 Seconds XOFFBATT : N/A SELFTEST : OK STATFLAG : 0x05060010 SERIALNO : 9B2015A09122 BATTDATE : 2001-01-01 NOMINV : 220 Volts NOMBATTV : 12.0 Volts NOMPOWER : 390 Watts END APC : 2021-03-17 00:14:21 +0800 ","description":"\n","tags":["NAS","APCUPSD","断电关机","电源管理","PVE"],"title":"\n为PVE配置APCUPSD断电后自动关机","uri":"/posts/%E4%B8%BAnas%E9%85%8D%E7%BD%AEapcupsd%E6%96%AD%E7%94%B5%E5%90%8E%E8%87%AA%E5%8A%A8%E5%85%B3%E6%9C%BA/"},{"categories":["小技巧"],"content":" 本文列出的 Docker 公共镜像加速器已陆续停服或仅限特定网络环境使用,不能再按原配置直接使用。本文正文仅保留作历史参考。\n废话不多说,直接把我本地的 daemon.json 亮出来:\n1 2 3 4 5 6 7 8 9 10 11 12 { \"debug\": true, \"experimental\": false, \"registry-mirrors\": [ \"https://mirror.ccs.tencentyun.com\", \"https://registry.docker-cn.com\", \"https://dockerhub.azk8s.cn\", \"https://docker.mirrors.ustc.edu.cn\", \"https://reg-mirror.qiniu.com\", \"https://hub-mirror.c.163.com\" ] } 这些都是免登录的,可以直接用,感谢大厂们的免费提供。\n还要感谢这篇文章的作者, 这些代理站都是从这篇文章里筛选出来的。\n","description":"\n","tags":["docker","代理","加速","docker for desktop"],"title":"\n【已失效】分享一些免费的Docker代理","uri":"/posts/%E5%88%86%E4%BA%AB%E4%B8%80%E4%BA%9B%E5%85%8D%E8%B4%B9%E7%9A%84docker%E4%BB%A3%E7%90%86/"},{"categories":["我的开发环境"],"content":" 更新于 2026-10:原文写于 2021 年,其中 Linuxbrew、apt-key、docker-compose v1 这几处已经失效(Linuxbrew 的两个仓库都已归档、apt-key 已弃用、Compose v1 于 2023-07 停止支持),本次一并更新,示例基于 Ubuntu 22.04 / 24.04。\n提前说明一下,对于Linux系统,我一向是倾向于用Ubuntu,所以以下的安装都是基于Ubuntu。Ubuntu 目前最新的 LTS 是 24.04(20.04 的标准支持已在 2025-05-31 结束),22.04 / 24.04 都适用下面的步骤。即使我在家用的是macOS,但介绍的工具在macOS上也能用。\n基本的应用 一般新机器/系统到手的时候,我都会执行以下这条命令以方便后面的使用:\nsudo apt update \u0026\u0026 sudo apt upgrade -y \u0026\u0026 sudo apt install curl git vim -y\nzsh 当初刚接触Linux的时候, 就在网上找资料的时候被安利上了, 配合oh-my-zsh的zsh-syntax-highlighting和zsh-autosuggestions这两个插件是真的好用。\nzsh本体 安装zsh\nsudo apt install zsh -y\n切换到zsh\nsudo chsh -s \"$(which zsh)\"\n执行完上述两步后,需要退出当前终端甚至是重启机器才能应用zsh。我为了这篇文章装了个Ubuntu Desktop测试安装步骤时发现,有时候哪怕重启了N多遍也没用,这种时候可以不用管,往下走安装oh-my-zsh,让oh-my-zsh老大哥来管……\noh-my-zsh 安装本体\nsh -c \"$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"\n原文用的是 raw.github.com 这个域名,现在已经不推荐了,换成 raw.githubusercontent.com(国内网络下这两个域名都不好访问,建议挂代理)。\n安装完成后,会问是否默认使用zsh,填 y 并回车,然后重启机器再打开终端,你就用上zsh了,且oh-my-zsh已经配置好默认配置了。\n安装插件\nzsh-autosuggestions\n1 git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions 本插件的作用是根据输入自动建议符合输入内容的输入过的命令。\nzsh-syntax-highlighting\n1 git clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 本插件的作用是如果你输入的工具名是存在的,那么该名字会以绿色高亮显示,否则为红色高亮。\n原文的 git://github.com/... 协议 GitHub 早已不支持,改用 https://。\n安装好插件后,记得要去用户根目录的 .zshrc 里修改plugins数组,plugins数组默认有一个git插件,这里再额外加上上面两个插件的名字就行了:\n1 plugins=(git zsh-autosuggestions zsh-syntax-highlighting extract) 保存修改后可通过执行 source ~/.zshrc 在当前终端应用本次修改(原文写成了 source ~./zshrc,是个笔误)。\nextract\n顺带推荐一下这个插件,这个是oh-my-zsh自带的插件,用途是解压压缩包或存档文件,直接把这个名字写到plugins数组就可以(上面那行已经加上了)。\nHomebrew(原 Linuxbrew) 这个工具说是macOS下必备的开发工具应该不算夸张,在 Linux 上它的存在算是对 apt 的补完和拓展,没了它依旧可以正常开发,但有了它你的开发体验会更顺畅。\n「Linuxbrew」这个名字已经废弃了:Linuxbrew/install 和 Linuxbrew/brew 两个仓库都已经归档(分别停更于 2020 和 2019),现在统一叫 Homebrew on Linux,安装脚本从 Homebrew 官方仓库取。\nTips1:因为该工具在安装其它工具时其实本质是拉取发行版二进制并自动安装、或拉取源码到本地自动编译,这其中下载速度一般等同于从GitHub拉取源码,所以嫌慢的话,建议开代理。\nTips2:官方给出的 macOS 和 Linux 安装脚本是同一个,脚本内会自己做判断。\n安装(先把依赖装好:sudo apt install build-essential procps curl file git -y)\n/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n安装时因为会要用到 sudo , 所以要输一次密码;然后会再问一次是否确定要继续安装,按回车则继续,按其它则取消安装。如果可以的话建议走代理,因为拢共几百兆的东西要克隆/下载。\n添加到path\nLinux 上 Homebrew 的安装前缀固定在 /home/linuxbrew/.linuxbrew,安装完成后脚本会直接提示要执行的那行命令:\n1 2 echo 'eval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\"' \u003e\u003e ~/.zshrc eval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\" 比如我的是zsh,那么我把这句话添加到.zshrc里,以后打开终端就可以正常使用 brew 命令了;装完可以跑一次 brew doctor 自检。\nsdkman 安装、管理jdk版本的好工具,当然它也支持maven和gradle~~,不过这两个我装了就没动过版本了~~。主要还是用这个来管理、切换jdk版本。\n安装\ncurl -s \"https://get.sdkman.io\" | bash\n(建议执行)应用到当前终端\nsource \"$HOME/.sdkman/bin/sdkman-init.sh\"\n这一步不执行也没关系,但要关闭当前终端,然后新开一个终端,也能直接使用 sdk 命令。\ndocker docker在macOS和Windows上有docker for desktop,且自带 compose,故唯有Linux需要手动执行以下的安装步骤。\ndocker与compose 移除系统自带的旧版本/冲突包\nsudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)\n添加 Docker 的官方 GPG 密钥\n原文用的是 apt-key add,这个命令在 Debian 12 / Ubuntu 24.04 已经弃用,现在改成 keyring 文件 + signed-by 的方式:\n1 2 3 4 5 sudo apt update sudo apt install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc 添加apt仓库。Ubuntu 24.04 起 apt 支持 deb822 格式,下面这种写法 22.04 和 24.04 都能用:\n1 2 3 4 5 6 7 8 9 10 sudo tee /etc/apt/sources.list.d/docker.sources \u003c\u003cEOF Types: deb URIs: https://download.docker.com/linux/ubuntu Suites: $(. /etc/os-release \u0026\u0026 echo \"${UBUNTU_CODENAME:-$VERSION_CODENAME}\") Components: stable Architectures: $(dpkg --print-architecture) Signed-By: /etc/apt/keyrings/docker.asc EOF sudo apt update 安装docker(compose 现在是插件,跟着一起装)\nsudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y\n验证\n1 2 sudo docker run hello-world docker compose version 完工。\n不过有个提醒,普通用户安装docker后,需要前置 sudo 来调用 docker 命令,比如 docker ps 这句命令,直接执行是会提示permission denied的,要加上sudo, sudo docker ps 这样才能执行成功。如果你不介意当前用户获得root权限的话,可以使用usermod -aG docker {username}来将当前用户加入到docker组,这样执行docker命令的时候就无需前置sudo了(注意:docker 组的权限等价于 root,只在个人机器上这么干)。\n关于 docker-compose 原文那套「下载 docker-compose 1.25.4 二进制放到 /usr/local/bin」的做法已经作废:Compose v1(Python 版)在 2023-07 就停止支持了,现在的命令是 docker compose(子命令形式,由 docker-compose-plugin 提供),写法上把原来的 docker-compose up -d 换成 docker compose up -d 即可。另外 compose 文件顶层的 version: 键也已废弃,写了会告警并被忽略,直接删掉即可。\n国内拉镜像 再补一句国内网络的现状:以前往 /etc/docker/daemon.json 里塞一长串公共加速器(registry.docker-cn.com、reg-mirror.qiniu.com、hub-mirror.c.163.com、docker.mirrors.ustc.edu.cn 之类)的做法已经失效——2024 年年中开始,这些公共 Docker Hub 镜像加速服务相继关停,其中 registry.docker-cn.com、reg-mirror.qiniu.com 是直接停止服务,dockerhub.azk8s.cn 转为内部使用,USTC 的也已在 2024-06-06 关闭。现在还行的路子是:\n给 dockerd 配 HTTP 代理(写 /etc/systemd/system/docker.service.d/http-proxy.conf),让拉取走代理 用云服务器所在厂商的内网镜像(只有该厂商的机器能用) 自建 pull-through cache 本博客里那篇《分享一些免费的Docker代理》正是因为这件事整篇作废了。\n","description":"\n","tags":["开发环境","zsh","oh-my-zsh","linuxbrew","homebrew","sdkman","docker","docker-compose","Ubuntu"],"title":"\n我的开发环境之Linux篇","uri":"/posts/%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E4%B9%8Blinux%E7%AF%87/"},{"categories":["小技巧"],"content":"先说一下环境:\n1 2 ~ uname -a Linux vmi237400.contaboserver.net 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u4 (2019-07-19) x86_64 GNU/Linux 这是我在contabo上买的一个VPS, 我在上面跑的OS是Debian.\n前两天用docker-compose部署sonarqube的时候, 发现sonarqube一直在重启, 然后我用sudo docker logs sonarqube去看的时候发现, 是里面的es一直跑不起来, 提示要我把vm.max_map_count这个东西调整为262144以上, 然后我查了下资料, 可以在宿主机上跑了sudo sysctl -w vm.max_map_count=262144后, sonarqube就可以正常启动了, 不过这个只是临时有效, 如果机器重启后还是会再次无法启动. 而持久性修改的办法则是到/etc/systctl.conf中修改vm.max_map_count的值为262144, 如果在文件中找不到的话, 可以把这个属性加上. 图省事的话可以用echo \"vm.max_map_count=262144\" \u003e /etc/sysctl.conf. 改完之后重启系统就可以了.\n","description":"\n","tags":["sonarqube","docker-compose","docker","Linux"],"title":"\n最近在VPS上部署sonarqube踩了个坑","uri":"/posts/%E6%9C%80%E8%BF%91%E5%9C%A8vps%E4%B8%8A%E9%83%A8%E7%BD%B2sonarqube%E8%B8%A9%E4%BA%86%E4%B8%AA%E5%9D%91/"},{"categories":["记录"],"content":" 本文使用 Traefik v2.0.4 及旧版 lego DNSPod 集成,相关版本和配置方式已经过时,文中的 DNSPod 令牌流程不能直接用于当前 Traefik;配套图片资源也已失效。本文正文仅保留作历史参考。\nDNSPOD 登录官网 在控制台中打开安全设置 点击密钥管理 点击创建密钥 把密钥信息(id和token)保存下来(包括但不限于截图、复制到文本文件等手段, 随你喜欢)\n把id和token组合而成的login token填入到traefik的环境变量中\n1 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 version: '3' networks: traefik: services: traefik: # The official v2.0 Traefik docker image image: traefik:v2.0.4 restart: always container_name: traefik networks: - traefik ports: # The HTTP port - \"80:80\" # The Web UI - \"8080:8080\" - \"443:443\" expose: - 8080 environment: # DNSPOD - DNSPOD_API_KEY=xxxxx,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx volumes: # docker - \"/var/run/docker.sock:/var/run/docker.sock:ro\" # config - \"./traefik.yml:/etc/traefik/traefik.yml\" - \"./dynamic.yml:/etc/traefik/dynamic.d/dynamic.yml\" # log - \"./log:/data/traefik/log/\" # https - \"./ca/:/data/traefik/ca/\" 这一步我要说一下, 理论上来说, 这样应该是可以的了, 因为我用curl测试的话是可以访问的\n1 2 3 curl -X POST https://dnsapi.cn/Domain.List -d 'login_token=xxxxx,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\u0026format=json' {\"status\":{\"code\":\"1\",\"message\":\"Action completed successful\",\"created_at\":\"2019-11-24 22:58:30\"},\"info\":{\"domain_total\":1,\"all_total\":1,\"mine_total\":\"1\",\"share_total\":\"0\",\"vip_total\":\"0\",\"ismark_total\":\"0\",\"pause_total\":\"0\",\"error_total\":\"0\",\"lock_total\":\"0\",\"spam_total\":\"0\",\"vip_expire\":0,\"share_out_total\":0},\"domains\":[{\"id\":64856337,\"status\":\"enable\",\"grade\":\"DP_Free\",\"group_id\":\"1\",\"searchengine_push\":\"yes\",\"is_mark\":\"no\",\"ttl\":\"600\",\"cname_speedup\":\"disable\",\"remark\":\"\",\"created_on\":\"2018-03-09 18:06:05\",\"updated_on\":\"2018-03-10 14:16:52\",\"punycode\":\"alexc.cn\",\"ext_status\":\"\",\"src_flag\":\"QCLOUD\",\"name\":\"alexc.cn\",\"grade_title\":\"\\u65b0\\u514d\\u8d39\\u5957\\u9910\",\"is_vip\":\"no\",\"owner\":\"qcloud_uin_894057821@qcloud.com\",\"records\":\"13\"}]}% 而且我翻过源码, 发现traefik的ACME是引用了lego实现的, 而lego则是引用了dnspod-go来实现对dnspod的相关API操作, 而且我也跑过一下这个的源码, 是可以解析的, 但就是在traefik上不行, 会报无法解析/解析错误之类的错, 而我在考虑到后面会用CLOUDFLARE的DNS来解析我的域名, 我也就没深究下去了. 如果有人愿意研究一下的话, 可以看看是什么情况.\nCLOUDFLARE 注意: 这里需要你在CLOUDFLARE里已经有一个可用的域名\n登录官网 进入profile 点击API Tokens 点击Create Token, 并选择Start with a template这个radio button 选择Edit DNS Zone这个模板 为这个token选择要应用的目标域名 然后点下一步、再点下一步,就会出现你要的token 将这个用于DNS的token填入环境变量中的API token 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 version: '3' networks: traefik: services: traefik: # The official v2.0 Traefik docker image image: traefik:v2.0.4 restart: always container_name: traefik networks: - traefik ports: # The HTTP port - \"80:80\" # The Web UI - \"8080:8080\" - \"443:443\" expose: - 8080 environment: # CLOUDFLARE - CF_API_EMAIL=alexcdever@gmail.com - CF_API_KEY=xxxxxxxxxxxxxxxx - CF_DNS_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx volumes: # docker - \"/var/run/docker.sock:/var/run/docker.sock:ro\" # config - \"./traefik.yml:/etc/traefik/traefik.yml\" - \"./dynamic.yml:/etc/traefik/dynamic.d/dynamic.yml\" # log - \"./log:/data/traefik/log/\" # https - \"./ca/:/data/traefik/ca/\" 再点击一下这里回到token管理页 点击这里你就可以看到CF_API_KEY这个环境变量对应的key了 ","description":"\n","tags":["traefik","dnspod","cloudflare","dns","token","ca","ssl"],"title":"\n【已失效】在DNS服务商申请token给traefik用来申请证书","uri":"/posts/%E5%9C%A8dns%E6%9C%8D%E5%8A%A1%E5%95%86%E7%94%B3%E8%AF%B7token%E7%BB%99traefik%E7%94%A8%E6%9D%A5%E7%94%B3%E8%AF%B7%E8%AF%81%E4%B9%A6/"},{"categories":["记录"],"content":" 更新于 2026-10:全文示例已升级到 Traefik v3(当前 v3.7)。Traefik v2 全系已于 2026-02-01 停止支持,网上还在流传的 v2.0.x 配置不要再直接照抄。\n详细介绍就不多说了, 大家可以去官网看官方的介绍, 总而言之就是一个配置起来比较方便的网关, 起码我是这样认为的.\n通过docker-compose部署 traefik支持docker部署和二进制文件部署, 为了方便和“不污染”系统环境, 我选择前者, 用的是docker-compose的方式.\n目录结构 ├── ca │ └── acme.json ├── docker-compose.yml ├── dynamic │ └── dynamic.yml ├── log │ ├── access.log │ └── traefik.log └── traefik.yml 我是在服务器上用户home目录里建了个叫traefik的文件夹存放这些文件, 其中ca和log这两个目录是为了将证书数据和日志做持久化, 而dynamic目录下的dynamic.yml和traefik.yml是要载入到容器中使用的配置文件.\ndocker-compose.yml 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 services: traefik: image: traefik:v3.7 restart: always container_name: traefik networks: - traefik ports: # The HTTP port - \"80:80\" # The HTTPS port - \"443:443\" # The Dashboard Web UI - \"8080:8080\" environment: # DNS Challenge 需要的服务商凭据, 建议通过 .env 文件注入, 不要写进仓库 - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} volumes: # docker - \"/var/run/docker.sock:/var/run/docker.sock:ro\" # config - \"./traefik.yml:/etc/traefik/traefik.yml:ro\" # 动态配置挂目录而不是单个文件, 原因见下文“几个坑” - \"./dynamic:/etc/traefik/dynamic:ro\" # log - \"./log:/data/traefik/log/\" # https - \"./ca/:/data/traefik/ca/\" # sync the time - \"/etc/localtime:/etc/localtime:ro\" blog: image: alexcdever/blog:last restart: always container_name: blog networks: - traefik volumes: # sync the time - \"/etc/localtime:/etc/localtime:ro\" networks: traefik: 这个docker-compose配置里目前定义了两个服务, 一个是traefik, 另一个是我的博客, 博客可以不用管, traefik那里要注意的是, 8080端口一定要绑定到宿主机.\n另外两点:\nCompose v2 之后顶层 version: 键已废弃(写了会告警并被忽略), 所以这里不再写 version: '3' traefik 不需要 links, 同一个 network 里的容器直接用服务名互访 环境变量那里配置的是用于ACME的DNS Challenge而要用到的DNS服务商的授权认证信息, 服务商清单和对应的环境变量名见官方文档.\ntraefik.yml 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 global: checkNewVersion: true sendAnonymousUsage: false entryPoints: web: address: :80 websecure: address: :443 providers: # filename和directory这两个配置项只能二选一, 官方推荐用directory file: directory: /etc/traefik/dynamic # 这个是表示要实时监听文件的变更 watch: true docker: # 这个是表示要实时监听宿主机上的docker daemon中其它容器 watch: true endpoint: unix:///var/run/docker.sock # 我设置这个为false是因为我选择的是通过动态配置文件去管理其它服务, 而不是docker label, # 这里设置为false的话dashboard那边就不会显示docker生成的router之类的信息了 exposedByDefault: false api: # 下面这两个是用来开启dashboard的, insecure表示监听在默认的 :8080 上 # 生产环境请加上认证, 或者只在内网暴露这个端口 insecure: true dashboard: true # 开启debug模式 debug: true # 这里记录的是traefik本身的日志 log: filePath: \"/data/traefik/log/traefik.log\" level: DEBUG format: json # 这里记录的是来自外部的请求 accessLog: filePath: \"/data/traefik/log/access.log\" format: json bufferingSize: 100 # 设置https证书 # traefik本身有三种配置证书的方式, 分别是tls Challenge、web Challenge和DNS Challenge, 其中只有DNS Challenge支持泛域名证书 certificatesResolvers: # DNS Challenge需要告知DNS服务商的代号 cf: acme: email: your-mail@example.com storage: /data/traefik/ca/acme.json dnsChallenge: provider: cloudflare 在traefik v3中, 这种只能在应用启动时加载的配置被称为静态配置(install configuration).\n因为我这个traefik.yml挂载到的/etc/traefik这个路径下是traefik默认会检查的一个目录, 所以容器在跑起来的时候会应用这个配置.\ndynamic/dynamic.yml 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 http: routers: blog-http: # 拦截http中的请求 entryPoints: - web # 判断请求的目的地的域名是否符合以下两者之一 rule: \"(Host(`blog.alexc.cn`) || Host(`www.alexc.cn`))\" # 将符合条件的请求重定向到https协议 middlewares: - redirect-to-https blog-https: entryPoints: - websecure rule: \"(Host(`blog.alexc.cn`) || Host(`www.alexc.cn`))\" # 将符合路由规则的请求发到blog服务 service: blog # 开启证书验证, 使用静态配置中名为cf的解析器 tls: certResolver: cf domains: - main: \"alexc.cn\" sans: - \"*.alexc.cn\" dashboard-https: entryPoints: - websecure rule: \"(Host(`traefik.alexc.cn`))\" # 这个表示dashboard的服务所在 service: api@internal tls: certResolver: cf domains: - main: \"alexc.cn\" sans: - \"traefik.alexc.cn\" middlewares: # 用于重定向到https的中间件 redirect-to-https: redirectScheme: permanent: true port: 443 scheme: https services: blog: loadBalancer: servers: - url: http://blog 在traefik v3中, 这种无须重启应用就能实时应用的配置被称为动态配置.\n另一条路: 用容器标签管理路由 比起把服务写进 dynamic.yml, 更省事的做法是在 compose 里直接给容器打标签, 让 docker provider 自动生成路由:\n1 2 3 4 5 6 7 8 9 10 11 services: blog: image: alexcdever/blog:last labels: - traefik.enable=true - traefik.http.routers.blog.rule=(Host(`blog.alexc.cn`) || Host(`www.alexc.cn`)) - traefik.http.routers.blog.entrypoints=websecure - traefik.http.routers.blog.tls.certresolver=cf - traefik.http.services.blog.loadbalancer.server.port=80 networks: - traefik 两种方式可以混用, 但不要给同一个服务定义同名的 router, 否则后加载的会覆盖先加载的.\n几个坑 acme.json 的权限必须是 600, 否则 traefik 会报 permissions 0644 for acme.json are too open, please use 600 并拒绝启动:\n1 touch ca/acme.json \u0026\u0026 chmod 600 ca/acme.json 动态配置要挂目录而不是单个文件: 宿主侧重命名/替换文件会断开 bind mount, 容器里就看不到变更了.\nDNSPod 用户的坑: traefik 的 ACME 是用 lego 实现的, 而 lego 已经在 v5.2.2 里移除了 dnspod provider, 现在要用 tencentcloud(腾讯云), 或者把域名 DNS 托管到 Cloudflare 用 cloudflare.\ndocker.sock 尽量只读挂载(:ro), 想进一步收紧可以用 docker-socket-proxy. 放开 docker API 基本等于把宿主机交出去, 官方文档也反复强调这一点.\nv2 升级到 v3 的破坏性改动很小: 静态配置有个别选项调整, 动态配置的路由语法兼容 v2 写法(也可以在静态配置里用 core.defaultRuleSyntax: v2 全局切换), 细节见官方 v2 到 v3 迁移指南.\n总结 因为2.0版本是一次大更新, 所以配置方式上跟1.x相差甚远, 且网上中文资料也少, 加上官方文档那奇怪的结构, 摸索起来时真的难受, 不过用起来还是比nginx好点, 跟docker结合地比较好, 写配置也方便简单. 从 v2 到 v3 反倒平缓得多, 照着迁移指南走一遍就行.\n","description":"\n","tags":["traefik","docker","docker-compose","note","nginx"],"title":"\n使用traefik代替nginx","uri":"/posts/%E4%BD%BF%E7%94%A8traefik%E4%BB%A3%E6%9B%BFnginx/"},{"categories":["记录"],"content":" 本文针对旧版 Docker for Mac 的设置界面,相关界面和配置入口已经变化;文中的外部图片资源也已失效,不能按原步骤直接操作。本文正文仅保留作历史参考。\n打开设置 点击打开Proxies选项页, 选中Manual proxy configuration,填入{本机的局域网IP}:{http代理所监听的端口} 备注: 如果IP地址填写的是127.0.0.1, 0.0.0.0, localhost 这种地址的话, 代理无效 完成\n","description":"\n","tags":["docker","Docker for Mac","Mac","proxy","代理"],"title":"\n【已失效】设置docker for Mac的代理","uri":"/posts/%E8%AE%BE%E7%BD%AEdocker-for-mac%E7%9A%84%E4%BB%A3%E7%90%86/"},{"categories":["归纳总结"],"content":"指针 当声明了一个指针变量, 并将一个变量的指针地址赋值给该指针变量, 那么该变量的值可以通过给指针变量加星号获取, 如: 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 package main import \"fmt\" func main() { // 声明了一个名为i的int类型的变量, 并赋值为10 var i int i = 10 // 声明了一个名为point的[int类型的指针]类型的变量, 并赋值为变量i的内存地址 var point *int point = \u0026i fmt.Printf(\"i的值为: %d, *point的值为: %d \\n\", i, *point) assertTheTwoVariablesAreEqual(i, *point) } func assertTheTwoVariablesAreEqual(varA, varB interface{}) { varAValue, varAIsInt := varA.(int) varBValue, VarBIsInt := varB.(int) if varAIsInt == VarBIsInt \u0026\u0026 varAValue == varBValue { fmt.Print(\"i即是*point\") } } 所以, * 为取值符, 用于获取指针变量所指向的内存地址上的值; \u0026 为取址符, 用于获取变量 (包括指针变量) 的内存地址\nPS: 星号+指针变量名=内存地址上的值, 星号+类型/结构体=[类型/结构体的指针]类型\n严格意义上来说, go的传参方式只有一种, 那就是 值传递 , 但在编码过程中, 会出现两种写法, 变量传递 和 指针传递 . 两者的区别在于, 前者在程序实际运行中, 在传值的时候会在新的内存地址上复制参数, 并把这个参数的新的副本传入函数中, 这样的话函数内的变量副本无论发生什么改变, 都与函数外的变量无关; 后者的话则是复制了变量的内存地址并把复制出来的\u001c新内存地址\u001c传入了函数中, 一旦在函数中值发生了改变则在函数外值也会改变. 测试 普通测试用例\n文件名以 _test.go 结尾\n普通测试用例(函数名)以 Test 开头, 需要传入唯一参数 t *testing.T\n一般情况下go不保证测试用例会按顺序执行, 所以需要使编写一个空的测试用例, 并在用例内部使用t.Run函数按顺序调用其它测试用例. 建议使用这种方法的情况下, 其他的测试用例建议不遵循普通测试用例的命名标准, 这样可以避免每个测试用例都执行2\n遍.\n性能测试用例\n性能测试需要使用-bench 参数, 如 go test -bench=. 即表示执行测试用例时的同时执行所有性能测试用例 性能测试用例中的唯一入参是b *testing.B 性能测试用例需要以Benchmark开头 其它 fmt.Println() 函数使用%v作为格式化输出, 所以打印内存地址请使用fmt.Printf()搭配%p使用 ","description":"\n","tags":["go","golang","note","knowleage","要点"],"title":"\nGolang笔记","uri":"/posts/golang%E7%AC%94%E8%AE%B0/"},{"categories":["小技巧"],"content":" 本文针对 nginx 已经移除的 ssl on; 配置指令,原文解决方案和外部参考链接均已过时,不能作为当前 nginx 配置指南。本文正文仅保留作历史参考。\n如果网站出现了如下报错: “400 Bad Request: The plain HTTP request was sent to HTTPS port”,那么原因多半是因为在做http重定向到https的配置里将 ssl 设置了为 on , 解决办法就是将该属性设置为 off 或者注释掉该属性就可以了.\n参考资料 : https://www.centos.bz/2018/01/nginx%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3the-plain-http-request-was-sent-to-https-port%E9%94%99%E8%AF%AF/\n","description":"\n","tags":["http","https",400,"nginx"],"title":"\n【已失效】在保持http和https都可用的情况下避免nginx出现400的情况","uri":"/posts/%E5%9C%A8%E4%BF%9D%E6%8C%81http%E5%92%8Chttps%E9%83%BD%E5%8F%AF%E7%94%A8%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E9%81%BF%E5%85%8Dnginx%E5%87%BA%E7%8E%B0400%E7%9A%84%E6%83%85%E5%86%B5/"},{"categories":["小技巧"],"content":"一句话就可以了:\n1 apt install locales-all -y ","description":"\n","tags":["Debian","language","Linux","env"],"title":"\n在Debian里启用全语言支持","uri":"/posts/%E5%9C%A8debian%E9%87%8C%E5%90%AF%E7%94%A8%E5%85%A8%E8%AF%AD%E8%A8%80%E6%94%AF%E6%8C%81/"},{"categories":["记录"],"content":" 本文使用的 docker-compose v1 命令和旧版 Nexus 部署说明已经过时,配套的外部图片资源也已失效,不能按原文直接部署。本文正文仅保留作历史参考。\n安装nexus 这个很简单,我安利一下我的一个github项目,我在里面存了一些可以通过docker-compose部署的应用的docker-compose脚本。\n你可以使用终端进入docker-compose.yml文件所在的目录,直接执行docker-compose up -d就可以了,然后你就可以通过docker logs nexus -f来看到实时的安装日志输出,只要里面有类似于 nexus start 的字样出现,就代表着安装成功了。\n另外单独提醒一下nexus默认的初始管理员账密是admin和admin123。\n配置nexus 当部署好nexus只有我建议大家第一步先把这个勾去掉:\n这样的意思是禁止匿名用户访问(包括下载)nexus,这个匿名用户其实就是游客的意思。\n然后的话我建议是修改管理员密码,并新建一个属于自己的账号:\n再然后,如果不想从中央仓库那么远下载第三方jar包,而是想走国内的镜像节点的话,那么可以如下操作:\n首先是创建一个proxy类型的仓库: 填写一个唯一的名字:\n建议选版本管理策略选mixed:\n把从网上找到的阿里云maven仓库地址填到如图位置:\n然后其余的配置不需要变动,可以直接点创建按钮了\n创建后打开maven-public仓库的配置页:\n然后进行如下操作:\n点击保存,就完成配置了\n接入nexus 从nexus下载 找到maven目录下的conf目录里的settings.xml文件,并打开编辑\n在servers标签里加入以下表示公司仓库的server标签:\n1 2 3 4 5 6 7 8 \u003cserver\u003e \u003c!--id表示可以随意自定义的名称,但必须要唯一--\u003e \u003cid\u003ecompony\u003c/id\u003e \u003c!--访问该仓库是用于验证授权的登录名--\u003e \u003cusername\u003eadmin\u003c/username\u003e \u003c!--访问该仓库是用于验证授权的登录密码--\u003e \u003cpassword\u003eadmin123\u003c/password\u003e \u003c/server\u003e 在mirrors里添加mirror标签:\n1 2 3 4 5 6 7 8 9 10 \u003cmirror\u003e \u003c!--这里的id必须与server里的id一致--\u003e \u003cid\u003ecompony\u003c/id\u003e \u003c!--主要起到一个描述左右--\u003e \u003cname\u003eprivate nexus repo\u003c/name\u003e \u003c!--仓库的url--\u003e \u003curl\u003ehttp://localhost:8081/repository/maven-public/\u003c/url\u003e \u003c!--这里的*号表示对任意远程仓库的访问都会被拦截并重定向到本镜像配置里的url--\u003e \u003cmirrorOf\u003e*\u003c/mirrorOf\u003e \u003c/mirror\u003e 上传到nexus 网页手动上传 该方法适合用于上传一些无法通过中央仓库下载的jar包说是购买自商业公司有版权限制的jar包:\n选择目标仓库\n填写资料\n完成\n通过maven上传 项目级别 修改项目的pom.xml, 在顶级\u003cproject\u003e 下新增一下配置:\n1 2 3 4 5 6 7 8 9 10 11 12 13 \u003cdistributionManagement\u003e \u003csnapshotRepository\u003e \u003cid\u003ecompony\u003c/id\u003e \u003cname\u003eSnapshot\u003c/name\u003e \u003curl\u003ehttp://localhost:8081/repository/maven-snapshots/\u003c/url\u003e \u003cuniqueVersion\u003etrue\u003c/uniqueVersion\u003e \u003c/snapshotRepository\u003e \u003crepository\u003e \u003cid\u003ecompony\u003c/id\u003e \u003cname\u003eRelease\u003c/name\u003e \u003curl\u003ehttp://localhost:8081/repository/maven-releases/\u003c/url\u003e \u003c/repository\u003e \u003c/distributionManagement\u003e 上面这种配置方式,id必须要与settings.xml中的server的id一致\n用户级别 在settings.xml中的\u003cprofiles\u003e标签里新增一个\u003cprofile\u003e标签,snapshot仓库和release仓库设置在其中:\n1 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 \u003cprofiles\u003e \u003cprofile\u003e \u003cid\u003edefaultProfile\u003c/id\u003e \u003crepositories\u003e \u003crepository\u003e \u003cid\u003emaven-releases\u003c/id\u003e \u003cname\u003eUser Project Release\u003c/name\u003e \u003curl\u003ehttp://localhost:8081/repository/maven-releases/\u003c/url\u003e \u003csnapshots\u003e \u003cenabled\u003efalse\u003c/enabled\u003e \u003c/snapshots\u003e \u003creleases\u003e \u003cenabled\u003etrue\u003c/enabled\u003e \u003c/releases\u003e \u003c/repository\u003e \u003crepository\u003e \u003cid\u003emaven-snapshots\u003c/id\u003e \u003cname\u003eUser Project Snapshot\u003c/name\u003e \u003curl\u003ehttp://localhost:8081/repository/maven-snapshots/\u003c/url\u003e \u003csnapshots\u003e \u003cenabled\u003etrue\u003c/enabled\u003e \u003cupdatePolicy\u003ealways\u003c/updatePolicy\u003e \u003c/snapshots\u003e \u003c/repository\u003e \u003c/repositories\u003e \u003c/profile\u003e \u003c/profiles\u003e ","description":"\n","tags":["nexus","maven","repository","jar","docker","docker-compose"],"title":"\n【已失效】搭建并使用nexus","uri":"/posts/%E6%90%AD%E5%BB%BA%E5%B9%B6%E4%BD%BF%E7%94%A8nexus/"},{"categories":["记录"],"content":" 更新于 2026-10:GitHub Pages 的后台和 DNS 要求这些年都变过(原文依赖的几张截图所在图床也已失效),本文重写为当前流程。\n需要事先具备的东西:\n域名 部署在github page的博客 1.配置域名解析 以「根域名 + www 子域」为例,两条记录都要加:\n场景 记录类型 记录名 记录值 根域名(example.com) A @ 185.199.108.153、185.199.109.153、185.199.110.153、185.199.111.153(四条都加) 根域名(example.com) AAAA @ 2606:50c0:8000::153、2606:50c0:8001::153、2606:50c0:8002::153、2606:50c0:8003::153(可选,IPv6 普及度还不高,建议保留 A 记录) 子域名(www.example.com) CNAME www USERNAME.github.io(组织站是 ORG.github.io) 要点:\nCNAME 的值只能是 \u003cuser\u003e.github.io,不要带上仓库名(写成 user.github.io/repo 是错的)\n如果 DNS 服务商支持 ALIAS / ANAME 记录,可以直接把根域名指向 user.github.io,省得维护四条 A 记录\n加完可以用 dig 验证一下:\n1 dig www.example.com +nostats +nocomments +nocmd 2.修改仓库配置 进仓库的 Settings → Pages,在 Custom domain 里填你要绑定的域名,然后点 Save。\n不需要自己手工新建 CNAME 文件:在设置里填好域名后,GitHub 会把这个域名写进发布分支的 CNAME 文件并代为维护(用 GitHub Actions 发布时,自定义域名保存在仓库设置里,也不必自己维护 CNAME 文件)。\n3.等证书、勾上 Enforce HTTPS 域名保存后 GitHub 会去签发 Let's Encrypt 证书,在签发完成之前 Enforce HTTPS 是灰的,等待时间从几分钟到几小时(官方文档给的上限是 24 小时) 如果一直签不下来,多半是 DNS 记录还没生效或记录类型不对,Pages 设置页会给出提示 证书签发完成后勾上 Enforce HTTPS,这样 http 访问会自动跳转到 https 4.完成 这样就完成了,自此以后就可以通过自定义域名访问github page了。我这次操作下来是立刻生效,但我见到网上有的人要半个小时才生效,域名解析和证书签发都可能有延迟,操作完不生效的话可以先放一段时间再看。\n","description":"\n","tags":["Github Pages","自定义域名","域名","domain","custom domain"],"title":"\n使用自定义域名绑定到GitHub-Page","uri":"/posts/%E4%BD%BF%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9F%9F%E5%90%8D%E7%BB%91%E5%AE%9A%E5%88%B0github-page/"},{"categories":["小技巧"],"content":"暂停追踪指定文件或目录 git update-index --assume-unchanged {目标文件的相对路径或绝对路径}\n恢复追踪指定文件或目录 git update-index --no-assume-unchanged {目标文件的相对路径或绝对路径}\n","description":"\n","tags":["git","file","文件","版本","追踪","index"],"title":"\n使git暂停追踪指定文件或目录","uri":"/posts/%E4%BD%BFgit%E6%9A%82%E5%81%9C%E8%BF%BD%E8%B8%AA%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6%E6%88%96%E7%9B%AE%E5%BD%95/"},{"categories":["归纳总结"],"content":"dockerfile 基本知识点 镜像的构建顺序按照dockerfile里的指令顺序来构建。 docker镜像是由多层叠加的. 当通过dockerfile构建镜像时,每执行一句就叠加一层,最底层则是基础镜像,即第一个 from 指令所指定的镜像\ndocker的容器即是在镜像之上加上一个可以读写的临时层, 可以认为是在镜像上构建了一个沙箱环境.\n镜像的构建过程中的删除动作只在所在的指令语句的那一层中起作用。比如有两句RUN指令:前一个是安装了某个软件或添加了每个文件,即执行了对镜像来说增大体积的操作;后一个则是卸载这个软件的下载缓存或删除对应的目标文件,既执行了对镜像来说的减少体积的操作。那么,镜像真的会减去这一部分的体积吗?不,并不会,在docker镜像构建过程中,它是一层一层往上叠的,也就是说,新的层会叠加在旧镜像层之上,所以,在旧的层里加进镜像里的东西,哪怕在后面的层执行了删除操作也并不会真正地在镜像里消失,依旧会存留在镜像某些层内。所以要缩减镜像体积的话,首先要选一个符合要求的、最小的基础镜像,然后构建过程中每一次安装软件都要注意在同一个RUN操作中同时执行清除缓存等操作。\ndocker的规范规定,dockerfile的文件名默认是dockerfile,docker和file这两个单词的首字母可以不区分大小写。如果你非要将docker的构建文件命名为其他名字 (如aaa) , 那么要跑这个构建文件的话就要加上路径, 如: 当我想要以root用户的身份构建在/root 里的名为aaa的dockerfile的镜像构建文件,那么可以执行\n1 2 cd /root docker build -f aaa 或\ndocker build -f ~/aaa .\n镜像名称的具体命名方式为: [ip/domain]/[project]/image:version , 只是因为一般来说我们用的都是docker hub上的公共镜像, 所以我们并不需要在镜像名里加上域名. 如果我们要执行的是私有镜像, 那么这个镜像名就必定会加上域名或者IP地址, 举个例子:\n假如我有一个私有的docker仓库放在了registry.alexc.cn 上, 并且有一个叫 hero 的项目, 项目里的第一个镜像叫 king , 镜像的版本号是 0.0.1 , 那么我要启动这个镜像的话, 命令就是这样写的:\ndocker run --rm -p 8080:8080 registry.alexc.cn/hero/king:0.0.1\nPS: 有些仓库可能设置了访问权限, 需要先登录才能拉取下来或是更新上去\n指令参数的作用 FROM:dockerfile文件的第一行必须是该关键字,用于指定dockerfile所构建的镜像的基础镜像是什么,该参数以镜像名称作为值, 如 FROM nginx:latest RUN:该参数表示在构建过程中需要执行的bash命令, 如 RUN: uname -a LABEL:用于自定义镜像的元数据,如LABEL author=\"AlexC\" 记录了author为AlexC ARG:定义了本构建镜像文件在构建时的变量。如ARG a=1,那么如果我在后面的指令中有用到变量a的值的地方的话,我只需要使用美元符+变量名,即$a就可以了,如WORKDIR /root/$a,这里的意思就是工作目录设定在WORKDIR/root/1。 COPY:用于复制外部文件进镜像。对外部文件支持相对路径和绝对路径。使用格式为COPY {原文件路径}+空格+{目标文件路径},如COPY ROOT.war /home的意思就是把与dockerfile同级的ROOT.war放进镜像内部的/home目录下。 dockerfile示例 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 # 本镜像的基础镜像 FROM tomcat:8-slim # 记录维护者联系方式到镜像的元数据 LABEL maintainer=\"alexcdever@gmail.com\" # 设置工作目录 WORKDIR /root # 定义构建变量,以下变量只在构建镜像过程中起作用,不会写入到镜像中的操作系统里 ARG tomcat=\"/usr/local/tomcat\" ARG web=\"${tomcat}/webapps\" ARG log=\"${tomcat}/logs\" ARG workspace=\"/home/ProjectWorkspace\" # 表示以root用户操作镜像内的系统 USER root # 执行更新系统的操作 RUN apt update -y \\ \u0026\u0026 apt upgrade -y # 安装软件 RUN apt install -y imagemagick RUN rm -rf ${web}/* # 复制与dockerfile文件在同一目录下的一个叫index.html的文件到镜像内的root目录下 COPY ROOT.rar /root/ RUN mkdir ${web}/ROOT \\ \u0026\u0026 unzip /root/ROOT.war -d ${web}/ROOT/ docker-compose 基本知识点 docker-compose是一个简单的docker镜像编排工具,其配置文件名称一般默认为为docker-compose.yml,docker-compose将会根据该配置文件里的设置构建出单个或多个docker容器以及其他和容器相关的东西并按照配置项将不同容器联系起来。 配置项 用过yml做配置文件的应该都知道.yml文件的写法其实和json的格式是类似的,都是键值对。在docker-compose的配置文件里有两大配置项是必要的,他们分别是service和VERSION。\nVERSION:原文写的是「用于指定docker-compose执行编排时使用的API版本,写法是version: \"3\"」。注意:这个顶层 version: 键在 Compose v2 已经废弃,写了会告警并被忽略,现在直接删掉即可,compose 文件从顶层 services: 开始写;另外独立的 docker-compose 命令(Compose v1)已于 2023-07 停止支持,现在的命令是 docker compose(子命令形式)。 services:按我的了解,对于docker来说,一个容器相当于一个服务,所以在services下的都是服务。每一个容器都需要指定一个镜像用于生成容器。 NETWORK:表示网段,其下的二级配置项表示不同的隔离网络,每个网络可以使用driver属性定义网络的连接模式。模式有三种,分别是桥接模式bridge、宿主模式host和容器模式container [container name]。 VOLUMES:表示数据卷,其下二级配置项表示不同的数据卷。当声明一个空数据卷时(即只有一个数据卷名字且不存在任何属性),该数据卷会根据docker自身的缺省值在/var/lib/docker/volumes/{hash值}/_data(这个路径是我在Mac OS 10.11.6里查到的,不保证其他版本和其他系统也是这个路径)里存放被挂载映射的数据。 docker-compose.yml示例 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 # 声明docker-compose执行编排时使用的api版本 version: '3' networks: # 声明了一个名字叫app的隔离网络,该网络的连接模式为桥接模式 app: driver: bridge volumes: # 声明了一个名字叫db的数据卷,且不做设置,即一切设置都是用docker的缺省值 db: services: # 定义了一个,名字叫mysql的服务 mysql: # 声明该服务所使用的镜像是来自于docker hub的mysql:latest镜像 image: mysql # 声明本次启动的基于mysql:latest镜像的容器的名字为mysql container_name: mysql # 为容器提权,避免容器在启动时遇到权限不足导致启动失败的情况 privileged: true # 表示该容器会随着宿主机的重启而重启 restart: always # 表示对外暴露的端口,这里是要将容器内的3306端口映射到宿主机的3306端口,冒号左边是宿主机的端口,右边是容器内的端口 ports: - \"3306:3306\" # 这里表示本容器的网络使用的是名字为app的网段 networks: - app # 这里表示向其它同样在相同网段内的其他容器暴露自己的3306端口,其他容器可以通过3306端口访问本容器的3306端口 expose: - \"3306\" # 这里表示将容器内的/var/lib/mysql目录与名为db的数据卷映射 volumes: - \"db:/var/lib/mysql\" # 这里表示本service依赖于一个叫abc的服务。在docker-compose中,service的启动顺序越是被其它service所依赖,那么这个service的启动优先级越高,但docker-compose的启动并不是阻塞同步的,而是只是排好启动顺序后按顺序发送启动指令,所以当一个叫“甲”的服务启动时间长而未启动完成时,依赖于“甲”的服务“乙”需要调用“甲”时,“乙就会报错”。所以请注意这一点。 depends_on: - \"abc\" ","description":"\n","tags":["docker","dockerfile","docker-compose"],"title":"\n总结这几天使用dockerfile和docker-compose的经验","uri":"/posts/%E6%80%BB%E7%BB%93%E8%BF%99%E5%87%A0%E5%A4%A9%E4%BD%BF%E7%94%A8dockerfile%E5%92%8Cdocker-compose%E7%9A%84%E7%BB%8F%E9%AA%8C/"},{"categories":["记录","黑苹果"],"content":" 本文通过修改特定旧版 macOS 的系统二进制文件实现显示输出,补丁字节和代码签名方式均绑定旧版本,不能直接用于当前 macOS 或其他硬件。本文正文仅保留作历史参考。\n只需要打开自带的terminal或其它命令行工具,执行一下两句命令,再重启就可以了。\n1 sudo perl -i.bak -pe '$before = qr\"\\x0F\\x85\\x92\\x03\\x00\\x00\"s;s/$before/\\xE9\\x78\\x03\\x00\\x00\\x90/g' /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit 1 sudo codesign -f -s - /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit ","description":"\n","tags":["Mac","黑苹果","2K分辨率"],"title":"\n【已失效】使黑苹果突破限制输出2K分辨率画面到显示器","uri":"/posts/%E4%BD%BF%E9%BB%91%E8%8B%B9%E6%9E%9C%E7%AA%81%E7%A0%B4%E9%99%90%E5%88%B6%E8%BE%93%E5%87%BA2k%E5%88%86%E8%BE%A8%E7%8E%87%E7%94%BB%E9%9D%A2%E5%88%B0%E6%98%BE%E7%A4%BA%E5%99%A8/"},{"categories":["记录"],"content":" 更新于 2026-10:acme.sh 现已到 3.1.x,默认 CA 从 Let's Encrypt 换成了 ZeroSSL,证书也不建议再从 ~/.acme.sh/ 里直接引用,改用 --install-cert 安装;nginx 侧的 ssl on; 指令在 1.25.1 已被移除,本文的 nginx 配置一并更新。\n使用acme.sh申请CA证书 前情提要:我的服务器系统用的是Debian,并装有nginx。\n安装acme.sh 下载脚本并安装(安装时会自动往 crontab 里写一条定时任务,用来续签):\n1 curl https://get.acme.sh | sh -s email=your-mail@example.com 脚本会被安装到 ~/.acme.sh/,同时会在 shell 配置里加一行 alias,新开一个终端就可以直接用 acme.sh 命令;想手动加也行:\n1 alias acme.sh=~/.acme.sh/acme.sh 选定CA(3.0 起默认是 ZeroSSL,会要求注册邮箱;想继续用 Let's Encrypt 就显式切过去):\n1 acme.sh --set-default-ca --server letsencrypt 生成证书 关闭nginx或其他占用80端口的应用或服务,nginx可以这样操作(standalone 模式要独占 80 端口,不想停服务可以改用 --nginx 模式或 --dns 模式):\n1 nginx -s stop 生成证书:\n1 acme.sh --issue -d www.example.com --standalone 要泛域名证书就得走 DNS 模式,以 Cloudflare 为例:\n1 2 3 export CF_Token=\"xxxxxxxxxxxxxxxxxxxx\" export CF_Email=\"your-mail@example.com\" acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf 把证书安装到固定位置。不要直接让 nginx 去读 ~/.acme.sh/ 里的文件,那是 acme.sh 的内部目录,续签后路径和文件名都可能变:\n1 2 3 4 acme.sh --install-cert -d www.example.com \\ --key-file /etc/nginx/ssl/example.com.key \\ --fullchain-file /etc/nginx/ssl/example.com.fullchain.pem \\ --reloadcmd \"nginx -s reload\" --reloadcmd 会在每次自动续签后执行,这样 nginx 用的始终是最新证书。\n证书生成了三种:普通证书、中级证书和完整链条证书,nginx 的 ssl_certificate 要放完整链条证书(fullchain)。\n把证书的路径配置到nginx里(这里是我主域名,即www域名的配置):\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 server { listen 80; listen [::]:80; server_name www.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; http2 on; # nginx 1.25.1 起用这个指令替代 listen ... http2 server_name www.example.com; ssl_certificate /etc/nginx/ssl/example.com.fullchain.pem; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_session_timeout 5m; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; root /home/git/hexo; index index.html; return 301 https://blog.alexc.cn; } 注意别再写 ssl on;:这个指令从 nginx 1.15 起弃用、1.25.1 起被移除,写上会直接启动失败。加密套件也不用再自己拼一长串,TLSv1.2 TLSv1.3 配 ssl_prefer_server_ciphers off 就是目前的推荐做法。\n检查配置并重载nginx:\n1 nginx -t \u0026\u0026 nginx -s reload 使acme.sh自动升级 作者原话:\n目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.\n1 acme.sh --upgrade --auto-upgrade 续签靠安装时写入的 cron 定时任务(默认每天检查一次,可以用 crontab -l 看到),证书到期前 30 天会自动续期,续期后由 --install-cert 注册的 --reloadcmd 负责让 nginx 加载新证书。\n","description":"\n","tags":["CA","https","acme.sh","ssl","nginx"],"title":"\n使用acme.sh部署CA证书","uri":"/posts/%E4%BD%BF%E7%94%A8acme.sh%E9%83%A8%E7%BD%B2ca%E8%AF%81%E4%B9%A6/"},{"categories":["记录"],"content":"在前公司的时候公司里有个项目因为要做微信小程序,我负责其中的后端开发。一般来说微信开发的后端开发主要都要做鉴权验证,我为了偷点懒就上github找了一下,就发现了本文要讲的这个jar包。\n传送门\nPS0:这个库早年叫 weixin-java-tools、挂在 Wechat-Group 组织下,后来作者把仓库迁到了自己账号下并改名为 WxJava,老地址会 301 跳过去,但建议直接用新地址。\n 使用的第一步,理所当然的是要导包,我用的是gradle,所以我在build.gradle文件里的依赖区内这样写:\n1 2 3 4 5 6 7 //微信开发工具 //小程序 implementation \"com.github.binarywang:weixin-java-miniapp:${WX_TOOL_VERSION}\" //公众号 implementation \"com.github.binarywang:weixin-java-mp:${WX_TOOL_VERSION}\" //开放平台 implementation \"com.github.binarywang:weixin-java-open:${WX_TOOL_VERSION}\" PS1:maven引用请参照github说明。原文用的是 gradle 的 compile 配置,它在 Gradle 7.0 已被移除,现在要写 implementation。\nPS2:我引入了三个包是因为这个项目并不仅仅只是小程序,还有其他微信相关的需求要实现,所以如果你只是要做小程序的后端项目的话,只引入小程序的包就足够了。\n接下来的第二部步并不是直接写代码,而是要配置参数项,如下:\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 #微信 wechat: #小程序 miniapp: #APPID appid: appid #secret secret: secret #token token: token #aesKey aesKey: aesKey #数据格式 msgDataFormat: JSON 写入从微信公众平台获取到的对应的数据后,再写一个配置类读取以上配置:\n1 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 @Data @ConfigurationProperties(prefix = \"wechat.miniapp\") public class WxPrgConfig { /** * 设置微信小程序的appid */ private String appid; /** * 设置微信小程序的Secret */ private String secret; /** * 设置微信小程序的token */ private String token; /** * 设置微信小程序的EncodingAESKey */ private String aesKey; /** * 消息格式,XML或者JSON */ private String msgDataFormat; } PS:我这里使用了Lombok,所以没有getter和setter。\n再然后把这里的配置写入到bean中,载入到spring中:\n1 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 @Configuration @ConditionalOnClass(WxMaService.class) @EnableConfigurationProperties(WxPrgConfig.class) public class WxConfig { @Autowired private WxPrgConfig properties; @Bean @ConditionalOnMissingBean public WxMaConfig maConfig() { WxMaInMemoryConfig config = new WxMaInMemoryConfig(); config.setAppid(this.properties.getAppid()); config.setSecret(this.properties.getSecret()); config.setToken(this.properties.getToken()); config.setAesKey(this.properties.getAesKey()); config.setMsgDataFormat(this.properties.getMsgDataFormat()); return config; } @Bean @ConditionalOnMissingBean public WxMaService wxMaService(WxMaConfig maConfig) { WxMaService service = new WxMaServiceImpl(); service.setWxMaConfig(maConfig); return service; } PS:工具类的作者有写小程序的demo,那里的配置更全面。传送门\n做完以上三个步骤就OK了,剩下的就是在你需要使用这个工具的地方注入WxMaService,再通过它就可以获取用户的微信信息了。\n","description":"\n","tags":["微信开发","代码库","wechat","lib","Spring Boot"],"title":"\n使用第三方代码库接入微信","uri":"/posts/%E4%BD%BF%E7%94%A8%E7%AC%AC%E4%B8%89%E6%96%B9%E4%BB%A3%E7%A0%81%E5%BA%93%E6%8E%A5%E5%85%A5%E5%BE%AE%E4%BF%A1/"},{"categories":["记录"],"content":" 本文使用的是旧式自建 Git 服务器和本机回环地址示例,缺少当前服务器端部署、认证和权限配置,不能按原文直接用于实际发布。本文正文仅保留作历史参考。\n首先,在本地和服务器各有一个git仓库,服务器的git仓库最好是空仓库,即只有.git文件夹的目录。\n然后在本地仓库目录下执行添加远程仓库的操作: 1 2 3 4 5 6 7 # 添加的远程仓库地址有两种写法,分别对应两种传输协议,下面两种写法的意思都是一样的,IP地址为127.0.0.1的服务器上的/home/git/repo目录作为远程仓库,其中ssh的写法指定了以git用户的账号进行操作。在这其中127.0.0.1对应的是IP地址或域名,而IP地址后面的冒号后面的则是仓库的绝对路径 # 这是http协议的写法,添加后通过这种写法来执行git仓库同步的话优点是不受设备限制,可以在任意设备对远程仓库进行推送/拉取操作,缺点是每一次操作都需要输一次账号密码 git remote add origin http://127.0.0.1:/home/git/repo/.git # 这是ssh协议的写法,这种写法的好处是免去了每次操作后都要验证账号的繁琐,缺点则是需要在可信任设备里生成一对ssh秘钥,并把密钥中的公钥记录到服务器对应账号的$home目录下的.ssh目录里的authorized_keys文件里(如果不存在的话需要新建一个) git remote add origin git@127.0.0.1:/home/git/repo/.git 添加完远程仓库地址的话就可以随时通过git的pull、push来传输数据/文件了 ","description":"\n","tags":["git","服务器","server"],"title":"\n【已失效】使用git推送源码到私有服务器","uri":"/posts/%E4%BD%BF%E7%94%A8git%E6%8E%A8%E9%80%81%E6%BA%90%E7%A0%81%E5%88%B0%E7%A7%81%E6%9C%89%E6%9C%8D%E5%8A%A1%E5%99%A8/"}]