Solved freebsd-update: files have been modified locally

Hello everybody,

when running freebsd-update(8) on my 13.2-RELEASE-p2 boxes, I get:

Code:
Fetching metadata signature for 13.2-RELEASE from update1.freebsd.org... done.
Fetching metadata index... done.
Inspecting system... done.
Preparing to download files... done.
The following files are affected by updates. No changes have
been downloaded, however, because the files have been modified
locally:
/etc/ssh/sshd_config

Now I am confused. Is it a warning or an error? Will freebsd-update refuse to update my systems? Why would modifying a config file cause this? How can I restore the original file so that I can fake a 'not modified' state?
 
It's just information that freebsd-update is refusing to update that file (and that file only) as it has been modified. Sadly it does not provide means to merge the changes (it seems to be implemented for release upgrades only).

If you have src installed, you could try replacing your /etc/ssh/sshd_config with original:
Code:
$ find /usr/src -name sshd_config
/usr/src/crypto/openssh/sshd_config
 
Sounds a bit strange to me. All my sshd_config files are modified slightly for a long time, but I have never seen that message before. OK, so I will have to switch to a 'fake' original file and do the merge manually after the update.
 
Probably the only thing changing in that file is this line:
Code:
#VersionAddendum FreeBSD-20230316
That version usually gets updated if/when openssh is updated.
 
One feature of slackpkg I miss was a prompt after each one of these updates that allowed you to view the diff, merge, merge, save, or delete (or something like that). I wonder if that is something that would be considered if someone were to offer a similar feature on the freebsd-update script?
 
The feature of merging configs is there, it's just not applied to security updates as it seems to be the first time ever the config file was touched by one (I could be wrong, of course).
 
It's specifically this change: https://cgit.freebsd.org/src/commit/?h=releng/13.2&id=20bcfc33d3f2549e121f34b3839e33e176a313fc

The important one, with regards to sshd_config at least, is this change:
Code:
diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config
index 3540210daaee..30655ee03582 100644
--- a/crypto/openssh/sshd_config
+++ b/crypto/openssh/sshd_config
@@ -105,7 +105,7 @@ AuthorizedKeysFile	.ssh/authorized_keys
 #PermitTunnel no
 #ChrootDirectory none
 #UseBlacklist no
-#VersionAddendum FreeBSD-20230316
+#VersionAddendum FreeBSD-20230719
As I suspected, it's only that VersionAddendum line that got changed. You can ignore it.
 
  • Like
Reactions: mer
As I suspected, it's only that VersionAddendum line that got changed. You can ignore it.

Part of my concern is that *this* time, it's just a benign VersionAddendum but if at some point it changes an important default setting like allowed-ciphers/kex, tightening it down, upstream improvements won't get incorporated because I've made some unrelated change to my sshd_config. IIRC, there are processes in place for doing an etc-merge during certain types of freebsd-update (maybe during an upgrade?), but that it's not getting invoked here.

It seems like the Right Thing To Do™ would be to download the new sshd_config and do a 3-way merge like OpenBSD's sysmerge does. Or strongly push to using some /etc/ssh/sshd_config.d/ type directory to isolate local changes, allowing sshd_config to be upgraded independently.
 
Part of my concern is that *this* time, it's just a benign VersionAddendum but if at some point it changes an important default setting like allowed-ciphers/kex, tightening it down, upstream improvements won't get incorporated
You can avoid updating /etc/ssh/sshd_config by setting configuration data in /etc/rc.conf. For example I have the following:
Code:
sshd_enable="YES"
sshd_flags="-o PermitRootLogin=prohibit-password -o ChallengeResponseAuthentication=no"
 
Please note this from sshd_config man page:
Unless noted otherwise, for each keyword, the first obtained value will be used.
So the /etc/ssh/sshd_config.custom probably should be the other way round:
Code:
# Custom stuff above...
# ...

# last line
Include sshd_config

Otherwise the custom changes only will work for commented settings in default config.

Side note: On Debian based systems sshd_config starts with Include /etc/ssh/sshd_config.d/*.conf on first line, which IMHO is really fine...
 
  • Thanks
Reactions: mro
It seems like the Right Thing To Do™ would be to download the new sshd_config and do a 3-way merge like OpenBSD's sysmerge does.
Three-way merge is actually done by freebsd-update, but only when doing an upgrade (changes from one release to another, like 13.2 -> 13.3), not when doing an update (security fixes within a release, like 13.2-RELEASE-p4 -> ...-p5).

The behavior described here is actually controlled by /etc/freebsd-update.conf, which has the following line:
UpdateIfUnmodified /etc/ /var/ /root/ /.cshrc /.profile
which says: In these directories, only update files when they are unmodified. But be careful: If you remove the directories from this line, then locally made changes to config files will be quietly overwritten!

This is a difficult compromise. A few common solutions:
  1. (rawthey) move all the local customization to /etc/rc.conf. Disadvantage: rc.conf becomes unmanageably large and complex. And if the admin reads /etc/ssh/sshd_config, they don't know that what they see is NOT what they get, and they need to look in a separate file. Also, not all flags can be specified as command-line options for all programs. And sometimes the modifications are so extensive (I fundamentally rewrite the apache config file) that the resulting command-line version would be unmaintainably complex.
  2. (seanthingee) move all the local customization to a separate config file, which includes and overrides the original. Problem is that again one has to look in two places (but at least they're in the same directory with similar names), and that not all programs offer the ability to have two config files.
  3. Whenever you change a config file that comes from the install, save the diffs in a patch file (can be automated by using freebsd-update IDS). Then after every update, re-apply the diffs. Doing this manually for every change is an enormous amount of extra work, and error prone. Doing this automatically requires writing a bit if infrastructure, and makes the post-processing after every update tedious and hazardous.
  4. An extension of 3 is to use an integrated config management system; those have existed forever, but they are a heavy hammer for a minor problem.
My favorite answer would be: Use the 3-way merge even for updates, but that doesn't seem to be an option in freebsd-update. So for now here is what I do: If I see this message, I save a copy of the offending file myself, temporarily edit /etc/freebsd-update.conf to force the change, then do the merge by hand. It would be nice to have a computer to help me with that task.
 
Back
Top