Maintenance Contacts
Sets who is emailed about a server’s monthly OS-patching window — the notice a few days ahead, the one when patching starts, and the one confirming it finished. There are two lists per client team, and a host can override either of them on its own.
Primary use: Adding yourself to the notices for a server you now look after, or taking off somebody who has left the project. Also the quickest way to answer “who actually hears about this server going down?”
These addresses used to live in our Ansible configuration, so changing one meant asking the DevOps team for a commit. You own them now. A change takes effect on the very next notice — nothing is deployed and nothing is regenerated.
Available for web application servers as well as FileMaker ones, like Maintenance Windows and the Maintenance Calendar — the patching automation behind the notices is the same either way.
The two lists
| List | Who it is | Where they appear on the email |
|---|---|---|
| The customer list | The customer | The To line, when anyone is on it. |
| The project team list | The team running the maintenance | Cc when the customer list has someone; the To line when it does not. |
So an empty customer list is not only “the customer is not told” — it is also what moves the notice from the customer to the project team. That is deliberate: a server whose customer contact is not yet known should still tell somebody.
Our IT team is added to every notice by the automation, on every host, whatever these lists say. Do not list them here — they would get two copies, and a list that looks populated because it contains the IT team hides the fact that nobody on the project is being told.
Finding your team
Maintenance → Maintenance Contacts lists the client teams you can reach, each with how many servers it covers. Teams where a production server has nobody outside the IT team are flagged and sorted to the top — that flag is the one thing on this page worth acting on. Nothing is hidden; only the order changes.
Two controls narrow the list, and they combine:
| Control | What it does |
|---|---|
| Filter by team or host name | Matches the team’s name and its hostnames, so a server you only know by hostname finds its team. |
| N teams need attention on production | Click it — it is a toggle, not a caption. Pressed, the list is only those teams. Click again to go back. |
Servers with no maintenance window at all are left out, since they never send these notices. If a whole team’s servers are in that position the team does not appear — which is what the footnote under the list is telling you when a team you expected is missing.
If you can reach more teams than you belong to, a toggle switches between your own teams and all of them. Ordinary members of one team never see it, because it would change nothing.
Who is notified about these servers
Click a team and the page is two steps, in the order the work happens in.
1 — Default recipients is the card at the top: the team’s two lists, a tab each. They cover every server underneath, so they are the thing to set first, and most teams never need anything else.
2 — Server overrides is the list below it, one row per server, saying which lists that server uses:
| On a row | Meaning |
|---|---|
| Both lists use team defaults | Nothing special here. This server uses the two defaults above. |
| custom for the project team | That list is set on this server and replaces the default for it. |
| no one for the project team | Set on this server and empty — nobody on that side is told, whatever the default says. |
| Customer: not set up yet | Nobody has taken that list over in the portal, so its recipients still come from our Ansible configuration. The portal cannot show you those addresses, because until somebody sets the list up here their value only exists in that repo. |
The subheading counts the exceptions — 1 of 16 servers differs from the defaults above — so a team where nothing differs can be left alone after step 1.
Which lists, not who is on them. The answer for most servers is the default, and printing it per server printed it once per server — the same names sixteen times for a team of sixteen, with the one row that differed no louder than the rest. Addresses live where they can be changed: the defaults in the card above, a server’s own inside its row.
A production server with nobody on either list is marked with an amber edge, and counted in a line at the top of the list — a total tells you how many, not which.
Find a server… filters the list as you type, on name and hostname.
When a server’s list hides the team’s
A server with a list of its own does not use its team’s, and that is easy to miss when the server’s list is empty — nothing about an empty list suggests it is the thing keeping the default’s recipients out.
Three places say so. The row carries an amber **no one for
Teams whose servers were imported with a list each often start out with a few of these. When our Ansible configuration held different lists for different servers in a team, the import made the commonest one the team’s default and left the servers that genuinely differed with a list of their own — including servers whose list was empty. So a handful of servers may be sitting out the team’s default on day one. Setting each back to Default, or ticking them all and choosing Use the team’s default, brings them back in.
One Save for the page
Nothing on a team’s page is written until you press Save changes, in the bar that follows you down the bottom of it. The defaults, and every server’s overrides, are one form: change two boxes and a segmented control in three different places, press Save once.
| What you see | What it means |
|---|---|
| Nothing changed yet | The page matches what is saved. Save and Discard are greyed out. |
| 3 lists changed — not saved yet | Counted in lists, not boxes: switching a server to No one touches a control and abandons a box, which is one decision. |
| unsaved on a collapsed row | That row has a pending edit. The badges beside it still describe what is saved, so they fade rather than pretending. |
| Undo changes to this server | Inside an open row: backs that row out without costing the others. |
| Discard changes | Puts the whole page back to what is saved. |
Leaving the page with something unsaved gets you the browser’s own “are you sure” — these addresses are worth one click of friction.
A rejected save writes nothing at all, not even the boxes that were fine: one bad address cannot be worth re-entering fifteen good ones, so the page comes back with everything exactly as you typed it, the offending row open, and one alert naming the server and the list — pir web, the Customer list: “nope” is not a valid email address.
However many lists one Save changed, the admins get one email listing them, not one per list.
Two things are deliberately not part of it. Reset hands a list back to our Ansible configuration, and the bulk bar writes to the servers you ticked; both apply immediately, and neither is an edit to what is on screen. The bulk buttons stay disabled while anything is unsaved — Save or discard your changes above first — rather than reloading the page and throwing your work away.
Changing several servers at once
Select multiple puts a tick box on every row and opens a bar above them. Until you tick something the bar is one muted line — Tick the servers you want to change together — with its buttons disabled; ticking wakes them up.
| Action | What it does |
|---|---|
| Use the team’s default for both lists | Removes the ticked servers’ own lists, so they follow the defaults again. The dropdown finishes the sentence — for both lists, for the customer list, for the project team list — and starts on both, since removing a server’s own lists is the one place that is the ordinary answer. The confirmation repeats the count and the lists before anything is removed. |
| Set recipients… | Gives every ticked server the same list of its own, replacing the default for them. |
Set recipients… asks These addresses are for — the customer, the project team, or both lists — and nothing is preselected. Setting the same addresses on both lists makes the customer’s contacts the project team’s as well, which is almost never what somebody typing a customer’s address meant, so it has to be said rather than defaulted to.
Save this as the team’s default too writes the same addresses to the team’s list in the same submit. Note what that leaves behind: the ticked servers keep a copy of their own, so a later change to the default will not reach them. If you want them following the team from now on, use Use the team’s default instead.
An empty box is not accepted here. Emptying a list is a real instruction — “tell nobody” — but doing it to a dozen servers at once is what makes a team’s default unreachable, so it stays on a single server’s row where it applies to one server and says so.
Bulk changes email our admins as one message listing every list that changed, rather than one per server.
Editing the defaults
The team’s two lists share the card at the top of the page, a tab each — the customer and the project team. Each tab says what state that list is in (1 recipient, none added, not set up), and the pane opens with a line telling you the same in full: Currently notifying 1 recipient. Put one email address per line; the page’s Save changes writes it.
A list that is not set up here shows an empty box, exactly like one that is set up and deliberately empty. Leaving it empty changes nothing — a page-wide Save will not quietly take that list over from our Ansible configuration on its way past. Type an address in and it does.
Making one server differ
Open the server’s row. Each list gets the same three choices, and the two are chosen independently — the customer list following the default while the project team list is set here is a perfectly ordinary combination.
| Choice | What it means |
|---|---|
| Default | This server follows the team. The line underneath says how many recipients that currently means; the addresses are in the card above. |
| Custom | The box below is this server’s own list, replacing the default for these notices. |
| No one | Nobody on that list is told about this server, whatever the default says. Our IT team still is. |
An empty box under Custom is refused rather than guessed at: it could mean “notify nobody” or “I have not typed it in yet”, and one of those silences a customer’s notice. No one is the choice that means it on purpose.
Going back is the same control: choose Default, then Save. There is no separate button for it, because “this server has no list of its own” and “this server follows its team” are the same fact, and having them look like two things is what used to make a team’s list appear to reach nobody.
What this server’s notices say, at the bottom of an open row, goes to that server’s own page. It previews the actual To and Cc the notices will use — worth a look when an empty customer list has moved the To line to the project team — and names the addresses each list resolves to and which scope they came from.
Saving empty, versus Reset
These are different outcomes, which is why they are different controls.
| Action | What happens |
|---|---|
| Clearing a team’s default that is already managed, then Save changes | “Tell nobody.” The list is yours and it is empty. Our IT team is still notified. |
| Reset, on a team’s default | Hands that list back, so its recipients come from our Ansible configuration again. |
| No one, on a server | “Tell nobody” for that server alone. |
| Default, on a server | Hands that server back to its team — the per-server equivalent of Reset, and the only one you need day to day. |
Reset is the one that gives up control, and the addresses that take over may not be the ones you last saw here. Use it when a list should not be managed in the portal at all; use an empty Save when you mean that nobody should be emailed.
When changes take effect
On the next notice for that host. The playbooks ask the portal at the top of every run, so there is no deploy step and no waiting for a sync.
Each of the team’s defaults shows when it was last changed and by whom, and when the automation last read it; a server’s own lists say the same on the server’s page. A list that has never been read says so — useful when you want to know whether the wiring is working at all rather than whether the addresses are right.
If the portal is unreachable when a notice goes out, the notice still goes out, addressed from the copy of these lists held in our Ansible configuration, and our IT team is told it happened. A recent change can therefore be missing from one notice during an outage. A notice that does not send at all would be worse.
Sync with Ansible
Superusers only, and only when the portal is wired up to read the repository. Everyone else never sees the link.
Sync with Ansible, at the top right of the contacts page, is where the portal and our Ansible configuration are reconciled. It is a different job from everything above — it is about a repository rather than about who is emailed — so it has its own page rather than a card above the teams.
| Direction | What it does |
|---|---|
| Import from the Ansible configuration | Copies any list not already set up here out of files/maintenance-contacts.json. Lists edited in the portal are never overwritten, so it is safe to run twice. Preview first if you want to see the count before it writes. |
| Publish back to the Ansible configuration | Opens a pull request against ansible-deploy carrying these lists, so a notice that cannot reach the portal falls back to something current. A scheduled job does this nightly; the buttons are for when you want the PR now. |
Publishing normally only checks the hosts whose lists have changed since the last publish, which takes seconds. Check every host compares all of them — worth it only if someone has edited the Ansible files by hand, which the fast path has no way of noticing. Either way a dialog shows progress and can be stopped; nothing is left half-applied, because the next run supersedes whatever the stopped one had done.
If the contacts page says no contact lists have been set up here yet, this is the page that fixes it: until something is imported, every notice is still addressed from the repository and nobody can change a recipient from the portal.
Who can change them
Anyone who can already see a host can say who is told about it — the same access that shows you its maintenance windows. There is no separate permission, on the grounds that anyone trusted to skip a server’s patching is trusted to say who hears about it.
Every change emails our admins, with the before and after. That is not an opt-in: these addresses decide who a customer hears from during an outage.