Thanks for helping with OpenHat Max Privacy. This file is how to work on the repo. GitHub’s community profile and Bootstrap’s contributing guide are the layout we followed.
By opening a pull request you agree to license your contribution under the MIT License.
A Safari installer and .mobileconfig profiles that harden a personal iPhone without MDM, a custom root CA, or a jailbreak. The default path on main must stay that way.
| Version | |
|---|---|
| Current public iOS we build against | iOS 26.6 |
| Full restriction set (Apple Intelligence keys) | iOS 18.2 and later |
| Safari website block list extra | iOS 16 and later |
| Encrypted DNS payload | iOS 14 and later |
| iOS 27 developer / public beta | Not supported until Apple ships it |
Unknown restriction keys are ignored on older iOS. Do not drop iOS 18.2+ keys to “support” older phones; those phones already skip them.
All Python in this repo — build_profile.py and mdm/*.py — must stay on the Python 3 standard library. No requirements.txt, no pip install, no new third-party imports.
This is a security rule, not a style preference. A privacy installer should not ask anyone to pull packages from PyPI. If a change needs a library that is not in stdlib, it does not belong here. Use json, plistlib, uuid, pathlib, urllib.request, and the rest of the stdlib.
The optional MDM server is Docker (NanoMDM / SCEP / Caddy). That is separate from our Python. Do not wrap those daemons in a pip package.
You need Python 3.9+ (stdlib only).
python3 build_profile.py
echo "iPhone Safari: http://$(ipconfig getifaddr en0):8080/" && python3 -m http.server 8080 --directory srcOpen the printed LAN URL in Safari on an iPhone. Chrome and desktop Safari will not install a configuration profile the same way. Public host is GitHub Pages.
| Path | What it is |
|---|---|
src/ |
GitHub Pages site. Published as the site root, so URLs stay /, /paper.html, /wipe.html, /mdm.html, /profiles/… |
data/ |
Schema-stable JSON: Apple settings, leftovers, DNS, deny list, apps |
build_profile.py |
Writes src/profiles/*.mobileconfig from data/ |
mdm/ |
Self-hosted MDM server (Level 4.1; not Lockdown Mode) |
logos/ |
Brand marks |
Local preview must serve src/, not the repo root.
| Change | Edit this | Then |
|---|---|---|
| Apple restriction key | data/settings.json |
python3 build_profile.py |
| Leftover Settings taps | data/leftovers.json |
no rebuild (docs only) |
| DNS providers | data/dns.json |
rebuild |
| Safari deny list | data/safari-denylist.json |
rebuild |
| Tracker apps | data/tracker-apps.json |
rebuild |
| Installer UI | src/index.html, src/css/, src/js/ |
refresh Safari |
| Lockdown Mode (Level 3) | src/lockdown.html |
no rebuild |
| Supervised (erase) path | src/wipe.html, src/configurator.html, Level 4 files in src/profiles/ |
Level 4.2 still erases the iPhone |
Do not hand-edit src/profiles/*.mobileconfig. Those are generated from data/settings.json and the other data/*.json lists. Each file has a schema in data/schema/.
These are Apple’s rules, not missing payloads:
- No custom root CA / HTTPS interception
- No MDM enrollment on
main - No jailbreak
- No PyPI / pip dependencies in any Python we ship
- Do not set
allowCloudPhotoLibrary=false(can delete undownloaded photos) - Do not set
allowFindMyDevice=falseon the default profile - Do not force-disable iMessage or Face ID on the default profile
blockedAppBundleIDsonly works after Apple Configurator Prepare (erases the phone) — that is Level 4.2 insrc/profiles/
If a setting cannot be flipped by a profile, add it to the catalog as via: "manual" (or skipped / app). Do not invent a restriction key.
- Open an issue first for anything that changes payload keys or the keep-vs-erase story.
- Keep
mainfree of MDM enrollment payloads. Supervised / erase work belongs onwipe.html/ Level 4.2 profiles. Lockdown Mode islockdown.html(Level 3). - Rebuild generated files in the same commit as the catalog or data change.
- Say how you tested: iOS version, Safari install, and whether extras (PIN / Safari list) were on.
- Do not add pip packages. New
imports must be from the Python standard library.
Use the pull request template. Be kind; we follow the Code of Conduct.
Do not file a public issue for a vulnerability. See SECURITY.md.