Files
Nitro-V3/docs/secure-production-setup.en.md
T
2026-05-06 06:27:40 +02:00

366 lines
8.7 KiB
Markdown

# 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
<div id="root"></div>
<script src="/configuration/bootstrap.js"></script>
```
Vite development example:
```html
<div id="root"></div>
<script type="module" src="/src/bootstrap.ts"></script>
```
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`.