IHASMAIL_IMMUTABLE defaulted to 0, and .env.production doesn't set it either. So a plain ./deploy.sh origin/main --yes handed back a writable container with a /data volume mounted — quietly, and then reported healthy.
Nothing in the deploy output said the immutability had gone. docker inspect was the only place it showed, and only if you thought to look:
ReadonlyRootfs=false Mounts=1
That is the wrong way round for the posture the project leads with. The safe one is now the default, and giving it up is the half that has to be deliberate:
IHASMAIL_IMMUTABLE=0 ./ihasmail-deploy.sh --yes
Found by deploying prod today. The running container had IMMUTABLE=1 and a read-only root, and reproducing that state took passing the variable by hand — because the script's own default would have taken it away.
No behaviour change for anyone already passing IHASMAIL_IMMUTABLE=1, and the named volume is still never touched either way, so an instance that opts back out finds whatever was in it.
One line of code; the rest is the comment explaining which way round the two options should sit and why.
`IHASMAIL_IMMUTABLE` defaulted to `0`, and `.env.production` doesn't set it either. So a plain `./deploy.sh origin/main --yes` handed back a **writable container with a `/data` volume mounted** — quietly, and then reported healthy.
Nothing in the deploy output said the immutability had gone. `docker inspect` was the only place it showed, and only if you thought to look:
```
ReadonlyRootfs=false Mounts=1
```
That is the wrong way round for the posture the project leads with. The safe one is now the default, and giving it up is the half that has to be deliberate:
```
IHASMAIL_IMMUTABLE=0 ./ihasmail-deploy.sh --yes
```
Found by deploying prod today. The running container had `IMMUTABLE=1` and a read-only root, and reproducing that state took passing the variable by hand — because the script's own default would have taken it away.
No behaviour change for anyone already passing `IHASMAIL_IMMUTABLE=1`, and the named volume is still never touched either way, so an instance that opts back out finds whatever was in it.
One line of code; the rest is the comment explaining which way round the two options should sit and why.
**Merged** 2026-08-30 as coffey-labs/ihasmail@0fb504748d29
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
IHASMAIL_IMMUTABLEdefaulted to0, and.env.productiondoesn't set it either. So a plain./deploy.sh origin/main --yeshanded back a writable container with a/datavolume mounted — quietly, and then reported healthy.Nothing in the deploy output said the immutability had gone.
docker inspectwas the only place it showed, and only if you thought to look:That is the wrong way round for the posture the project leads with. The safe one is now the default, and giving it up is the half that has to be deliberate:
Found by deploying prod today. The running container had
IMMUTABLE=1and a read-only root, and reproducing that state took passing the variable by hand — because the script's own default would have taken it away.No behaviour change for anyone already passing
IHASMAIL_IMMUTABLE=1, and the named volume is still never touched either way, so an instance that opts back out finds whatever was in it.One line of code; the rest is the comment explaining which way round the two options should sit and why.
Merged 2026-08-30 as coffey-labs/ihasmail@0fb504748d
Rebuilt from: git history, session transcript.