Update main repo

This commit is contained in:
2026-06-09 18:14:59 +03:00
parent 7a53666245
commit f603d99587
6 changed files with 1326 additions and 10 deletions

327
README.md Normal file
View File

@@ -0,0 +1,327 @@
# MrixsCraft
Private Minecraft server project with a web-based launcher. Consists of two independent Go repositories unified via git submodules:
- **`server/`** — backend (Go + net/http + PostgreSQL)
- **`launcher/`** — desktop launcher (Go + Fyne GUI)
Domain: `minecraft.mrixs.me` · CDN: `cdn.mrixs.me`
---
## Architecture
```
┌─────────────┐ HTTP/API ┌──────────────┐
│ Launcher │ ◄──────────────► │ Server │
│ (Go+Fyne) │ Yggdrasil+REST │ (Go+pgx) │
└─────────────┘ └──────┬──────┘
┌──────┴──────┐
│ PostgreSQL │
│ 16 │
└─────────────┘
cdn.mrixs.me minecraft.mrixs.me
┌──────────┐ ┌────────────────┐
│ Caddy │ │ Caddy │
│ file srv │ │ reverse proxy │
│ (CAS) │ │ + HTTPS │
└──────────┘ └────────────────┘
```
**Infrastructure (Docker Compose):** Caddy · Go backend · PostgreSQL 16 · Watchtower (auto-update)
---
## Directory Structure
```
MC-server/
├── .gitmodules # Submodules: launcher, server
├── docs/
│ ├── state.md # Project status and detailed architecture
│ ├── launcher/Specification.md # Launcher specification (RU)
│ └── server/Specification.md # Server specification (RU)
├── launcher/ # Git submodule — MrixsCraft-launcher
│ ├── cmd/launcher/main.go
│ └── internal/
│ ├── auth/ # Yggdrasil client
│ ├── config/ # Launcher settings & system paths
│ ├── fetcher/ # HTTP downloader with SHA-1 verification
│ ├── java/ # JRE detection/download
│ ├── launch/ # Manifest parsing, game launch, classpath assembly
│ ├── selfupdate/# Binary auto-updater (SHA-256)
│ └── ui/ # Fyne GUI (screens, components, theme)
└── server/ # Git submodule — MrixsCraft-server
├── cmd/
│ ├── server/main.go # HTTP routes, middleware, graceful shutdown
│ └── ci-release/main.go # CI release uploader
├── Dockerfile # Multi-stage (~20 MB)
├── docker-compose.yml # Caddy + backend + postgres + watchtower
├── Caddyfile # Reverse proxy, CDN, HTTPS
├── .gitea/workflows/ci.yml # CI: lint → test → build → docker push
├── migrations/
│ ├── 001_init.sql # Full schema: 6 tables + indexes
│ └── 002_migration_history.sql # Migration tracking
└── internal/
├── admin/ # Modpack CRUD, file upload, manifests
├── api/ # Public API: auth, skins, capes, launcher
├── auth/ # Yggdrasil: authenticate/refresh/validate
├── cas/ # Content-Addressable Storage (SHA-1)
├── config/ # ENV configuration
├── database/ # PostgreSQL (pgx/pgxpool), data models
├── middleware/ # CORS, Logging, Recovery, RateLimiter
├── session/ # Background expired-session cleanup
└── templates/ # Go html/template (dark theme)
```
---
## Tech Stack
| Component | Technology |
|-----------|-----------|
| Language | Go 1.25 (server) · Go 1.22 (launcher) |
| HTTP | net/http (stdlib) |
| Database | PostgreSQL 16 + pgx/v5 |
| Hashing | SHA-1 (CAS) · SHA-256 (launcher releases) · bcrypt (passwords) |
| GUI | Fyne v2.4.5 |
| Auth | Custom Yggdrasil server + authlib-injector |
| Proxy | Caddy 2 (auto-HTTPS) |
| Containers | Docker + Docker Compose |
| Registry | Gitea Container Registry |
| CI/CD | Gitea Actions |
| Auto-update | Watchtower |
---
## Getting Started
### Prerequisites
- Go 1.25+ (server) / Go 1.22+ (launcher)
- Docker & Docker Compose (production)
- PostgreSQL 16 (if running without Docker)
### Clone with Submodules
```bash
git clone --recurse-submodules gitea.mrixs.me:mrixs/mrixscraft.git MC-server
```
If already cloned without submodules:
```bash
git submodule update --init --recursive
```
### Server
```bash
cd server/
# Configure
cp .env.example .env
# edit .env: DATABASE_URL, JWT_SECRET, etc.
# Run locally
go run ./cmd/server
# Or via Docker Compose
docker compose up -d
```
**Required environment variables:**
| Variable | Default | Required |
|----------|---------|----------|
| `SERVER_PORT` | `8080` | No |
| `DATABASE_URL` | — | **Yes** |
| `CAS_DIR` | `/var/www/cdn/files` | No |
| `JWT_SECRET` | — | **Yes** |
### Launcher
```bash
cd launcher/
go build -o mrixscraft-launcher ./cmd/launcher
./mrixscraft-launcher
```
Or: `go run ./cmd/launcher`
---
## Server API
### Yggdrasil (Mojang-compatible)
| Method | Path | Description |
|--------|------|-------------|
| POST | `/authserver/authenticate` | Login with credentials |
| POST | `/authserver/refresh` | Refresh token |
| POST | `/authserver/validate` | Validate token (204) |
| POST | `/authserver/invalidate` | Invalidate token |
| POST | `/authserver/signout` | Sign out (delete all sessions) |
| GET | `/sessionserver/session/minecraft/profile/{uuid}` | Player profile with textures |
### Public API
| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/web/register` | Player registration |
| POST | `/api/web/login` | Website login |
| POST | `/api/web/profile/skin` | Upload skin (PNG) |
| POST | `/api/web/profile/cape` | Upload cape (PNG) |
| DELETE | `/api/web/profile/skin` | Delete skin |
| GET | `/api/web/profile/{uuid}` | Player profile |
### Launcher API
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/launcher/latest` | Latest launcher version |
| GET | `/api/servers.json` | Active modpack list |
| GET | `/api/instances/{slug}/manifest.json` | Modpack manifest |
### CAS (File Server)
| Method | Path | Description |
|--------|------|-------------|
| GET | `/files/{sha1}` | File by SHA-1 hash |
| GET | `/files/launcher/{version}/{os}/{arch}/{filename}` | Launcher binary |
| GET | `/skins/{hash}` | Skin/cape by hash |
### Admin (Bearer token + role=admin)
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/admin/modpacks` | List modpacks |
| POST | `/api/admin/modpacks` | Create modpack |
| PUT | `/api/admin/modpacks/{id}` | Update modpack |
| DELETE | `/api/admin/modpacks/{id}` | Deactivate modpack |
| POST | `/api/admin/modpacks/{slug}/upload` | Upload files (≤500 MB) |
| POST | `/api/admin/modpacks/{slug}/manifest` | Generate manifest.json |
| POST | `/api/admin/launcher/release` | Upload launcher release (X-CI-Token) |
| GET | `/admin` | Web admin interface (requires admin role) |
---
## Content-Addressable Storage (CAS)
All files (mods, libraries, assets) are stored by their SHA-1 hash:
```
/var/www/cdn/files/ab/abcdef1234... (first 2 chars as subdirectory)
```
- **Immutable** — files are never overwritten
- **Cache-Control:** `public, max-age=31536000, immutable` (1 year)
- **Deduplication** — automatic (same hash = same file)
- **Concurrent-safe** — per-hash `sync.Mutex` prevents race conditions
- **Verification** — constant-time SHA-1 comparison
---
## Database Schema
7 tables:
| Table | Purpose |
|-------|---------|
| `users` | Players (username, email, password_hash, uuid, role) |
| `player_textures` | Skins & capes (skin_hash, cape_hash → CAS) |
| `yggdrasil_sessions` | Auth sessions (access_token, client_token, expires_at) |
| `modpacks` | Modpacks/servers (slug, name, minecraft_version, java_version, server_ip) |
| `global_files` | CAS file registry (sha1 PK, size_bytes, file_name, mime_type) |
| `launcher_releases` | Launcher releases (version, os, arch, sha256, file_path) |
| `migration_history` | Applied migration tracking |
Migrations are applied manually: `psql $DATABASE_URL -f migrations/001_init.sql`
---
## Launcher Client File Structure
| OS | Root Directory |
|----|---------------|
| Windows | `%APPDATA%\MrixsCraft\` |
| macOS | `~/Library/Application Support/MrixsCraft/` |
| Linux | `~/.MrixsCraft/` |
```
MrixsCraft/
├── launcher.json # Settings (RAM, server URL, window)
├── session.json # Yggdrasil tokens
├── authlib-injector.jar # Auth interceptor
├── Java/{8,17,21}/ # Portable JREs
├── assets/ # Game assets
├── libraries/ # Shared libraries (LWJGL, etc.)
└── instances/{slug}/ # Isolated modpack clients
├── mods/
├── mods_backup/ # Unknown mods moved here (soft delete)
├── config/
└── resourcepacks/
```
---
## Testing
```bash
# Server
cd server/
go test ./... -v -race -cover
# Launcher — no tests (GUI testing is impractical)
```
Server test coverage: `cas`, `auth`, `api`, `session` packages.
---
## CI/CD
Gitea Actions pipeline (`.gitea/workflows/ci.yml`):
```
lint (go vet + gofmt) → test (race detector) → build → docker push (master only)
```
Images: `gitea.mrixs.me/mrixs/mrixscraft-server:latest` + `:sha`
Watchtower on VPS polls every 5 minutes and auto-deploys new images.
---
## Known TODOs
### Server
- Full-text file search in DB
- SIGHUP config reload (requires `config.Atomic` refactor)
### Launcher
- PLAY button wired to `launch.Prepare` + `Game.Start` (stub)
- Server list hardcoded (not loaded from `/api/servers.json`)
- Java auto-download not implemented
- Skin avatar rendering (8×64 face crop)
- News/patchnotes on MainScreen
- `servers.dat` NBT manipulation
### Infrastructure
- CI deploy step (SSH + docker compose up) — needs secrets
- Automatic Go migration runner (currently manual)
- Backup script not in cron
---
## Commands Reference
```bash
# Server
cd server/
go build -o mrixscraft-server ./cmd/server
go test ./...
go run ./cmd/server
docker compose up -d
# Launcher
cd launcher/
go build -o mrixscraft-launcher ./cmd/launcher
go run ./cmd/launcher
```