Skip to main content
The iOS VPN app is a native Swift / SwiftUI application that connects to your VPN backend over the same REST API used by the web frontend. It supports WireGuard and OpenVPN and ships with Apple Sign-In, reCAPTCHA protection, and a Network Extension tunnel provider.

Prerequisites

  • macOS with Xcode 15+ installed
  • An Apple Developer Program membership (required to sign a Network Extension)
  • Your VPN backend deployed and reachable over HTTPS
  • A Google reCAPTCHA v3 site key registered for your domain
  • The iOS app source code (VPN-Release/ folder from your purchase)

Step 1 — Open the Project

Open VPN.xcodeproj in Xcode. The project contains two targets:
TargetPurpose
VPNThe main iOS application
VPNExtensionThe Network Extension that runs the WireGuard / OpenVPN tunnel

Step 2 — Set Bundle Identifiers

Select the VPN target → General tab → Identity:
com.YOURTEAM.VPN
Select the VPNExtension target → General tab → Identity:
com.YOURTEAM.VPN.VPNExtension
The extension bundle ID must be a sub-identifier of the main app (i.e. it must start with the main app’s bundle ID followed by a dot).

Step 3 — Configure Signing & Capabilities

For both targets, open Signing & Capabilities:
  1. Set Team to your Apple Developer account.
  2. Enable Network Extensions → check Packet Tunnel.
  3. Enable App Groups → add group.com.YOURTEAM.VPN (the same value in both targets).
For the VPN target only, also enable:
  • Sign in with Apple (if you want Apple Sign-In — see Step 8).
  • Associated Domains → add applinks:YOURDOMAIN.com (for password-reset universal links).

Step 4 — Configure Configuration.swift

Open VPN/Utils/Configuration.swift and fill in:
struct Configuration {
    static let baseURL = "https://vpn.yourdomain.com"
    static let upgradeURL = "https://vpn.yourdomain.com/pricing"
    static let recaptchaSiteKey = "6Lc..."          // your v3 site key
    static let recaptchaDomain = "https://vpn.yourdomain.com"
}
KeyDescription
baseURLRoot URL of your VPN backend. No trailing slash.
upgradeURLShown as an “Upgrade” link when the user has no active plan.
recaptchaSiteKeyGoogle reCAPTCHA v3 site key. Register at google.com/recaptcha/admin.
recaptchaDomainMust match the domain registered in the reCAPTCHA console. Usually the same as baseURL.

Step 5 — Update Hardcoded Identifiers

Several Swift files contain identifiers that must match your bundle ID. Search for YOURTEAM and replace:

Extension bundle ID (2 files)

  • VPN/Services/WireGuardAdapter.swift
  • VPN/Services/OpenVPNAdapter.swift
proto.providerBundleIdentifier = "com.YOURTEAM.VPN.VPNExtension"
Change this to your VPNExtension bundle ID from Step 2.

App Group identifier (3 files)

  • VPN/Services/KeychainHelper.swiftprivate let service = "com.YOURTEAM.vpn"
  • VPN/Views/MyAccountView.swiftlet appGroupIdentifier = "group.com.YOURTEAM.VPN"
  • VPNExtension/PacketTunnelProvider.swiftlet appGroupIdentifier = "group.com.YOURTEAM.VPN"

Step 6 — Update Entitlements

VPN/VPN.entitlements

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.YOURTEAM.VPN</string>
</array>
<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:YOURDOMAIN.com</string>
</array>

VPNExtension/VPNExtension.entitlements

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.YOURTEAM.VPN</string>
</array>
Both files are XML plists — you can edit them directly in Xcode via the Signing & Capabilities pane or in any text editor.

Step 7 — Add Your App Logo & Icon

  1. Prepare a square PNG at 1024×1024 px (transparent background recommended).
  2. Name it AppLogo.png and place it in:
    VPN/Assets.xcassets/AppLogo.imageset/AppLogo.png
    
  3. The Contents.json in that folder already references this filename.

App Icon

Replace the images inside VPN/Assets.xcassets/AppIcon.appiconset/ with your own icons at the required sizes. Use appicon.co or similar to generate all sizes from a 1024×1024 master.

Step 8 — App Name & Tagline

Open VPN/Views/SplashView.swift and update:
Text("Your VPN App")          // change to your app name
Text("Private. Secure. Free.") // change to your tagline
You should also update the Display Name in Xcode:
  • Select the VPN target → GeneralDisplay Name.

Step 9 — Apple Sign-In (optional)

Apple Sign-In is controlled server-side. Your backend’s /api/v1/app-config endpoint returns:
{ "apple_login_enabled": true }
Set this to false on the backend to hide the button without any code changes. If you do not want to offer Apple Sign-In at all, remove the com.apple.developer.applesignin entitlement from VPN/VPN.entitlements and remove the capability from Xcode.
The app handles password-reset deep links sent by the backend in the form:
https://YOURDOMAIN.com/reset-password/{token}?email=user@example.com
For these to open the app automatically, your web server must serve the Apple App Site Association file at:
https://YOURDOMAIN.com/.well-known/apple-app-site-association
The Laravel backend serves this file automatically. Ensure the applinks: value in VPN.entitlements matches your domain exactly.

Step 11 — Build & Archive

  1. Select a real device or Any iOS Device (arm64) as the build target.
  2. Product → Archive.
  3. In the Organizer, click Distribute AppApp Store Connect (or Ad Hoc for testing).
  4. Follow the prompts to upload to App Store Connect.

Quick Checklist

1

Bundle IDs

Set unique bundle IDs for both targets in Xcode.
2

Signing

Set your Team and enable required capabilities (Network Extension, App Groups).
3

Configuration.swift

Fill in baseURL, upgradeURL, recaptchaSiteKey, and recaptchaDomain.
4

Hardcoded identifiers

Update extension bundle ID in WireGuardAdapter.swift and OpenVPNAdapter.swift.
5

App group

Update group.com.YOURTEAM.VPN in KeychainHelper.swift, MyAccountView.swift, and PacketTunnelProvider.swift.
6

Entitlements

Update app group and associated domain in both .entitlements files.
7

Logo & icon

Add your AppLogo.png and replace App Icon assets.
8

App name

Update display name in Xcode and the Text("Your VPN App") line in SplashView.swift.
9

Archive & submit

Build for a device, archive, and upload to App Store Connect.