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
OpenVPN.xcodeproj in Xcode. The project contains two targets:
| Target | Purpose |
|---|---|
| VPN | The main iOS application |
| VPNExtension | The Network Extension that runs the WireGuard / OpenVPN tunnel |
Step 2 — Set Bundle Identifiers
Select the VPN target → General tab → Identity: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:- Set Team to your Apple Developer account.
- Enable Network Extensions → check Packet Tunnel.
- Enable App Groups → add
group.com.YOURTEAM.VPN(the same value in both targets).
- 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:
| Key | Description |
|---|---|
baseURL | Root URL of your VPN backend. No trailing slash. |
upgradeURL | Shown as an “Upgrade” link when the user has no active plan. |
recaptchaSiteKey | Google reCAPTCHA v3 site key. Register at google.com/recaptcha/admin. |
recaptchaDomain | Must 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 forYOURTEAM and replace:
Extension bundle ID (2 files)
VPN/Services/WireGuardAdapter.swiftVPN/Services/OpenVPNAdapter.swift
App Group identifier (3 files)
VPN/Services/KeychainHelper.swift→private let service = "com.YOURTEAM.vpn"VPN/Views/MyAccountView.swift→let appGroupIdentifier = "group.com.YOURTEAM.VPN"VPNExtension/PacketTunnelProvider.swift→let appGroupIdentifier = "group.com.YOURTEAM.VPN"
Step 6 — Update Entitlements
VPN/VPN.entitlements
VPNExtension/VPNExtension.entitlements
Step 7 — Add Your App Logo & Icon
Splash screen logo
- Prepare a square PNG at 1024×1024 px (transparent background recommended).
- Name it
AppLogo.pngand place it in: - The
Contents.jsonin that folder already references this filename.
App Icon
Replace the images insideVPN/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
OpenVPN/Views/SplashView.swift and update:
- Select the VPN target → General → Display Name.
Step 9 — Apple Sign-In (optional)
Apple Sign-In is controlled server-side. Your backend’s/api/v1/app-config endpoint returns:
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.
Step 10 — Universal Links (Password Reset)
The app handles password-reset deep links sent by the backend in the form:applinks: value in VPN.entitlements matches your domain exactly.
Step 11 — Build & Archive
- Select a real device or Any iOS Device (arm64) as the build target.
- Product → Archive.
- In the Organizer, click Distribute App → App Store Connect (or Ad Hoc for testing).
- Follow the prompts to upload to App Store Connect.
Quick Checklist
Hardcoded identifiers
Update extension bundle ID in
WireGuardAdapter.swift and OpenVPNAdapter.swift.App group
Update
group.com.YOURTEAM.VPN in KeychainHelper.swift, MyAccountView.swift, and PacketTunnelProvider.swift.