Deploy with .mobileconfig Profiles
Build Apple .mobileconfig profiles that install Vylos WireGuard tunnels as read-only managed system entries.
Choose a Profile Type
| Goal | VPN payload type | Delivery requirement |
|---|---|---|
| Route eligible device traffic through one tunnel | com.apple.vpn.managed | Install directly or deliver through MDM. |
| Route assigned managed applications through Vylos | com.apple.vpn.managed.applayer | MDM is required for production app assignments, even if the VPN profile itself was installed directly. |
Both profile types create a managed tunnel in Vylos. They are separate from Managed App Configuration, which controls app behavior but does not install a VPN.
Where Each Setting Belongs
| Capability | Profile location |
|---|---|
| WireGuard interface and peers | VendorConfig.WgQuickConfigBase64 or WgQuickConfig |
| Split DNS and search domains | VendorConfig.VylosConfigBase64 or VylosConfig |
| Automatic activation | VPN.OnDemandEnabled and VPN.OnDemandRules |
| Block connections without the VPN | VPN.IncludeAllNetworks |
| Per-app activation | Top-level OnDemandMatchAppEnabled and VPNUUID |
| Vylos restrictions and preferences | Managed App Configuration, not the VPN profile |
The examples below use Apple's property-list form. If your MDM presents a form instead, reproduce the same dictionary nesting and types rather than flattening dotted names into literal keys.
WireGuard Configuration Transport
Place exactly one of the following keys inside the VPN payload's VendorConfig dictionary:
| Key | Value |
|---|---|
WgQuickConfig | Raw multiline UTF-8 contents of a WireGuard .conf file. |
WgQuickConfigBase64 | Single-line Base64 encoding of those same UTF-8 .conf contents. |
Use WgQuickConfigBase64 when an MDM field does not preserve line breaks. Vylos rejects a payload containing both keys because the intended source would be ambiguous.
Base64 is a transport encoding, not encryption. The encoded value is the .conf text itself—not a .vylos file, a ZIP archive, or a path to either one.
On macOS, this command copies a paste-ready value to the clipboard:
base64 -i "tunnel.conf" | tr -d '\n' | pbcopy
base64 encodes the file, tr -d '\n' removes line breaks from the encoded output, and pbcopy places the result on the clipboard. In an MDM key-value editor, paste that result as WgQuickConfigBase64 and omit WgQuickConfig.
Split DNS Settings Transport
Add exactly one of these optional keys to the same VendorConfig dictionary when the managed tunnel uses Split DNS:
| Key | Value |
|---|---|
VylosConfig | Raw multiline UTF-8 Vylos settings in the settings.conf format. |
VylosConfigBase64 | Single-line Base64 encoding of those same UTF-8 Vylos settings. |
Use VylosConfigBase64 for MDM delivery so a key-value editor cannot remove or alter line breaks. Vylos continues to accept the raw VylosConfig key for directly authored profiles, but rejects a payload containing both forms.
Create a settings.conf file containing the managed Split DNS rules:
[SplitDNS]
Domains = corp.example.com, *.internal.example.com
SearchDomains = example.com
Then copy its single-line Base64 value on macOS:
base64 -i "settings.conf" | tr -d '\n' | pbcopy
Paste the result as VylosConfigBase64. The WireGuard configuration must also provide at least one DNS server under [Interface]; Domains selects which DNS queries use those servers, while SearchDomains supplies suffixes for bare hostnames. AllowedIPs remains responsible for traffic routing and is independent of Split DNS.
The Vylos settings transport is part of the VPN profile. It is not a Managed App Configuration key.
Kill Switch for Managed Tunnels
Use Apple's IncludeAllNetworks key in the VPN payload to give a managed device-wide tunnel kill-switch behavior. Do not add the app-created [Routing] section to VylosConfig; managed routing policy belongs to Apple's VPN dictionary.
Add the following beside RemoteAddress and AuthenticationMethod inside the payload's VPN dictionary:
<key>IncludeAllNetworks</key>
<integer>1</integer>
Configure automatic activation separately with Apple's OnDemandRules. Vylos reads both values from NetworkExtension and shows the resulting On-Demand and kill-switch state as read-only tunnel details.
IncludeAllNetworks does not replace or broaden the WireGuard AllowedIPs inside WgQuickConfig or WgQuickConfigBase64. It prevents ordinary traffic from bypassing the VPN; AllowedIPs still determines whether a peer can carry each destination.
| WireGuard routes across all peers | Effective managed policy |
|---|---|
0.0.0.0/0, ::/0 or equivalent complete coverage | Full IPv4 and IPv6 tunnel protection. |
| Complete coverage for only one address family | That family uses the VPN; destinations in the other family are blocked unless explicitly routed. |
| Private networks, hosts, or other partial ranges | Strict allowlist: only covered destinations can connect, even while the tunnel is connected. |
No AllowedIPs routes | Ordinary IP traffic is blocked. |
Ensure that each DNS server in the WireGuard [Interface] section is covered by at least one peer's AllowedIPs. Otherwise the kill switch also blocks access to that DNS server. Vylos reports the effective route scope and any uncovered DNS servers in the read-only managed-tunnel details; users cannot change the profile there.
Use the restricted forms deliberately for organization allowlists. For a conventional dual-stack full tunnel, deploy both 0.0.0.0/0 and ::/0. Vylos never edits an administrator's route set.
Apple's all-network routing still exempts traffic needed for network control and certain device services. Review the IncludeAllNetworks VPN payload field and NEVPNProtocol.includeAllNetworks before deployment.
Device-Wide Profile
Use com.apple.vpn.managed for a conventional device-wide tunnel. Replace every example identifier, UUID, key, address, and endpoint before deployment.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadDisplayName</key>
<string>Vylos Managed Tunnel</string>
<key>PayloadIdentifier</key>
<string>com.example.vylos.vpn</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>00000000-0000-0000-0000-000000000003</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>VPN</string>
<key>PayloadIdentifier</key>
<string>com.example.vylos.vpn.corp</string>
<key>PayloadType</key>
<string>com.apple.vpn.managed</string>
<key>PayloadUUID</key>
<string>00000000-0000-0000-0000-000000000004</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>UserDefinedName</key>
<string>Corporate VPN</string>
<key>VPNType</key>
<string>VPN</string>
<key>VPNSubType</key>
<string>io.cbnventures.vylos</string>
<key>VendorConfig</key>
<dict>
<key>WgQuickConfig</key>
<string>[Interface]
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
Address = 10.0.0.2/32
DNS = 10.0.0.1
[Peer]
PublicKey = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=
AllowedIPs = 0.0.0.0/0
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25
</string>
<key>VylosConfig</key>
<string>[SplitDNS]
Domains = corp.example.com, *.internal.example.com
SearchDomains = example.com
</string>
</dict>
<key>VPN</key>
<dict>
<key>RemoteAddress</key>
<string>vpn.example.com</string>
<key>AuthenticationMethod</key>
<string>Password</string>
</dict>
</dict>
</array>
</dict>
</plist>
Generate unique UUIDs with uuidgen. Each additional tunnel is another com.apple.vpn.managed dictionary inside the outer PayloadContent array.
Before deployment, replace every example-specific value:
| Replace | With |
|---|---|
Both PayloadIdentifier values | Identifiers owned by your organization. |
Both PayloadUUID values | Fresh UUIDs generated with uuidgen. |
UserDefinedName and display names | The user-facing tunnel and profile names. |
The complete WgQuickConfig value | The device's real WireGuard configuration, including unique client keys and address. |
RemoteAddress | The WireGuard endpoint hostname or address used for display and system metadata. |
The optional VylosConfig value | Your Split DNS settings, or remove the key when Split DNS is not used. |
Never deploy the sample private key, public key, addresses, endpoint, or UUIDs.
To use a single-line value, replace the example WgQuickConfig key and multiline string with:
<key>WgQuickConfigBase64</key>
<string>BASE64_ENCODED_CONF</string>
Replace the example VylosConfig key and multiline string in the same way:
<key>VylosConfigBase64</key>
<string>BASE64_ENCODED_SETTINGS_CONF</string>
Per-App Profile
Use com.apple.vpn.managed.applayer with Vylos's packet-tunnel provider for per-app WireGuard routing. The payload accepts the same WgQuickConfig and WgQuickConfigBase64 alternatives, plus optional VylosConfig or VylosConfigBase64 Split DNS settings.
| Setting | Value |
|---|---|
PayloadType | com.apple.vpn.managed.applayer |
VPNType | VPN |
VPNSubType | io.cbnventures.vylos |
VPN.ProviderBundleIdentifier | io.cbnventures.vylos.packet-tunnel |
VPN.ProviderType | packet-tunnel |
VPNUUID | Unique value shared with every managed app assigned to this VPN. |
OnDemandMatchAppEnabled | true to connect when an assigned app initiates network traffic. |
The following dictionary can replace the device-wide VPN dictionary inside the profile's PayloadContent array:
<dict>
<key>PayloadDisplayName</key>
<string>Vylos Per-App VPN</string>
<key>PayloadIdentifier</key>
<string>com.example.vylos.vpn.per-app</string>
<key>PayloadType</key>
<string>com.apple.vpn.managed.applayer</string>
<key>PayloadUUID</key>
<string>00000000-0000-0000-0000-000000000005</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>UserDefinedName</key>
<string>Corporate Per-App VPN</string>
<key>VPNType</key>
<string>VPN</string>
<key>VPNSubType</key>
<string>io.cbnventures.vylos</string>
<key>VPNUUID</key>
<string>00000000-0000-0000-0000-000000000006</string>
<key>OnDemandMatchAppEnabled</key>
<true/>
<key>VendorConfig</key>
<dict>
<key>WgQuickConfigBase64</key>
<string>BASE64_ENCODED_CONF</string>
<key>VylosConfigBase64</key>
<string>BASE64_ENCODED_SETTINGS_CONF</string>
</dict>
<key>VPN</key>
<dict>
<key>AuthenticationMethod</key>
<string>Password</string>
<key>RemoteAddress</key>
<string>vpn.example.com</string>
<key>ProviderBundleIdentifier</key>
<string>io.cbnventures.vylos.packet-tunnel</string>
<key>ProviderType</key>
<string>packet-tunnel</string>
<key>OnDemandEnabled</key>
<integer>1</integer>
</dict>
</dict>
Installing this payload creates the VPN but does not assign applications to it. Continue with Configure Per-App VPN to associate managed apps with the same VPNUUID and understand the supported routing fields.
Install and Remove Profiles
Deliver profiles through MDM for centralized ownership, replacement, and removal. A user can also install a device-wide profile directly when MDM is unavailable, then remove it later through the operating system's profile-management settings.
Vylos treats either delivery method as profile-owned and read-only. Updating or removing the profile—not editing inside Vylos—is the supported way to change the tunnel.
For the resulting app experience, see Deploy Managed Tunnels. For Apple's complete payload contract, see the VPN payload reference and AppLayerVPN payload reference.