diff --git a/ennstatus/api/model.py b/ennstatus/api/model.py
--- a/ennstatus/api/model.py
+++ b/ennstatus/api/model.py
@@ -255,10 +255,13 @@ class Server:
         except:
             raise NotImplementedError
 
-        if data is not None:
-            self.flags = data.relays[0].flags
-        else:
-            raise NotImplementedError
+        try:
+            if data is not None:
+                self.flags = data.relays[0].flags
+            else:
+                raise NotImplementedError
+        except IndexError as e:
+            raise NotImplementedError from e
 
     def check_status(self):
 
diff --git a/ennstatus/api/views.py b/ennstatus/api/views.py
--- a/ennstatus/api/views.py
+++ b/ennstatus/api/views.py
@@ -115,15 +115,16 @@ def update():
         current_app.logger.warning(' '.join([str(e), str(data)]))
         return str(e), 409, {'Content-Type': 'text/plain'}
 
-    try:
-        server.update_weights()
-    except NotImplementedError:
-        pass
+    if current_app.config['ENNSTATUS_ENABLE_ONIONOO']:
+        try:
+            server.update_weights()
+        except NotImplementedError:
+            pass
 
-    try:
-        server.update_flags()
-    except NotImplementedError:
-        pass
+        try:
+            server.update_flags()
+        except NotImplementedError:
+            pass
 
     try:
         server.save()
diff --git a/ennstatus/cli/__init__.py b/ennstatus/cli/__init__.py
--- a/ennstatus/cli/__init__.py
+++ b/ennstatus/cli/__init__.py
@@ -15,9 +15,13 @@
 # along with this program.  If not, see .
 
 import pathlib
+import importlib
+import operator
 
 import click
 
+from .commands import __all__ as commands_all
+
 
 @click.group()
 @click.option('-p', '--path', default='/srv/http/enn.lu',
@@ -35,9 +39,10 @@ def cli(ctx, path):
     ctx.obj['config_file'] = path / 'config.json'
     ctx.obj['data_dir'] = path / 'data'
 
-
-from .commands import config
-cli.add_command(config, 'config')
+subcommands = importlib.import_module('ennstatus.cli.commands')
+for command in commands_all:
+    get = operator.attrgetter(command)
+    cli.add_command(get(subcommands), command)
 
 if __name__ == '__main__':
     cli()
diff --git a/ennstatus/cli/commands/__init__.py b/ennstatus/cli/commands/__init__.py
--- a/ennstatus/cli/commands/__init__.py
+++ b/ennstatus/cli/commands/__init__.py
@@ -15,5 +15,6 @@
 # along with this program.  If not, see .
 
 from .config import config
+from .stats import stats
 
-__all__ = ['config']
+__all__ = ['config', 'stats']
diff --git a/ennstatus/cli/commands/config.py b/ennstatus/cli/commands/config.py
--- a/ennstatus/cli/commands/config.py
+++ b/ennstatus/cli/commands/config.py
@@ -16,6 +16,7 @@
 
 import json
 import ipaddress
+import subprocess
 
 from pprint import pprint
 
@@ -83,6 +84,7 @@ def add(obj, name, ips, password, bridge
         except KeyError:
             config['ENNSTATUS_BRIDGE_PROGRAM'] = [name]
 
+    click.echo('%s password: %s' % (name, password))
     with obj['config_file'].open(mode='w', encoding='utf-8') as f:
         json.dump(config, f, indent=4, sort_keys=True)
 
@@ -103,7 +105,7 @@ def delete(obj, name):
 
     try:
         config['ENNSTATUS_BRIDGE_PROGRAM'].remove(name)
-    except KeyError:
+    except (KeyError, ValueError):
         pass
 
     with obj['config_file'].open(mode='w', encoding='utf-8') as f:
@@ -114,3 +116,37 @@ def delete(obj, name):
         filename.unlink()
     except FileNotFoundError:
         pass
+
+
+@config.group(short_help='Configure more servers at once')
+def servers():
+    pass
+
+
+@servers.command('add', short_help='Add servers')
+@click.argument('names', nargs=-1, required=True)
+@click.option('-i', '--ips', prompt='IPs (comma separated)')
+@click.option('--bridgeprogram/--no-bridgeprogram', default=False)
+@click.pass_context
+def adds(ctx, names, ips, bridgeprogram):
+
+    for name in names:
+        password = subprocess.check_output(['pwgen', '8', '1'])
+        password = password.decode('utf-8')
+        password = password.strip()
+        ctx.invoke(
+            add,
+            name=name,
+            ips=ips,
+            password=password,
+            bridgeprogram=bridgeprogram
+        )
+
+
+@servers.command('delete', short_help='Delete servers')
+@click.argument('names', nargs=-1, required=True)
+@click.pass_context
+def dels(ctx, names):
+
+    for name in names:
+        ctx.invoke(delete, name=name)
diff --git a/ennstatus/cli/commands/stats.py b/ennstatus/cli/commands/stats.py
new file mode 100644
--- /dev/null
+++ b/ennstatus/cli/commands/stats.py
@@ -0,0 +1,232 @@
+import json
+
+from collections import defaultdict
+
+import click
+
+from ennstatus import create_app
+from ...status.functions import split_all_servers_to_types
+
+
+@click.group(short_help='Get statistics')
+def stats():
+    pass
+
+
+@stats.command('count')
+@click.option('--by-type', 'by_type', is_flag=True, default=False)
+@click.pass_obj
+def count(obj, by_type):
+
+    def calculate_host_number(config, type='all', servers=None):
+
+        hosts = set()
+        if type == 'all':
+
+            for values in config['ENNSTATUS_SERVERS'].values():
+                ips = frozenset(values['IPS'])
+                hosts.add(ips)
+
+            return len(hosts)
+        else:
+            for server in servers[servertype]:
+                ips = frozenset(
+                    config['ENNSTATUS_SERVERS'][server.name.lower()]['IPS']
+                )
+                hosts.add(ips)
+        return len(hosts)
+
+    app = create_app()
+
+    with app.app_context():
+        app.logger.disabled = True
+        servers = split_all_servers_to_types()
+
+    if not by_type:
+
+        click.echo(
+            'We have %s servers in total!' % (
+                click.style(
+                    str(sum(len(x) for x in servers.values())),
+                    fg='blue'
+                )
+            )
+        )
+
+        click.echo(
+            'We have %s different hosts!' % (
+                click.style(
+                    str(calculate_host_number(app.config)),
+                    fg='blue'
+                )
+            )
+        )
+    else:
+        for servertype, server in servers.items():
+            click.echo(
+                'We have %s %s servers!' % (
+                    click.style(
+                        str(len(server)),
+                        fg='blue'
+                    ),
+                    click.style(
+                        servertype,
+                        fg='red'
+                    )
+                )
+            )
+            click.echo(
+                'We have %s different %s hosts!' % (
+                    click.style(
+                        str(
+                            calculate_host_number(
+                                app.config,
+                                type=servertype,
+                                servers=servers
+                            )
+                        ),
+                        fg='blue'
+                    ),
+                    click.style(
+                        servertype,
+                        fg='red'
+                    )
+                )
+            )
+
+
+@stats.command('countries')
+@click.option('--by-type', 'by_type', is_flag=True, default=False)
+@click.pass_obj
+def countries(obj, by_type):
+    app = create_app()
+
+    with app.app_context():
+        app.logger.disabled = True
+        servers = split_all_servers_to_types()
+
+    if not by_type:
+        countries = defaultdict(int)
+
+        for key, value in servers.items():
+            for server in value:
+                countries[server.country] += 1
+
+        for key, value in sorted(countries.items(), key=lambda x: x[1]):
+            click.echo(
+                '%s: %s' % (
+                    click.style(key, fg='green'),
+                    click.style(str(value), fg='blue')
+                )
+            )
+
+        click.echo(
+            'We are hosted in %s different countries' % click.style(
+                str(len(countries.keys())),
+                fg='blue'
+            )
+        )
+    else:
+        type_countries = {
+            'exit': defaultdict(int),
+            'relay': defaultdict(int),
+            'bridge': defaultdict(int)
+        }
+
+        for key, value in servers.items():
+            for server in value:
+                type_countries[key][server.country] += 1
+
+        type_countries = dict((k, v) for k, v in type_countries.items() if v)
+
+        for key, value in sorted(type_countries.items(), key=lambda x: x[0]):
+            click.echo(
+                click.style(
+                    key.capitalize(),
+                    fg='red',
+                    bold=True,
+                    underline=True
+                )
+            )
+
+            for country, count in sorted(type_countries[key].items(), key=lambda x: x[1]):
+                click.echo(
+                    '%s: %s' % (
+                        click.style(country, fg='green'),
+                        click.style(str(count), fg='blue')
+                    )
+                )
+
+            click.echo(
+                '%s are hosted in %s different countries' % (
+                    key,
+                    click.style(
+                        str(len(type_countries[key].keys())),
+                        fg='blue'
+                    )
+                )
+            )
+
+
+@stats.command('exit_probability')
+@click.option('--by-server', 'by_server', is_flag=True, default=False)
+@click.pass_obj
+def exit_probability(obj, by_server):
+
+    app = create_app()
+    with app.app_context():
+        app.logger.disabled = True
+        servers = split_all_servers_to_types()
+
+    if not by_server:
+        exit_probability = defaultdict(int)
+        for server in servers['exit']:
+            for subkey in ('1_week', '1_month', '3_months', '1_year', '5_years'):
+                try:
+                    if server.mean_exit_probability[subkey] is not None:
+                        exit_probability[subkey] += server.mean_exit_probability[subkey]
+                except KeyError:
+                    continue
+        for subkey in ('1_week', '1_month', '3_months', '1_year', '5_years'):
+            try:
+                click.echo(
+                    'Mean exit probability over %s: %s' % (
+                        click.style(
+                            subkey,
+                            fg='blue'
+                        ),
+                        click.style(
+                            str(round(exit_probability[subkey], 2)) + '%',
+                            fg='red'
+                        )
+                    )
+                )
+            except KeyError:
+                continue
+    else:
+        for server in servers['exit']:
+            click.echo(
+                click.style(
+                    server.name.capitalize(),
+                    fg='red',
+                    bold=True,
+                    underline=True
+                )
+            )
+            for subkey in ('1_week', '1_month', '3_months', '1_year', '5_years'):
+                try:
+                    if server.mean_exit_probability[subkey] is not None:
+                        click.echo(
+                            'Mean exit probabilty over %s: %s' % (
+                                click.style(
+                                    subkey,
+                                    fg='blue'
+                                ),
+                                click.style(
+                                    str(round(server.mean_exit_probability[subkey], 2)) + "%",
+                                    fg='red'
+                                )
+                            )
+                        )
+                except KeyError:
+                    continue
diff --git a/ennstatus/config.py b/ennstatus/config.py
--- a/ennstatus/config.py
+++ b/ennstatus/config.py
@@ -36,3 +36,5 @@ def init_app(app):
     config.setdefault('ENNSTATUS_MOMENTJS_FORMAT', 'DD MMMM YYYY HH:mm:ss')
 
     config.setdefault('ENNSTATUS_STRFTIME_FORMAT', '%d %B %Y %H:%M:%S')
+
+    config.setdefault('ENNSTATUS_ENABLE_ONIONOO', False)
diff --git a/ennstatus/donate/views.py b/ennstatus/donate/views.py
--- a/ennstatus/donate/views.py
+++ b/ennstatus/donate/views.py
@@ -22,40 +22,12 @@ from babel.numbers import parse_decimal,
 from ennstatus.donate.forms import DateForm
 from ennstatus.donate.functions import load_csv, get_choices
 
-from ennstatus.root.forms import BPMForm
-from ennstatus.root.constants import BPM_ADDRESSES
-
 donate_page = Blueprint('donate', __name__)
 
 
-@donate_page.route('/', methods=('GET', 'POST'))
+@donate_page.route('/')
 def index():
-
-    current_app.logger.info('Handling index')
-    form = BPMForm()
-    country_choices = [choice[0] for choice in form.country.choices]
-
-    if request.method == 'POST':
-        current_app.logger.debug('Validating form')
-        if form.validate_on_submit():
-            country = form.country.data
-            return redirect(url_for('donate.index', country=country))
-    else:
-        if 'country' in request.args:
-            country = request.args['country']
-            if country in country_choices:
-                current_app.logger.info('Showing country %s' % country)
-            else:
-                current_app.logger.warn('Country %s not found' % country)
-                country = 'luxembourg'
-        else:
-            current_app.logger.info('Using default country')
-            country = 'luxembourg'
-
-    form.country.data = country
-    address = BPM_ADDRESSES[country]
-
-    return render_template('donate/index.html', form=form, address=address)
+    return render_template('donate/index.html')
 
 
 @donate_page.route('/received',
diff --git a/ennstatus/root/constants.py b/ennstatus/root/constants.py
deleted file mode 100644
--- a/ennstatus/root/constants.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Ënnstatus
-# Copyright (C) 2015  Dennis Fink
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see .
-
-
-BPM_ADDRESSES = {
-    'germany': {
-        'address': 'Zum Bürgerwehr 28',
-        'postal_code': 'D-54516',
-        'city': 'Wittlich',
-        'country': 'Germany',
-    },
-    'belgium': {
-        'address': '3, Rue des Deux Luxembourg',
-        'postal_code': 'B-6791',
-        'city': 'Athus',
-        'country': 'Belgium',
-    },
-    'france': {
-        'address': 'Les Maragolles',
-        'postal_code': 'F-54720',
-        'city': 'Lexy',
-        'country': 'France',
-    },
-    'luxembourg': {
-        'address': '34, Rue Gabriel Lippmann',
-        'postal_code': 'L-5365',
-        'city': 'Munsbach',
-        'country': 'Luxembourg',
-    },
-}
diff --git a/ennstatus/root/forms.py b/ennstatus/root/forms.py
--- a/ennstatus/root/forms.py
+++ b/ennstatus/root/forms.py
@@ -15,28 +15,12 @@
 # along with this program.  If not, see .
 
 from flask_wtf import Form
-from wtforms import (SelectField,
-                     StringField,
+from wtforms import (StringField,
                      RadioField,
                      BooleanField,
                      SubmitField
                      )
-from wtforms.validators import InputRequired, Email, Length, DataRequired
-
-
-COUNTRIES = [
-    ('luxembourg', 'Luxembourg'),
-    ('belgium', 'Belgium'),
-    ('france', 'France'),
-    ('germany', 'Germany'),
-]
-
-
-class BPMForm(Form):
-    country = SelectField('Country',
-                          validators=[DataRequired()],
-                          choices=COUNTRIES)
-    submit = SubmitField('Submit')
+from wtforms.validators import InputRequired, Email, Length
 
 
 class MembershipForm(Form):
diff --git a/ennstatus/root/views.py b/ennstatus/root/views.py
--- a/ennstatus/root/views.py
+++ b/ennstatus/root/views.py
@@ -17,8 +17,7 @@
 from flask import (Blueprint, render_template, current_app,
                    request, redirect, url_for, flash)
 
-from ennstatus.root.forms import BPMForm, MembershipForm, BridgeprogramForm
-from ennstatus.root.constants import BPM_ADDRESSES
+from ennstatus.root.forms import MembershipForm, BridgeprogramForm
 from ennstatus.root.functions import (create_membership_ticket,
                                       create_bridgeprogram_ticket)
 
@@ -80,35 +79,9 @@ def mirrors():
     return render_template('root/mirrors.html')
 
 
-@root_page.route('/contact', methods=('GET', 'POST'))
+@root_page.route('/contact')
 def contact():
-
-    current_app.logger.info('Handling contact')
-    form = BPMForm()
-    country_choices = [choice[0] for choice in form.country.choices]
-
-    if request.method == 'POST':
-        current_app.logger.debug('Validating form')
-        if form.validate_on_submit():
-            country = form.country.data
-            return redirect(url_for('root.contact', country=country))
-    else:
-        if 'country' in request.args:
-            country = request.args['country']
-            if country in country_choices:
-                current_app.logger.info('Showing country %s' % country)
-            else:
-                current_app.logger.warn('Country %s not found' % country)
-                country = 'luxembourg'
-        else:
-            current_app.logger.info('Using default country')
-            country = 'luxembourg'
-
-    form.country.data = country
-
-    address = BPM_ADDRESSES[country]
-
-    return render_template('root/contact.html', form=form, address=address)
+    return render_template('root/contact.html')
 
 
 @root_page.route('/abuse')
diff --git a/ennstatus/static/css/ennstatus.css b/ennstatus/static/css/ennstatus.css
--- a/ennstatus/static/css/ennstatus.css
+++ b/ennstatus/static/css/ennstatus.css
@@ -165,3 +165,12 @@ a, a:hover, a:active, a:visited {
 footer {
     margin-bottom: 20px;
 }
+
+@media (min-width: 768px) {
+    .dl-horizontal dd {
+        margin-left: 200px
+    }
+    .dl-horizontal dt {
+        width: 180px
+    }
+}
diff --git a/ennstatus/templates/base.html b/ennstatus/templates/base.html
--- a/ennstatus/templates/base.html
+++ b/ennstatus/templates/base.html
@@ -111,6 +111,8 @@
         
           Statistics 
           
         
@@ -131,18 +133,20 @@
   {% block content %}
   {% endblock %}
   
-