
Local Development Environment on Mac (2026)
Set up a perfect local dev environment on macOS. MAMP vs Laravel Valet vs Docker comparison, .test domains, local HTTPS with mkcert. Complete checklist.
Manage hosts files without the terminal
ToggleHosts helps you manage environments visually on Windows, macOS, and Linux, with automatic DNS flush and backups.
One-time payment
A well-configured local development environment is the foundation of a productive workflow. On Mac, several options are available depending on your needs. This guide covers everything you need to create a modern and efficient setup in 2026.
How to set up a local development environment on Mac
A modern Mac local dev setup combines a package manager (Homebrew), a runtime version manager (nvm, pyenv, rbenv), a local web server or Docker, custom .test domains via the hosts file, and local HTTPS with mkcert. The sections below walk through each piece step by step.
Components of a modern local environment
A complete development environment includes:
- Web server (Apache, Nginx)
- Runtime/language (PHP, Node.js, Python)
- Database (MySQL, PostgreSQL, SQLite)
- Local domain manager (hosts file, dnsmasq)
- SSL certificates (for local HTTPS)
- Productivity tools (Terminal, editor)
MAMP: the beginner-friendly solution
MAMP (Mac, Apache, MySQL, PHP) is the simplest all-in-one solution.
Strengths
- 2-minute setup
- Complete GUI
- Built-in phpMyAdmin
- Ideal for WordPress
Weaknesses
- Average performance
- Limited free version
- No virtualization
Configuring local domains with MAMP
By default, MAMP uses localhost:8888. For custom domains, edit the hosts file:
127.0.0.1 myproject.testLaravel Valet: maximum performance
Valet is a minimalist and ultra-fast solution for PHP on Mac.
Strengths
- Ultra-fast (Nginx + PHP-FPM)
- Minimal configuration
- Automatic .test domains
- HTTPS in one command
Weaknesses
- PHP only
- No containerization
Valet configuration
# Install Valet
composer global require laravel/valet
valet install
# Park a projects folder
cd ~/Sites
valet park
# Secure with HTTPS
cd ~/Sites/my-project
valet secureDocker: maximum flexibility
Docker lets you create isolated and reproducible environments.
Strengths
- Isolated environments
- Reproducible (same config for whole team)
- Maximum flexibility
- Close to production
Weaknesses
- Learning curve
- Resource consumption
Example docker-compose.yml
version: '3.8'
services:
web:
image: php:8.3-apache
ports:
- "80:80"
volumes:
- ./src:/var/www/html
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myappWhich stack should you choose?
The best local environment depends on the kind of work you do every day.
WordPress or classic PHP sites
Choose MAMP, Laravel Herd or Valet. You get fast setup, simple database management and predictable local domains. MAMP is friendlier for beginners, while Valet and Herd feel faster for developers who live in the terminal.
Recommended setup:
- MAMP or Herd for the web server.
- TablePlus for database inspection.
- ToggleHosts for hosts file domains.
- mkcert for HTTPS.
Laravel or Symfony apps
Choose Valet if you work alone on mostly PHP apps. It is fast, light and excellent with .test domains. Choose Docker if the app has Redis, queues, workers, custom services or strict production parity needs.
Recommended setup:
- Valet for simple PHP projects.
- Docker Compose for multi-service apps.
- ToggleHosts groups for dev/staging/prod domains.
- mkcert for OAuth and secure-cookie testing.
Node.js, Next.js or API projects
Use Node version management plus either native dev servers or Docker. Many Next.js projects only need npm run dev, but custom hostnames and HTTPS matter when testing auth callbacks, cookies, webhooks or service workers.
Recommended setup:
fnmornvmfor Node versions..testdomains mapped in hosts.- mkcert certificates for local HTTPS.
- Chrome DNS cache workflow for stale hostnames.
Read how to clear Chrome DNS cache on Mac if Chrome ignores a new local mapping.
Team environments
Use Docker or documented setup scripts. The goal is not only to make your Mac work, but to make every teammate's Mac behave the same way.
Recommended setup:
- Docker Compose for shared services.
- A committed
.env.example. - A README setup checklist.
- Shared hosts profiles exported from ToggleHosts.
- A common
.testnaming convention.
Naming local domains
Good domain names make local development easier to reason about.
Use patterns like:
app.client.test
api.client.test
admin.client.test
webhook.client.testAvoid patterns that collide with production:
client.com.local
dev.client.com
client.local.local can be slow on macOS because Bonjour/mDNS uses it. .dev is a real public TLD and browsers force HTTPS. .test is the safest default for development.
HTTPS and browser APIs
Local HTTPS is no longer optional for many modern features:
- Service Workers and PWAs.
- Secure cookies.
- OAuth redirect testing.
- WebAuthn and passkeys.
- Geolocation prompts.
- Clipboard API.
- Webhooks that validate HTTPS callbacks.
If HTTPS fails with mkcert, check hostname coverage first. A certificate for localhost does not cover api.myproject.test.
Sources and further reading
Managing local domains
The hosts file
For a detailed understanding of the hosts file, check our complete guide to the hosts file.
# /etc/hosts
127.0.0.1 localhost
# Projects
127.0.0.1 blog.test
127.0.0.1 api.blog.test
# Client A
127.0.0.1 clienta.testRecommended TLDs
| TLD | Recommended | Notes |
|---|---|---|
| .test | Yes | IETF reserved |
| .localhost | Yes | Always local |
| .local | No | Bonjour conflict on Mac |
| .dev | No | Real domain, HTTPS required |
Automation with dnsmasq
To avoid editing the hosts file for each project:
# Install dnsmasq
brew install dnsmasq
# Redirect all .test to localhost
echo "address=/.test/127.0.0.1" >> /usr/local/etc/dnsmasq.conf
# Create a resolver
sudo mkdir -p /etc/resolver
echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/test
# Start dnsmasq
sudo brew services start dnsmasqNow, any .test domain points to localhost!
Local HTTPS with mkcert
Why HTTPS locally?
- Test Service Workers, Geolocation API
- Secure cookies (SameSite, Secure)
- Avoid dev/prod differences
- OAuth and redirects
Creating certificates
brew install mkcert
mkcert -install # Install root CA
# Create a certificate
mkcert myproject.test "*.myproject.test" localhostEssential productivity tools
Terminal
brew install --cask iterm2Oh My Zsh
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"Node version management
brew install fnm
fnm install 20Database client
brew install --cask tableplusProject organization
Recommended structure
~/Sites/
├── clients/
│ ├── client-a/
│ └── client-b/
├── personal/
│ ├── blog/
│ └── portfolio/
└── experiments/Well-organized hosts file
# ===================
# LOCALHOST
# ===================
127.0.0.1 localhost
::1 localhost
# ===================
# PERSONAL PROJECTS
# ===================
127.0.0.1 blog.test
127.0.0.1 portfolio.test
# ===================
# CLIENT: Acme Corp
# ===================
127.0.0.1 acme.test
127.0.0.1 api.acme.testWith ToggleHosts
The ToggleHosts app simplifies this management:
- Import/export configurations
- Quick environment switching
- Instant search
- Modification history
Configuration checklist
First-time setup
- [ ] Install Homebrew
- [ ] Install Git
- [ ] Configure SSH for GitHub
- [ ] Install local server (MAMP/Valet/Docker)
- [ ] Configure hosts file or dnsmasq
- [ ] Install mkcert for HTTPS
- [ ] Install version managers
- [ ] Configure terminal (iTerm2 + Oh My Zsh)
New project
- [ ] Create folder in ~/Sites
- [ ] Add hosts entry
- [ ] Create SSL certificates if needed
- [ ] Configure database
- [ ] Test access via local domain
Troubleshooting checklist
When a local site fails, isolate the layer:
Domain layer
dscacheutil -q host -a name myproject.test
ping myproject.test
cat /etc/hostsIf the IP is wrong, fix the hosts file and flush DNS.
Server layer
lsof -i :3000
curl -I http://127.0.0.1:3000
curl -I http://myproject.test:3000If direct IP works but the domain fails, it is a DNS or hosts issue. If both fail, the server is not listening where you think it is.
Browser layer
Chrome can cache DNS separately. Clear chrome://net-internals/#dns and socket pools when a hostname keeps opening the old project.
Certificate layer
Check that the certificate includes the exact hostname and wildcard you use:
mkcert myproject.test "*.myproject.test"For deeper troubleshooting, use the localhost not working guide.
Conclusion
A well-configured local development environment will save you hours each week. Whether you choose MAMP for its simplicity, Valet for its performance, or Docker for its flexibility, the principles remain the same:
- Clear local domains: .test to avoid conflicts
- Systematic HTTPS: mkcert makes it trivial
- Rigorous organization: commented hosts file or tool like ToggleHosts
- Automation: dnsmasq, scripts, aliases
With these solid foundations, you can focus on what matters: writing code.
Frequently Asked Questions
MAMP for beginners and WordPress. Laravel Valet for PHP/Laravel with max performance. Docker for reproducible multi-service environments.
.test is recommended as it's reserved by IETF. Avoid .local on Mac (Bonjour conflict) and .dev (real domain requiring HTTPS).
Use mkcert to create trusted local SSL certificates. Free, simple via Homebrew, works with all servers.
Use version managers: phpenv or Homebrew for PHP, nvm or fnm for Node.js. Docker also allows different versions per project.
macOS uses Bonjour/mDNS for .local, creating delays. Use .test or .localhost, or add the entry in both IPv4 AND IPv6.
Related Articles
Using Hosts Files for Docker Development on MacLocal development
Using Hosts Files for Docker Development on Mac
9 min read
How to Flush DNS Cache on Windows, macOS & Linux (2026)Flushing DNS & cache
How to Flush DNS Cache on Windows, macOS & Linux (2026)
8 min read
How to Sync WSL2 with Windows Hosts File for Local Domains (2026)Local development
How to Sync WSL2 with Windows Hosts File for Local Domains (2026)
5 min read