Manual deployment¶
This guide describes the installation of a installation of OpenBike with its components from source. In this setup, everything is being run on one host.
Warning
Even though we try to make it straightforward to run OpenBike, it still requires some Linux experience to get it right.
We wrote this guide based on our setup on the Linux distribution Ubuntu 18.04 but it should work very similar on other modern distributions, especially on all systemd-based ones.
Requirements¶
Please set up the following systems beforehand, we’ll not explain them here in detail (but see these links for external installation guides):
A HTTP reverse proxy, e.g. nginx, Apache or Caddy to allow HTTPS connections
A PostgreSQL 9.5+ database server with PostGIS
Redis, as a message broker for the asynchronous workers
We also recommend that you use a firewall, although this is not a OpenBike-specific recommendation. If you’re new to Linux and firewalls, we recommend that you start with ufw.
Note
Please, do not run OpenBike without HTTPS encryption. You’ll handle user accounts and thanks to Let’s Encrypt SSL certificates can be obtained for free these days. We also do not provide support for HTTP-only installations except for development purposes.
Unix user¶
As we do not want to run the different OpenBike services as root, we first create a new unprivileged user:
# adduser openbike --system --disabled-password --shell /bin/bash --home /srv/openbike
In this guide, all code lines prepended with a #
symbol are commands that you need to execute on your server as
root
user (e.g. using sudo
); all lines prepended with a $
symbol should be run by the unprivileged user.
Database¶
Having the database server installed, we still need a database and a database user. We can create these with any kind of database managing tool or directly on our database’s shell. For PostgreSQL, we would do:
# sudo -u postgres createuser openbike
# sudo -u postgres createdb -O openbike openbike
Additionally, GIS extensions must be enabled. For PostgreSQL with PostGIS, use:
# sudo -u postgres psql -d openbike -c "CREATE EXTENSION postgis;"
Package dependencies¶
To build and run cykel, you will need the following packages:
# apt install git build-essential python3 python3-dev python3-venv python3-pip libpq-dev libgdal-dev
For nodejs, we recommend using the nodesource PPA to get the latest LTS version. Look into https://github.com/nodesource/distributions#deb for instructions to add the repository. A short, slightly dangerous way is here:
# curl -sL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
# apt install -y nodejs
Install cykel from source¶
Now we will install cykel. The following steps are to be executed as the openbike
user. Before we
actually install cykel, we will create a virtual environment to isolate the python packages from your global
python installation:
$ python3 -m venv /srv/openbike/venv
$ source /srv/openbike/venv/bin/activate
(venv)$ pip3 install -U pip wheel
We now clone the cykel source and install the dependencies:
(venv)$ git clone https://github.com/transportkollektiv/cykel.git /srv/openbike/cykel
(venv)$ cd /srv/openbike/cykel
(venv)$ pip3 install -U -r requirements.txt
(venv)$ pip3 install -U gunicorn
Configure cykel¶
For configuration normally settings.py
is used. cykel also uses this file, but many important settings are set by environment variables. These can reside in your environment, or in an .env
file in the cykel/
directory (next to the settings.py
file), that gets automatically loaded.
The following is the baseline of environment variables you have to set:
SECRET_KEY=a1b2c3d4e5f6examplechangeit7g8h9
DEBUG=0
DATABASE_URL=postgis:///openbike
REDIS_URL=redis://localhost:6379/0
ALLOWED_HOSTS=api.dev.bike
UI_SITE_URL=https://dev.bike
CORS_ORIGIN_WHITELIST=https://dev.bike
USE_X_FORWARDED_PROTO=true
SECRET_KEY
The Secret Key is a django feature, used for cryptographic signing for sessions, messages, and more. Generate a nice long random string for this key. (You could use
openssl rand -hex 32
for that)DEBUG
Set to 1 to enable DEBUG output, or 0 to disable. This should be really only used for development and troubleshooting.
Warning
Never deploy a site into production with DEBUG turned on.
DATABASE_URL
Here you have configure the access to your database in a format supported by dj-database-url. If your PostgreSQL with PostGIS is residing on the same host, try
postgis:///openbike
For user/password auth on another host, usepostgis://username:password@host/database
REDIS_URL
The URL which contains the host and port where your redis-server is running at. The used format is
redis://[:password@]host[:port][/db-number]
, if redis is running on the same host, tryredis://localhost:6379/0
.ALLOWED_HOSTS
Comma seperated list of hostnames, where cykel is reachable at.
UI_SITE_URL
The full URL to your deployment of voorwiel. This is used to redirect the user after the login. Do not use a trailing slash here!
CORS_ORIGIN_WHITELIST
CORS origins to allow, i.e. the frontend URL (with scheme, without path)
USE_X_FORWARDED_PROTO
If you’re serving cykel behind a reverse proxy (like in this manual), set this to
true
, so theX-Forwarded-Proto
header gets interpreted and URLs are built correctly with https.Prepare cykel for first run¶
After the configuration we can finally compile static files and create the database structure:
(venv)$ python3 manage.py migrate (venv)$ python3 manage.py collectstatic
Start cykel as a service¶
We recommend starting cykel using systemd to make sure it runs correctly after a reboot. Create a file named
/etc/systemd/system/cykel.service
with the following content:[Unit] Description=gunicorn daemon for cykel After=network.target [Service] User=openbike Group=nogroup PIDFile=/run/openbike/cykel.pid WorkingDirectory=/srv/openbike/cykel ExecStart=/srv/openbike/venv/bin/gunicorn cykel.wsgi \ --name cykel \ --pid /run/openbike/cykel.pid \ --bind 127.0.0.1:8000 --access-logfile - ExecReload=/bin/kill -s HUP $MAINPID KillSignal=SIGTERM PrivateTmp=true Restart=on-failure [Install] WantedBy=multi-user.target
This runs an gunicorn application server on localhost on port
8000
. Requests are made to this port by our reverse proxy, which gets configured below.The referenced
/run/openbike/cykel.pid
pid file resides in a directory that does not exist yet. For these temporary directories, systemd brought us the tmpfiles mechanism. To create this directory, we create the file/etc/tmpfiles.d/openbike.conf
with the following contents:# Directory for openbike pid files d /run/openbike 0755 openbike nogroup - -
To create the directory right now (without waiting for your next reboot) run:
# systemd-tmpfiles --create openbike.conf
You can now run the following commands to enable and start the service:
# systemctl daemon-reload # systemctl enable cykel # systemctl start cykel
Run cykel worker as a service¶
Some tasks cykel is doing are best run in the background. For this, we’re using celery, which provides us seperate processes to run these tasks without impacting the api and administration interfaces.
To keep a worker running in the background, create a file named
/etc/systemd/system/cykel-worker.service
with the following content:[Unit] Description=cykel background worker After=network.target redis-server.service [Service] User=openbike Group=nogroup WorkingDirectory=/srv/openbike/cykel ExecStart=/srv/openbike/venv/bin/celery -A cykel worker -l INFO -B Restart=on-failure [Install] WantedBy=multi-user.target
You can now again run the following commands to enable and start the background service:
# systemctl daemon-reload # systemctl enable cykel-worker # systemctl start cykel-worker
Get voorwiel source¶
To let people rent the bikes, you need a visual interface. voorwiel is the default UI for cykel. The following steps are again executed as the
openbike
user:$ git clone https://github.com/transportkollektiv/voorwiel.git /srv/openbike/voorwiel $ cd /srv/openbike/voorwiel $ npm ci
Configure voorwiel¶
The configuration of voorwiel currently still happens before the build process. The configuration happens in the
config/config.production.js
file:var ENV = "production"; var TITLE = "dev.bike - open bikesharing for everyone"; var NAME = "dev.bike"; var SYSTEM_URL = "https://api.dev.bike"; var API_ROOT = SYSTEM_URL + "/api"; var GBFS_URL = SYSTEM_URL + "/gbfs/gbfs.json"; var DEFAULT_LOCATION = [48.3984, 9.9908]; var DEFAULT_ZOOM = 15; var I18N_MESSAGE_OVERRIDE = {}; var SUPPORT_TYPE; var SUPPORT_URL; var SENTRY_DSN;
TITLE
Title of the voorwiel application page
NAME
Name of your bikesharing system
SYSTEM_URL
The URL to your cykel instance
DEFAULT_LOCATION
Latitude and Longitude for the center of the map
DEFAULT_ZOOM
Zoom level for the default view of the map
Deploy voorwiel¶
voorwiel and its configuration is built into a big bundle of javascript. Run the following command to build voorwiel and drop the result into the
dist
folder:$ NODE_ENV=production NPM_CONFIG_PRODUCTION=true npm run build
Get skoetsel source¶
To help yourself operating the sharing, having an easier look at the bikes for maintenance etc, skoetsel is the UI for operators and maintenance staff. The following steps are again executed as the
openbike
user:$ git clone https://github.com/transportkollektiv/skoetsel.git /srv/openbike/skoetsel $ cd /srv/openbike/skoetsel $ npm ci
Configure and deploy skoetsel¶
skoetsel is currently in a very beta state of development. The only configuration change you have to do, is to set the URL to the api.
$ export API_URL=https://api.dev.bike $ npm run generate
Reverse Proxy (nginx)¶
The following snippet is an example on how to configure a nginx proxy for cykel, skoetsel and voorwiel:
server { server_name api.dev.bike; client_max_body_size 50M; location /static/ { alias /srv/openbike/cykel/public/; try_files $uri $uri/ =404; } location / { try_files $uri $uri/ @cykel; } location @cykel { 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_read_timeout 300; proxy_pass http://127.0.0.1:8000; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/api.dev.bike/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/api.dev.bike/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { server_name care.dev.bike; root /srv/openbike/skoetsel/dist; index index.html index.htm; location / { try_files $uri $uri/ /index.html; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/care.dev.bike/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/care.dev.bike/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { server_name dev.bike; root /srv/openbike/voorwiel/dist; index index.html index.htm; location / { try_files $uri $uri/ /index.html; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/dev.bike/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/dev.bike/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }
We recommend reading about setting strong encryption settings for your web server. Certbot provides these with the
options-ssl-nginx.conf
file.Reverse Proxy (apache2)¶
If you’re using apache2 instead, the following snippet is an example on how to configure the reverse proxy for cykel, skoetsel and voorwiel in the apache2 format:
<VirtualHost *:443> ServerName api.dev.bike SSLCertificateFile /etc/letsencrypt/live/api.dev.bike/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/api.dev.bike/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf Alias /static /srv/openbike/cykel/public <Directory /srv/openbike/cykel/public> Require all granted </Directory> ProxyPreserveHost On RequestHeader set X-Forwarded-Proto 'https' ProxyPass /static ! ProxyPass / http://127.0.0.1:8000/ ProxyPassReverse / http://127.0.0.1:8000/ </VirtualHost> <VirtualHost *:443> ServerName care.dev.bike SSLCertificateFile /etc/letsencrypt/live/care.dev.bike/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/care.dev.bike/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf DocumentRoot /srv/openbike/skoetsel/dist <Directory /srv/openbike/skoetsel/dist> Require all granted </Directory> FallbackResource /index.html </VirtualHost> <VirtualHost *:443> ServerName dev.bike SSLCertificateFile /etc/letsencrypt/live/dev.bike/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/dev.bike/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf DocumentRoot /srv/openbike/voorwiel/dist <Directory /srv/openbike/voorwiel/dist> Require all granted </Directory> FallbackResource /index.html </VirtualHost>
Do not forget to enable the proxy, proxy_http and the headers module.
We recommend reading about setting strong encryption settings for your web server. Certbot provides these with the
options-ssl-apache.conf
file.Next steps¶
Yay! You’ve installed cykel and voorwiel. To configure your new running bikesharing system and get access to the administration interface, read the Configuration chapter.