Configuration Compilation
This document describes how xp2p turns operator-facing configuration (TOML + optional JSON snippets)
into the final xray-core runtime configuration.
The goal is to:
- Keep human-editable inputs small and stable.
- Allow safe user extensions without editing generated files.
- Produce a deterministic, validated final Xray JSON config.
Sources of Truth
xp2p treats configuration as layered inputs.
Desired Inputs (operator-editable)
Managed behavior is configured through TOML and can be edited manually or via CLI/UI:
CONFIG_ROOT/xp2p-client.tomlCONFIG_ROOT/xp2p-server.toml
User extensions are provided as JSON snippets under role config directories:
CONFIG_ROOT/config-client/*.jsonCONFIG_ROOT/config-server/*.json
xp2p reads these JSON files and merges them into the final Xray configuration. xp2p must not rewrite them.
Build Artifacts (runtime outputs)
xp2p compiles inputs into a final Xray JSON configuration file that is used at runtime:
CONFIG_ROOT/.state/live/config-client/xray.jsonCONFIG_ROOT/.state/live/config-server/xray.json
These files are generated by the service/apply layer and must not be edited manually.
Directory Layout
- Desired inputs
CONFIG_ROOT/xp2p-*.tomlCONFIG_ROOT/config-*/(JSON snippets)- Service state and runtime artifacts
CONFIG_ROOT/.state/apply.requestCONFIG_ROOT/.state/apply.errorCONFIG_ROOT/.state/live/config-*/xray.jsonCONFIG_ROOT/.state/lkg/config-*/xray.json(optional)CONFIG_ROOT/audit.log
The .state directory stores service/apply metadata and compiled runtime artifacts. It does not mirror Desired inputs.
Compilation Pipeline
For each role (client/server), the service/apply layer performs:
- Load Desired TOML (
CONFIG_ROOT/xp2p-*.toml). - Load Desired JSON snippets from
CONFIG_ROOT/config-*/(if present). - Build the managed base Xray configuration from TOML (endpoints, routing, inbounds, logs, reverse bridges, etc.).
- Merge user snippets into the managed base according to deterministic rules.
- Validate the final config (structure, reserved tag collisions, required sections).
- Write the final config to
.state/live/config-*/xray.jsonatomically. - Start/restart Xray using the final JSON file only.
Merge Rules
xp2p merges JSON snippets into the managed base in a role-specific way. The merge is explicit and deterministic.
Supported Extension Files
JSON snippets live in:
CONFIG_ROOT/config-client/CONFIG_ROOT/config-server/
All files are optional. For discoverability, xp2p ships blank templates in:
config_templates/extensions/config-client/config_templates/extensions/config-server/
Client
routing.rules.after-xp2p-system.json- Shape:
{ "rules": [ ... ] } - Inserted after managed endpoint-bypass + system glue rules.
- Use for high-priority rules that should win over redirects/forwards.
routing.rules.after-xp2p-managed.json- Shape:
{ "rules": [ ... ] } - Inserted after all managed rules and before the full-tunnel rule (when enabled).
- Use for additional rules that should not override core safety rules.
inbounds.append.json- Shape:
{ "inbounds": [ ... ] } - Appended to managed inbounds.
outbounds.append.json- Shape:
{ "outbounds": [ ... ] } - Appended to managed outbounds.
Server
routing.rules.after-xp2p-system.json(same meaning as client)routing.rules.after-xp2p-managed.json(same meaning as client)inbounds.append.json(append to managed inbounds)outbounds.append.json(append to managed outbounds)
Reserved Namespace
xp2p reserves identifiers it manages (tags, remarks, internal routing domains).
The following are reserved by default:
proxy-*(endpoint outbounds)*.rev(reverse bridge domains)xp2p-*(internal tags and glue components)
User snippets must not introduce collisions with reserved identifiers unless an explicit override mode is enabled.
Routing Rule Order
The final routing rule order is stable:
- Managed endpoint bypass rules (used for safe tunnel reachability).
- Managed system rules (reverse/marker glue, internal responders).
- Managed redirect/forward rules.
- User rules (optional) inserted at extension points (see Supported Extension Files above).
- Managed full-tunnel rule (when enabled).
If user routing snippets are present, they are inserted at the configured extension points only.
Outbounds, Inbounds, and Other Sections
User snippets can add additional objects, but xp2p-managed objects remain authoritative.
Common supported extension points:
- Additional
inbounds - Additional
outbounds - Additional
routing.rules - DNS and policy sections (if provided by Xray)
For safety, xp2p rejects:
- Attempts to delete managed objects.
- Attempts to modify reserved tags without override mode.
- Attempts to add objects with invalid or conflicting tags.
Commands for Inspection
xp2p provides inspection commands that do not change runtime state.
Render Final Xray JSON
Render the exact JSON that would be used at runtime:
xp2p client render xray --live --output -
xp2p server render xray --live --output -
Render the configuration compiled from Desired inputs (without applying it):
xp2p client render xray --desired --output -
xp2p server render xray --desired --output -
Debug Bundle
Collect a self-contained archive for troubleshooting:
xp2p client debug bundle --output /tmp/xp2p-client-debug.zip
xp2p server debug bundle --output /tmp/xp2p-server-debug.zip
The bundle includes:
- Desired inputs (
xp2p-*.tomlandconfig-*/snippets) apply.request/apply.error(when present)- final
xray.json audit.log- service logs under
XP2P_LOG_ROOT
Operational Notes
- Operators edit TOML and JSON snippets only.
- The service/apply layer compiles and validates configs into
xray.json. - Runtime processes always use the live compiled
xray.jsononly.