# Secure Runtime Production Setup Quick setup guide for running Nitro with: - configuration and gamedata served through `/nitro-sec/file`; - encrypted runtime `/api/*` calls; - obfuscated production bundles loaded as `.dat`. Replace the example domains with your real domains: - `https://hotel.example.com` - `https://nitro.example.com:2096` ## 1. Build Nitro Inside the `Nitro-V3` repository: ```bash yarn build ``` Then publish the `dist` folder to your web server, for example: ```txt C:/inetpub/wwwroot/hotel/nitro ``` The deployed folder should contain at least: ```txt configuration/ assets/ asset-loader.js index.html src/ ``` ## 2. `configuration/client-mode.json` File: ```txt Nitro-V3/dist/configuration/client-mode.json ``` Secure production configuration: ```json { "distObfuscationEnabled": true, "secureAssetsEnabled": true, "secureApiEnabled": true, "apiBaseUrl": "https://nitro.example.com:2096", "plainConfigBaseUrl": "https://hotel.example.com/configuration/", "plainGamedataBaseUrl": "https://hotel.example.com/client/nitro/gamedata/" } ``` Meaning: - `distObfuscationEnabled: true` loads `app.js.dat` and `app.css.dat`. - `secureAssetsEnabled: true` loads `renderer-config.json`, `ui-config.json`, and gamedata through `/nitro-sec/file`. - `secureApiEnabled: true` automatically encrypts `/api/*` requests. - `apiBaseUrl` must point to the emulator/API. - `plainConfigBaseUrl` and `plainGamedataBaseUrl` are fallbacks when secure assets are disabled. ## 3. `configuration/renderer-config.json` File: ```txt Nitro-V3/dist/configuration/renderer-config.json ``` Important values: ```json { "socket.url": "wss://nitro.example.com:2096", "api.url": "https://nitro.example.com:2096", "gamedata.url": "https://nitro.example.com:2096/nitro-sec/file?kind=gamedata&file=", "external.texts.url": [ "${gamedata.url}/ExternalTexts.json", "${gamedata.url}/UITexts.json" ], "furnidata.url": "${gamedata.url}/FurnitureData.json?t=%timestamp%", "productdata.url": "${gamedata.url}/ProductData.json?t=%timestamp%", "avatar.actions.url": "${gamedata.url}/HabboAvatarActions.json?t=%timestamp%", "avatar.figuredata.url": "${gamedata.url}/FigureData.json?t=%timestamp%", "avatar.figuremap.url": "${gamedata.url}/FigureMap.json?t=%timestamp%", "avatar.effectmap.url": "${gamedata.url}/EffectMap.json?t=%timestamp%", "crypto.ws.enabled": true } ``` If you are not using WebSocket crypto yet, use: ```json "crypto.ws.enabled": false ``` ## 4. `configuration/ui-config.json` File: ```txt Nitro-V3/dist/configuration/ui-config.json ``` Static image and camera URLs can remain plain: ```json { "camera.url": "https://hotel.example.com/client/camera/", "thumbnails.url": "https://hotel.example.com/client/camera/thumbnail/%thumbnail%.png" } ``` Non-sensitive images can stay static. JSON configuration and gamedata should go through the secure endpoint. ## 5. Emulator `config.ini` Inside `Arcturus-Morningstar-Extended`, edit the emulator config: ```txt Emulator/config.ini ``` Production example: ```ini ws.enabled=true ws.host=0.0.0.0 ws.port=2096 ws.whitelist=https://hotel.example.com ws.ip.header=CF-Connecting-IP crypto.ws.enabled=1 nitro.secure.assets.enabled=true nitro.secure.api.enabled=true nitro.secure.config.root=C:/inetpub/wwwroot/hotel/nitro/configuration nitro.secure.gamedata.root=C:/inetpub/wwwroot/hotel/nitro/client/nitro/gamedata nitro.secure.master_key=change-this-to-a-long-random-secret login.remember.enabled=true login.remember.duration.days=30 login.remember.jwt.secret=change-this-too-if-you-use-remember-me ``` Notes: - `nitro.secure.config.root` must point to the folder containing `renderer-config.json`, `ui-config.json`, and `client-mode.json`. - `nitro.secure.gamedata.root` must point to the live gamedata folder. - Files are read live from disk: if you update a JSON file, a new browser refresh reads the new version. - `nitro.secure.master_key` must be secret and stable. Never put it in public files. ## 6. Cloudflare If you use Cloudflare: 1. Keep the proxy enabled for the website domain `hotel.example.com`. 2. Make sure Cloudflare supports/proxies the port used by `nitro.example.com:2096`. 3. Always use HTTPS/WSS in the browser: ```json "api.url": "https://nitro.example.com:2096", "socket.url": "wss://nitro.example.com:2096" ``` If you get CORS errors, check: ```ini ws.whitelist=https://hotel.example.com ``` ## 7. IIS / `.dat` MIME type If obfuscated `.dat` assets are enabled, IIS must serve them correctly. Add this MIME type: ```txt Extension: .dat MIME type: application/octet-stream ``` Without it, the browser can receive 404 even when the file exists. ## 8. Final checklist - `client-mode.json` has `secureAssetsEnabled=true`. - `client-mode.json` has `secureApiEnabled=true`. - `renderer-config.json` uses `/nitro-sec/file?kind=gamedata&file=`. - `api.url` points to `https://nitro.example.com:2096`. - `socket.url` points to `wss://nitro.example.com:2096`. - `config.ini` has the correct `nitro.secure.config.root`. - `config.ini` has the correct `nitro.secure.gamedata.root`. - `config.ini` has a stable `nitro.secure.master_key`. - IIS knows the `.dat` MIME type. - Restart the emulator after changing `config.ini`. - Refresh the browser after changing JSON files in `configuration` or `gamedata`. ## 9. Temporarily disable secure mode For quick debugging, only change `client-mode.json`: ```json { "distObfuscationEnabled": false, "secureAssetsEnabled": false, "secureApiEnabled": false, "apiBaseUrl": "https://nitro.example.com:2096", "plainConfigBaseUrl": "https://hotel.example.com/configuration/", "plainGamedataBaseUrl": "https://hotel.example.com/client/nitro/gamedata/" } ``` Then hard refresh the browser. ## 10. `configuration/bootstrap.js` File: ```txt Nitro-V3/dist/configuration/bootstrap.js ``` This is the first loader when you use the external secure mode. It does three things: 1. opens an ECDH session with the emulator through `/nitro-sec/bootstrap`; 2. downloads encrypted `client-mode.json` through `/nitro-sec/file?kind=config`; 3. downloads encrypted `asset-loader.js` and imports it as a JavaScript module. ### Value to check Inside `bootstrap.js` there is: ```js const API_BASE = "https://nitro.example.com:2096"; ``` It must point to your public emulator/API URL. In production: ```js const API_BASE = "https://nitro.example.com:2096"; ``` In local development: ```js const API_BASE = "http://localhost:2096"; ``` If `bootstrap.js` fails, it automatically falls back to the plain loader: ```txt configuration/asset-loader.js ``` So `asset-loader.js` must always exist inside the `configuration` folder. ## 11. `configuration/asset-loader.js` File: ```txt Nitro-V3/dist/configuration/asset-loader.js ``` This loader loads the actual bundle: - if `distObfuscationEnabled=true` - it loads `app.css.dat`; - it loads `app.js.dat`; - it decodes, decompresses, and imports the bundle from a blob. - if `distObfuscationEnabled=false` - it loads `assets/app.css`; - it loads `assets/app.js`. ### Required files in production With obfuscation enabled, these files must exist: ```txt assets/app.css.dat assets/app.js.dat configuration/asset-loader.js configuration/bootstrap.js configuration/client-mode.json ``` With obfuscation disabled, these files must exist: ```txt assets/app.css assets/app.js configuration/asset-loader.js configuration/client-mode.json ``` ## 12. `index.html` `index.html` should stay minimal. Secure production example: ```html
``` Vite development example: ```html ``` Do not mix the two flows: - production build: use `configuration/bootstrap.js`; - `yarn start` development: use `/src/bootstrap.ts`. ## 13. Files inside `/configuration` The `configuration` folder should contain: ```txt asset-loader.js bootstrap.js client-mode.json renderer-config.json ui-config.json adsense.json optional hotlooks.json if register hot looks are enabled UITexts.json if separate UI texts are enabled ``` Login news should not live in `news.json` in production. They come from the database through: ```json "login.news.url": "${api.url}/api/auth/news" ``` The emulator reads from the `ui_news` table. With `secureAssetsEnabled=true`, client-loaded files go through: ```txt https://nitro.example.com:2096/nitro-sec/file?kind=config&file=... ``` The emulator reads them from: ```ini nitro.secure.config.root=C:/inetpub/wwwroot/hotel/nitro/configuration ``` If you add new JSON/JS files inside `configuration` and want to protect them, they must be requested through the secure endpoint or loaded through `bootstrap.js`.