M9 (first part): the means to locate a server

- IConnectedAddresses remembers which address each host's last connection reached, set in
  SafeHttpHandlerFactory's connect callback. That is once per pooled connection, with no
  second DNS lookup, and the address is never stored.
- IGeoLocator / DbIpLocator reads the offline DB-IP Lite city and ASN databases (MaxMind
  .mmdb, via MaxMind.Db). It maps memory, swaps to new files within ten minutes, rounds
  coordinates to one decimal, never looks up a private address, and answers nothing
  when the files are missing. CdnNetworks names the CDNs whose edge addresses say nothing
  about where a server is.
- deploy/max/geo-update.sh fetches this or last month's databases, checks them and swaps
  them in atomically. The privapub-geo timer runs it monthly as www-data, and setup.sh
  installs the directory, the script, the units and a first download.

Describing servers will use these in M8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELjqpznMFMNrJoJUj6K5p2
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-03 11:33:30 +02:00
1 parent fc15f6356d
commit cee85309b8
12 files changed
+357 -7

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Fetches the month's DB-IP Lite city and ASN databases (CC BY 4.0, https://db-ip.com) into the directory PrivaPub reads
# them from (Statistics:GeoDirectory). The app swaps to new files on its own; a failed download leaves the old ones.
set -euo pipefail
dir="${GEO_DIR:-/var/lib/privapub/geo}"
tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
this=$(date -u +%Y-%m)
last=$(date -u -d "$(date -u +%Y-%m-15) -1 month" +%Y-%m)
for kind in city asn; do
got=""
for month in "$this" "$last"; do
if curl -fsS --max-time 900 -o "$tmp/$kind.gz" "https://download.db-ip.com/free/dbip-$kind-lite-$month.mmdb.gz"; then
got=$month; break
fi
done
[ -n "$got" ] || { echo "no $kind database for $this or $last" >&2; exit 1; }
gunzip -t "$tmp/$kind.gz"
gunzip -c "$tmp/$kind.gz" > "$tmp/dbip-$kind-lite.mmdb"
[ "$(stat -c %s "$tmp/dbip-$kind-lite.mmdb")" -gt 1000000 ] || { echo "the $kind database is too small" >&2; exit 1; }
install -m 640 "$tmp/dbip-$kind-lite.mmdb" "$dir/.dbip-$kind-lite.mmdb.new"
mv -f "$dir/.dbip-$kind-lite.mmdb.new" "$dir/dbip-$kind-lite.mmdb"
echo "$kind: DB-IP Lite $got"
done
+6 -1
View File
@@ -12,7 +12,7 @@ ACME=/root/.acme.sh/acme.sh
echo "== directories"
install -d -o "$RUNNER" -g www-data -m 755 /var/www/$HOST
install -d -o "$RUNNER" -g "$RUNNER" -m 750 /var/backups/$HOST
install -d -o www-data -g www-data -m 750 /var/lib/privapub /var/lib/privapub/mongo
install -d -o www-data -g www-data -m 750 /var/lib/privapub /var/lib/privapub/mongo /var/lib/privapub/geo
echo "== sudoers"
SUDOERS=/etc/sudoers.d/$RUNNER
@@ -23,10 +23,15 @@ visudo -cf "$SUDOERS"
echo "== units"
install -m 644 "$SRC/systemd/privapub-mongod.service" /etc/systemd/system/privapub-mongod.service
install -m 644 "$SRC/systemd/$UNIT.service" /etc/systemd/system/$UNIT.service
install -m 755 "$SRC/max/geo-update.sh" /usr/local/bin/privapub-geo-update
install -m 644 "$SRC/systemd/privapub-geo.service" /etc/systemd/system/privapub-geo.service
install -m 644 "$SRC/systemd/privapub-geo.timer" /etc/systemd/system/privapub-geo.timer
systemctl daemon-reload
systemctl enable --now privapub-mongod >/dev/null
systemctl enable $UNIT >/dev/null
systemctl enable --now privapub-geo.timer >/dev/null
systemctl is-active privapub-mongod
[ -f /var/lib/privapub/geo/dbip-city-lite.mmdb ] || systemctl start privapub-geo.service || echo "geolocation databases not fetched yet; the timer retries"
echo "== nginx snippet and bootstrap vhost"
install -m 644 "$SRC/nginx/privapub-headers.conf" /etc/nginx/snippets/privapub-headers.conf
+15
View File
@@ -0,0 +1,15 @@
[Unit]
Description=PrivaPub: fetch the DB-IP Lite geolocation databases
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=www-data
Group=www-data
ExecStart=/usr/local/bin/privapub-geo-update
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/privapub/geo
+10
View File
@@ -0,0 +1,10 @@
[Unit]
Description=PrivaPub: refresh the geolocation databases monthly
[Timer]
OnCalendar=*-*-03 04:00:00
RandomizedDelaySec=6h
Persistent=true
[Install]
WantedBy=timers.target