Profile manual
Profiles
On this page
A profile is a text file that configures proxies, groups, routing rules and DNS. It can also rewrite HTTP, decrypt HTTPS for selected hosts and run scripts. Start with the default below; use the reference pages when you need a particular setting.
The format is Pipe's own, and this manual is its reference: write your profiles in it. It began from Surge's, but follows Pipe, not Surge. A profile from Surge, Clash, mihomo or sing-box is converted into it when you import it, as far as Pipe's format can say what the other app's said; what does not come across is listed once, when it is added. Importing profiles explains what carries across.
The default profile#
New installs use these routing settings, the same in every country:
[General]
loglevel = notify
# The resolvers of the network you are on.
dns-server = system
[Proxy]
[Proxy Group]
# Every proxy you imported, one of them active. Until one is imported
# the group has no member and refuses what reaches it: that traffic
# waits for a proxy, rather than leaving unproxied.
Proxy = select, policy-path=pool.list
[Rule]
# Your own network, by its local names and addresses: nothing is looked up for it.
RULE-SET,LAN,DIRECT,no-resolve
# Your region: addresses in the country of the network you are on.
GEOIP,REGION,DIRECT
# Other traffic.
FINAL,Proxy,dns-failed
- Your own network — its local names, and connections made to its addresses — and addresses in your region — the country of the network the device is on (Your region) — go directly. A name is never taken for your network by what its lookup says (Address rules on names). Everything else uses the proxy selected from your pool. Travel, and your region travels with you.
- Until you import a usable proxy, the empty
Proxygroup refuses traffic sent to it. It does not queue connections or send them directly. - Names are looked up at the resolvers of the network you are on, in
plain DNS.
GEOIP,REGIONgoes by the address of the name a connection is made to, so every name that is not local is looked up there before its connection goes on (a connection through the proxy is given the name, not that address). Apps' own lookups get fake addresses and reach no server, except for names inalways-real-ipand for record types other than addresses. - The app can ask a DNS preset — a public resolver, in plain DNS, over HTTPS, over TLS or with DNSCrypt — in place of the network's own, and can set the region itself. Neither changes a line of the profile: it stays the default profile. See DNS for the rest, and Rules for lookup behaviour.
Profiles compile for iOS in the app and for the Mac or Linux host in the CLI. Use line requirements when a whole profile line should apply only on the app or on a CLI host. Controls for other apps are kept as source text and diagnosed as unknown settings.
How a connection is decided#
These steps apply to traffic entering Pipe. Traffic excluded by the OS's VPN settings bypasses Pipe.
- Your networks. What a tailnet or a WireGuard network claims — its devices' names and addresses, its routes — goes to it, in every mode and on every network: tailnets first, then WireGuard networks. While a tailnet is not running (starting, signed out, waiting for approval, expired), what it claims is refused rather than sent anywhere else.
- The exit node. With an exit node chosen for the internet, the
rules are still tried, and a
REJECTstands; everything else goes through the exit node — or, while it cannot carry it, nowhere. The local network stays direct while the tailnet allows it. - The network. On a network an
[SSID Setting]line suspends Pipe on, ordinary profile traffic goes directly. - The mode. In Rule mode the rules decide. In Global mode every
connection goes to the one proxy picked for it in the app — the
FINALrule's policy until one is — but for local destinations — private, loopback and link-local addresses,.localnames and names of one label — which go directly. In Direct mode ordinary profile traffic goes directly. - The rules.
[Rule]lines are tried from the top, and the first that matches decides.FINAL, the last, takes what no other matched (Rules). - The policy. A rule names a policy: a built-in one (
DIRECT,REJECTand their kin), a proxy, or a group (Built-in policies). - The group. A group hands the connection to one of its members: the one picked by hand, the fastest, the first that answers, and so on. A member may be another group (Groups).
- The proxy. A proxy connects to its server — directly, or through
another policy (
underlying-proxy), or through the tailnet or WireGuard network its server is on — and carries the connection there (Proxies).
Two things work alongside these steps.
- Names. Through the tunnel, apps are given fake IPs for the names
they look up — addresses that stand for the names — so that each
connection still carries its name and rules can decide by it. A name
is really looked up only when a rule needs its address, or when the
connection goes out directly; a proxy is given the name itself
(DNS). A tailnet's names are answered from its map, and its
split-DNS domains — and a WireGuard network's
dns-domains— are asked of its own DNS. With an exit node chosen, every other name is asked of the exit node, after[Host]andpre-matchingrejects, with real addresses rather than fake ones. - HTTP requests. Plain HTTP, and HTTPS for the hosts
[MITM]names, is carried request by request: each request can be rewritten, answered locally, handed to a script, and routed by itself (The HTTP engine).
What Pipe says about a profile#
Pipe compiles a profile — reads it, and builds from it what the engine runs — whenever the profile changes, and whenever the proxy pool, a group's pick or the mode changes. Compiling never drops a line in silence: what Pipe cannot do stays in the file, and compiling says so, with the line it is on. What it says is of three kinds.
| Kind | Meaning | For example |
|---|---|---|
| Error | The profile cannot be used as it is written: it does not compile. | a rule naming a policy that does not exist; two proxies with one name; no FINAL rule; a group of an unknown type |
| Warning | Something in the profile does not do here what it says. The profile still runs. | a proxy Pipe cannot use; a rule type it cannot evaluate; a feature it does not have yet; a line it had to leave out |
| Note | Worth knowing; it changes nothing. | a setting Pipe does not know (hijack-dns); a parameter that is read past |
Each message starts with where it was written: line 12 in the profile,
corp.list:3 in a file the profile names, ads.sgmodule:7 in a module.
line 8: 'Streaming' is not a proxy, a group or a built-in policy
line 12: proxy 'JP 02' cannot be used: MASQUE is not supported yet. Groups leave it out; rules that name it reject
line 31: this rule comes after FINAL, so it never applies
line 3: `mptcp` (on 40 proxies) is not supported yet and is ignored
The first is an error, the next two are warnings, the last a note. A
parameter that many proxies share is said once for the whole profile,
with how many proxies have it. A setting of another platform's — a Mac's
skip-proxy on an iPhone — is not said at all: one profile serves a
phone and a computer alike, and each reads its own
(General). A profile converted
from another app's has nothing of that app's left to be said about: the
conversion says what it left out once, when the profile is added
(Importing), and what checking it reports from then on is
about the Pipe profile.
A proxy Pipe cannot use is left out of every group, and a rule that names
it directly refuses what it matches: traffic never goes through a proxy
other than the one the profile describes. A group left with no member
Pipe can use refuses everything it is given — unless DIRECT is among
the members it names, in which case that is where its traffic goes. Both
are said.
In the iOS app, messages are shown with the profile, and the text view marks the lines they are about. When the profile in use stops compiling, Pipe keeps running the last version of it that did.
Editing and updates#
The iOS app offers structured settings and a text editor. Structured edits
preserve unrelated lines and comments. They edit the profile's own lines,
not content from #!include or modules.
Use modules to customize a managed profile without losing your changes
when its source updates.
When the profile in use changes — edited, fetched again from where it is managed, or patched by a module — it goes into the running engine whole. The tunnel stays up, and so do open connections.
This manual#
| Page | What it covers |
|---|---|
| The file | Sections and lines, comments, quoting, #!include, line requirements, managed profiles, the kinds of values |
| General | Every [General] setting |
| Proxies | Proxy types and their parameters, TLS, WebSocket, chains, built-in policies, [Keystore], WireGuard, tailnets, the pool |
| Groups | Group types, how members are assembled, policy-path, tests, choosing by hand |
| Rules | Rule types, their options, sniffing, rule sets and list formats |
| DNS | Named DNS servers, ordered DNS rules and response filtering, encrypted DNS, [Host], fake IPs, DNS scripts |
| The HTTP engine | Requests and answers, rewrites, [Map Local], HTTPS decryption, capture |
| Scripts | [Script], the script API, [Panel] |
| Networks | Per-network settings, subnet expressions, the tunnel, [IP Rewrite], [Port Forwarding] |
| Modules | Modules: what they patch and how, and how the app applies them |
| Importing profiles | Profiles from other apps, converted into Pipe profiles |
| The command line | The pipe command: running an engine, controlling one here or on another machine |