Хостинг ресурс-пака для 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.
Базовый сценарий:
- Создаёшь bucket в R2.
- Заливаешь zip через
rcloneилиaws s3 cpс endpoint от R2. - Привязываешь публичный домен (
packs.example.net) к bucket через R2 settings. - Ставишь 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: что делать если пак не загружается
Симптомы и куда копать:
-
Failed to download resource pack. Проверь URL руками черезcurl -I. Если 200 OK и Content-Type правильный (application/zip или application/octet-stream), идёт дальше. Если 403, значит CDN блокирует, проверь правила. Если timeout, проверь что URL вообще наружу резолвится с другой машины. -
Pack hash mismatch. На 99% это рассинхрон sha1 вserver.propertiesи реального файла. Перевычисли черезsha1sum, скопируй один в один, перезапусти сервер. -
Игроки говорят, что пак скачивается, но текстуры не применяются. Проверь pack_format в
pack.mcmeta, скорее всего он не подходит под версию клиента. Можно добавитьsupported_formatsмассивом. -
Couldn't load resource pack: invalid pack format. Внутри zip лишняя папка-обёртка. Перепакуй черезcd my-pack && zip -r ../my-pack.zip ., а неzip -r my-pack.zip my-pack/. -
Кастомный 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 ТБ трафика в подарок.
Попробовать бесплатноЧитайте также
Как скрыть IP Minecraft сервера: полный гайд
Открытый IP сервера - главная причина успешных DDoS-атак. Разбираем, как именно атакующие находят ваш реальный IP, и что сделать, чтобы его невозможно было вычислить.
Skyblock сервер с нуля: настройка на BentoBox и не только
Полный гайд по запуску Skyblock сервера на Paper 1.21: BentoBox и BSkyBlock, альтернативы вроде SuperiorSkyblock2 и ASkyBlock, настройка экономики, вызовов, уровней острова и защиты от гриферов.
Тренды DDoS-атак на Minecraft серверы в 2026 году
Разбираем главные тренды DDoS-атак на Minecraft-серверы в 2025-2026: рост объемов, новые векторы атак, умные ботнеты и как от всего этого защититься.