Update
An update replaces the code (jars, launchers, lib/defaults.cf, service units) and keeps everything host-local. Everything host-local lives in /opt/msh-zr/etc/, so the update unpacks the new package with etc/ excluded.
File in etc/ | On which host (on a single server, all of them) | Holds |
|---|---|---|
config.cf | Every host | Your configuration overrides |
msh-zr-web.db | Web admin server | Servers, users of the web admin, directory service settings |
msh-zr-master.db | Web admin server | Rules, templates and all other settings, the source the servers get their copy from |
msh-zr-node.db | Every MTA server | The node's copy of the rules and settings, read by the milter |
msh-zr-milter.db | Every MTA server | Message history and message counts |
node.token, node.p12, node.p12.password | Every MTA server | The node's access token and HTTPS certificate |
license.id, license.key | Every host | The license, sent to the servers by the web admin |
keystore.p12 | Web admin server | The web admin's HTTPS certificate, if you enabled HTTPS |
The scripts/ directory is kept as well: the update replaces only the shipped samples accept.sh, reject.sh and README.txt. Stored attachments in var/attachments/ are kept.
Keep the files in etc/, in particular node.token and node.p12 on the MTA servers. If they are lost, the node creates a new token and certificate, and the web admin no longer accepts the server until you remove it and add it again on the Servers page.
Update order
Update the MTA servers first and the web admin last, so the web admin never sends rules and settings to a server that is older than itself.
- Single server: update the one host, all three services at once.
- Multiple servers: update every MTA server (node and milter), one at a time. Then update the web admin server.
While a server is older than the web admin, the Servers page shows it as Version mismatch. It keeps filtering mail with the rules and settings it received before, and gets the current ones as soon as it is updated.
Back up first
Copy the etc/ directory of each host before you update it, for example:
sudo cp -a /opt/msh-zr/etc /opt/msh-zr/etc.backup-$(date +%F)
On the web admin server, also export a backup on the Backup & Restore page.
Commands
Single server (web admin, node and milter)
sudo systemctl stop msh-zr-web.service msh-zr-node.service msh-zr-milter.service
sudo tar zxvf msh-zr-<VERSION>.tgz -C /opt --exclude='msh-zr/etc/*'
sudo sh /opt/msh-zr/lib/fixperms.sh
sudo systemctl daemon-reload
sudo systemctl start msh-zr-node.service msh-zr-milter.service msh-zr-web.service
MTA server (node and milter)
sudo systemctl stop msh-zr-node.service msh-zr-milter.service
sudo tar zxvf msh-zr-<VERSION>.tgz -C /opt --exclude='msh-zr/etc/*'
sudo sh /opt/msh-zr/lib/fixperms.sh
sudo systemctl daemon-reload
sudo systemctl start msh-zr-node.service msh-zr-milter.service
Web admin server (web admin)
Update it after every MTA server runs the new version.
sudo systemctl stop msh-zr-web.service
sudo tar zxvf msh-zr-<VERSION>.tgz -C /opt --exclude='msh-zr/etc/*'
sudo sh /opt/msh-zr/lib/fixperms.sh
sudo systemctl daemon-reload
sudo systemctl start msh-zr-web.service
Description
The steps are the same on every host; only the services differ. The single server commands are explained here.
Stop the services. From this point until the milter is started again, mail on this host is handled according to milter_default_action (see Mail flow during the update).
sudo systemctl stop msh-zr-web.service msh-zr-node.service msh-zr-milter.service
Unpack the new package over the existing tree, keeping the live etc/ directory as-is.
sudo tar zxvf msh-zr-<VERSION>.tgz -C /opt --exclude='msh-zr/etc/*'
Re-apply ownership and permissions.
sudo sh /opt/msh-zr/lib/fixperms.sh
Reload systemd to pick up any changes to the service unit files.
sudo systemctl daemon-reload
Start the services again. The order does not matter. If you switched milter_default_action to tempfail for the update, set it back to accept now.
sudo systemctl start msh-zr-node.service msh-zr-milter.service msh-zr-web.service
Verify
Watch the logs to confirm a clean start:
journalctl -u msh-zr-node.service -u msh-zr-milter.service -u msh-zr-web.service -f
Then open the Servers page of the web admin. Every server must show the new version in the Version column and the state Up to date.
Mail flow during the update
While msh-zr-milter.service is stopped on a host, the Postfix on that host cannot reach the milter and falls back to milter_default_action. With the recommended accept (see Zimbra configuration) mail keeps flowing, but no rules are applied - messages arriving during the update are delivered without signatures, disclaimers, blocking or any other action, and nothing is logged about them. The window is usually only a few seconds, but if your rules matter for security (blocked senders, attachment filtering, quarantine), do not rely on it being empty.
Stopping the web admin or the node does not affect mail: the milter keeps working with the rules and settings it already has. Only the milter matters for mail flow, and only on the host it runs on. In a multi-server installation the other MTA servers keep filtering normally while one is being updated.
If unfiltered mail during the update is not acceptable, temporarily switch the default action of the host you are updating to tempfail. Postfix then answers every incoming message with 451 4.7.1 Service unavailable - try again later while the milter is down: sending mail servers keep the message in their own queue and retry (typically within 5-15 minutes), and locally injected mail stays in Zimbra's queue. Nothing is lost, only delayed. Users sending from the Zimbra web client during those seconds see the same 451 error and have to resend.
Before stopping the services, as the zimbra user on that host (sudo su - zimbra):
zmprov ms $(zmhostname) zimbraMtaMilterDefaultAction tempfail
zmmtactl reload
Wait until Postfix has picked up the change before you stop the milter - check with postconf milter_default_action until it reports tempfail.
After the update, once msh-zr-milter.service is running again, switch back:
zmprov ms $(zmhostname) zimbraMtaMilterDefaultAction accept
zmmtactl reload
Deferred messages are delivered as soon as the sending servers retry; run mailq on the Zimbra host to see anything still waiting locally.
Stopping the whole MTA instead (zmmtactl stop) also prevents unfiltered mail, but it additionally pauses outbound delivery and rejects connections at the TCP level, so tempfail is the less disruptive option.
Additional resources
- Servers - server states after the update
- Troubleshooting starting services - diagnostic steps if the services do not start after the update