at master 5.3 kB view raw
1{ pkgs, lib, ... }: 2 3let 4 # Andorra - the smallest dataset in Europe (3.1 MB) 5 osmData = pkgs.fetchurl { 6 url = "https://web.archive.org/web/20250430211212/https://download.geofabrik.de/europe/andorra-latest.osm.pbf"; 7 hash = "sha256-Ey+ipTOFUm80rxBteirPW5N4KxmUsg/pCE58E/2rcyE="; 8 }; 9in 10{ 11 name = "nominatim"; 12 meta = { 13 maintainers = with lib.teams; [ 14 geospatial 15 ngi 16 ]; 17 }; 18 19 nodes = { 20 # nominatim - self contained host 21 nominatim = 22 { config, pkgs, ... }: 23 { 24 # Nominatim 25 services.nominatim = { 26 enable = true; 27 hostName = "nominatim"; 28 settings = { 29 NOMINATIM_IMPORT_STYLE = "admin"; 30 }; 31 ui = { 32 config = '' 33 Nominatim_Config.Page_Title='Test Nominatim instance'; 34 Nominatim_Config.Nominatim_API_Endpoint='https://localhost/'; 35 ''; 36 }; 37 }; 38 39 # Disable SSL 40 services.nginx.virtualHosts.nominatim = { 41 forceSSL = false; 42 enableACME = false; 43 }; 44 45 # Database 46 services.postgresql = { 47 enableTCPIP = true; 48 authentication = lib.mkForce '' 49 local all all trust 50 host all all 0.0.0.0/0 md5 51 host all all ::0/0 md5 52 ''; 53 }; 54 systemd.services.postgresql-setup.postStart = '' 55 psql --command "ALTER ROLE \"nominatim-api\" WITH PASSWORD 'password';" 56 ''; 57 networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ]; 58 }; 59 60 # api - web API only 61 api = 62 { config, pkgs, ... }: 63 { 64 # Database password 65 system.activationScripts = { 66 passwordFile.text = with config.services.nominatim.database; '' 67 mkdir -p /run/secrets 68 echo "${host}:${toString port}:${dbname}:${apiUser}:password" \ 69 > /run/secrets/pgpass 70 chown nominatim-api:nominatim-api /run/secrets/pgpass 71 chmod 0600 /run/secrets/pgpass 72 ''; 73 }; 74 75 # Nominatim 76 services.nominatim = { 77 enable = true; 78 hostName = "nominatim"; 79 settings = { 80 NOMINATIM_LOG_DB = "yes"; 81 }; 82 database = { 83 host = "nominatim"; 84 passwordFile = "/run/secrets/pgpass"; 85 extraConnectionParams = "application_name=nominatim;connect_timeout=2"; 86 }; 87 }; 88 89 # Disable SSL 90 services.nginx.virtualHosts.nominatim = { 91 forceSSL = false; 92 enableACME = false; 93 }; 94 }; 95 }; 96 97 testScript = '' 98 # Test nominatim host 99 nominatim.start() 100 nominatim.wait_for_unit("nominatim.service") 101 102 # Import OSM data 103 nominatim.succeed(""" 104 cd /tmp 105 sudo -u nominatim \ 106 NOMINATIM_DATABASE_WEBUSER=nominatim-api \ 107 NOMINATIM_IMPORT_STYLE=admin \ 108 nominatim import --continue import-from-file --osm-file ${osmData} 109 """) 110 nominatim.succeed("systemctl restart nominatim.service") 111 112 # Test CLI 113 nominatim.succeed("sudo -u nominatim-api nominatim search --query Andorra") 114 115 # Test web API 116 nominatim.succeed("curl 'http://localhost/status' | grep OK") 117 118 nominatim.succeed(""" 119 curl "http://localhost/search?q=Andorra&format=geojson" | grep "Andorra" 120 curl "http://localhost/reverse?lat=42.5407167&lon=1.5732033&format=geojson" 121 """) 122 123 # Test UI 124 nominatim.succeed(""" 125 curl "http://localhost/ui/search.html" \ 126 | grep "<title>Nominatim Demo</title>" 127 """) 128 129 130 # Test api host 131 api.start() 132 api.wait_for_unit("nominatim.service") 133 134 # Test web API 135 api.succeed(""" 136 curl "http://localhost/search?q=Andorra&format=geojson" | grep "Andorra" 137 curl "http://localhost/reverse?lat=42.5407167&lon=1.5732033&format=geojson" 138 """) 139 140 141 # Test format rewrites 142 # Redirect / to search 143 nominatim.succeed(""" 144 curl --verbose "http://localhost" 2>&1 \ 145 | grep "Location: http://localhost/ui/search.html" 146 """) 147 148 # Return text by default 149 nominatim.succeed(""" 150 curl --verbose "http://localhost/status" 2>&1 \ 151 | grep "Content-Type: text/plain" 152 """) 153 154 # Return JSON by default 155 nominatim.succeed(""" 156 curl --verbose "http://localhost/search?q=Andorra" 2>&1 \ 157 | grep "Content-Type: application/json" 158 """) 159 160 # Return XML by default 161 nominatim.succeed(""" 162 curl --verbose "http://localhost/lookup" 2>&1 \ 163 | grep "Content-Type: text/xml" 164 165 curl --verbose "http://localhost/reverse?lat=0&lon=0" 2>&1 \ 166 | grep "Content-Type: text/xml" 167 """) 168 169 # Redirect explicitly requested HTML format 170 nominatim.succeed(""" 171 curl --verbose "http://localhost/search?format=html" 2>&1 \ 172 | grep "Location: http://localhost/ui/search.html" 173 174 curl --verbose "http://localhost/reverse?format=html" 2>&1 \ 175 | grep "Location: http://localhost/ui/reverse.html" 176 """) 177 178 # Return explicitly requested JSON format 179 nominatim.succeed(""" 180 curl --verbose "http://localhost/search?format=json" 2>&1 \ 181 | grep "Content-Type: application/json" 182 183 curl --verbose "http://localhost/reverse?format=json" 2>&1 \ 184 | grep "Content-Type: application/json" 185 """) 186 ''; 187}