Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Overv/openstreetmap-tile-server
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.3.3
Choose a base ref
...
head repository: Overv/openstreetmap-tile-server
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Sep 27, 2019

  1. Copy the full SHA
    d106610 View commit details

Commits on Sep 29, 2019

  1. Merge pull request #71 from stevo01/master

    use carto version 0.18.2 to solve carto conflicts / warnings
    Overv authored Sep 29, 2019
    Copy the full SHA
    598a481 View commit details

Commits on Oct 3, 2019

  1. Copy the full SHA
    bfcc7d7 View commit details

Commits on Oct 4, 2019

  1. Merge pull request #73 from stevo01/master

    use tag v4.23.0 from openstreetmap-carto instead to use master
    Overv authored Oct 4, 2019
    Copy the full SHA
    40ebaf7 View commit details

Commits on Oct 12, 2019

  1. Copy the full SHA
    ca4b1ac View commit details
  2. Copy the full SHA
    6e5f4f4 View commit details

Commits on Oct 14, 2019

  1. Upgrade to postgresql 12

    root authored and root committed Oct 14, 2019
    Copy the full SHA
    e249f30 View commit details

Commits on Oct 16, 2019

  1. Fix README.md

    Y0ngg4n committed Oct 16, 2019
    Copy the full SHA
    101bb62 View commit details

Commits on Oct 20, 2019

  1. Copy the full SHA
    ca1626a View commit details

Commits on Oct 22, 2019

  1. Copy the full SHA
    626158f View commit details

Commits on Nov 7, 2019

  1. Copy the full SHA
    64c66a7 View commit details

Commits on Dec 5, 2019

  1. Copy the full SHA
    789ff77 View commit details

Commits on Dec 22, 2019

  1. Copy the full SHA
    010f87d View commit details
  2. Create .travis.yml

    Gjacquenot committed Dec 22, 2019
    Copy the full SHA
    879e5f2 View commit details
  3. Copy the full SHA
    92708df View commit details
  4. Copy the full SHA
    c8a79a1 View commit details
  5. Copy the full SHA
    8bac516 View commit details
  6. Copy the full SHA
    0527120 View commit details
  7. Copy the full SHA
    868d2fa View commit details
  8. Copy the full SHA
    6de21a4 View commit details
  9. Copy the full SHA
    efc2cb1 View commit details
  10. 📝 Typo update

    Gjacquenot committed Dec 22, 2019
    Copy the full SHA
    69cb804 View commit details
  11. 📝 Typo update

    Gjacquenot committed Dec 22, 2019
    Copy the full SHA
    fa4b0eb View commit details

Commits on Dec 23, 2019

  1. 📝 Updated .travis.yml

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    f9f1047 View commit details
  2. 🔨 Updated user command

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    62a9727 View commit details
  3. Copy the full SHA
    b71e7a6 View commit details
  4. 🔧 Removed clang

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    d8ccc2c View commit details
  5. 🔨 Refactored Dockerfile

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    e8e95c6 View commit details
  6. Copy the full SHA
    637e821 View commit details
  7. 🔨 Updated Makefile

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    e0f7438 View commit details
  8. Copy the full SHA
    bae840f View commit details
  9. Copy the full SHA
    f77c926 View commit details
  10. Copy the full SHA
    f69bcd2 View commit details
  11. Copy the full SHA
    837a38d View commit details
  12. Copy the full SHA
    d792242 View commit details
  13. Copy the full SHA
    17a2c6d View commit details
  14. Copy the full SHA
    4ca2e8f View commit details
  15. Copy the full SHA
    d042852 View commit details
  16. 🔨 Updated .travis.yml

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    e9a26dd View commit details
  17. 🔨 Updated .travis.yml

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    18c97f5 View commit details
  18. 🔧 Updated .travis.yml

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    515dd2a View commit details
  19. 🔧 Updated .travis.yml

    Gjacquenot committed Dec 23, 2019
    Copy the full SHA
    a90f8f1 View commit details

Commits on Dec 25, 2019

  1. Copy the full SHA
    dafb461 View commit details

Commits on Dec 27, 2019

  1. Merge pull request #98 from Gjacquenot/master

    Add CI for openstreetmap-tile-server
    Overv authored Dec 27, 2019
    Copy the full SHA
    ac609fe View commit details
  2. Update Travis config

    Overv committed Dec 27, 2019
    Copy the full SHA
    99484a5 View commit details
  3. Copy the full SHA
    0d789b8 View commit details
  4. Copy the full SHA
    f2971fa View commit details

Commits on Jan 23, 2020

  1. remove unnecessary shapefile archives

    irekzagan committed Jan 23, 2020
    Copy the full SHA
    b192fab View commit details

Commits on Feb 4, 2020

  1. Merge pull request #99 from irexiz/master

    Remove unnecessary shapefile archives to reduce final image size
    Overv authored Feb 4, 2020
    Copy the full SHA
    f0f36a6 View commit details

Commits on Feb 9, 2020

  1. Get nodejs from source

    pandel committed Feb 9, 2020
    Copy the full SHA
    0a5ac2a View commit details
Showing with 914 additions and 341 deletions.
  1. +6 −0 .dockerignore
  2. +189 −0 .github/workflows/build-and-test.yaml
  3. +28 −0 .travis.yml
  4. +149 −149 Dockerfile
  5. +201 −0 LICENSE
  6. +11 −5 Makefile
  7. +126 −46 README.md
  8. +3 −2 apache.conf
  9. +14 −0 docker-compose.yml
  10. +0 −48 indexes.sql
  11. +2 −2 leaflet-demo.html
  12. +60 −60 openstreetmap-tiles-update-expire → openstreetmap-tiles-update-expire.sh
  13. +1 −1 postgresql.custom.conf.tmpl
  14. +124 −28 run.sh
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/.github/
/.travis.yml
/docker-compose.yml
/LICENSE
/Makefile
/README.md
189 changes: 189 additions & 0 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
name: Build and test image

on:
push:
branches:
- master
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
pull_request:
branches:
- master

# cancel outdated jobs for the same reference
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
IMAGE : ${{ github.repository_owner }}/openstreetmap-tile-server
TAG : ${{ github.sha }}

jobs:

build:
strategy:
matrix:
include:
- arch : amd64
mode : build-and-test
- arch : arm64
variant : v8
mode : build-only
runs-on: ubuntu-latest
env:
VOLUME : osm-db
CONTAINER : osm-www
MOUNT : /data/database/
PLATFORM : linux/${{ matrix.arch }}${{ (matrix.variant != '' && format('/{0}', matrix.variant)) || '' }}
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: ${{ matrix.arch }}
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Environment
run : |
echo IMAGE=$(echo ${{ env.IMAGE }} | tr '[:upper:]' '[:lower:]') >>$GITHUB_ENV
-
name: Docker build
uses: docker/build-push-action@v3
with:
pull : true
load : ${{ matrix.mode == 'build-and-test' }}
platforms : ${{ env.PLATFORM }}
context : .
file : ./Dockerfile
tags : ${{ env.IMAGE }}:${{ env.TAG }}
cache-from : type=gha,scope=${{ github.workflow }}:${{ env.PLATFORM }}
cache-to : type=gha,scope=${{ github.workflow }}:${{ env.PLATFORM }},mode=max
-
name: Import Luxembourg
if : ${{ matrix.mode == 'build-and-test' }}
run : |
docker volume create ${VOLUME}
docker run --rm --shm-size=128M -v ${VOLUME}:${MOUNT} -e UPDATES=enabled ${IMAGE}:${TAG} import
-
name: Start server
if : ${{ matrix.mode == 'build-and-test' }}
run : |
docker run --shm-size=128M -v ${VOLUME}:${MOUNT} -e UPDATES=enabled -p 80:80 -d --name ${CONTAINER} ${IMAGE}:${TAG} run
sleep 30
docker logs ${CONTAINER}
-
name: Download tiles
if : ${{ matrix.mode == 'build-and-test' }}
run : |
curl http://localhost/tile/0/0/0.png --fail -o 000.png
curl http://localhost/tile/1/0/0.png --fail -o 100.png
curl http://localhost/tile/1/0/1.png --fail -o 101.png
curl http://localhost/tile/1/1/0.png --fail -o 110.png
curl http://localhost/tile/1/1/1.png --fail -o 111.png
curl http://localhost/tile/18/138474/85459.png --fail -o empty.png
curl http://localhost/tile/18/135536/89345.png --fail -o example.png
-
name: Upload tiles
if : ${{ matrix.mode == 'build-and-test' }}
uses: actions/upload-artifact@v3
with:
name: tiles
path: '*.png'
-
name: Verify tiles
if : ${{ matrix.mode == 'build-and-test' }}
run : |
sha1sum *.png
sha1sum --check <<EOF
c226ca747874fb1307eef853feaf9d8db28cef2b *empty.png
EOF
tiles=(`ls *.png`)
for ((i=0; i<${#tiles[@]}; i++)) ; do
if [ `file --brief --mime-type "${tiles[$i]}"` != 'image/png' ] ; then
>&2 echo "ERROR: ${tiles[$i]} is not a image/png file"
exit 1
fi
for ((j=i+1; j<${#tiles[@]}; j++)) ; do
if ( diff "${tiles[$i]}" "${tiles[$j]}" ) ; then
>&2 echo "ERROR: ${tiles[$i]} is identical to ${tiles[$j]}"
exit 2
fi
done
done
-
name: Cleanup
if : ${{ matrix.mode == 'build-and-test' }}
run : |
docker rm --force --volumes ${CONTAINER}
docker volume rm --force ${VOLUME}
docker rmi --force ${IMAGE}:${TAG}
deploy:
runs-on: ubuntu-latest
needs:
- build
if: ${{ github.event_name != 'pull_request' }}
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Environment
run : |
echo IMAGE=$(echo ${{ env.IMAGE }} | tr '[:upper:]' '[:lower:]') >>$GITHUB_ENV
echo DOCKERHUB_IMAGE=$([ "${{ secrets.DOCKERHUB_USERNAME }}" != '' ] && [ "${{ secrets.DOCKERHUB_PASSWORD }}" != "" ] && echo "$IMAGE") >>$GITHUB_ENV
-
name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
${{ env.DOCKERHUB_IMAGE }}
ghcr.io/${{ env.IMAGE }}
tags: |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: amd64,arm64
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Login to DockerHub
uses: docker/login-action@v2
if: ${{ env.DOCKERHUB_IMAGE != '' }}
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
-
name: Login to GHCR
uses: docker/login-action@v2
with:
registry : ghcr.io
username : ${{ github.repository_owner }}
password : ${{ secrets.GITHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v3
with:
pull : true
push : true
platforms : linux/amd64,linux/arm64/v8
context : .
file : ./Dockerfile
tags : ${{ steps.meta.outputs.tags }}
labels : ${{ steps.meta.outputs.labels }}
cache-from: |
type=gha,scope=${{ github.workflow }}:linux/amd64
type=gha,scope=${{ github.workflow }}:linux/arm64/v8
28 changes: 28 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
os: linux
language: minimal
services:
- docker
# DOCKER_USERNAME/DOCKER_PASSWORD have been configured in Travis CI
# env:
before_install:
- echo "Before install"
before_script:
- docker pull overv/openstreetmap-tile-server || true
script:
- docker build --pull --cache-from overv/openstreetmap-tile-server --tag overv/openstreetmap-tile-server .
- docker volume create osm-data
- docker run --rm -v osm-data:/data/database/ overv/openstreetmap-tile-server import
- docker run --rm -v osm-data:/data/database/ -p 8080:80 -d overv/openstreetmap-tile-server run
- sleep 30
- make DOCKER_IMAGE=overv/openstreetmap-tile-server stop
after_script:
- docker images
after_success:
- if [[ "$TRAVIS_BRANCH" == "master" ]];
then
docker images ;
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin ;
docker push overv/openstreetmap-tile-server ;
fi
notifications:
email: true
298 changes: 149 additions & 149 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,174 +1,174 @@
FROM ubuntu:18.04
FROM ubuntu:22.04 AS compiler-common
ENV DEBIAN_FRONTEND=noninteractive
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates gnupg lsb-release locales \
wget curl \
git-core unzip unrar \
&& locale-gen $LANG && update-locale LANG=$LANG \
&& sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' \
&& wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& apt-get update && apt-get -y upgrade

###########################################################################################################

FROM compiler-common AS compiler-stylesheet
RUN cd ~ \
&& git clone --single-branch --branch v5.4.0 https://github.com/gravitystorm/openstreetmap-carto.git --depth 1 \
&& cd openstreetmap-carto \
&& sed -i 's/, "unifont Medium", "Unifont Upper Medium"//g' style/fonts.mss \
&& sed -i 's/"Noto Sans Tibetan Regular",//g' style/fonts.mss \
&& sed -i 's/"Noto Sans Tibetan Bold",//g' style/fonts.mss \
&& sed -i 's/Noto Sans Syriac Eastern Regular/Noto Sans Syriac Regular/g' style/fonts.mss \
&& rm -rf .git

###########################################################################################################

FROM compiler-common AS compiler-helper-script
RUN mkdir -p /home/renderer/src \
&& cd /home/renderer/src \
&& git clone https://github.com/zverik/regional \
&& cd regional \
&& rm -rf .git \
&& chmod u+x /home/renderer/src/regional/trim_osc.py

###########################################################################################################

FROM compiler-common AS final

# Based on
# https://switch2osm.org/manually-building-a-tile-server-18-04-lts/

# Set up environment
ENV TZ=UTC
# https://switch2osm.org/serving-tiles/manually-building-a-tile-server-18-04-lts/
ENV DEBIAN_FRONTEND=noninteractive
ENV AUTOVACUUM=on
ENV UPDATES=disabled
ENV REPLICATION_URL=https://planet.openstreetmap.org/replication/hour/
ENV MAX_INTERVAL_SECONDS=3600
ENV PG_VERSION 15

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# Install dependencies
RUN echo "deb [ allow-insecure=yes ] http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main" >> /etc/apt/sources.list.d/pgdg.list \
&& apt-get update \
&& apt-get install -y apt-transport-https ca-certificates \
&& apt-get install -y --no-install-recommends --allow-unauthenticated \
apache2 \
apache2-dev \
autoconf \
build-essential \
bzip2 \
cmake \
fonts-noto-cjk \
fonts-noto-hinted \
fonts-noto-unhinted \
clang \
gdal-bin \
git-core \
libagg-dev \
libboost-all-dev \
libbz2-dev \
libcairo-dev \
libcairomm-1.0-dev \
libexpat1-dev \
libfreetype6-dev \
libgdal-dev \
libgeos++-dev \
libgeos-dev \
libgeotiff-epsg \
libicu-dev \
liblua5.3-dev \
libmapnik-dev \
libpq-dev \
libproj-dev \
libprotobuf-c0-dev \
libtiff5-dev \
libtool \
libxml2-dev \
lua5.3 \
make \
mapnik-utils \
nodejs \
npm \
postgis \
postgresql-10 \
postgresql-10-postgis-2.5 \
postgresql-10-postgis-2.5-scripts \
postgresql-contrib-10 \
protobuf-c-compiler \
python-mapnik \
sudo \
tar \
ttf-unifont \
unzip \
wget \
zlib1g-dev \
osmosis \
osmium-tool \
cron \
python3-psycopg2 python3-shapely python3-lxml \
# Get packages
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
apache2 \
cron \
dateutils \
fonts-hanazono \
fonts-noto-cjk \
fonts-noto-hinted \
fonts-noto-unhinted \
fonts-unifont \
gnupg2 \
gdal-bin \
liblua5.3-dev \
lua5.3 \
mapnik-utils \
npm \
osm2pgsql \
osmium-tool \
osmosis \
postgresql-$PG_VERSION \
postgresql-$PG_VERSION-postgis-3 \
postgresql-$PG_VERSION-postgis-3-scripts \
postgis \
python-is-python3 \
python3-mapnik \
python3-lxml \
python3-psycopg2 \
python3-shapely \
python3-pip \
renderd \
sudo \
vim \
&& apt-get clean autoclean \
&& apt-get autoremove --yes \
&& rm -rf /var/lib/{apt,dpkg,cache,log}/

# Set up renderer user
RUN adduser --disabled-password --gecos "" renderer
USER renderer

# Install latest osm2pgsql
RUN mkdir /home/renderer/src
WORKDIR /home/renderer/src
RUN git clone https://github.com/openstreetmap/osm2pgsql.git
WORKDIR /home/renderer/src/osm2pgsql
RUN mkdir build
WORKDIR /home/renderer/src/osm2pgsql/build
RUN cmake .. \
&& make -j $(nproc)
USER root
RUN make install
RUN mkdir /nodes \
&& chown renderer:renderer /nodes
USER renderer

# Install and test Mapnik
RUN python -c 'import mapnik'

# Install mod_tile and renderd
WORKDIR /home/renderer/src
RUN git clone -b switch2osm https://github.com/SomeoneElseOSM/mod_tile.git
WORKDIR /home/renderer/src/mod_tile
RUN ./autogen.sh \
&& ./configure \
&& make -j $(nproc)
USER root
RUN make -j $(nproc) install \
&& make -j $(nproc) install-mod_tile \
&& ldconfig
USER renderer

# Configure stylesheet
WORKDIR /home/renderer/src
RUN git clone https://github.com/gravitystorm/openstreetmap-carto.git
WORKDIR /home/renderer/src/openstreetmap-carto
USER root
RUN npm install -g carto
USER renderer
RUN carto project.mml > mapnik.xml

# Load shapefiles
WORKDIR /home/renderer/src/openstreetmap-carto
RUN scripts/get-shapefiles.py

# Configure renderd
USER root
RUN sed -i 's/renderaccount/renderer/g' /usr/local/etc/renderd.conf \
&& sed -i 's/hot/tile/g' /usr/local/etc/renderd.conf
USER renderer

# Get Noto Emoji Regular font, despite it being deprecated by Google
RUN wget https://github.com/googlefonts/noto-emoji/blob/9a5261d871451f9b5183c93483cbd68ed916b1e9/fonts/NotoEmoji-Regular.ttf?raw=true --content-disposition -P /usr/share/fonts/

# For some reason this one is missing in the default packages
RUN wget https://github.com/stamen/terrain-classic/blob/master/fonts/unifont-Medium.ttf?raw=true --content-disposition -P /usr/share/fonts/

# Install python libraries
RUN pip3 install \
requests \
osmium \
pyyaml

# Install carto for stylesheet
RUN npm install -g carto@1.2.0

# Configure Apache
USER root
RUN mkdir /var/lib/mod_tile \
&& chown renderer /var/lib/mod_tile \
&& mkdir /var/run/renderd \
&& chown renderer /var/run/renderd
RUN echo "LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so" >> /etc/apache2/conf-available/mod_tile.conf \
&& echo "LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so" >> /etc/apache2/conf-available/mod_headers.conf \
&& a2enconf mod_tile && a2enconf mod_headers
&& echo "LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so" >> /etc/apache2/conf-available/mod_headers.conf \
&& a2enconf mod_tile && a2enconf mod_headers
COPY apache.conf /etc/apache2/sites-available/000-default.conf
COPY leaflet-demo.html /var/www/html/index.html
RUN ln -sf /dev/stdout /var/log/apache2/access.log \
&& ln -sf /dev/stderr /var/log/apache2/error.log
&& ln -sf /dev/stderr /var/log/apache2/error.log

# leaflet
COPY leaflet-demo.html /var/www/html/index.html
RUN cd /var/www/html/ \
&& wget https://github.com/Leaflet/Leaflet/releases/download/v1.8.0/leaflet.zip \
&& unzip leaflet.zip \
&& rm leaflet.zip

# Icon
RUN wget -O /var/www/html/favicon.ico https://www.openstreetmap.org/favicon.ico

# Copy update scripts
COPY openstreetmap-tiles-update-expire.sh /usr/bin/
RUN chmod +x /usr/bin/openstreetmap-tiles-update-expire.sh \
&& mkdir /var/log/tiles \
&& chmod a+rw /var/log/tiles \
&& ln -s /home/renderer/src/mod_tile/osmosis-db_replag /usr/bin/osmosis-db_replag \
&& echo "* * * * * renderer openstreetmap-tiles-update-expire.sh\n" >> /etc/crontab

# Configure PosgtreSQL
COPY postgresql.custom.conf.tmpl /etc/postgresql/10/main/
COPY postgresql.custom.conf.tmpl /etc/postgresql/$PG_VERSION/main/
RUN chown -R postgres:postgres /var/lib/postgresql \
&& chown postgres:postgres /etc/postgresql/10/main/postgresql.custom.conf.tmpl \
&& echo "\ninclude 'postgresql.custom.conf'" >> /etc/postgresql/10/main/postgresql.conf
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/10/main/pg_hba.conf \
&& echo "host all all ::/0 md5" >> /etc/postgresql/10/main/pg_hba.conf

# copy update scripts
COPY openstreetmap-tiles-update-expire /usr/bin/
RUN chmod +x /usr/bin/openstreetmap-tiles-update-expire \
&& mkdir /var/log/tiles \
&& chmod a+rw /var/log/tiles \
&& ln -s /home/renderer/src/mod_tile/osmosis-db_replag /usr/bin/osmosis-db_replag \
&& echo "* * * * * renderer openstreetmap-tiles-update-expire\n" >> /etc/crontab

# install trim_osc.py helper script
USER renderer
RUN cd ~/src \
&& git clone https://github.com/zverik/regional \
&& cd regional \
&& git checkout 612fe3e040d8bb70d2ab3b133f3b2cfc6c940520 \
&& chmod u+x ~/src/regional/trim_osc.py
&& chown postgres:postgres /etc/postgresql/$PG_VERSION/main/postgresql.custom.conf.tmpl \
&& echo "host all all 0.0.0.0/0 scram-sha-256" >> /etc/postgresql/$PG_VERSION/main/pg_hba.conf \
&& echo "host all all ::/0 scram-sha-256" >> /etc/postgresql/$PG_VERSION/main/pg_hba.conf

# Create volume directories
RUN mkdir -p /run/renderd/ \
&& mkdir -p /data/database/ \
&& mkdir -p /data/style/ \
&& mkdir -p /home/renderer/src/ \
&& chown -R renderer: /data/ \
&& chown -R renderer: /home/renderer/src/ \
&& chown -R renderer: /run/renderd \
&& mv /var/lib/postgresql/$PG_VERSION/main/ /data/database/postgres/ \
&& mv /var/cache/renderd/tiles/ /data/tiles/ \
&& chown -R renderer: /data/tiles \
&& ln -s /data/database/postgres /var/lib/postgresql/$PG_VERSION/main \
&& ln -s /data/style /home/renderer/src/openstreetmap-carto \
&& ln -s /data/tiles /var/cache/renderd/tiles \
;

RUN echo '[default] \n\
URI=/tile/ \n\
TILEDIR=/var/cache/renderd/tiles \n\
XML=/home/renderer/src/openstreetmap-carto/mapnik.xml \n\
HOST=localhost \n\
TILESIZE=256 \n\
MAXZOOM=20' >> /etc/renderd.conf \
&& sed -i 's,/usr/share/fonts/truetype,/usr/share/fonts,g' /etc/renderd.conf

# Install helper script
COPY --from=compiler-helper-script /home/renderer/src/regional /home/renderer/src/regional

COPY --from=compiler-stylesheet /root/openstreetmap-carto /home/renderer/src/openstreetmap-carto-backup

# Start running
USER root
COPY run.sh /
COPY indexes.sql /
ENTRYPOINT ["/run.sh"]
CMD []

EXPOSE 80 5432
201 changes: 201 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2019 Alexander Overvoorde

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
16 changes: 11 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
.PHONY: build push test

DOCKER_IMAGE=overv/openstreetmap-tile-server

build:
docker build -t overv/openstreetmap-tile-server .
docker build -t ${DOCKER_IMAGE} .

push: build
docker push overv/openstreetmap-tile-server:latest
docker push ${DOCKER_IMAGE}:latest

test: build
docker volume create openstreetmap-data
docker run -v openstreetmap-data:/var/lib/postgresql/10/main overv/openstreetmap-tile-server import
docker run -v openstreetmap-data:/var/lib/postgresql/10/main -p 80:80 -d overv/openstreetmap-tile-server run
docker volume create osm-data
docker run --rm -v osm-data:/data/database/ ${DOCKER_IMAGE} import
docker run --rm -v osm-data:/data/database/ -p 8080:80 -d ${DOCKER_IMAGE} run

stop:
docker rm -f `docker ps | grep '${DOCKER_IMAGE}' | awk '{ print $$1 }'` || true
docker volume rm -f osm-data
172 changes: 126 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,93 +1,174 @@
# openstreetmap-tile-server

This container allows you to easily set up an OpenStreetMap PNG tile server given a `.osm.pbf` file. It is based on the [latest Ubuntu 18.04 LTS guide](https://switch2osm.org/manually-building-a-tile-server-18-04-lts/) from [switch2osm.org](https://switch2osm.org/) and therefore uses the default OpenStreetMap style.
[![Build Status](https://travis-ci.org/Overv/openstreetmap-tile-server.svg?branch=master)](https://travis-ci.org/Overv/openstreetmap-tile-server) [![](https://images.microbadger.com/badges/image/overv/openstreetmap-tile-server.svg)](https://microbadger.com/images/overv/openstreetmap-tile-server "openstreetmap-tile-server")
[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/overv/openstreetmap-tile-server?label=docker%20image)](https://hub.docker.com/r/overv/openstreetmap-tile-server/tags)

This container allows you to easily set up an OpenStreetMap PNG tile server given a `.osm.pbf` file. It is based on the [latest Ubuntu 18.04 LTS guide](https://switch2osm.org/serving-tiles/manually-building-a-tile-server-18-04-lts/) from [switch2osm.org](https://switch2osm.org/) and therefore uses the default OpenStreetMap style.

## Setting up the server

First create a Docker volume to hold the PostgreSQL database that will contain the OpenStreetMap data:

docker volume create openstreetmap-data
docker volume create osm-data

Next, download an .osm.pbf extract from geofabrik.de for the region that you're interested in. You can then start importing it into PostgreSQL by running a container and mounting the file as `/data.osm.pbf`. For example:
Next, download an `.osm.pbf` extract from geofabrik.de for the region that you're interested in. You can then start importing it into PostgreSQL by running a container and mounting the file as `/data/region.osm.pbf`. For example:

```
docker run \
-v /absolute/path/to/luxembourg.osm.pbf:/data.osm.pbf \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v /absolute/path/to/luxembourg.osm.pbf:/data/region.osm.pbf \
-v osm-data:/data/database/ \
overv/openstreetmap-tile-server \
import
```

If the container exits without errors, then your data has been successfully imported and you are now ready to run the tile server.

Note that the import process requires an internet connection. The run process does not require an internet connection. If you want to run the openstreetmap-tile server on a computer that is isolated, you must first import on an internet connected computer, export the `osm-data` volume as a tarfile, and then restore the data volume on the target computer system.

Also when running on an isolated system, the default `index.html` from the container will not work, as it requires access to the web for the leaflet packages.

### Automatic updates (optional)

If your import is an extract of the planet and has polygonal bounds associated with it, like those from geofabrik.de, then it is possible to set your server up for automatic updates. Make sure to reference both the OSM file and the polygon file during the import process to facilitate this:
If your import is an extract of the planet and has polygonal bounds associated with it, like those from [geofabrik.de](https://download.geofabrik.de/), then it is possible to set your server up for automatic updates. Make sure to reference both the OSM file and the polygon file during the `import` process to facilitate this, and also include the `UPDATES=enabled` variable:

```
docker run \
-e UPDATES=enabled \
-v /absolute/path/to/luxembourg.osm.pbf:/data/region.osm.pbf \
-v /absolute/path/to/luxembourg.poly:/data/region.poly \
-v osm-data:/data/database/ \
overv/openstreetmap-tile-server \
import
```

Refer to the section *Automatic updating and tile expiry* to actually enable the updates while running the tile server.

Please note: If you're not importing the whole planet, then the `.poly` file is necessary to limit automatic updates to the relevant region.
Therefore, when you only have a `.osm.pbf` file but not a `.poly` file, you should not enable automatic updates.

### Letting the container download the file

It is also possible to let the container download files for you rather than mounting them in advance by using the `DOWNLOAD_PBF` and `DOWNLOAD_POLY` parameters:

```
docker run \
-e DOWNLOAD_PBF=https://download.geofabrik.de/europe/luxembourg-latest.osm.pbf \
-e DOWNLOAD_POLY=https://download.geofabrik.de/europe/luxembourg.poly \
-v osm-data:/data/database/ \
overv/openstreetmap-tile-server \
import
```

### Using an alternate style

By default the container will use openstreetmap-carto if it is not specified. However, you can modify the style at run-time. Be aware you need the style mounted at `run` AND `import` as the Lua script needs to be run:

```
docker run \
-v /absolute/path/to/luxembourg.osm.pbf:/data.osm.pbf \
-v /absolute/path/to/luxembourg.poly:/data.poly \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-e DOWNLOAD_PBF=https://download.geofabrik.de/europe/luxembourg-latest.osm.pbf \
-e DOWNLOAD_POLY=https://download.geofabrik.de/europe/luxembourg.poly \
-e NAME_LUA=sample.lua \
-e NAME_STYLE=test.style \
-e NAME_MML=project.mml \
-e NAME_SQL=test.sql \
-v /home/user/openstreetmap-carto-modified:/data/style/ \
-v osm-data:/data/database/ \
overv/openstreetmap-tile-server \
import
```

Refer to the section *Automatic updating and tile expiry* to actually enable the updates.
If you do not define the "NAME_*" variables, the script will default to those found in the openstreetmap-carto style.

Be sure to mount the volume during `run` with the same `-v /home/user/openstreetmap-carto-modified:/data/style/`

If you do not see the expected style upon `run` double check your paths as the style may not have been found at the directory specified. By default, `openstreetmap-carto` will be used if a style cannot be found

**Only openstreetmap-carto and styles like it, eg, ones with one lua script, one style, one mml, one SQL can be used**

## Running the server

Run the server like this:

```
docker run \
-p 80:80 \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-p 8080:80 \
-v osm-data:/data/database/ \
-d overv/openstreetmap-tile-server \
run
```

Your tiles will now be available at `http://localhost:80/tile/{z}/{x}/{y}.png`. The demo map in `leaflet-demo.html` will then be available on `http://localhost:80`. Note that it will initially take quite a bit of time to render the larger tiles for the first time.
Your tiles will now be available at `http://localhost:8080/tile/{z}/{x}/{y}.png`. The demo map in `leaflet-demo.html` will then be available on `http://localhost:8080`. Note that it will initially take quite a bit of time to render the larger tiles for the first time.

### Using Docker Compose

The `docker-compose.yml` file included with this repository shows how the aforementioned command can be used with Docker Compose to run your server.

### Preserving rendered tiles

Tiles that have already been rendered will be stored in `/var/lib/mod_tile`. To make sure that this data survives container restarts, you should create another volume for it:
Tiles that have already been rendered will be stored in `/data/tiles/`. To make sure that this data survives container restarts, you should create another volume for it:

```
docker volume create openstreetmap-rendered-tiles
docker volume create osm-tiles
docker run \
-p 80:80 \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v openstreetmap-rendered-tiles:/var/lib/mod_tile \
-p 8080:80 \
-v osm-data:/data/database/ \
-v osm-tiles:/data/tiles/ \
-d overv/openstreetmap-tile-server \
run
```

**If you do this, then make sure to also run the import with the `osm-tiles` volume to make sure that caching works properly across updates!**

### Enabling automatic updating (optional)

Given that you've specified both the OSM data and polygon as specified in the *Automatic updates* section during server setup, you can enable the updating process by setting the variable `UPDATES` to `enabled`:
Given that you've set up your import as described in the *Automatic updates* section during server setup, you can enable the updating process by setting the `UPDATES` variable while running your server as well:

```
docker run \
-p 80:80 \
-p 8080:80 \
-e REPLICATION_URL=https://planet.openstreetmap.org/replication/minute/ \
-e MAX_INTERVAL_SECONDS=60 \
-e UPDATES=enabled \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v openstreetmap-rendered-tiles:/var/lib/mod_tile \
-v osm-data:/data/database/ \
-v osm-tiles:/data/tiles/ \
-d overv/openstreetmap-tile-server \
run
```

This will enable a background process that automatically downloads changes from the OpenStreetMap server, filters them for the relevant region polygon you specified, updates the database and finally marks the affected tiles for rerendering.

### Tile expiration (optional)

Specify custom tile expiration settings to control which zoom level tiles are marked as expired when an update is performed. Tiles can be marked as expired in the cache (TOUCHFROM), but will still be served
until a new tile has been rendered, or deleted from the cache (DELETEFROM), so nothing will be served until a new tile has been rendered.

The example tile expiration values below are the default values.

```
docker run \
-p 8080:80 \
-e REPLICATION_URL=https://planet.openstreetmap.org/replication/minute/ \
-e MAX_INTERVAL_SECONDS=60 \
-e UPDATES=enabled \
-e EXPIRY_MINZOOM=13 \
-e EXPIRY_TOUCHFROM=13 \
-e EXPIRY_DELETEFROM=19 \
-e EXPIRY_MAXZOOM=20 \
-v osm-data:/data/database/ \
-v osm-tiles:/data/tiles/ \
-d overv/openstreetmap-tile-server \
run
```

### Cross-origin resource sharing

To enable the `Access-Control-Allow-Origin` header to be able to retrieve tiles from other domains, simply set the `ALLOW_CORS` variable to `1`:
To enable the `Access-Control-Allow-Origin` header to be able to retrieve tiles from other domains, simply set the `ALLOW_CORS` variable to `enabled`:

```
docker run \
-p 80:80 \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-e ALLOW_CORS=1 \
-p 8080:80 \
-v osm-data:/data/database/ \
-e ALLOW_CORS=enabled \
-d overv/openstreetmap-tile-server \
run
```
@@ -98,9 +179,9 @@ To connect to the PostgreSQL database inside the container, make sure to expose

```
docker run \
-p 80:80 \
-p 8080:80 \
-p 5432:5432 \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v osm-data:/data/database/ \
-d overv/openstreetmap-tile-server \
run
```
@@ -115,10 +196,10 @@ The default password is `renderer`, but it can be changed using the `PGPASSWORD`

```
docker run \
-p 80:80 \
-p 8080:80 \
-p 5432:5432 \
-e PGPASSWORD=secret \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v osm-data:/data/database/ \
-d overv/openstreetmap-tile-server \
run
```
@@ -132,9 +213,9 @@ Details for update procedure and invoked scripts can be found here [link](https:
The import and tile serving processes use 4 threads by default, but this number can be changed by setting the `THREADS` environment variable. For example:
```
docker run \
-p 80:80 \
-p 8080:80 \
-e THREADS=24 \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v osm-data:/data/database/ \
-d overv/openstreetmap-tile-server \
run
```
@@ -144,9 +225,9 @@ docker run \
The import and tile serving processes use 800 MB RAM cache by default, but this number can be changed by option -C. For example:
```
docker run \
-p 80:80 \
-p 8080:80 \
-e "OSM2PGSQL_EXTRA_ARGS=-C 4096" \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v osm-data:/data/database/ \
-d overv/openstreetmap-tile-server \
run
```
@@ -156,28 +237,27 @@ docker run \
The database use the autovacuum feature by default. This behavior can be changed with `AUTOVACUUM` environment variable. For example:
```
docker run \
-p 80:80 \
-p 8080:80 \
-e AUTOVACUUM=off \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-v osm-data:/data/database/ \
-d overv/openstreetmap-tile-server \
run
```

### Flat nodes
### FLAT_NODES

If you are planning to import the entire planet or you are running into memory errors then you may want to enable the `--flat-nodes` option for osm2pgsql. You can then use it during the import process as follows:

```
docker run \
-v /absolute/path/to/luxembourg.osm.pbf:/data.osm.pbf \
-v openstreetmap-nodes:/nodes \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-e "OSM2PGSQL_EXTRA_ARGS=--flat-nodes /nodes/flat_nodes.bin" \
-v /absolute/path/to/luxembourg.osm.pbf:/data/region.osm.pbf \
-v osm-data:/data/database/ \
-e "FLAT_NODES=enabled" \
overv/openstreetmap-tile-server \
import
```

>Note that if you use a folder other than `/nodes` then you must make sure that you manually set the owner to `renderer`!
Warning: enabling `FLAT_NOTES` together with `UPDATES` only works for entire planet imports (without a `.poly` file). Otherwise this will break the automatic update script. This is because trimming the differential updates to the specific regions currently isn't supported when using flat nodes.

### Benchmarks

@@ -189,14 +269,14 @@ You can find an example of the import performance to expect with this image on t

If you encounter such entries in the log, it will mean that the default shared memory limit (64 MB) is too low for the container and it should be raised:
```
renderd[121]: ERROR: failed to render TILE ajt 2 0-3 0-3
renderd[121]: ERROR: failed to render TILE default 2 0-3 0-3
renderd[121]: reason: Postgis Plugin: ERROR: could not resize shared memory segment "/PostgreSQL.790133961" to 12615680 bytes: ### No space left on device
```
To raise it use `--shm-size` parameter. For example:
```
docker run \
-p 80:80 \
-v openstreetmap-data:/var/lib/postgresql/10/main \
-p 8080:80 \
-v osm-data:/data/database/ \
--shm-size="192m" \
-d overv/openstreetmap-tile-server \
run
@@ -216,7 +296,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
5 changes: 3 additions & 2 deletions apache.conf
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<VirtualHost *:80>
ServerAdmin webmaster@localhost

LoadTileConfigFile /usr/local/etc/renderd.conf
ModTileRenderdSocketName /var/run/renderd/renderd.sock
AddTileConfig /tile/ default
LoadTileConfigFile /etc/renderd.conf
ModTileRenderdSocketName /run/renderd/renderd.sock
ModTileRequestTimeout 0
ModTileMissingRequestTimeout 30

14 changes: 14 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: '3'

services:
map:
image: overv/openstreetmap-tile-server
volumes:
- osm-data:/data/database/
ports:
- "8080:80"
command: "run"

volumes:
osm-data:
external: true
48 changes: 0 additions & 48 deletions indexes.sql

This file was deleted.

4 changes: 2 additions & 2 deletions leaflet-demo.html
Original file line number Diff line number Diff line change
@@ -6,8 +6,8 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
<link rel="stylesheet" href="leaflet.css"/>
<script src="leaflet.js"></script>

<style>
html, body, #map {
120 changes: 60 additions & 60 deletions openstreetmap-tiles-update-expire → openstreetmap-tiles-update-expire.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -3,14 +3,9 @@
set -e

#------------------------------------------------------------------------------
# AJT - change directory to mod_tile directory so that we can run replag
# Change directory to mod_tile directory so that we can run replag
# and other things directly from this script when run from cron.
# Change the actual location to wherever installed locally.
#------------------------------------------------------------------------------
export PATH=.:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ACCOUNT=renderer
cd /home/$ACCOUNT/src/mod_tile/

#------------------------------------------------------------------------------
# Extra OSM2PGSQL_OPTIONS may need setting if a tag transform script is
# in use. See https://github.com/SomeoneElseOSM/SomeoneElse-style and
@@ -19,24 +14,28 @@ cd /home/$ACCOUNT/src/mod_tile/
#------------------------------------------------------------------------------
OSMOSIS_BIN=osmosis
OSM2PGSQL_BIN=osm2pgsql
TRIM_BIN=/home/$ACCOUNT/src/regional/trim_osc.py
TRIM_BIN=/home/renderer/src/regional/trim_osc.py

DBNAME=gis
OSM2PGSQL_OPTIONS="-d $DBNAME -G --hstore ${OSM2PGSQL_EXTRA_ARGS} --tag-transform-script /home/renderer/src/openstreetmap-carto/openstreetmap-carto.lua --number-processes ${THREADS:-4} -S /home/renderer/src/openstreetmap-carto/openstreetmap-carto.style"
OSM2PGSQL_OPTIONS="-d $DBNAME -G --hstore --tag-transform-script /data/style/${NAME_LUA:-openstreetmap-carto.lua} --number-processes ${THREADS:-4} -S /data/style/${NAME_STYLE:-openstreetmap-carto.style} ${OSM2PGSQL_EXTRA_ARGS}"

# flat-nodes
if [ -f /data/database/flat_nodes.bin ]; then
OSM2PGSQL_OPTIONS="${OSM2PGSQL_OPTIONS} --flat-nodes /data/database/flat_nodes.bin"
fi

#------------------------------------------------------------------------------
# When using trim_osc.py we can define either a bounding box (such as this
# example for England and Wales) or a polygon.
# See https://github.com/zverik/regional .
# This area will usually correspond to the data originally loaded.
#------------------------------------------------------------------------------
TRIM_POLY_FILE="/var/lib/mod_tile/data.poly"
TRIM_POLY_FILE="/data/database/region.poly"
TRIM_OPTIONS="-d $DBNAME"
#TRIM_REGION_OPTIONS="-b -14.17 48.85 2.12 61.27"
TRIM_REGION_OPTIONS="-p $TRIM_POLY_FILE"

BASE_DIR=/var/lib/mod_tile
LOG_DIR=/var/log/tiles/
BASE_DIR=/data/database
LOG_DIR=/var/log/tiles
WORKOSM_DIR=$BASE_DIR/.osmosis

LOCK_FILE=/tmp/openstreetmap-update-expire-lock.txt
@@ -57,17 +56,17 @@ RUNLOG=$LOG_DIR/run.log
# Here we expire (but don't immediately rerender) tiles between zoom levels
# 13 and 18 and delete between 19 and 20.
#------------------------------------------------------------------------------
EXPIRY_MINZOOM=13
EXPIRY_TOUCHFROM=13
EXPIRY_DELETEFROM=19
EXPIRY_MAXZOOM=20
EXPIRY_MINZOOM=${EXPIRY_MINZOOM:="13"}
EXPIRY_TOUCHFROM=${EXPIRY_TOUCHFROM:="13"}
EXPIRY_DELETEFROM=${EXPIRY_DELETEFROM:="19"}
EXPIRY_MAXZOOM=${EXPIRY_MAXZOOM:="20"}

#*************************************************************************
#*************************************************************************

m_info()
{
echo "[`date +"%Y-%m-%d %H:%M:%S"`] $$ $1" >> "$RUNLOG"
echo "[`date +"%Y-%m-%d %H:%M:%S"`] $$ $1" >> "$RUNLOG"
}

m_error()
@@ -109,23 +108,29 @@ freelock()

if [ $# -eq 1 ] ; then
m_info "Initialising Osmosis replication system to $1"
mkdir $WORKOSM_DIR
$OSMOSIS_BIN --read-replication-interval-init workingDirectory=$WORKOSM_DIR 1>&2 2> "$OSMOSISLOG"
wget "http://replicate-sequences.osm.mazdermind.de/?"$1"T00:00:00Z" -O $WORKOSM_DIR/state.txt
mv $WORKOSM_DIR/configuration.txt $WORKOSM_DIR/configuration_orig.txt
sed "s!baseUrl=http://planet.openstreetmap.org/replication/minute!baseUrl=https://planet.openstreetmap.org/replication/minute!" $WORKOSM_DIR/configuration_orig.txt > $WORKOSM_DIR/configuration.txt
else
# make sure the lockfile is removed when we exit and then claim it
mkdir -p $WORKOSM_DIR
$OSMOSIS_BIN -v 5 --read-replication-interval-init workingDirectory=$WORKOSM_DIR 1>&2 2> "$OSMOSISLOG"

if ! getlock "$LOCK_FILE"; then
m_info "pid `cat $LOCK_FILE` still running"
exit 3
fi
init_seq=$(/usr/lib/python3-pyosmium/pyosmium-get-changes --server $REPLICATION_URL -D $1)
url_dynamicPart=$(printf %09d $init_seq | sed 's_\([0-9][0-9][0-9]\)\([0-9][0-9][0-9]\)\([0-9][0-9][0-9]\)_\1/\2/\3_')
wget $REPLICATION_URL/$url_dynamicPart.state.txt -O $WORKOSM_DIR/state.txt

if [ -e $STOP_FILE ]; then
m_info "stopped"
exit 2
fi
cat > $WORKOSM_DIR/configuration.txt <<- EOM
baseUrl=$REPLICATION_URL
maxInterval=$MAX_INTERVAL_SECONDS
EOM
fi

# make sure the lockfile is removed when we exit and then claim it
if ! getlock "$LOCK_FILE"; then
m_info "pid `cat $LOCK_FILE` still running"
exit 3
fi

if [ -e $STOP_FILE ]; then
m_info "stopped"
exit 2
fi

# -----------------------------------------------------------------------------
# Add disk space check from https://github.com/zverik/regional
@@ -137,16 +142,17 @@ if `python -c "import os, sys; st=os.statvfs('$BASE_DIR'); sys.exit(1 if st.f_ba
exit 4
fi

seq=`cat $WORKOSM_DIR/state.txt | grep sequenceNumber | cut -d= -f2`
seq=`cat $WORKOSM_DIR/state.txt | grep sequenceNumber | cut -d= -f2`
replag=`dateutils.ddiff $(cat $WORKOSM_DIR/state.txt | grep timestamp | cut -d "=" -f 2 | sed 's,\\\,,g') now`

m_ok "start import from seq-nr $seq, replag is `osmosis-db_replag -h`"
m_ok "start import from seq-nr $seq, replag is $replag"

/bin/cp $WORKOSM_DIR/state.txt $WORKOSM_DIR/last.state.txt
m_ok "downloading diff"
/bin/cp $WORKOSM_DIR/state.txt $WORKOSM_DIR/last.state.txt
m_ok "downloading diff"

if ! $OSMOSIS_BIN --read-replication-interval workingDirectory=$WORKOSM_DIR --simplify-change --write-xml-change $CHANGE_FILE 1>&2 2> "$OSMOSISLOG"; then
m_error "Osmosis error"
fi
if ! $OSMOSIS_BIN --read-replication-interval workingDirectory=$WORKOSM_DIR --simplify-change --write-xml-change $CHANGE_FILE 1>&2 2> "$OSMOSISLOG"; then
m_error "Osmosis error"
fi

if [ -f $TRIM_POLY_FILE ] ; then
m_ok "filtering diff"
@@ -156,51 +162,45 @@ if [ -f $TRIM_POLY_FILE ] ; then
else
m_ok "filtering diff skipped"
fi
m_ok "importing diff"
m_ok "importing diff"

#------------------------------------------------------------------------------
# Previously openstreetmap-tiles-update-expire tried to dirty layer
# "$EXPIRY_MAXZOOM - 3" (which was 15) only. Instead we write all expired
# tiles in range to the list (note the "-" rather than ":" in the "-e"
# parameter).
#------------------------------------------------------------------------------
if ! $OSM2PGSQL_BIN -a --slim -e$EXPIRY_MINZOOM-$EXPIRY_MAXZOOM $OSM2PGSQL_OPTIONS -o "$EXPIRY_FILE.$$" $CHANGE_FILE 1>&2 2> "$PGSQLLOG"; then
m_error "osm2pgsql error"
fi
if ! $OSM2PGSQL_BIN -a --slim -e$EXPIRY_MINZOOM-$EXPIRY_MAXZOOM $OSM2PGSQL_OPTIONS -o "$EXPIRY_FILE.$$" $CHANGE_FILE 1>&2 2> "$PGSQLLOG"; then
m_error "osm2pgsql error"
fi

#------------------------------------------------------------------------------
# The lockfile is normally removed before we expire tiles because that is
# something thatcan be done in parallel with further processing. In order to
# something that can be done in parallel with further processing. In order to
# avoid rework, if actually rerendering is done rather than just deleting or
# dirtying, it makes sense to move it lower down.
#------------------------------------------------------------------------------
# m_ok "Import complete; removing lock file"
# freelock "$LOCK_FILE"
# m_ok "Import complete; removing lock file"
# freelock "$LOCK_FILE"
m_ok "expiring tiles"

m_ok "expiring tiles"
#------------------------------------------------------------------------------
# When expiring tiles we need to define the style sheet if it's not "default".
# In this case it's "ajt".
# Previously all tiles on the "dirty" list between $EXPIRY_MINZOOM and
# $EXPIRY_MAXZOOM were dirtied. We currently re-render
# tiles >= $EXPIRY_MINZOOM and < $EXPIRY_DELETEFROM, expiry from 14 and
# delete >= $EXPIRY_DELETEFROM and <= $EXPIRY_MAXZOOM.
# The default path to renderd.sock is fixed.
#------------------------------------------------------------------------------
if ! render_expired --map=ajt --min-zoom=$EXPIRY_MINZOOM --touch-from=$EXPIRY_TOUCHFROM --delete-from=$EXPIRY_DELETEFROM --max-zoom=$EXPIRY_MAXZOOM -s /var/run/renderd/renderd.sock < "$EXPIRY_FILE.$$" 2>&1 | tail -8 >> "$EXPIRYLOG"; then
m_info "Expiry failed"
fi
if ! render_expired --map=default --min-zoom=$EXPIRY_MINZOOM --touch-from=$EXPIRY_TOUCHFROM --delete-from=$EXPIRY_DELETEFROM --max-zoom=$EXPIRY_MAXZOOM -s /run/renderd/renderd.sock < "$EXPIRY_FILE.$$" 2>&1 | tail -8 >> "$EXPIRYLOG"; then
m_info "Expiry failed"
fi

rm "$EXPIRY_FILE.$$"
rm "$EXPIRY_FILE.$$"

#------------------------------------------------------------------------------
# Only remove the lock file after expiry (if system is slow we want to delay
# the next import, not have multiple render_expired processes running)
#------------------------------------------------------------------------------
freelock "$LOCK_FILE"

m_ok "Done with import"

freelock "$LOCK_FILE"



fi
m_ok "Done with import"
2 changes: 1 addition & 1 deletion postgresql.custom.conf.tmpl
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

shared_buffers = 128MB
min_wal_size = 1GB
max_wal_size = 2GB
# max_wal_size = 2GB # Overridden below
maintenance_work_mem = 256MB

# Suggested settings from
152 changes: 124 additions & 28 deletions run.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/bin/bash

set -x
set -euo pipefail

function createPostgresConfig() {
cp /etc/postgresql/10/main/postgresql.custom.conf.tmpl /etc/postgresql/10/main/postgresql.custom.conf
sudo -u postgres echo "autovacuum = $AUTOVACUUM" >> /etc/postgresql/10/main/postgresql.custom.conf
cat /etc/postgresql/10/main/postgresql.custom.conf
cp /etc/postgresql/$PG_VERSION/main/postgresql.custom.conf.tmpl /etc/postgresql/$PG_VERSION/main/conf.d/postgresql.custom.conf
sudo -u postgres echo "autovacuum = $AUTOVACUUM" >> /etc/postgresql/$PG_VERSION/main/conf.d/postgresql.custom.conf
cat /etc/postgresql/$PG_VERSION/main/conf.d/postgresql.custom.conf
}

function setPostgresPassword() {
@@ -15,15 +15,40 @@ function setPostgresPassword() {
if [ "$#" -ne 1 ]; then
echo "usage: <import|run>"
echo "commands:"
echo " import: Set up the database and import /data.osm.pbf"
echo " import: Set up the database and import /data/region.osm.pbf"
echo " run: Runs Apache and renderd to serve tiles at /tile/{z}/{x}/{y}.png"
echo "environment variables:"
echo " THREADS: defines number of threads used for importing / tile rendering"
echo " UPDATES: consecutive updates (enabled/disabled)"
echo " NAME_LUA: name of .lua script to run as part of the style"
echo " NAME_STYLE: name of the .style to use"
echo " NAME_MML: name of the .mml file to render to mapnik.xml"
echo " NAME_SQL: name of the .sql file to use"
exit 1
fi

if [ "$1" = "import" ]; then
set -x

# if there is no custom style mounted, then use osm-carto
if [ ! "$(ls -A /data/style/)" ]; then
mv /home/renderer/src/openstreetmap-carto-backup/* /data/style/
fi

# carto build
if [ ! -f /data/style/mapnik.xml ]; then
cd /data/style/
carto ${NAME_MML:-project.mml} > mapnik.xml
fi

if [ "$1" == "import" ]; then
# Ensure that database directory is in right state
mkdir -p /data/database/postgres/
chown renderer: /data/database/
chown -R postgres: /var/lib/postgresql /data/database/postgres/
if [ ! -f /data/database/postgres/PG_VERSION ]; then
sudo -u postgres /usr/lib/postgresql/$PG_VERSION/bin/pg_ctl -D /data/database/postgres/ initdb -o "--locale C.UTF-8"
fi

# Initialize PostgreSQL
createPostgresConfig
service postgresql start
@@ -36,45 +61,103 @@ if [ "$1" = "import" ]; then
setPostgresPassword

# Download Luxembourg as sample if no data is provided
if [ ! -f /data.osm.pbf ]; then
echo "WARNING: No import file at /data.osm.pbf, so importing Luxembourg as example..."
wget -nv http://download.geofabrik.de/europe/luxembourg-latest.osm.pbf -O /data.osm.pbf
wget -nv http://download.geofabrik.de/europe/luxembourg.poly -O /data.poly
if [ ! -f /data/region.osm.pbf ] && [ -z "${DOWNLOAD_PBF:-}" ]; then
echo "WARNING: No import file at /data/region.osm.pbf, so importing Luxembourg as example..."
DOWNLOAD_PBF="https://download.geofabrik.de/europe/luxembourg-latest.osm.pbf"
DOWNLOAD_POLY="https://download.geofabrik.de/europe/luxembourg.poly"
fi

if [ -n "${DOWNLOAD_PBF:-}" ]; then
echo "INFO: Download PBF file: $DOWNLOAD_PBF"
wget ${WGET_ARGS:-} "$DOWNLOAD_PBF" -O /data/region.osm.pbf
if [ -n "${DOWNLOAD_POLY:-}" ]; then
echo "INFO: Download PBF-POLY file: $DOWNLOAD_POLY"
wget ${WGET_ARGS:-} "$DOWNLOAD_POLY" -O /data/region.poly
fi
fi

# determine and set osmosis_replication_timestamp (for consecutive updates)
osmium fileinfo /data.osm.pbf > /var/lib/mod_tile/data.osm.pbf.info
osmium fileinfo /data.osm.pbf | grep 'osmosis_replication_timestamp=' | cut -b35-44 > /var/lib/mod_tile/replication_timestamp.txt
REPLICATION_TIMESTAMP=$(cat /var/lib/mod_tile/replication_timestamp.txt)
if [ "${UPDATES:-}" == "enabled" ] || [ "${UPDATES:-}" == "1" ]; then
# determine and set osmosis_replication_timestamp (for consecutive updates)
REPLICATION_TIMESTAMP=`osmium fileinfo -g header.option.osmosis_replication_timestamp /data/region.osm.pbf`

# initial setup of osmosis workspace (for consecutive updates)
sudo -u renderer openstreetmap-tiles-update-expire $REPLICATION_TIMESTAMP
# initial setup of osmosis workspace (for consecutive updates)
sudo -E -u renderer openstreetmap-tiles-update-expire.sh $REPLICATION_TIMESTAMP
fi

# copy polygon file if available
if [ -f /data.poly ]; then
sudo -u renderer cp /data.poly /var/lib/mod_tile/data.poly
if [ -f /data/region.poly ]; then
cp /data/region.poly /data/database/region.poly
chown renderer: /data/database/region.poly
fi

# flat-nodes
if [ "${FLAT_NODES:-}" == "enabled" ] || [ "${FLAT_NODES:-}" == "1" ]; then
OSM2PGSQL_EXTRA_ARGS="${OSM2PGSQL_EXTRA_ARGS:-} --flat-nodes /data/database/flat_nodes.bin"
fi

# Import data
sudo -u renderer osm2pgsql -d gis --create --slim -G --hstore --tag-transform-script /home/renderer/src/openstreetmap-carto/openstreetmap-carto.lua --number-processes ${THREADS:-4} ${OSM2PGSQL_EXTRA_ARGS} -S /home/renderer/src/openstreetmap-carto/openstreetmap-carto.style /data.osm.pbf
sudo -u renderer osm2pgsql -d gis --create --slim -G --hstore \
--tag-transform-script /data/style/${NAME_LUA:-openstreetmap-carto.lua} \
--number-processes ${THREADS:-4} \
-S /data/style/${NAME_STYLE:-openstreetmap-carto.style} \
/data/region.osm.pbf \
${OSM2PGSQL_EXTRA_ARGS:-} \
;

# old flat-nodes dir
if [ -f /nodes/flat_nodes.bin ] && ! [ -f /data/database/flat_nodes.bin ]; then
mv /nodes/flat_nodes.bin /data/database/flat_nodes.bin
chown renderer: /data/database/flat_nodes.bin
fi

# Create indexes
sudo -u postgres psql -d gis -f indexes.sql
if [ -f /data/style/${NAME_SQL:-indexes.sql} ]; then
sudo -u postgres psql -d gis -f /data/style/${NAME_SQL:-indexes.sql}
fi

#Import external data
chown -R renderer: /home/renderer/src/ /data/style/
if [ -f /data/style/scripts/get-external-data.py ] && [ -f /data/style/external-data.yml ]; then
sudo -E -u renderer python3 /data/style/scripts/get-external-data.py -c /data/style/external-data.yml -D /data/style/data
fi

# Register that data has changed for mod_tile caching purposes
sudo -u renderer touch /data/database/planet-import-complete

service postgresql stop

exit 0
fi

if [ "$1" = "run" ]; then
if [ "$1" == "run" ]; then
# Clean /tmp
rm -rf /tmp/*

# migrate old files
if [ -f /data/database/PG_VERSION ] && ! [ -d /data/database/postgres/ ]; then
mkdir /data/database/postgres/
mv /data/database/* /data/database/postgres/
fi
if [ -f /nodes/flat_nodes.bin ] && ! [ -f /data/database/flat_nodes.bin ]; then
mv /nodes/flat_nodes.bin /data/database/flat_nodes.bin
fi
if [ -f /data/tiles/data.poly ] && ! [ -f /data/database/region.poly ]; then
mv /data/tiles/data.poly /data/database/region.poly
fi

# sync planet-import-complete file
if [ -f /data/tiles/planet-import-complete ] && ! [ -f /data/database/planet-import-complete ]; then
cp /data/tiles/planet-import-complete /data/database/planet-import-complete
fi
if ! [ -f /data/tiles/planet-import-complete ] && [ -f /data/database/planet-import-complete ]; then
cp /data/database/planet-import-complete /data/tiles/planet-import-complete
fi

# Fix postgres data privileges
chown postgres:postgres /var/lib/postgresql -R
chown -R postgres: /var/lib/postgresql/ /data/database/postgres/

# Configure Apache CORS
if [ "$ALLOW_CORS" == "1" ]; then
if [ "${ALLOW_CORS:-}" == "enabled" ] || [ "${ALLOW_CORS:-}" == "1" ]; then
echo "export APACHE_ARGUMENTS='-D ALLOW_CORS'" >> /etc/apache2/envvars
fi

@@ -85,15 +168,28 @@ if [ "$1" = "run" ]; then
setPostgresPassword

# Configure renderd threads
sed -i -E "s/num_threads=[0-9]+/num_threads=${THREADS:-4}/g" /usr/local/etc/renderd.conf
sed -i -E "s/num_threads=[0-9]+/num_threads=${THREADS:-4}/g" /etc/renderd.conf

# start cron job to trigger consecutive updates
if [ "$UPDATES" = "enabled" ]; then
/etc/init.d/cron start
if [ "${UPDATES:-}" == "enabled" ] || [ "${UPDATES:-}" == "1" ]; then
/etc/init.d/cron start
sudo -u renderer touch /var/log/tiles/run.log; tail -f /var/log/tiles/run.log >> /proc/1/fd/1 &
sudo -u renderer touch /var/log/tiles/osmosis.log; tail -f /var/log/tiles/osmosis.log >> /proc/1/fd/1 &
sudo -u renderer touch /var/log/tiles/expiry.log; tail -f /var/log/tiles/expiry.log >> /proc/1/fd/1 &
sudo -u renderer touch /var/log/tiles/osm2pgsql.log; tail -f /var/log/tiles/osm2pgsql.log >> /proc/1/fd/1 &

fi

# Run
sudo -u renderer renderd -f -c /usr/local/etc/renderd.conf
# Run while handling docker stop's SIGTERM
stop_handler() {
kill -TERM "$child"
}
trap stop_handler SIGTERM

sudo -u renderer renderd -f -c /etc/renderd.conf &
child=$!
wait "$child"

service postgresql stop

exit 0