{"id":49530907,"url":"https://github.com/smartwatermelon/mac-dev-server-setup","last_synced_at":"2026-05-02T07:33:58.186Z","repository":{"id":351180681,"uuid":"1160392298","full_name":"smartwatermelon/mac-dev-server-setup","owner":"smartwatermelon","description":"Automated setup for Apple Silicon Mac Minis as mobile development build servers","archived":false,"fork":false,"pushed_at":"2026-04-23T03:03:31.000Z","size":1210,"stargazers_count":0,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-23T05:09:19.725Z","etag":null,"topics":["android-sdk","apple-silicon","automation","build-server","devops","mac-mini","macos","mobile-development","shell-script","xcode"],"latest_commit_sha":null,"homepage":"https://projectinsomnia.com","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smartwatermelon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"smartwatermelon","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":"9vzwhcwtzh","thanks_dev":null,"custom":null}},"created_at":"2026-02-17T22:11:10.000Z","updated_at":"2026-04-23T03:03:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/smartwatermelon/mac-dev-server-setup","commit_stats":null,"previous_names":["smartwatermelon/mac-dev-server-setup"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/smartwatermelon/mac-dev-server-setup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwatermelon%2Fmac-dev-server-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwatermelon%2Fmac-dev-server-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwatermelon%2Fmac-dev-server-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwatermelon%2Fmac-dev-server-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smartwatermelon","download_url":"https://codeload.github.com/smartwatermelon/mac-dev-server-setup/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwatermelon%2Fmac-dev-server-setup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32527138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"online","status_checked_at":"2026-05-02T02:00:05.923Z","response_time":132,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-sdk","apple-silicon","automation","build-server","devops","mac-mini","macos","mobile-development","shell-script","xcode"],"created_at":"2026-05-02T07:33:57.343Z","updated_at":"2026-05-02T07:33:58.177Z","avatar_url":"https://github.com/smartwatermelon.png","language":"Shell","funding_links":["https://ko-fi.com/smartwatermelon","https://buymeacoffee.com/9vzwhcwtzh"],"categories":[],"sub_categories":[],"readme":"# Mac Dev Server Setup\n\nAutomated setup for an Apple Silicon Mac Mini as a mobile development build server. Xcode, Android SDK, Node.js, dotfiles -- the whole toolchain.\n\n\u003e Forked from [mac-server-setup](https://github.com/smartwatermelon/mac-server-setup), stripped of media server components, refocused on developer tooling. See [SPEC.md](SPEC.md) for full roadmap.\n\n## TL;DR\n\n**What this does**: Takes a fresh Mac Mini and turns it into a development build server with Xcode tooling, Android SDK, Node.js, and your dotfiles.\n\n**Prerequisites** (5 minutes):\n\n1. Install 1Password CLI: `brew install 1password-cli \u0026\u0026 op signin`\n2. Generate SSH keys: `ssh-keygen -t ed25519`\n3. Copy `config/config.conf.template` to `config/config.conf` and set your `SERVER_NAME`\n4. Create these 1Password items: \"TimeMachine\", \"Apple\"\n\n**Setup** (15-30 minutes):\n\n1. **On dev Mac**: `./prep-airdrop.sh` (builds deployment package)\n2. **AirDrop** the generated folder to your Mac Mini\n3. **On Mac Mini desktop** (not SSH): `cd ~/Downloads/macmini-setup \u0026\u0026 ./first-boot.sh`\n4. **On Mac Mini**: `cd ~/app-setup \u0026\u0026 ./run-app-setup.sh` (installs dev tools)\n\n**Post-setup** (manual):\n\n1. `claude auth login` (enables cloud-synced MCPs: Sentry, Gmail, Calendar)\n2. `gh auth login` (enables `/post-push-loop` CI monitoring)\n\n**Result**: Dev server at `your-server-name.local`, ready for builds.\n\nMore detail in [Prerequisites](docs/prerequisites.md) and [Environment Variables](docs/environment-variables.md).\n\n## How it works\n\nThree phases, two machines.\n\n**Phase 1** (`prep-airdrop.sh`, on your dev Mac): Pulls credentials from 1Password, creates a hardware-locked keychain, copies SSH keys and configs, packages it all into a folder.\n\n**Phase 2** (`first-boot.sh`, on the Mac Mini): Validates the hardware fingerprint, imports the keychain, runs 15+ setup modules (SSH, Homebrew, FileVault, Time Machine, etc). Has to be run from the local desktop, not SSH.\n\n**Phase 3** (`run-app-setup.sh`, on the Mac Mini): Discovers and runs\nall `*-setup.sh` scripts in dependency order -- Xcode, Node.js,\nAndroid SDK, dotfiles, Claude Code (CLI + plugins + MCPs), and storage.\n\n### Configuration flow\n\nOne config file runs the show:\n\n```text\nconfig/config.conf\n  ├── prep-airdrop.sh reads it     (Phase 1)\n  ├── first-boot.sh sources it     (Phase 2)\n  └── run-app-setup.sh sources it  (Phase 3)\n```\n\nKey variables: `SERVER_NAME`, `ONEPASSWORD_VAULT`, `DOTFILES_REPO`, `ANDROID_SDK_VERSION`, `NODE_VERSION`.\n\n### Credentials\n\nNo plaintext secrets in the deployment package:\n\n```text\n1Password (dev Mac)\n  -\u003e prep-airdrop.sh retrieves via `op` CLI\n  -\u003e Stored in external keychain (password = hardware UUID)\n  -\u003e AirDropped as .keychain-db file\n\nfirst-boot.sh (Mac Mini)\n  -\u003e Imports external keychain\n  -\u003e Extracts credentials to system/login keychain\n  -\u003e Scripts read via `security find-generic-password`\n```\n\n1Password is dev-machine only. The server never needs it.\n\n## Current status\n\nAll implementation phases are complete. The project is ready to deploy on a fresh Mac Mini.\n\nSee [SPEC.md](SPEC.md) for the original roadmap.\n\n## Prerequisites\n\n- Apple Silicon Mac Mini with a fresh macOS install\n- Development Mac with:\n  - 1Password CLI (`brew install 1password-cli \u0026\u0026 op signin`)\n  - SSH keys (`~/.ssh/id_ed25519` and `~/.ssh/id_ed25519.pub`)\n  - 1Password vault items: TimeMachine, Apple ID\n  - `jq` and `openssl` (both pre-installed on macOS)\n  - `config/config.conf` created from the template\n\nSee [Prerequisites Guide](docs/prerequisites.md) for validation commands.\n\n\u003e Tested on macOS 15.x, Apple Silicon only. Might work on Intel or older macOS but I haven't tried.\n\n## Setup\n\n1. **Build the deployment package** on your dev Mac:\n\n   ```bash\n   ./prep-airdrop.sh\n   ```\n\n   Pulls credentials from 1Password, builds a hardware-locked keychain, processes config, generates a deployment manifest.\n\n2. **AirDrop the folder** to your Mac Mini.\n\n   \u003e [airdrop-cli](https://github.com/vldmrkl/airdrop-cli) lets you do this from the terminal:\n   \u003e `brew install --HEAD vldmrkl/formulae/airdrop-cli`\n\n3. **Run first-boot** on the Mac Mini (local desktop session, not SSH):\n\n   ```bash\n   cd ~/Downloads/macmini-setup  # default name\n   ./first-boot.sh\n   ```\n\n   \u003e This needs the local desktop for System Settings dialogs and FileVault management. It will not work over SSH.\n\n4. **Run app-setup** on the Mac Mini (new Terminal window opens automatically after first-boot):\n\n   ```bash\n   cd ~/app-setup\n   ./run-app-setup.sh\n   ```\n\n   This installs Xcode (via App Store), configures Node.js globals, sets up the Android SDK, and clones your dotfiles. Scripts run in dependency order and can be re-run safely.\n\n## File structure\n\n```plaintext\n.\n├── prep-airdrop.sh                # Entry point: builds deployment package\n├── app-setup/                     # Application setup scripts\n│   ├── run-app-setup.sh          # Orchestrator (runs scripts in dependency order)\n│   ├── xcode-setup.sh            # Xcode via mas, license, simulators\n│   ├── node-setup.sh             # npm global config, eas-cli\n│   ├── android-setup.sh          # SDK components, licenses, ANDROID_HOME\n│   ├── dotfiles-setup.sh         # Clone repo, run install script\n│   ├── claude-setup.sh           # CLI, plugins, MCP servers, post-push-loop\n│   └── storage-setup.sh          # External storage configuration\n├── scripts/\n│   └── server/\n│       ├── first-boot.sh          # Main provisioning script (15+ modules)\n│       ├── setup-apple-id.sh\n│       ├── setup-application-preparation.sh\n│       ├── setup-auto-updates.sh\n│       ├── setup-bash-configuration.sh\n│       ├── setup-command-line-tools.sh\n│       ├── setup-dock-configuration.sh\n│       ├── setup-firewall.sh\n│       ├── setup-hostname-volume.sh\n│       ├── setup-log-rotation.sh\n│       ├── setup-package-installation.sh\n│       ├── setup-power-management.sh\n│       ├── setup-remote-desktop.sh\n│       ├── setup-shell-configuration.sh\n│       ├── setup-ssh-access.sh\n│       ├── setup-system-preferences.sh\n│       ├── setup-terminal-profiles.sh\n│       ├── setup-timemachine.sh\n│       ├── setup-touchid-sudo.sh\n│       └── setup-wifi-network.sh\n├── config/\n│   ├── config.conf.template      # Configuration template\n│   ├── formulae.txt              # Homebrew CLI packages\n│   ├── casks.txt                 # Homebrew GUI applications\n│   └── logrotate.conf            # Log rotation rules\n└── docs/\n    ├── prerequisites.md\n    ├── environment-variables.md\n    ├── configuration.md\n    ├── keychain-credential-management.md\n    └── setup/\n        ├── prep-airdrop.md\n        ├── first-boot.md\n        ├── firstboot-README.md\n        └── apple-first-boot-dialogs.md\n```\n\n## Design choices\n\nEvery script is idempotent (safe to re-run). Errors display immediately during setup and again in a summary at the end, so nothing gets buried in scroll.\n\n## Security\n\nSSH is key-only (password login disabled). The admin account gets TouchID sudo. Firewall is on with an SSH allowlist. Credentials travel in a hardware-locked keychain, not plaintext. The setup script checks the hardware fingerprint and refuses to run on the wrong machine. The Mac restarts automatically after power failure.\n\n## Error handling\n\nErrors show up immediately during setup and again in a summary at the end:\n\n```bash\n====== SETUP SUMMARY ======\nSetup completed, but 1 error and 2 warnings occurred:\n\nERRORS:\n  x Installing Homebrew Packages: Formula installation failed: some-package\n\nWARNINGS:\n  ! Copying SSH Keys: SSH private key not found at ~/.ssh/id_ed25519\n  ! WiFi Network Configuration: Could not detect current WiFi network\n\nReview the full log for details: ~/.local/state/macmini-setup.log\n```\n\nErrors block setup. Warnings are optional stuff that wasn't available. Each message tags which setup section it came from.\n\n## Logs\n\n| Script             | Log location                              |\n| ------------------ | ----------------------------------------- |\n| `prep-airdrop.sh`  | Console output only                       |\n| `first-boot.sh`    | `~/.local/state/\u003chostname\u003e-setup.log`     |\n| App setup scripts  | `~/.local/state/\u003chostname\u003e-app-setup.log` |\n\n## Troubleshooting\n\n**\"GUI session required\"**: You're running over SSH. `first-boot.sh` needs the local desktop. Check: `launchctl managername` should say `Aqua`, not `Background`.\n\n**SSH access denied**: SSH keys didn't make it into the deployment package, or SSH isn't enabled on the target.\n\n**Homebrew not found**: Restart Terminal or `source ~/.bash_profile`.\n\n**1Password items not found**: Vault name and item titles in `config.conf` have to match exactly.\n\n## Docs\n\n| Topic | Link |\n| --- | --- |\n| What you need before starting | [Prerequisites](docs/prerequisites.md) |\n| Configuration options | [Environment Variables](docs/environment-variables.md) |\n| Customizing parameters | [Configuration Reference](docs/configuration.md) |\n| Building the deployment package | [Prep-AirDrop](docs/setup/prep-airdrop.md) |\n| Running system provisioning | [First Boot](docs/setup/first-boot.md) |\n| How credentials move between machines | [Keychain Management](docs/keychain-credential-management.md) |\n| Full project roadmap | [SPEC](SPEC.md) |\n\n## Contributing\n\nScripts must be idempotent (re-runnable without breaking things). Use `log()`/`show_log()` for output. Use `collect_error()` for blockers, `collect_warning()` for optional stuff, `set_section()` so errors have context. Update docs when you change config. `shellcheck` must pass clean, no exceptions.\n\n## License\n\nMIT; see [LICENSE](license.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartwatermelon%2Fmac-dev-server-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartwatermelon%2Fmac-dev-server-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartwatermelon%2Fmac-dev-server-setup/lists"}