Свой S3 или пошаговая настройка Garage

Опубликовано 27 апр. 2026 г.

Здрасти, здрасти. Теперь по выходным у меня полнейший «цифровой детокс», а причина этому — дача. Круче всякого спортзала прокачивает, а заодно прочищает голову. Физический труд всегда в почёте.

Ладно, это детали… сегодня будем поднимать собственный S3 и да, без хуйни вроде minio и ceph.

 читать первым в телеграм    читать первым в макс

А на помощь к нам приходит «Гараж», в котором мы и будем хранить наши «Вёдра». Garage ориентирован на маленький и средние кластера, домашние сервера и распределенные ноды. И да, он полностью в opensource и не просит денег. Для self-host пиздатейшее решений, да и морда есть из коробки.

Я возьму 3 своих рандомных сервера и сделаю из них кластер. Сервера не пустые, на них что-то крутится и вертится, просто рядышком впендюрю еще одну хуёвинку.

Почему именно 3 сервера? Кластерная классика, если один из серверов пойдёт по пизде, то 2 других соберут кворум и отдадут тебе твои данные. То есть тебе не нужно иметь заранее подготовленные машины, можно взять какойнить хлам и из него запилить кластер под бекапы. И всё это дело будет работать нативно через API S3.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Да, когда ты будешь заливать файлы в своё облако, данные будут реплицироваться на все 3 сервера. Поэтому сервера рекомендую держать в разных регионах или вообще у разных провайдеров. Например, если сгорит один дата центр, то ты не проебешь свои данные. Удобно и надёжно. Ну и смотри в сторону дискового места, если на одном сервере выделил 50 гигов под бакет, то на остальных серверах выдели столько же, чтобы не возникало коллизий.

Прицепом воткнем балансировщик нагрузки, чтобы по домену всё работало. И да, запускать будем в докере.

Поехали настроим это безобразие.

Демон докера надеюсь у тебя уже установлен, поэтому заострять внимание на этом не будем. Заходим на первый сервер и мутим мутки:

Файл compose.yaml:

services:
  garage:
    image: dxflrs/garage:v2.3.0
    ports:
      - "3900:3900"  # S3 API
      - "3901:3901"  # RPC
      - "3902:3902"  # Web (optional)
      - "3903:3903"  # Admin API
    volumes:
      - ./garage.toml:/etc/garage.toml:ro
      - ./meta:/var/lib/garage/meta
      - ./data:/var/lib/garage/data

Думаю, вопросов не должно возникнуть. Банальный композник, порты я тебе все подписал. Версию гаража можешь глянуть в интернете, на момент написания статьи последняя v2.3.0. Да буква «v» тут важна и latest тут не канает.

Рядышком подкидываем конфиг garage.toml:

metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"

replication_factor = 3
consistency_mode = "consistent"

rpc_bind_addr = "0.0.0.0:3901"
rpc_public_addr = "95.95.95.95:3901"
rpc_secret = "5a69376ed4253b21370dbdfda2a5e..."

[s3_api]
api_bind_addr = "0.0.0.0:3900"
s3_region = "garage"

[admin]
api_bind_addr = "0.0.0.0:3903"

Создаём секрет для rpc_secret:

openssl rand -hex 32

Обращаем внимание на параметр rpc_public_addr это общедоступный адрес, можешь связать все 3 сервера приватной сетью через тот же netbird и прописать айпишник сюда. Он нужен для кластера. Все остальные параметры, тоже интуитивно понятны.

Например consistency_mode нужен, чтобы соблюдать строгую консистентность, прям как в настоящих S3.

Запускаем: docker compose up

Супер, мастер нода успешно запущена. Теперь можно добавить ключик -d и запустить контейнер в фоне.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
На варнинг «No valid previous cluster layout stored» не обращаем внимания, оно говорит — «Я не нашёл старую конфигурацию кластера, начинаю с нуля».

Теперь отправляемся на 2 других сервера и конфигурируем их. Будут нюансы, поэтому повнимательнее.

Композник оставляем такой же, как и на первой ноде, а в конфиге меняем только параметр rpc_public_addr. Запускаем в фоне docker compose up -d.

Запускаем в консоли:

docker exec -it garage-garage-1 /garage node id

И смотрим выхлоп:

Что-то есть. Дальше план такой:

  • Поднимаем оставшиеся ноды
  • Получаем их IDшники
  • Собираем кластер

Так, айдишники у нас на руках, идем на первую ноду и добавляем 2 других ноды:

docker exec -it garage-garage-1 /garage node connect ID2
docker exec -it garage-garage-1 /garage node connect ID3

В ID2 и ID3 подставляем те самые строки вида:

193e204ac94c92d0a81e59841735@79.45.31.104:3901
e77af28b18504c80ca57f61dd3cd@102.51.11.56:3901

Проверяем связку:

docker exec -it garage-garage-1 /garage status

Отлично, оно живое. Продолжаем разговор.

Поздравляю, кластер S3 успешно собран. Теперь нужно пройтись напильником:

docker exec -it garage-garage-1 /garage layout assign 193e204ac94c92d0 -z z1 -c 1G
docker exec -it garage-garage-1 /garage layout assign 86535d1f65cde795 -z z2 -c 1G
docker exec -it garage-garage-1 /garage layout assign b897100c9b408729 -z z3 -c 1G

Айдишники меняем на свои (выше на скрине они есть, когда запрашивает статус кластера), следом указываем зону и размер стораджа. Для примера я выставил 1 гигабайт. Для синтетических тестов этого вполне хватит.

Смотрим что у нас получилось:

docker exec -it garage-garage-1 /garage layout show

Видим что всё прекрасно, все 3 ноды видны, они в кластере, доступен 1 гигабайт.

Применяем:

docker exec -it garage-garage-1 /garage layout apply --version 1

Аще заебись! Снова смотрим статус:

docker exec -it garage-garage-1 /garage status

Вуаля, хранилище создано и введено в эксплуатацию. Гараж балансирует данные и синхронизирует ноды.

Теперь у тебя есть полноценный и свой собственный S3. Можешь его теперь ебать и в хвост и в гриву.

А как? Ну для начала нужно сгенерить API ключик, выполняем:

docker exec -it garage-garage-1 /garage key create bashdays-key

Получаем ожидаемый результат. Тут нужно забрать Key ID и Secret key, они пригодятся для подключения.

Создаем первый bucket:

docker exec -it garage-garage-1 /garage bucket create bashdays-bucket

Выдаем доступ:

docker exec -it garage-garage-1 /garage bucket allow --read --write --owner bashdays-bucket --key bashdays-key

Ну и всё. теперь можно проверить, я взял rclone и сконфигурировал так:

[garage]
type = s3
provider = Other
access_key_id = GK5eba63ef8f5
secret_access_key = a0333b9e7a9d61f
region = garage
endpoint = http://103.90.33.11:3900

Можем подключиться:

rclone lsd garage:

В результате видим:

-1 2026-04-27 14:30:49 -1 bashdays-bucket

То есть rclone успешно подключился по протоколу S3 и увидел наш созданный бакет. Давай загрузим файл и посмотрим как оно все пройдет:

echo "hello from garage" > /tmp/bashdays.txt
rclone copy /tmp/bashdays.txt garage:bashdays-bucket
rclone ls garage:bashdays-bucket

Что и требовалось доказать:

Всё прекрасно работает. Забираем файл обратно:

rclone copy garage:bashdays-bucket/bashdays.txt .

Красота неописуемая! Ну а теперь проверяем отказоустойчивость, гасим первый сервер docker compose down и смотрим статус. Статус запрашиваем на втором сервере:

Видим что первая нода пошла по пизде, но кластер не развалился. Запрашиваем файл со второй ноды. Но предварительно в rclone конфиге меняем endpoint на айпишник второй ноды.

rclone copy garage:bashdays-bucket/bashdays.txt .
 cat bashdays.txt

Вот и произошла кластерная магия. Первый сервер сгорел, но наши данные не утеряны, у нас есть к ним доступ. Возвращаем первую ноду встрой и смотрим:

Супер, всё успешно восстановилось:

Основная настройка на этом закончена. Чуть позже покажу тебе как делать прямые ссылки на файлы, чтобы каждый желающий смог скачать файлы с твоего хранилища. Ну и накинем haproxy, чтобы оно прям по всем бест-практикам себя чувствовало.

А пока на этом всё, настоятельно рекомендую потыкать эту настройку и проникнуться.

Комментарии