# Xray config example

### Definition

A configuration is considered “complete” if the JSON contains **both** fields:

* `inbounds` — incoming connections
* `outbounds` — outgoing connections

Any JSON object containing both `inbounds`and `outbounds`is recognized as a complete configuration — regardless of the presence of balancers, observatories, or metadata.

### Format

#### Single configuration

```json
{
    "log": { "loglevel": "warning" },
    "dns": { "servers": [...] },
    "inbounds": [
        { "tag": "socks-in", "protocol": "socks", "port": 10808, "listen": "127.0.0.1" },
        { "tag": "http-in", "protocol": "http", "port": 10809, "listen": "127.0.0.1" }
    ],
    "outbounds": [
        { "tag": "proxy-1", "protocol": "vless", "settings": {...} },
        { "tag": "proxy-2", "protocol": "vless", "settings": {...} },
        { "tag": "direct", "protocol": "freedom" },
        { "tag": "block", "protocol": "blackhole" }
    ],
    "routing": {
        "domainStrategy": "IPIfNonMatch",
        "rules": [...],
        "balancers": [
            {
                "tag": "balancer-1",
                "selector": ["proxy-1", "proxy-2"],
                "strategy": { "type": "leastPing" }
            }
        ]
    },
    "burstObservatory": {
        "subjectSelector": ["proxy-1", "proxy-2"],
        "pingConfig": {
            "destination": "http://www.google.com/generate_204",
            "connectivity": "http://www.google.com/generate_204",
            "interval": "30s",
            "sampling": 2,
            "timeout": "5s"
        }
    },
    "stats": {}
}
```

#### Array of configurations

```json
[
    { "outbounds": [...], "routing": { "balancers": [...] }, "burstObservatory": {...} },
    { "outbounds": [...], "routing": { "balancers": [...] }, "burstObservatory": {...} }
]
```

Each item in the array is a separate complete configuration, imported as a separate “server.”

### Automatic patching

On startup, the app automatically patches the configuration (`patchFullConfigInbounds`):

#### 1. Logging

* `log.loglevel` — set from the user’s settings
* `log.access` and `log.error` — the application log file path is set

> iOS: `group.llc.itdev.incy/logs/xray.log` Android/Desktop: passed via parameter `logFilePath`

#### 2. Inbound ports

* All `socks` inbounds → port `10808`, listen `127.0.0.1`
* All `http` inbounds → port `10809`, listen `127.0.0.1`
* If the SOCKS inbound is missing, it is added automatically with sniffing settings

#### 3. Stats

If the configuration contains `burstObservatory` or `observatory`, but does not contain `stats` — an empty object is added automatically `"stats": {}`.

#### 4. DNS Direct Routing (preventing a circular dependency)

**Condition:** the configuration contains **and** observatory, **and** balancers.

**Problem:** The Observatory checks servers → DNS is needed for the check → DNS goes through the balancer → the balancer depends on Observatory results → cycle.

**Solution:** The IP addresses of DNS servers from `dns.servers` are added to the beginning of `routing.rules` with outbound `"direct"`:

```json
{
    "type": "field",
    "ip": ["8.8.8.8", "1.1.1.1"],
    "outboundTag": "direct"
}
```

If an outbound with the tag `"direct"` or protocol `"freedom"` is missing, it is added automatically.

### Display in the UI

* Complete configurations are displayed as one server in the list
* Security and transport badges are hidden (information is inside the config)
* If `meta` contains `serverDescription` — it is displayed as the server description
* The server name is taken from the first proxy-outbound

### Features of working with complete configurations

#### MPH Cache

For complete configurations **MPH cache is not used**. The cache (`mph_cache.dat`) is intended for serializing DomainMatcher, but is incompatible with complete JSON configurations. When a complete configuration is detected:

* The existing file `mph_cache.dat` is deleted
* Xray-core builds matchers at runtime
* The flag `isFullConfig` is passed from the main app to the Network Extension (iOS) via `providerConfiguration` and `sharedDefaults`

#### Geo files (Geo Trimming)

For complete configurations **geo file trimming is skipped**. Complete configurations come with their own custom geo files from the subscription, which are used as-is. When connecting:

* `GeoTrimmer` is not called
* Trimmed files are deleted (`deleteTrimmedGeoFiles`)
* Xray-core uses the original geo files

#### DNS

For complete configurations **DNS servers are not replaced**. Complete configurations already contain correctly configured DNS with filters `domains`/`expectIPs`, so the app:

* Does not substitute its own DNS servers
* Preserves the original DNS records from the configuration
* Adds only a Direct rule for DNS servers (to prevent a circular dependency with Observatory)

### Storage

The complete JSON configuration is stored in the field `fullConfigJson` of the `VLESSConfig`model. When xray-core starts, the config is patched and passed through as a whole, without generating it from separate fields.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://incy.gitbook.io/docs/docs-en/developer-documentation/xray-config-example.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
