MoreRSS

site iconLala | 荒岛修改

一个应用分享、教程类的博客,主要是那些需要自部署的。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Lala | 荒岛的 RSS 预览

ChronoFrame:美观的照片展示和管理应用

2025-12-25 16:48:57

ChronoFrame非常适合喜欢玩摄影、拍照的用户食用。我觉得这程序的UI设计的是真好看,无论是前台还是后台都好看,非常符合我的审美,没需求的我都想怼几张图片上去挂着了= =

ChronoFrame特性(摘自项目页面)

在线管理照片 – 通过 Web 界面轻松管理和浏览照片
探索地图 – 在地图上浏览照片拍摄位置
智能 EXIF 解析 – 自动提取拍摄时间、地理位置、相机参数等元数据
地理位置识别 – 自动识别(Reverse Geocoding)照片拍摄地点
多格式支持 – 支持 JPEG、PNG、HEIC/HEIF 等主流图片格式
智能缩略图 – 基于 ThumbHash 技术的高效缩略图生成

现代技术栈
Nuxt 4 – 基于最新的 Nuxt 框架,提供 SSR/SSG 支持
TypeScript – 完整的类型安全保障
TailwindCSS – 现代化的 CSS 框架
Drizzle ORM – 类型安全的数据库 ORM

灵活的存储方案
多存储后端 – 支持 S3 兼容存储、本地文件系统
CDN 加速 – 可配置 CDN 地址加速图片访问

安装Docker:

apt -y update
apt -y install curl
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

创建目录新建compose文件:

mkdir /opt/chronoframe && cd /opt/chronoframe && nano docker-compose.yml

写入如下内容:

services:
  chronoframe:
    image: ghcr.io/hoshinosuzumi/chronoframe:latest
    container_name: chronoframe
    restart: unless-stopped
    ports:
      - '127.0.0.1:3000:3000'
    volumes:
      - ./data:/app/data
    env_file:
      - .env

创建.env文件:

nano .env

写入如下内容,自行按注释内容修改:

# 管理员邮箱(必须)
[email protected]
# 管理员用户名(可选,默认ChronoFrame)
CFRAME_ADMIN_NAME=imlala
# 管理员密码(可选,默认 CF1234@!)
CFRAME_ADMIN_PASSWORD=passwd

# 站点信息(全部可选)
NUXT_PUBLIC_APP_TITLE=
NUXT_PUBLIC_APP_SLOGAN=
NUXT_PUBLIC_APP_AUTHOR=
NUXT_PUBLIC_APP_AVATAR_URL=

# 地图提供器 (maplibre/mapbox)
NUXT_PUBLIC_MAP_PROVIDER=maplibre
# 使用MapLibre需要MapTiler的访问令牌
NUXT_PUBLIC_MAP_MAPLIBRE_TOKEN=
# 使用Mapbox需要Mapbox的访问令牌
NUXT_PUBLIC_MAPBOX_ACCESS_TOKEN=

# 存储提供者(支持local/s3/openlist)
NUXT_STORAGE_PROVIDER=local
NUXT_PROVIDER_LOCAL_PATH=/app/data/storage

# 会话密码(必须,32位随机字符串,使用命令生成:openssl rand -base64 32)
NUXT_SESSION_PASSWORD=

若选择使用s3,则将存储部分替换为:

NUXT_STORAGE_PROVIDER=s3
NUXT_PROVIDER_S3_ENDPOINT=
NUXT_PROVIDER_S3_BUCKET=chronoframe
NUXT_PROVIDER_S3_REGION=auto
NUXT_PROVIDER_S3_ACCESS_KEY_ID=
NUXT_PROVIDER_S3_SECRET_ACCESS_KEY=
NUXT_PROVIDER_S3_PREFIX=photos/
NUXT_PROVIDER_S3_CDN_URL=

启动:

docker compose up -d

ChronoFrame建议生产环境使用反向代理,如果您必须使用IP+端口来访问,请在.env文件内添加如下内容:

NUXT_ALLOW_INSECURE_COOKIE=true

以解决类似问题:https://github.com/HoshinoSuzumi/chronoframe/issues/14#issuecomment-3333256569

我这里配置Ferron反向代理:

nano /etc/ferron.kdl

写入如下内容:

chronoframe.example.com {
    proxy "http://127.0.0.1:3000/"
}

重载Ferron:

systemctl reload ferron

前台的效果参考项目页面,我这里放两张后台的效果图:

Sudoku (ASCII):一种抛弃随机数基于数独的代理协议

2025-12-20 15:45:33

SUDOKU是一个基于4×4数独设题解题的流量混淆协议。它通过将任意数据流(数据字节最多有256种可能,4×4数独的非同构体有288种)映射为以4个Clue为题目的唯一可解数独谜题,每种Puzzle有不少于一种的设题方案,随机选择的过程使得同一数据编码后有多种组合,产生了混淆性。

以上内容摘自官方项目文档,更多内容见:https://github.com/SUDOKU-ASCII/sudoku/blob/main/README.zh_CN.md

服务器端一键部署脚本:

sudo bash -c "$(curl -fsSL https://raw.githubusercontent.com/SUDOKU-ASCII/easy-install/main/install.sh)"

您也可以按照下面的步骤手动部署服务端,提供更灵活的配置。下载最新版本:

wget https://github.com/SUDOKU-ASCII/sudoku/releases/download/v0.0.9/sudoku-linux-amd64.tar.gz
tar -xzvf sudoku-linux-amd64.tar.gz
chmod +x sudoku
mv sudoku /usr/local/bin

生成key:

sudoku -keygen

回显的内容类似:

Available Private Key: 98af9788db059d4df7a46c8631d203dec6899cb4c366a16a9b23572d14a18605c62961391abed62575271eb2d23cd3273ca39e2c295e8fce6ab3c7f774bf6706
Master Private Key: 5ed9f8c1f5c373736ccc8a38040fd705032d3be1ecc4303906d71e258960ee0b
Master Public Key:  c4c7019df5de89638e467f4cb624086ea6ab79eb48259592fe48012bbe309034

其中Master Public Key是服务端key,Available Private Key是客户端key。

创建配置文件:

mkdir /etc/sudoku && nano /etc/sudoku/config.json

示例配置:

{
  "mode": "server",
  "local_port": 60888,
  "fallback_address": "127.0.0.1:80",
  "key": "c4c7019df5de89638e467f4cb624086ea6ab79eb48259592fe48012bbe309034",
  "aead": "chacha20-poly1305",
  "suspicious_action": "fallback",
  "padding_min": 2,
  "padding_max": 7,
  "ascii": "prefer_entropy",
  "custom_table": "vxvpxvvp",
  "enable_pure_downlink": false,
  "disable_http_mask": true
}

如需自定义字节特征,可修改custom_table,必须满足条件:两个x、两个p、四个v。

防御性回落 (Fallback)默认回落到本机NGINX的80端口,若机器内没有NGINX可以安装一下:

apt install nginx

创建systemd配置文件:

nano /etc/systemd/system/sudoku.service

写入如下内容:

[Unit]
Description=Sudoku Proxy Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/sudoku -c /etc/sudoku/config.json
Restart=on-failure
RestartSec=5
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

启动并设置开机自启:

systemctl enable --now sudoku.service

客户端可以使用mihomo(Alpha),注意是Alpha版本。虽然mihomo在v1.19.17已经支持sudoku协议了,但由于协议作者又更新了一些内容,现已不再支持新的sudoku协议。

mihomo配置:

- name: sudoku
  type: sudoku
  server: 89.64.19.37
  port: 60888
  key: "98af9788db059d4df7a46c8631d203dec6899cb4c366a16a9b23572d14a18605c62961391abed62575271eb2d23cd3273ca39e2c295e8fce6ab3c7f774bf6706"
  aead-method: chacha20-poly1305
  padding-min: 2
  padding-max: 7
  table-type: prefer_entropy
  custom-table: vxvpxvvp
  enable-pure-downlink: false
  http-mask: false

AIChat:您的赛博AI命令行工具

2025-12-17 11:00:46

AIChat是一款多合一的LLM CLI工具,具有Shell助手、CMD和REPL模式、RAG、AI工具和代理等功能。

Linux安装:

wget https://github.com/sigoden/aichat/releases/download/v0.30.0/aichat-v0.30.0-x86_64-unknown-linux-musl.tar.gz
tar -xzvf aichat-v0.30.0-x86_64-unknown-linux-musl.tar.gz
mv aichat /usr/local/bin

初次运行:

aichat

按照提示配置AI厂商和KEY:

> No config file, create a new one? Yes
> Platform: openai
> API Key: ***
✨ Saved config file to '/home/imlala/.config/aichat/aichat.yaml'

查看配置文件和其他信息:

aichat --info

aichat的-e模式,效果:

更多玩法见:https://github.com/sigoden/aichat/wiki

DMMTV解锁问题排查

2025-12-16 19:04:54

记录下排查与解决过程。起因:一台日本VPS(Debian12)用脚本测试能解锁DMMTV,但是搭建了代理用浏览器访问却解不了。。

一开始走弯路了,有点怀疑是解锁脚本测试的不准确,但是我还是更愿意相信是自己环境的问题,毕竟解锁脚本经过多人使用出错的概览不大,然后又以为是DMM用了WebRTC,给浏览器装了个关闭WebRTC的扩展还是不行。。

后来我发现这个VPS是双栈网络,有IPv6地址,然后又跑了一遍解锁脚本测试发现IPv6是不能解锁的,我就猜测是不是访问DMMTV的时候流量走了IPv6?我试着把IPv6关闭后,确实就能解锁了,到这里就能够确定是IPv6的问题了,但是我还是想保留IPv6,平时还是会用到IPv6的,直接关掉有点太鲁莽了。

我知道Linux系统中有一个gai.conf的配置文件,它可以控制系统如何选择地址,尤其是当系统同时支持IPv4和IPv6时,它决定了应用优先使用IPv4还是IPv6,我试着编辑gai.conf:

nano /etc/gai.conf

取消如下内容的注释,以启用IPv4优先:

precedence ::ffff:0:0/96  100

但是这并不能解决我的问题,虽然在VPS内curl还有ping等工具确实优先使用IPv4了,但作为代理服务器,我用浏览器访问DMMTV还是不能解锁。。。百思不得其解,突然想到会不会是代理节点的问题?我使用的是Remnawave面板,这台VPS安装的是Docker运行的Remnanode,使用的网络模式是host:

services:
    remnanode:
        container_name: remnanode
        hostname: remnanode
        image: remnawave/node:latest
        restart: always
        network_mode: host
        env_file:
            - .env

host网络默认应该也是没有启用IPv6支持的,但我记不太清楚,所以特地验证了一下,确实是没有启用IPv6:

docker network inspect host

我不知道这里的IPv6启用与否是否真的会影响到容器内的程序,所以我想看看容器的日志,我先用这个命令查看:

docker compose logs -f

发现看不到真正有用的日志,因为Remnanode实际上是用的Xray-core内核,它这个容器相当于是套了一层supervisor,最外层看不到Xray-core内核的日志,所以通过下面的命令我终于看到Xray-core内核的日志了:

docker exec -it remnanode tail -n +1 -f /var/log/supervisor/xray.out.log

按道理来说应该挂载一个volume,把这个log保存到宿主机的,当时配置的时候疏忽了,这日志一看就知道问题所在了,Xray-core一直在用IPv6去连接DMMTV。。。接着去搜Xray-core的文档,发现这段话:

可以通过修改 “domainStrategy”: “UseIPv6″来控制对应用户的访问方式 实测优先级要高于系统本身的 gai.config

难怪我之前配置gai.conf不起作用,现在就明朗了= =在Remnawave面板,修改配置文件,在出站配置domainStrategy:

"settings": {
  "domainStrategy": "UseIPv4"
}

如图所示:

再次测试,DMMTV就能够正常解锁了= =

部署MoonTVPlus二开增强版+LogVar弹幕API

2025-12-09 06:10:37

MoonTVPlus是基于MoonTV v100二次开发的增强版影视聚合播放器。它在原版基础上新增了外部播放器支持、视频超分、弹幕系统、评论抓取等实用功能,提供更强大的观影体验。

相对原版新增内容:

🎮 外部播放器跳转:支持 PotPlayer、VLC、MPV、MX Player、nPlayer、IINA 等多种外部播放器
✨ 视频超分 (Anime4K):使用 WebGPU 技术实现实时视频画质增强(支持 1.5x/2x/3x/4x 超分)
💬 弹幕系统:完整的弹幕搜索、匹配、加载功能,支持弹幕设置持久化、弹幕屏蔽
📝 豆瓣评论抓取:自动抓取并展示豆瓣电影短评,支持分页加载
🪒自定义去广告:你可以自定义你的去广告代码,实现更强力的去广告功能

安装Docker:

apt -y update
apt -y install curl
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

创建目录新建compose文件:

mkdir /opt/moontvplus && cd /opt/moontvplus && nano docker-compose.yml

写入如下内容,需要修改的地方写了注释:

services:
  moontv-core:
    image: ghcr.io/mtvpls/moontvplus:latest
    container_name: moontv-core
    restart: on-failure
    ports:
      - '10300:3000'
    environment:
      - USERNAME=admin
      - PASSWORD=yourpasswd # 设置moontvplus管理员密码
      - NEXT_PUBLIC_STORAGE_TYPE=kvrocks
      - KVROCKS_URL=redis://moontv-kvrocks:6666
    depends_on:
      - moontv-kvrocks

  moontv-kvrocks:
    image: apache/kvrocks
    container_name: moontv-kvrocks
    restart: unless-stopped
    volumes:
      - kvrocks-data:/var/lib/kvrocks

  danmu-api:
    image: logvar/danmu-api:latest
    container_name: danmu-api
    restart: unless-stopped
    ports:
      - "9321:9321"
    environment:
      - TOKEN=89641937 # 设置访问token
      - ADMIN_TOKEN=19378964 # 设置管理员访问token
    volumes:
      - ./.chche:/app/.cache

volumes:
  kvrocks-data:

启动:

docker compose up -d

配置Ferron反向代理:

nano /etc/ferron.kdl

写入如下内容:

moontvplus.example.com {
    proxy "http://127.0.0.1:10300/"
}

重载Ferron:

systemctl reload ferron

弹幕配置,弹幕API地址填写:http://danmu-api:9321,弹幕APIToken填写你设置的TOKEN=值(默认89641937)

配置订阅(视频源),这里推荐这个项目LunaTV-config。将这个URL填写上去保存即可。

效果:

如果你不想公开danmu-api服务器,可以删掉端口映射的配置,改为如下内容:

...
  danmu-api:
    image: logvar/danmu-api:latest
    container_name: danmu-api
    restart: unless-stopped
    ports:
      - "9321:9321"
    expose:
      - "9321"
    environment:
      - TOKEN=89641937 # 设置访问token
      - ADMIN_TOKEN=19378964 # 设置管理员访问token
    volumes:
      - ./.chche:/app/.cache
...

Ferron:一个用Rust编写的快速、内存安全的Web服务器

2025-12-08 13:18:44

Ferron是一个用Rust编写的高性能Web服务器。Ferron特点(摘自项目页面):

High performance – built with Rust’s async capabilities for optimal speed.
Memory-safe – built with Rust, which is a programming language offering memory safety.
Extensibility – modular architecture for easy customization.
Secure – focus on robust security practices and safe concurrency.

我安装用了一段时间,觉得各方面非常不错,所以特地写篇入门的文章,顺便也算是推荐一下吧。目前我已经把多台服务器的NGINX换成这个了。初次用Ferron给人最大的感觉就是配置起来特别简单,有点Caddy那味,甚至比Caddy还简单。

除了配置简单以外,很多特性或者说功能都是开箱即用的,比如HTTP3、PROXY Protocol、WebSocket、GRPC反代、FastCGI、自动申请TLS证书等等。废话就不多说了,下面一起来体验一下。

安装Ferron,这里我的系统是Debian 13,使用官方的存储库来安装:

apt update
apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring
curl https://deb.ferron.sh/signing.pgp | gpg --dearmor | tee /usr/share/keyrings/ferron-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/ferron-keyring.gpg] https://deb.ferron.sh $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/ferron.list
apt update
apt install ferron

管理Ferron服务:

systemctl stop ferron
systemctl restart ferron
systemctl reload ferron

重要的目录和文件:

/var/log/ferron/access.log # 访问日志
/var/log/ferron/error.log # 错误日志
/var/www/ferron # Ferron的网站根目录
/etc/ferron.kdl # Ferron的主配置文件

默认使用的用户和主目录:

ferron:x:1000:1000::/var/lib/ferron:/usr/sbin/nologin

编辑主配置文件:

nano /etc/ferron.kdl

在主配置文件添加如下内容可以包含(include)其他配置文件:

include "/var/lib/ferron/*.kdl"

在主配置文件添加如下内容以支持HTTP3、PROXY Protocol(默认未启用)、自动申请TLS证书功能:

* {
    protocols "h1" "h2" "h3"
    protocol_proxy #false
    auto_tls
    auto_tls_contact "[email protected]"
    auto_tls_cache "/var/lib/ferron/letsencrypt-cache"
    auto_tls_letsencrypt_production
    auto_tls_challenge "http-01"
}

现在简单说一下最常见的用例:反向代理。在主配置文件或者包含(include)一个新的配置文件写入如下内容:

example.com {
    proxy "http://127.0.0.1:3000/"
}

这就完成了一个反向代理的配置,并且Ferron直接就支持WebSocket,不需要额外的配置。我们需要注意的是Ferron默认会将请求发送到后端服务器之前重写“Host”标头,并在“X-Forwarded-Host”标头中保留原始的“Host”标头值。然而,有些Web应用程序可能无法在这种配置下正常工作,这可能会导致主机头不匹配以及其他问题。在这种情况下,你可以将“Host”标头设置为原始值(保留完整的“Host”标头):

example.com {
    proxy "http://127.0.0.1:3000/"
    proxy_request_header_replace "Host" "{header:Host}"
}

Ferron还支持多域名(virtual host)、IP(virtual host):

example.com,www.example.com {
    ...
}

"192.168.1.1" {
    ...
}

自动重定向,将不带“www”的URL重定向到带“www”的URL:

example.com {
    wwwredirect #true
}

每当配置文件发生更改,只需要Reload即可使Ferron使用新的配置:

systemctl reload ferron

除了反代,Ferron还支持通过FastCGI运行PHP程序,例如这里我要配置一个Laravel:

example.com {
    root "/var/www/laravel/public"
    rewrite "^/(.*)" "/index.php/$1" file=#false directory=#false last=#true
    fcgi_php "unix:///run/php/php8.4-fpm.sock"
}

这里要特别注意,Debian系统默认的Unix套接字(php8.4-fpm.sock)所有者和组是www-data,我们需要将其修改为ferron,编辑如下配置文件:

nano /etc/php/8.4/fpm/pool.d/www.conf

找到如下内容将其修改为ferron:

listen.owner = ferron
listen.group = ferron

重启PHP-FPM:

systemctl restart php8.4-fpm.service

重载Ferron:

systemctl reload ferron

完整的配置和文档请参考官方网站:https://ferron.sh/docs