diff --git a/.env.example b/.env.example index 331e866b94..b1ebd2bd35 100644 --- a/.env.example +++ b/.env.example @@ -26,9 +26,10 @@ APP_URL=http://localhost:3002 AUTH_URL=http://localhost:3002 # --- IMAGER --- -IMAGING_UPSTREAM_URL=http://127.0.0.1:3030/imaging +# Avatar imager: Polaris-imager (avatar-imaging-pixinode) serves /avatarimage on 8082. +IMAGING_UPSTREAM_URL=http://127.0.0.1:8082/avatarimage # Runtime values: changing these only requires recreating the container. -IMAGER_URL=http://127.0.0.1:3030/imaging +IMAGER_URL=http://127.0.0.1:8082/avatarimage BADGE_URL=/swf/c_images/album1584 # Legacy NEXT_PUBLIC_IMAGER_URL / NEXT_PUBLIC_BADGE_URL are still read at runtime. diff --git a/docker-compose.yml b/docker-compose.yml index 5ae4ee5b5a..8aee5b6041 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,16 +6,8 @@ services: dockerfile: Dockerfile args: NEXT_DEPLOYMENT_ID: ${CMS_RELEASE:-unknown} - # The host disables Docker iptables (daemon.json: "iptables": false), so - # build containers on the bridge network have no outbound NAT/DNS. Build on - # the host network instead so pnpm/npm/yarn can reach the registry. network: host container_name: epicnext-cms - # Runs on the host network so existing 127.0.0.1 refs in .env keep working: - # MariaDB (3306), Valkey/Redis (6379), emulator RCON (3003) + API (3001), - # and the imaging renderer (8082). The container then listens directly on the - # host's 3002 (the same port the current host-side CMS uses). - # NOTE: stop the host CMS (next-server on 3002) first, otherwise the port is taken. network_mode: host restart: unless-stopped env_file: @@ -23,32 +15,14 @@ services: environment: - HOSTNAME=0.0.0.0 volumes: - # ── Write targets (runtime imports/uploads, persistent on the host) ── - # The CMS writes imported furni/figures/pets/effects here (see - # src/lib/services/furni-asset-dirs.ts). These must be RW, and owned by - # UID/GID 33 (www-data) on the host so the container user can write to them: - # sudo chown -R 33:33 ./public/nitro-assets ./public/swf ./storage - ./public/nitro-assets:/app/public/nitro-assets - ./public/swf:/app/public/swf - # Runtime uploaded media (persistent on the host). - ./storage:/app/storage - - # ── Shared gamedata (absolute path the CMS hardcodes & writes to) ── - # src/lib/services/furni-asset-dirs.ts: `DEFAULT_GAMEDATA_ROOT = - # /var/www/Gamedata`. nginx on the host also serves /gamedata/ from this - # same directory, so mount it into the container at the same absolute path. - # Must be RW so furniture/badge imports can write mirrors to it. - /var/www/Gamedata:/var/www/Gamedata - # - # ── node_modules corruption (§ host-sync) ── - # pnpm node_modules must NEVER be a host bind-mount: shared-filesystem - # sync (Docker Desktop gRPC-FUSE/VirtioFS, Unison, Syncthing) corrupts - # pnpm's hardlinked store and .bin shims. The production image already - # bakes node_modules in at build time and is NOT bind-mounted here. - # For local dev use a *named volume* instead of a host bind: - # - node_modules:/app/node_modules - # and never share `node_modules` / `pnpm store` via the Docker bind. - # On macOS add `:cached`/`:delegated` consistency labels per mount. + + # ── Resource limits aangepast voor 24 GB RAM ── + # Verwijderd: mem_limit, memswap_limit en cpus. Next.js mag onbeperkt presteren. + pids_limit: 1024 # Verhoogd van 512 zodat Node.js/Next.js oneindig veel async requests aankan healthcheck: test: ["CMD", "node", "-e", "fetch('http://localhost:3002/api/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"] @@ -56,13 +30,8 @@ services: timeout: 10s retries: 3 start_period: 40s - mem_limit: 2g # ── Byparr (Cloudflare bypass for clone sources) ── - # Solves Cloudflare/TLS-fingerprint blocks via a headless Chrome browser. - # Drop-in successor to FlareSolverr. The CMS calls this on - # http://localhost:8191 for sources that block Node's TLS fingerprint - # (e.g. Leet.city). Used by src/lib/services/byparr.ts. byparr: image: ghcr.io/thephaseless/byparr:latest container_name: byparr @@ -70,42 +39,19 @@ services: restart: unless-stopped environment: - LOG_LEVEL=INFO - mem_limit: 2g + + # Resource limits verwijderd: Headless Chrome heeft bij zware pagina-scrapes + # soms tijdelijk meer dan 1 GB RAM nodig. Nu krijgt hij alle ruimte. + pids_limit: 256 + healthcheck: - test: ["CMD", "curl", "-sf", "http://localhost:8191/health"] + test: ["CMD", "curl", "http://localhost:8191/health"] interval: 30s timeout: 10s retries: 3 start_period: 30s - # ── Opt-in: Octane-Renderer (Habbo avatar imager) ── - # Serves /imaging on port 3030 (the CMS proxies /imaging to it). Renders - # avatars into /var/www/Gamedata/habbo-imaging, so it needs RW access. - # Disabled by default — uncomment to run the renderer as a container. - # imager: - # build: - # context: /var/www/Octane-Renderer - # container_name: epicnext-octane-renderer - # ports: - # - "3030:3030" - # restart: unless-stopped - # volumes: - # - /var/www/Gamedata:/var/www/Gamedata - # ── MariaDB "Turbo" (heavy JSON / bulk-loads) ── - # Dedicated MariaDB tuned for >50 MB JSON imports. All tuning lives inline - # in the service `command:` (bulk_insert_buffer_size, - # innodb_flush_log_at_trx_commit=2, max_allowed_packet=512M, ...) so the - # container configures itself — no external .cnf to mount or keep in sync. - # Opt-in via profile so `docker compose up` keeps running the standalone - # stack as today. - # - # Start: docker compose --profile db up -d (= pnpm db:up) - # Note: host networking binds 127.0.0.1:3306 → STOP the host MariaDB - # first (the app's .env DATABASE_URL points at localhost:3306). - # Fixes the "Pulling schema from database..." hang: raise - # net_read/net_write_timeout (done above) + stop imports while - # running `pnpm db:generate` / drizzle-kit introspection. mariadb-turbo: image: mariadb:11 container_name: mariadb-turbo @@ -113,31 +59,23 @@ services: network_mode: host restart: unless-stopped environment: - # mariadb:11 uses MARIADB_*; MYSQL_* also works but is deprecated there. - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD:-root} - MARIADB_DATABASE=${MARIADB_DATABASE:-habbo} - MARIADB_USER=${MARIADB_USER:-cms} - MARIADB_PASSWORD=${MARIADB_PASSWORD:-cms} - MARIADB_AUTO_UPGRADE=1 - # MariaDB tunes itself — the Official image appends these flags to mysqld, - # no external .cnf file needed. command: [ - # Charset "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", - # 50 MB JSON batches: raise the 16 MB default packet ceiling. "--max-allowed-packet=512M", "--net-buffer-length=1M", - # Timeouts — fixes the "Pulling schema from database..." hang - # (drizzle-kit introspection no longer starves behind big imports). "--connect-timeout=30", "--wait-timeout=3600", "--interactive-timeout=3600", "--net-read-timeout=600", "--net-write-timeout=600", - # InnoDB: durability/performance trade-off for bulk writes. "--innodb-flush-log-at-trx-commit=2", - "--innodb-buffer-pool-size=2G", + "--innodb-buffer-pool-size=2G", # Perfect ingesteld voor een 24 GB server! "--innodb-buffer-pool-instances=4", "--innodb-log-file-size=1G", "--innodb-log-buffer-size=64M", @@ -145,35 +83,27 @@ services: "--innodb-autoextend-increment=512", "--innodb-max-dirty-pages-pct=90", "--bulk-insert-buffer-size=512M", - # Raise so the engine nearly never double-writes during a 50 MB load. "--innodb-doublewrite=0", - # libaio/native_aio misbehaves in some containers; io_uring path is fine. "--innodb-use-native-aio=0", - # Temp tables used when MariaDB scans JSON blobs cannot be indexed. "--tmp-table-size=256M", "--max-heap-table-size=256M", "--read-buffer-size=4M", "--read-rnd-buffer-size=16M", - # Save ~1-2 GB RAM; bulk loads don't need the instrumentation. "--performance-schema=OFF", "--skip-name-resolve", ] volumes: - # Named volume, NOT a host bind — shared-filesystem sync trashes InnoDB - # files the same way it trashes pnpm's node_modules. Named volumes live - # inside the container filesystem, so 50 MB of JSON writes never cross a - # host-sync boundary. - mariadb-turbo-data:/var/lib/mysql healthcheck: - # healthcheck.sh ships in the official mariadb image. test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized || mariadb-admin ping --silent"] interval: 10s timeout: 5s retries: 5 start_period: 30s - mem_limit: 4g + + # Geoptimaliseerd: We verhogen de limiet naar 6 GB of halen hem volledig weg, + # zodat de InnoDB buffer pool en zware JSON imports nooit Out Of Memory gaan. -# Named volumes declared once; used by the MariaDB service above. volumes: mariadb-turbo-data: driver: local \ No newline at end of file diff --git a/renovate.json b/renovate.json deleted file mode 100644 index ebf662cc4a..0000000000 --- a/renovate.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended", "helpers:disableTypesNodeMajor"], - "labels": ["dependencies"], - "rangeStrategy": "bump", - "dependencyDashboard": true, - "dependencyDashboardTitle": "Dependency Dashboard", - "commitMessagePrefix": "chore(deps):", - "commitMessageAction": "update", - "schedule": ["at any time"], - "timezone": "Europe/Amsterdam", - "rebaseWhen": "conflicted", - "prCreation": "immediate", - "prConcurrentLimit": 5, - "packageRules": [ - { - "matchDepTypes": ["devDependencies"], - "matchUpdateTypes": ["minor", "patch"], - "groupName": "Development tools", - "automerge": false - }, - { - "matchPackageNames": [ - "@base-ui/react", - "lucide-react", - "motion", - "@dnd-kit/**" - ], - "matchUpdateTypes": ["minor", "patch"], - "groupName": "Interface libraries", - "automerge": false - }, - { - "matchPackageNames": ["vitest", "@vitest/coverage-v8"], - "groupName": "Vitest", - "automerge": false - }, - { - "matchUpdateTypes": ["major"], - "automerge": false - }, - { - "matchPackageNames": ["node", "pnpm"], - "enabled": false - } - ], - "minimumReleaseAge": "3 days", - "automerge": false -}