Apple quickstart
Add the ForestVPN Swift package from source and read your first tunnel status on iOS, macOS, or tvOS.
The Apple SDK is a source SwiftPM package at forestvpn-apple/ in the
ForestVPN repository. Its Swift API (ForestVPNKit) wraps the Rust
control-plane runtime through a UniFFI layer (ForestVPNFFI), so one build
of the native library serves your app and its Network Extension.
Honest distribution note: there is no prebuilt xcframework download and
no registry package — you add the package from a source checkout and build
the Rust FFI once yourself. Platform floors: iOS 18.0, macOS 14.0, tvOS 17.0.
Prerequisites
- macOS with Xcode (the toolchain that ships
swift6+) - The Rust toolchain (rustup.rs) — the FFI library builds from Rust source
- A checkout of the ForestVPN repository
1. Get the source
git clone [email protected]:forestvpn/forestvpn.git
cd forestvpn2. Build the Rust FFI once
The Swift package links a native library built from the Rust workspace. From the repository root:
make apple-ffi-xcframeworkThis produces forestvpn-apple/Frameworks/ForestvpnApple.xcframework — the
single native artifact your app target and a Network Extension appex both
link. The Swift package itself links the library by name
(libforestvpn_apple_ffi), so make sure the xcframework (or, for
command-line swift build/swift test, a -Xlinker -L<path> pointing at
the built library) is on your target's link path.
3. Add the package
In Xcode: File → Add Package Dependencies… → Add Local… and select the
forestvpn-apple/ directory, then add the step-2 xcframework to your
target's Frameworks, Libraries, and Embedded Content. Or, from your own
Package.swift, add a path dependency:
dependencies: [
.package(path: "../forestvpn/forestvpn-apple"),
],
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "ForestVPNKit", package: "forestvpn-apple"),
]
),
]ForestVPNKit is the app-facing product; the package also exposes
ForestVPNFFI (the raw UniFFI bindings) and further products for Network
Extension, billing, and the generated API clients.
4. First call: open a session, read status
import Foundation
import ForestVPNKit
/// Open a control-plane session and read the current status.
///
/// The bootstrap profile JSON comes from your project's consumer plane
/// (`GET /consumer/v1/bootstrap`) after the device authenticates.
func firstStatus(bootstrapProfileJSON: String, stateDirectory: URL) throws -> Data {
print("SDK ABI \(ForestVPNControlPlaneClient.abiVersion), "
+ "runtime \(ForestVPNControlPlaneClient.runtimeVersion)")
let client = try ForestVPNControlPlaneClient.open(
stateDirectory: stateDirectory,
bootstrapProfileJSON: bootstrapProfileJSON
)
defer { client.close() }
return try client.statusJSON()
}The bootstrap profile JSON is the per-device configuration your backend
fetches from GET /consumer/v1/bootstrap after the device authenticates —
see Devices for the device lifecycle.
5. Run
Build your app target as usual (swift build inside a package that depends
on ForestVPNKit, or ⌘R in Xcode). On first launch the snippet prints the SDK
ABI and runtime versions, then the current status document as JSON.
Verified by
scripts/quickstart-verify/apple-swiftpm.sh — resolves the package manifest,
asserts the documented products exist, and parses this page's snippet on
every CI run (the full swift build needs the step-2 Rust build, so CI on
non-macOS runners skips it loudly).