diff --git a/swift/apple/Firezone/ExportOptions.plist b/swift/apple/Firezone/ExportOptions.plist
index 8caf53fba..90d492ecd 100644
--- a/swift/apple/Firezone/ExportOptions.plist
+++ b/swift/apple/Firezone/ExportOptions.plist
@@ -7,10 +7,10 @@
provisioningProfiles
dev.firezone.firezone
- b32a5853-699d-4f19-85d3-5b13b1ac5dbb
+ 9aafa0f8-4b68-49c8-b023-0d4576142e1f
dev.firezone.firezone.network-extension
- 23402aaa-f72c-4947-a795-23a9cf495968
+ 49b53dcc-efaf-4171-9f3b-ca8c46e41069
diff --git a/swift/apple/Firezone/xcconfig/release.xcconfig b/swift/apple/Firezone/xcconfig/release.xcconfig
index 77f438102..78ce67608 100644
--- a/swift/apple/Firezone/xcconfig/release.xcconfig
+++ b/swift/apple/Firezone/xcconfig/release.xcconfig
@@ -5,7 +5,7 @@ APP_GROUP_ID[sdk=macosx*] = 47R2M6779T.group.dev.firezone.firezone
APP_GROUP_ID[sdk=iphoneos*] = group.dev.firezone.firezone
CODE_SIGN_STYLE = Manual
CODE_SIGN_IDENTITY = Apple Distribution: Firezone, Inc. (47R2M6779T)
-IOS_APP_PROVISIONING_PROFILE_IDENTIFIER = b32a5853-699d-4f19-85d3-5b13b1ac5dbb
-MACOS_APP_PROVISIONING_PROFILE_IDENTIFIER = 70055d90-0252-4ee5-a60c-4d6f3840ee62
-IOS_NE_PROVISIONING_PROFILE_IDENTIFIER = 23402aaa-f72c-4947-a795-23a9cf495968
-MACOS_NE_PROVISIONING_PROFILE_IDENTIFIER = 1e965794-0b2c-46d3-a955-d96aacf25546
+IOS_APP_PROVISIONING_PROFILE_IDENTIFIER = 9aafa0f8-4b68-49c8-b023-0d4576142e1f
+MACOS_APP_PROVISIONING_PROFILE_IDENTIFIER = 5a382464-185f-456c-8e21-da43c920f958
+IOS_NE_PROVISIONING_PROFILE_IDENTIFIER = 49b53dcc-efaf-4171-9f3b-ca8c46e41069
+MACOS_NE_PROVISIONING_PROFILE_IDENTIFIER = b79986e4-4b54-43b3-9634-724e4a98ed64
diff --git a/swift/apple/README.md b/swift/apple/README.md
index f7ea9f7f1..450ec0efe 100644
--- a/swift/apple/README.md
+++ b/swift/apple/README.md
@@ -119,3 +119,87 @@ item is missing. You can remove the keychain item with the following command:
```bash
security delete-generic-password -s "dev.firezone.firezone"
```
+
+## Generating new signing certificates and provisioning profiles
+
+Certs are only good for a year, then you need to generate new ones. Since we use
+GitHub CI, we have to use manually-managed signing and provisioning. Here's how
+you populate the required GitHub secrets.
+
+### Certificates
+
+You first need two certs: The build / signing cert (Apple Distribution) and the
+installer cert (Mac Installer Distribution). You can generate these in the Apple
+Developer portal.
+
+These are the secrets in GH actions:
+
+```
+APPLE_BUILD_CERTIFICATE_BASE64
+APPLE_BUILD_CERTIFICATE_P12_PASSWORD
+APPLE_MAC_INSTALLER_CERTIFICATE_BASE64
+APPLE_MAC_INSTALLER_CERTIFICATE_P12_PASSWORD
+```
+
+How to do it:
+
+1. Go to
+ [Apple Developer](https://developer.apple.com/account/resources/certificates/list)
+1. Click the "+" button to generate a new distribution certificate for App Store
+1. It will ask for a CSR. Open Keychain Access, go to Keychain Access ->
+ Certificate Assistant -> Request a Certificate from a Certificate Authority
+ and follow the prompts. Make sure to select "save to disk" to save the CSR.
+1. Upload the CSR to Apple Developer. Download the resulting certificate.
+ Double-click to install it in Keychain Access.
+1. Right-click the cert in Keychain access. Export the certificate, choose p12
+ file. Make sure to set a password -- this is the
+ `APPLE_BUILD_CERTIFICATE_P12_PASSWORD`.
+1. Convert the p12 file to base64:
+ ```bash
+ cat cert.p12 | base64
+ ```
+1. Save the base64 output as `APPLE_BUILD_CERTIFICATE_BASE64`.
+
+Repeat the steps above but choose "Mac Installer certificate" instead of
+"distribution certificate" in step 2, and save the resulting base64 and password
+as `APPLE_MAC_INSTALLER_CERTIFICATE_BASE64` and
+`APPLE_MAC_INSTALLER_CERTIFICATE_P12_PASSWORD`.
+
+### Provisioning profiles
+
+```
+APPLE_IOS_APP_PROVISIONING_PROFILE
+APPLE_IOS_NE_PROVISIONING_PROFILE
+APPLE_MACOS_APP_PROVISIONING_PROFILE
+APPLE_MACOS_NE_PROVISIONING_PROFILE
+```
+
+1. Go to
+ [Apple Developer](https://developer.apple.com/account/resources/profiles/list)
+1. Click the "+" button to generate a new provisioning profile for App Store
+1. Select the appropriate app ID and distribution certificate you just created.
+ You'll need a provisioning profile for each app and network extension, so 4
+ total (mac app, mac network extension, ios app, ios network extension).
+1. Download the resulting provisioning profiles.
+1. Encode to base64 and save each using the secrets names above:
+
+```bash
+cat profile.mobileprovision | base64
+```
+
+1. Now, you need to update the XCConfig to use these. Edit
+ Firezone/xcconfig/release.xcconfig and update the provisioning profile UUIDs.
+ The UUID can be found by grepping for them in the provisioning profile files
+ themselves, or just opening them in a text editor and looking halfway down
+ the file.
+1. Now, for iOS only, you need to edit Firezone/ExportOptions.plist and update
+ the provisioning profile UUIDs there as well.
+
+### Runner keychain password
+
+This can be randomly generated. It's only used ephemerally to load the secrets
+into the runner's keychain for the build.
+
+```
+APPLE_RUNNER_KEYCHAIN_PASSWORD
+```