Garage
Лёгкий self-hosted S3 на Rust, без внешних зависимостей, хорошо тянет разнесённые по географии узлы. Разумный выбор по умолчанию для своего хранилища.
Файлы адресуются по хешу содержимого: одинаковые не задваиваются, а лаунчер докачивает только изменившееся. Где физически лежат байты, задаёт раздел storage в конфиге сервера (/etc/laminara/config.json).
Локальный диск — самый простой вариант, подходит для одного сервера. Байты раздаёт nginx.
{ "storage": { "backend": "fs", "config": { "root": "/var/lib/laminara/objects", "xaccelPrefix": "/internal-objects/" } }}xaccelPrefix включает раздачу через X-Accel-Redirect силами nginx — см. Продакшен.
Для нескольких серверов, отказоустойчивости или раздачи через CDN. Лаунчер качает объекты напрямую по presigned-ссылкам — байты не идут через сервер.
{ "storage": { "backend": "s3", "config": { "endpoint": "s3.example.com", "region": "us-east-1", "bucket": "laminara", "accessKeyId": "...", "secretAccessKey": "...", "pathStyle": true } }}pathStyle включите для self-hosted хранилищ (Garage, SeaweedFS, MinIO); большинству облаков он не нужен. secure управляет HTTPS и по умолчанию включён.
MinIO, Garage или SeaweedFS на своём сервере за nginx с сертификатом:
"config": { "endpoint": "https://s3.example.com", "region": "us-east-1", "bucket": "laminara", "accessKeyId": "…", "secretAccessKey": "…", "pathStyle": true}То же хранилище на соседней машине во внутренней сети, без TLS — так можно, только если игроки ходят не напрямую, а через CDN или прокси, который вы поставите перед ним:
"config": { "endpoint": "http://10.0.0.5:9000", "region": "us-east-1", "bucket": "laminara", "accessKeyId": "…", "secretAccessKey": "…", "pathStyle": true, "secure": false}Amazon S3 — регион обязателен, pathStyle не нужен:
"config": { "endpoint": "https://s3.eu-central-1.amazonaws.com", "region": "eu-central-1", "bucket": "laminara-builds", "accessKeyId": "AKIA…", "secretAccessKey": "…"}Хранилища, где адрес бакета устроен как поддомен (Cloudflare R2, Backblaze B2, Selectel, Timeweb):
"config": { "endpoint": "https://<идентификатор>.r2.cloudflarestorage.com", "region": "auto", "bucket": "laminara", "accessKeyId": "…", "secretAccessKey": "…"}Ключу доступа нужны права на чтение, запись, удаление и выдачу временных ссылок в пределах одного бакета — раздавать полный доступ к хранилищу не требуется.
Сборка живёт в двух видах: папка профиля, которую оператор правит руками, и хранилище объектов,
откуда качает лаунчер. publish переносит файлы профиля в хранилище одним движением:
хеш считается чтением исходника, промежуточная копия во временной папке не делается, а если
такой объект уже есть — при повторной публикации это почти все файлы — не пишется ничего.
На btrfs, XFS и bcachefs новый объект получает общие блоки с файлом профиля, поэтому второй
копии на диске не появляется вовсе. Эта ветка проверена тестом, но не на живом сервере с такой
файловой системой. На ext4 общих блоков нет, и объект остаётся обычной копией:
папка профиля и хранилище занимают место каждый за себя. Если сборок много и диск дорог, стоит
завести под build.profilesDir и storage.config.root файловую систему с общими блоками — они должны
быть одной файловой системой, иначе делить блоки не с чем.
Garage
Лёгкий self-hosted S3 на Rust, без внешних зависимостей, хорошо тянет разнесённые по географии узлы. Разумный выбор по умолчанию для своего хранилища.
SeaweedFS
S3 поверх быстрого хранилища мелких файлов. Силён там, где объектов очень много, — а к сборкам это относится напрямую.
Backblaze B2
Управляемый S3-совместимый сервис с дешёвым egress (особенно в связке с Cloudflare). Когда держать хранилище самому не хочется.
Если сервер живёт под панелью, хранилище поднимается тем же способом, что и сам лаунчсервер, — импортом egg. В репозитории, в каталоге deploy/pterodactyl, лежат два: egg-garage-s3.json и egg-seaweedfs-s3.json. Импортируются как обычный egg (в Pterodactyl — «Nests → Import Egg», в Pelican — так же).
Egg сам качает бинарь хранилища, при первом запуске заводит ключ доступа и bucket и печатает готовый блок storage для конфига Laminara. Создавать ключ и bucket руками не нужно — Laminara bucket не создаёт и ждёт готовый.