Appearance
dqx next to Herd, Valet or Sail
dqx can run beside the other Laravel tools on your machine. What it takes depends on how each one listens:
| Tool | Listens on | Beside dqx |
|---|---|---|
| Herd, Valet | 127.0.0.1:80/443 | yes, with dqx loopback - both keep ports 80 and 443 |
| Laravel Sail | APP_PORT, 80 by default, on every address | yes, once its APP_PORT moves |
| DDEV, lerd | 80/443 on every address | not at the same time: dqx up stops them |
| MAMP, XAMPP, WAMP, a system Apache or nginx | 80/443 on every address | not at the same time: dqx up stops them, or names the command when it needs your password |
Herd and Valet: dqx loopback
Herd and Valet cannot leave 127.0.0.1, so dqx moves: its router listens on 127.0.0.2, and both keep 80 and 443 with no port in any URL.
bash
dqx loopback 127.0.0.2The first time, 127.0.0.2 does not exist yet - macOS has only 127.0.0.1 - so dqx installs a small LaunchDaemon that adds the address now and at every boot. That needs root once, and dqx asks for your password rather than handing you commands to copy. Then it moves everything else:
text
127.0.0.2 is not on lo0 yet. macOS starts with only 127.0.0.1 there and forgets any other
address at reboot, so dqx adds a LaunchDaemon that puts 127.0.0.2 back at every boot.
Writing to /Library/LaunchDaemons and loading it needs root, once.
Ctrl-C at the password prompt stops without changing anything.
Password for you, to add 127.0.0.2 to lo0:
→ 127.0.0.2 on lo0, now and after every reboot
→ routerBindAddress = 127.0.0.2
→ .test handed to Herd on 127.0.0.1 (alsoResolve)
→ router on 127.0.0.2
These are on .test, which now reaches Herd. Move each with:
cd ~/dockers/shop && dqx domains --to dqx --writeWhat that did:
- The router listens on
127.0.0.2only. - dqx's resolver answers dqx's own suffixes -
.dqx,local.dolphiq.eu- with127.0.0.2, and hands.testto Herd or Valet on127.0.0.1. Nothing in/etc/resolver/testchanges. dqx upno longer sees Herd as in the way: it checks the ports on dqx's own address, where Herd is not listening.
Measured on one machine with Herd 1.30, both at once:
text
https://nx7.dqx/ served by dqx on nx7.dqx [200 via 127.0.0.2]
https://nx7.internal/ served by dqx on nx7.internal [200 via 127.0.0.2]
http://nx7herd.test/ served by Herd, PHP 8.4.23 [200 via 127.0.0.1]bash
dqx loopback # what is set, the address, the reboot, and each suffix's resolver file
dqx loopback 127.0.0.2 --dry-run
dqx loopback 127.0.0.2 --force # move even though a suffix is not ready - see below
dqx loopback reset # back to 127.0.0.1; removes the address too, with your password
dqx loopback reset --keep-aliasdqx doctor checks it while it is set: the address missing (every dqx site unreachable), nothing to add it at boot, and a suffix without its resolver file.
Every suffix needs its resolver file first
Once dqx has moved, a suffix only reaches it through dqx's own resolver, and macOS only asks that resolver when /etc/resolver/<suffix> says nameserver 127.0.0.1 and port 5354. Without the file local.dolphiq.eu still resolves - through public DNS, to 127.0.0.1 - which is Herd's or Valet's address now, so its sites quietly land on the wrong tool. .dqx resolves nowhere at all.
So dqx loopback 127.0.0.2 checks every suffix dqx serves before it changes anything: the file, and whether dqx's resolver answers on 127.0.0.1:5354. If one is not ready, it refuses and exits non-zero:
text
✗ Not moving to 127.0.0.2: a suffix dqx serves would stop reaching it.
.local.dolphiq.eu /etc/resolver/local.dolphiq.eu is missing: public DNS answers 127.0.0.1 - Herd's or Valet's address - so its sites would stop reaching dqx
fix: dqx resolver install
Nothing was changed. Fix these, then `dqx loopback 127.0.0.2` again, or add --force to move anyway.dqx resolver install writes the missing files itself, in one sudo: you only type your password. Without a terminal it prints the lines to run instead. When the file is there but nothing answers, the fix is dqx repair, which reloads dqx's resolver agent. --dry-run shows the same refusal. --force moves anyway and prints the same reasons as a warning. dqx loopback reset is never refused: 127.0.0.1 is what public DNS answers anyway.
dqx loopback on its own lists each suffix too, with the same reason and fix when one is not ready.
After the move
When the router is on its new address, dqx asks the system resolver - the way a browser asks - for a name under each suffix, and says whether it answers the new address:
text
Each suffix, asked the way a browser asks:
✓ .dqx answers 127.0.0.2
! .local.dolphiq.eu answers 127.0.0.1, not 127.0.0.2
! Not every suffix answers 127.0.0.2 yet. macOS may still be answering from its cache - flush it:
sudo killall -HUP mDNSResponder
then `dqx loopback` shows where each suffix stands.That is a warning only; the move stays.
Projects on .test
.test is Herd's and Valet's. A dqx project on .test reaches them once dqx has moved, and dqx doctor says so wherever Herd or Valet is installed. Move it:
bash
dqx domains --to dqx # what would change
dqx domains --to dqx --write # the config, the www/ directories, each site's .env
dqx sync && dqx upHerd serves what is parked
herd parked lists the directories whose every folder is a Herd site. If your dqx projects are under one of them - ~/dockers, say - Herd serves each folder as <folder>.test too. herd forget ~/dockers stops that.
Laravel Sail
Sail is docker compose publishing ${APP_PORT:-80} on every address, so on the default port it is in the way and dqx up stops it - and says it was Sail. To keep both running, give Sail another port or an address of its own, in that project's .env:
bash
APP_PORT=8080 # Sail at http://localhost:8080
APP_PORT=127.0.0.3:80 # Sail on its own address, after `sudo ifconfig lo0 alias 127.0.0.3 up`dqx needs no change for that: it listens on 127.0.0.1 by default, and a Sail on 8080 or on 127.0.0.3 is not in its way.
Suffixes
A new project gets .dqx. On a Dolphiq machine local.dolphiq.eu is served as well - dqx knows from repositoryBase, which you never had to set - and a project whose config states no suffix keeps local.dolphiq.eu. .test is not served unless a project states it or you add it.
bash
dqx suffix # what is served here, and what new projects get
dqx suffix add internal # serve .internal too
dqx suffix default internal # new projects get .internal
dqx suffix remove internalEvery served suffix is answered by dqx's own resolver, on this machine: local.dolphiq.eu works without an internet connection. The installer sets that up (dqx resolver install, one password).
| Suffix | Can it ever be a real domain? | Notes |
|---|---|---|
.dqx | not today; a future new-TLD round could create it | short, and dqx's |
.internal | never: ICANN reserved it for private use in 2024 | the safest choice; long |
local.dolphiq.eu | no - it is Dolphiq's own domain | its public DNS answers 127.0.0.1, so offline and beside Herd it needs the local resolver |
.test | never (RFC 6761) | Herd's and Valet's |
.dev, .app | they are real, HSTS-preloaded TLDs | don't: names resolve on the internet and HTTPS is forced |
.local | reserved for mDNS | don't: slow, and clashes with Bonjour |
A browser may not recognise .dqx or .internal as a URL when you type it bare, and search instead. Type it once with https://, and the history takes it from there.
The default address
dqx's router listens on 127.0.0.1: this machine only. Earlier releases listened on every address, which also put 80, 443 and every site behind them on your Wi-Fi and LAN. To have that back:
bash
dqx config machine routerBindAddress 0.0.0.0
dqx router:upAn old, pre-router stack whose extra_hosts send a sibling's domain to host-gateway cannot reach a router on 127.0.0.1; dqx doctor names it, and dqx sync moves it onto the router's network.