普通视图

Received before yesterdaySolitudes

轻松部署 Artifactory(不推荐款)

2025年6月7日 14:50

在 DevOps 实践中,软件包管理是不可或缺的一环。JFrog Artifactory 作为一款强大的制品管理工具,广泛应用于存储和管理二进制文件。本文简单介绍如何部署 Artifactory 开源版。

主要有客户需要部署这个,简单研究一下,上次用这个还是 4 年前了,新版本部署坑有点多,没老版本丝滑。简单说不如 Nexus,有兴趣的可以看看我之前写的私有化部署 Nexus3 镜像源

镜像

镜像有点点大

docker pull releases-docker.jfrog.io/jfrog/artifactory-oss:7.111.8
# 国内
docker pull ccr.ccs.tencentyun.com/k7scn/artifactory-oss:7.111.8

部署

  • docker-compose.yaml
services:
  traefik:
    image: traefik:v3.4
    container_name: traefik
    networks:
      - ysicing-net
    command:
      - "--api=true"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.http.address=:80"
      - "--providers.docker.network=ysicing-net"
      - "--log.level=INFO"
      - "--accesslog=true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik-dashboard.entrypoints=http"
      - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.192.168.23.16.sslip.io`)"
      - "traefik.http.routers.traefik-dashboard.service=dashboard@internal"
      - "traefik.http.routers.traefik-dashboard-api.entrypoints=http"
      - "traefik.http.routers.traefik-dashboard-api.rule=Host(`traefik.192.168.23.16.sslip.io`) && PathPrefix(`/api`)"
      - "traefik.http.routers.traefik-dashboard-api.service=api@internal"
      - "traefik.http.middlewares.gzip.compress=true"
      - "traefik.http.routers.traefik-dashboard.middlewares=gzip@docker"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always

  artifactorydb:
    image: docker.io/bitnami/postgresql:15
    # image: ccr.ccs.tencentyun.com/k7scn/postgresql:15
    container_name: artifactorydb
    restart: always
    networks:
      - ysicing-net
    volumes:
      - './postgresql:/bitnami/postgresql'
    environment:
      - POSTGRESQL_USERNAME=bn_artifactory
      - POSTGRESQL_DATABASE=bitnami_artifactory
      - POSTGRESQL_PASSWORD=bitnami

  artifactory:
    image: releases-docker.jfrog.io/jfrog/artifactory-oss:7.111.8
    # image: ccr.ccs.tencentyun.com/k7scn/artifactory-oss:7.111.8
    container_name: artifactory
    depends_on:
      - artifactorydb
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.artifactory.rule=Host(`artifactory.192.168.23.16.sslip.io`)"
      - "traefik.http.routers.artifactory.service=artifactory"
      - "traefik.http.services.artifactory.loadbalancer.server.port=8081"
      - "traefik.http.routers.artifactory-ui.service=artifactory-ui"
      - "traefik.http.routers.artifactory-ui.rule=Host(`artifactory-ui.192.168.23.16.sslip.io`)"
      - "traefik.http.services.artifactory-ui.loadbalancer.server.port=8082"
    networks:
      - ysicing-net
    environment:
      - EXTRA_JAVA_OPTIONS=-Dartifactory.home=/var/opt/jfrog/artifactory
      - JF_ROUTER_ENTRYPOINTS_EXTERNALPORT=8082
    # ports:
    #   - 8082:8082 # for router communication
    #   - 8081:8081 # for artifactory communication
    volumes:
      - artifactory_data:/var/opt/jfrog/artifactory
      - /etc/localtime:/etc/localtime:ro
      - ./system.yaml:/opt/jfrog/artifactory/var/etc/system.yaml
    restart: always
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "10"
    ulimits:
      nproc: 65535
      nofile:
        soft: 32000
        hard: 40000

volumes:
  artifactory_data:
    driver: local

networks:
  ysicing-net:
    name: ysicing-net
    driver: bridge

默认使用 pg 数据库,方便些

创建配置文件 system.yaml

touch system.yaml

创建完配置文件,生成相关配置

shared:
    database:
        type: postgresql
        driver: org.postgresql.Driver
        url: jdbc:postgresql://artifactorydb:5432/bitnami_artifactory
        username: bn_artifactory
        password: bitnami

修改文件权限

chown -R 1030:1030 system.yaml
chmod 644  system.yaml

运行启动

服务非常吃资源,机器配置太低不推荐。

docker compose up -d

访问 Artifactory

地址:artifactory-ui.192.168.23.16.sslip.io
默认的账号密码 | 默认用户名 admin,默认密码 password

总结

没有特殊要求,不推荐。


欢迎关注我的微信公众号,可以看看我郑再打工每天都在折腾什么。

  •  

轻松部署 Artifactory(不推荐款)

2025年6月6日 19:24

在 DevOps 实践中,软件包管理是不可或缺的一环。JFrog Artifactory 作为一款强大的制品管理工具,广泛应用于存储和管理二进制文件。本文简单介绍如何部署 Artifactory 开源版。

主要有客户需要部署这个,简单研究一下,上次用这个还是 4 年前了,新版本部署坑有点多,没老版本丝滑。简单说不如 Nexus,有兴趣的可以看看我之前写的私有化部署 Nexus3 镜像源

镜像

镜像有点点大

docker pull releases-docker.jfrog.io/jfrog/artifactory-oss:7.111.8
# 国内
docker pull ccr.ccs.tencentyun.com/k7scn/artifactory-oss:7.111.8

部署

  • docker-compose.yaml
services:
  traefik:
    image: traefik:v3.4
    container_name: traefik
    networks:
      - ysicing-net
    command:
      - "--api=true"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.http.address=:80"
      - "--providers.docker.network=ysicing-net"
      - "--log.level=INFO"
      - "--accesslog=true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik-dashboard.entrypoints=http"
      - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.192.168.23.16.sslip.io`)"
      - "traefik.http.routers.traefik-dashboard.service=dashboard@internal"
      - "traefik.http.routers.traefik-dashboard-api.entrypoints=http"
      - "traefik.http.routers.traefik-dashboard-api.rule=Host(`traefik.192.168.23.16.sslip.io`) && PathPrefix(`/api`)"
      - "traefik.http.routers.traefik-dashboard-api.service=api@internal"
      - "traefik.http.middlewares.gzip.compress=true"
      - "traefik.http.routers.traefik-dashboard.middlewares=gzip@docker"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always

  artifactorydb:
    image: docker.io/bitnami/postgresql:15
    # image: ccr.ccs.tencentyun.com/k7scn/postgresql:15
    container_name: artifactorydb
    restart: always
    networks:
      - ysicing-net
    volumes:
      - './postgresql:/bitnami/postgresql'
    environment:
      - POSTGRESQL_USERNAME=bn_artifactory
      - POSTGRESQL_DATABASE=bitnami_artifactory
      - POSTGRESQL_PASSWORD=bitnami

  artifactory:
    image: releases-docker.jfrog.io/jfrog/artifactory-oss:7.111.8
    # image: ccr.ccs.tencentyun.com/k7scn/artifactory-oss:7.111.8
    container_name: artifactory
    depends_on:
      - artifactorydb
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.artifactory.rule=Host(`artifactory.192.168.23.16.sslip.io`)"
      - "traefik.http.routers.artifactory.service=artifactory"
      - "traefik.http.services.artifactory.loadbalancer.server.port=8081"
      - "traefik.http.routers.artifactory-ui.service=artifactory-ui"
      - "traefik.http.routers.artifactory-ui.rule=Host(`artifactory-ui.192.168.23.16.sslip.io`)"
      - "traefik.http.services.artifactory-ui.loadbalancer.server.port=8082"
    networks:
      - ysicing-net
    environment:
      - EXTRA_JAVA_OPTIONS=-Dartifactory.home=/var/opt/jfrog/artifactory
      - JF_ROUTER_ENTRYPOINTS_EXTERNALPORT=8082
    # ports:
    #   - 8082:8082 # for router communication
    #   - 8081:8081 # for artifactory communication
    volumes:
      - artifactory_data:/var/opt/jfrog/artifactory
      - /etc/localtime:/etc/localtime:ro
      - ./system.yaml:/opt/jfrog/artifactory/var/etc/system.yaml
    restart: always
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "10"
    ulimits:
      nproc: 65535
      nofile:
        soft: 32000
        hard: 40000

volumes:
  artifactory_data:
    driver: local

networks:
  ysicing-net:
    name: ysicing-net
    driver: bridge

默认使用 pg 数据库,方便些

创建配置文件 system.yaml

touch system.yaml

创建完配置文件,生成相关配置

shared:
    database:
        type: postgresql
        driver: org.postgresql.Driver
        url: jdbc:postgresql://artifactorydb:5432/bitnami_artifactory
        username: bn_artifactory
        password: bitnami

修改文件权限

chown -R 1030:1030 system.yaml
chmod 644  system.yaml

运行启动

服务非常吃资源,机器配置太低不推荐。

docker compose up -d

访问 Artifactory

地址:artifactory-ui.192.168.23.16.sslip.io
默认的账号密码 | 默认用户名 admin,默认密码 password

总结

没有特殊要求,不推荐。


欢迎关注我的微信公众号,可以看看我郑再打工每天都在折腾什么。

  •  

FFmpeg常用命令备份

2025年6月5日 22:13

FFmpeg 是一个强大的开源多媒体处理工具,广泛应用于音视频的转换、裁剪、合并、提取等操作。无论是开发、剪辑还是日常处理,掌握 FFmpeg 的常用命令都能极大提升效率。本文整理了一些高频使用的 FFmpeg 命令,方便你快速上手或作为备忘录收藏!

临时需要处理一些上次到群晖 MinIO 的视频,写个流水线自动化处理。温故一下相关命令。

FFmpeg 简介

Fmpeg 是一个跨平台的音视频处理框架,支持几乎所有格式的音视频文件。它功能强大、命令灵活,堪称“音视频处理瑞士军刀”。以下是常见操作的命令合集,建议收藏备用!

常用命令速查

格式转换

将文件从一种格式转换为另一种格式,例如将 MP4 转为 AVI:

ffmpeg -i input.mp4 output.avi

-i:指定输入文件

提示:FFmpeg 会根据输出文件名自动推断目标格式

提取音频

从视频中提取音频,例如提取 MP3

ffmpeg -i input.mp4 -vn -acodec mp3 output.mp3
  • -vn:禁用视频流。
  • -acodec mp3:指定音频编码为 MP3

歌曲

截取视频片段

裁剪视频的指定时间段,例如从第 10 秒到第 30 秒:

ffmpeg -i input.mp4 -ss 10 -t 20 output.mp4
# 通常搭配如下
ffmpeg -i input.mp4 -ss 10 -t 20 -c copy output.mp4
  • -ss:起始时间(秒或 hh:mm:ss)
  • -t:裁剪时长(秒或 hh:mm:ss)
  • -c copy:直接复制流,避免重新编码,速度更快

视频截图

ffmpeg -ss 00:20:00 -i "input.mp4" -vframes 1 "01.jpg"

视频压缩

压缩视频文件大小,调整比特率:

ffmpeg -i input.mp4 -vcodec libx264 -b:v 1000k output.mp4
  • -b:v:设置视频比特率,值越低压缩越高,但画质可能下降

调整视频分辨率

将视频缩放到指定分辨率,例如 1280x720:

ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4
  • -vf scale:设置缩放参数

转换帧率

更改视频帧率,例如从 60fps 转为 24fps:

ffmpeg -i input.mp4 -r 24 output.mp4
  • -r:设置目标帧率

例如 h264 编码无损转换至 h265 编码

ffmpeg -c:v h264_cuvid -i input.mp4 -c:v hevc_nvenc -r 24 -c:a copy -x265-params lossless=1 output.mp4;

提取视频帧

将视频转为图片序列,例如每秒提取一帧:

ffmpeg -i input.mp4 -vf fps=1 frame_%04d.png
  • %04d:生成文件名递增,如 frame_0001.png

查看文件信息

快速查看音视频文件的详细信息:

ffmpeg -i input.mp4

输出包含编码格式、分辨率、时长等详细信息

通常如下所用一键输出视频的编码、帧率、码率

codec=$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 input.mp4)
r_frame_rate=$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=noprint_wrappers=1:nokey=1 input.mp4)
bit_rate=$(ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 input.mp4)
echo -e "$codec\t$r_frame_rate\t$bit_rate\tinput.mp4"

视频合并

将多个视频文件合并为一个(需确保分辨率、编码一致):

# 创建文件列表 mv.txt
echo "file 'input1.mp4'" > mv.txt
echo "file 'input2.mp4'" >> mv.txt
ffmpeg -f concat -i mv.txt -c copy output.mp4

这个没用过,仅供参考

实用技巧与注意事项

  • Linux:apt install ffmpeg(Debian)
  • macOS:brew install ffmpeg

我仅在这两个环境实操过,其他环境可以参考官方文档,类似文档很详细了

另外结合脚本语言很方便,例如 bash

写在最后

FFmpeg 的功能远不止这些,熟练使用后,你可以轻松应对音视频处理的各种场。对于我而言,掌握基本功能从视频中导出音频文件使用就行(大部分还用不上,因为还有一些第三方工具帮你自动一键搞定)


欢迎关注我的微信公众号。

  •  

MinIO最新社区版砍掉 Web 管理功能

2025年6月3日 22:14

近日,MinIO 社区版迎来重大更新,删除了 11 万行代码,彻底移除 Web 管理控制台功能,官方称此举为“精简代码,专注核心存储功能”。这一决定引发社区热议,对用户体验和项目生态造成显著影响。本文将深入剖析这一变化的细节、影响及社区反应。

Web 管理功能移除的影响

MinIO 作为一款高性能分布式对象存储系统,因其 S3 协议兼容性和易用性深受开发者喜爱。其 Web 管理控制台是社区版的核心功能,支持存储桶管理、文件浏览和权限配置,极大降低了操作门槛,尤其适合:

  • 非技术用户:通过直观界面快速上手,减少对命令行的依赖
  • 团队协作:便捷管理存储资源,提升效率
  • 实时监控:查看文件列表、使用量等存储状态

然而,新版本将 Web 控制台的核心管理功能(包括用户账户管理、访问策略配置、存储桶管理和系统配置)全部移除,官方推荐使用 mc 命令行工具替代。相比可视化界面,mc 命令行工具对新手不够友好,且在快速调试和监控场景下效率较低。

新老控制台对比

2025.4.22

2025.5.24

被移除的具体功能

此次更新几乎清空了 Web 管理控制台的功能,仅保留基本的对象浏览能力。以下是主要受影响的模块:

  • 账户与策略管理
    • 移除用户账户创建、访问密钥管理和策略设置功能
    • OIDC 单点登录等高级认证功能被砍,用户只能使用管理员初始账户登录,无法通过界面创建新访问密钥
  • 配置与集群管理
    • 无法通过界面查看或修改服务器配置、后端存储设置及集群状态
    • 所有实例调整和服务监控需依赖命令行或 API
  • 存储桶管理
    • 删除新建存储桶、设置策略、版本控制和生命周期规则的界面功能
    • Web 界面退化为纯对象浏览器,仅支持列出存储桶及文件
  • 其他功能
    • 服务器信息仪表盘、多节点集群视图、日志和通知配置等管理功能全部移除

简言之,新版 Web 界面已不再是管理控制台,而是一个功能极简的文件浏览器。用户被迫转向 mc 命令行工具完成所有管理任务,操作门槛显著提高

受影响的版本

  • 2025.4.22 版本是最后一个保留完整控制台功能的版本, 可用镜像 ccr.ccs.tencentyun.com/k7scn/minio:2025.4.22
  • 2025.5.24 版本则包含了删除控制台功能的改动(MinIO 官方在发布说明的 “重要事项” 中明确提到嵌入式 Web 控制台(Console)已被弃用,并移至独立的 object-browser 项目)

社区反应与讨论

MinIO 官方称,删除 11 万行代码旨在优化性能、聚焦核心存储功能。然而,Web 控制台资源占用较低,维护成本有限,社区对这一理由普遍质疑。相比之下,MinIO 商用版保留了完整的 Web 管理功能,功能更强大,引发了“社区版精简是为了推销商用版”的猜测

X 平台和 Reddit 等社区反馈显示,开发者认为这是开源项目商业化的常见策略:通过削减免费版功能,引导用户转向付费版本。部分用户甚至称此次更新为特洛伊木马式更新,批评官方未提供过渡方案,给中小团队带来额外适配成本

作为回应,社区迅速行动:

  • 启动 OpenMaxIO 分支项目,试图恢复被移除的功能
  • SeaweedFS 和 Garage 等替代方案获得更多关注

结语

MinIO 社区版移除 Web 管理功能的决定,削弱了其易用性和吸引力。开源项目的核心在于平衡社区需求与商业利益,MinIO 的后续决策将直接影响其在对象存储领域的地位。对于依赖 Web 控制台的团队,建议暂时停留在 2025.4.22 版本,或探索其他替代方案。


欢迎关注,可以看看我郑再打工每天都在折腾什么。

  •  

值得入手的Steam模拟类神作:缺氧(Oxygen Not Included)

2025年5月31日 23:07

各位小伙伴!今天给大家安利一款超硬核、超上头的模拟经营类游戏——缺氧(Oxygen Not Included)! 如果你喜欢挑战脑力、沉浸式体验和无限可能的建造乐趣,这款游戏绝对不容错过!

缺氧是由 Klei Entertainment(饥荒开发商)打造的一款生存模拟类游戏。玩家需要在一个地下星球中管理一群可爱的小人(复制人),通过建造基地、分配资源、应对环境危机,让他们在缺氧、缺食、缺电的恶劣环境中存活下来!

特点

  • 超高自由度的建造体验
    在游戏中,你可以自由规划地下基地,设计复杂的管道、电力和氧气系统。想建一个自给自足的生态圈?还是一个高科技的自动化基地?全看你的脑洞!从简单的茅厕到复杂的核反应堆,建造过程既烧脑又满足
  • 硬核的资源管理
    氧气、食物、水、能源、温度……每一项资源都需要你精打细算。稍有不慎,小人可能会因为缺氧窒息、食物中毒,甚至被高温烫伤
  • 随机生成的挑战
    每次开局的地图和资源分布都不相同,随机事件(如陨石雨、火山喷发)让每一局都充满新鲜感。你需要根据环境灵活调整策略,永远不会觉得无聊
  • 丰富的 MOD 支持
    社区 MOD 丰富多样,从增加新建筑到优化游戏体验,应有尽有!无论你是想降低难度还是挑战极限,都能找到适合自己的玩法

我的玩法开局看水和铜多不多,不多重开

适合人群

  • 喜欢模拟经营
  • 热衷挑战的硬核玩家:喜欢烧脑、追求极限生存
  • 创意玩家:想打造独一无二的地下乌托邦

当然耐心很重要, 同时要有自我控制能力,因为很容易肝上头

入手性价比

推荐直接购买缺氧完整包, 我上个月入手大概不到 90CNY。

缺氧完整包

推荐购买正版,请勿相信廉价购买,谨防虚假入库,导致游戏和钱两失。

新手建议

  • 前期多关注氧气和食物,善用“暂停”功能规划基地
  • 游戏上手稍有难度,但官方有中文支持,社区教程也超多,入门后根本停不下来
  • 多在 B 站搜搜相关教程
  • 早期多重开几次就会玩了。

官方介绍节选

  • 建立广阔的基地以及探索生存所需的资源:
    从挖掘、资源分配到管道、电力系统,太空殖民地的一切都在你的掌控之下。然而,资源会从你第一次呼吸开始被消耗 ,所以如果你想生存下来的话,就一定要确保你探索得够快。
  • 伴随着压力模拟的精神状态问题
    给你的殖民地提供娱乐休闲活动、优越的住宿条件和更好的食物,来保证生存不会受到精神状态的影响。每个复制人之间都有差异,会对压力做出不同的潜在破坏性反应。 所以不管付出什么代价,一定要确保他们拥有愉悦的心情
  • 用复杂的气体和液体模拟系统来提高效率
    建立一个连锁的管道系统,可以迅速的将燃料和液体输送到基地的关键区域。优质的规划以及获得的加成可以让你的殖民地转变成一个运转良好的不朽机器
  • 通过电网模拟系统来获得电力:
    你可以通过众多不同的能源来获得电力,包括煤,氢,天然气或者仅仅是朴实老旧的油脂。修复电力流失,电路过载和崩溃问题以保持你殖民地的顺利运行

欢迎关注,可以看看我郑再打工每天都在折腾什么。

  •  

轻松管理K3s集群服务:System Upgrade Controller 的超实用指南

2025年5月30日 21:20

K3s 作为轻量级 Kubernetes 发行版,以其高效、简洁的特性深受开发者与运维人员喜爱。但手动升级 K3s 集群可能是个繁琐的任务,幸好有 System Upgrade Controller!这个工具能让你的 K3s 集群实现自动化、无宕机升级,省时又省心。本文将带你了解 System Upgrade Controller 的魅力,并提供简洁的部署步骤,让你的集群管理更轻松!

主要用于升级 k3s 集群节点上的服务,不仅仅局限于 k3s 服务本身。

简介

System Upgrade Controller 是 Rancher 开发的一个自动化升级工具。它通过 Kubernetes 原生资源(如 Plan)管理节点和 K3s 版本的升级,核心优势包括:

  • 自动化:一键配置,自动完成 K3s 版本升级
  • 零宕机:逐节点升级,确保服务不中断
  • 灵活性:支持自定义升级策略,适配各种集群规模
  • 轻量高效:与 K3s 的低资源占用理念完美契合

如果你想让 K3s 集群保持最新或者减少运维负担,绝对值得一试!

项目地址:

在 K3s 上部署

以下是快速部署 System Upgrade Controller 的步骤,简单易上手

kubectl apply -f https://raw.githubusercontent.com/rancher/system-upgrade-controller/master/manifests/system-upgrade-controller.yaml

或者

kubectl apply -k github.com/rancher/system-upgrade-controller

服务控制器默认会部署到 system-upgrade 命名空间下

kubectl get deploy -n system-upgrade
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
system-upgrade-controller   1/1     1            1           335d

使用场景

常见使用如下,由于权限极高,操作时需要确保重复执行没影响。

  • 升级 k3s 本身
  • 升级 k3s 集群节点服务

升级 k3s 服务

由于我现在的环境特殊,只有一个 master 节点,每次跨版本升级 master 节点都是先手动升级到最新版本,然后在使用下面的命令升级计算节点。(保障至少 1 个控制节点版本是最新的)

---
apiVersion: v1
kind: Secret
metadata:
  name: k3s1306
  namespace: system-upgrade
type: Opaque
stringData:
  upgrade.sh: |
    #!/bin/bash

    set -x

    binfile=$(command -v k3s)

    $binfile -v | grep "v1.30.6" && (
      echo "done"
      exit 0
    ) || (
      wget https://c.ysicing.net/oss/tiga/linux/amd64/k3s
      chmod +x k3s
      mv k3s $binfile && systemctl restart k3s
    )
---
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: k3s1306
  namespace: system-upgrade
spec:
  concurrency: 3
  nodeSelector:
    matchExpressions:
      - {key: kubernetes.io/os, operator: Exists}
  tolerations:
  - {operator: Exists}
  serviceAccountName: system-upgrade
  secrets:
    - name: k3s1306
      path: /host/run/system-upgrade/secrets/k3s1306
  cordon: false
  version: latest
  upgrade:
    image: hub.ysicing.net/ysicing/debian-upgrade:20230909
    command: ["chroot", "/host"]
    args: ["sh", "/run/system-upgrade/secrets/k3s1306/upgrade.sh"]

想了解更多官方的姿势,可以参考

升级集群服务

  • 升级 tailscale 服务
---
apiVersion: v1
kind: Secret
metadata:
  name: ts-script
  namespace: system-upgrade
type: Opaque
stringData:
  upgrade.sh: |
    #!/bin/bash

    set -x
    if tailscale version 2>/dev/null | grep -q "1.82.5"; then
        echo "Tailscale 1.82.5 already installed"
        exit 0
    fi
    export DEBIAN_FRONTEND=noninteractive
    apt-get update -qq
    apt-get install -y --no-install-recommends tailscale
---
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: ts1825
  namespace: system-upgrade
spec:
  concurrency: 1
  nodeSelector:
    matchExpressions:
      - {key: kubernetes.io/os, operator: Exists}
  tolerations:
  - {operator: Exists}
  serviceAccountName: system-upgrade
  secrets:
    - name: ts-script
      path: /host/run/system-upgrade/secrets/ts-script
  cordon: false
  version: latest
  upgrade:
    image: hub.ysicing.net/ysicing/debian-upgrade:20230909
    command: ["chroot", "/host"]
    args: ["sh", "/run/system-upgrade/secrets/ts-script/upgrade.sh"]
  • 升级 easytier
---
apiVersion: v1
kind: Secret
metadata:
  name: debian
  namespace: system-upgrade
type: Opaque
stringData:
  upgrade.sh: |
    #!/bin/sh
    set -e
    if easytier-core -V 2>/dev/null | grep -q "2.2.4"; then
        echo "easytier 2.2.4 already installed"
        exit 0
    fi
    apt-get --assume-yes update
    DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade --assume-yes
    curl https://c.ysicing.net/oss/scripts/easytier.sh | bash
---
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: debian-25021514
  namespace: system-upgrade
spec:
  concurrency: 3
  nodeSelector:
    matchExpressions:
      - {key: kubernetes.io/os, operator: Exists}
  tolerations:
  - {operator: Exists}
  serviceAccountName: system-upgrade
  secrets:
    - name: debian
      path: /host/run/system-upgrade/secrets/debian
  cordon: false
  version: latest
  upgrade:
    image: ysicing/debian
    command: ["chroot", "/host"]
    args: ["sh", "/run/system-upgrade/secrets/debian/upgrade.sh"]

通过上面 3 个例子,其实就是帮你去每个节点执行相关脚本,如果你有大量类似的重复的工作,System Upgrade Controller 就是个绝佳的运维工具,它让版本管理变得简单、高效、无忧,显著提升你的运维体验。


欢迎关注,可以看看我郑再打工每天都在折腾什么。

  •  

Raphael AI图片生成器:释放创意,零门槛打造惊艳视觉盛宴

2025年5月23日 19:53

在 AI 技术席卷全球的今天,图像生成工具正成为内容创作者、设计师和营销人员的得力助手。Raphael AI 作为全球首款完全免费无限制无需注册登录的 AI 图像生成器,以其强大的功能和便捷的操作,迅速在创意圈掀起热潮。

今天偶然看到的,有免费额度的 AI 图片生成器。适合生成配图或者插图,用来生成封面感觉还差点意思,和即梦效果差不多。

Raphael AI 是什么?

Raphael AI 是一款基于先进的 FLUX.1-Dev 模型打造的 AI 图像生成工具,用户只需输入文字描述(提示词),即可在几秒钟内生成高质量、多风格的图像。它的核心优势在于:

  • 完全免费, 零成本创作:无使用次数限制,无需注册或登录,打开网页即可创作
  • 多样化风格:支持写实摄影、动漫、油画、数字艺术等多种艺术风格
  • 快速生成:优化的推理管道确保几秒内出图,效率惊人
  • 隐私保护:零数据保留政策,提示词和生成图像不存储于服务器,保障用户隐私
  • 商业用途:生成图像无水印,可自由用于个人或商业项目
  • 一定质量保障:由 FLUX.1-Dev 模型驱动,提供具有卓越细节和艺术风格控制的照片级逼真图像;高级文本理解

对比国内大模型,我觉得是优势功能的都标注了。为啥说一定质量保障,因为高质量需要订阅才行 😄

测试

英文提示词

Humorous and funny style, preferably with a purple-haired Japanese anime girl holding a sign that says, "I need 66 more followers to reach 1000, please subscribe."

选择一个,其他都略微有些瑕疵

中文提示词

幽默搞笑风, 最好有个紫色头发日漫妹子举牌子,牌子上写着「我还有 66 个粉丝才满 1000,请求订阅」》

总结

官方建议: 请用英文输入提示词以获得最佳效果

经过实操,确实英文提示词要比中文好多了,可能我问的方式仅在 ChatGPT 上实验良好。

官方也提供了一些灵感示例提示词,点击相关图片就可以查看其他人的提示词

再次实操一下,发现生成 SB 比缘生更简单哈哈哈

生成: Cute chubby Pikachu on the grass, surrounded by small white flowers, with the two Chinese characters "SB" written on Pikachu's belly, soft pastel anime style

官网


  •  

Google新AI产品无法使用解决指南

2025年5月22日 18:21

今天看到这个消息推送,之前也遇到过这种情况,这个简单写下如何解决,当个精神美国佬

背景

受限于某些特殊环境或者边缘因素影响,国内是没法正常使用 Google AI 相关的产品的。(默认你已经可以访问 Google AI 等产品了)

接下来给的几种方式,都可以尝试

修改浏览器默认语言

这个跟之前 Github 默认禁止中文用户访问类似,检查你的请求头 accept-language 信息

示例修改 Edge 默认首选语言为英语即可,生效后随便访问一个网站开发者工具查看请求头或者支持切换语言的网站打开是否为英文

如果你的账号没问题了,通常打开那些网站就可以正常使用了。如果还不行,可能就是账号问题了

当然也会带来一些问题,你打开所有支持多语言的网站都会默认使用英文,影响也不大

申请谷歌账号地区修改

有可能,你很早之前就注册了谷歌账号,地区选的中国

查看账号绑定的地区 https://policies.google.com/terms

换区操作

找对入口,其实也很简单,通常我们都选择美区,精神美国佬,社会大学生, 部分 AI 功能暂时只对美区开发。

换区入口 https://policies.google.com/country-association-form

理由选择其他原因,听劝

好了,其他就是基本要求了,自行准备就行。

对了,这两个我港区的小号也是可以正常访问的。

PS: 大佬们都买了 Google One Ultra 没?


  •  

Drawnix:无限画布上的开源白板工具

2025年5月21日 20:40

这个项目很早之前就关注过, 那时还没提供 Dockerfile😁

简介

Drawnix 是一款基于 Plait 框架打造的免费开源白板工具,提供思维导图、流程图和自由绘画等功能。依托插件化架构,用户能够随需扩展多种交互组件。每一次操作都能实时保存至浏览器缓存,确保内容不丢失

核心特性

  • 多样化绘图模式
    • 支持思维导图、流程图与自由画笔,满足不同场景需求
    • 可插入图片,通过简单拖拽丰富画面
  • 高效编辑体验
    • 撤销、重做、复制与粘贴操作流畅
    • 自动保存功能避免意外丢失(浏览器缓存)
  • 无限画布与导出能力
    • 通过缩放与滚动打造无边界创作空间
    • 可将画布导出为 PNG 或 JSON(.drawnix) 文件
  • 插件机制与兼容性
    • 插件架构支持 Angular、React 等多种 UI 框架
    • 自带 Slate 富文本扩展,后续可接入更多文本编辑插件
    • 未来可通过社区插件实现更多应用场景

项目

名称灵感

Drawnix ,源于绘画( Draw )与凤凰( Phoenix )的灵感交织。
凤凰象征着生生不息的创造力,而 Draw 代表着人类最原始的表达方式。在这里,每一次创作都是一次艺术的涅槃,每一笔绘画都是灵感的重生。
创意如同凤凰,浴火方能重生,而 Drawnix 要做技术与创意之火的守护者。
Draw Beyond, Rise Above.

与 Plait 框架的深度结合

Drawnix 底层依托作者公司开源的 Plait 画图框架,这是知识库产品的重要技术沉淀。两者紧密结合让开发者享受“一键开箱即用”的便捷,同时还能在业务分层中灵活装载自定义插件。

这款工具不仅是面向个人创作者,同样适用于团队协作与在线教学。无限画布中,每一次涂抹都让构思变得更生动、更立体,技术与想象力在此汇合,带来前所未有的白板体验。

私有化部署

作者已经提供了 Dockerfile,基于此 Dockerfile,我构建了一个镜像, 默认监听 80 端口,除此外无特殊配置

  • ccr.ccs.tencentyun.com/k7scn/drawnix 基于此97ab1d4构建完成

compose 部署

  • docker-compose.yaml
services:
  drawnix:
    image: ccr.ccs.tencentyun.com/k7scn/drawnix
    container_name: drawnix
    ports:
      - '100.90.80.15:8088:80'
    restart: always

然后配置 caddy 代理即可。

k3s 部署

我主要使用 k3s 部署,对外访问使用 cft

  • drawnix.yaml
---
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  labels:
    app: drawnix
  name: drawnix
  namespace: kc-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: drawnix
  updateStrategy:
    type: InPlaceIfPossible
  template:
    metadata:
      labels:
        app: drawnix
    spec:
      tolerations:
      - operator: Exists
      nodeSelector:
        node-role.kubernetes.io/kc: "true"
      containers:
      - image: tcr.china.12306.work/github/drawnix
        imagePullPolicy: Always
        name: drawnix
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: drawnix
  name: drawnix
  namespace: kc-system
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: drawnix
  type: ClusterIP

apply 之后,在 cfd tunnel 管理页添加公共主机名

演示站

欢迎自建,不保证 SLA,暂时不知道开源版与官方演示有什么区别。


欢迎订阅我的微信公众号,同步更新 😁

  •  

解锁高效开发利器——Gitness,助力你的DevOps之旅

2025年5月18日 22:19

在快节奏的软件开发世界中,高效的代码托管和自动化部署是每个开发团队的追求。你是否曾为繁琐的 CI/CD 流程而头疼?是否希望有一个简单易用、功能强大的平台来管理你的代码和流水线?今天,我们为你介绍一款开源神器——Gitness,它将彻底改变你的开发体验。

作为 Drone 和 Gitness 深度定制用户,我还值得很推荐的。

什么是 Gitness

Gitness 是一个集代码托管与自动化 DevOps 流水线于一体的开源开发平台。作为 Drone CI 的下一代产品,Gitness 不仅保留了强大的持续集成(CI)功能,还新增了源代码托管能力,支持本地部署和 Docker 容器化运行。无论是个人开发者还是小型团队,Gitness 都能提供灵活、高效的解决方案。

核心亮点

  • 一体化平台:代码托管 + CI/CD 流水线 + 制品库
  • 用户友好:提供直观的 UI 界面、REST API,满足不同开发者的使用习惯
  • 灵活部署:支持私有化本地部署
  • 开源免费:完全开源,社区驱动,适合预算有限的团队(非常适合个人用户)

对比 Drone、Woodpecker

  • 目前支持 Runner 有限,仅支持 docker
  • 新增的制品库支持的种类相对比较少,常见的 Docker、Helm 是没问题的
  • 目前数据库仅支持 PG、Sqlite3
  • 流水线
    • 日志相比较 v2 仅支持存储到数据库,暂不支持存储到对象存储
    • 不支持重复执行(如定时、失败重试)
    • 流水线语法变更,相比较 Drone、Woodpecker 等 v2 版本的语法,功能缺少较多,但是满足基本使用
  • 代码仓库功能完善,日常使用是没问题

部署

环境变量配置

目前官方文档未提供,需要参考官方文档 harness/harness#config.go

部署

镜像:

  • harness/harness:unstable
  • 国内镜像 ccr.ccs.tencentyun.com/k7scn/harness:unstable
  • docker-compose.yaml
services:

  gitness:
    image: harness/harness:unstable
    container_name: gitness
    restart: always
    ports:
      - "3000:3000"
      - "3022:3022"
    volumes:
      - /data/gitness:/data
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - GITNESS_DEBUG=true
      - GITNESS_TRACE=true
      - GITNESS_GIT_TRACE=true
      - GITNESS_GIT_DEFAULTBRANCH=master
      - GITNESS_WEBHOOK_ALLOW_LOOPBACK=true
      - GITNESS_WEBHOOK_ALLOW_PRIVATE_NETWORK=true
      - GITNESS_METRIC_ENABLED=false
      - GITNESS_PRINCIPAL_ADMIN_UID=ysicing
      - GITNESS_PRINCIPAL_ADMIN_DISPLAY_NAME=ysicing
      - GITNESS_PRINCIPAL_ADMIN_EMAIL=ysicing@12306.work
      - GITNESS_PRINCIPAL_ADMIN_PASSWORD=ysicing
#     - GITNESS_SMTP_HOST=
#     - GITNESS_SMTP_PORT
#     - GITNESS_SMTP_USERNAME
#     - GITNESS_SMTP_PASSWORD
#     - GITNESS_SMTP_FROM_MAIL
#     - GITNESS_SMTP_INSECURE
      - GITNESS_GITSPACE_DEFAULT_BASE_IMAGE=ccr.ccs.tencentyun.com/k7scn/base:dev-ubuntu-24.04
      - GITNESS_UI_SHOW_PLUGIN=true
      - GITNESS_URL_GIT=http://192.168.23.16:3000/git
      - GITNESS_URL_UI=http://192.168.23.16:3000
      - GITNESS_URL_API=http://192.168.23.16:3000/api
      - GITNESS_URL_GIT_SSH=ssh://192.168.23.16
      - GITNESS_SSH_ENABLE=true
#      - GITFOX_SSH_PORT=3022
#      - GITNESS_CI_PARALLEL_WORKERS=2
#      - GITNESS_GIT_ROOT
      - GITNESS_CI_PLUGINS_ZIP_URL=https://c.ysicing.net/oss/offline/master.zip

部署完成,使用 IP:3000 访问. 账号密码需要使用设置的 GITNESS_PRINCIPAL_ADMIN_UIDGITNESS_PRINCIPAL_ADMIN_PASSWORD

目前配置参数过多,稍微配置不对还可能有 bug。针对这个

  • 我司会开源 GitFox,基于 Gitness 定制的 fork 版本,一些额外特性功能的补充(企业、与禅道的联动)
  • 我个人也维护了一套 Gitness 的魔改版本 Gitless,在上游的版本增加了个人开发者常用的特性(仅从我个人使用)

使用说明

这里简单过一些,后面会专门写一些文章介绍一下。

创建组织

对应其他 Git 服务的组织(ORG/GROUP)

创建仓库

流水线

执行流水线,目前支持部分 drone 插件,基本可以拿来就用如果熟悉 drone 和 gitness 的流水线语法的话

制品仓库

目前支持如下,感觉是借鉴了 Nexus,基本已经覆盖了日常使用。

WebIDE

总结

Gitness 不仅是一款工具,更是开发者高效协作的伙伴。无论你是追求极致效率的个人开发者,还是需要稳定流水线的小型企业团队,Gitness 都能满足你的需求。不过有一说一,目前 Gitness 还是处于快速发展阶段,有 Bug 是正常不过的事,但是基本功能还是没啥问题的。其次他们开源版本支持力度不是那么紧急,更多的还是服务他们的 SAAS 产品。


  •  

私有化部署Nexus3镜像源

2025年5月17日 09:19

昨天升级 Nexus3 翻车了,准备基于 PG 重新搭建 Nexus3 源,并移除一些不用的软件源, 新版软件源支持如下

环境要求

  • 机器配置至少 2C4G
  • 网络要好,推荐境外机器部署
  • 大硬盘可选(不代理 py 等还好)

部署

nexus 服务

使用 compose 或者 k8s,原理差不多,我的环境使用 k3s。

  • docker-compose.yaml
services:
  nexus3:
    image: sonatype/nexus3:latest
    container_name: nexus3
    restart: always
    ports:
      - "8081:8081"
    environment:
      - INSTALL4J_ADD_VM_PARAMS=-Xms2703m -Xmx4G -XX:MaxDirectMemorySize=2703m -Djava.util.prefs.userRoot=/nexus-data/javaprefs
      - NEXUS_DATASTORE_ENABLED=true
      - NEXUS_DATASTORE_NEXUS_JDBCURL=jdbc:postgresql://postgres:5432/nexus3
      - NEXUS_DATASTORE_NEXUS_USERNAME=oup44Fai4ta
      - NEXUS_DATASTORE_NEXUS_PASSWORD=ienah9eiquah7GeiMaengeitie5aeq66
    volumes:
      - /data/nexus/nexusdata:/nexus-data
    depends_on:
      - postgres

  postgres:
    image: bitnami/postgresql:17
    container_name: postgres
    environment:
      - POSTGRESQL_DATABASE=nexus3
      - POSTGRESQL_USERNAME=oup44Fai4ta
      - POSTGRESQL_PASSWORD=ienah9eiquah7GeiMaengeitie5aeq66
    volumes:
      - /data/nexus/postgres:/bitnami/postgresql
    restart: always

在启动前,先创建好目录,并给予权限

mkdir -p /data/nexus/postgres /data/nexus/nexusdata
chmod 777 /data/nexus -R

然后启动, 访问 ip:8081 即可

docker compose up -d

配置 caddy

mirrors.china.12306.work {
	import LOG "/var/log/caddy/mirrors.log"
	@rootOrIndex {
		path /
		path /index.html
		path /mirror.css
		path /.help*
	}

	handle @rootOrIndex {
		file_server {
			hide .git
			root /etc/caddy/pages/mirrors
		}
	}
	reverse_proxy http://100.90.80.3:8081
}

样式我从网易镜像源借鉴来的

目前支持的软件

本文档由 ysicing 收集整理, 希望能对国内开源软件用户有所帮助.

仅列出部分核心软件包:

  • tailscale
  • caddy
  • docker-ce
  • postgresql
  • trivy

为什么没有我用的软件包?因为我暂时用不上, 有好的想法可以联系我.


  •  

Nexus3 容器部署3.70.x升级实践-非成功案例

2025年5月16日 21:09

docker 从 3.70.x 及以下版本升级 3.71.x 及以上版本出现旧数据库不支持错误

官方也很细心给了一份升级文档 upgrading-to-nexus-repository-3-71-0-and-beyond

由于我使用的也是官方镜像,社区也有人给出了解决方案 sonatype/nexus-public#51

友情提示,操作前需要备份持久化数据,避免升级失败,建议先阅读文尾后再参考我的升级

创建 nexus 备份文件

  • 设置-系统-任务-创建任务

  • 搜索 Backup,选择它

  • 创建一下手动触发的任务,备份路径 /nexus-data/backup 就行

  • 创建完任务后,点击 backup 任务运行

  • 触发备份

  • 等待备份完成

不放心,也可以进容器内,看一下:

19:56 ➜  ~ kubectl exec -it pods/nexus3-859bb76886-mc29s -n nat -- bash
bash-4.4$ ls
nexus  sonatype-work  start-nexus-repository-manager.sh
bash-4.4$ cd /nexus-data/
bash-4.4$ ls
backup	blobs  cache  db  elasticsearch  etc  generated-bundles  instances  javaprefs  kar  karaf.pid  keystores  lock	log  orient  port  restore-from-backup	tmp
bash-4.4$ cd backup/
bash-4.4$ ls
analytics-2025-05-16-11-56-22-3.70.1-02.bak  component-2025-05-16-11-56-22-3.70.1-02.bak  config-2025-05-16-11-56-22-3.70.1-02.bak  security-2025-05-16-11-56-22-3.70.1-02.bak
bash-4.4$ exit

示例是 k8s 方式,docker 部署也是类似。

数据迁移

查询对应 nexus-db-migrator 迁移工具

需要下载和你 Nexus 版本匹配的 nexus-db-migrator 工具, 最新版本下载 nexus-db-migrator, 目前最新版本是 3.70.4-02

大概格式如下:

https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-<version版本号>.jar

由于我的版本是 3.70.1-02, 选择下载

https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/nxrm3-migrator/nexus-db-migrator-3.70.1-03.jar

可能你对应的版本不存在,可以尝试改 patch 版本,实在不行你就先升级到 3.70.4 最新版本

再次提醒版本一定要匹配上

操作

进入容器内部操作,方便起见, 确保在 /nexus-data/backup 目录下

bash-4.4$ pwd
/nexus-data/backup

下载迁移工具,或者同步到容器内也行(网络不好的情况下)

curl -s -L -O https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/nxrm3-migrator/nexus-db-migrator-3.70.1-03.jar

停 nexus 服务

/opt/sonatype/nexus/bin/nexus stop

执行迁移操作,将数据迁移到 H2 数据库,根据数据量和配置灵活调整 -Xmx4G -Xms4G 值,这里条件有限默认 4G, 执行完成如下图

java -Xmx4G -Xms4G -XX:+UseG1GC -XX:MaxDirectMemorySize=28672M -jar nexus-db-migrator-3.70.1-03.jar --migration_type=h2

再次停 nexus 服务

bash-4.4$ /opt/sonatype/nexus/bin/nexus stop
Shutting down nexus
nexus is not running.

查看迁移的数据

bash-4.4$ ls -ahl nexus.mv.db
-rw-r--r-- 1 nexus nexus 320K May 16 12:19 nexus.mv.db

将迁移的数据文件复制到 db 文件夹中

cp nexus.mv.db /nexus-data/db

然后退出容器

销毁容器

  • compose 部署
docker compose down nexus3
  • k8s 部署副本改成 0
kubectl scale --replicas 0 deploy/nexus3 -n nat

编辑配置文件

为啥不在容器里编辑,啥工具都没有不方便,而且这个配置持久化了

  • 默认配置如下 old
root@nat3:/data/k8s/local/nexus3/etc# cat nexus.properties
# Jetty section
# application-port=8081
# application-host=0.0.0.0
# nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-http.xml,${jetty.etc}/jetty-requestlog.xml
# nexus-context-path=/${NEXUS_CONTEXT}

# Nexus section
# nexus-edition=nexus-pro-edition
# nexus-features=\
#  nexus-pro-feature

# nexus.hazelcast.discovery.isEnabled=true
  • 新增 nexus.datastore.enabled=true, 新配置如下
root@nat3:/data/k8s/local/nexus3/etc# cat nexus.properties
# Jetty section
# application-port=8081
# application-host=0.0.0.0
# nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-http.xml,${jetty.etc}/jetty-requestlog.xml
# nexus-context-path=/${NEXUS_CONTEXT}

# Nexus section
# nexus-edition=nexus-pro-edition
# nexus-features=\
#  nexus-pro-feature

# nexus.hazelcast.discovery.isEnabled=true
nexus.datastore.enabled=true

启动老服务,验证数据库切换成功

  • compose 部署
docker compose up -d
  • k8s 部署副本改成 0
kubectl scale --replicas 1 deploy/nexus3 -n nat

观察日志,搜索 H2

2025-05-16 12:33:15,378+0000 INFO  [FelixStartLevel] *SYSTEM org.sonatype.nexus.datastore.DataStoreConfigurationDefaultSource - Loaded 'nexus' data store configuration defaults (Embedded H2)
2025-05-16 12:33:15,710+0000 INFO  [FelixStartLevel] *SYSTEM com.zaxxer.hikari.HikariDataSource - nexus - Starting...
2025-05-16 12:33:16,018+0000 INFO  [FelixStartLevel] *SYSTEM com.zaxxer.hikari.HikariDataSource - nexus - Start completed.
2025-05-16 12:33:16,020+0000 INFO  [FelixStartLevel] *SYSTEM org.sonatype.nexus.datastore.mybatis.MyBatisDataStore - nexus - Loading MyBatis configuration from /opt/sonatype/nexus/etc/fabric/mybatis.xml
2025-05-16 12:33:16,147+0000 INFO  [FelixStartLevel] *SYSTEM org.sonatype.nexus.datastore.mybatis.MyBatisDataStore - nexus - MyBatis databaseId: H2
2025-05-16 12:33:16,346+0000 INFO  [FelixStartLevel] *SYSTEM org.sonatype.nexus.datastore.mybatis.MyBatisDataStore - nexus - Creating schema for UpgradeTaskDAO

升级版本失败

直接替换镜像升级就完成了,然后我的数据就没了 😂, 严格按照官方文档来的哇 😂

后续

  • 云缘生镜像站暂停营业几天
  • 虽然有备份数据,但是不想回滚了,重新部署,数据存储使用 PG 吧

  •  

Caddy拦截响应处理小记

2025年5月15日 20:34

简单小记,分享一下,主要还是针对 MinIO 异常的处理,其他服务应该也类似

之前配置 MinIO:

xxxx {
        import ERR
        import LOG "/var/log/caddy/minio.log"
        @rootPath {
                path /
        }
        handle @rootPath {
                respond "EdgeONE 403 Forbidden" 403
        }
        reverse_proxy 127.0.0.1:9000
}

仅禁止访问/,且有问题使用 import ERR 兜底

(ERR) {
	handle_errors {
		redir https://dxgw-{err.status_code}.external.ysicing.net
	}
}

之前没太注意,之前这种情况下,如果 MinIO 放回 400 的话是没法拦截的。这时候需要响应匹配器来干活了

域名 {
		import LOG "/var/log/caddy/minio.log"
	    import ERR
        @rootPath {
                path /
        }
        handle @rootPath {
                respond "EdgeONE 403 Forbidden" 403
        }
        reverse_proxy 127.0.0.1::9000 {
	     		@error status 4xx
	     		handle_response @error {
 						respond "EdgeONE 451 Forbidden" 451
				}
		}
}

handle_response 块内,可以使用任何其他指令,功能还挺强大的


  •  

CodeBuddy腾讯云代码助手初体验

2025年5月13日 19:52

本文算个安利吧,目前比 trae 实在,至少不是老是排队,暂时免费使用。

CodeBuddy 是什么

腾讯云出品的代码助手插件, 支持 VSCodeJetBrains微信开发者工具

对比 Cursor

对比我用的 cursor,目前有两大优势

  • 暂时免费(Craft 对话限制 50 次/月,很容易用完的)
  • Craft 支持从用户需求转到研发需求,最后拆分成迭代执行(很早之前,就跟同事讨论过这个问题,这个应该是未来发展的趋势)

安装

插件安装教程, 安装完成后,扫码登录

使用

简单演示,空仓库如何写一个 caddy 插件

mkdir go/src/github.com/ysicing/caddy2-admin-ui
cd go/src/github.com/ysicing/caddy2-admin-ui
git init
go mod init

配置助手,默认全启用

  • 用户需求 - 研发需求

  • 研发需求 - 迭代执行

  • 迭代 1 - 迭代 n

可能问题

除写了"垃圾代码"外,偶尔不会重构代码外,Agent 执行命令提示没法获取结果,需要 ~/.zshrc 新增如下配置

[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path zsh)"

总结

用的不多,偶尔用用还行,更多的还得关注他们后续的付费计划。


  •  

ImageFlow一款更适合个人使用的图床项目

2025年5月11日 22:45

ImageFlow 是一个为现代网站和应用程序设计的高效图像服务系统。它能根据设备类型自动提供最合适的图像,并支持 WebP 和 AVIF 等现代图像格式,显著提升网站性能和用户体验。

主要特性

  • API 密钥认证:安全的 API 密钥验证机制,保护您的图片上传功能
  • 自适应图像服务:根据设备类型(桌面端/移动端)自动提供横向或纵向图片
  • 现代格式支持:自动检测浏览器兼容性并提供 WebP 或 AVIF 格式图片
  • 图片过期功能:支持设置图片过期时间,过期后自动删除(支持本地和 S3 存储)
  • 简单的 API:通过简单的 API 调用获取随机图片,支持标签过滤
  • 用户友好的上传界面:支持拖拽上传,具有暗黑模式、实时预览和标签管理功能
  • 图片管理功能:通过直观的管理界面查看、筛选和删除图片
  • 自动图像处理:上传后自动检测图像方向并转换为多种格式
  • 异步处理:图像转换在后台进行,不影响主服务
  • 高性能:优化的网络性能以减少加载时间
  • 易于部署:简单的配置和部署流程
  • 多存储支持:支持本地存储和 S3 兼容存储(如 R2, 不支持MinIO
  • Redis 支持:可选的 Redis 集成,用于元数据和标签存储,提高性能

项目地址

快速部署

使用 docker compose 快速操作

  • 镜像: soyorins/imageflow
  • 国内镜像: ccr.ccs.tencentyun.com/k7scn/imageflow
git clone https://github.com/Yuri-NagaSaki/ImageFlow && cd ImageFlow

更新配置文件

cp .env.example .env
nano .env
# 主要修改API_KEY和存储方式,想快速体验建议填写local

示例.env

API_KEY=ohji8lob1Sagoh4shizooNe9oxif9pai
STORAGE_TYPE=local
LOCAL_STORAGE_PATH=static/images
CUSTOM_DOMAIN=
MAX_UPLOAD_COUNT=20
IMAGE_QUALITY=75
WORKER_THREADS=4
SPEED=5
WORKER_POOL_SIZE=4
# Debug Mode
DEBUG_MODE=false

启动

docker compose up -d
  • 目前版本存在 panic 问题,等后续版本修复, 可以使用 soyorins/imageflow:2.1.1 版本

常见参数设置

  • API_KEY, 用于保护上传和管理接口, 推荐使用 pwgen 32 1 生成
  • IMAGE_QUALITY, WebP 转换的质量设置, 数值范围 1-100, 越高表示质量越好,文件越大
  • SPEED, 范围:0-8 0-8,0=最慢/最高质量,8=最快/最低质量

如何使用

  • 打开 IP:8686 端口 输入你在 env 设置的 API_Key

  • 上传图片, 支持选择图片的过期时间,添加标签对图片进行分类,图片会自动转换为 WebP 和 AVIF 格式

  • 当删除图片时,所有相关格式(原始、WebP、AVIF)将同时被移除

  •  

FileCodeBox:告别网盘烦恼,安全高效的文件分享神器

2025年5月9日 22:13

在日常工作生活中,处理敏感项目文件时,担心文件被第三方泄露; 使用第三方网盘时还要下载客户端(客户端有时还给你偷跑流量,美名加速),有时下载还得开会员。如果有这些问题的话,我强烈安利一款开源利器——FileCodeBox!它开源、好用、安全,完美解决文件分享的各种难题,让你轻松搞定工作和生活中的文件传输。

开源地址

  • 代码仓库 vastsa/FileCodeBox
  • 镜像地址: lanol/filecodebox
  • 国内镜像: ccr.ccs.tencentyun.com/k7scn/filecodebox

三大优势,解决分享痛点

FileCodeBox 专为文件分享的痛点设计,简单几步就能让你的分享体验焕然一新

超快传输,省时省心

速度取决于你的网络带宽

  • 无大小限制:无论是高清设计稿还是海量项目文件,统统支持,轻松上传
  • 拖拽即传:无需压缩打包,直接拖文件到页面,秒速完成上传
  • 批量分享:支持多文件同时上传和分享,项目交付、团队协作 so easy!

安全可靠,隐私无忧

  • 加密保护:分享链接全程加密,只有指定接收者才能访问,杜绝泄露风险
  • 阅后即焚:支持设置文件过期时间,自动删除,防止资料被长期留存
  • 下载控制:可限制链接使用次数或者有效期,避免文件被恶意传播,敏感资料更安心

极致便捷,随时随地

  • 无需注册:凭码取件
  • 清爽体验:界面简洁

部署简单

要求

以下任选一个就行,我推荐使用腾讯云锐驰 200M,存储使用赠送的对象存储 😄

  • 有公网 IP 的服务器
  • 内网穿透走 cloudflare tunnels

PS: FileCodeBox 也支持对象存储,这里我就不推荐 MinIO 了直接使用本地存储就行,因为这个分享服务我定位是短期临时分享或者按次永久分享。

部署

  • docker-compose.yaml
version: "3"
services:
  filecodebox:
    image: lanol/filecodebox:latest
    # image: ccr.ccs.tencentyun.com/k7scn/filecodebox
    container_name: filecodebox
    volumes:
      - /data/filecodebox:/app/data
    ports:
      - "12345:12345"
    restart: always
  • caddy
kd.012321.best {
        import LOG "/var/log/caddy/kd.log"
        reverse_proxy 10.25.123.1:12345
}

分享文件

  • 打开网页,点击"分享文件"
  • 选择或拖拽文件
  • 设置过期时间和次数
  • 获取提取码

获取文件

  • 打开网页,输入提取码
  • 点击获取
  • 下载文件或查看文本

是不是用 FileCodeBox 分享文件,简单到不可思议。整个过程无需复杂操作,接收方也不需要注册,真正“即传即得”!

管理面板

访问 /#/admin
输入管理员密码 FileCodeBox2023, 登录后请立即修改

管理文件和配置

如果需要发送私密信息,建议自建请勿使用第三方服务,避免不必要的问题

最后想说

在数据安全越来越重要的今天,FileCodeBox 不仅是一款工具,更是一种自由、安全的文件分享方式。它让分享变得高效、可控,完美适配各种场景。如果你也厌倦了网盘的限速和收费,或为敏感文件的隐私问题担忧,FileCodeBox 绝对值得一试!
快部署你的 FileCodeBox,体验前所未有的文件分享自由吧!


  •  

安利一下我最近写的两个caddy插件

2025年5月7日 22:07

我个人 Caddy 粉哈,习惯 Caddy 一梭子,从我历史博客中就可以看出来。最近写了两个 Caddy 的插件,geocngfw.

源码及镜像

源码 ysicing/dockerfiles#caddy

以下是我构建好的镜像,可以根据自己的环境拉取

  • ysicing/caddy2
  • ghcr.io/ysicing/caddy2
  • registry.cn-beijing.aliyuncs.com/k7scn/caddy2
  • ccr.ccs.tencentyun.com/k7scn/caddy2

源码构建

需要 go 环境了

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
xcaddy build \
    --with github.com/caddyserver/jsonc-adapter \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/caddy-dns/tencentcloud \
    --with github.com/caddy-dns/alidns \
    --with github.com/ysicing/caddy2-geocn \
    --with github.com/ysicing/caddy2-gfw \
    --with github.com/mholt/caddy-dynamicdns \
    --with github.com/mholt/caddy-events-exec \
    --with github.com/WeidiDeng/caddy-cloudflare-ip \
    --with github.com/xcaddyplugins/caddy-trusted-cloudfront \
    --with github.com/mholt/caddy-l4 \
    --with github.com/mholt/caddy-webdav \
    --with github.com/mholt/caddy-ratelimit

插件 geocn

  • 源码:https://github.com/ysicing/caddy2-geocn
  • 用途:识别来源 ip 是否为中国 ip,我的大部分服务都开启了这个,只针对大陆放行,甚至部分服务只针对部分省市(误判比较大,后续有需要也可以开源 😄)
@china {
		geocn 
	}
	file_server @china {
		root ./docker/example/deny
	}

上面是默认参考,正常情况下不需要调整,GeoIP 数据源来自 Hackl0us/GeoIP2-CN,支持自定义

geocn {
 georemote 你的自定义地址
}

插件 gfw

{
    order gfw before respond
}

:80 {
    gfw {
        # 基本规则配置
        block_rule ip:1.2.3.4
        block_rule url:/admin
        block_rule ua:curl
        block_rule_file /path/to/rules.txt
        ttl 24h

        # 额外安全检测(默认关闭)
        enable_extra true
    }
}

目前是所有实例共享黑名单的,命中就 1 天黑名单直接返回 403,之前想的是命中后触发 hook 执行 iptables 封禁 ip,但是容器跑的好像不太方便。

最后

大家对 Caddy 插件有什么的需求或者想法么?


  •  

轻松部署 Alist + MinIO,打造你的专属私人网盘

2025年5月6日 20:49

还在为网盘限速、空间不足而焦虑?想要一个安全、快速、完全掌控的私人网盘?今天带你一步步用 Alist 结合 MinIO,快速搭建一个高性能的私人云存储,文件管理从此自由无忧!

部署非常简单,也很适合内网私有化部署。另外这也是一个开源项目,社区灵活度特别高,对接的存储类型非常丰富,但是本文还是着重写写对接 minio。今天的音频调了几版,目前这版相关好点

什么是 Alist 和 MinIO?

  • Alist:一款开源免费的目录列表程序,支持挂载多种存储(如本地存储、云盘、对象存储等),提供简洁美观的界面,支持文件预览、下载、分享等功能。简单来说,它是你文件管理的“超级中枢”。
  • MinIO:一个高性能、分布式的对象存储服务,兼容 S3 协议,适合搭建私有云存储。相比第三方网盘,MinIO 让你完全掌控数据,安全又高效。

通过 Alist + MinIO 的组合,你可以轻松打造一个私有网盘,享受无限存储空间和极速访问体验!

Alist + MinIO 的优势

  • 多存储支持:Alist 支持 MinIO、本地存储、OneDrive、阿里云盘等多种存储方式,灵活扩展。
  • 简洁易用:Alist 界面美观直观,操作简单。
  • 高性能:MinIO 提供企业级的对象存储性能,适合大文件存储和高速访问。
  • 安全可靠:数据存储在你自己的服务器上,隐私有保障。
  • 开源免费:Alist 和 MinIO 均为开源项目,自由使用,社区活跃。

部署步骤:Alist + MinIO 一键搞定

以下以 Docker 部署为例,带你快速搭建 Alist 和 MinIO 的组合。这里就跳过 MinIO 部署相关了,之前也讲过,可以查看我之前写的文章:

准备工作

  • 准备好 MinIO 的账号即可,有存储视频资源最好不过

镜像

根据实际情况来,默认 aio 镜像已经包含本地存储缩略图 ffmpeg 和离线下载 aria2, 后面需要用的上

  • xhofe/alist:main-aio
  • 国内镜像 ccr.ccs.tencentyun.com/k7scn/alist:main-aio

创建 docker compose 文件

  • docker-compose.yml
services:
  alist:
    image: xhofe/alist:main-aio
    # image: ccr.ccs.tencentyun.com/k7scn/alist:main-aio
    container_name: alist
    ports:
      - "5244:5244"
    volumes:
      - /data/alist:/opt/alist/data # 应用程序持久化数据
      - /data/share:/opt/share # 本地存储,可选
    environment:
      - TZ=Asia/Shanghai
      - ALIST_ADMIN_PASSWORD=goxee7dieXeihu9uochoo6iquaighail
    restart: always

ALIST_ADMIN_PASSWORD 支持自定义密码,很早之前我提交的 PR😂,估计也就我一个人这么用。

启动容器

docker compose up -d

配置 caddy

caddy 配置比较简单

alist.ysicing.eu.org {
  reverse_proxy 100.90.80.2:5244
}

访问 alist

访问 Alist:在浏览器输入 http://你的服务器IP:5244 或者 caddy域名,进入 Alist 界面。

默认用户名是 admin, 密码是你配置的 ALIST_ADMIN_PASSWORD 值信息

挂载 MinIO 存储

登录 Alist,点击 管理 > 存储 > 添加

选择存储类型为对象存储

填写以下信息:

  • 挂载路径:自定义,例如 /minio。
  • Endpoint:http://minio 域名地址:9000。
  • Bucket:填写你在 MinIO 创建的存储桶名称,例如 ja。
  • Access Key 和 Secret Key:填入 MinIO 控制台生成的密钥。
  • 强制路径样式:默认勾选
  • 地区:默认留空

保存配置后,返回 Alist 主页,即可看到挂载的 MinIO 存储

可以上面的操作后就可以通过 Alist 浏览、分享 MinIO 中的文件,支持在线预览、下载等功能。

其他

官方文档

总结

通过 Alist 和 MinIO 的组合,你可以轻松搭建一个功能强大、安全可靠的私人网盘,告别存储焦虑!无论是个人文件管理还是团队协作,这个方案都能满足你的需求。快动手试试吧!


  •  

私有化部署无名杀卡牌游戏

2025年5月5日 19:52

部署非常简单,非常适合收藏,内网私有化部署。另外这是一个开源项目,灵活度比较高。

项目地址

https://github.com/libnoname/noname

镜像

可以根据自己的网络情况选择对应的镜像下载,镜像比较大, 大概 3.5G 左右。

  • hsiaoshun/noname
  • ccr.ccs.tencentyun.com/k7scn/noname

部署 compose

services:
  noname:
    image: hsiaoshun/noname
    # image: ccr.ccs.tencentyun.com/k7scn/noname
    container_name: noname
    ports:
      - '6080:80'
    restart: always

端口配置

  • 80 游戏本体网页版入口
  • 8080 WS 协议,联机大厅服务(客户端使用)

caddy 代理

示例,不建议公网跑,对带宽有点要求

sgs.ysicing.eu.org {
reverse_proxy 100.90.80.2:6080
}

联机大厅配置说明

目前只支持 windows 和安卓

注意: 结尾的/不能省略, 如果没有证书就是 ws,有证书就是 wss

其他

如果有更多兴趣的话,可以看看无名杀懒人包。


  •  

Debian常用初始化流程

2025年5月5日 14:50


在搭建 k3s 轻量级 Kubernetes 集群时,Debian 系统因其稳定性和灵活性成为首选。然而,Debian 默认配置可能无法满足 k3s 的需求,需要通过初始化优化系统设置。本文将分享一套针对 k3s 环境的 Debian 初始化方案,涵盖基础包安装、系统配置和防火墙规则,仅供参考。

安装基础包

以下命令安装 k3s 集群所需的基础工具,保持系统轻量:

export DEBIAN_FRONTEND=noninteractive
apt update -qq
apt remove -y -qq ufw lxd lxd-client lxcfs lxc-common
apt install --no-install-recommends --no-install-suggests -y -qq nfs-common iptables conntrack jq socat bash-completion open-iscsi rsync ipset ipvsadm htop net-tools wget psmisc git curl nload ebtables ethtool procps

配置系统

配置 ssh

修改 ssh 端口,设置密钥登录,禁用密码登录。这些比较常见,这里就不细说了。

更新内核

之前好像也写过,通常我都是使用最新内核,仅供参考.(通常也会踩坑比较多)

curl https://c.ysicing.net/oss/scripts/debian-upcore.sh | bash
# 或者
apt install -t bookworm-backports linux-image-amd64 -y

配置 system 相关

调整 Systemd 的资源限制和日志设置

mkdir -pv /etc/systemd/system.conf.d
cat > /etc/systemd/system.conf.d/30-k8s-ulimits.conf <<EOF
[Manager]
DefaultLimitCORE=infinity
DefaultLimitNOFILE=100000
DefaultLimitNPROC=100000
EOF

mkdir -pv /etc/systemd/journald.conf.d /var/log/journal

cat > /etc/systemd/journald.conf.d/95-k3s-journald.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 最大占用空间 2G
SystemMaxUse=2G
# 单日志文件最大 100M
SystemMaxFileSize=100M
# 日志保存时间 1 周
MaxRetentionSec=1week
# 禁止转发
ForwardToSyslog=no
ForwardToWall=no
EOF

systemctl daemon-reload
systemctl restart systemd-journald

cat > /etc/modules-load.d/10-k3s-modules.conf <<EOF
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF

systemctl daemon-reload
systemctl restart systemd-modules-load

配置防火墙规则

提示:8.8.8.8 为示例白名单 IP,请替换为实际 IP,搭配rc.local

  • /data/scripts/iprule.sh
#!/bin/bash
iptables -I INPUT -s 8.8.8.8 -j ACCEPT
iptables -I INPUT -p udp -j ACCEPT
iptables -I INPUT -i lo -j ACCEPT
iptables -I INPUT -i tailscale0 -j ACCEPT
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -I INPUT -s 172.16.0.0/12 -j ACCEPT
iptables -I INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -I INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp -j DROP
iptables -A OUTPUT -j ACCEPT
iptables -A INPUT -j DROP

防火墙规则没考虑使用 iptables-save 等保存恢复,而是每次开启时重新配置。

总结

通过以上步骤,我们完成了一套针对 k3s 环境的 Debian 系统初始化,优化了网络、资源限制和安全性。你可以直接使用以下脚本一键初始化

curl https://c.ysicing.net/oss/scripts/init.sh

  •  

Debian 双栈网络时开启 IPv4 优先(音频版)

2025年5月3日 23:32

PS: 用 AI 生成的图老是不合法微信封面的比例,放到文尾。本文也提供音频版, 欢迎订阅我的微信公众号。

在如今的网络世界,IPv6 正在逐渐普及,但 IPv4 依然是许多场景的“老大哥”。如果你用的是 Debian 系统,并且身处 IPv4 和 IPv6 共存的双栈网络环境,可能会发现系统默认优先使用 IPv6——这在某些情况下并不理想,比如某些服务只支持 IPv4,或者 IPv6 连接不稳定。今天,我们就来聊聊如何在 Debian 上实现 IPv4 优先,甚至在需要时完全禁用 IPv6。跟着这篇教程,轻松搞定网络配置!

为什么需要调整网络优先级?

先来点背景知识:双栈网络指的是设备同时支持 IPv4 和 IPv6 协议栈。现代操作系统(如 Debian)和浏览器通常默认优先使用 IPv6,只有当 IPv6 连接失败时才会“退而求其次”用 IPv4。这听起来很智能,但在实际场景中可能会遇到问题:

  • 服务兼容性:某些老旧服务或内网应用只支持 IPv4,IPv6 优先可能导致连接失败
  • 网络性能:部分网络环境下,IPv6 的延迟或稳定性不如 IPv4
  • 特殊需求:比如开发测试时,你可能希望强制使用某一种协议

所以学会调整 IPv4 和 IPv6 的优先级,或者在极端情况下禁用 IPv6,是每个 Debian 用户的“进阶技能”。下面,我们一步步教你搞定!

让 IPv4 优先:修改 gai.conf 文件

Debian 系统中,/etc/gai.conf 文件控制了 getaddrinfo 函数的行为,这个函数决定了系统如何选择 IPv4 或 IPv6 地址。默认情况下,IPv6 优先,但我们可以通过简单修改让 IPv4 站到“C 位”。

修改步骤

打开终端,输入以下命令编辑 /etc/gai.conf

#precedence ::ffff:0:0/96  100

去掉 # 号,修改为:

precedence ::ffff:0:0/96  100

保存并退出。

懒人福利:如果你不想手动编辑,可以直接用这条命令一键搞定:
bash

sed -i 's/#precedence ::ffff:0:0\/96  100/precedence ::ffff:0:0\/96  100/' /etc/gai.conf

测试效果

配置完成后,用 curl 命令测试一下:

curl ip.sb

也可以使用

# 查询本机外网IPv4地址
curl 4.ipw.cn

# 查询本机外网IPv6地址
curl 6.ipw.cn

# 测试网络是IPv4还是IPv6访问优先(访问IPv4/IPv6双栈站点,如果返回IPv6地址,则IPv6访问优先)
curl test.ipw.cn

如果返回的是类似 6.6.6.6 的 IPv4 地址,恭喜你,IPv4 优先已生效!如果返回的是类似 2001:db8::2 的 IPv6 地址,检查是否正确保存了配置。

原理

::ffff:0:0/96 是 IPv4 地址在 IPv6 协议中的映射范围,设置其优先级为 100(高于默认 IPv6 的优先级),系统就会优先选择 IPv4 地址。

特殊场景:强制 IPv6 优先

有些朋友可能有“奇特”需求,比如测试 IPv6 环境或某些服务明确要求 IPv6 优先。别担心,我们也可以反向操作!

同样编辑 /etc/gai.conf, 在文件末尾添加以下两行:

label 2002::/16    1
label 2001:0::/32   1

保存退出,或者用命令一键添加:
bash

echo -e "label 2002::/16    1\nlabel 2001:0::/32   1" | sudo tee -a /etc/gai.conf

原理

2002::/162001:0::/32 是常见的 IPv6 地址段,设置它们的 label 优先级为 1,确保系统优先选择这些 IPv6 地址。IANA 目前分配的公网 IPv6 地址还未覆盖到 3000:0000::/4,所以这招基本万无一失

(这个未测试过,仅供参考)

极端情况:完全禁用 IPv6

如果你的网络环境压根不需要 IPv6,或者 IPv6 总给你添乱,可以直接禁用它。以下是禁用 IPv6 的方法,适合“断舍离”爱好者。
编辑 /etc/sysctl.conf 文件:

net.ipv6.conf.all.disable_ipv6 = 1
# 禁用eth0的ipv6
net.ipv6.conf.eth0.disable_ipv6 = 1

结语

通过简单的配置文件调整,你就可以在 Debian 双栈网络中自由掌控 IPv4 和 IPv6 的优先级,甚至彻底禁用 IPv6。无论是提升网络兼容性、优化性能,还是满足特定需求,这些技巧都能让你事半功倍!


  •  

Debian 12 解决 /etc/rc.local 开机启动问题

2025年5月3日 06:59

在 Debian 12(以及 Debian 9 及以上版本)中,/etc/rc.local 是配置开机自启动脚本的传统方式,但默认未启用,导致自定义脚本无法自动运行。本文将详细指导你在 Debian 12 上启用和配置 /etc/rc.local,步骤同样适用于 Debian 9 Stretch、10 Buster 和 11 Bullseye

问题背景:rc.local 为什么不生效?

Debian 9 起采用 systemd 作为初始化系统,传统的 /etc/rc.local 默认不生效。尽管系统内置了 rc-local,但默认处于禁用状态:

root@debian:~$ systemctl status rc-local.service
○ rc-local.service - /etc/rc.local Compatibility
     Loaded: loaded (/lib/systemd/system/rc-local.service; static)
    Drop-In: /usr/lib/systemd/system/rc-local.service.d
             └─debian.conf
     Active: inactive (dead)
       Docs: man:systemd-rc-local-generator(8)

以下是默认的 rc-local.service 配置,表明它会在 /etc/rc.local 可执行时自动拉起:

root@docker:~$ systemctl cat rc-local.service
# /lib/systemd/system/rc-local.service
#  SPDX-License-Identifier: LGPL-2.1-or-later
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

# /usr/lib/systemd/system/rc-local.service.d/debian.conf
[Unit]
# not specified by LSB, but has been behaving that way in Debian under SysV
# init and upstart
After=network-online.target

# Often contains status messages which users expect to see on the console
# during boot
[Service]
StandardOutput=journal+console
StandardError=journal+console

解决步骤:启用 /etc/rc.local

以下步骤助你快速启用 /etc/rc.local,实现开机脚本自动运行

创建 /etc/rc.local 文件

默认没有 /etc/rc.local,我们需要手工添加一个 /etc/rc.local 文件:

cat <<EOF >/etc/rc.local
#!/bin/bash
# 这是一个示例 rc.local 文件
# 在这里添加你的开机执行命令
# 示例:启动一个自定义脚本
# /path/to/your/script.sh
exit 0
EOF

设置可执行权限

确保文件具有可执行权限

chmod +x /etc/rc.local

启用并立即启动 rc-local 服务

启动 rc-local 服务,此时可能会弹出警告,可直接忽略

systemctl enable --now rc-local

检查服务状态, 状态显示 active (exited) 表示服务已运行

root@docker:~$ systemctl status rc-local.service
● rc-local.service - /etc/rc.local Compatibility
     Loaded: loaded (/lib/systemd/system/rc-local.service; static)
    Drop-In: /usr/lib/systemd/system/rc-local.service.d
             └─debian.conf
     Active: active (exited) since Fri 2025-05-02 18:21:26 EDT; 3s ago
       Docs: man:systemd-rc-local-generator(8)
    Process: 333116 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
        CPU: 4ms

May 02 18:21:26 docker systemd[1]: Starting rc-local.service - /etc/rc.local Compatibility...
May 02 18:21:26 docker systemd[1]: Started rc-local.service - /etc/rc.local Compatibility.

添加自定义开机脚本

在 /etc/rc.local 的 exit 0 前添加命令。例如:

#!/bin/sh -e
#
# rc.local
#
# By default this script does nothing.
/data/scripts/ip.sh || true
exit 0

注意:使用绝对路径(如 /data/scripts/ip.sh),确保脚本有执行权限。|| true 可防止脚本失败影响。

测试配置

重启系统

总结

通过以上步骤,你可以在 Debian 9 及以上版本快速启用 /etc/rc.local,实现开机自动运行脚本。尽管 systemd 提供更现代的方案,rc.local 仍适合简单任务


  •  

深入浅出 MinIO:身份管理与权限配置实战

2025年5月2日 01:21

前面刚刚讲了如何搭建 MinIO,本文趁热打铁手把手教你如何配置 MinIO 权限配置。对于略懂 MinIO 的用户,配置权限可能是个挑战:如何安全地让别人读取存储内容,但不能列出所有存储桶或文件列表?或者让某个存储桶的内容可以列出? 本文将深入讲解 MinIO 的身份管理和权限配置,聚焦存储桶权限(private、public、custom)的区别和 匿名访问 的应用,通过清晰的场景示例,教你实现安全分享,同时保护数据

MinIO 身份管理基础

MinIO 的身份管理负责用户认证和授权,默认使用内置身份提供者(IDP)。核心概念包括:

  1. 用户(User)
    用户通过 Access Key(用户名)和 Secret Key(密码)访问 MinIO,可用命令行工具 mc 或 Web 控制台管理。
  2. 服务账号(Service Account)
    服务账号是为应用程序设计的专用凭证,无法登录控制台,但可通过 API 访问资源,适合自动化脚本或服务集成。
  3. 策略(Policy)
    JSON 格式的策略定义用户、服务账号或匿名访问对存储桶(Bucket)和对象(Object)的权限,基于 AWS S3 语法。
  4. 匿名访问(Anonymous Access)
    允许未认证用户(无 Access Key)通过 URL 或 API 访问特定资源,需通过存储桶权限配置。

用户组:可通过 mc admin group 批量管理用户权限,本文不展开。

我们的目标是:安全地让匿名用户或服务账号读取特定内容,限制列出存储桶或文件列表,或有选择地允许列出某个存储桶的内容。

准备工作

  1. 确保 MinIO 运行:假设 MinIO 部署在 http://localhost:9000,管理员账号为 homes4,密码为 aiy0ooCheephai0ohNahmu3Aijee6eiv
  2. 安装 mc 工具:下载 MinIO 客户端(mc),用于配置权限(支持 Windows、Mac、Linux)。
  3. 配置 mc
mc alias set homes4 http://localhost:9000 homes4 aiy0ooCheephai0ohNahmu3Aijee6eiv
Added `homes4` successfully.

准备好后,我们开始配置权限!

PS:命令行方式和可视化操作效果是一样的,下文会穿插着来,但是主要还是以可视化 web 操作为主

存储桶权限:Private、Public 和 Custom

MinIO 的存储桶权限控制匿名访问行为,分为 privatepubliccustom 三种模式,可通过 mc anonymous 命令设置。以下是它们的区别

Private(私有)

  • 定义:禁止所有匿名访问,仅允许认证用户或服务账号(有 Access Key 和策略授权)访问。
  • 适用场景:保护敏感数据,如内部文档、用户数据。
  • 效果:匿名用户访问存储桶或对象时,返回 403 Forbidden
  • 配置:mc anonymous set none homes4/web

Public(公开)

注意:风险较高,容易暴露所有文件,慎用。(我个人基本不用)

  • 定义:允许匿名用户访问,权限包括:

    • download:只读(s3:GetObject)
    • upload:只写(s3:PutObject)。
    • public:读写均可。
  • 适用场景:分享公开资源,如网站静态文件、开源软件。

  • 配置(只读):mc anonymous set download homes4/web

  • 效果:匿名用户可通过 URL(如 http://localhost:9000/web/file.jpg)读取对象,可能列出文件列表(若未限制)。

Custom(自定义)

推荐用

  • 定义:通过 JSON 策略精确控制匿名访问权限,如限制特定路径或操作。
  • 适用场景:部分公开,如只分享某个文件夹,或禁止列出文件列表。
  • 配置:见下文场景示例。
  • 效果:灵活性最高,匿名用户只能执行策略允许的操作。

存储桶权限区别总结

模式 匿名访问权限 适用场景 配置命令
Private 禁止匿名访问 敏感数据 mc anonymous set none
Public 读、写或读写(看设置) 公开资源 mc anonymous set download upload/public
Custom 自定义(JSON 策略) 部分公开、精确控制 mc anonymous set-json

实战:安全分享存储内容

通过一个最常见的场景,教你如何:

  • 让匿名用户只读特定文件,禁止列出存储桶或文件列表。

此外,还会写如何用服务账号为应用程序提供类似权限。

新建存储桶

先创建一个存储桶,默认创建的存储桶都是私有权限

root@docker:~$ mc mb homes4/cli
Bucket created successfully `homes4/cli`.
root@docker:~$ mc ls homes4
[2025-05-01 11:26:11 EDT]     0B cli/
[2025-05-01 11:23:57 EDT]     0B ddd/
[2025-05-01 10:38:53 EDT]     0B homes4/
[2025-05-01 11:29:06 EDT]     0B web/

场景:只读特定文件,禁止列出存储桶或文件列表

需求:存储桶 web 包含 public/photo.jpg 和 private/secret.pdf。想让匿名用户只读 photo.jpg,但不能列出 web 桶中 的文件列表,也不能访问其他文件或存储桶

步骤:

设为 Private(默认安全)

mc anonymous set none homes4/web

创建自定义策略:只允许匿名读取 public/photo.jpg

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["s3:GetObject"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::web/public/photo.jpg"],
      "Principal": "*"
    }
  ]
}
  • s3:GetObject:允许读取对象
  • Resource:精确到 photo.jpg, 例如你想某个目录读写 arn:aws:s3:::web/public/*
  • Principal: "*":表示匿名用户
  • s3:ListBucket:禁止列出文件列表

应用策略

mc anonymous set-json custom.json homes4/web

控制台可以直接编辑存储桶的 Access Policy,改成 Custom,内容和上面一致

查看策略

root@docker:~$ mc anonymous get-json homes4/web
{
 "Statement": [
  {
   "Action": [
    "s3:GetObject"
   ],
   "Effect": "Allow",
   "Principal": {
    "AWS": [
     "*"
    ]
   },
   "Resource": [
    "arn:aws:s3:::web/public/photo.jpg"
   ]
  }
 ],
 "Version": "2012-10-17"
}

效果

  • 匿名用户可通过 http://localhost:9000/web/public/photo.jpg 下载 photo.jpg。
  • 其他访问都是 403

服务账号:为应用程序配置相同权限

需求:为应用程序(如网站后端)提供只读 public/photo.jpg 的权限,类似上述场景,但通过服务账号实现

步骤:

创建用户(服务账号需绑定到用户):

密码长度需要 8-40

mc admin user add homes4 app1user app1pass

web 可视化操作,policy 那里随便选个小权限的,后面需要调整

创建服务账号:为 app1user 生成服务账号,绑定 custom.json 策略

mc admin user svcacct add homes4 app1user --access-key svc1 --secret-key svc1pass --policy custom.json

可视化操作创建服务状态,凭证信息会随机生成,且只显示一次

策略信息只能在生成 access key 后才能编辑操作

实用技巧:兼顾安全与便利

  • 优先 Custom 模式:比 public 安全,精确控制分享内容。
  • 避免 Public 模式:除非真想完全公开,否则可能暴露所有文件。
  • 检查权限:定期用 mc anonymous get-json homes4/web 确认存储桶权限
  • 随机存储桶名:用随机名,降低被猜到风险
  • 用预签名 URL 临时分享:生成带有效期的链接,过期失效:
# 分享下载链接,下载速度限制10MB/s有效期7天
mc share download --limit-download 10MB homes4/web/private/secret.pdf

总结

MinIO 的权限配置简单而灵活,用服务账号拥有某个存储桶的只读权限就行了。


  •  

超简单!5分钟用群晖搭建 MinIO + Caddy 对象存储

2025年5月1日 18:12

对象存储和 Web 服务是开发者必备工具。MinIO 凭借高性能和 S3 兼容性成为存储领域的“顶流”,Caddy 则以自动 HTTPS 和极简配置深受开发者喜爱。结合 Docker Compose,只需 5 分钟,你就能搭建一个安全、高效的对象存储服务!本文手把手教你部署 MinIO + Caddy。

前提要求

  • 群晖/大盘鸡(大硬盘 VPS):运行 MinIO 服务。
  • 大带宽机器(如腾讯云锐驰 200):运行 Caddy,代理 MinIO 服务。
  • 组网服务(如 Tailscale/EasyTier):确保内网互联互通

我的网络环境通过组网服务实现全链路打通,家里的群晖与腾讯云锐驰无缝互联,Caddy 代理内网 MinIO 服务,借助锐驰大带宽对外提供高效访问。

为啥选择 MinIO + Caddy

  • MinIO:开源、S3 兼容、支持分布式存储,轻松应对海量数据。
  • Caddy:自动 HTTPS、配置简洁,专为高并发优化,支持丰富插件。
  • Docker Compose:一键部署多容器,省时省力。

组合优势:Caddy 为 MinIO 提供安全访问和负载均衡,Docker Compose 确保部署简单,完美适配静态文件托管、API 服务或私有云存储。

5 分钟快速部署

根据需求,可选择在同一机器上部署或分布式部署。我因跨机器需求,选择分布式部署。

部署 MinIO

群晖已支持 Docker Compose,通用配置如下:

  • docker-compose.yaml
version: "3"
services:
  minio:
    image: bitnami/minio:2025
    # image: ccr.ccs.tencentyun.com/k7scn/minio:2025
    container_name: minio
    restart: always
    environment:
      - MINIO_ROOT_USER=homes4
      - MINIO_ROOT_PASSWORD=aiy0ooCheephai0ohNahmu3Aijee6eiv
      - MINIO_DEFAULT_BUCKETS=homes4
    ports:
      - '9000:9000'
      - '9001:9001'
    volumes:
      - '/volume1/docker/minio/data:/bitnami/minio/data'

注意:可能遇到目录权限问题,可运行以下命令解决:
chmod 777 /volume1/docker/minio/data -R

访问 MinIO 管理界面

在浏览器输入 http://NAS_IP:9001http://域名:9001,进入 MinIO 登录页面,使用 MINIO_ROOT_USERMINIO_ROOT_PASSWORD 登录。

安装客户端

提供 Linux/amd64 的 mc 客户端下载链接:

https://c.ysicing.net/oss/tiga/linux/amd64/mc

或从官网获取最新客户端 Install mc

部署 Caddy

  • docker-compose.yaml
services:
  caddy:
    image: ysicing/caddy2
    # image: ccr.ccs.tencentyun.com/k7scn/caddy2
    container_name: caddy
    restart: always
    # 可选host或者端口映射
    network_mode: host
    volumes:
      - '/data/caddy/cfg:/etc/caddy'
      - '/data/caddy/data:/data'
      - '/data/caddy/config:/config'
      - '/data/caddy/log:/var/log/caddy'

此 Caddy 镜像为我的定制版,内置以下常用插件:

xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/caddy-dns/tencentcloud \
    --with github.com/caddy-dns/alidns \
    --with github.com/caddy-dns/dnspod \
    --with github.com/ysicing/caddy2-geocn \
    --with github.com/mholt/caddy-l4 \
    --with github.com/mholt/caddy-ratelimit

Caddy 配置

配置文件位于 /data/caddy/cfg,目录结构如下:

/data/caddy/cfg# tree
.
├── Caddyfile
├── load.sh
└── site
    ├── cr.caddy
    ├── dev.caddy
    ├── hub.caddy
    ├── http.caddy
    └── minio.caddy

Caddyfile 示例

(LOG) {
	log {
		output file "{args[0]}" {
			roll_size 50M
			roll_uncompressed
			roll_local_time
			roll_keep 3
			roll_keep_for 7d
		}
		format json
	}
}

(COMCFG) {
	encode zstd gzip
}

(ERR) {
	handle_errors {
    	# 异常重定向
		redir https://dxgw-{err.status_code}.caddy.local
	}
}

{
	debug
	# admin off
}

(TLS) {
tls {
  dns tencentcloud {
    secret_id AKID***
    secret_key CH85***
  }
}
}

import /etc/caddy/site/*.caddy

MinIO 配置

minio.caddy

域名 {
	import ERR
    # 如果是内网域名可以设置import TLS开启dns签发证书
    # import TLS
    import LOG "/var/log/caddy/minio.log"
	@rootPath {
		path /
	}
	handle @rootPath {
		respond "EdgeONE 451 Forbidden" 451
	}
    # 内网minio地址
    reverse_proxy 100.90.80.2:9000
}

同理,minio 控制台也是一样,通常控制台不对外开放,仅限内网访问。

minio-api.caddy

域名 {
	import ERR
    # 如果是内网域名可以设置import TLS开启dns签发证书
    # import TLS
    import LOG "/var/log/caddy/minio-api.log"
    @denied not remote_ip 192.168.1.0/24
    respond @denied "Access Denied" 403
    # 内网minio api地址
    reverse_proxy 100.90.80.2:9001
}

重新加载配置

curl "http://localhost:2019/load" -H "Content-Type: text/caddyfile" --data-binary @Caddyfile

使用 MinIO

配置 MinIO 客户端(mc)以访问服务:

# 内网
mc alias set home http://100.90.80.2:9000 homes4 aiy0ooCheephai0ohNahmu3Aijee6eiv
# 外网
mc alias set home https://域名 homes4 aiy0ooCheephai0ohNahmu3Aijee6eiv

更多场景可结合 restic,rclone,下载服务

写在最后

通过 MinIO 和 Caddy 的组合,你可以快速搭建一个高性能、安全的对象存储服务。本文提供的配置仅供参考,MinIO 还有更多玩法等待探索!


  •  

五一大盘大带宽物理服务器活动推荐

2025年4月30日 09:39

之前,也有小伙伴让我推荐几家物理服务器(后面简称杜甫), 趁着五一假期有活动,推荐两家我都在用的,各有优势,但是活动期价格会有优惠。

物语云

优点

  • 工单响应速度快
  • 有 DDoS 攻击防护
  • 大带宽流量套餐/上行限速的不限流量套餐(账单日可互换)
  • 测试不满意满足条件可退款

不足

  • 多台机器暂不支持组内网
  • 暂不支持 ipv6
  • 暂时只支持国内
  • 只支持操作系统安装

目前活动

立减优惠码 Event8259

物语云计算物理机活动:双路铂金物理机600G防护399/月起。
🎉限时立减100循环优惠码:
Event8259
※优惠码使用流程:登录账号后选择对应产品,在下单处点击“我有优惠码”之后填入。

硬件配置:
物理服务器|NVMe SSD|资源完全独享|自助管理面板
CPU:双路铂金Platinum8259CL 48核96线程
内存:128G RECC DDR4
硬盘:1TB NVMe SSD

网络规格:
以下四种网络规格可选,价格相同:
 - 浙江宁波/电信/50Mbps独享/100G防护/不限流量
 - 湖北十堰/电信/50Mbps独享/600G防护/不限流量
 - 浙江宁波/移动/50Mbps独享/10G防护/不限流量
 - 浙江宁波/电信/500Mbps流量计费/100G防护/双向2TB

优惠活动:
销售价:1150/月 优惠价:499/月
活动价:399/月,循环优惠,续费同价。

※上述产品均为独享带宽,并非“峰值”、“共享”带宽,可7x24小时随时跑满,拒绝带宽竞技场!

<服务协议与退款>
云服务器产品 24 小时内上行方向使用不超过30GB流量均支持退款,
物理服务器产品 24 小时内上行方向使用不超过100GB流量均支持退款,每用户每月最多退款 1 次。

购买链接 物语云杜甫

测评

具体可以参考 https://www.nodeseek.com/post-303956-1,带宽是可以长时间跑满的。

狗云

多年资深狗云老用户了,目前我只用他们家的 KC 杜甫、重庆联通杜甫

优点

  • 相比较其他杜甫首发优惠力度很大
  • 预购活动多
  • 香港大带宽流量套餐
  • 支持多台机器组网
  • 支持 ipv6, 掩码 /64
  • 安装系统支持种类多
  • 支持快递硬盘

缺点

  • 只支持工单响应(可以 PY 德克狗老板)
  • 杜甫 VNC 需要工单才能开,且有时间限制(每次半小时,记得不太清了)
  • 重装每小时限制一次
  • 需要实名

目前活动

预售活动

预售活动力度大些,折扣也比较高, 走 aff 成功绑定后返利一半

预售地址 二代铂金服务器预售

主要说一下网络规则,支持切换每次手续费 20, 推荐优化线路,优化线路可以附加国际线路,但是不支持附加精品线路

网络规格:
以下三种网络规格可选,价格相同:
 - 精品线路 75 Mbps, 额外附加20元/个/月
 - 优化线路  750 Mbps,额外附加15元/个/月
 - 国际线路  1000 Mbps,额外附加10元/个/月
 - 额外附加高防IP200元/个/月

五一 · 劳动节促销

活动一:
折扣码“51”,新开弹性云7折,新开经典云(特价机除外)8折。
折扣码“jian100”,新开独立服务器优惠100元。

活动二:
5月1日-5月5日,单笔充值每满100元送10元。

活动三:
5月1日-5月5日,幸运大转盘每日抽取5折码,流量,余额等奖品。

活动四:
二代铂金服务器预售:https://ds.dogyun.com/server/preorder

香港-KC物理服务器邮件硬盘添加活动将在5月10日开始接收

测评 KC

具体可以参考 https://www.nodeseek.com/post-314492-1

其他 CQA

他们家的老款绝版 CQA 月付 200 还是挺不错的,稳定的很,可以收一收。

最后

祝各位老板五一假期玩的开心。


欢迎关注我的微信公众号
  •  

沉迷塔防的乐趣:推荐Kingdom Rush系列游戏

2025年4月28日 20:41

作为一名开发者,我下班后除了写写代码、折腾技术,也喜欢通过游戏放松一下。塔防类游戏是我的最爱,尤其 Ironhide Game Studio(铁皮) 的 Kingdom Rush 系。这系列塔防游戏以扎实的玩法、精致的设计和恰到好处的挑战性,俘获了无数玩家的心。今天,我想向大家安利这个系列,希望你也能爱上它的独特魅力!

Kingdom Rush 系列简介

We make the games we'd love to play!

Steam 直达

Kingdom Rush 系列始于 2011 年的 Flash 游戏《Kingdom Rush》(早期我记得叫 皇家守卫军, 现在普遍翻译为 王国保卫战),随后推出了多款续作,覆盖 PC、移动端(iOS/Android)和主机平台,核心玩法保持一致,同时不断创新。目前包括以为五代作品(衍生品不算):

-《Kingdom Rush》(2011):初代经典,奠定系列基础。
-《Kingdom Rush: 前线》(2013):地图更复杂,敌人多样。
-《Kingdom Rush: 起源》(2014):优化塔升级,精灵主题, 节奏感比较好。
-《Kingdom Rush: 复仇》(2018):扮演反派,暗黑风格暗黑风格搭配创新塔种, 我最推荐。
-《Kingdom Rush 5: 联盟》(2024):双英雄机制,通关难度适中,兼顾新老玩家。

游戏设定在一个奇幻世界,玩家扮演指挥官,通过建造防御塔、操控英雄和使用魔法,抵御兽人、巨魔、恶魔等多样化敌人的进攻。核心玩法直观易上手:沿固定路线部署防御塔,合理分配资源,阻挡敌人前进。防御塔分为弓箭塔、兵塔、魔法塔和炮塔四类,每种塔可升级并解锁独特技能,如弓箭塔的连发箭、魔法塔的闪电链,策略性极强。
此外,系列引入了英雄系统,每位英雄拥有独特技能,例如弓箭手擅长远程狙击,骑士适合近战肉搏。玩家需操控英雄移动,堵截漏网敌人或支援薄弱防线。魔法技能(如陨石雨、援军召唤)则为战斗增添变数,关键时刻往往能逆转局势。特别值得一提的是,《复仇》的凤凰能喷射烈焰清场,《联盟》的双龙组合则带来史诗级输出,令人印象深刻。

为什么推荐 Kingdom Rush?

Kingdom Rush 系列由* Ironhide Studio* 精心打造,品质始终如一。以下是我推荐它的几大理由:

难度平衡,适合各水平玩家

关卡设计用心,普通模式新手友好,挑战模式(如老兵模式,即高难度关卡)则满足硬核玩家。敌人波次与资源分配恰到好处,既不无脑也不虐心。

高可玩性,玩法丰富多样

每作包含十余主线关卡,外加挑战关和隐藏关,内容充实。防御塔与英雄的多样组合,让每关都有新鲜玩法,重复游玩也不乏味。

碎片时间友好,单机体验纯粹

游戏无需联网,随时暂停,适合忙碌的玩家抽空玩一把。单机设计无内购压力,带来纯粹的游戏乐趣。

性价比高,物超所值

游戏在 Steam 和移动端定价多在几十元,经常打折。DLC 内容丰富,诚意十足,堪称塔防游戏的良心之作。

我的个人体验

高中时,我在 4399 平台接触到初代 Kingdom Rush,被它精致的画面和紧凑的节奏深深吸引。熬夜尝试不同防御塔组合,解锁隐藏关卡的成就感让我乐此不疲。后来,系列续作不断推出,我始终保持热情。2024 年 Kingdom Rush 5: 联盟 发布后,我迫不及待挑战老兵模式。双英雄机制让战斗更灵活,但也略微降低了通关难度。相比之下,我更偏爱《复仇》的暗黑风格和高难度设计,每次通关都充满成就感,尽管偶尔会被棘手的关卡“虐”得抓狂。

写在最后

Kingdom Rush 系列适合各类型玩家,无论是喜欢策略的硬核玩家,还是想休闲娱乐的轻度玩家,都能找到乐趣。作为技术人,我欣赏它在关卡设计和技能平衡上的用心。如果你喜欢塔防,或想找款轻松耐玩的单机游戏,不妨试试 Kingdom Rush。一旦上手,可能就停不下来!


  •  

在群晖上使用 Docker 部署 Proxmox Backup Server

2025年4月27日 20:45

在群晖上使用 Docker 部署 Proxmox Backup Server

Proxmox Backup Server(后续简称 PBS) 是 PVE 容器、虚拟机的备份解决方案,支持增量、重复数据消除备份,可以节省存储空间,同时支持加密和完整性校验。

PBS 官方提供了 iso 格式的镜像,同时社区也有开源的 Docker 镜像的部署方式,为了在群晖等 NAS 上部署方便,本文使用 Docker 的方式进行部署,项目地址:https://github.com/ayufan/pve-backup-server-dockerfiles

镜像:

  • ayufan/proxmox-backup-server:latest
  • ccr.ccs.tencentyun.com/k7scn/proxmox-backup-server:latest (国内镜像)

部署 PBS

使用 Docker 或者 Docker Compose 方式部署都可以。方便起见,统一使用 docker compose 方式部署, 不管群晖还是飞牛都适用。

安装配置 PBS

参加官方的 compose 示例,可以配置如下:

  • docker-compose.yaml
services:
  pve-backup-server:
    image: ayufan/proxmox-backup-server:latest
    # image: ccr.ccs.tencentyun.com/k7scn/proxmox-backup-server:latest
    container_name: pbs
    ports:
      - "8007:8007"
    volumes:
      - /data/pve/pbs/etc:/etc/proxmox-backup
      - /data/pve/pbs/log:/var/log/proxmox-backup
      - /data/pve/pbs//lib:/var/lib/proxmox-backup
      - /data/pve/pbs/data:/backups
    tmpfs:
      - /run
    restart: always

唯一需要关注的是

  • /data/pve/pbs/data:/backups 存储你的备份数据的,所属目录空间需要大一些

配置 PBS

在启动容器后,访问 https://<ip>:8007/ 端口即可进行登录,默认的用户名是 admin,密码是 pbspbs,选择 Proxmox Backup authentication server 进行登录,可把语言切换成中文,证书问题可忽略

配置备份存储

配置存储路径

首次登录是没有配置存储的,在 数据存储中添加数据存储,将刚才映射的 /backups 目录作为存储路径

配置用户权限

默认情况下,新用户和 API 令牌没有任何权限。给用于备份的 admin 用户添加备份路径的访问权限

获取 PBS 指纹信息

指纹用于在 PVE 中添加备份时进行认证

在 PBS 仪表盘里显示指纹备用

配置 PVE

在 PVE 的数据中心-存储中选择添加 Proxmox Backup Server,输入认证信息和指纹;Datastore 为 Proxmox Backup Server 的数据存储的名称,如 local, 相关参数都是上面步骤配置的

验证备份是否可用

在 PVE 的数据中心-备份中添加备份计划,按需添加,添加完成后选择现在运行即可开始备份

在 PBS 处验证看是否有备份数据

End

到这里 PVE 系列教程结束了,新买的杜甫应该算折腾好了,趋向于稳定了。后面会陆续写些之前工作积攒的一些小技巧,吐槽一下 Caddy 新版本 libdns 变更真是一个特别大的破坏性更新。


  •  

Proxmox VE 添加监控

2025年4月26日 20:32

Proxmox VE 添加监控

PVE 支持添加 InfluxDB 或者 Graphite 作为指标数据的存储;在添加配置后,PVE 会主动上报相关监控数据,用于记录和监控 PVE 的状态

效果图

使用 InfluxDB 和 Grafana 对 PVE 进行监控,效果如图:

本文适用 8.x 版本,仅在 PVE8.3、PVE8.4 版本测试过。

安装配置 InfluxDB

当前 PVE 版本需要使用的 InfluxDB v2 版本,使用 Flux 语法进行查询。方便操作,本次仅提供 compose 部署方式,k8s 部署也是类似比较简单。

  • docker-compose.yaml
services:
  influxdb:
    image: bitnami/influxdb:2
     # image: ccr.ccs.tencentyun.com/k7scn/influxdb:2
    container_name: influxdb
    environment:
      - INFLUXDB_ADMIN_USER_PASSWORD=Cha3ie7gahthooyeech1xohgaeyax7Gi
      - INFLUXDB_ADMIN_USER_TOKEN=Eing5yaew6ujoo9ohd3saeH6neeshei3
      - INFLUXDB_USER_ORG=proxmox
      - INFLUXDB_USER_BUCKET=proxmox
      - INFLUXDB_USER=proxmox
      - INFLUXDB_USER_PASSWORD=Ao2eeGh7aDoh2eich0zeith6viyae4er
    volumes:
      - /data/influxdb:/bitnami/influxdb
    ports:
      - '8086:8086'
      - '8088:8088'
    restart: always

密码可以使用 pwgen 工具生成, 例如:

# 生成一个32位的随机密码
pwgen 32 1
  • INFLUXDB_ADMIN_USER_TOKEN 后续上报还是 grafana 获取监控数据都使用这个配置

由于我这个 influxdb 只有 PVE 使用,故初始化组织和 Bucket 都为 proxmox

配置 PVE

登录 PVE 后,PVE 的 服务器视图 下,选择数据中心 - 指标服务器,选择添加 InfluxDB,输入相关的配置;
协议选择 HTTP,组织添加 INFLUXDB_USER_ORG 配置的值,插槽添加 INFLUXDB_USER_BUCKET 配置的 Bucket, 令牌填写 INFLUXDB_ADMIN_USER_TOKEN 配置的 Token

添加后 PVE 就会将监控指标推送到 InfluxDB 的 Bucket 中了。

登录 InfluxDB 验证配置是否正确,使用 admin 账号密码登录

配置 Grafana

启动 Grafana

在上面的 docker-compose.yaml 的基础上,添加 grafana

grafana:
    image: bitnami/grafana:11
    # image: ccr.ccs.tencentyun.com/k7scn/grafana:11
    container_name: grafana
    ports:
      - '100.90.80.15:3000:3000'
    environment:
      - 'GF_SECURITY_ADMIN_PASSWORD=joh1AhDah9quah8ruteexaeloh1Ohyuc'
    volumes:
      - /data/grafana:/opt/bitnami/grafana/data
    restart: always

配置启动 grafana

docker compose pull
docker compose up -d

添加 InfluxDB 数据源

访问 http://ip:3000/connections/datasources/new, 使用 InfluDB 作为数据源

  1. Query Language 选择 Flux
  2. URL 填写 InfluxDB 的地址,如 http://100.90.80.15:8086
  3. Auth 下的配置不需要启用,默认启动 Basic auth,去掉勾选
  4. Custom HTTP Headers 添加一个新的配置,Header 名称为 Authorization, Value 为 Token+ 配置的 Token,如 Token Eing5yaew6ujoo9ohd3saeH6neeshei3(需注意 Token 和值中间有一个空格)
  5. OrganizationDefault Bucket 填写和上面配置的值一致就行,如果没变更填 proxmox
  6. 配置完成后,点击 Save and Test,如果提示成功则表示配置正确

添加 Grafana 图表

Grafana Dashboard 中搜索 proxmox,选择支持 Flux 查询语法的图表进行添加,如添加 Proxmox Flux,根据 ID 导入 Grafana 即可看到 PVE 的监控指标

这里推荐 ID 使用 15356

访问 http://100.90.80.15:3000/dashboard/import

导入 Dashboard 后效果如下:


  •  

PVE环境折腾之配置DHCP

2025年4月23日 20:37

感觉最近售卖杜甫的 IDC 有点多,最近凑热闹买了几台杜甫(物理服务器简称),本文不会过多介绍安装 PVE,仅记录配置 dhcp

安装 PVE 环境

推荐先安装 Debian12 环境,在这个的基础上部署 PVE 环境。

  • 物语云暂时只支持系统, 配置 96 核 128G1T 存储 399 元/月,境内服务器
  • 狗云杜甫支持 PVE 环境,配置 48 核 64G1.92T 存储 450 元/月,香港 KC

Debian12 安装 PVE

推荐使用 https://github.com/oneclickvirt/pve 这个项目,基本很稳, 一键虚拟化项目。

细节这里就不多说了,更多可以参考文档

配置 DHCP

默认情况下,是没有配置 DHCP 的,不然每次创建虚拟机后还要手动配置多麻烦,也没 cloud-init

添加 NAT 网桥

如果你是按照上面的文档安装,整个流程走完 NAT 网桥默认已经配置完成了的。

示例配置文件应该如下, 具体网卡具体分析哈

# /etc/network/interfaces 仅摘选相关的部分
auto vmbr1
iface vmbr1 inet static
    address 192.168.23.1
    netmask 255.255.255.0
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward
    post-up echo 1 > /proc/sys/net/ipv4/conf/vmbr1/proxy_arp
    post-up iptables -t nat -A POSTROUTING -s '192.168.23.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '192.168.23.0/24' -o vmbr0 -j MASQUERADE

虚拟机网段默认使用 192.168.23.0/24, 网卡是 vmbr1

安装 DHCP 服务

安装完可能会提示报错,这是正常情况需要配置才能启动成功。

apt-get install isc-dhcp-server

配置 DHCP 服务

这里仅涉及 ipv4 部分,所以改动仅涉及 ipv4

编辑 /etc/default/isc-dhcp-server

INTERFACESv4="vmbr1" # 仅修改这里,默认为空,修改为你的NAT网卡vmbr1
INTERFACESv6=""

编辑 /etc/dhcp/dhcpd.conf

:> /etc/dhcp/dhcpd.conf

清空配置文件,重新生成

option domain-name-servers 8.8.8.8;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

authoritative;

log-facility local7;

subnet 192.168.23.0 netmask 255.255.255.0 {
  range 192.168.23.10 192.168.23.50;
  option subnet-mask 255.255.255.0;
  option domain-name-servers 8.8.8.8;
  option routers 192.168.23.1;
  option netbios-name-servers 192.168.23.1;
  option netbios-node-type 8;
  get-lease-hostnames true;
  use-host-decl-names true;
  default-lease-time 600;
  max-lease-time 7200;
  interface vmbr1;
}

默认分配 IP 从 192.168.23.10~192.168.23.50, 切记不要包含网关哈

service isc-dhcp-server restart

重启服务没有报错,即表示配置成功了。如果有错误配置,重启服务会失败。

PVE 导入备份

qmrestore vzdump-qemu-104-2025_04_15-14_56_54.vma.zst 100 -storage local2

其中 local2 为你的存储池

AD 部分

狗云续费、新购充值可以走我的 AFF,如果成功绑定了我的 AFF,返利 50%


欢迎关注、订阅我的微信公众号
  •  

快速部署私有微信编辑器

2025年4月22日 22:05

快速部署私有微信编辑器

之前都是在使用开源作者提供的官方演示站点, 但是最近不知道是不是网络问题,我打开站点比较慢,即使上了手段

WeChat Markdown Editor

一款高度简洁的微信 Markdown 编辑器:支持 Markdown 语法、自定义主题样式、内容管理、多图床、AI 助手等特性

项目地址: doocs/md

功能特性

  • • 支持 Markdown 所有基础语法、数学公式
  • • 提供对 Mermaid 图表的渲染和 GFM 警告块的支持
  • • 丰富的代码块高亮主题,提升代码可读性
  • • 允许自定义主题色和 CSS 样式,灵活定制展示效果
  • • 提供多图上传功能,并可自定义配置图床
  • • 便捷的文件导入、导出功能,提升工作效率
  • • 内置本地内容管理功能,支持草稿自动保存
  • • 集成主流 AI 模型(如 DeekSeek、OpenAI、通义千问),辅助内容创作

那为啥选择它,主要是我的博客系统 Solitudes 也支持它的语法,我只要写一次就可以复用。

PS: 打个广告 Solitudes 是使用 Go 编写的轻量博客引擎, 我的博客是魔改版,一直说要把改动 PR 到上游一直鸽到现在

部署

部署比较简单,官方也提供了镜像

docker 部署

执行完如下命令后,访问你的 80 端口就可以了

docker run -d -p 80:80 doocs/md:latest

k3s+caddy

下面仅供参考

---
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  labels:
    app: wxmd
  name: wxmd
  namespace: nb-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wxmd
  updateStrategy:
    type: InPlaceIfPossible
  template:
    metadata:
      labels:
        app: wxmd
    spec:
      tolerations:
      - operator: Exists
      nodeSelector:
        node-role.kubernetes.io/china: "true"
      containers:
      - image: doocs/md
        imagePullPolicy: Always
        name: wxmd
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: wxmd
  namespace: nb-system
spec:
  selector:
    app: wxmd
  ports:
  - port: 80
    targetPort: 80

将服务部署到 china 的节点池上,并且创建 svc, 配置 caddy,直接使用 svc 的 ip 更方便

wxmd.nbds.ysicing.net {
reverse_proxy http://10.25.220.235
}

公益服务

wxmd.nbds.ysicing.net, 本文就是使用该服务完成的。本服务应该会长期提供服务,下线会提前通知的。


  •  

Cherry Studio:搭建个人知识库的完美助手!

2025年4月21日 21:15

Cherry Studio:搭建个人知识库的完美助手!

之前我曾写过一篇关于如何基于 LobeHub 部署个人知识库的文章。有朋友反馈上手难度较高,因此今天我想再推荐一款非常适合我们国人的 AI 助手——Cherry Studio

这款工具非常易于使用,现已基本完成对 LobeHub 的替代。为什么我现在选择使用它呢?我觉得主要有以下几个优点:

  • 客户端支持:兼容 macOS 和 Windows 系统,下载安装后便可直接使用,无需复杂的服务部署。
  • 数据私有化:非 SaaS 服务,数据管理更加安全。
  • 内置丰富的提示词模板(智能体),大大提高使用效率。
  • 便捷的 数据备份,让信息管理更顺畅

相较于 LobeHub,Cherry Studio 唯一不足之处在于多客户端之间的记录同步和合并。但我相信,有了 AI 的加持,这些问题在后续都将迎刃而解(这里先给大家埋个伏笔!)

总之,Cherry Studio 上手简单且功能强大。如果你在寻找一款优秀的 AI 终端应用,我毫不犹豫地推荐它,真的是 YYDS!

安装 Cherry Studio

打开 Cherry Studio 官方下载页面 https://cherry-ai.com/download,根据你的操作系统进行下载。如果是 macOS 系统,M 系列用户请下载 Apple 芯片版本。
当然,如果你有相关技术,还可以通过官方 GitHub 开源项目下载 CherryHQ/cherry-studio

下载完成后,点击进行安装,过程非常简单。安装完成后,启动 Cherry Studio,开始配置。

配置模型服务

Cherry Studio 支持主流大模型服务,配置过程也大同小异,界面上还有相关引导。

配置国产大模型

以深度求索的 DeepSeek 模型为例进行演示

在第五步这里,是验证你的大模型和 Token 配置正常,如果请求成功,则可以设置启用

配置 ollama

整体流程与上述类似,唯一的区别是 Token 地址为空;下图示范的模型是我本地经常进行测试的模型。

需要注意的一点,添加完模型后需要管理,将模型添加上,上面显示的是已经附加了的模型

配置中转大模型

在许多场景下,我们经常使用中转服务商提供的 AI 网关,以解决特殊因素导致的非必要问题。

大部分 AI 网关支持通用的 OpenAI 格式 AI 请求,因此我在这里选择 OpenAI 进行配置。

整体流程与其他模型相似,同样需要在管理页添加所需使用的模型。

设置默认模型

Cherry Studio 允许为不同对话设置不同模型,我们可以在设置中定义默认助手模型。我这里配置的是 GPT-4o-mini。主要这个模型便宜的很,日常使用没有特别大的问题。

在聊天过程中,当然也可以随时切换不同的模型。

网络搜索

强烈推荐使用搜索引擎,可以免费获取实时信息资讯,配置也相对简单。

这里简单给大家实操一下, 查询北京明天天气情况

智能体

虽说是智能体,但更多像单一 Agent 哈,只是内置了相关提词。

生成网页也是轻轻松松, 预览效果如下

图片

默认只能用硅基流动,通常不用它。可以使用 gpt-4o-image 模型生图

个人知识库

Cherry Studio 的个人知识库功能非常实用,下面是配置流程的简要说明:

点击知识库,添加一个知识库

随便添加一些文本

编辑默认助手,勾选知识库

在使用过程中,系统有时能够命中知识库的信息,效果相当不错。

数据备份

Cherry Studio 支持多种数据备份方式,我推荐使用 WebDAV。如果你有飞牛,可以直接开启 WebDAV 服务;如果没有,也可以用 Docker 部署一个 WebDAV 服务。

docker run -d -e USERNAME=test -e PASSWORD=test -v /data/webdav:/var/webdav -p 8888:80 morrisjobke/webdav

顺便提一句,我利用 AI 解决了 WebDAV 的两个问题:

  • 同类型设备备份没发区分备份文件所属机器问题 #5004
  • 备份文件保留设置 #5060,只支持清理当前设备备份数据,历史数据需要手动自行清理了

其他

关于 MCP 部分的内容,下次再分享哈。

  •  

重磅,Tailscale的Derp服务器原生支持自签发证书

2025年4月5日 21:32

重磅,Tailscale 的 Derp 服务器原生支持自签发证书

最近比较忙,鸽了很久 😄。如题的功能已经出了比较长的时间了。本篇文章简单讲讲有啥新的调整。

背景

在官方支持之前,大家普遍通过修改源码来支持的,也有不少大佬提供相关镜像。可能大家会有疑问,为啥会有这类需求?受限于部分网络环境下 LetsEncrypt 是被禁用的;还有一些场景,使用域名的方式需要 ICP 许可,跨云 IDC 会比较麻烦。

开源作者讨论 tailscale#issues/11776
相关 PR tailscale#pull/15208

新版本好处

  • • 不需要域名
  • • 不需要 ICP 许可/接入
  • • 不需要证书

新版本部署

编译或下载二进制

如果你有 Go 的环境,可以使用如下命令

go install tailscale.com/cmd/derper@latest

当然也可以使用我编译好的二进制文件

wget https://c.ysicing.net/oss/tiga/linux/amd64/derper

将相关二进制复制到 /usr/bin/derper, 并赋予执行权限

cp -a derper /usr/bin/derper
chmod +x /usr/bin/derper

手动签发 IP 证书

示例是你的 derper 公网 ip

export DERP_IP="1.1.1.1"
mkdir /etc/derper
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /etc/derper/${DERP_IP}.key -out /etc/derper/${DERP_IP}.crt -subj "/CN=${DERP_IP}" -addext "subjectAltName=IP:${DERP_IP}"

手动启动 derper

derper --hostname="1.1.1.1"  -certmode manual -certdir /etc/derper

启动完成会提示如下信息

2025/04/05 20:00:25 Using self-signed certificate for IP address "1.1.1.1". Configure it in DERPMap using: (https://tailscale.com/s/custom-derp)
  {"Name":"custom","RegionID":900,"HostName":"1.1.1.1","CertName":"sha256-raw:970d3fae5ccd1480ad5e1017597c91f33d4bf0ef5bbeb5f54a2c20c0156ca081"}

然后可以打开浏览器访问这个网址看看,需要放行 804433478, 其中 3478 是 UDP 端口。

配置 ACL

方便显示,格式化如下:

{
    "RegionID": 910,
    "RegionCode": "yxvm",
    "RegionName": "yxvm",
    "Nodes": [
        {
            "Name": "yxvm",
            "RegionID": 910,
            "HostName": "46.x.x.x",
            "IPv4": "46.x.x.x",
            "CertName":"sha256-raw:8a81f6658a7e1830fbaf363b72427f975d1f033d1616bf603cec3defa7e52391",
            "InsecureForTests": true 
        }
    ]
}

保存之后,使用 tailscale netcheck 测试

* DERP latency:
        - yxvm: 118.8ms (yxvm)

总结

如果你之前就使用自签证书的话,更新一下二进制就行

  •  

离线私有化环境部署deepseek之ollama模型缓存

2025年2月14日 16:48

离线私有化环境部署 deepseek 之 ollama 模型缓存

在某些特殊的环境下,导致我们使用 ollama 模型存在各种各样的问题。最常见的就是拉取不了或者拉取速度很慢。基于这点,想到了如何去镜像缓存这些。

应用场景

方便给离线环境下的用户部署私有大模型体验。

ollama 与 oci

可以跳过这部分记录早期我的探索,得出目前不支持通用 OCI 方式。

从上面 ollama 拉取模型来看,是不是很眼熟,和我们经常拉取容器镜像是不是很相似。深入研究后发现,有着容器镜像的模型名称、分层存储结构,其中 manifest 保存 layer 列表,blob 存储二进制文件。那灵机一动是不是,可以存镜像的 registry 是不是也可以存 model。

搭建镜像服务

services:
  registry:
    image: registry:latest
    container_name: registry
    restart: always
    ports:
      - "5000:5000"
    environment:
      TZ: Asia/Shanghai

基于官方的 registry 镜像跑了一个镜像仓库来模拟,将上面的文件保存为 docker-compose.yaml

运行起来

docker compose pull
docker compose up -d

下载 deepseek-r1 小模型

# 下载deepseek最小模型验证
ollama pull deepseek-r1:1.5b
# 重命名
ollama cp deepseek-r1:1.5b 127.0.0.1:5000/ollama/deepseek-r1:1.5b

推送到本地镜像仓库

ollama push 127.0.0.1:5000/ollama/deepseek-r1:1.5b --insecure

推送很成功,给人一种万事俱备,只等下载了

验证下载

ollama pull 100.90.80.29:5001/ollama/deepseek-r1:1.5b --insecure
pulling manifest
pulling aabd4debf0c8...   0% ▕                                                                                                                                                                                    ▏    0 B/1.1 GB
Error: http: no Location header in response

下载提示这个,去搜了一下这个报错,也有人反馈这个问题,解决也可以参考这个 ollama#7474

根据核心开发者的反馈,我大概总结了一下:

尚未公开使用 OCI 规范,因为我们正在对其进行重大修改,以确保未来的灵活性。

其实到这里使用 oci 的方式行不通了。另外官方也没有透露如何搭建私有化模型仓库。

基于 caddy+ollama 部署镜像缓存加速

主要参考了大佬 ollama 模型缓存这篇博客,有兴趣的可以看看作者的逆向分析。这里主要讲一下如何快速搭建模型缓存。

镜像版本

使用这个镜像,可能有丢丢麻烦,但是也还好,需要套两层 caddy,一个是镜像内置的 caddy,一个是外部的 caddy 代理服务。

services:
  ollama-registry:
    image: wbuntu/ollama-registry:v0.1
    container_name: ollama-registry
    restart: always
    ports:
      - "8080:8080"
    volumes:
      - '/data/ollama-models:/data'

将上面的文件保存为 docker-compose.yaml, 执行

docker compose pull
docker compose up -d

配置 caddy 服务

ai-models.china.12306.work {
    import LOG "/var/log/caddy/ai-models.log"
	reverse_proxy 127.0.0.1:8080
}

到这里基本模型缓存服务就搭建完了,但是使用需要满足以下几点需求

  1. 首先需要 ollama-registry 服务缓存相关模型
  2. 其次才能通过 ollama-registry 拉取模型
# 通过ollama-registry缓存qwen2.5的模型
docker exec ollama-registry ollama pull qwen2.5:latest
# 其他服务器下载模型
ollama pull ai-models.china.12306.work/library/qwen2.5:latest

非镜像版本

要求部署了 ollama 和 caddy,方便操作 caddy 部署用户使用 root,避免权限问题.(默认情况,两者都已经跑起来了), 主要是配置 caddy。

其实就是将镜像里的 caddy 独立出来了,Caddyfile 示例如下:

ai-models.china.12306.work {
 	import LOG "/var/log/caddy/ai-models.log"
	# root directory 
	root * /root/.ollama/models

	# match blob request
	@blobRequests path_regexp blob /v2/([^/]+)/([^/]+)/blobs/sha256:(.+)
	# rewrite blob request
	rewrite @blobRequests /blobs/sha256-{re.blob.3}
	# add Location header on response
	header @blobRequests {
		Location {uri}
	}

	# match manifest request
	@manifestRequests {
		path_regexp manifest /v2/([^/]+)/([^/]+)/manifests/(.+)
	}
	# rewrite manifest request
	rewrite @manifestRequests /manifests/registry.ollama.ai/{re.manifest.1}/{re.manifest.2}/{re.manifest.3}
	# add Content-Type header on response
	header @manifestRequests {
		Content-Type application/vnd.docker.distribution.manifest.v2+json
	}

	# static file server
	file_server browse
}

其他

目前,我已经缓存了 5 个通用大模式供大家下载, 如果大家还有其他模型需要加速,可以私信我。

ai-models.china.12306.work/library/qwen2.5:latest
ai-models.china.12306.work/library/qwen2.5-coder:latest
ai-models.china.12306.work/library/deepseek-r1:1.5b
ai-models.china.12306.work/library/deepseek-r1:7b
ai-models.china.12306.work/library/deepseek-r1:8b

附录

  •  

离线私有化环境部署deepseek之ollama模型缓存

2025年2月11日 22:23

离线私有化环境部署 deepseek 之 ollama 模型缓存

在某些特殊的环境下,导致我们使用 ollama 模型存在各种各样的问题。最常见的就是拉取不了或者拉取速度很慢。基于这点,想到了如何去镜像缓存这些。

应用场景

方便给离线环境下的用户部署私有大模型体验。

ollama 与 oci

可以跳过这部分记录早期我的探索,得出目前不支持通用 OCI 方式。

从上面 ollama 拉取模型来看,是不是很眼熟,和我们经常拉取容器镜像是不是很相似。深入研究后发现,有着容器镜像的模型名称、分层存储结构,其中 manifest 保存 layer 列表,blob 存储二进制文件。那灵机一动是不是,可以存镜像的 registry 是不是也可以存 model。

搭建镜像服务

services:
  registry:
    image: registry:latest
    container_name: registry
    restart: always
    ports:
      - "5000:5000"
    environment:
      TZ: Asia/Shanghai

基于官方的 registry 镜像跑了一个镜像仓库来模拟,将上面的文件保存为 docker-compose.yaml

运行起来

docker compose pull
docker compose up -d

下载 deepseek-r1 小模型

# 下载deepseek最小模型验证
ollama pull deepseek-r1:1.5b
# 重命名
ollama cp deepseek-r1:1.5b 127.0.0.1:5000/ollama/deepseek-r1:1.5b

推送到本地镜像仓库

ollama push 127.0.0.1:5000/ollama/deepseek-r1:1.5b --insecure

推送很成功,给人一种万事俱备,只等下载了

验证下载

ollama pull 100.90.80.29:5001/ollama/deepseek-r1:1.5b --insecure
pulling manifest
pulling aabd4debf0c8...   0% ▕                                                                                                                                                                                    ▏    0 B/1.1 GB
Error: http: no Location header in response

下载提示这个,去搜了一下这个报错,也有人反馈这个问题,解决也可以参考这个 ollama#7474

根据核心开发者的反馈,我大概总结了一下:

尚未公开使用 OCI 规范,因为我们正在对其进行重大修改,以确保未来的灵活性。

其实到这里使用 oci 的方式行不通了。另外官方也没有透露如何搭建私有化模型仓库。

基于 caddy+ollama 部署镜像缓存加速

主要参考了大佬 ollama 模型缓存这篇博客,有兴趣的可以看看作者的逆向分析。这里主要讲一下如何快速搭建模型缓存。

镜像版本

使用这个镜像,可能有丢丢麻烦,但是也还好,需要套两层 caddy,一个是镜像内置的 caddy,一个是外部的 caddy 代理服务。

services:
  ollama-registry:
    image: wbuntu/ollama-registry:v0.1
    container_name: ollama-registry
    restart: always
    ports:
      - "8080:8080"
    volumes:
      - '/data/ollama-models:/data'

将上面的文件保存为 docker-compose.yaml, 执行

docker compose pull
docker compose up -d

配置 caddy 服务

ai-models.china.12306.work {
    import LOG "/var/log/caddy/ai-models.log"
	reverse_proxy 127.0.0.1:8080
}

到这里基本模型缓存服务就搭建完了,但是使用需要满足以下几点需求

  1. 首先需要 ollama-registry 服务缓存相关模型
  2. 其次才能通过 ollama-registry 拉取模型
# 通过ollama-registry缓存qwen2.5的模型
docker exec ollama-registry ollama pull qwen2.5:latest
# 其他服务器下载模型
ollama pull ai-models.china.12306.work/library/qwen2.5:latest

非镜像版本

要求部署了 ollama 和 caddy,方便操作 caddy 部署用户使用 root,避免权限问题.(默认情况,两者都已经跑起来了), 主要是配置 caddy。

其实就是将镜像里的 caddy 独立出来了,Caddyfile 示例如下:

ai-models.china.12306.work {
 	import LOG "/var/log/caddy/ai-models.log"
	# root directory 
	root * /root/.ollama/models

	# match blob request
	@blobRequests path_regexp blob /v2/([^/]+)/([^/]+)/blobs/sha256:(.+)
	# rewrite blob request
	rewrite @blobRequests /blobs/sha256-{re.blob.3}
	# add Location header on response
	header @blobRequests {
		Location {uri}
	}

	# match manifest request
	@manifestRequests {
		path_regexp manifest /v2/([^/]+)/([^/]+)/manifests/(.+)
	}
	# rewrite manifest request
	rewrite @manifestRequests /manifests/registry.ollama.ai/{re.manifest.1}/{re.manifest.2}/{re.manifest.3}
	# add Content-Type header on response
	header @manifestRequests {
		Content-Type application/vnd.docker.distribution.manifest.v2+json
	}

	# static file server
	file_server browse
}

其他

目前,我已经缓存了 4 个通用大模式供大家下载, 如果大家还有其他模型需要加速,可以私信我。

ai-models.china.12306.work/library/qwen2.5:latest
ai-models.china.12306.work/library/deepseek-r1:1.5b
ai-models.china.12306.work/library/deepseek-r1:7b
ai-models.china.12306.work/library/deepseek-r1:8b

附录

  •  
❌