Хостинг ресурс-пака для Minecraft сервера: полный гайд (2026)

Хостинг ресурс-пака для Minecraft сервера: полный гайд (2026)

Если у тебя на сервере есть кастомные модели через ItemsAdder или Oraxen, переменный шрифт, локализация на четыре языка или просто свой ванильный пак с текстурами под лор, рано или поздно ты упрёшься в один и тот же вопрос: где этот zip-архив должен лежать, чтобы клиент его скачал быстро, без обрывов и без Failed to download resource pack. В этом гайде разбираем, как правильно положить пак на хост, как сгенерировать sha1, какие опции в server.properties нужны на 1.21+, и почему Discord CDN из этой схемы выпал ещё в конце 2024 года.

Зачем хостить пак самому, а не отдавать через плагин

Minecraft 1.20.3+ умеет отдавать игроку до пятидесяти ресурс-паков подряд через серверный API, но сам бандл с текстурами на клиент клиенту приносит не сервер, а HTTP. То есть ванильный mc-клиент идёт напрямую по URL из resource-pack= (или из плагина) и тянет zip обычным GET-запросом. Сервер в этом обмене вообще не участвует: ему всё равно, лежит ли пак рядом с jar-кой или на другом континенте, главное чтобы URL отвечал и hash совпадал.

Из этого следует простое правило: скорость и стабильность загрузки пака никак не зависят от твоего хостинга Minecraft, она зависит от того, где ты положил zip. Если пак раздаётся с дешёвой американской VPS на 100 Mbps, игрок из Польши на средней домашней линии будет ждать 30 секунд только на rope-загрузке, а ещё словит timeout при первом сбое TCP. Если пак лежит за нормальным CDN (Cloudflare, Bunny, R2), та же самая загрузка займёт 2-3 секунды, и неважно, откуда подключается игрок.

Второй момент: force-resource-pack=true плюс правильный resource-pack-sha1 это твой ключ к тому, чтобы клиент не висел на промпте, а либо принял пак автоматически, либо отвалился по Failed to apply resource pack. Без sha1 клиент после каждого захода скачивает пак заново, а это либо лишний трафик, либо лишние секунды загрузки на стороне игрока. С корректным sha1 клиент уже после первой загрузки кеширует архив и при следующем заходе просто берёт его с диска.

Подготовка пака: pack.mcmeta, формат, сборка zip

Перед тем как хоститить, важно убедиться, что пак вообще сложен правильно. Базовая структура для Minecraft 1.21+ выглядит так:

my-pack/
  pack.mcmeta
  pack.png
  assets/
    minecraft/
      textures/
      models/
      lang/
      sounds/

Файл pack.mcmeta для 1.21.4 (Java Edition) содержит pack_format. Для каждой версии клиента число своё, актуальную таблицу всегда смотри на minecraft.wiki в статье Pack format. На середину 2025 года 1.21.4 это pack_format 46, а 1.21 это 34. Если ставишь не то число, клиент не покажет ошибку, но просто не загрузит часть текстур.

{
  "pack": {
    "pack_format": 46,
    "supported_formats": [34, 46],
    "description": "MyServer textures 1.21+"
  },
  "language": {
    "ru_ru": {"name": "Russian", "region": "Russia", "bidirectional": false}
  }
}

Поле supported_formats помогает клиентам разных версий воспринимать один и тот же архив, а language нужен только если ты добавляешь свой lang/ru_ru.json поверх ванильного. Не забудь про pack.png (64x64 или 128x128, обычный PNG), его клиент покажет в списке паков.

Сборка архива. Тут важно zip-нуть содержимое, а не саму папку:

cd my-pack
zip -r -9 ../my-pack.zip . -x "*.DS_Store" -x ".*"

Проверка: unzip -l my-pack.zip | head должен показать pack.mcmeta и assets/ без обёртки my-pack/ сверху. Если внутри zip лежит лишняя папка, клиент скажет Couldn't load resource pack: invalid pack format.

Генерация sha1: sha1sum и онлайн-инструменты

Minecraft проверяет ровно SHA-1 от байтов zip-файла. Никакой соли, никаких трюков. Команда на Linux/macOS:

sha1sum my-pack.zip
8f3a9c1d4e2b6f7a8d9e0f1a2b3c4d5e6f708192  my-pack.zip

На Windows можно через PowerShell:

Get-FileHash -Algorithm SHA1 .\my-pack.zip

Важно: hash должен быть в нижнем регистре в server.properties, иначе ванильный клиент срежет проверку и выдаст pack hash mismatch. Если редактируешь файл вручную, копируй из вывода sha1sum как есть. Если автоматизируешь обновление пака, добавь шаг генерации в свой CI:

HASH=$(sha1sum my-pack.zip | awk '{print $1}')
echo "resource-pack-sha1=${HASH}" > .env.pack

Потом этот .env.pack подмешивается в твой шаблон server.properties при деплое.

Опция 1: GitHub raw

Самый дешёвый и простой способ, особенно если пак уже у тебя в гите. Создаёшь публичный репозиторий, кладёшь туда my-pack.zip, берёшь raw-URL:

https://raw.githubusercontent.com/<user>/<repo>/main/my-pack.zip

Плюсы: бесплатно, версионирование через git тегами и коммитами, простой rollback. Минусы и подводные камни:

  • GitHub официально не рекомендует raw как CDN для бинарников. Если твой пак скачивается несколько тысяч раз в час, ты можешь словить rate limit, а в тяжёлых случаях аккаунт временно ограничат.
  • Размер одного файла в обычном репо ограничен примерно 100 MB, если пак больше, нужен Git LFS, а LFS отдаёт через свой URL и со своими лимитами трафика.
  • Latency средняя. raw.githubusercontent.com отдаёт через сеть GitHub и Fastly, для большинства регионов это нормально, но не всегда лучшее.

Когда подходит: маленький сервер, пак до 20 MB, не более 100-200 онлайн.

Опция 2: Mc-Packs.net

Сервис специально для серверных ресурс-паков. Кидаешь zip через веб-форму на mc-packs.net, получаешь прямой URL и готовый sha1. Обновлять можно той же ссылкой через API (см. документацию на сайте).

Плюсы: бесплатно, не нужен свой хостинг, sha1 они считают сами и показывают рядом с URL. Минусы: ты зависишь от чужого сервиса, при просадках их инфраструктуры пак не загружается у твоих игроков, а ты об этом узнаёшь из чата. Ещё один момент: на бесплатных тарифах нет SLA и нет гарантии, что ссылка будет жить через год.

Когда подходит: тестовый сервер, маленький продакшен, либо как backup mirror для основного хоста.

Опция 3: Cloudflare R2

R2 это S3-совместимое объектное хранилище от Cloudflare, у которого нет egress-платы (это ключевое отличие от AWS S3). За хранение платишь копейки, за загрузку игроками не платишь вообще. Документация на developers.cloudflare.com/r2.

Базовый сценарий:

  1. Создаёшь bucket в R2.
  2. Заливаешь zip через rclone или aws s3 cp с endpoint от R2.
  3. Привязываешь публичный домен (packs.example.net) к bucket через R2 settings.
  4. Ставишь Cache-Control: public, max-age=31536000, immutable на сам zip, чтобы клиенты и edge-кэш Cloudflare не дёргали origin лишний раз.

Пример заливки через rclone:

rclone copy ./my-pack.zip r2:my-bucket/ --header-upload "Cache-Control: public,max-age=31536000,immutable"

URL для server.properties:

https://packs.example.net/my-pack-v12.zip

Я специально пишу -v12 в имени файла. Это проще, чем играть в инвалидацию кеша: новая версия пака получает новое имя, sha1 меняется, старые игроки докачивают новый файл, кеш работает корректно. На R2 это бесплатно, на других CDN тоже хорошая практика.

Плюсы R2: anycast от Cloudflare, никакого egress-биллинга, нативная интеграция с CF cache, простой публичный домен. Минусы: нужно один раз разобраться с Cloudflare API и rclone, но это разовая задача.

Опция 4: Self-hosted nginx или Caddy

Если у тебя уже есть VPS или дедик под сайт сервера, проще всего поднять статический раздел. Минимальный nginx:

server {
    listen 443 ssl http2;
    server_name packs.example.net;

    ssl_certificate /etc/letsencrypt/live/packs.example.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/packs.example.net/privkey.pem;

    root /var/www/packs;

    location ~* \.zip$ {
        add_header Cache-Control "public, max-age=31536000, immutable";
        add_header Access-Control-Allow-Origin "*";
        sendfile on;
        tcp_nopush on;
    }
}

Caddy ещё короче:

packs.example.net {
    root * /var/www/packs
    file_server
    header /*.zip Cache-Control "public, max-age=31536000, immutable"
}

Плюсы: полный контроль, latency почти нулевая если хост сервера и хост паков рядом. Минусы: ты сам отвечаешь за uptime, бэкапы и канал. Если у твоего VPS 100 Mbps и заходит 200 игроков сразу после рестарта, канал ляжет на 30 секунд и кто-то отвалится по timeout.

Хорошая практика: ставить Cloudflare в proxy-режиме (оранжевое облако) поверх своего nginx. Это даёт бесплатное кеширование на edge и сглаживает пики.

Discord CDN: почему НЕ надо

Раньше многие админы заливали zip в служебный канал в Discord и копировали ссылку из вложения. Это работало годами, и до конца 2023 года такие URL были вечными.

В конце 2023 года Discord начал переход на временные подписанные URL (?ex=...&is=...&hm=...), и с весны 2024 это стало нормой для всех вложений. Подпись истекает примерно через 24 часа. То есть если ты сегодня поставил такой URL в server.properties, завтра у твоих игроков будет Failed to download resource pack. Никаких трюков с обновлением подписи через бота тоже не работает: Discord ToS прямо запрещает использовать CDN как hosting для сторонних проектов.

Вывод простой: Discord CDN для серверного пака не пригоден. Если у тебя сейчас в server.properties стоит ссылка вида cdn.discordapp.com/..., переезжай на любой из вариантов выше до того, как игроки начнут жаловаться.

Конфигурация server.properties

В Minecraft 1.21+ на ванильном Paper/Spigot/Folia актуальные опции такие:

resource-pack=https://packs.example.net/my-pack-v12.zip
resource-pack-sha1=8f3a9c1d4e2b6f7a8d9e0f1a2b3c4d5e6f708192
require-resource-pack=true
resource-pack-prompt=Required textures for the server

Что важно знать:

  • resource-pack-sha1 именно так, не resource-pack-hash и не sha-1. Имя опции прописано в minecraft.wiki в разделе Server.properties.
  • require-resource-pack=true это аналог старого force-resource-pack. Если игрок отказывается, сервер его кикает с сообщением из resource-pack-prompt (либо стандартным текстом, если prompt пустой).
  • В 1.20.3 и старше был лимит 224 символа на URL. В 1.20.3+ лимит снят, но не делай URL длиннее 1024 символов на всякий случай, некоторые launcher-ы и моды до сих пор урезают.
  • resource-pack-prompt поддерживает базовый JSON text component, можно красить и переводить.

После правки server.properties обязательно перезапусти сервер, hot-reload этих опций не работает.

Per-player паки: ItemsAdder, Oraxen, force-resource-pack плагины

Через server.properties ты можешь отдать только один пак. Но в 1.20.3+ через серверный API можно слать игроку до пятидесяти паков за сессию, и это используют все большие плагины кастомных предметов.

ItemsAdder и Oraxen уже умеют сами хостить пак: ставишь плагин, он генерирует zip, поднимает встроенный HTTP-сервер либо отдаёт через nginx и шлёт игроку через ProtocolLib или Paper API. Тебе остаётся только проверить, что порт открыт наружу и URL доступен снаружи (а не только из локалки).

Если ты хочешь свой пак сверху, есть плагины класса ResourcePackHost или ForceResourcePack, которые умеют слать пак по событию PlayerJoinEvent через Player#setResourcePack(url, sha1). У них же обычно есть опция per-permission или per-world паков, например в лобби один пак, в выживании другой.

Особый случай: BungeeCord/Velocity. На прокси server.properties уже не работает (там его просто нет), пак нужно слать либо через Velocity API, либо через плагин на самом backend-сервере. Большинство админов делает второе, потому что это даёт точку контроля per-server.

Многоязычные паки

Если у тебя сервер с локализацией на ru/en/de, ты можешь либо собирать один большой пак с папками lang/ для всех языков (клиент сам выберет нужный по настройкам), либо делать несколько паков и слать нужный по геолокации/настройкам игрока через плагин.

Ванильный путь чище: в одном zip кладёшь assets/minecraft/lang/ru_ru.json, en_us.json, de_de.json, и в pack.mcmeta перечисляешь их в секции language. Размер архива растёт незначительно (lang-файлы это json по 50-200 KB), а на стороне игрока всё работает без плагинов.

Если паки сильно расходятся (например текстуры под Halloween-ивент только для ru-клиентов), тогда уже отдавать через плагин с проверкой Player#getLocale().

Таблица: варианты хостинга

СпособЦенаСкоростьЛимитыКогда брать
GitHub rawбесплатносредняя100 MB файл, soft rate-limitмелкий сервер, пак до 20 MB
Mc-Packs.netбесплатносредняябез SLA, чужая инфратест, mirror, маленький прод
Cloudflare R2копейки/месвысокая (anycast)бесплатный egress, бакеты любого размерасредний и большой прод
Nginx/Caddyстоимость VPSзависит от каналатвой uptime, твой backupуже есть VPS под сайт
S3 классика$$$ за egressвысокаяegress дороже всего остальногоесли уже на AWS
Discord CDNбесплатновременно работаетURL живёт 24 чникогда

Debugging: что делать если пак не загружается

Симптомы и куда копать:

  1. Failed to download resource pack. Проверь URL руками через curl -I. Если 200 OK и Content-Type правильный (application/zip или application/octet-stream), идёт дальше. Если 403, значит CDN блокирует, проверь правила. Если timeout, проверь что URL вообще наружу резолвится с другой машины.

  2. Pack hash mismatch. На 99% это рассинхрон sha1 в server.properties и реального файла. Перевычисли через sha1sum, скопируй один в один, перезапусти сервер.

  3. Игроки говорят, что пак скачивается, но текстуры не применяются. Проверь pack_format в pack.mcmeta, скорее всего он не подходит под версию клиента. Можно добавить supported_formats массивом.

  4. Couldn't load resource pack: invalid pack format. Внутри zip лишняя папка-обёртка. Перепакуй через cd my-pack && zip -r ../my-pack.zip ., а не zip -r my-pack.zip my-pack/.

  5. Кастомный CA. Если ты держишь пак за внутренним TLS с самоподписанным сертификатом, ванильный клиент его не примет. Используй Let's Encrypt, ZeroSSL или другой публичный CA.

Версионирование без боли

Самая частая проблема при апдейте пака: ты заменил zip по тому же URL, обновил sha1 в конфиге, перезапустил сервер, а у части игроков всё равно старый пак из кеша. Это происходит потому, что клиент кеширует zip по URL, а не по содержимому.

Решение: каждая новая версия пака получает новое имя файла. Вместо pack.zip пиши pack-v1.zip, pack-v2.zip. Это не требует никакой инвалидации кеша, не требует Cache-Control: no-cache, и новые игроки сразу качают актуальную версию. Старые файлы можно удалить через неделю-другую, когда все доиграли.

Этот же приём решает проблему долгого CDN-кеша: edge-серверы Cloudflare/Bunny могут держать файл сутками, а ты его обновил пять минут назад. С версионированием в имени никакого конфликта.

FAQ

Можно ли отдавать пак по HTTP без TLS? В теории да, ванильный клиент примет http://. На практике делать так не стоит: некоторые корпоративные сети и провайдеры режут http к незнакомым доменам, а Let's Encrypt бесплатный и ставится в две команды.

Что если у меня пак на 200 MB? Технически клиент примет, но задумайся над тем, чтобы делить на base + addon-паки и слать через ItemsAdder/Oraxen API. Большие zip это долгая загрузка для игрока на мобильной связи и больше шансов на обрыв соединения.

Зачем immutable в Cache-Control? Это говорит браузеру/клиенту, что файл по этому URL никогда не меняется. С версионированным именем (pack-v12.zip) это правда, и клиент перестаёт делать revalidation-запросы.

SHA-1 же сломан, можно ли SHA-256? Можно, начиная с Minecraft 1.20.3+ через серверный API через Player#setResourcePack с параметром hash, но в server.properties поле всё ещё resource-pack-sha1. Криптостойкость тут не нужна, hash используется только для валидации целостности и для cache-key.

Что насчёт Bedrock паков? Bedrock-клиент работает иначе: пак раздаётся прямо через Minecraft-протокол, без HTTP. Если у тебя кросс-платформа через Geyser/Floodgate, кастомные паки на Bedrock-стороне делаются отдельно через систему behavior_packs и resource_packs в папке мира.

Можно ли отдавать пак прямо с Minecraft-сервера? Технически да, в Paper можно поднять веб-сервер плагином или открыть файл через external. На практике не стоит: трафик пака конкурирует с трафиком игроков за один и тот же канал, а tick rate проседает на больших нагрузках. Лучше отдельный хост/CDN.

Когда у тебя ресурс-пак раздаётся через CDN с правильным sha1, версионированием и нормальным Cache-Control, история со скачиванием перестаёт быть проблемой. Игрок получает текстуры за пару секунд, кеш работает прозрачно, а ты при апдейте просто заливаешь новый файл с новым именем и подставляешь свежий hash в конфиг.


Защитите свой сервер от DDoS-атак

Бесплатная защита с настройкой за 5 минут. 1 ТБ трафика в подарок.

Попробовать бесплатно


Читайте также