bolt Valebyte VPS від $4/міс — NVMe, запуск за 60 секунд.

Отримати VPS arrow_forward
eco Початковий Туторіал

Garage і SeaweedFS: власне S3-сховище на dedicated-сервері

calendar_month Sep 24, 2026 schedule 19 хв. читання visibility 66 переглядів
Garage и SeaweedFS: своё S3-хранилище на dedicated
info

Потрібен сервер для цього гайду? Ми пропонуємо виділені сервери та VPS у 50+ країнах з миттєвим налаштуванням.

Потрібен сервер для цього гайду?

Розгорніть VPS або виділений сервер за хвилини.

Garage і SeaweedFS: як розгорнути власне S3-сховище на dedicated-сервері

TL;DR

У цьому посібнику ми підготуємо dedicated-сервер і запустимо на ньому два сумісні з S3 сховища: Garage для компактної відмовостійкої інсталяції та SeaweedFS для сценаріїв із великою кількістю об'єктів і масштабуванням за вузлами. Доступ до обох сервісів буде захищено HTTPS, а конфігурації та дані буде підготовлено до резервного копіювання.

  • Garage підійде для простого приватного S3, резервних копій і застосунків.
  • SeaweedFS зручніший за великої кількості файлів, високого навантаження та подальшого горизонтального масштабування.
  • Для тестової єдиної ноди достатньо 4 vCPU, 8 ГБ RAM і NVMe від 500 ГБ.
  • Для production краще використовувати ECC-пам'ять, RAID або ZFS, окремі диски для даних і резервну копію поза сервером.
  • API S3 публікується через Caddy з автоматичними сертифікатами Let’s Encrypt.
  • Резервувати потрібно не лише конфіги, а й дані, ключі доступу, layout Garage і метадані SeaweedFS.

1. Що ми налаштовуємо і навіщо

Схема: 1. Что мы настраиваем и зачем
Схема: 1. Що ми налаштовуємо і навіщо

S3 — це не конкретний сервер, а протокол об'єктного зберігання: застосунки звертаються до bucket, завантажують об'єкти та отримують їх за ключами. Більшість сучасних клієнтів, SDK та інструментів резервного копіювання вміють працювати з S3-compatible API. Тому замість публічної хмари можна запустити власне сховище на dedicated-сервері.

У статті розглядаються два проєкти. Garage — компактне розподілене S3-сховище, орієнтоване на просту експлуатацію та невеликі кластери. SeaweedFS — універсальніша розподілена файлова система з S3-шлюзом, master-сервісом, volume-серверами та filer.

Зазвичай не потрібно використовувати Garage і SeaweedFS одночасно для тих самих даних. Вибирайте один основний backend:

  • Garage — коли потрібен зрозумілий приватний S3, мінімальна кількість компонентів і кілька вузлів у майбутньому.
  • SeaweedFS — коли очікуються мільйони або мільярди невеликих об'єктів, висока швидкість запису та розвиток кластера.
  • Обидва на одному dedicated — лише для лабораторії, міграції, порівняння або розміщення різних незалежних завдань.

Що буде в результаті

Після виконання інструкцій на сервері працюватимуть два незалежні S3 endpoint:

  • https://garage.example.com — S3 API Garage;
  • https://seaweed.example.com — S3 API SeaweedFS;
  • https://garage-admin.example.com — адміністративний інтерфейс Garage, якщо він знадобиться;
  • локальні каталоги з об'єктами на окремому диску;
  • Docker Compose-файли, systemd-керування, firewall і схема резервного копіювання.

У прикладах використовуються домени garage.example.com і seaweed.example.com. Замініть їх на власні домени. DNS-записи мають вказувати на публічну IPv4-адресу сервера, а для IPv6 потрібно окремо перевірити, що firewall і маршрутизацію налаштовано коректно.

Self-hosted або managed S3

Managed S3 знімає з власника сервера завдання експлуатації: резервування, заміну дисків, моніторинг і розширення. Це гарний вибір, якщо важливіша швидкість запуску, ніж контроль над даними. Проте ціна зберігання, вихідного трафіку та великої кількості операцій може суттєво зрости.

Self-hosted S3 дає змогу контролювати диски, ключі, локацію та вартість зберігання. Зворотний бік — відповідальність за резервні копії, відмовостійкість і оновлення повністю лежить на адміністраторі. Один сервер без зовнішньої копії не є надійним сховищем, навіть якщо саме ПЗ підтримує реплікацію.

Критерій Managed S3 Garage або SeaweedFS
Запуск Дуже швидкий Потрібне налаштування сервера
Контроль над даними Обмежений політикою провайдера Повний контроль
Масштабування Зазвичай автоматичне Потрібно планувати самостійно
Відповідальність за бекапи Розподіляється з провайдером На власникові інфраструктури

2. Яка VPS-конфігурація потрібна для цього завдання

Схема: 2. Какой VPS-конфиг нужен под эту задачу
Схема: 2. Яка VPS-конфігурація потрібна для цього завдання

Вимоги залежать від обсягу даних, розміру об'єктів і кількості запитів. S3-сховище здебільшого впирається в дискову підсистему та мережу, а не в частоту CPU. Для великої кількості невеликих файлів SeaweedFS споживає більше RAM на метадані та фонові операції, ніж простий Garage-кластер.

Сценарій CPU RAM Диск Мережа
Лабораторія та тести 2 vCPU 4 ГБ 100 ГБ SSD 100 Мбіт/с
Невеликий production 4 vCPU 8–16 ГБ 500 ГБ–2 ТБ NVMe 1 Гбіт/с
Багато об'єктів і активний API 8–16 vCPU 32–64 ГБ 2–8 ТБ NVMe або окремий storage 1–10 Гбіт/с

Практичний стартовий варіант

Для однієї production-ноди, на якій одночасно запускаються Garage, SeaweedFS і Caddy, розумна стартова конфігурація — 8 vCPU, 16 ГБ RAM, 1 ТБ NVMe, публічний IPv4 і порт 1 Гбіт/с. Якщо планується використовувати лише один backend, можна почати з 4 vCPU і 8 ГБ RAM.

Як один із варіантів можна підібрати dedicated з такими характеристиками. Конкретний тариф не є частиною архітектури: важливі продуктивність дисків, доступ до резервних копій, ліміт трафіку та можливість додати другий диск.

Чому dedicated може бути кращим за VPS

Dedicated є кращим, якщо дані займають сотні гігабайтів або терабайти, потрібна передбачувана I/O-продуктивність і планується безперервний запис. На VPS швидкість дисків може залежати від сусідів, а гарантований обсяг диска іноді обмежений тарифом.

Для невеликого bucket, резервних копій і development VPS цілком достатньо. Dedicated стає виправданим за високої кількості операцій, великих послідовних завантажень, вимог до ECC-пам'яті, RAID/ZFS або потреби фізично контролювати диски.

Диски та файлова система

Для об'єктного storage використовуйте локальний NVMe або enterprise SSD. Не розміщуйте дані на системному розділі без окремого ліміту: заповнення root filesystem може зупинити SSH, Docker і системні служби. Практична схема — окремий том, змонтований у /srv/object-storage.

Для однієї ноди підійдуть XFS або ext4. ZFS корисна за достатнього обсягу RAM і потреби в snapshot, checksumming та керуванні пулом, але вона додає операційну складність. RAID захищає від відмови диска, але не замінює резервну копію.

Локація сервера

Вибирайте дата-центр ближче до застосунків і користувачів. Це зменшує затримку під час завантаження об'єктів і скорочує час роботи multipart upload. Якщо сховище використовується лише для бекапів, важливіші стабільний вихідний трафік і можливість передавати дані в іншу географічну локацію.

Для персональних даних також враховуйте вимоги законодавства, договори з клієнтами та фізичну юрисдикцію дата-центру. Географічна близькість сама по собі не гарантує відповідність вимогам щодо обробки даних.

3. Підготовка сервера

Схема: 3. Подготовка сервера
Схема: 3. Підготовка сервера

Нижче передбачається Debian 12 або Ubuntu Server 24.04 LTS із чистою інсталяцією та користувачем, який має тимчасовий доступ через SSH. Усі команди виконуються від користувача з sudo. У прикладах використовується ім'я storage.

Оновлення системи та базові пакети

Спочатку оновіть індекс пакетів, встановіть виправлення безпеки й інструменти, які знадобляться для Docker, діагностики та резервного копіювання.

sudo apt update && sudo apt full-upgrade -y
sudo apt install -y ca-certificates curl gnupg lsb-release jq vim htop ncdu \
  unzip rsync restic ufw fail2ban dnsutils smartmontools

Створення окремого адміністратора

Не використовуйте root для повсякденної роботи. Створіть користувача, додайте його до sudo та перенесіть публічний SSH-ключ. Команду з ключем замініть на власний ключ.

sudo adduser storage
sudo usermod -aG sudo storage
sudo install -d -m 700 -o storage -g storage /home/storage/.ssh
sudo sh -c 'echo "ssh-ed25519 AAAA_REPLACE_WITH_YOUR_PUBLIC_KEY admin@workstation" > /home/storage/.ssh/authorized_keys'
sudo chown storage:storage /home/storage/.ssh/authorized_keys
sudo chmod 600 /home/storage/.ssh/authorized_keys

Відкрийте нову SSH-сесію та переконайтеся, що вхід працює. Лише після перевірки можна заборонити парольну автентифікацію та root login.

ssh storage@SERVER_IP
sudo install -d -m 0755 /etc/ssh/sshd_config.d
sudo tee /etc/ssh/sshd_config.d/ hardening.conf > /dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
EOF
sudo sshd -t
sudo systemctl reload ssh

В останній команді в реальному терміналі ім'я файлу має бути без пробілу: /etc/ssh/sshd_config.d/hardening.conf. Виправлений варіант:

sudo tee /etc/ssh/sshd_config.d/hardening.conf > /dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
EOF
sudo sshd -t
sudo systemctl reload ssh

Firewall

До увімкнення UFW дозвольте SSH на нестандартному порту, якщо ви його змінювали, а також HTTP і HTTPS для ACME-перевірки та S3 API. Адміністративні порти Garage і SeaweedFS назовні не публікуємо.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Fail2ban і каталог даних

Fail2ban тимчасово блокуватиме адреси з великою кількістю невдалих SSH-входів. Він не замінює ключі, firewall і оновлення, але знижує шум від автоматичних сканерів.

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban --no-pager
sudo mkdir -p /srv/object-storage/{garage,seaweedfs,caddy,data,backup}
sudo chown -R storage:storage /srv/object-storage

Перевірте диск перед розгортанням:

df -hT
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,MODEL
sudo smartctl -a /dev/nvme0n1 | less

Якщо для даних використовується окремий диск, спочатку створіть файлову систему, додайте UUID до /etc/fstab, змонтуйте її в /srv/object-storage і лише потім запускайте контейнери. Не форматуйте диск, доки не перевірили його пристрій через lsblk.

4. Встановлення ПЗ

Схема: 4. Установка ПО
Схема: 4. Встановлення ПЗ

Для ізоляції компонентів використовуємо Docker Engine і Compose plugin. У production краще фіксувати версії образів, а не використовувати тег latest. У прикладах наведено версії, актуальні для практичного розгортання у 2026 році; перед оновленням перевірте release notes і сумісність формату даних.

Встановлення Docker Engine з офіційного репозиторію

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Додайте репозиторій Docker для Ubuntu 24.04. Для Debian замініть шлях ubuntu на debian і codename на bookworm.

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER"

Перезапустіть SSH-сесію або виконайте newgrp docker, після чого перевірте встановлення:

docker run --rm hello-world
docker compose version
sudo systemctl enable --now docker

Версії образів

У прикладі використовуються Garage 2.1.0 і SeaweedFS 3.99. Якщо на момент встановлення вийшли новіші стабільні версії, спочатку протестуйте їх на копії даних. Не можна бездумно змінювати образ із major-версією: у систем зберігання міграція метаданих може бути незворотною.

Створіть робочий каталог і файл Compose:

mkdir -p /srv/object-storage/app
cd /srv/object-storage/app
touch .env docker-compose.yml garage.toml s3.json Caddyfile
chmod 600 .env

Створення секретів

Секрети не повинні зберігатися у публічному Git-репозиторії, Dockerfile або історії команд. Згенеруйте адміністративний токен, access key і secret key через системний генератор випадкових даних.

GARAGE_ADMIN_TOKEN=$(openssl rand -hex 32)
S3_ACCESS_KEY=$(openssl rand -hex 16)
S3_SECRET_KEY=$(openssl rand -hex 32)
sudo tee /srv/object-storage/app/.env > /dev/null <<EOF
GARAGE_ADMIN_TOKEN=${GARAGE_ADMIN_TOKEN}
S3_ACCESS_KEY=${S3_ACCESS_KEY}
S3_SECRET_KEY=${S3_SECRET_KEY}
EOF
sudo chmod 600 /srv/object-storage/app/.env

Збережіть ці значення в менеджері паролів. Втрата access key не знищить дані, але вимагатиме створити новий ключ. Втрата адміністративних секретів ускладнить відновлення доступу.

5. Конфігурація Garage і SeaweedFS

Схема: 5. Конфигурация Garage и SeaweedFS
Схема: 5. Конфігурація Garage і SeaweedFS

Конфігурація Garage

Garage використовує конфігураційний файл TOML і окремий каталог метаданих. Для однієї ноди задамо локальний RPC, S3 API на порту 3900 і web endpoint на порту 3902. У production-кластері RPC-порт має бути доступний лише між вузлами, а не з інтернету.

cat > /srv/object-storage/app/garage.toml <<'EOF'
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "lmdb"

replication_factor = 1
consistency_mode = "consistent"

[rpc]
bind_addr = "[::]:3901"
secret_file = "/run/secrets/garage_rpc_secret"

[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = ".s3.garage.local"

[admin]
api_bind_addr = "[::]:3903"
admin_token = "CHANGE_IN_ENV_OR_SECRET"

[web]
bind_addr = "[::]:3902"
root_domain = ".web.garage.local"
index = "index.html"
EOF

Для production не залишайте рядок із демонстраційним токеном. Залежно від версії Garage синтаксис секції admin може відрізнятися, тому перед запуском звіряйте приклад конфігурації з release notes. Нижче використовується безпечніша схема: адміністративний API не публікується назовні, а Docker-сервіс отримує токен через змінну середовища лише для допоміжних операцій.

Створіть RPC-секрет і структуру каталогів:

openssl rand -hex 32 > /srv/object-storage/app/garage-rpc-secret
chmod 600 /srv/object-storage/app/garage-rpc-secret
mkdir -p /srv/object-storage/data/garage/{meta,data}
chown -R 1000:1000 /srv/object-storage/data/garage

Конфігурація SeaweedFS

На одній машині SeaweedFS можна запустити в режимі master, volume, filer і S3 gateway. Така схема зручна для тесту й невеликого production, але не забезпечує відмовостійкості: відмова сервера означає недоступність усього сховища.

cat > /srv/object-storage/app/s3.json <<'EOF'
{
  "identities": [
    {
      "name": "admin",
      "credentials": [
        {
          "accessKey": "CHANGE_ACCESS_KEY",
          "secretKey": "CHANGE_SECRET_KEY"
        }
      ],
      "actions": ["Read", "Write", "List", "Tagging"]
    }
  ]
}
EOF
chmod 600 /srv/object-storage/app/s3.json

Підставте значення з .env замість CHANGE_ACCESS_KEY і CHANGE_SECRET_KEY. Автоматичне підставлення без відображення секрету в аргументах процесу:

set -a
. /srv/object-storage/app/.env
set +a
sed -i "s/CHANGE_ACCESS_KEY/${S3_ACCESS_KEY}/; s/CHANGE_SECRET_KEY/${S3_SECRET_KEY}/" \
  /srv/object-storage/app/s3.json

Docker Compose

Створіть єдиний Compose-файл. Сервіси Garage і SeaweedFS використовують різні порти й каталоги. Для SeaweedFS застосовано образ chrislusf/seaweedfs:3.99. Якщо офіційний тег змінився, замініть його на перевірений стабільний реліз.

services:
  garage:
    image: dxflrs/garage:v2.1.0
    container_name: garage
    restart: unless-stopped
    command: ["/garage", "-c", "/etc/garage.toml", "server"]
    volumes:
      - /srv/object-storage/app/garage.toml:/etc/garage.toml:ro
      - /srv/object-storage/app/garage-rpc-secret:/run/secrets/garage_rpc_secret:ro
      - /srv/object-storage/data/garage/meta:/var/lib/garage/meta
      - /srv/object-storage/data/garage/data:/var/lib/garage/data
    ports:
      - "127.0.0.1:3900:3900"
      - "127.0.0.1:3902:3902"
      - "127.0.0.1:3903:3903"
      - "127.0.0.1:3901:3901"
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:3903/health"]
      interval: 30s
      timeout: 5s
      retries: 5

  seaweed-master:
    image: chrislusf/seaweedfs:3.99
    container_name: seaweed-master
    restart: unless-stopped
    command: master -ip=seaweed-master -mdir=/data
    volumes:
      - /srv/object-storage/data/seaweedfs/master:/data
    expose:
      - "9333"
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:9333/cluster/status"]
      interval: 30s
      timeout: 5s
      retries: 5

  seaweed-volume:
    image: chrislusfs/seaweedfs:3.99
    container_name: seaweed-volume
    restart: unless-stopped
    command: volume -mserver=seaweed-master:9333 -dir=/data -port=8080
    depends_on:
      seaweed-master:
        condition: service_healthy
    volumes:
      - /srv/object-storage/data/seaweedfs/volume:/data
    expose:
      - "8080"

  seaweed-filer:
    image: chrislusfs/seaweedfs:3.99
    container_name: seaweed-filer
    restart: unless-stopped
    command: filer -master=seaweed-master:9333 -ip=seaweed-filer
    depends_on:
      seaweed-master:
        condition: service_healthy
      seaweed-volume:
        condition: service_started
    volumes:
      - /srv/object-storage/data/seaweedfs/filer:/data
    expose:
      - "8888"

  seaweed-s3:
    image: chrislusfs/seaweedfs:3.99
    container_name: seaweed-s3
    restart: unless-stopped
    command: s3 -filer=seaweed-filer:8888 -port=8333 -config=/etc/seaweed/s3.json
    depends_on:
      - seaweed-filer
    volumes:
      - /srv/object-storage/app/s3.json:/etc/seaweed/s3.json:ro
    ports:
      - "127.0.0.1:8333:8333"

  caddy:
    image: caddy:2.9
    container_name: caddy
    restart: unless-stopped
    depends_on:
      - garage
      - seaweed-s3
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /srv/object-storage/app/Caddyfile:/etc/caddy/Caddyfile:ro
      - /srv/object-storage/data/caddy/data:/data
      - /srv/object-storage/data/caddy/config:/config

Перевірте синтаксис і запустіть сервіси:

cd /srv/object-storage/app
docker compose --env-file .env config
docker compose --env-file .env up -d
docker compose ps
docker compose logs --tail=100 garage
docker compose logs --tail=100 seaweed-master seaweed-s3

Ініціалізація layout Garage

Після запуску Garage необхідно отримати ідентифікатор вузла та призначити йому capacity. Команди залежать від версії CLI й можуть виконуватися всередині контейнера.

cd /srv/object-storage/app
docker compose exec garage garage status
docker compose exec garage garage layout assign \
  -z dc1 -c 800G NODE_ID
docker compose exec garage garage layout show
docker compose exec garage garage layout apply --version 1

Замість NODE_ID підставте ідентифікатор із виводу garage status. Значення 800G має бути меншим за вільне місце на розділі. Для кластера з трьох вузлів використовуйте різні зони, наприклад dc1, dc2, dc3, і replication factor 3.

Створення bucket і ключа також залежить від версії CLI. Загальна послідовність має такий вигляд:

docker compose exec garage garage bucket create backups
docker compose exec garage garage key create app-backups
docker compose exec garage garage bucket allow \
  --read --write --owner backups --key app-backups
docker compose exec garage garage bucket list
docker compose exec garage garage key list

Не надавайте застосункам owner-права без потреби. Для застосунку створюйте окремий ключ і обмежуйте доступ конкретними bucket. Адміністративний ключ зберігайте окремо від ключів автоматичних завдань.

6. TLS, DNS і перевірка роботи

Схема: 6. TLS, DNS і перевірка роботи
Схема: 6. TLS, DNS і перевірка роботи

DNS

Створіть A-записи:

  • garage.example.com → IPv4 сервера;
  • seaweed.example.com → IPv4 сервера.

Якщо використовується IPv6, додайте AAAA-записи лише після перевірки доступності сервера через IPv6. Помилковий AAAA-запис може призвести до того, що частина клієнтів підключатиметься до недоступної адреси.

dig +short garage.example.com
dig +short seaweed.example.com

Caddy і HTTPS

Caddy автоматично отримує сертифікати Let’s Encrypt, якщо домен уже вказує на сервер, а порти 80/443 доступні з інтернету. Усередину Garage і SeaweedFS передається звичайний HTTP-трафік через локальну Docker-мережу; назовні відкривається лише HTTPS.

cat > /srv/object-storage/app/Caddyfile <<'EOF'
garage.example.com {
    reverse_proxy host.docker.internal:3900
    request_body {
        max_size 50GB
    }
}

seaweed.example.com {
    reverse_proxy seaweed-s3:8333
    request_body {
        max_size 50GB
    }
}
EOF

У Linux контейнер Caddy не завжди може звернутися до host.docker.internal без спеціального налаштування. Надійніше додати Garage до спільної Docker-мережі та проксувати за іменем сервісу. Для цього замініть Caddyfile і Compose-файл так, щоб Caddy і Garage перебували в одній мережі:

networks:
  storage_net:

services:
  garage:
    networks:
      - storage_net

  seaweed-s3:
    networks:
      - storage_net

  caddy:
    networks:
      - storage_net

Після додавання мережі використовуйте імена контейнерів:

cat > /srv/object-storage/app/Caddyfile <<'EOF'
garage.example.com {
    reverse_proxy garage:3900
    request_body {
        max_size 50GB
    }
}

seaweed.example.com {
    reverse_proxy seaweed-s3:8333
    request_body {
        max_size 50GB
    }
}
EOF
cd /srv/object-storage/app
docker compose up -d
docker compose logs --tail=100 caddy

Параметр max_size не обмежує фактичний розмір bucket, а захищає reverse proxy від випадково величезного запиту. Для файлів понад 50 ГБ використовуйте multipart upload або збільште ліміт з урахуванням диска й тайм-аутів.

Перевірка HTTP і S3

curl -I https://garage.example.com
curl -I https://seaweed.example.com
curl -vk https://garage.example.com 2>&1 | grep -E "subject:|issuer:|HTTP/"
docker compose ps
docker stats --no-stream

Для S3-клієнта встановіть AWS CLI v2 з офіційного архіву AWS або використовуйте S3-compatible клієнт. Приклад із AWS CLI:

export AWS_ACCESS_KEY_ID='REPLACE_ACCESS_KEY'
export AWS_SECRET_ACCESS_KEY='REPLACE_SECRET_KEY'
export AWS_DEFAULT_REGION='garage'

aws --endpoint-url https://garage.example.com s3 ls
aws --endpoint-url https://garage.example.com s3 mb s3://test-bucket
printf 's3 smoke test\n' > /tmp/test.txt
aws --endpoint-url https://garage.example.com s3 cp /tmp/test.txt s3://test-bucket/test.txt
aws --endpoint-url https://garage.example.com s3 cp s3://test-bucket/test.txt -
aws --endpoint-url https://garage.example.com s3 rb s3://test-bucket --force

Для SeaweedFS замініть endpoint:

aws --endpoint-url https://seaweed.example.com s3 mb s3://seaweed-test
aws --endpoint-url https://seaweed.example.com s3 cp /tmp/test.txt s3://seaweed-test/test.txt
aws --endpoint-url https://seaweed.example.com s3 ls s3://seaweed-test/

Якщо HTTPS ще не налаштовано, тимчасово перевіряйте локальний endpoint через http://127.0.0.1:8333. Не залишайте локальний тестовий endpoint опублікованим на публічному інтерфейсі та не вимикайте перевірку TLS у production-клієнтах.

7. Бекапи й обслуговування

Схема: 7. Бекапи й обслуговування
Схема: 7. Бекапи й обслуговування

Що потрібно резервувати

Об’єктне сховище має кілька типів даних:

  • об’єкти користувачів у каталогах Garage і SeaweedFS;
  • метадані Garage, його layout і конфігурація;
  • master data і filer metadata SeaweedFS;
  • Docker Compose, Caddyfile, JSON-конфігурація та секрети;
  • список bucket, користувачів, access key і політик доступу.

Копіювання лише Docker Compose не відновить файли. Копіювання лише volume-даних без конфігурацій ускладнить запуск. Перед резервуванням складіть документ із версіями образів, точками монтування та командами відновлення.

Restic на окремий сервер

Не зберігайте єдину копію бекапу на тому самому диску. Хороший мінімальний варіант — окремий сервер через SFTP, віддалений S3 з object lock або інший дата-центр. Нижче наведено приклад restic через SFTP. На backup-сервері має існувати користувач restic і каталог репозиторію.

Створіть файл із секретами лише для root:

sudo tee /root/.restic-env > /dev/null <<'EOF'
export RESTIC_REPOSITORY='sftp:[email protected]:/srv/restic/object-storage'
export RESTIC_PASSWORD='CHANGE_TO_LONG_RANDOM_PASSWORD'
export RESTIC_SFTP_COMMAND='ssh -i /root/.ssh/restic_backup_ed25519 -o StrictHostKeyChecking=yes'
EOF
sudo chmod 600 /root/.restic-env

Ініціалізуйте репозиторій один раз і протестуйте з’єднання:

sudo bash -c 'source /root/.restic-env && restic init'
sudo bash -c 'source /root/.restic-env && restic snapshots'

Скрипт бекапу

Для узгодженої копії зупинимо контейнери на коротке вікно обслуговування. Це простіше й безпечніше для однієї ноди, ніж копіювання volume-файлів, що активно змінюються. Для великих сховищ краще використовувати вбудовану реплікацію, snapshot файлової системи або окремий backup-кластер.

sudo tee /usr/local/sbin/object-storage-backup > /dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail

source /root/.restic-env
APP=/srv/object-storage/app
DATA=/srv/object-storage/data
STAMP=$(date +%F-%H%M)
LOG=/var/log/object-storage-backup.log

exec > >(tee -a "$LOG") 2>&1

echo "[$(date -Is)] backup started"
cd "$APP"
docker compose stop garage seaweed-master seaweed-volume seaweed-filer seaweed-s3

restic backup \
  "$APP/garage.toml" \
  "$APP/garage-rpc-secret" \
  "$APP/s3.json" \
  "$APP/Caddyfile" \
  "$APP/docker-compose.yml" \
  "$APP/.env" \
  "$DATA/garage" \
  "$DATA/seaweedfs" \
  --tag object-storage \
  --tag "$STAMP"

docker compose start garage seaweed-master seaweed-volume seaweed-filer seaweed-s3
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
echo "[$(date -Is)] backup completed"
EOF
sudo chmod 700 /usr/local/sbin/object-storage-backup

Файл .env містить секрети, тому його включено до резервної копії лише за умови, що доступ до віддаленого репозиторію суворо обмежений. Якщо політика забороняє зберігати секрети в бекапі, виключіть його та збережіть секрети в окремому зашифрованому менеджері.

Cron і перевірка відновлення

sudo crontab -e

Додайте запуск щоночі о 03:30:

30 3   * /usr/local/sbin/object-storage-backup

Раз на місяць перевіряйте не лише наявність snapshot, а й відновлення окремого об’єкта в тимчасовий каталог:

sudo bash -c 'source /root/.restic-env && restic snapshots --tag object-storage'
sudo mkdir -p /srv/restore-test
sudo bash -c 'source /root/.restic-env && restic restore latest --target /srv/restore-test --tag object-storage'
sudo find /srv/restore-test -maxdepth 4 -type f | head

Бекап, який жодного разу не відновлювали, є припущенням, а не доказом можливості відновлення. Перевіряйте контрольні файли, розмір каталогів, права доступу та можливість запустити контейнери з відновленою конфігурацією.

Оновлення

Перед оновленням зафіксуйте поточні образи:

cd /srv/object-storage/app
docker compose images
docker image ls
sudo bash -c 'source /root/.restic-env && restic backup /srv/object-storage/app --tag pre-upgrade'

Для однієї ноди використовуйте maintenance window: зупиніть запис, зробіть бекап, завантажте новий образ і перезапустіть сервіси.

docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=200 garage seaweed-master seaweed-s3

Rolling update можливий лише в кластері з кількох вузлів із реплікацією та сумісним протоколом. Спочатку оновлюють один вузол, перевіряють healthcheck і операції читання/запису, потім переходять до наступного. Не оновлюйте всі вузли одночасно.

Моніторинг

Мінімально контролюйте вільне місце, inode, RAM, load average, SMART і помилки контейнерів:

df -h /srv/object-storage
df -ih /srv/object-storage
free -h
uptime
docker compose ps
docker compose logs --since=15m garage seaweed-s3
sudo journalctl -u docker --since "15 minutes ago"

Налаштуйте сповіщення при заповненні диска понад 80–85 відсотків. При 95 відсотках сервіси можуть почати повертати помилки запису, а фонові операції відновлення — аварійно завершуватися. Плануйте розширення заздалегідь.

8. Усунення несправностей і FAQ

Чому Caddy повертає 502 Bad Gateway?

Спочатку перевірте стан контейнерів командою docker compose ps і журнали docker compose logs caddy garage seaweed-s3. Якщо Caddy не бачить ім’я сервісу, переконайтеся, що обидва контейнери підключені до однієї Docker-мережі. Якщо використовується host.docker.internal, замініть його на ім’я сервісу, наприклад garage:3900. Також перевірте локальний endpoint через curl http://127.0.0.1:3900 або мережевий запит із контейнера Caddy.

Сертифікат Let’s Encrypt не випускається. Що перевірити?

Перевірте A-записи командою dig, доступність портів 80 і 443 із зовнішньої мережі та відсутність іншого reverse proxy. Для домену не має бути увімкнено неправильний AAAA-запис. Перегляньте docker compose logs caddy. Якщо DNS щойно змінився, дочекайтеся оновлення TTL. Не запускайте багато повторних запитів у разі помилки: Let’s Encrypt застосовує rate limits.

Помилка AccessDenied під час завантаження в S3

Перевірте, до якого endpoint і bucket підключений клієнт, а також значення змінних AWS_ACCESS_KEY_ID і AWS_SECRET_ACCESS_KEY. У Garage ключ повинен мати дозволи на конкретний bucket. У SeaweedFS перевірте формат s3.json і збіг ключів. Для діагностики виконайте aws s3 ls без multipart і перевірте, що системний час синхронізовано через NTP.

Запис завершується помилкою No space left on device

Перевірте не лише вільні гігабайти через df -h, а й inode через df -i. Мільйони маленьких файлів можуть вичерпати inode раніше за місце. Видаляйте старі Docker-образи лише після перевірки, що вони не потрібні для rollback: docker system df. Не видаляйте вручну файли всередині каталогів Garage або SeaweedFS — це може пошкодити метадані та призвести до втрати об’єктів.

Яка VPS-конфігурація мінімально підійде?

Для тестування достатньо 2 vCPU, 4 ГБ RAM і 100 ГБ SSD. Для невеликого production з одним backend розумний мінімум — 4 vCPU, 8 ГБ RAM і 500 ГБ NVMe. Якщо одночасно запускаються Garage, SeaweedFS, Caddy і резервне копіювання, краще взяти щонайменше 8 ГБ RAM, а для активного навантаження — 16 ГБ. Залишайте 20–30 відсотків диска вільними для тимчасових файлів і відновлення.

Що вибрати — VPS чи dedicated для цього завдання?

VPS підходить для development, невеликих bucket, резервних копій і навантаження з передбачуваним I/O. Dedicated краще вибрати за обсягу від кількох терабайтів, великої кількості операцій, потреби в ECC, RAID/ZFS або гарантованій продуктивності дисків. В обох випадках зовнішній бекап обов’язковий. Dedicated з одним диском без копії не захищає від апаратної відмови, помилки адміністратора або шифрувальника.

Чи можна запускати Garage і SeaweedFS на одній ноді в production?

Технічно можна, але це створює конкуренцію за RAM, CPU і дисковий I/O. Така схема допустима для міграції, порівняння або незалежних малих завдань. Для постійної експлуатації виберіть один backend і вимкніть другий. Якщо потрібні різні класи зберігання, краще розділити сервіси за дисками або серверами та задати окремі ліміти ресурсів Docker.

Як зробити сховище відмовостійким?

Одна нода не є відмовостійкою. Для Garage використовуйте кілька вузлів, різні failure domain і replication factor 3. Для SeaweedFS рознесіть master, volume і filer на кілька серверів, увімкніть реплікацію volume та забезпечте окреме зберігання метаданих. Вузли повинні мати незалежне живлення та бажано не перебувати в одному фізичному failure domain. Навіть кластерна реплікація не замінює offline або географічно віддалений бекап.

Як мігрувати з одного сервісу на інший?

Створіть bucket на новому endpoint і перенесіть об’єкти через S3-клієнт, наприклад rclone sync або AWS CLI. Спочатку виконайте пробну міграцію одного bucket, порівняйте кількість об’єктів, розміри та контрольні суми. Після перемикання застосунку залиште старе сховище в режимі читання на період відкоту. Не копіюйте внутрішні каталоги Garage безпосередньо в SeaweedFS: перенесення виконується через S3 API.

9. Висновки та наступні кроки

Схема: 9. Висновки та наступні кроки
Схема: 9. Висновки та наступні кроки

На dedicated-сервері можна розмістити власне S3-сховище на Garage або SeaweedFS, закривши API через Caddy і HTTPS. Для однієї ноди отримано робочу схему з Docker Compose, окремими каталогами даних, обмеженим firewall і резервним копіюванням через restic.

  1. Виберіть один основний backend і проведіть навантажувальний тест із реальним розміром об’єктів.
  2. Додайте другий сервер, реплікацію та моніторинг, якщо дані критичні для бізнесу.
  3. Налаштуйте автоматичне розширення дисків, перевірку відновлення та lifecycle-політики для старих об’єктів.

Чи був цей гайд корисним?

Ваш відгук допомагає нам покращувати гайди.

Share this post:

Надішліть гайд тому, кому він може стати в пригоді.

Telegram VKVK WhatsApp Facebook LinkedIn XX

garage і seaweedfs: власне s3-сховище на dedicated
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.