Merge pull request #3339 from lonvia/python-frontend-as-default

Switch to Python frontend as the default
This commit is contained in:
Sarah Hoffmann 2024-02-20 10:17:21 +01:00 committed by GitHub
commit 5afd96d210
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 319 additions and 254 deletions

View File

@ -11,7 +11,7 @@ jobs:
with:
submodules: true
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: |
data/country_osm_grid.sql.gz
@ -27,7 +27,7 @@ jobs:
mv nominatim-src.tar.bz2 Nominatim
- name: 'Upload Artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: full-source
path: nominatim-src.tar.bz2
@ -43,40 +43,28 @@ jobs:
ubuntu: 20
postgresql: '9.6'
postgis: '2.5'
php: '7.3'
lua: '5.1'
- flavour: ubuntu-20
ubuntu: 20
postgresql: 13
postgis: 3
php: '7.4'
lua: '5.3'
- flavour: ubuntu-22
ubuntu: 22
postgresql: 15
postgis: 3
php: '8.1'
lua: '5.3'
runs-on: ubuntu-${{ matrix.ubuntu }}.04
steps:
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: full-source
- name: Unpack Nominatim
run: tar xf nominatim-src.tar.bz2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: phpunit:9, phpcs, composer
ini-values: opcache.jit=disable
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/setup-python@v4
with:
python-version: 3.7
@ -119,20 +107,11 @@ jobs:
run: pip3 install -U pylint
if: matrix.flavour != 'oldstuff'
- name: PHP linting
run: phpcs --report-width=120 .
working-directory: Nominatim
if: matrix.flavour != 'oldstuff'
- name: Python linting
run: python3 -m pylint nominatim
working-directory: Nominatim
if: matrix.flavour != 'oldstuff'
- name: PHP unit tests
run: phpunit ./
working-directory: Nominatim/test/php
- name: Python unit tests
run: python3 -m pytest test/python
working-directory: Nominatim
@ -156,7 +135,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: full-source
@ -185,16 +164,16 @@ jobs:
- name: BDD tests (legacy tokenizer)
run: |
python3 -m behave -DREMOVE_TEMPLATE=1 -DBUILDDIR=$GITHUB_WORKSPACE/build -DTOKENIZER=legacy --format=progress3
python3 -m behave -DREMOVE_TEMPLATE=1 -DBUILDDIR=$GITHUB_WORKSPACE/build -DAPI_ENGINE=php -DTOKENIZER=legacy --format=progress3
working-directory: Nominatim/test/bdd
python-api-test:
php-test:
needs: create-archive
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: full-source
@ -206,6 +185,23 @@ jobs:
postgresql-version: 15
postgis-version: 3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
tools: phpunit:9, phpcs, composer
ini-values: opcache.jit=disable
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: PHP linting
run: phpcs --report-width=120 .
working-directory: Nominatim
- name: PHP unit tests
run: phpunit ./
working-directory: Nominatim/test/php
- uses: ./Nominatim/.github/actions/build-nominatim
with:
flavour: 'ubuntu-22'
@ -213,12 +209,9 @@ jobs:
- name: Install test prerequsites
run: sudo apt-get install -y -qq python3-behave
- name: Install Python webservers
run: pip3 install starlette asgi_lifespan httpx
- name: BDD tests (starlette)
- name: BDD tests (php)
run: |
python3 -m behave -DREMOVE_TEMPLATE=1 -DBUILDDIR=$GITHUB_WORKSPACE/build -DAPI_ENGINE=starlette --format=progress3
python3 -m behave -DREMOVE_TEMPLATE=1 -DBUILDDIR=$GITHUB_WORKSPACE/build -DAPI_ENGINE=php --format=progress3
working-directory: Nominatim/test/bdd
@ -268,7 +261,7 @@ jobs:
OS: ${{ matrix.name }}
INSTALL_MODE: ${{ matrix.install_mode }}
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: full-source
path: /home/nominatim
@ -355,7 +348,7 @@ jobs:
needs: create-archive
steps:
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: full-source
@ -392,5 +385,4 @@ jobs:
NOMINATIM_DATABASE_DSN="pgsql:host=127.0.0.1;dbname=nominatim;user=osm-import;password=osm-import" nominatim import --continue import-from-file --osm-file test.pbf
- name: Check full import
run: |
nominatim admin --check-database
run: nominatim admin --check-database

View File

@ -82,13 +82,14 @@ endif()
# Setting PHP binary variable as to command line (prevailing) or auto detect
if (BUILD_API OR BUILD_IMPORTER)
if (BUILD_API)
if (NOT PHP_BIN)
find_program (PHP_BIN php)
endif()
# sanity check if PHP binary exists
if (NOT EXISTS ${PHP_BIN})
message(FATAL_ERROR "PHP binary not found. Install php or provide location with -DPHP_BIN=/path/php ")
message(WARNING "PHP binary not found. Only Python frontend can be used.")
set(PHP_BIN "")
else()
message (STATUS "Using PHP binary " ${PHP_BIN})
endif()
@ -226,7 +227,11 @@ if (BUILD_IMPORTER)
PATTERN "paths.py" EXCLUDE
PATTERN __pycache__ EXCLUDE)
configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py.tmpl paths-py.installed)
if (EXISTS ${PHP_BIN})
configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py.tmpl paths-py.installed)
else()
configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py-no-php.tmpl paths-py.installed)
endif()
install(FILES ${PROJECT_BINARY_DIR}/paths-py.installed
DESTINATION ${NOMINATIM_LIBDIR}/lib-python/nominatim
RENAME paths.py)
@ -254,7 +259,7 @@ if (BUILD_MODULE)
DESTINATION ${NOMINATIM_LIBDIR}/module)
endif()
if (BUILD_API)
if (BUILD_API AND EXISTS ${PHP_BIN})
install(DIRECTORY lib-php DESTINATION ${NOMINATIM_LIBDIR})
endif()

2
Vagrantfile vendored
View File

@ -38,7 +38,7 @@ Vagrant.configure("2") do |config|
lv.memory = 2048
lv.nested = true
if ENV['CHECKOUT'] != 'y' then
override.vm.synced_folder ".", "/home/vagrant/Nominatim", type: 'nfs'
override.vm.synced_folder ".", "/home/vagrant/Nominatim", type: 'nfs', nfs_udp: false
end
end

View File

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# This file is part of Nominatim. (https://nominatim.org)
#
# Copyright (C) 2022 by the Nominatim developer community.
# For a full list of authors see the git log.
"""
Path settings for extra data used by Nominatim (installed version).
"""
from pathlib import Path
PHPLIB_DIR = None
SQLLIB_DIR = (Path('@NOMINATIM_LIBDIR@') / 'lib-sql').resolve()
DATA_DIR = Path('@NOMINATIM_DATADIR@').resolve()
CONFIG_DIR = Path('@NOMINATIM_CONFIGDIR@').resolve()

View File

@ -268,27 +268,10 @@ nominatim reverse --lat 51 --lon 45
```
If you want to run Nominatim as a service, you need to make a choice between
running the traditional PHP frontend or the new experimental Python frontend.
running the modern Python frontend and the legacy PHP frontend.
Make sure you have installed the right packages as per
[Installation](Installation.md#software).
#### Testing the PHP frontend
You can run a small test server with the PHP frontend like this:
```sh
nominatim serve
```
Go to `http://localhost:8088/status.php` and you should see the message `OK`.
You can also run a search query, e.g. `http://localhost:8088/search.php?q=Berlin`
or, for reverse-only installations a reverse query,
e.g. `http://localhost:8088/reverse.php?lat=27.1750090510034&lon=78.04209025`.
Do not use this test server in production.
To run Nominatim via webservers like Apache or nginx, please continue reading
[Deploy the PHP frontend](Deployment-PHP.md).
#### Testing the Python frontend
To run the test server against the Python frontend, you must choose a
@ -296,10 +279,10 @@ web framework to use, either starlette or falcon. Make sure the appropriate
packages are installed. Then run
``` sh
nominatim serve --engine falcon
nominatim serve
```
or
or, if you prefer to use Starlette instead of Falcon as webserver,
``` sh
nominatim serve --engine starlette
@ -314,6 +297,24 @@ Do not use this test server in production.
To run Nominatim via webservers like Apache or nginx, please continue reading
[Deploy the Python frontend](Deployment-Python.md).
#### Testing the PHP frontend
You can run a small test server with the PHP frontend like this:
```sh
nominatim serve --engine php
```
Go to `http://localhost:8088/status.php` and you should see the message `OK`.
You can also run a search query, e.g. `http://localhost:8088/search.php?q=Berlin`
or, for reverse-only installations a reverse query,
e.g. `http://localhost:8088/reverse.php?lat=27.1750090510034&lon=78.04209025`.
Do not use this test server in production.
To run Nominatim via webservers like Apache or nginx, please continue reading
[Deploy the PHP frontend](Deployment-PHP.md).
## Enabling search by category phrases

View File

@ -55,23 +55,24 @@ For running Nominatim:
* [PyYaml](https://pyyaml.org/) (5.1+)
* [datrie](https://github.com/pytries/datrie)
When running the PHP frontend:
* [PHP](https://php.net) (7.3+)
* PHP-pgsql
* PHP-intl (bundled with PHP)
For running continuous updates:
* [pyosmium](https://osmcode.org/pyosmium/)
For running the experimental Python frontend:
For running the Python frontend:
* one of the following web frameworks:
* [falcon](https://falconframework.org/) (3.0+)
* [starlette](https://www.starlette.io/)
* [uvicorn](https://www.uvicorn.org/)
For running the legacy PHP frontend:
* [PHP](https://php.net) (7.3+)
* PHP-pgsql
* PHP-intl (bundled with PHP)
For dependencies for running tests and building documentation, see
the [Development section](../develop/Development-Environment.md).

View File

@ -22,8 +22,8 @@ nav:
- 'Basic Installation': 'admin/Installation.md'
- 'Import' : 'admin/Import.md'
- 'Update' : 'admin/Update.md'
- 'Deploy (PHP frontend)' : 'admin/Deployment-PHP.md'
- 'Deploy (Python frontend)' : 'admin/Deployment-Python.md'
- 'Deploy (PHP frontend)' : 'admin/Deployment-PHP.md'
- 'Nominatim UI' : 'admin/Setup-Nominatim-UI.md'
- 'Advanced Installations' : 'admin/Advanced-Installations.md'
- 'Maintenance' : 'admin/Maintenance.md'

View File

@ -13,6 +13,7 @@ import datetime as dt
import textwrap
import io
import re
import html
import sqlalchemy as sa
from sqlalchemy.ext.asyncio import AsyncConnection
@ -227,7 +228,7 @@ class HTMLLogger(BaseLogger):
HtmlFormatter(nowrap=True, lineseparator='<br />'))
self._write(f'<div class="highlight"><code class="lang-sql">{sqlstr}</code></div>')
else:
self._write(f'<code class="lang-sql">{sqlstr}</code>')
self._write(f'<code class="lang-sql">{html.escape(sqlstr)}</code>')
def _python_var(self, var: Any) -> str:
@ -235,7 +236,7 @@ class HTMLLogger(BaseLogger):
fmt = highlight(str(var), PythonLexer(), HtmlFormatter(nowrap=True))
return f'<div class="highlight"><code class="lang-python">{fmt}</code></div>'
return f'<code class="lang-python">{str(var)}</code>'
return f'<code class="lang-python">{html.escape(str(var))}</code>'
def _write(self, text: str) -> None:

View File

@ -159,13 +159,15 @@ class AdminServe:
group = parser.add_argument_group('Server arguments')
group.add_argument('--server', default='127.0.0.1:8088',
help='The address the server will listen to.')
group.add_argument('--engine', default='php',
group.add_argument('--engine', default='falcon',
choices=('php', 'falcon', 'starlette'),
help='Webserver framework to run. (default: php)')
help='Webserver framework to run. (default: falcon)')
def run(self, args: NominatimArgs) -> int:
if args.engine == 'php':
if args.config.lib_dir.php is None:
raise UsageError("PHP frontend not configured.")
run_php_server(args.server, args.project_dir / 'website')
else:
import uvicorn # pylint: disable=import-outside-toplevel

View File

@ -214,19 +214,20 @@ class ICUTokenizer(AbstractTokenizer):
return list(s[0].split('@')[0] for s in cur)
def _install_php(self, phpdir: Path, overwrite: bool = True) -> None:
def _install_php(self, phpdir: Optional[Path], overwrite: bool = True) -> None:
""" Install the php script for the tokenizer.
"""
assert self.loader is not None
php_file = self.data_dir / "tokenizer.php"
if phpdir is not None:
assert self.loader is not None
php_file = self.data_dir / "tokenizer.php"
if not php_file.exists() or overwrite:
php_file.write_text(dedent(f"""\
<?php
@define('CONST_Max_Word_Frequency', 10000000);
@define('CONST_Term_Normalization_Rules', "{self.loader.normalization_rules}");
@define('CONST_Transliteration', "{self.loader.get_search_rules()}");
require_once('{phpdir}/tokenizer/icu_tokenizer.php');"""), encoding='utf-8')
if not php_file.exists() or overwrite:
php_file.write_text(dedent(f"""\
<?php
@define('CONST_Max_Word_Frequency', 10000000);
@define('CONST_Term_Normalization_Rules', "{self.loader.normalization_rules}");
@define('CONST_Transliteration', "{self.loader.get_search_rules()}");
require_once('{phpdir}/tokenizer/icu_tokenizer.php');"""), encoding='utf-8')
def _save_config(self) -> None:

View File

@ -269,15 +269,16 @@ class LegacyTokenizer(AbstractTokenizer):
def _install_php(self, config: Configuration, overwrite: bool = True) -> None:
""" Install the php script for the tokenizer.
"""
php_file = self.data_dir / "tokenizer.php"
if config.lib_dir.php is not None:
php_file = self.data_dir / "tokenizer.php"
if not php_file.exists() or overwrite:
php_file.write_text(dedent(f"""\
<?php
@define('CONST_Max_Word_Frequency', {config.MAX_WORD_FREQUENCY});
@define('CONST_Term_Normalization_Rules', "{config.TERM_NORMALIZATION}");
require_once('{config.lib_dir.php}/tokenizer/legacy_tokenizer.php');
"""), encoding='utf-8')
if not php_file.exists() or overwrite:
php_file.write_text(dedent(f"""\
<?php
@define('CONST_Max_Word_Frequency', {config.MAX_WORD_FREQUENCY});
@define('CONST_Term_Normalization_Rules', "{config.TERM_NORMALIZATION}");
require_once('{config.lib_dir.php}/tokenizer/legacy_tokenizer.php');
"""), encoding='utf-8')
def _init_db_tables(self, config: Configuration) -> None:

View File

@ -213,6 +213,10 @@ def _quote_php_variable(var_type: Type[Any], config: Configuration,
def setup_website(basedir: Path, config: Configuration, conn: Connection) -> None:
""" Create the website script stubs.
"""
if config.lib_dir.php is None:
LOG.info("Python frontend does not require website setup. Skipping.")
return
if not basedir.exists():
LOG.info('Creating website directory.')
basedir.mkdir()

View File

@ -28,7 +28,7 @@ userconfig = {
'SERVER_MODULE_PATH' : None,
'TOKENIZER' : None, # Test with a custom tokenizer
'STYLE' : 'extratags',
'API_ENGINE': 'php',
'API_ENGINE': 'falcon',
'PHPCOV' : False, # set to output directory to enable code coverage
}

View File

@ -243,7 +243,7 @@ def step_impl(context, fmt):
try:
tree = ET.fromstring(context.response.page)
except Exception as ex:
assert False, f"Could not parse page:\n{context.response.page}"
assert False, f"Could not parse page: {ex}\n{context.response.page}"
assert tree.tag == 'html'
body = tree.find('./body')

View File

@ -63,7 +63,7 @@ def test_cli_add_data_tiger_data(cli_call, cli_tokenizer_mock, mock_func_factory
def test_cli_serve_php(cli_call, mock_func_factory):
func = mock_func_factory(nominatim.cli, 'run_php_server')
cli_call('serve') == 0
cli_call('serve', '--engine', 'php') == 0
assert func.called == 1

View File

@ -16,16 +16,16 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
# Make sure all packages are up-to-date by running:
#
sudo apt update -qq
sudo apt-get update -qq
# Now you can install all packages needed for Nominatim:
sudo apt install -y build-essential cmake g++ libboost-dev libboost-system-dev \
sudo apt-get install -y build-essential cmake g++ libboost-dev libboost-system-dev \
libboost-filesystem-dev libexpat1-dev zlib1g-dev \
libbz2-dev libpq-dev liblua5.3-dev lua5.3 lua-dkjson \
nlohmann-json3-dev postgresql-12-postgis-3 \
postgresql-contrib-12 postgresql-12-postgis-3-scripts \
php-cli php-pgsql php-intl libicu-dev python3-dotenv \
libicu-dev python3-dotenv \
python3-psycopg2 python3-psutil python3-jinja2 python3-pip \
python3-icu python3-datrie python3-yaml git
@ -133,45 +133,107 @@ fi #DOCS:
# Nominatim is now ready to use. You can continue with
# [importing a database from OSM data](../admin/Import.md). If you want to set up
# a webserver first, continue reading.
# the API frontend first, continue reading.
#
# Setting up the Python frontend
# ==============================
#
# Some of the Python packages in Ubuntu are too old. Therefore run the
# frontend from a Python virtualenv with current packages.
#
# To set up the virtualenv, run:
#DOCS:```sh
sudo apt-get install -y virtualenv
virtualenv $USERHOME/nominatim-venv
$USERHOME/nominatim-venv/bin/pip install SQLAlchemy PyICU psycopg[binary] \
psycopg2-binary python-dotenv PyYAML falcon uvicorn gunicorn
#DOCS:```
# Next you need to create a systemd job that runs Nominatim on gunicorn.
# First create a systemd job that manages the socket file:
#DOCS:```sh
sudo tee /etc/systemd/system/nominatim.socket << EOFSOCKETSYSTEMD
[Unit]
Description=Gunicorn socket for Nominatim
[Socket]
ListenStream=/run/nominatim.sock
SocketUser=www-data
[Install]
WantedBy=multi-user.target
EOFSOCKETSYSTEMD
#DOCS:```
# Then create the service for Nominatim itself.
#DOCS:```sh
sudo tee /etc/systemd/system/nominatim.service << EOFNOMINATIMSYSTEMD
[Unit]
Description=Nominatim running as a gunicorn application
After=network.target
Requires=nominatim.socket
[Service]
Type=simple
Environment="PYTHONPATH=/usr/local/lib/nominatim/lib-python/"
User=www-data
Group=www-data
WorkingDirectory=$USERHOME/nominatim-project
ExecStart=$USERHOME/nominatim-venv/bin/gunicorn -b unix:/run/nominatim.sock -w 4 -k uvicorn.workers.UvicornWorker nominatim.server.falcon.server:run_wsgi
ExecReload=/bin/kill -s HUP \$MAINPID
StandardOutput=append:/var/log/gunicorn-nominatim.log
StandardError=inherit
PrivateTmp=true
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
EOFNOMINATIMSYSTEMD
#DOCS:```
# Activate the services:
if [ "x$NOSYSTEMD" != "xyes" ]; then #DOCS:
sudo systemctl daemon-reload
sudo systemctl enable nominatim.socket
sudo systemctl start nominatim.socket
sudo systemctl enable nominatim.service
fi #DOCS:
# Setting up a webserver
# ======================
#
# The webserver should serve the php scripts from the website directory of your
# [project directory](../admin/Import.md#creating-the-project-directory).
# This directory needs to exist when being configured.
# Therefore set up a project directory and create a website directory:
# The webserver is only needed as a proxy between the public interface
# and the gunicorn service.
#
# The frontend will need configuration information from the project
# directory, which will be populated later
# [during the import process](../admin/Import.md#creating-the-project-directory)
# Already create the project directory itself now:
mkdir $USERHOME/nominatim-project
mkdir $USERHOME/nominatim-project/website
# The import process will populate the directory later.
#
# Option 1: Using Apache
# ----------------------
#
if [ "x$2" == "xinstall-apache" ]; then #DOCS:
#
# Apache has a PHP module that can be used to serve Nominatim. To install them
# run:
# First install apache itself and enable the proxy module:
sudo apt install -y apache2 libapache2-mod-php
sudo apt-get install -y apache2
sudo a2enmod proxy_http
# You need to create an alias to the website directory in your apache
# configuration. Add a separate nominatim configuration to your webserver:
# To set up proxying for Apache add the following configuration:
#DOCS:```sh
sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF
<Directory "$USERHOME/nominatim-project/website">
Options FollowSymLinks MultiViews
AddType text/html .php
DirectoryIndex search.php
Require all granted
</Directory>
Alias /nominatim $USERHOME/nominatim-project/website
ProxyPass /nominatim "unix:/run/nominatim.sock|http://localhost/"
EOFAPACHECONF
#DOCS:```
@ -196,33 +258,9 @@ fi #DOCS:
#
if [ "x$2" == "xinstall-nginx" ]; then #DOCS:
# Nginx has no native support for php scripts. You need to set up php-fpm for
# this purpose. First install nginx and php-fpm:
# First install nginx itself:
sudo apt install -y nginx php-fpm
# You need to configure php-fpm to listen on a Unix socket.
#DOCS:```sh
sudo tee /etc/php/7.4/fpm/pool.d/www.conf << EOF_PHP_FPM_CONF
[www]
; Replace the tcp listener and add the unix socket
listen = /var/run/php-fpm-nominatim.sock
; Ensure that the daemon runs as the correct user
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
; Unix user of FPM processes
user = www-data
group = www-data
; Choose process manager type (static, dynamic, ondemand)
pm = ondemand
pm.max_children = 5
EOF_PHP_FPM_CONF
#DOCS:```
sudo apt-get install -y nginx
# Then create a Nginx configuration to forward http requests to that socket.
@ -233,45 +271,26 @@ server {
listen [::]:80 default_server;
root $USERHOME/nominatim-project/website;
index search.php index.html;
location / {
try_files \$uri \$uri/ @php;
}
index /search;
location @php {
fastcgi_param SCRIPT_FILENAME "\$document_root\$uri.php";
fastcgi_param PATH_TRANSLATED "\$document_root\$uri.php";
fastcgi_param QUERY_STRING \$args;
fastcgi_pass unix:/var/run/php-fpm-nominatim.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f \$document_root\$fastcgi_script_name) {
return 404;
}
fastcgi_pass unix:/var/run/php-fpm-nominatim.sock;
fastcgi_index search.php;
include fastcgi.conf;
location /nominatim/ {
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_redirect off;
proxy_pass http://unix:/run/nominatim.sock:/;
}
}
EOF_NGINX_CONF
#DOCS:```
# If you have some errors, make sure that php-fpm-nominatim.sock is well under
# /var/run/ and not under /var/run/php. Otherwise change the Nginx configuration
# to /var/run/php/php-fpm-nominatim.sock.
#
# Enable the configuration and restart Nginx
#
if [ "x$NOSYSTEMD" == "xyes" ]; then #DOCS:
sudo /usr/sbin/php-fpm7.4 --nodaemonize --fpm-config /etc/php/7.4/fpm/php-fpm.conf & #DOCS:
sudo /usr/sbin/nginx & #DOCS:
else #DOCS:
sudo systemctl restart php7.4-fpm nginx
sudo systemctl restart nginx
fi #DOCS:
# The Nominatim API is now available at `http://localhost/`.

View File

@ -16,19 +16,20 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
# Make sure all packages are up-to-date by running:
#
sudo apt update -qq
sudo apt-get update -qq
# Now you can install all packages needed for Nominatim:
sudo apt install -y build-essential cmake g++ libboost-dev libboost-system-dev \
sudo apt-get install -y build-essential cmake g++ libboost-dev libboost-system-dev \
libboost-filesystem-dev libexpat1-dev zlib1g-dev \
libbz2-dev libpq-dev liblua5.3-dev lua5.3 lua-dkjson \
nlohmann-json3-dev postgresql-14-postgis-3 \
postgresql-contrib-14 postgresql-14-postgis-3-scripts \
php-cli php-pgsql php-intl libicu-dev python3-dotenv \
libicu-dev python3-dotenv \
python3-psycopg2 python3-psutil python3-jinja2 \
python3-icu python3-datrie python3-sqlalchemy \
python3-asyncpg python3-yaml git
python3-sqlalchemy python3-asyncpg \
python3-icu python3-datrie python3-yaml git
#
# System Configuration
@ -128,20 +129,89 @@ fi #DOCS:
# Nominatim is now ready to use. You can continue with
# [importing a database from OSM data](../admin/Import.md). If you want to set up
# a webserver first, continue reading.
# the API frontend first, continue reading.
#
# Setting up the Python frontend
# ==============================
#
# Some of the Python packages in Ubuntu are too old. Therefore run the
# frontend from a Python virtualenv with current packages.
#
# To set up the virtualenv, run:
#DOCS:```sh
sudo apt-get install -y virtualenv
virtualenv $USERHOME/nominatim-venv
$USERHOME/nominatim-venv/bin/pip install SQLAlchemy PyICU psycopg[binary] \
psycopg2-binary python-dotenv PyYAML falcon uvicorn gunicorn
#DOCS:```
# Next you need to create a systemd job that runs Nominatim on gunicorn.
# First create a systemd job that manages the socket file:
#DOCS:```sh
sudo tee /etc/systemd/system/nominatim.socket << EOFSOCKETSYSTEMD
[Unit]
Description=Gunicorn socket for Nominatim
[Socket]
ListenStream=/run/nominatim.sock
SocketUser=www-data
[Install]
WantedBy=multi-user.target
EOFSOCKETSYSTEMD
#DOCS:```
# Then create the service for Nominatim itself.
#DOCS:```sh
sudo tee /etc/systemd/system/nominatim.service << EOFNOMINATIMSYSTEMD
[Unit]
Description=Nominatim running as a gunicorn application
After=network.target
Requires=nominatim.socket
[Service]
Type=simple
Environment="PYTHONPATH=/usr/local/lib/nominatim/lib-python/"
User=www-data
Group=www-data
WorkingDirectory=$USERHOME/nominatim-project
ExecStart=$USERHOME/nominatim-venv/bin/gunicorn -b unix:/run/nominatim.sock -w 4 -k uvicorn.workers.UvicornWorker nominatim.server.falcon.server:run_wsgi
ExecReload=/bin/kill -s HUP \$MAINPID
StandardOutput=append:/var/log/gunicorn-nominatim.log
StandardError=inherit
PrivateTmp=true
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
EOFNOMINATIMSYSTEMD
#DOCS:```
# Activate the services:
if [ "x$NOSYSTEMD" != "xyes" ]; then #DOCS:
sudo systemctl daemon-reload
sudo systemctl enable nominatim.socket
sudo systemctl start nominatim.socket
sudo systemctl enable nominatim.service
fi #DOCS:
# Setting up a webserver
# ======================
#
# The webserver should serve the php scripts from the website directory of your
# [project directory](../admin/Import.md#creating-the-project-directory).
# This directory needs to exist when being configured.
# Therefore set up a project directory and create a website directory:
# The webserver is only needed as a proxy between the public interface
# and the gunicorn service.
#
# The frontend will need configuration information from the project
# directory, which will be populated later
# [during the import process](../admin/Import.md#creating-the-project-directory)
# Already create the project directory itself now:
mkdir $USERHOME/nominatim-project
mkdir $USERHOME/nominatim-project/website
# The import process will populate the directory later.
#
# Option 1: Using Apache
@ -149,24 +219,18 @@ fi #DOCS:
#
if [ "x$2" == "xinstall-apache" ]; then #DOCS:
#
# Apache has a PHP module that can be used to serve Nominatim. To install them
# run:
# First install apache itself and enable the proxy module:
sudo apt install -y apache2 libapache2-mod-php
sudo apt-get install -y apache2
sudo a2enmod proxy_http
# You need to create an alias to the website directory in your apache
# configuration. Add a separate nominatim configuration to your webserver:
#
# To set up proxying for Apache add the following configuration:
#DOCS:```sh
sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF
<Directory "$USERHOME/nominatim-project/website">
Options FollowSymLinks MultiViews
AddType text/html .php
DirectoryIndex search.php
Require all granted
</Directory>
Alias /nominatim $USERHOME/nominatim-project/website
ProxyPass /nominatim "unix:/run/nominatim.sock|http://localhost/"
EOFAPACHECONF
#DOCS:```
@ -174,7 +238,10 @@ EOFAPACHECONF
# Then enable the configuration and restart apache
#
sudo a2enconf nominatim
#DOCS:```sh
sudo a2enconf nominatim
#DOCS:```
if [ "x$NOSYSTEMD" == "xyes" ]; then #DOCS:
sudo apache2ctl start #DOCS:
else #DOCS:
@ -191,33 +258,10 @@ fi #DOCS:
#
if [ "x$2" == "xinstall-nginx" ]; then #DOCS:
# Nginx has no native support for php scripts. You need to set up php-fpm for
# this purpose. First install nginx and php-fpm:
# First install nginx itself:
sudo apt install -y nginx php-fpm
sudo apt-get install -y nginx
# You need to configure php-fpm to listen on a Unix socket.
#DOCS:```sh
sudo tee /etc/php/8.1/fpm/pool.d/www.conf << EOF_PHP_FPM_CONF
[www]
; Replace the tcp listener and add the unix socket
listen = /var/run/php-fpm-nominatim.sock
; Ensure that the daemon runs as the correct user
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
; Unix user of FPM processes
user = www-data
group = www-data
; Choose process manager type (static, dynamic, ondemand)
pm = ondemand
pm.max_children = 5
EOF_PHP_FPM_CONF
#DOCS:```
# Then create a Nginx configuration to forward http requests to that socket.
@ -228,49 +272,28 @@ server {
listen [::]:80 default_server;
root $USERHOME/nominatim-project/website;
index search.php index.html;
location / {
try_files \$uri \$uri/ @php;
}
index /search;
location @php {
fastcgi_param SCRIPT_FILENAME "\$document_root\$uri.php";
fastcgi_param PATH_TRANSLATED "\$document_root\$uri.php";
fastcgi_param QUERY_STRING \$args;
fastcgi_pass unix:/var/run/php-fpm-nominatim.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f \$document_root\$fastcgi_script_name) {
return 404;
}
fastcgi_pass unix:/var/run/php-fpm-nominatim.sock;
fastcgi_index search.php;
include fastcgi.conf;
location /nominatim/ {
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_redirect off;
proxy_pass http://unix:/run/nominatim.sock:/;
}
}
EOF_NGINX_CONF
#DOCS:```
# If you have some errors, make sure that php-fpm-nominatim.sock is well under
# /var/run/ and not under /var/run/php. Otherwise change the Nginx configuration
# to /var/run/php/php-fpm-nominatim.sock.
#
# Enable the configuration and restart Nginx
#
if [ "x$NOSYSTEMD" == "xyes" ]; then #DOCS:
sudo /usr/sbin/php-fpm8.1 --nodaemonize --fpm-config /etc/php/8.1/fpm/php-fpm.conf & #DOCS:
sudo /usr/sbin/nginx & #DOCS:
else #DOCS:
sudo systemctl restart php8.1-fpm nginx
sudo systemctl restart nginx
fi #DOCS:
# The Nominatim API is now available at `http://localhost/`.
# The Nominatim API is now available at `http://localhost/nominatim/`.
fi #DOCS: