122个版本

0.5.17-pre.52024年7月21日
0.5.17-pre.32024年6月26日
0.5.10 2024年3月24日
0.5.0-rc.92023年12月28日
0.3.0-alpha.422021年10月27日

80图像 中排名

Download history 103/week @ 2024-04-28 10/week @ 2024-05-05 18/week @ 2024-05-12 209/week @ 2024-05-19 53/week @ 2024-05-26 167/week @ 2024-06-02 256/week @ 2024-06-09 68/week @ 2024-06-16 331/week @ 2024-06-23 51/week @ 2024-06-30 120/week @ 2024-07-07 71/week @ 2024-07-14 144/week @ 2024-07-21 15/week @ 2024-07-28 36/week @ 2024-08-04 31/week @ 2024-08-11

每月263次下载
lemmy_server 中使用

AGPL-3.0

2MB
20K SLoC

pict-rs

一个简单的图像托管服务

导航

  1. 链接
  2. 用法
    1. 运行
      1. 命令行
      2. Docker
      3. 裸机
        1. 发行版软件包
        2. 二进制下载
        3. 从源码编译
        4. Nix
    2. Api
  3. 管理
    1. 备份
    2. 从0.4到0.5迁移指南
      1. 概述
      2. 升级配置
      3. 配置更新
        1. 图像更改
        2. 动画更改
        3. 视频更改
      4. 直接升级到Postgres
    3. 文件系统到对象存储迁移
      1. 故障排除
    4. Sled到Postgres迁移
  4. 开发
    1. Nix开发
      1. 使用direnv和nix-direnv
      2. 仅使用Nix
    2. Docker开发
      1. 使用Arch
      2. 使用Alpine
  5. 贡献
  6. 常见问题解答
    1. pict-rs是无状态的吗?
    2. 我能使用不同的数据库吗?
    3. 我如何提交更改?
    4. 我想使用$format进行配置
    5. 我如何捐赠?
  7. 常见问题
  8. 许可证

用法

运行

命令行

$ pict-rs -h
A simple image hosting service

Usage: pict-rs [OPTIONS] <COMMAND>

Commands:
  run            Runs the pict-rs web server
  migrate-store  Migrates from one provided media store to another
  migrate-repo   Migrates from one provided repo to another
  help           Print this message or the help of the given subcommand(s)

Options:
  -c, --config-file <CONFIG_FILE>
          Path to the pict-rs configuration file
      --old-repo-path <OLD_REPO_PATH>
          Path to the old pict-rs sled database
      --old-repo-cache-capacity <OLD_REPO_CACHE_CAPACITY>
          The cache capacity, in bytes, allowed to sled for in-memory operations
      --log-format <LOG_FORMAT>
          Format of logs printed to stdout [possible values: compact, json, normal, pretty]
      --log-targets <LOG_TARGETS>
          Log levels to print to stdout, respects RUST_LOG formatting
      --log-spans
          Whether to log openning and closing of tracing spans to stdout
      --console-address <CONSOLE_ADDRESS>
          Address and port to expose tokio-console metrics
      --console-buffer-capacity <CONSOLE_BUFFER_CAPACITY>
          Capacity of the console-subscriber Event Buffer
      --opentelemetry-url <OPENTELEMETRY_URL>
          URL to send OpenTelemetry metrics
      --opentelemetry-service-name <OPENTELEMETRY_SERVICE_NAME>
          Service Name to use for OpenTelemetry
      --opentelemetry-targets <OPENTELEMETRY_TARGETS>
          Log levels to use for OpenTelemetry, respects RUST_LOG formatting
      --save-to <SAVE_TO>
          File to save the current configuration for reproducible runs
  -h, --help
          Print help
  -V, --version
          Print version

尝试运行 help 命令以获取更多运行时配置选项

$ pict-rs run -h
$ pict-rs run filesystem -h
$ pict-rs run object-storage -h
$ pict-rs run filesystem sled -h
$ pict-rs run filesystem postgres -h
$ pict-rs run object-storage sled -h
$ pict-rs run object-storage postgres -h

有关更多配置信息,请参阅 pict-rs.toml

示例

使用默认配置运行

$ ./pict-rs run

在所有接口上运行,端口8080,数据存储在/opt/data

$ ./pict-rs \
    run -a 0.0.0.0:8080 \
    filesystem -p /opt/data/files \
    sled -p /opt/data/sled-repo

本地运行,端口9000,数据存储在data/,并将所有上传转换为PNG

$ ./pict-rs \
    run \
        -a 127.0.0.1:9000 \
        --media-format png \
    filesystem -p data/files \
    sled -p data/sled-repo

本地运行,端口8080,数据存储在data/目录中,仅允许使用thumbnailidentity过滤器

$ ./pict-rs \
    run \
        -a 127.0.0.1:8080 \
        --media-filters thumbnail \
        --media-filters identity \
    filesystem -p data/files \
    sled -p data/sled-repo

从配置文件运行

$ ./pict-rs -c ./pict-rs.toml run

从文件系统存储迁移到对象存储。更多详细信息,请参阅文件系统到对象存储迁移

$ ./pict-rs \
    migrate-store \
    filesystem -p data/files \
    object-storage \
        -a ACCESS_KEY \
        -b BUCKET_NAME \
        -r REGION \
        -s SECRET_KEY

将配置覆盖写入toml文件

$ ./pict-rs --save-to pict-rs.toml \
    run \
    object-storage \
        -a ACCESS_KEY \
        -b pict-rs \
        -r us-east-1 \
        -s SECRET_KEY \
    sled -p data/sled-repo

Docker

运行以下命令

# Create a folder for the files (anywhere works)
$ mkdir ./pict-rs
$ cd ./pict-rs
$ mkdir -p volumes/pictrs
$ sudo chown -R 991:991 volumes/pictrs
$ wget https://git.asonix.dog/asonix/pict-rs/raw/branch/main/docker/prod/docker-compose.yml
$ sudo docker-compose up -d
注意
  • pict-rs使用系统临时文件夹。在Linux上通常是/tmp

裸机

有几个方法可以获得pict-rs以在docker外运行。

  1. 通过您选择的发行版打包
  2. 发布页面下载二进制文件
  3. 从源代码编译

如果在外部运行docker,建议的配置方法是使用pict-rs.toml文件。在运行pict-rs时,可以将文件作为命令行参数传递给二进制文件。

$ pict-rs -c /path/to/pict-rs.toml run
发行版软件包

如果您从您的发行版获取pict-rs,请确保它是最新版本(意味着0.3.x稳定版,或0.4.x稳定版)。如果它较旧,请考虑使用其他选项安装pict-rs。我目前知道pict-rs打包在AURnixpkgs中,但可能还有其他发行版也打包了它。

二进制下载

pict-rs提供了预编译的二进制文件,应该适用于任何x86_64、aarch64和armv7h的Linux系统。有关发布页面,请参阅发布页面。如果下载二进制文件,请确保已安装以下依赖项

  • ImageMagick 7
  • ffmpeg 5或6
  • exiftool 12(有时称为perl-image-exiftool

这些二进制文件由pict-rs调用以处理上传的媒体,因此它们必须位于pict-rs可用的$PATH中。

这里的一个明显问题是ImageMagick 7,它未打包在Debian Sid中,因此在任何版本的Debian或Ubuntu中都不可用。如果您正在运行Ubuntu或Debian系统,请考虑使用Nix安装和运行方法。

更多信息请参阅Ubuntu和Debian文档

从源码编译

可以使用最新版本的rust编译器从源代码编译pict-rs。我在1.75上开发和发布版本

与二进制下载选项类似,必须安装imagemagickffmpegexiftool才能正确运行pict-rs。

Nix

pict-rs附带相关的nix flake。这对于开发环境很有用,也可以用于运行带有所有必要依赖项的“生产”版本的pict-rs。

可以使用这些说明安装Nix包管理器。安装后,必须启用两个实验性功能:flakenix-command。这些需要在/etc/nix/nix.conf中添加。

experimental-features = nix-command flakes

启用 flakes 之后,您可以从 pict-rs 源目录运行 nix build。这将生成包含 pict-rs 及其依赖项的 nix 包。同时,它还会在 pict-rs 目录中创建一个名为 result 的符号链接,指向新构建的包。result 的内容应为一个名为 bin 的单一文件夹,其中包含一个名为 pict-rs 的文件。此文件是一个 shell 脚本,用于调用具有所需 $PATHpict-rs 二进制文件,以便找到 imagemagick 7、ffmpeg 6 和 exiftool。您可以像对待真正的 pict-rs 二进制文件一样处理此 shell 脚本,并传递给 pict-rs 相同的参数。

示例

./result/bin/pict-rs -c dev.toml run

API

pict-rs 提供以下端点

  • POST /image?{args} 用于上传图像。上传的内容必须是有效的 multipart/form-data,且图像数组位于 images[] 键内

    {args} 查询在图像上传中具有多重用途。首先,它为上传的媒体提供请求级别的验证。以下是可以用的键:

    • max_width:允许上传媒体的最大宽度(像素)
    • max_height:允许上传媒体的最大高度(像素)
    • max_area:允许上传媒体的最大面积(像素)
    • max_frame_count:动画和视频允许的最大帧数
    • max_file_size:允许的最大文件大小(兆字节)
    • allow_image:是否允许上传静态图像
    • allow_animation:是否允许上传动画
    • allow_video:是否允许上传视频

    这些验证在 pict-rs 配置中指定的验证之外应用,因此如果任何验证失败,上传的媒体将被拒绝。

    {args} 查询的第二个目的是为上传的图像提供预处理步骤。格式与 process.{ext} 端点相同。使用这些步骤提供的图像在保存之前将进行处理。

    此端点在成功时返回以下 JSON 结构,状态为 201 Created

    {
        "files": [
            {
                "delete_token": "JFvFhqJA98",
                "file": "lkWZDRvugm.jpg",
                "details": {
                    "width": 800,
                    "height": 800,
                    "content_type": "image/jpeg",
                    "created_at": "2022-04-08T18:33:42.957791698Z"
                }
            },
            {
                "delete_token": "kAYy9nk2WK",
                "file": "8qFS0QooAn.jpg",
                "details": {
                    "width": 400,
                    "height": 400,
                    "content_type": "image/jpeg",
                    "created_at": "2022-04-08T18:33:42.957791698Z"
                }
            },
            {
                "delete_token": "OxRpM3sf0Y",
                "file": "1hJaYfGE01.jpg",
                "details": {
                    "width": 400,
                    "height": 400,
                    "content_type": "image/jpeg",
                    "created_at": "2022-04-08T18:33:42.957791698Z"
                }
            }
        ],
        "msg": "ok"
    }
    
  • POST /image/backgrounded?{args}/image 端点类似上传图像,但不需要等待验证和处理。{args} 查询与内联图像上传端点格式相同。

    此端点在成功时返回以下 JSON 结构,状态为 202 Accepted

    {
        "uploads": [
            {
                "upload_id": "c61422e1-9294-4f1f-977f-c696b7939467",
            },
            {
                "upload_id": "62cc707f-725c-44b6-908f-2bd8946c3c29"
            }
        ],
        "msg": "ok"
    }
    
  • GET /image/download?url={url}&backgrounded=(true|false) 从远程服务器下载图像,默认返回与 POST /image 端点相同的 JSON 有效负载。

    如果 backgrounded 设置为 true,则摄取处理将被排队等待后续处理,响应 JSON 将与 POST /image/backgrounded 端点相同。

  • GET /image/backgrounded/claim?upload_id={uuid} 等待后台上传完成,并声明其结果 可能的结果

    • 200 Ok(验证和摄取完成)
      {
          "files": [
              {
                  "delete_token": "OxRpM3sf0Y",
                  "file": "1hJaYfGE01.jpg",
                  "details": {
                      "width": 400,
                      "height": 400,
                      "content_type": "image/jpeg",
                      "created_at": "2022-04-08T18:33:42.957791698Z"
                  }
              }
          ],
          "msg": "ok"
      }
      
    • 422 Unprocessable Entity(验证或其他失败)
      {
          "msg": "Error message about what went wrong with upload"
      }
      
    • 204 No Content(上传验证和摄取未完成,等待超时)在这种情况下,再次尝试是可行的
  • GET /image/original/{alias} 获取全分辨率图像。这里的 aliasfile 键,来自 /image 端点的 JSON

  • GET /image/original?alias={alias} 获取全分辨率图像。这里的 aliasfile 键,来自 /image 端点的 JSON 可用源参数包括

    • ?alias={alias} 通过别名提供服务原始文件
    • ?proxy={url} 这个 proxy 字段可用于通过原始端点代理外部 URL。这些代理图像在最后一次访问后的一段时间内从 pict-rs 中删除。这个时间可以通过 PICTRS__MEDIA__RETENTION__PROXY 配置。更多信息请参见(./pict-rs.toml)[./pict-rs.toml]。
  • HEAD /image/original/{alias} 只返回与类似 GET 请求相对应的头信息。

  • HEAD /image/original?alias={alias} 只返回与类似 GET 请求相对应的头信息。可用源参数包括

    • ?alias={alias} 通过别名提供服务原始文件
    • ?proxy={url} 这个 proxy 字段可用于通过原始端点代理外部 URL。这些代理图像在最后一次访问后的一段时间内从 pict-rs 中删除。这个时间可以通过 PICTRS__MEDIA__RETENTION__PROXY 配置。更多信息请参见(./pict-rs.toml)[./pict-rs.toml]。
  • GET /image/details/original/{alias} 用于获取全分辨率图像的详细信息。返回的 JSON 结构如下

    {
        "width": 800,
        "height": 537,
        "content_type": "image/webp",
        "created_at": "2022-04-08T18:33:42.957791698Z"
    }
    
  • GET /image/details/original?alias={alias} 与上述端点相同,但使用查询而不是路径

    可用源参数包括

    • ?alias={alias} 通过别名提供服务原始文件
    • ?proxy={url}proxy 字段可用于获取 pict-rs 中代理图像的详细信息。这些代理图像在最后一次访问后一段时间将从 pict-rs 中删除。此时间可通过 PICTRS__MEDIA__RETENTION__PROXY 配置。更多信息请参阅 (./pict-rs.toml)[./pict-rs.toml]。
  • GET /image/blurhash?alias={alias} 为提供的别名创建并存储 blurhash

    可用源参数包括

    • ?alias={alias} 为通过提供的别名识别的图像提供 blurhash
    • ?proxy={url} 为位于 url 的媒体提供 blurhash。这将下载并存储指定媒体的原始版本及其 blurhash。代理媒体的保留时间可通过 PICTRS__MEDIA__RETENTION__PROXY 配置。更多信息请参阅 (./pict-rs.toml)[./pict-rs.toml]。

    返回的 JSON 结构如下

    {
        "msg": "ok",
        "blurhash": "LGF5]+Yk^6#M@-5c,1J5@[or[Q6."
    }
    
  • GET /image/process.{ext}?src={alias}&... 获取应用了转换的文件。可用的源参数包括

    • ?src={alias} 此行为与之前版本相同
    • ?alias={alias}alias 字段与 src 字段相同。重命名以提高一致性
    • ?proxy={url}proxy 字段可用于通过进程端点代理外部 URL。这些代理图像在最后一次访问后一段时间将从 pict-rs 中删除。此时间可通过 PICTRS__MEDIA__RETENTION__PROXY 配置。更多信息请参阅 (./pict-rs.toml)[./pict-rs.toml]。

    现有的转换包括

    • identity=true:不应用任何更改

    • blur={float}:对文件应用高斯模糊

    • thumbnail={int}:通过原始像素采样生成适合 {int} 正方形内的图像缩略图

    • resize={int}:生成一个适合放入 {int} 大小的正方形内的缩略图,使用 Lanczos2 过滤器。这比采样慢,但在某些情况下看起来会更好。

    • resize={filter}.(a){int}:生成一个适合放入 {int} 大小的正方形内的缩略图,或者当 (a) 存在时,生成一个面积小于 {int} 的缩略图。 {filter} 是可选的,表示在调整图像大小时使用什么过滤器。可用的过滤器有 LanczosLanczos2LanczosSharpLanczos2SharpMitchellRobidouxSharp

      示例

      • resize=300:生成一个适合放入 300x300 px 正方形内的图像
      • reizie=.a10000:生成一个面积最多为 10000 px 的图像
      • resize=Mitchell.200:使用 Mitchell 过滤器生成一个适合放入 200x200 px 正方形内的图像
      • resize=RobidouxSharp.40000:使用 RobidouxSharp 过滤器生成一个面积最多为 40000 px 的图像
    • crop={int-w}x{int-h}:生成一个裁剪后的图像,其宽高比为 {int-w}。裁剪后的图像将居中显示。图像的宽度和高度中至少有一个将保持原始大小,这取决于图像的宽高比和请求的宽高比。例如,一个 1600x900 的图像以 1x1 的宽高比裁剪将变为 900x900。一个 1600x1100 的图像以 16x9 的宽高比裁剪将变为 1600x900。

    支持的 ext 文件扩展名包括 apngavifgifjpgjxlpngwebp。请注意,虽然 avifwebp 可用于动画和非动画图像,但某些格式如 apnggif 只用于提供动画,而其他格式如 jpgjxlpng 只用于提供静态图像。

    使用示例可以是

    GET /image/process.jpg?src=asdf.png&thumbnail=256&blur=3.0
    

    这将创建一个 256x256 像素的 JPEG 缩略图并将其模糊化

  • HEAD /image/process.{ext}?src={alias} 返回类似于 GET 请求的头部信息。如果处理过的图像尚未生成,则返回 404。

    可用源参数包括

    • ?src={alias} 此行为与之前版本相同
    • ?alias={alias}alias 字段与 src 字段相同。重命名以提高一致性
    • ?proxy={url}proxy 字段可以用来获取代理图像的头部信息。
  • GET /image/process_backgrounded.{ext}?src={alias}&... 将转换队列应用于指定文件。此操作接受与 process.{ext} 端点相同的参数,但不等待处理完成。

    可用源参数包括

    • ?src={alias} 此行为与之前版本相同
    • ?alias={alias}alias 字段与 src 字段相同。重命名以提高一致性
  • GET /image/details/process.{ext}?src={alias}&... 获取处理过的图像详情。返回的 JSON 格式与全分辨率详情端点列出的格式相同。

    可用源参数包括

    • ?src={alias} 此行为与之前版本相同
    • ?alias={alias}alias 字段与 src 字段相同。重命名以提高一致性
    • ?proxy={url}proxy 字段可以用来获取代理图像的详细信息。
  • GET /image/details/process.{ext}?alias={alias} 与上述端点相同,但使用查询而不是路径

    可用源参数包括

    • ?alias={alias} 通过别名提供服务文件
    • ?proxy={url} 这个 proxy 字段可以用来获取 pict-rs 中代理图像的详细信息。这些代理图像在其最后访问后的一段时间内将从 pict-rs 中删除。这个时间可以通过 PICTRS__MEDIA__RETENTION__PROXY 进行配置。更多信息请参阅 ./pict-rs.toml
  • DELETE /image/delete/{delete_token}/{alias}GET /image/delete/{delete_token}/{alias} 来删除文件,其中 delete_tokenalias 来自 /image 端点的 JSON

  • GET /healthz 检查 pict-rs 服务器的健康状态。这将检查内嵌的 sled 数据库是否正常工作,以及配置的存储是否可访问

以下端点通过 X-Api-Token 标头受 API 密钥保护,并且除非将 --api-key 选项传递给二进制文件或设置 PICTRS__SERVER__API_KEY 环境变量,否则它们将禁用。

可以通过任何密码生成器生成安全的 API 密钥。

  • POST /internal/import 用于上传图像,同时保留文件名作为第一个别名。上传格式和响应格式与 POST /image 端点相同。

  • POST /internal/delete?alias={alias} 无需删除令牌即可删除别名。可用的源参数有

    • ?alias={alias} 删除文件别名
    • ?proxy={url} 删除代理文件的别名

    此端点返回以下 JSON

    {
        "msg": "ok",
    }
    
  • POST /internal/purge?alias={alias} 通过别名清除文件。这将删除与查询相关联的所有别名和文件。

    可用源参数包括

    • ?alias={alias} 通过别名清除文件
    • ?proxy={url} 通过 URL 清除代理文件

    此端点返回以下 JSON

    {
        "msg": "ok",
        "aliases": ["asdf.png"]
    }
    
  • GET /internal/aliases?alias={alias} 通过别名获取文件的别名

    可用源参数包括

    • ?alias={alias} 通过提供的别名获取文件的全部别名
    • ?proxy={url} 通过URL获取代理文件的全部别名

    此端点返回与清除端点相同的JSON

  • DELETE /internal/variants 为上传图像生成的变体排队清理。

    如果再次获取清理的变体,它们将重新生成。

  • GET /internal/identifier?alias={alias} 获取给定别名的图像标识符(文件路径或对象路径)。

    可用源参数包括

    • ?alias={alias} 通过提供的别名获取文件的标识符
    • ?proxy={url} 通过URL获取代理文件的标识符

    成功时,返回的JSON应如下所示

    {
        "msg": "ok",
        "identifier": "/path/to/object"
    }
    
  • POST /internal/set_not_found?alias={alias} 设置从原始和处理端点服务404图像。使用的图像必须已经上传并具有别名。请求应如下所示

    {
        "alias": "asdf.png"
    }
    

    成功时,返回的JSON应如下所示

    {
        "msg": "ok"
    }
    

    如果pict-rs找不到提供的别名,它将返回以下JSON的400 Bad Request

    {
        "msg": "No hash associated with provided alias"
    }
    
  • POST /internal/export 将当前sled数据库导出到配置的export_path。这对于备份正在运行的pict-rs服务器非常有用。成功时,它将返回

    {
        "msg": "ok"
    }
    

    从导出的数据库恢复就像这样

    1. 停止pict-rs
    2. 将您的当前sled-repo目录移动到安全位置(例如sled-repo.bak
      $ mv sled-repo sled-repo.bak
      
    3. 将导出的数据库复制到sled-repo
      $ cp -r exports/2023-07-08T22:26:21.194126713Z sled-repo
      
    4. 启动pict-rs
  • GET /internal/hashes?{query} 根据提供的查询按最新到最旧的顺序获取一页哈希值。成功时,它将返回以下JSON

    {
        "msg": "ok",
        "page": {
            "limit": 20,
            "current": "some-long-slug-string",
            "next": "some-long-slug-string",
            "prev": "some-long-slug-string",
            "hashes": [{
                "hex": "some-long-hex-encoded-hash",
                "aliases": [
                    "file-alias.png",
                    "another-alias.png",
                ],
                "details": {
                    "width": 1920,
                    "height": 1080,
                    "frames": 30,
                    "content_type": "video/mp4",
                    "created_at": "2022-04-08T18:33:42.957791698Z"
                }
            }]
        }
    }
    

    请注意,此响应中的一些字段是可选的(包括nextprevcurrentdetailsframes

    可用查询选项

    • empty:这将获取结果的第一页(例如,最新媒体)
    • ?slug={slug} 这将获取结果页面的特定页面。字段 slug 来自页面 JSON 中的 currentnextprev 字段
    • ?timestamp={timestamp} 这将获取早于指定时间戳的结果,以便轻松搜索数据。 timestamp 应根据 RFC3339 格式化
    • ?limit={limit} 指定每页返回的结果数量
  • POST /internal/prune_missing?force={force} 启动一个后台任务,该任务将检查数据库中的每个哈希值是否有相关的媒体文件,删除任何缺少媒体记录的记录。

    警告:此操作非常具有破坏性。请在调用之前进行备份。

    此端点可以被重复调用以检查准备工作的进度。返回的 progress 值表示已标记为修剪的记录数量。

    可选地,可以将 force 查询参数传递给值 true,以便在当前任务似乎卡住时让 pict-rs 启动另一个任务。

此外,所有端点都支持设置截止日期,在此之后请求将停止处理。要为您的请求启用截止日期,可以将 X-Request-Deadline 标头设置为表示自 UNIX Epoch 以来的纳秒数的 i128 值。计算此值的一个简单方法是使用 time crate 的 OffsetDateTime::unix_timestamp_nanos 方法。例如,

// set deadline of 1ms
let deadline = time::OffsetDateTime::now_utc() + time::Duration::new(0, 1_000);

let request = client
    .get("http://pict-rs:8080/image/details/original/asdfghjkla.png")
    .insert_header(("X-Request-Deadline", deadline.unix_timestamp_nanos().to_string())))
    .send()
    .await;

最后,还有一个可选的 Prometheus 抓取端点,可以通过 PICTRS__METRICS__PROMETHEUS_ADDRESS 配置启用。这将绑定到主 pict-rs 应用程序之外的一个单独端口。有关更多详细信息,请参阅 pict-rs.toml

管理

备份

pict-rs 维护两个重要的文件夹:sled-repo 目录和 files 目录。 sled-repo 是它存储有关文件元数据的地方,例如:它们的位置、它们的别名、它们处理后的版本的位置、它们的尺寸、MIME 类型等。 files 是它将上传的文件存储在本地文件系统中的位置。

files 文件夹相比,sled-repo 文件夹通常很小,备份它只需将其复制到其他位置即可。我建议在 pict-rs 不运行时进行此操作。

如果您无法停止 pict-rs,但想备份数据库,则可以在 Api 中找到的内部端点 /internal/export,用于生成当前数据库的副本,以便轻松备份。

从0.4到0.5迁移指南

注意

如果您正在运行 pict-rs 的旧版本,您需要首先更新到 0.4,然后再继续到 0.5。请参阅 0.3 到 0.4 迁移指南

概述

在第一次启动0.5版本时,pict-rs将自动将0.4数据库格式迁移到0.5数据库格式。这个过程可能需要一些时间,尤其是如果你从0.3版本之前就开始运行pict-rs。原因是pict-rs现在要求原始文件在数据库中存储相关详细信息记录,而虽然0.3和0.4版本默认会生成这些记录,但在这一标准之前上传的图像可能从未生成过详细信息记录。

升级配置

由于升级可能需要很长时间,因此引入了新的配置选项以尝试提高其速度。

[upgrade]
concurrency = 32

PICTRS__UPGRADE__CONCURRENCY=32

$ pict-rs run --upgrade-concurrency 32

此值指定pict-rs将同时尝试迁移多少个哈希值。由于此值将增加对Repo和Store的并发连接数,以及可能增加CPU和内存使用,因此在增加之前应仔细考虑。

对于大规模部署,此值可能应该增加到128、256甚至512。默认值为32。

配置更新

以前,pict-rs只有两种文件类别:图像和视频。pict-rs 0.5添加了第三个类别:动画。由于现在显式支持动画文件类型,一些配置选项已移动。

图像更改
旧环境变量 新环境变量
PICTRS__MEDIA__FORMAT PICTRS__MEDIA__IMAGE__FORMAT
PICTRS__MEDIA__MAX_WIDTH PICTRS__MEDIA__IMAGE__MAX_WIDTH
PICTRS__MEDIA__MAX_HEIGHT PICTRS__MEDIA__IMAGE__MAX_HEIGHT
PICTRS__MEDIA__MAX_AREA PICTRS__MEDIA__IMAGE__MAX_AREA
PICTRS__MEDIA__IMAGE__MAX_FILE_SIZE
旧 TOML 值 新 TOML 值
[media]format [media.image]format
[media]max_width [media.image]max_width
[media]max_height [media.image]max_height
[media]max_area [media.image]max_area
[media.image]max_file_size
动画更改
旧环境变量 新环境变量
PICTRS__MEDIA__GIF__MAX_WIDTH PICTRS__MEDIA__ANIMATION__MAX_WIDTH
PICTRS__MEDIA__GIF__MAX_HEIGHT PICTRS__MEDIA__ANIMATION__MAX_HEIGHT
PICTRS__MEDIA__GIF__MAX_AREA PICTRS__MEDIA__ANIMATION__MAX_AREA
PICTRS__MEDIA__GIF__MAX_FILE_SIZE PICTRS__MEDIA__ANIMATION__MAX_FILE_SIZE
PICTRS__MEDIA__GIF__MAX_FRAME_COUNT PICTRS__MEDIA__ANIMATION__MAX_FRAME_COUNT
PICTRS__MEDIA__ANIMATION__FORMAT
PICTRS__MEDIA__ANIMATION__MAX_FILE_SIZE
旧 TOML 值 新 TOML 值
[media.gif]max_width [media.animation]max_width
[media.gif]max_height [media.animation]max_height
[media.gif]max_area [media.animation]max_area
[media.gif]max_file_size [media.animation]max_file_size
[media.gif]max_frame_count [media.animation]max_frame_count
[media.animation]format
[media.animation]max_file_size
视频更改
旧环境变量 新环境变量
PICTRS__MEDIA__ENABLE_SILENT_VIDEO PICTRS__MEDIA__VIDEO__ENABLE
PICTRS__MEDIA__ENABLE_FULL_VIDEO PICTRS__MEDIA__VIDEO__ALLOW_AUDIO
PICTRS__MEDIA__VIDEO_CODEC PICTRS__MEDIA__VIDEO__VIDEO_CODEC
PICTRS__MEDIA__AUDIO_CODEC PICTRS__MEDIA__VIDEO__AUDIO_CODEC
PICTRS__MEDIA__MAX_FRAME_COUNT PICTRS__MEDIA__VIDEO__MAX_FRAME_COUNT
PICTRS__MEDIA__ENABLE_FULL_VIDEO PICTRS__MEDIA__VIDEO__ALLOW_AUDIO
PICTRS__MEDIA__VIDEO__MAX_WIDTH
PICTRS__MEDIA__VIDEO__MAX_HEIGHT
PICTRS__MEDIA__VIDEO__MAX_AREA
PICTRS__MEDIA__VIDEO__MAX_FILE_SIZE
旧 TOML 值 新 TOML 值
[media]enable_silent_video [media.video]enable
[media]enable_full_video [media.video]allow_audio
[media]video_codec [media.video]video_codec
[media]audio_codec [media.video]audio_codec
[media]max_frame_count [media.video]max_frame_count
[media]enable_full_video [media.video]allow_audio
[media.video]max_width
[media.video]max_height
[media.video]max_area
[media.video]max_file_size

请注意,尽管每种媒体类型现在都有自己的MAX_FILE_SIZE配置,但PICTRS__MEDIA__MAX_FILE_SIZE值仍然存在,作为任何文件类型的全局限制。

除了上述所有配置选项之外,现在还可以为每种图像和动画类型以及视频文件配置单独的质量设置。有关更多信息,请参阅pict-rs.toml文件。

直接升级到Postgres

pict-rs支持在升级期间直接迁移到postgres repo。为了执行此操作,需要配置postgres repo并指定old_repo。该old_repo部分仅包含您的0.4配置中repo部分的path

示例

[old_repo]
path = '/mnt/sled-repo'

[repo]
type = 'postgres'
url = 'postgres://user:password@host:5432/db'

或使用环境变量

PICTRS__OLD_REPO__PATH=/mnt/sled-repo
PICTRS__REPO__TYPE=postgres
PICTRS__REPO__URL=postgres://user:password@host:5432/db

设置这些变量后,即可启动0.5并自动执行迁移。

文件系统到对象存储迁移

在运行此命令之前,请确保备份sled-repo目录!!!将迁移到对象存储会更新数据库,如果您需要因任何原因回滚,则需要备份。

可以迁移到对象存储。如果在云环境中托管,这可能很有用,因为对象存储通常比块存储便宜得多。

对象存储需要一些配置选项。我将尝试解释。

  • 端点:这是对象存储可用的URL。通常这个URL看起来像这样 https://<bucket-name>.<region>.s3.example.com,但有时它可能看起来像 https://<region>.s3.example.com 或只是 https://s3.example.com
  • bucket-name:这是对象将驻留的“bucket”的名称。bucket必须已经存在,迁移才能工作 - pict-rs不会自己创建bucket。您需要提前使用存储提供商创建bucket。
  • region:这是bucket所在的“位置”。根据您的云提供商,这可能没有意义,但它总是必需的。
  • access-key:这是云提供商将为您提供以访问bucket的秘密。
  • secret-key:这是云提供商将为您提供以访问bucket的第二个秘密。

此外,还有一个命令行参数可以设置以更改迁移的默认并发级别。pict-rs将尝试一次迁移32个散列,但对于大型部署,尝试增加此值可能是有益的。将其设置为128、256甚至512可能很有用。请注意,此值越大,对对象存储提供商的并发连接就越多。

命令看起来可能如下所示

$ pict-rs \
    migrate-store \
        --concurrency 32 \
    filesystem \
        -p /path/to/files \
    object-storage \
        -e https://object-storage-endpoint \
        -b bucket-name \
        -r region \
        -a access-key \
        -s secret-key \
    sled \
        -p /path/to/sled-repo

如果您使用默认路径运行docker容器,它可以简化为以下内容

$ pict-rs \
    migrate-store \
    filesystem \
    object-storage \
        -e https://object-storage-endpoint \
        -b bucket-name \
        -r region \
        -a access-key \
        -s secret-key

此命令必须在pict-rs离线时运行。

如果您使用docker-compose运行,它可能看起来如下所示

$ sudo docker compose stop pictrs # stop the pict-rs container
$ sudo docker compose run pictrs sh # launch a shell in the pict-rs container
> pict-rs --version # verify pict-rs version is recent (should probably be 0.4.0 or later)
> pict-rs \
    migrate-store \
    filesystem \
    object-storage \
        -e endpoint \
        -b bucket \
        -r region \
        -a -access-key \
        -s secret-key
> exit
$ vi docker-compose.yml # edit the docker-compose yaml however you like to edit it, make sure all the variables described below are set
$ sudo docker compose up -d pictrs # start pict-rs again after the migration. Note that this is not 'docker compose start'. using the `up` subcommand explicitly reloads configurations

根据您的docker或docker-compose版本,您可能需要使用以下命令打开shell

$ sudo docker-compose run -i pictrs sh

以下是基于我自己的对象存储的示例,我在kubernetes上自己托管,使用garage

$ pict-rs \
    migrate-store \
    filesystem \
    object-storage \
        --use-path-style \
        -e http://garage-daemon.garage.svc:3900 \
        -b pict-rs \
        -r garage \
        -a <redacted> \
        -s <redacted>

以下是基于backblaze b2用户的配置示例;

$ pict-rs \
    migrate-store \
    filesystem \
    object-storage \
        --use-path-style \
        -e https://s3.us-east-005.backblazeb2.com \
        -r us-east-005 \
        -b SitenamePictrs \
        -a redacted \
        -s redacted

迁移完成后,请更新pict-rs配置以使用对象存储。如果您使用环境变量配置,请确保以下设置

  • PICTRS__STORE__TYPE=object_storage
  • PICTRS__STORE__ENDPOINT=https://object-storage-endpoint
  • PICTRS__STORE__BUCKET_NAME=bucket-name
  • PICTRS__STORE__REGION=region
  • PICTRS__STORE__USE_PATH_STYLE=false(如果您的对象存储需要路径样式访问,请将其设置为true)
  • PICTRS__STORE__ACCESS_KEY=access-key
  • PICTRS__STORE__SECRET_KEY=secret-key

如果您使用配置文件,它将是这样的

[store]
type = "object_storage"
endpoint = "https://object-storage-endpoint"
bucket_name = "bucket-name"
region = "region"
use_path_style = false # Set to true if your object storage requires path style access
access_key = "access-key"
secret_key = "secret-key"

迁移故障排除

如果您在尝试启动迁移时看到如下错误

   0: IO error: could not acquire lock on "/mnt/sled-repo/v0.4.0-alpha.1/db": Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }

这意味着pict-rs无法打开其数据库。这可能是由于另一个pict-rs副本正在运行。在迁移之前,请确保停止所有运行的pict-rs进程。

如果您尝试迁移并看到“Failed moving file. Retrying +1”,请不要取消迁移。让它达到10次重试。之后将打印出更具有意义的错误。以下是一些错误及其原因的示例

错误

   0: Error in store
   1: Error in object store
   2: Invalid status: 400 Bad Request
   2: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <Error>
          <Code>InvalidRequest</Code>
          <Message>Authorization header's Credential is malformed</Message>
      </Error>

原因:区域设置不正确。另外,使用了路径样式端点而没有传递 --use-path-style

错误

   0: Error in store
   1: Error in object store
   2: Invalid status: 403 Forbidden
   2: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <Error>
          <Code>InvalidAccessKeyId</Code>
          <Message>Malformed Access Key Id</Message>
      </Error>

原因:access key设置不正确

如果您在将现有文件迁移到对象存储之前启用了对象存储,这些迁移命令可能会无限期地重试文件迁移。为了成功解决这个多存储问题,已在 --skip-missing-files 子命令中添加了标志。这将告诉 pict-rs 如果文件返回某种形式的“未找到”错误,则不要重试迁移该文件。

$ pict-rs \
    migrate-store --skip-missing-files \
    filesystem -p /path/to/files \
    object-storage \
        -e https://object-storage-endpoint \
        -b bucket-name \
        -r region \
        -a access-key \
        -s secret-key \
    sled \
        -p /path/to/sled-repo

如果您在使用 pict-rs 上传到对象存储时遇到问题,请检查以下事项:您的对象存储是否需要路径风格访问?一些对象存储提供商,如 Contabo,不支持虚拟托管存储桶。以下是一个基本示例

路径风格 URL:https://region.example.com/bucket-name 虚拟主机风格 URL:https://bucket-name.region.example.com

如果确实需要使用路径风格,您的命令可能看起来像这样

$ pict-rs \
    migrate-store \
    filesystem -p /path/to/files \
    object-storage \
        --use-path-style \
        -e https://object-storage-endpoint \
        -b bucket-name \
        -r region \
        -a access-key \
        -s secret-key \
    sled \
        -p /path/to/sled-repo

此外,一些提供商可能要求您在端点 URL 中包含 region:例如 https://region.host.com,而其他提供商可能只需要顶级端点:例如 https://example.com

请检查对象存储提供商的文档,以确保您设置了正确的值。

Sled到Postgres迁移

如果您在没有迁移到 postgres 的情况下升级到 0.5,您可以使用内置的迁移工具事后迁移到 postgres。在运行迁移之前,请确保您为 pict-rs 准备了一个 postgres 角色和数据库名称。pict-rs 连接到新数据库时,首先要做的事情是尝试添加 pgcrypto 扩展,如果为 pict-rs 创建的角色没有这个权限,则迁移将失败。

迁移命令相当简单。只需要提供现有存储库的路径和新的存储库 URL。

$ pict-rs \
    migrate-repo \
    sled -p /path/to-/sled-repo \
    postgres -u postgres://user:password@host:5432/db

如果您使用docker-compose运行,它可能看起来如下所示

$ sudo docker compose stop pictrs # stop the pict-rs container
$ sudo docker compose run pictrs sh # launch a shell in the pict-rs container
> pict-rs --version # verify pict-rs version is recent (should probably be 0.5.0 or later)
> pict-rs \
    migrate-repo \
    sled -p /mnt/sled-repo \
    postgres -u postgres://user:password@host:5432/db
> exit
$ vi docker-compose.yml # edit the docker-compose yaml however you like to edit it, make sure all the variables described below are set
$ sudo docker compose up -d pictrs # start pict-rs again after the migration. Note that this is not 'docker compose start'. using the `up` subcommand explicitly reloads configurations

此命令必须在pict-rs离线时运行。

这次迁移应该相当快,因为没有实际文件被移动。迁移完成后,确保 pict-rs 配置为使用 postgres 存储库,然后重新启动。

示例

[repo]
type = 'postgres'
url = 'postgres://user:password@host:5432/db'

PICTRS__REPO__TYPE=postgres
PICTRS__REPO__URL=postgres://user:password@host:5432/db

开发

pict-rs 有一些需要安装才能正常运行的原生依赖项。目前这些如下

  • imagemagick 7.1.1(尽管 7.0 和 7.1.0 也可能工作)
  • ffmpeg 6(尽管 5 也可能工作)
  • exiftool 12.62(尽管 12.50 或更新版本也可能工作)

此外,pict-rs 在编译步骤需要 protobuf 编译器以支持 tokio-console,这是一个运行时调试工具。

使用您喜欢的包管理器安装这些依赖项应该足够了。以下是开发和使用 pict-rs 二进制文件的几种有趣方式。

Nix开发

我本人使用 nix 进行开发。提供的 flake.nix 文件应该足以在安装 nix 的任何 Linux 发行版上创建 pict-rs 的开发环境。

使用direnv和nix-direnv

使用这些工具,在进入 pict-rs 目录时可以自动加载 pict-rs 开发环境。

设置(仅一次)

$ echo 'use flake' > .envrc
$ direnv allow

运行

$ cargo run -- -c dev.toml run

仅使用Nix

$ nix develop
$ cargo run -- -c dev.toml run

Docker开发

以前,我已经在包含正确依赖项的容器中运行 pict-rs。下面列出的两个选项是我亲自尝试过的。

使用Arch

此选项不需要太多配置,只需在容器内编译二进制文件并运行即可

$ cargo build
$ sudo docker run --rm -it -p 8080:8080 -v "$(pwd):/mnt" archlinux:latest
> pacman -Syu imagemagick ffmepg perl-image-exiftool
> PATH=$PATH:/usr/bin/vendor_perl /mnt/target/debug/pict-rs --log-targets debug run

使用Alpine

此选项需要安装 cargo-zigbuild。Cargo Zigbuild 是一个工具,它使用 Zig 的链接器链接 Rust 二进制文件,从而可以轻松地针对许多目标进行交叉编译。Zig 在无缝交叉编译方面投入了大量努力,能够从 Rust 中利用这些工作非常令人高兴。

$ cargo zigbuild --target=x86_64-unknown-linux-musl
$ sudo docker run --rm -it -p 8080:8080 -v "$(pwd):/mnt" alpine:3.18
> apk add imagemagick ffmpeg exiftool
> /mnt/target/x86_64-unknown-linux-musl/debug/pict-rs --log-targets debug run

贡献

如果您发现任何问题,请随时提交问题。请注意,任何贡献的代码都将根据 AGPLv3 许可。

常见问题解答

问题:pict-rs 是否无状态?

回答:可以。默认情况下,pict-rs 使用磁盘存储文件以及名为 sled 的磁盘键值存储来存储元数据。这是为了便于小型配置的部署。如果需要 pict-rs 不保留任何本地状态(除 /tmp 外),可以配置它使用对象存储来存储文件和使用 Postgres 来存储元数据。

问题:我能否使用与 pict-rs 不同的数据库?

回答:可以。pict-rs 支持 sledpostgres 来存储元数据。将来我也可能支持 BonsaiDB。如果您希望 pict-rs 支持其他数据库,请随意提交更改 :)

问题:我如何提交更改?

回答:如果您想为 pict-rs 做贡献,可以将您的代码推送到您选择的公共 git 主机,并通过 matrix 或电子邮件通知我。我可以从那里拉取和合并您的更改到这个仓库中。

或者,您也可以通过电子邮件将补丁发给我。

我不会在我的 forgejo 服务器上创建额外的账户,抱歉了。

问题:我想用 yaml 而不是 toml 来配置它?

回答:这不是一个问题,但您可以使用 json、hjson、yaml、ini 或 toml 来配置 pict-rs。将配置写入其他格式是留给读者的练习。

问题:我如何捐赠给 pict-rs?

回答:您不需要。我通过做其他工作来赚钱。不要给我不需要的钱。

常见问题

在某些情况下,pict-rs 可能会崩溃并且无法重新启动。最常见的原因是文件系统达到 100%,pict-rs 无法写入磁盘,但这也可能在不幸的时刻杀死 pict-rs 时发生。如果发生这种情况,解决方案是首先为您的服务器获取更多磁盘空间,然后查找 sled-repo 目录中的 pict-rs。很可能是 pict-rs 创建了一个名为 snap.somehash.generating 的零大小文件。删除该文件并重新启动 pict-rs。

当使用提供的 docker 容器运行时,pict-rs 可能会因为权限错误而无法启动,显示“权限被拒绝”的 I/O 错误。这很可能意味着 pict-rs 的卷不是由正确的用户拥有的。将 pict-rs 卷的所有权更改为 991:991 应该解决这个问题。

许可证

版权 © 2022 Riley Trautman

pict-rs 是自由软件:您可以在自由软件基金会发布的 GNU 通用公共许可证的条款下重新分配它和/或修改它,无论是许可证的第 3 版,还是(根据您的选择)任何后续版本。

pict-rs 是希望它会有用而发布的,但没有任何保证;甚至没有关于适销性或特定用途的隐含保证。有关详细信息,请参阅 GNU 通用公共许可证。本文件是 pict-rs 的一部分。

您应该已经随 pict-rs 收到了一份 GNU 通用公共许可证的副本。如果没有,请参阅 https://gnu.ac.cn/licenses/

依赖项

~68MB
~1.5M SLoC