Files
ulicraft-server-v1/plan/10-assets-mirror.md
2026-05-24 04:03:42 +02:00

5.2 KiB
Raw Blame History

Assets mirror — offline Minecraft asset objects for clients

Summary

Guest launchers (FjordLauncherUnlocked, a Prism soft-fork) download ~400600 MB of asset objects (textures, sounds, lang) from resources.download.minecraft.net on first instance launch. For an air-gapped party that's the single biggest client-side download. Fjord/Prism expose an "Assets Server" override, so we mirror the objects onto our host and point guests at it.

tooling/mirror-assets.sh downloads + verifies every asset object for the pinned Minecraft version and lays them out so Caddy can serve them in the exact path shape the launcher expects.

Fjord/Prism override fields (confirmed)

Settings → APIs → Services tab:

Field Setting key Default What it overrides
Assets Server ResourceURL https://resources.download.minecraft.net/ asset objects only
Metadata Server (meta URL) https://meta.prismlauncher.org/v1/ Prism-format version meta
  • Added in Prism 10.0.0 (PR #3875); inherited by Fjord.
  • There is NO libraries-URL field. Library + client.jar URLs live inside the version/meta JSON; only a meta mirror (or DNS spoof) can redirect them.

⚠️ HTTPS is forced

PR #3875 validates the Assets Server URL as HTTPS and auto-rewrites http://https://. So the assets mirror must be served over TLS — plain :80 Caddy will not work for this endpoint. This pulls local TLS forward for one subdomain ahead of the rest of the stack.

Options to satisfy it:

  1. Caddy TLS on assets.${BASE_DOMAIN} with a cert from a local CA (step-ca); guests import the CA root once. Cleanest, matches homelab.
  2. Caddy internal CA / self-signed — guests must trust it (more friction, per machine).
  3. Sidestep entirely with pre-seed (below) and skip the Assets Server override.

What this mirror does and does NOT cover

Client download Host Covered here?
asset objects (bulk) resources.download.minecraft.net this mirror + Assets Server field
asset index json meta/piston ⚠️ fetched here for completeness; launcher still pulls it from meta unless meta is also mirrored
libraries libraries.minecraft.net no override field
client.jar piston-data.mojang.com
version/meta json meta.prismlauncher.org (separate Metadata Server field)

Full client air-gap therefore needs more than this. For the uncovered, small (~150 MB) remainder, the pragmatic fallback is pre-seed: each guest launches the instance once while online (on arrival, before air-gapping); Prism caches libraries/jar/meta locally. The assets mirror still saves the heavy 400 MB+ per guest. A full meta+libraries mirror (mcm-style / PrismLauncher-meta gen) is the heavyweight alternative, deferred.

tooling/mirror-assets.sh — design

Input: MC_VERSION (default 1.21.1, or read from the pre-baked server's version.json). Cautious: verifies SHA1 on every file, halts on mismatch, idempotent (skips already-valid files).

1. GET https://piston-meta.mojang.com/mc/game/version_manifest_v2.json
   → find entry for $MC_VERSION → version-json URL
2. GET version-json → read .assetIndex { id, url, sha1 }
3. GET asset index → mirror/assets/indexes/<id>.json   (verify sha1)
4. For each object in index .objects{}:
     hash=<sha1>;  rel="${hash:0:2}/${hash}"
     dest="mirror/assets/objects/${rel}"
     [ -f "$dest" ] && sha1 ok → skip
     else GET https://resources.download.minecraft.net/${rel} → $dest ; verify sha1
5. Report counts; non-zero exit on any failure.

Layout served by Caddy:

mirror/assets/
├── indexes/<id>.json        # e.g. 17.json / 1.21.json (for pre-seed/meta use)
└── objects/<2hex>/<sha1>    # launcher requests <ResourceURL>/<2hex>/<sha1>

Caddy wiring

Serve the objects dir at the web root of an HTTPS vhost so the launcher's <ResourceURL>/<2hex>/<hash> resolves directly:

https://assets.{$BASE_DOMAIN} {
	tls <local-ca-cert> <key>      # or `tls internal`
	root * /srv/assets/objects
	file_server
}

Mount ./mirror/assets/objects:/srv/assets/objects:ro. Add network alias assets.${BASE_DOMAIN} to Caddy (same trick as auth/packwiz). Fjord "Assets Server" = https://assets.${BASE_DOMAIN}/.

Tasks

  • Write tooling/mirror-assets.sh (above); chmod +x; deps curl + jq + sha1sum
  • Decide MC_VERSION source: hardcode 1.21.1 vs read pre-baked version.json
  • Run pre-party while online; verify mirror/assets/objects/ populated + sha1 clean
  • Stand up TLS for assets.${BASE_DOMAIN} (step-ca or tls internal) — REQUIRED (HTTPS forced)
  • Add assets. Caddy vhost + network alias + mount
  • Document guest step: Settings → APIs → Assets Server = https://assets.${BASE_DOMAIN}/
  • Document guest CA-trust step (import local CA root) if not using a publicly-trusted cert
  • Confirm in Fjord's actual UI that the field exists + HTTPS-forcing behavior matches Prism
  • Fallback path: pre-seed instructions (launch once online) for libraries/jar/meta
  • Defer decision: full meta+libraries mirror (mcm / PrismLauncher-meta) vs pre-seed
  • .gitignore already covers mirror/