Add Docker image, Compose, CI/CD workflows and docs
- Multi-arch (amd64/arm64) panel image: static musl binary on scratch, cross-compiled with cargo-zigbuild (no QEMU), non-root, healthcheck - docker-compose.yml + .env.example for one-command deployment - CI: fmt, clippy, tests, web type-checks, Windows launcher build, real-network installs of vanilla/Fabric/Quilt/Forge/NeoForge, Docker build - Release: Windows NSIS installer with baked-in panel URL, GHCR image push and GitHub release (tag push or manual dispatch) - README, admin guide, Microsoft auth setup, architecture, development - rustfmt config and formatting pass Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011ARcGWxLx21FwXJ3yfGriS
No files matched your search
@@ -0,0 +1,78 @@
|
||||
# Admin guide
|
||||
|
||||
## Deploying the panel
|
||||
|
||||
```bash
|
||||
cp .env.example .env # set ADMIN_PASSWORD
|
||||
docker compose up -d
|
||||
docker compose logs -f panel # first start prints the admin account
|
||||
```
|
||||
|
||||
Everything the panel stores lives in the `panel-data` volume (`/data`):
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `panel.db` | SQLite database (users, instances, settings, stats) |
|
||||
| `files/<instance>/` | Configs and uploads hosted for launchers |
|
||||
| `uploads/` | Logos, backgrounds, icons |
|
||||
| `jwt.secret` | Token signing key (unless `JWT_SECRET` is set) |
|
||||
|
||||
**Backups:** stop the container (or use `sqlite3 panel.db ".backup backup.db"`) and copy the volume.
|
||||
|
||||
**Updating:** `docker compose pull && docker compose up -d`. Database migrations run automatically.
|
||||
|
||||
### HTTPS
|
||||
|
||||
Launchers talk to the panel over the internet, so serve it over HTTPS. Example with Caddy:
|
||||
|
||||
```caddyfile
|
||||
panel.example.com {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
```
|
||||
|
||||
Large modpack uploads go through the proxy — raise its body-size limit if needed (nginx: `client_max_body_size 2g;`).
|
||||
|
||||
## Instances
|
||||
|
||||
An instance = one playable profile: a Minecraft version, an optional mod loader, files (mods, configs…) and an optional server.
|
||||
|
||||
- **Version** — choose any Minecraft version and Vanilla / Fabric / Quilt / Forge / NeoForge. Leave the loader version empty for the latest recommended build (it's pinned when you save).
|
||||
- **Modrinth** — search, pick a version, *Use*. Mods are downloaded by players straight from Modrinth's CDN; configs (`overrides/`) are hosted by the panel.
|
||||
- **CurseForge** — needs a free API key from [console.curseforge.com](https://console.curseforge.com) (Settings → Integrations, or `CURSEFORGE_API_KEY`). Some authors block third-party downloads; those files show up under **Files** with a link — download them yourself and upload them into the same folder.
|
||||
- **Upload .zip** — a `.mrpack`, a CurseForge export, or any zipped instance folder (with `mods/`, `config/`, … or a `.minecraft/` inside). For plain zips, pick the Minecraft version and loader.
|
||||
- **Files** — add or remove individual files at any time. Files players add themselves are never touched; files you remove are deleted from players' instances on their next launch.
|
||||
|
||||
Every save bumps the instance **revision**; launchers re-verify files when it changes, otherwise launching is instant.
|
||||
|
||||
### Built-in server
|
||||
|
||||
On the **Server** tab: name, address, port.
|
||||
|
||||
- *Add to multiplayer list* writes the server into `servers.dat` (keeping servers players added).
|
||||
- *Join automatically* connects on start (Quick Play on 1.20+, `--server` on older versions).
|
||||
|
||||
Your server must allow the accounts you use: offline-mode (`online-mode=false`) for panel/offline accounts, or online-mode for Microsoft accounts. Protect offline-mode servers with a whitelist or an auth plugin.
|
||||
|
||||
### Access
|
||||
|
||||
- **Everyone** — any launcher, including offline and Microsoft accounts.
|
||||
- **Signed-in players** — any panel account.
|
||||
- **Specific groups** — members of the selected groups (create groups on the Players page). Admins see everything.
|
||||
|
||||
## Players
|
||||
|
||||
- **Sign-ups:** Settings → *Closed* (admins create accounts), *Needs approval*, or *Open*.
|
||||
- Panel accounts play under their username with the offline-mode UUID an offline server computes, so inventories and permissions stay consistent.
|
||||
- Disabling an account signs it out everywhere on the next request.
|
||||
- Ten failed logins lock an account for five minutes.
|
||||
|
||||
## Launcher design
|
||||
|
||||
Everything on this page is pushed to launchers when they start or refresh — no reinstall. The **Features** tab lets you allow or block players from changing the theme or Java settings. **Custom CSS** is injected last; handy variables are `--accent`, `--accent-2`, `--surface`, `--radius`.
|
||||
|
||||
## Releasing the launcher
|
||||
|
||||
See the README's *Build your branded launcher*. Players get updates automatically: the launcher checks GitHub Releases on start and offers the new installer.
|
||||
|
||||
**Code signing:** unsigned installers trigger a Windows SmartScreen warning ("More info → Run anyway"). To avoid it, sign the installer with a code-signing certificate (e.g. Azure Trusted Signing) — Tauri supports this via `bundle.windows.signCommand`.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────┐ HTTPS (JSON) ┌──────────────────────────┐
|
||||
│ Launcher (Tauri) │ ─────────────────────────▶ │ Panel (Axum + SQLite) │
|
||||
│ Svelte UI ⇄ Rust shell │ manifest, instances, │ Svelte admin UI │
|
||||
│ │ │ auth, stats │ /files, /uploads │
|
||||
│ scopenet-core engine │ └──────────────────────────┘
|
||||
│ ├─ Mojang / Java │ ──▶ piston-meta, libraries.minecraft.net, resources
|
||||
│ ├─ Fabric/Quilt/Forge │ ──▶ meta.fabricmc.net, maven.minecraftforge.net, …
|
||||
│ └─ modpack files │ ──▶ Modrinth/CurseForge CDNs, panel /files
|
||||
└──────────────────────────┘
|
||||
```
|
||||
|
||||
- **`crates/shared`** defines every JSON type exchanged, so the panel and launcher can't drift apart.
|
||||
- **`crates/core`** has no UI dependencies. It's unit-tested, and CI runs real installs of vanilla, legacy, Fabric, Quilt, Forge and NeoForge against the live servers.
|
||||
- The **panel** also uses `core` for version and loader lookups.
|
||||
|
||||
## Launch pipeline
|
||||
|
||||
1. Resolve the account (refreshing Microsoft tokens if needed).
|
||||
2. Fetch the instance from the panel (cached for offline play).
|
||||
3. `install`: vanilla version JSON → Java runtime (Mojang's own builds) → client jar, libraries, assets → loader profile (Fabric/Quilt), or replay the Forge/NeoForge installer's processors → merge → natives.
|
||||
4. `sync`: download the admin's files; remove files the admin removed; never touch the player's own files. With an unchanged revision, only existence is checked.
|
||||
5. Write `servers.dat` and keybinds, build the Java command (quick play / `--server`, memory, GC presets, `@argfile` for long classpaths), and start the game.
|
||||
6. Stream logs to the console; on a crash, show the tail of the log with hints.
|
||||
|
||||
## Disk layout (launcher)
|
||||
|
||||
```
|
||||
%APPDATA%\net.scopenet.launcher\
|
||||
settings.json, accounts.json, secrets.bin (encrypted), manifest.json (cache)
|
||||
minecraft\
|
||||
versions\ libraries\ assets\ runtimes\ natives\ cache\
|
||||
instances\<id>\ ← game directory (saves, mods, options.txt, …)
|
||||
```
|
||||
|
||||
## HTTP API
|
||||
|
||||
Public (used by launchers). Send `Authorization: Bearer <token>` to see restricted instances:
|
||||
|
||||
| Method | Path | |
|
||||
|---|---|---|
|
||||
| GET | `/api/v1/launcher/manifest` | Branding, auth options, visible instances |
|
||||
| GET | `/api/v1/launcher/instances/{id}` | Instance + file list |
|
||||
| POST | `/api/v1/launcher/events` | Launch stats |
|
||||
| POST | `/api/v1/auth/login` · `/register` | Panel accounts |
|
||||
| GET | `/api/v1/auth/me` | Current user |
|
||||
| GET | `/files/{instance}/{path}` | Hosted instance files |
|
||||
| GET | `/healthz` | Health check |
|
||||
|
||||
Admin (`role = admin`): `/api/admin/{stats,users,groups,branding,settings,instances,uploads}` plus `instances/{id}/{import/modrinth,import/curseforge,import/upload,files,reset}` and meta/search proxies under `/api/admin/{meta,modrinth,curseforge}`.
|
||||
|
||||
## Security notes
|
||||
|
||||
- Passwords are hashed with Argon2id; tokens are HS256 JWTs (30 days); disabled accounts are rejected on every request.
|
||||
- Server-provided paths are sanitised (`safe_join`) on both sides — no `..` or absolute paths.
|
||||
- The panel never returns the CurseForge key; SVG uploads are refused (script risk).
|
||||
- The launcher's CSP only allows scripts from the app itself; media may load from any HTTPS host (admin-chosen images).
|
||||
- Hosted `/files` are public URLs. Don't put secrets in instance files.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Development
|
||||
|
||||
**Requirements:** Rust (stable), Node 22. On Linux, also the Tauri deps: `libwebkit2gtk-4.1-dev librsvg2-dev libayatana-appindicator3-dev`.
|
||||
|
||||
## Panel
|
||||
|
||||
```bash
|
||||
cd panel/web && npm install && npm run build && cd ../..
|
||||
ADMIN_PASSWORD=adminadmin cargo run -p scopenet-panel # http://localhost:8080
|
||||
# UI hot reload: (cd panel/web && npm run dev) # http://localhost:5173, proxies /api
|
||||
```
|
||||
|
||||
## Launcher
|
||||
|
||||
```bash
|
||||
cd launcher && npm install
|
||||
npm run tauri dev # full desktop app
|
||||
npm run dev # UI only in a browser, with a mock backend (http://localhost:1420)
|
||||
```
|
||||
|
||||
Browser mock scenarios: `?mock=setup`, `?mock=login`, `?mock=progress`.
|
||||
|
||||
Build-time options (environment variables when building): `SCOPENET_PANEL_URL`, `SCOPENET_LOCK_PANEL=1`, `SCOPENET_REPO=owner/repo`.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
cargo test --workspace # unit + panel API tests
|
||||
cargo test -p scopenet-core --test online -- --ignored # real installs (needs internet, ~2 GB)
|
||||
(cd panel/web && npm run check) && (cd launcher && npm run check)
|
||||
cargo fmt --all && cargo clippy --workspace --all-targets -- -D warnings
|
||||
```
|
||||
|
||||
## Releasing
|
||||
|
||||
Push a tag `vX.Y.Z` or run the **Release** workflow. It stamps the version into `Cargo.toml` and `tauri.conf.json`, builds the NSIS installer on Windows, pushes the multi-arch panel image to GHCR, and publishes the release.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Microsoft sign-in
|
||||
|
||||
Microsoft accounts give players their real skin and let them join online-mode servers. It needs an Azure app registration that Mojang has approved for the Minecraft API.
|
||||
|
||||
## 1. Register an app
|
||||
|
||||
1. Go to [portal.azure.com](https://portal.azure.com) → **Microsoft Entra ID → App registrations → New registration**.
|
||||
2. Name: your launcher's name. Supported account types: **Personal Microsoft accounts only**.
|
||||
3. Redirect URI: leave empty.
|
||||
4. After creating it, open **Authentication** → enable **Allow public client flows** (needed for the device-code flow) → Save.
|
||||
5. Copy the **Application (client) ID**.
|
||||
|
||||
## 2. Request Minecraft API access
|
||||
|
||||
New apps can't call the Minecraft services API until Mojang approves them. Submit the form at <https://aka.ms/mce-reviewappid> with your client ID. Approval can take a while; until then sign-in fails with *"Minecraft services rejected the Xbox token"*.
|
||||
|
||||
## 3. Enable it in the panel
|
||||
|
||||
**Settings → Microsoft accounts** → turn on *Sign in with Microsoft* and paste the client ID. Launchers show the Microsoft tab on their next refresh.
|
||||
|
||||
## How it works
|
||||
|
||||
The launcher uses the OAuth **device-code flow**: it shows a short code, opens `microsoft.com/link`, and waits. The chain is Microsoft → Xbox Live → XSTS → Minecraft services → profile. The refresh token is stored encrypted on the player's PC and renewed silently before launches. The panel never sees Microsoft credentials.
|
||||
|
||||
Common errors are translated for players (no Xbox profile yet, child account, game not owned).
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 32 KiB |