A Thunderstore modpack is a small zip containing four files and no mods: a manifest.json whose dependencies list names every mod and version your server runs, a 256 by 256 icon.png, a README.md, and optionally a config folder. You upload it under a team name, and from then on every player installs your exact set with one click in r2modman, Gale or Thunderstore Mod Manager. The catch is in the word "private": Thunderstore has no private or unlisted packages, so a modpack is public the moment it is uploaded. If that matters, share an exported profile file instead. If it does not, a published pack is the cleanest way to keep a group on the same versions for months, provided you update it deliberately rather than every time a mod author does.
Modpack, profile code or profile file#
There are three ways to hand a group the same set of mods, and they solve slightly different problems.
| Method | Where it lives | Lifetime | Who can see it |
|---|---|---|---|
| Profile code | Thunderstore's profile sharing service | Temporary, codes expire | Anyone with the code |
Profile file (.r2z) | A file you send around | Permanent | Whoever you send it to |
| Thunderstore modpack | A package on thunderstore.io | Permanent, versioned | Everyone |
A profile code is the quickest, and the right tool for a first evening. An exported .r2z is permanent and carries the config folder, which makes it the best private option - r2modman profiles for a group covers both. A modpack is worth the extra work when any of these is true:
- The group changes. New players arrive weeks later and should not have to find a file pinned in a Discord channel.
- You run a public or semi-public server and want a link on the server's description that always points at the current set.
- You want version history. Every upload is a numbered version, and the manager tells each player when a new one exists.
- Players use different managers. Thunderstore packages are the common format every manager reads.
What a modpack is not: a way to redistribute other people's mods. A pack depends on mods; it does not contain their .dll files. Thunderstore's rules forbid re-uploading another author's work, and a pack that bundles copies will be removed. The dependency mechanism exists precisely so that you do not have to.
The layout of the zip#
The upload is one zip archive, and the files must sit at its root - not inside a folder. Zipping the folder rather than its contents is the commonest reason an upload is rejected.
LongshipCrew_Modpack-1.0.0.zip manifest.json icon.png README.md CHANGELOG.md optional, shown on its own tab config/ optional, mod settings for clients com.example.somemod.cfgThe file name of the zip does not matter to Thunderstore, but naming it after the package and version keeps your own folder readable when you have twelve of them.
The requirements Thunderstore enforces at upload:
- `manifest.json` - valid JSON, with the fields described in the next section.
- `icon.png` - a PNG of exactly 256 by 256 pixels. Not 512, not a JPEG renamed. A plain coloured square with the server's initials is fine; nobody browses modpacks for their art.
- `README.md` - rendered as the package page. It can be short, but it must exist.
CHANGELOG.md is optional. If present, the package page shows it on a Changelog tab, which is the most useful thing you can give players who want to know why the manager is offering them an update.
manifest.json, field by field#
This is the whole file for a small group pack:
{ "name": "LongshipCrew_Modpack", "version_number": "1.0.0", "website_url": "", "description": "Mods for the Longship Crew server. Install this, then join.", "dependencies": [ "denikson-BepInExPack_Valheim-5.4.2202", "ValheimModding-Jotunn-2.20.1", "ValheimModding-HookGenPatcher-0.0.4", "RandyKnapp-EpicLoot-0.10.3", "Advize-PlantEverything-1.18.2" ]}The version numbers above are examples of the format, not a recommendation - copy the real ones from each package page, as described below.
| Field | Rule | Notes |
|---|---|---|
name | Letters, digits and underscore only | No spaces, no hyphens. It becomes part of the URL and cannot be renamed later |
version_number | Major.Minor.Patch | Three numbers. Each upload needs a version that has not been used before |
website_url | A URL or an empty string | The field must be present; "" is accepted |
description | Up to 250 characters | Shown in search results inside every manager |
dependencies | Array of dependency strings | The mod list itself |
The name restriction trips people because hyphens are forbidden for a reason: the hyphen is the separator in dependency strings. Longship-Crew would be ambiguous; Longship_Crew is not.
Thunderstore also publishes a manifest validator on its site under Tools. Paste the file in before you zip, and you find the missing comma before the upload form does.
Dependency strings
Each entry is Namespace-PackageName-Version, where the namespace is the uploading team, not necessarily the author's display name. You do not need to guess any part of it: every Thunderstore package page shows its dependency string for the version you are looking at, ready to copy. Go to the version list on the page if you want an older one.
Three things to get right:
- Include the loader and the libraries.
BepInExPack_Valheimbydeniksonis the BepInEx build for Valheim and should be in every pack. Libraries such as Jotunn and HookGenPatcher are pulled in as dependencies of the mods that need them, but listing them explicitly pins their version too, which is what stops a library update quietly breaking the set. - One entry per package. Two versions of the same mod in the list is an error waiting to happen, and some managers will install whichever they meet last.
- Leave out what the server forbids. If the server does not run a client-side mod that changes rules - a carry-weight tweak, a stack-size mod - do not ship it in the pack. A player who has it and connects to a server without it is out of step with everyone else.
Publishing it on thunderstore.io#
You need an account and a team. Sign in to thunderstore.io (it offers Discord, GitHub and Overwolf sign-in), open your settings, and create a team. The team name is the namespace that prefixes your package in every dependency string, and like the package name it is effectively permanent, so choose something you will not be embarrassed by in a year - the server's name is usual.
Then:
- Open the upload page from the site menu and select the zip.
- Choose the Valheim community. Uploading to the wrong one is easier than it sounds, because the form remembers your last choice.
- Choose the Modpacks category, plus any others that describe the content honestly.
- Tick the NSFW box only if it applies, and submit.
If the form rejects the upload, the message names the problem: icon dimensions, a manifest field, a version that already exists. Fix it and upload again. Once accepted, the package appears in the Valheim listing and in every manager's search, normally within a few minutes.
Treat every published version as permanent. You cannot quietly edit an uploaded version, and you should not plan on deleting one; the fix for a broken release is a new version with a higher number. That is a feature as well as a limit: a player who imported 1.2.0 in March can still find exactly what it contained.
For anyone who publishes often, Thunderstore maintains a command-line tool, tcli, which builds the zip from a project folder and uploads it with a token created in your team settings. It is overkill for a pack updated once a month, and its configuration format has changed between releases, so read its own README rather than a copied example if you go that way.
Shipping config files with the pack#
A modpack can carry settings as well as mods. Files in a top-level config folder of the zip are copied by r2modman and the managers built on it into the profile's BepInEx/config when the pack is installed. This is how you get every client's interface mods, keybind-free defaults and client-side values identical from the first launch.
What belongs there, and what does not:
- Client-only settings you want shared. Map pin defaults, an agreed hotkey layout, a quality-of-life mod configured the way the group decided.
- Not server-synced settings. If a mod pushes its config from the server - most mods built on ServerSync or Jotunn's admin-only sync do - the client copy is overwritten on connect. Shipping it is harmless but pointless, and it misleads anyone who edits it expecting a change. How ServerSync and config enforcement work explains which side wins.
- Not BepInEx.cfg unless you have a specific reason. The loader's own settings are best left at the pack's defaults on clients.
Test what your manager does on an update. Some versions replace config files from the pack on every update, which resets a player's personal changes; others leave existing files alone. Install the pack in a fresh profile, change a setting, update the pack, and look. If players lose their personal settings, keep the shipped config to the few files that genuinely must match.
Putting the same set on the dedicated server#
No manager installs a modpack onto a server. The server needs the same plugins in its BepInEx/plugins, and you get them there by hand. The reliable method uses a profile as the source:
- Import your own modpack into a clean profile on your PC. This proves the published pack resolves, and gives you the exact files.
- In the manager's settings, use the option to browse the profile folder. For r2modman this lives under
%AppData%\r2modmanPlus-local\Valheim\profiles\<profile name>on Windows. - Copy
BepInEx/pluginsfrom the profile to the server'sBepInEx/plugins, leaving out mods that are client-only. - Copy any
BepInEx/patcherscontent too. HookGenPatcher lives there, not inplugins. - Start the server once, stop it, then edit the generated configs in the server's
BepInEx/config. - Start again and compare the plugin lines in the log with your manifest.
$ grep -o 'Loading \[[^]]*\]' BepInEx/LogOutput.log | sortLoading [EpicLoot 0.10.3]Loading [Jotunn 2.20.1]Loading [PlantEverything 1.18.2]BepInExPack itself goes on the server too, but from its own download, unpacked into the server root as Valheim mods with BepInEx on a server describes, rather than copied piecemeal out of a client profile. On a RE:NODE Valheim server the upload is the file manager or SFTP - drag the plugins folder in, or upload a zip and unpack it in place - and the console shows the BepInEx banner and each Loading line live as the server starts.
Client-only mods are worth leaving off the server even when they would load. Most are harmless on a headless process; a few touch the interface at start and throw exceptions, and every extra plugin is one more line to read when something genuinely breaks. If you are unsure which side a mod belongs on, the author's page says, and the BepInEx log guide shows what a client mod failing on a server looks like.
Updating the pack as mods change#
The pack is only useful if it matches the server, and it stops matching the day someone updates one side and not the other. A routine that holds up:
- Decide to update, rather than following the authors. A new Epic Loot release is not a reason to change the pack on a Tuesday night. Batch changes, and do them before a session rather than during one.
- Back up the server's `BepInEx` folder and the world. A lockable backup of the last working state is the thing you restore when the new set misbehaves. Backups that actually restore is the argument for testing it.
- Update a test profile first. Change the versions in a copy of the profile, launch, load a copy of the world locally if the change is large, and confirm it starts clean.
- Bump the version number. Patch for a version bump of one mod, minor for adding or removing a mod, major for a change that needs a fresh world or breaks saves.
- Write the changelog line. One line per change, with the reason.
- Upload, then update the server, then tell the group. In that order, and in the same hour. The window between the server changing and the players updating is when people are kicked for a mismatch.
## 1.3.0- Added PlantEverything (agreed in Discord, 12 Oct)- Jotunn 2.20.1, required by the new Epic Loot## 1.2.1- Epic Loot 0.10.3 - fixes the enchanting table crashAfter a Valheim patch, the order is different: the game update breaks mods until their authors catch up, so the pack waits for them, and the server waits for the pack. What to do when a mod update breaks has the general procedure, and kicked for mod version mismatch covers the messages players see when the sides drift.
Troubleshooting the upload and the install#
"Manifest is invalid" or a field error at upload. Usually a hyphen or space in name, a two-part version like 1.0, a missing website_url, or a trailing comma after the last dependency. Run the file through the validator.
"Icon must be 256x256". Exactly that size, PNG format. Re-export rather than renaming another format.
The upload says the package has no manifest. The files are inside a folder in the zip. Open the archive; you should see manifest.json immediately, not a directory.
"Version already exists". You re-uploaded without bumping version_number. Increase it, even for a one-character README fix.
Players import the pack and a mod is missing. A dependency string has a typo in the namespace or a version that was never published. Every string should be copied from a package page, not typed.
The pack installs but players are still kicked on connect. The server does not match the pack. Compare the server's Loading lines with the manifest; the difference is the answer. The usual culprit is a library updated on the server by hand.
Players' settings reset after every pack update. The pack ships config files the manager is overwriting. Trim the config folder to the files that must match.
FAQ#
Can I make a Thunderstore modpack private?
No. Thunderstore has no private or unlisted packages; anything uploaded is visible to everyone. For a private group, export the r2modman profile as a .r2z file and share it directly. It carries the same mod list and configs.
Do I need permission to put someone's mod in my modpack?
Not to depend on it. A modpack lists mods by dependency string and each player downloads them from the author's own package, which is how Thunderstore intends modpacks to work. Copying an author's files into your zip is a different matter and is not allowed.
Will players get my updates automatically?
The manager shows that a newer version of the pack exists and offers to update it. Most do not apply it without the player clicking, which is why a short announcement in the group's chat on the day you update saves a round of kicks.
Does the modpack install BepInEx on the server?
No. Modpacks are installed by mod managers into client profiles. The server needs BepInExPack unpacked into its root and the same plugins copied into BepInEx/plugins, done by hand over SFTP or a file manager.
Can I put Xbox players on a server that uses my pack?
Only if every mod in the pack is optional for clients. Console players cannot install mods, so a pack of client-and-server mods makes the server PC-only regardless of the crossplay setting.
What if a mod in my pack is deprecated or removed?
Older versions usually remain downloadable, so existing installs keep working, but do not build on it. Find the replacement, test it on a copy of the world, and publish a new version of the pack that swaps it out.


