4. Configuration File Model#
Link1 uses YAML configuration. You can think of the configuration file as a “network behavior specification”: which ports accept traffic, how DNS is resolved, which outbound options are available, and how rules select an outbound route.
App Configuration and Core Configuration#
The Link1 App manages profiles, runtime state, and UI display; the core configuration only describes network behavior. Most users mainly need to understand these parts of the core configuration:
| Configuration section | What it does | Required |
|---|---|---|
| Basic runtime | Ports, mode, log level, LAN access | At least one inbound entry is required |
| DNS/hosts | Domain resolution, Fake-IP, static domain mappings | Strongly recommended for TUN/transparent proxy |
| Inbound takeover | mixed-port, TUN, transparent proxy, protocol listeners | At least one inbound entry is required |
| Outbound and policy | Nodes, subscriptions, policy groups | An outbound target that can be referenced by rules is required |
| Rules | Decide where connections go | Recommended to have at least a fallback MATCH |
| Advanced features | HTTP Engine, device discovery, NTP, experimental switches | Enable as needed |
Users are not advised to manually write App-related internal state into the main configuration. The user documentation only covers fields that affect network behavior.
Top-Level Structure#
A common complete structure is as follows:
# 1. Basic runtime
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
# 2. DNS and hosts
dns: {}
hosts: {}
hosts-providers: {}
# 3. Inbound takeover
tun: {}
app-proxy: {}
sniffer: {}
listeners: []
# 4. Outbounds and policies
proxies: []
proxy-providers: {}
proxy-groups: []
# 5. Rules
rule-providers: {}
rule-sets: {}
sub-rules: {}
rules: []
# 6. Advanced features
http-engine: {}
device-discovery: {}
profile: {}
tls: {}
experimental: {}
ntp: {}
iptables: {}
You do not need to write every block at once. A minimal configuration only needs an inbound entry, an outbound target, and rules.
YAML Basics#
YAML uses indentation to represent hierarchy:
proxies:
- name: node-a
type: socks5
server: 127.0.0.1
port: 1080
Notes:
- Use spaces for indentation, not tabs.
- Field names are case-sensitive, and hyphens must be correct, such as
mixed-port.
- Quote strings that contain special characters.
- Use
-for lists.
- Use
key: valuefor maps.
- Indentation at the same level must align; incorrect indentation may place fields under the wrong level.
Names and References#
Many objects in Link1 are referenced by name:
proxies:
- name: node-a
type: socks5
server: 127.0.0.1
port: 1080
proxy-groups:
- name: PROXY
type: select
proxies:
- node-a
- DIRECT
rules:
- MATCH,PROXY
Practical effects:
node-ais the outbound node name.
PROXYis the policy group name.
- The action in
rulescan reference a node or policy group.
- Names must be unique and must not conflict with built-in actions.
- Referencing a nonexistent name will cause an error during configuration compilation.
Naming recommendations:
| Type | Recommended style | Examples |
|---|---|---|
| Manually written node | Short but identifiable route name | hk-1, jp-hy2 |
| Subscription provider | Indicate the source | airport, office-vpn |
| Manual policy group | Uppercase business name | PROXY, AI, MEDIA |
| Automatic policy group | Indicate the algorithm | AUTO, FALLBACK |
| Rule set | Lowercase category | private, china, reject |
Built-in Actions#
Link1 has these built-in actions:
| Name | Meaning |
|---|---|
DIRECT | Connect directly to the target |
REJECT | Reject the connection |
You can also explicitly create type: direct or type: reject nodes, but normal configurations usually use the built-in actions directly.
Path Resolution#
Many fields can contain file paths:
proxy-providers.*.path
rule-providers.*.path
hosts-providers.*.path
- Certificate and private key fields, such as
certificate,private-key,ca
- HTTP Engine fields such as
file,body-file,spool-dir
Recommended:
proxy-providers:
airport:
type: http
url: https://example.com/sub.yaml
path: ./providers/airport.yaml
Practical effects:
- Relative paths are resolved based on the configuration loading location/working directory.
- For router or service deployments, use a fixed working directory and relative paths to make migration easier.
- If a path file does not exist, an HTTP provider can download and generate it; a file provider usually requires the file to already exist.
- When importing a configuration in the App, make sure referenced local files are also placed in the corresponding configuration directory.
Defaults and Explicit Values#
Some fields have default values, for example:
| Field | Default | Effect |
|---|---|---|
mode | rule | Route by rules |
log-level | info | Output info-level logs |
allow-lan | false | Do not expose to the LAN by default |
bind-address | * | Works with port listen addresses |
ipv6 | true | Allows IPv6 globally, but DNS still has its own dns.ipv6 |
find-process-mode | strict | Process rules obtain process information in strict mode |
profile.store-selected | true | Persist policy group selections |
profile.store-fake-ip | true | Persist Fake-IP mappings |
Defaults make the configuration shorter, but that does not mean you do not need to understand them. For example, allow-lan=false is safe, but LAN devices will not be able to connect.
Configuration Compilation and Error Location#
Before the Link1 core starts, it compiles YAML into a runtime structure. The compilation stage checks:
- Whether port ranges are valid.
- Whether required fields are missing.
- Whether a protocol supports a given field.
- Whether rule actions exist.
- Whether provider types and formats are valid.
- Whether TUN/transparent proxy fields comply with platform restrictions.
- Whether DNS server schemes are supported.
Example error:
compile config "config.yaml": proxy-groups[0].proxies[1]="node-x" is undefined
How to read it:
proxy-groups[0]: the first policy group.
proxies[1]: the second member of that group.
node-x is undefined: it references a nonexistent node or group.
Troubleshooting tips:
- Check the path first:
proxies[3],rules[12], anddns.nameserver[1]point to the error location.
- Then check object names: many errors come from inconsistent spelling.
- Finally, check combination constraints: for example, TUN and a platform transparent inbound cannot be enabled at the same time, or a protocol may not support a certain transport layer.
Configuration Layering Recommendations#
The Link1 main configuration is a YAML file. Examples in the user manual are shown as single files to make copying, importing, and troubleshooting easier.
If you are familiar with !include in other tools, note that Link1 does not rely on YAML !include to split the main configuration. When the App imports a profile, it manages configuration around one main YAML file; relative paths are used to reference external resources, such as provider files, rule files, certificates, HTTP Engine scripts, and Mock bodies. During migration, you only need to keep the relative locations of these files and the main configuration unchanged.
Recommended directory layout:
link1/
config.yaml
providers/
airport.yaml
rules/
private.yaml
reject.yaml
certs/
ca.pem
client.key
http-engine/
scripts/
rewrite.js
bodies/
mock.json
Benefits:
- The main configuration only keeps “network behavior”: inbound, DNS, outbound, policy groups, and rules.
- Subscriptions/providers, rule sets, certificates, scripts, and Mock bodies have fixed locations.
- During troubleshooting, you can quickly locate files from error paths, such as
http-engine/scripts/rewrite.jsorrules/private.yaml.
- It is easier for the App to import/export profiles as a whole.
Practical guidance for splitting files:
| Content | Recommended location | Reason |
|---|---|---|
| Main inbound configuration | config.yaml | The App uses it as the entry point for import, validation, and application. |
| Subscription cache/local provider | providers/ | Avoid mixing them with manually written nodes. |
| Rule sets | rules/ | Rules are updated often and are clearer when maintained separately. |
| Certificates/private keys | certs/ | Easier to set permissions and troubleshoot path errors. |
| HTTP Engine scripts | http-engine/scripts/ | Scripts are usually longer than YAML and are easier to debug as separate files. |
| Mock body | http-engine/bodies/ | Keeps YAML concise and avoids escaping long text. |
If you need to send the configuration to someone else for troubleshooting, sending only the main YAML is often not enough. Any files referenced by file:, path:, providers, or rule sets should be provided together, with sensitive credentials redacted first.
Common Relationships Between Configuration Blocks#
proxies Static outbound nodes
proxy-providers Dynamic or subscription outbound nodes
proxy-groups Combine nodes/provider nodes into exits
rules Route connections to nodes or policy groups
rule-providers Sources for large rule sets
rule-sets Compiled or inline rule sets
sub-rules Sub-rule flows
dns Resolve domains and Fake-IP
hosts Static domain mappings
hosts-providers External hosts files
sniffer Sniff domains from traffic
mixed-port/port/socks-port/redir-port/tproxy-port/tun/app-proxy/listeners
Decide how traffic enters Link1
How a Configuration Grows Step by Step#
Stage 1: Confirm the Inbound Entry Works#
mixed-port: 7890
rules:
- MATCH,DIRECT
Goal: confirm that the core starts and clients can connect.
Stage 2: Add an Outbound Node#
proxies:
- name: node-a
type: socks5
server: 127.0.0.1
port: 1080
proxy-groups:
- name: PROXY
type: select
proxies: [node-a, DIRECT]
rules:
- MATCH,PROXY
Goal: confirm that the proxy node works.
Stage 3: Add DNS and Domain Rules#
dns:
enable: true
nameserver:
- https://dns.google/dns-query
rules:
- DOMAIN-SUFFIX,example.com,PROXY
- MATCH,DIRECT
Goal: confirm that domain rules are matched.
Stage 4: Add TUN, Subscriptions, Rule Sets, or HTTP Engine#
Add only one type of advanced feature at a time, and observe changes in connections, rules, and logs in the App.
Not Recommended#
Enabling All Advanced Features at the Start#
Do not enable TUN, Sniffer, HTTP Engine, multiple providers, and complex rules all at the same time for your first configuration. Use mixed-port + MATCH,DIRECT or one upstream node to validate the basic path first, then add features gradually.
Relying on Sniffer to Fix All Traffic#
Sniffer is a supplemental tool, not a replacement for DNS configuration. In TUN/transparent proxy scenarios, DNS should enter Link1 first.
Copying Another Core Configuration Without Validation#
Link1 is compatible with common fields, but not all historical fields are supported. After migrating a configuration, run validation in the App first, or run directly:
spark -f config.yaml -t