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 sectionWhat it doesRequired
Basic runtimePorts, mode, log level, LAN accessAt least one inbound entry is required
DNS/hostsDomain resolution, Fake-IP, static domain mappingsStrongly recommended for TUN/transparent proxy
Inbound takeovermixed-port, TUN, transparent proxy, protocol listenersAt least one inbound entry is required
Outbound and policyNodes, subscriptions, policy groupsAn outbound target that can be referenced by rules is required
RulesDecide where connections goRecommended to have at least a fallback MATCH
Advanced featuresHTTP Engine, device discovery, NTP, experimental switchesEnable 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:

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:

Naming recommendations:

TypeRecommended styleExamples
Manually written nodeShort but identifiable route namehk-1, jp-hy2
Subscription providerIndicate the sourceairport, office-vpn
Manual policy groupUppercase business namePROXY, AI, MEDIA
Automatic policy groupIndicate the algorithmAUTO, FALLBACK
Rule setLowercase categoryprivate, china, reject

Built-in Actions#

Link1 has these built-in actions:

NameMeaning
DIRECTConnect directly to the target
REJECTReject 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:

Recommended:

proxy-providers:
  airport:
    type: http
    url: https://example.com/sub.yaml
    path: ./providers/airport.yaml

Practical effects:

Defaults and Explicit Values#

Some fields have default values, for example:

FieldDefaultEffect
moderuleRoute by rules
log-levelinfoOutput info-level logs
allow-lanfalseDo not expose to the LAN by default
bind-address*Works with port listen addresses
ipv6trueAllows IPv6 globally, but DNS still has its own dns.ipv6
find-process-modestrictProcess rules obtain process information in strict mode
profile.store-selectedtruePersist policy group selections
profile.store-fake-iptruePersist 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:

Example error:

compile config "config.yaml": proxy-groups[0].proxies[1]="node-x" is undefined

How to read it:

Troubleshooting tips:

  1. Check the path first: proxies[3], rules[12], and dns.nameserver[1] point to the error location.
  1. Then check object names: many errors come from inconsistent spelling.
  1. 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:

Practical guidance for splitting files:

ContentRecommended locationReason
Main inbound configurationconfig.yamlThe App uses it as the entry point for import, validation, and application.
Subscription cache/local providerproviders/Avoid mixing them with manually written nodes.
Rule setsrules/Rules are updated often and are clearer when maintained separately.
Certificates/private keyscerts/Easier to set permissions and troubleshoot path errors.
HTTP Engine scriptshttp-engine/scripts/Scripts are usually longer than YAML and are easier to debug as separate files.
Mock bodyhttp-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