Ship private or paid Deadlock mods with automatic updates
Selling mods, or sharing them with a small group? Frogtech Mod Loader can install them from your own private repository. Each person gets a key, sees only the mods that key unlocks, and gets your updates automatically. This guide sets it up on Cloudflare's free tier in about half an hour.
How it works
- Your repository file (
repo.json) and your mod zips live on a small server you control. - A buyer adds your repository in the loader with their key. The loader sends the key with every request, as
Authorization: Bearer <key>, and only ever to your server's address. - Your server checks the key, lists only the mods it unlocks, and only hands out those downloads.
- You raise a version in
repo.json: every buyer gets the update, usually within the hour.
1. Set up storage and keys
- 1
Make a free Cloudflare account, then install Wrangler, its command-line tool, and sign in:
npm install -g wrangler wrangler login - 2
Create a storage bucket for your files:
wrangler r2 bucket create my-mods - 3
Create a key store, and note the id it prints:
wrangler kv namespace create KEYS
2. The server
Save this as worker.js. It checks the key, filters repo.json to the mods that key owns, and serves only those downloads.
// worker.js: a private Frogtech Mod Loader repository on Cloudflare Workers
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = (request.headers.get('Authorization') || '').replace(/^Bearer /, '');
// KEYS (KV): each buyer's key -> the ids of the mods they own, like ["cool_hud"]
const owned = key ? JSON.parse((await env.KEYS.get(key)) || 'null') : null;
if (!owned) return new Response('Key not accepted', { status: 401 });
if (url.pathname === '/repo.json') {
// FILES (R2): repo.json and the mod zips; each buyer only sees their mods
const repo = await (await env.FILES.get('repo.json')).json();
repo.mods = repo.mods.filter((m) => owned.includes(m.id));
return Response.json(repo);
}
const m = url.pathname.match(/^\/dl\/([a-z0-9_-]+)_v[0-9.]+\.zip$/);
if (m && owned.includes(m[1])) {
const file = await env.FILES.get(url.pathname.slice(1));
if (file) return new Response(file.body, { headers: { 'content-type': 'application/zip' } });
}
return new Response('Not found', { status: 404 });
}
};Next to it, a wrangler.toml that connects the bucket and the key store:
name = "my-mods"
main = "worker.js"
compatibility_date = "2026-10-01"
[[r2_buckets]]
binding = "FILES"
bucket_name = "my-mods"
[[kv_namespaces]]
binding = "KEYS"
id = "<the id from step 1>"Then deploy it. Your repository is now at https://my-mods.<you>.workers.dev/repo.json.
wrangler deploy3. Upload a mod
- 1 Zip your mod (with its
pak01_dir.vpkinside) as<id>_v<version>.zip, for examplecool_hud_v1.0.zip. - 2
Get its checksum. On Windows use
certutil -hashfile cool_hud_v1.0.zip SHA256instead.sha256sum cool_hud_v1.0.zip - 3 Write
repo.jsonwith the checksum, like below. - 4
Upload the zip and
repo.json:wrangler r2 object put my-mods/dl/cool_hud_v1.0.zip --file cool_hud_v1.0.zip --remote wrangler r2 object put my-mods/repo.json --file repo.json --remote
{
"format": 1,
"name": "My Private Mods",
"mods": [
{ "id": "cool_hud", "name": "Cool HUD", "version": "1.0",
"url": "https://my-mods.<you>.workers.dev/dl/cool_hud_v1.0.zip",
"sha256": "<from sha256sum>", "tags": ["HUD"] }
]
}Tip: The download links point at your own server (the /dl/ path), so the loader sends the key there too. Links on other hosts never receive the key.
4. Give someone access
- 1
Make a long random key:
openssl rand -hex 24 - 2
Store which mods that key unlocks:
wrangler kv key put --namespace-id <id> "<key>" '["cool_hud"]' --remote - 3
Send the buyer the key and this link, which opens the loader's Add repository dialog:
frogmod://repo/add?url=https%3A%2F%2Fmy-mods.<you>.workers.dev%2Frepo.json
To take access away, delete the key. Their loader then shows "Key not accepted" and stops updating your mods.
wrangler kv key delete --namespace-id <id> "<key>" --remoteShipping an update
- 1
Upload the new zip with the higher version in its name:
wrangler r2 object put my-mods/dl/cool_hud_v1.1.zip --file cool_hud_v1.1.zip --remote - 2
Change that mod's
version,urlandsha256inrepo.json, and upload it again:wrangler r2 object put my-mods/repo.json --file repo.json --remote
That's it: every buyer's loader installs it the next time Deadlock is closed.
Selling keys
Any shop that can send you a webhook or let you deliver a code works: Ko-fi, Patreon, Gumroad or your own site. Make a key when someone buys, store it as in step 4, and send it to them. For free mods you don't need any of this: our GitHub template hosts a public repository for free.
Related
More guides
- How to mod Deadlock: install mods and keep them working
- How to play Deadlock 4:3 stretched
- Deadlock mods not working after an update
- How to move and resize the Deadlock HUD
- Find and install GameBanana mods for Deadlock
- Colorblind settings for Deadlock
- Make the Deadlock HUD and text bigger
- Custom crosshairs in Deadlock
- A cleaner Deadlock HUD: setup tips
- How to see a player's hours and Steam profile in Deadlock