Skip to content

About

The server backend for WynnSource Project

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

WynnSourceServer

The server component of WynnSource — a Wynncraft crowdsourcing mod.

Python 3.12+ FastAPI Protobuf License: AGPL-3.0


Prerequisites

  • Python 3.12+
  • uv — Python package manager
  • buf — Protocol Buffers toolchain
  • A PostgreSQL database
  • A Redis instance

Development Setup

# Clone with submodules
git clone --recurse-submodules https://github.com/WynnSource/WynnSourceServer.git
cd WynnSourceServer

# Start PostgreSQL and Redis on localhost (add `--profile telemetry` for a local OTel collector)
docker compose -f .dev/docker-compose.yaml up -d

# Generate protobuf code
buf generate --template buf.gen.yaml

# Install dependencies
uv sync

# Run database migrations
uv run alembic upgrade head

# Start the development server
uv run fastapi dev

Windows

Everything above works natively on Windows. Differences:

  • Containers without Docker: wslc (WSL containers) has no compose, start the services individually:

    wslc run -d --name wcs-db -e POSTGRES_DB=wcs_db -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 127.0.0.1:5432:5432 postgres:15-alpine
    wslc run -d --name wcs-redis -p 127.0.0.1:6379:6379 redis:7-alpine
    # Optional local OTel collector (prints spans and metrics: wslc logs -f wcs-otelcol)
    wslc run -d --name wcs-otelcol -p 127.0.0.1:4318:4318 -v "$PWD\.dev\otel-collector.yaml:/etc/otelcol/config.yaml" otel/opentelemetry-collector-contrib:0.161.0 --config=/etc/otelcol/config.yaml
  • Non-UTF-8 console code page (e.g. GBK on Chinese Windows): fastapi dev crashes printing its emoji banner. Set $env:PYTHONUTF8 = "1", or run uv run uvicorn app.main:app --reload instead.

  • A .venv created from WSL or a container contains Linux symlinks (lib64) that Windows uv cannot remove. Delete it from WSL (rm -rf .venv) and run uv sync again.

Environment Variables

Variable Description Default
POSTGRES_HOST PostgreSQL host localhost
POSTGRES_PORT PostgreSQL port 5432
POSTGRES_USER PostgreSQL user postgres
POSTGRES_PASSWORD PostgreSQL password postgres
POSTGRES_DB PostgreSQL database name wcs_db
REDIS_HOST Redis host localhost
REDIS_PORT Redis port 6379
WCS_ADMIN_TOKEN Admin API token None
LEVEL Log level DEBUG
LOG_JSON Log one JSON object per line (with trace_id/span_id) instead of colored text false
BETA_ALLOWED_VERSIONS Comma-separated allowed mod versions ``
WCS_SENTRY_DSN Sentry DSN; errors and logs only, tagged with the OpenTelemetry trace id None (disabled)
WCS_SENTRY_ENVIRONMENT Sentry environment local
WCS_SENTRY_PROFILE_SESSION_SAMPLE_RATE Share of processes that run Sentry continuous profiling 0
OTEL_EXPORTER_OTLP_ENDPOINT OTLP/HTTP collector, e.g. http://localhost:4318; enables OpenTelemetry traces and metrics None (disabled)
OTEL_RESOURCE_ATTRIBUTES Extra resource attributes, e.g. service.instance.id=…,deployment.environment.name=dev. Give every replica a distinct service.instance.id —
K8S_POD_NAME Holder name for the cross-replica scheduler job locks hostname

Other standard OTEL_* variables (OTEL_TRACES_SAMPLER, OTEL_METRIC_EXPORT_INTERVAL, …) are honored. The default sampler is parentbased_always_on: requests follow the caller's sampling decision, scheduler jobs are always traced.

Deploying to Kubernetes

WynnSourceServer uses Kustomize overlays for deployment and ArgoCD with Image Updater for GitOps.

Directory Structure

deploy/
  base/                 # Shared manifests
    deployment.yaml     # App deployment with health probes
    service.yaml        # ClusterIP service on port 8000
    postgres.yaml       # CNPG PostgreSQL cluster
    redis.yaml          # Redis instance (via Redis Operator)
    migration-job.yaml  # Alembic migration (ArgoCD sync hook)
    kustomization.yaml
  overlays/
    dev/                # Dev environment (namespace: wynnsource-dev)
      kustomization.yaml
    prod/               # Prod environment (namespace: wynnsource, replicas: 2)
      kustomization.yaml

Cluster Prerequisites

The following operators must be installed in the cluster:

Step 1: Create Secrets

Create the application secrets in the target namespace. Using Sealed Secrets is recommended.

kubectl -n <namespace> create secret generic wynnsource-secrets \
  --from-literal=WCS_ADMIN_TOKEN='<your-admin-token>'

Step 2: Create ConfigMap

kubectl -n <namespace> create configmap wynnsource-config \
  --from-literal=LEVEL='INFO' \
  --from-literal=BETA_ALLOWED_VERSIONS='0.2.6, 0.2.7'

Step 3: Create ArgoCD Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: wynnsource
  namespace: argocd
  annotations:
    argocd-image-updater.argoproj.io/image-list: app=ghcr.io/wynnsource/wynnsource-server
    argocd-image-updater.argoproj.io/app.update-strategy: newest-build
    argocd-image-updater.argoproj.io/app.allow-tags: "regexp:^dev-"
    argocd-image-updater.argoproj.io/app.ignore-tags: "latest,dev-latest"
spec:
  project: default
  source:
    repoURL: https://github.com/WynnSource/WynnSourceServer.git
    targetRevision: dev           # or master for production
    path: deploy/overlays/dev     # or deploy/overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: wynnsource-dev     # or wynnsource
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true

Step 4: Configure Ingress

Add an IngressRoute (or Ingress) pointing to the wynnsource-server service on port 8000. Make sure the X-Real-IP header is forwarded from the ingress controller for proper client IP logging and rate limiting.

Using the Schema (Protobuf)

WynnSourceServer uses Protocol Buffers to define item encoding schemas. The .proto definitions live in the schema submodule under schema/proto/wynnsource/.

Generating Python Code

With buf (recommended)

Install buf, then from the repository root:

buf generate --template buf.gen.yaml

This generates Python protobuf modules into generated/wynnsource/ based on:

# buf.gen.yaml
version: v2
plugins:
  - remote: buf.build/protocolbuffers/python:v33.5
    out: generated
  - remote: buf.build/protocolbuffers/pyi:v33.5
    out: generated
inputs:
  - directory: schema/proto

With protoc

protoc \
  --proto_path=schema/proto \
  --python_out=generated \
  --pyi_out=generated \
  schema/proto/wynnsource/**/*.proto

Using Generated Code

Install the protobuf runtime, then import the generated modules:

pip install protobuf
from wynnsource.item.gear_pb2 import IdentifiedGear
from wynnsource.item.consumable_pb2 import Consumable
from wynnsource.common.enums_pb2 import Rarity

# Create an item
gear = IdentifiedGear()
gear.name = "Cataclysm"

# Serialize to bytes
data = gear.SerializeToString()

# Deserialize from bytes
parsed = IdentifiedGear()
parsed.ParseFromString(data)

Using as a Workspace Package

In this repository, the generated code is a uv workspace package called wynnsource-proto. After running buf generate and uv sync, you can import directly:

from wynnsource.item.wynn_source_item_pb2 import WynnSourceItem

Mappings

The schema repository includes JSON mapping files:

  • schema/mapping/identification.json — Identification ID mappings
  • schema/mapping/shiny.json — Shiny stat mappings

Generating for Other Languages

buf supports many languages. See the buf plugin registry for available plugins. Example for TypeScript:

# buf.gen.yaml
version: v2
plugins:
  - remote: buf.build/connectrpc/es
    out: gen/ts
inputs:
  - directory: schema/proto

License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) with the following exception.

Exception for Generated Client Code

As a special exception, the copyright holders grant permission to generate, use, distribute, and license client libraries and SDKs produced from this project's API specifications (including OpenAPI documents, Protocol Buffer definitions, and GraphQL schemas) under any license of your choice, including proprietary licenses. This exception applies solely to the generated client code — the server-side source code remains subject to the AGPL-3.0 in full.

Rationale

The AGPL-3.0 ensures that improvements to the server are shared with the community. However, client libraries derived from our API specifications are commonly embedded in Minecraft mods and other applications whose licenses may be incompatible with the AGPL. This exception removes that friction: developers can freely build and ship clients against our API without licensing concerns, while contributions to the backend itself continue to benefit everyone.

About

The server backend for WynnSource Project

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages