The Angular frontend for Tailormap.
Install Docker and Docker Compose (version 2) and run:
docker compose up -d
This runs Tailormap on http://localhost:8080/ together with a PostgreSQL container to store configuration and a Solr container for full text search indexing. The port (and other options) can
be changed by copying .env.template
to .env
and changing the variables (or use the --env-file <file>
argument). Tailormap will only
accept connections from the loopback interface, unless you set SERVER_ADDRESS=0.0.0.0
in the env-file.
Remove the Tailormap stack using docker compose down
(add -v
to remove the volume with the database).
By default, the latest development Docker image will be used (tagged with snapshot
). This is published automatically by a GitHub Action on
every change to the main
branch, so this might be an unstable version. To use the latest (stable) released version, set the VERSION
variable to latest
before running. To update a running stack after a new version is released, run docker compose
with the pull
and
up
commands but check the release notes beforehand because it may contain important information about upgrading to a new version.
The Docker Compose stack includes a PostgreSQL database, but you can also run just the Tailormap container with an existing PostgreSQL
database. The default database name, user and password are all tailormap
:
createuser tailormap
createdb tailormap --owner=tailormap
psql tailormap -c "alter role tailormap password 'tailormap'"
docker run -it --rm --network=host --name tailormap ghcr.io/tailormap/tailormap:snapshot
Specify the following command line parameters with docker run
to change the database connection settings:
-e SPRING_DATASOURCE_URL=jdbc:postgresql://host:port/database
-e SPRING_DATASOURCE_USERNAME=user
-e SPRING_DATASOURCE_PASSWORD=pass
-e SERVER_ADDRESS=0.0.0.0
if you want Tailormap to listen on all interfaces instead of localhost
If your database is running on localhost using --network=host
is recommended (you can try using the hostname host.docker.internal
but
that may not always work). If your database is on another host you can specify --publish 8080:8080
instead of --network=host
. Of course,
you need to specify SPRING_DATASOURCE_URL
with the database hostname.
To log in to the admin interface go to http://localhost:8080/admin/.
When starting up for the first time a password will be randomly generated for the admin account. This password is printed to the logs of
the tailormap
container. You can see the password with:
docker compose logs tailormap
Look for the output containing:
tailormap-server | INFO 1 --- [ main] n.b.t.api.security.AdminAccountCreator :
tailormap-server |
tailormap-server | +------ ------+
tailormap-server | | +-----------------------------------------+ |
tailormap-server | | | ______ _ __ | |
tailormap-server | | | /_ __/__ _(_) /__ ______ _ ___ ____ | |
tailormap-server | | | / / / _ `/ / / _ \/ __/ ' \/ _ `/ _ \ | |
tailormap-server | | | /_/ \_,_/_/_/\___/_/ /_/_/_/\_,_/ .__/ | |
tailormap-server | | | /_/ | |
tailormap-server | | +-----------------------------------------+ |
tailormap-server | +------ ------+
tailormap-server |
tailormap-server | *** Use this account to access the admin:
tailormap-server |
tailormap-server | *** Username: tm-admin
tailormap-server | *** Password: ***********
If you ever forget the admin password but do not want to re-initialize the database, reset the password with:
HASH=`docker run --rm rocko/spring-boot-cli-docker spring encodepassword [newpassword]`
docker compose exec --user postgres db \
psql tailormap -U tailormap -c "update users set password = '${HASH}' where username = 'tm-admin'"
Resetting a password in this way will securely hash the password (depending on your shell the space before the first command will also
prevent the password from remaining in your shell history). If you're in a bind you can also set a plain text password with a value like
{noop}changeme
but it is recommended you change it immediately so it will be hashed securely using bcrypt.
To run Tailormap in production, you need to put it behind a reverse proxy that handles SSL termination.
Copy the .env.template
file to .env
and change the HOST
variable to the hostname Tailormap will be running on. Tailormap must run on
the /
path.
If you're using a reverse proxy without Docker just reverse proxy 127.0.0.1:8080 (this port binding is added in
docker-compose.override.yml
). The ports can be changed in an .env
file or by using another override file in COMPOSE_FILE
.
Example Apache configuration:
<VirtualHost *:443>
ServerName myhost.com
...
RequestHeader set X-Forwarded-Proto https
ProxyPreserveHost On
ProxyTimeout 600
# If you're also running other webapps such as geoserver, add ProxyPass lines before this line
ProxyPass / http://localhost:8080/
</VirtualHost>
It's a good idea to use Traefik as a reverse proxy because it can be automatically configured by Docker labels and can automatically request
Let's Encrypt certificates. Add docker-compose.traefik.yml
to COMPOSE_FILE
in the .env
file. See the file for details.
You can also run multiple Tailormap stacks on one host, even running different versions. Just specify another .env
file with a
different HOST
and COMPOSE_PROJECT_NAME
and specify it using the --env-file <env>
option. Note that if you use the latest
tag and
pull a new image, stacks will only run with the updated version after recreating the containers with docker compose up
. It might be
advisable to only set VERSION
to a specific version and use a tool such
as renovatebot to automatically update your configuration when a new version is
released.
See the tailormap-starter and tailormap-hello-world repositories which demonstrate how you can add functionality to Tailormap by developing it in a separate repository.
General GIS viewer functionality that fits in most viewers can be added in this repository by creating a pull request. If you add functionality that is very specific to your use case, or is not open source it is best to develop it in a separate repository and publish it as a NPM package with an Angular library.
To build a Tailormap container image which includes extra functionality, you can build a Docker image in your own repository and use that
with the Docker Compose stack in this repository by setting the TAILORMAP_IMAGE
variable to the Docker image to use. If you want to easily
build an image which includes multiple Angular libraries (for instance several extra libraries from different repositories), it is possible
to specify Angular libraries to add when building by setting the ADD_NG_LIBRARIES
variable (see the comments in .env.template
). Set the
TAILORMAP_IMAGE
to a custom name and run docker compose build
. It will use the Dockerfile and base Angular app from the
tailormap-starter
repository. For now this will use the published release version of tailormap-viewer that is referenced in the
package.json in the tailormap-starter repositories' main
branch at build time. In the future we aim to have this also use the tailormap-viewer version in the VERSION
variable by creating the base
app in a schematic from a Dockerfile only.
You can push the built custom Tailormap image to a registry or build it on the host to deploy.
For extra backend functionality it is recommended to create another Docker (micro)service instead of customizing tailormap-api. If needed,
you can call the tailormap-api backend as a user proxying session cookie and XSRF tokens. If the service requires admin access (for instance
to get feature source database details) we'd need to add an API authentication method for internal services so an extra service can call the
Spring Data REST API just like the administration interface. It is not recommended to connect to the Tailormap configuration database
directly from an additional service, although it might be ok to store data in a separate PostgreSQL schema or database in the same db
PostgreSQL service to avoid an extra database service.
It is explicitly allowed to create a custom Tailormap with closed source (paid) additions.
All used open source components (frontend and backend) have licenses that allow linking with closed source. There are no components licensed under the GPL or Affero GPL. See 3rdpartylicenses.txt for all frontend licenses and here for the licenses used in the backend dependencies.
If you extend the Tailormap frontend with closed source frontend functionality, the minified source will of course be delivered to clients' browsers, even before logging in. By default, source maps (which provide the original source code to developer tools included in browsers) are generated but are not served to clients, unless you set the SOURCE_MAP_AUTH environment variable with a username:password. When opening DevTools in Chrome, you will get a HTTP Basic popup for this account in order to load source maps. At the moment the developer tools in Firefox do not support HTTP Basic authentication for source maps. Note that minified (or even obfuscated) sources are not security. Confidential algorithms should be implemented server-side, and copying of frontend code is prevented by copyright and licensing.
To allow public access to source maps without authentication for ease of debugging, set the SOURCE_MAP_AUTH
environment variable to public
.
Tailormap creates database tables automatically. To start fresh, bring the stack down removing the database volume with
docker compose down -v
and restart Tailormap.
The configuration database needs to be backed up if you don't want to lose your configuration. The backup procedure isn't any different when
using containers from using PostgreSQL without them: use pg_dump
and do not back up just the files in /var/lib/postgresql/
, tempting as
that may be.
Creating a backup:
docker compose exec --user postgres db pg_dump -U tailormap tailormap > tailormap.sql
The restore procedure: drop the database, recreate it and load the backup. You may need to stop the tailormap
container to close any
connections.
docker compose stop tailormap
docker compose exec --user postgres db dropdb -U tailormap tailormap
docker compose exec --user postgres db createdb -U tailormap --owner=tailormap tailormap
cat tailormap.sql | docker compose exec -T --user postgres db psql -U tailormap tailormap
docker compose start tailormap
The Docker image for the configuration database is kept up to date with the latest PostgreSQL releases and can move to a new major version
with a new Tailormap release. In this case the database must be dumped and restored (see above). Take note of the major PostgreSQL version
in the release notes whether this is required. You will see an error opening Tailormap and see errors about the PostgreSQL version in the
logs of the db
container if you don't do this upgrade. If you did not have a recent backup ready, downgrade the image used by the db
container to the previous major version and backup the database as normal and restore on the newer major version.
The following is required for successfully building Tailormap:
- NodeJS 22.x (https://nodejs.org/en/); the current LTS
- npm 10 (included with NodeJS)
Run npm install
and npm run start
to start a dev server, or npm run start-nl
for the Dutch localized version. Navigate
to http://localhost:4200/. Run npm run start-admin
to start the admin interface on http://localhost:4201/. The app will automatically
reload if you change any of the source files.
To bind the port of the PostgreSQL database of the Docker Compose stack, add docker-compose.db-port.yml
to the COMPOSE_FILE
environment
variable in the .env
file when running docker compose up
, see above.
You can connect to the PostgreSQL database with psql -h localhost -U tailormap tailormap
with the default password tailormap
.
The port PostgreSQL listens on can be customized using the DB_PORT
variable in the .env
file.
The Spring Boot backend middleware is developed in a separate tailormap-api repository.
When running a dev server, the tailormap-api is reverse proxied on the http://localhost:4200/api
path from https://snapshot.tailormap.nl/api
which runs the latest snapshot
, so you don't even need to run the backend and database locally.
If you want to change the viewer configuration you of course need to log in to the admin! Just run Tailormap locally as described above and
set the PROXY_USE_LOCALHOST
environment variable:
PROXY_USE_LOCALHOST=true npm run start
There is a Swagger UI for the API on http://localhost:8080/swagger-ui/.
If you want to make some changes to the backend source code, only start the db
container from this stack and run the backend from the tailormap-api
repository as described in the README in that project.
Run npm run ng -- generate component components/[name] --project core|map
to generate a new component. You can also
use ng generate directive|pipe|service|class|guard|interface|enum|module
.
To create a new service which uses the HttpClient to make API calls run
npm run ng -- generate service services/[name] --project core|map --http-service
This creates a service with a HttpClient injected and adjusted spec file to test HTTP calls.
Please use kebab-case
for filenames and PascalCase
for class names.
Run npm run test
to execute the unit tests via Jest.
Run npx @cyclonedx/cyclonedx-npm --output-file bom.xml --mc-type application --output-format XML
to create a CycloneDX BOM file.
After you've made your some changes to the source you can build your own Docker image using the following command. You may want to remove
the node_modules
and .angular
directories to reduce the Docker build context size.
docker build -t ghcr.io/tailormap/tailormap:snapshot .
or
docker compose build
The Dockerfile in this repository uses the ghcr.io/tailormap/tailormap-api
base image with the webserver and backend and adds the Angular
frontend bundles to it. To use your own base image with modifications, run mvn install
in the tailormap-api
repository to build the base image before building the tailormap
image.
You can also add the argument --build-arg API_VERSION=snapshot
to set the tag of the ghcr.io/tailormap/tailormap-api
base image to use.
Use the commands below to build and push the cross-platform Docker images to the GitHub container registry. See the Docker documentation for more information about building multi-platform images and the docker buildx build and docker buildx create commands.
# create a container for x-platform builds (only needed once)
docker buildx create --use --name tailormap-builder --platform linux/arm64,linux/arm/v8
# or activate an existing container
docker buildx use tailormap-builder
# install necessary QEMU platform architectures
docker run --privileged --rm tonistiigi/binfmt --install all
# set version of the docker image and base ref. This will also be the reported version of the application
export VERSION=snapshot
export BASE_HREF=/
# for pushing to the GitHub container registry, you need to be logged in with docker login
docker buildx build --pull --build-arg VERSION=${VERSION} --build-arg API_VERSION=${VERSION} --build-arg BASE_HREF=${BASE_HREF} \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/tailormap/tailormap:${VERSION} . \
--push
# leave the buildx context
docker buildx use default