Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The GeoIP databases from MaxMind have no stable URLs and change every month (or so). Our current method of packaging these database in Nix and playing catch-up with ever-changing file hashes is a bad idea. For instance, it makes it impossible to realize old NixOS configurations. This patch adds a NixOS service that periodically updates the GeoIP databases in /var/lib/geoip-databases. Moving NixOS modules over can be done in later patches. I tried adding MD5 check, but not all databases have them, so i skipped it. We are downloading over HTTPS though, it should be good. I also tried adding zip support, but the first zip file I extracted had a different filename inside than the archive name, which breaks an assumption in this service, so I skipped that too. Changes v9 -> v10: - Pass "--max-time" to curl to set upper bound on downloads (ensures no indefinite hanging if there's problem with networking). Timeout for network connectivity check: 60s. Timeout for geoip database (each): 15m. Changes v8 -> v9: - Mention the random timer delay in the documentation for the 'interval' option. Changes v7 -> v8: - Add "RemainAfterExit=true" for the setup service, so it won't be restarted needlessly. (Thanks @danbst!) Changes v6 -> v7: - Add --skip-existing flag to geoip-updater, which skips updating existing database files. Pass that flag when we run the service on boot (and on any NixOS configuration change). (IMHO, this is somewhat a workaround for systemd persistent timers not being triggered immediately when a timer has never expired before. But it does have the nice side effect of ensuring that the installed databases always correspond to the configured ones, since the service is now always run after configuration changes.) Changes v5 -> v6: - Update database files atomically (per DB) - If a database is removed from the configuration, it'll be removed from /var/lib/geoip-databases too (on next run). - Add NixOS module assertion so that if user inputs non- .gz or .xz file there will be a build time error instead of runtime. - Run updater as user "nobody" instead of "root". - Rename NixOS service from "geoip-databases" to "geoip-updater". - Drop RemainAfterExit, or else the timer won't trigger the unit. - Bring back "curl --fail", or else we won't catch and log curl failures. Changes v4 -> v5: - Add "GeoLite2-City.mmdb.gz" to default database list. Changes v3 -> v4: - Remove unneeded geoip-updater-setup.service after adding 'wantedBy = [ "multi-user.target" ]' directly to geoip-updater.service - Drop unneeded "Service" name from service descriptions. Changes v2 -> v3: - Network may be down when starting from a cold boot, so try a few times. Possibly, if using systemd-networkd, it'll pass on the first try. But with default DHCP on NixOS, the service is started before hostnames can be resolved and thus we need a few extra seconds. - Add error handling and mark service as failed if fatal error. - Add proper syslog log levels. - Add RandomizedDelaySec=3600 to the timer to not put high load on the MaxMind servers. Suggested by @Mic92. - Set RemainAfterExit on geoip-updater.service instead of geoip-updater-setup.service. (The latter is only a proxy that pulls in the former service). Changes v1 -> v2: From Данило Глинський (Danylo Hlynskyi) <abcz2.uprola@gmail.com>: nixos/geoip-databases: add `databases` option and fix initial setup There were two great issues when using this service: - When you just enable service, databases aren't downloaded, they are downloaded when timer triggers. Fixed this with automatic download on first system activation. - When there is no internet, updater outputs nothing to logs, which is IMO misbehavior. Fixed this with removing `--fail` option, better be explicit here.
- Loading branch information
824d82f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I get that correctly, one will be able to tamper with database as
nobody
(remove or modify it). Not sure if you can fix that without introducing new user. I may also be just plain wrong -- haven't tested that in practice!824d82f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but maybe better wait new systemd (dynamic users feature) and fix then properly?
824d82f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This then introduces possible security issue meanwhile -- I'm not sure how critical GeoIP can be (maybe for a shop with custom per-country prices this can lead to a money loss) but surely you don't want
nobody
s changing this...824d82f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we create a geoip-updater user?
Or is there some way to run the updater simply as root, but in a "protected" mode so that even if there is a security flaw in the downloader, it cannot be used for executing code as root (or have access to the whole system).
I know systemd has some options related to this, but need to look closer.
824d82f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the simplest/safest way would be to create user for now and to drop it after we get dynamic users as @danbst proposed. Maybe leave a FIXME comment?