summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md117
-rw-r--r--doc/common/_bigcouch_migration.md117
-rw-r--r--doc/common/_bigcouch_migration_begin.md66
-rw-r--r--doc/common/_bigcouch_migration_end.md26
-rw-r--r--doc/common/_bigcouch_migration_finish.md10
-rw-r--r--doc/details/development.md78
-rw-r--r--doc/details/en.haml4
-rw-r--r--doc/details/faq.md71
-rw-r--r--doc/details/ports.md92
-rw-r--r--doc/details/under-the-hood.md40
-rw-r--r--doc/en.md82
-rw-r--r--doc/guide/commands.md559
-rw-r--r--doc/guide/config.md360
-rw-r--r--doc/guide/domains.md129
-rw-r--r--doc/guide/en.haml4
-rw-r--r--doc/guide/environments.md75
-rw-r--r--doc/guide/getting-started.md145
-rw-r--r--doc/guide/keys-and-certificates.md272
-rw-r--r--doc/guide/miscellaneous.md14
-rw-r--r--doc/guide/nodes.md87
-rw-r--r--doc/guide/provider-configuration.md79
-rw-r--r--doc/service-diagram.odgbin12131 -> 0 bytes
-rw-r--r--doc/service-diagram.pngbin25988 -> 0 bytes
-rw-r--r--doc/services/couchdb.md159
-rw-r--r--doc/services/en.md80
-rw-r--r--doc/services/monitor.md36
-rw-r--r--doc/services/mx.md35
-rw-r--r--doc/services/openvpn.md49
-rw-r--r--doc/services/soledad.md12
-rw-r--r--doc/services/tor.md32
-rw-r--r--doc/services/webapp.md293
-rw-r--r--doc/troubleshooting/en.haml3
-rw-r--r--doc/troubleshooting/known-issues.md115
-rw-r--r--doc/troubleshooting/tests.md70
-rw-r--r--doc/troubleshooting/where-to-look.md267
-rw-r--r--doc/tutorials/en.haml4
-rw-r--r--doc/tutorials/quick-start.md230
-rw-r--r--doc/tutorials/single-node-email.md69
-rw-r--r--doc/tutorials/single-node-vpn.md112
-rw-r--r--doc/tutorials/vagrant.md471
-rw-r--r--doc/upgrading/en.haml5
-rw-r--r--doc/upgrading/upgrade-0-8.md141
-rw-r--r--docs/en/commands.html0
-rw-r--r--docs/en/details.html138
-rw-r--r--docs/en/details/development.html226
-rw-r--r--docs/en/details/development/index.html226
-rw-r--r--docs/en/details/faq.html213
-rw-r--r--docs/en/details/faq/index.html213
-rw-r--r--docs/en/details/ports.html209
-rw-r--r--docs/en/details/ports/index.html209
-rw-r--r--docs/en/details/under-the-hood.html168
-rw-r--r--docs/en/details/under-the-hood/index.html168
-rw-r--r--docs/en/guide.html192
-rw-r--r--docs/en/guide/commands.html784
-rw-r--r--docs/en/guide/commands/index.html784
-rw-r--r--docs/en/guide/config.html584
-rw-r--r--docs/en/guide/config/index.html584
-rw-r--r--docs/en/guide/domains.html298
-rw-r--r--docs/en/guide/domains/index.html298
-rw-r--r--docs/en/guide/environments.html228
-rw-r--r--docs/en/guide/environments/index.html228
-rw-r--r--docs/en/guide/getting-started.html317
-rw-r--r--docs/en/guide/getting-started/index.html317
-rw-r--r--docs/en/guide/keys-and-certificates.html480
-rw-r--r--docs/en/guide/keys-and-certificates/index.html480
-rw-r--r--docs/en/guide/miscellaneous.html145
-rw-r--r--docs/en/guide/miscellaneous/index.html145
-rw-r--r--docs/en/guide/nodes.html231
-rw-r--r--docs/en/guide/nodes/index.html231
-rw-r--r--docs/en/guide/provider-configuration.html223
-rw-r--r--docs/en/guide/provider-configuration/index.html223
-rw-r--r--docs/en/guide/virtual-machines.html299
-rw-r--r--docs/en/guide/virtual-machines/index.html299
-rw-r--r--docs/en/services.html251
-rw-r--r--docs/en/services/couchdb.html328
-rw-r--r--docs/en/services/couchdb/index.html328
-rw-r--r--docs/en/services/index.html251
-rw-r--r--docs/en/services/monitor.html186
-rw-r--r--docs/en/services/monitor/index.html186
-rw-r--r--docs/en/services/mx.html168
-rw-r--r--docs/en/services/mx/index.html168
-rw-r--r--docs/en/services/openvpn.html178
-rw-r--r--docs/en/services/openvpn/index.html178
-rw-r--r--docs/en/services/soledad.html136
-rw-r--r--docs/en/services/soledad/index.html136
-rw-r--r--docs/en/services/tor.html161
-rw-r--r--docs/en/services/tor/index.html161
-rw-r--r--docs/en/services/webapp.html479
-rw-r--r--docs/en/services/webapp/index.html479
-rw-r--r--docs/en/troubleshooting.html129
-rw-r--r--docs/en/troubleshooting/known-issues.html238
-rw-r--r--docs/en/troubleshooting/known-issues/index.html238
-rw-r--r--docs/en/troubleshooting/tests.html201
-rw-r--r--docs/en/troubleshooting/tests/index.html201
-rw-r--r--docs/en/troubleshooting/where-to-look.html451
-rw-r--r--docs/en/troubleshooting/where-to-look/index.html451
-rw-r--r--docs/en/tutorials.html138
-rw-r--r--docs/en/tutorials/quick-start.html446
-rw-r--r--docs/en/tutorials/quick-start/index.html446
-rw-r--r--docs/en/tutorials/single-node-email.html200
-rw-r--r--docs/en/tutorials/single-node-email/index.html200
-rw-r--r--docs/en/tutorials/single-node-vpn.html250
-rw-r--r--docs/en/tutorials/single-node-vpn/index.html250
-rw-r--r--docs/en/tutorials/vagrant.html724
-rw-r--r--docs/en/tutorials/vagrant/index.html724
-rw-r--r--docs/en/tutorials/vagrant/known-issues.html0
-rw-r--r--docs/en/tutorials/vagrant/quick-start.html0
-rw-r--r--docs/en/upgrading.html111
-rw-r--r--docs/en/upgrading/upgrade-0-8.html334
-rw-r--r--docs/index.html190
-rw-r--r--docs/robots.txt.html0
111 files changed, 18890 insertions, 4556 deletions
diff --git a/README.md b/README.md
index a8e46edb..999e0087 100644
--- a/README.md
+++ b/README.md
@@ -3,102 +3,93 @@ Leap Platform
[![Build Status](https://0xacab.org/leap/platform/badges/develop/build.svg)](https://0xacab.org/leap/platform/commits/develop)
-The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment. Its goal is to make it as painless as possible for sysadmins to deploy and maintain a service provider's infrastructure for secure communication. These recipes define an abstract service provider. It is a set of Puppet modules designed to work together to provide to sysadmins everything they need to manage a service provider infrastructure that provides secure communication services.
+The LEAP Platform is set of complementary packages and server recipes to
+automate the maintenance of LEAP services in a hardened Debian environment. Its
+goal is to make it as painless as possible for sysadmins to deploy and maintain
+a service provider's infrastructure for secure communication. These recipes
+define an abstract service provider. It is a set of Puppet modules designed to
+work together to provide to sysadmins everything they need to manage a service
+provider infrastructure that provides secure communication services.
Getting started
=============================
-It is highly recommended that you start by reading the overview of the [LEAP Platform](https://leap.se/docs/platform) and then begin with the [Quick Start tutorial](https://leap.se/en/docs/platform/tutorials/quick-start) to walk through a test environment setup to get familiar with how things work before deploying to live servers.
+It is highly recommended that you start by reading the overview of the [LEAP
+Platform](https://leap.se/docs/platform) and then begin with the [Quick Start
+tutorial](https://leap.se/en/docs/platform/tutorials/quick-start) to walk
+through a test environment setup to get familiar with how things work before
+deploying to live servers.
-An offline copy of this documentation is contained in the `doc` subdirectory. For more current updates to the documentation, visit the website.
+An offline copy of this documentation is contained in the `docs` subdirectory:
+
+ cd leap_platform
+ gnome-open docs/index.html
Requirements
-------------------
+-----------------------------
-For testing a virtual deployment simulated on your computer, you will need a fairly recent computer x86_64 with hardware virtualization features (AMD-V or VT-x) and plenty of RAM. If you follow the "Quick Start" documentation we will walk you through using Vagrant to setup a test deployment.
+For testing a virtual deployment simulated on your computer, you will need a
+fairly recent computer x86_64 with hardware virtualization features (AMD-V or
+VT-x) and plenty of RAM. If you follow the "Quick Start" documentation we will
+walk you through using Vagrant to setup a test deployment.
-For a live deployment of the platform, the number of servers that is required depends on your needs and which services you want to deploy. At the moment, the LEAP Platform supports servers with a base Debian Wheezy installation.
+For a live deployment of the platform, the number of servers that is required
+depends on your needs and which services you want to deploy. At the moment, the
+LEAP Platform supports servers with a base Debian Jessie installation.
Troubleshooting
=============================
If you have a problem, we are interested in fixing it!
-If you have a problem, be sure to have a look at the [Known Issues](https://leap.se/docs/platform/known-issues) to see if your issue is detailed there.
+If you have a problem, be sure to have a look at the [Known
+Issues](https://leap.se/docs/platform/known-issues) to see if your issue is
+detailed there.
-If not, the best way for us to solve your problem is if you provide to us the complete log of what you did, and the output that was produced. Please don't cut out what appears to be useless information and only include the error that you received, instead copy and paste the complete log so that we can better determine the overall situation. If you can run the same command that produced the error with a raised verbosity level (such as -v2), that provides us with more useful debugging information.
+If not, the best way for us to solve your problem is if you provide to us the
+complete log of what you did, and the output that was produced. Please don't
+cut out what appears to be useless information and only include the error that
+you received, instead copy and paste the complete log so that we can better
+determine the overall situation. If you can run the same command that produced
+the error with a raised verbosity level (such as -v2), that provides us with
+more useful debugging information.
-To capture the log, you can copy from the console, or run `leap --log FILE` or edit Leapfile to include `@log = '/tmp/leap.log'`.
+To capture the log, you can copy from the console, or run `leap --log FILE` or
+edit Leapfile to include `@log = '/tmp/leap.log'`.
-Visit https://leap.se/en/docs/get-involved/communication for details on how to contact the developers.
+Visit https://leap.se/en/docs/get-involved/communication for details on how to
+contact the developers.
Known issues
-============
-
-The following issues are known to exist in 0.5.2 and later:
-
-CouchDB Sync
-------------
-You can't deploy new couchdb nodes after one or more have been deployed. Make *sure* that you configure and deploy all your couchdb nodes when first creating your provider. The problem is that we dont not have a clean way of adding couch nodes after initial creation of the databases, so any nodes added after result in improperly synchronized data. See Bug [#5601](https://leap.se/code/issues/5601) for more information.
-
-User setup and ssh
-------------------
-
-. if you aren't using a single ssh key, but have different ones, you will need to define the following at the top of your ~/.ssh/config:
- HostName <ip address>
- IdentityFile <path to identity file>
-
- (see: https://leap.se/code/issues/2946 and https://leap.se/code/issues/3002)
-
-. If the ssh host key changes, you need to run node init again (see: https://leap.se/en/docs/platform/guide#Working.with.SSH)
-
-. At the moment, only ECDSA ssh host keys are supported. If you get the following error: `= FAILED ssh-keyscan: no hostkey alg (must be missing an ecdsa public host key)` then you should confirm that you have the following line defined in your server's **/etc/ssh/sshd_config**: `HostKey /etc/ssh/ssh_host_ecdsa_key`. If that file doesn't exist, run `ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ""` in order to create it. If you made a change to your sshd_config, then you need to run `/etc/init.d/ssh restart` (see: https://leap.se/code/issues/2373)
-
-. To remove an admin's access to your servers, please remove the directory for that user under the `users/` subdirectory in your provider directory and then remove that user's ssh keys from files/ssh/authorized_keys. When finished you *must* run a `leap deploy` to update that information on the servers.
-
-. At the moment, it is only possible to add an admin who will have access to all LEAP servers (see: https://leap.se/code/issues/2280)
+==============================
-. leap add-user --self allows only one key - if you run that command twice with different keys, you will just replace the key with the second key. To add a second key, add it manually to files/ssh/authorized_keys (see: https://leap.se/code/issues/866)
+ssh
+------------------------------
+* At the moment, it is only possible to add an admin who will have access to
+ all LEAP servers (see: https://leap.se/code/issues/2280)
Deploying
----------
-
-. If you have any errors during a run, please try to deploy again as this often solves non-deterministic issues that were not uncovered in our testing. Please re-deploy with `leap -v2 deploy` to get more verbose logs and capture the complete output to provide to us for debugging.
-
-. If when deploying your debian mirror fails for some reason, network anomoly or the mirror itself is out of date, then platform deployment will not succeed properly. Check the mirror is up and try to deploy again when it is resolved (see: https://leap.se/code/issues/1091)
-
-. Deployment gives 'error: in `%`: too few arguments (ArgumentError)' - this is because you attempted to do a deploy before initializing a node, please initialize the node first and then do a deploy afterwards (see: https://leap.se/code/issues/2550)
-
-. This release has no ability to custom configure apt sources or proxies (see: https://leap.se/code/issues/1971)
-
-. When running a deploy at a verbosity level of 2 and above, you will notice puppet deprecation warnings, these are known and we are working on fixing them
-
-Special Environments
---------------------
-
-. When deploying to OpenStack release "nova" or newer, you will need to do an initial deploy, then when it has finished run `leap facts update` and then deploy again (see: https://leap.se/code/issues/3020)
-
-leap-mx
--------
-
-. see https://github.com/leapcode/leap_mx#070 for issues regarding leap_mx
+-------------------------------
+* If you have any errors during a run, please try to deploy again as this often
+ solves non-deterministic issues that were not uncovered in our testing.
+ Please re-deploy with `leap -v2 deploy` to get more verbose logs and capture
+ the complete output to provide to us for debugging.
Contributing
-============
-
-In order to validate the syntax and style guide compliance
-before you commit, see https://github.com/pixelated-project/puppet-git-hooks#installation
+================================
+In order to validate the syntax and style guide compliance before you commit,
+see https://github.com/pixelated-project/puppet-git-hooks#installation
Changes
-=========
+================================
Read CHANGES.md or run `git log`.
Authors and Credits
-===================
+================================
See contributors:
@@ -106,6 +97,6 @@ See contributors:
Copyright/License
-=================
+================================
Read LICENSE
diff --git a/doc/common/_bigcouch_migration.md b/doc/common/_bigcouch_migration.md
deleted file mode 100644
index eb7e07e9..00000000
--- a/doc/common/_bigcouch_migration.md
+++ /dev/null
@@ -1,117 +0,0 @@
-@title = "Migrating from BigCouch to plain CouchDB"
-
-Here are the steps needed to replace BigCouch with CouchDB.
-
-At the end of this process, you will have just *one* node with `services` property equal to `couchdb`. If you had a BigCouch cluster before, you will be removing all but one of those machines to consolidate them into one CouchDB machine.
-
-1. if you have multiple nodes with the `couchdb` service on them, pick one of them to be your CouchDB server, and remove the service from the others. If these machines were only doing BigCouch before, you can remove the nodes completely with `leap node rm <nodename>` and then you can decommission the servers
-
-1. put the webapp into [[maintenance mode => webapp#maintenance-mode]]
-
-1. turn off daemons that access the database. For example:
-
- ```
- workstation$ leap ssh <each soledad-node>
- server# /etc/init.d/soledad-server stop
-
- workstation$ leap ssh <mx-node>
- server# /etc/init.d/postfix stop
- server# /etc/init.d/leap-mx stop
-
- workstation$ leap ssh <webapp-node>
- server# /etc/init.d/nickserver stop
- ```
-
- Alternately, you can create a temporary firewall rule to block access (run on couchdb server):
-
- ```
- server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
- ```
-
-1. remove orphaned databases and do a backup of all remaining, active databases. This can take some time and will place several hundred megabytes of data into /var/backups/couchdb. The size and time depends on how many users there are on your system. For example, 15k users took approximately 25 minutes and 308M of space:
-
- ```
- workstation$ leap ssh <couchdb-node>
- server# cd /srv/leap/couchdb/scripts
- server# ./cleanup-user-dbs
- server# time ./couchdb_dumpall.sh
- ```
-
-1. stop bigcouch:
-
- ```
- server# /etc/init.d/bigcouch stop
- server# pkill epmd
- ```
-
-1. remove bigcouch:
-
- ```
- server# apt-get remove bigcouch
- ```
-
-1. configure your couch node to use plain couchdb instead of bigcouch, you can do this by editing nodes/<couch-node>.json, look for this section:
-
- ```
- "couch": {
- "mode": "plain"
- }
- ```
-
- change it, so it looks like this instead:
-
- ```
- "couch": {
- "mode": "plain",
- "pwhash_alg": "pbkdf2"
- }
- ```
-
-1. deploy to the couch node:
-
- ```
- workstation$ leap deploy <couchdb-node>
- ```
-
- If you used the iptables method of blocking access to couchdb, you need to run it again because the deploy just overwrote all the iptables rules:
-
- ```
- server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
- ```
-
-1. restore the backup, this will take approximately the same amount of time as the backup took above:
-
- ```
- server# cd /srv/leap/couchdb/scripts
- server# time ./couchdb_restoreall.sh
- ```
-
-1. start services again that were stopped in the beginning:
-
- ```
- workstation$ leap ssh soledad-nodes
- server# /etc/init.d/soledad-server start
-
- workstation$ leap ssh mx-node
- server# /etc/init.d/postfix start
- server# /etc/init.d/leap-mx start
-
- workstation$ leap ssh webapp
- server# /etc/init.d/nickserver start
- ```
-
- Or, alternately, if you set up the firewall rule instead, now remove it:
-
- ```
- server# iptables -D INPUT -p tcp --dport 5984 --jump REJECT
- ```
-
-1. check if everything is working, including running the test on your deployment machine:
-
- ```
- workstation$ leap test
- ```
-
-1. Remove old bigcouch data dir `/opt` after you double checked everything is in place
-
-1. Relax, enjoy a refreshing beverage.
diff --git a/doc/common/_bigcouch_migration_begin.md b/doc/common/_bigcouch_migration_begin.md
deleted file mode 100644
index 4e4233dd..00000000
--- a/doc/common/_bigcouch_migration_begin.md
+++ /dev/null
@@ -1,66 +0,0 @@
-@title = "Migrating from BigCouch to plain CouchDB"
-
-At the end of this process, you will have just *one* node with `services` property equal to `couchdb`. If you had a BigCouch cluster before, you will be removing all but one of those machines to consolidate them into one CouchDB machine.
-
-1. if you have multiple nodes with the `couchdb` service on them, pick one of them to be your CouchDB server, and remove the service from the others. If these machines were only doing BigCouch before, you can remove the nodes completely with `leap node rm <nodename>` and then you can decommission the servers
-
-1. put the webapp into [[maintenance mode => webapp#maintenance-mode]]
-
-1. turn off daemons that access the database. For example:
-
- ```
- workstation$ leap ssh <each soledad-node>
- server# /etc/init.d/soledad-server stop
-
- workstation$ leap ssh <mx-node>
- server# /etc/init.d/postfix stop
- server# /etc/init.d/leap-mx stop
-
- workstation$ leap ssh <webapp-node>
- server# /etc/init.d/nickserver stop
- ```
-
- Alternately, you can create a temporary firewall rule to block access (run on couchdb server):
-
- ```
- server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
- ```
-
-1. remove orphaned databases and do a backup of all remaining, active databases. This can take some time and will place several hundred megabytes of data into /var/backups/couchdb. The size and time depends on how many users there are on your system. For example, 15k users took approximately 25 minutes and 308M of space:
-
- ```
- workstation$ leap ssh <couchdb-node>
- server# cd /srv/leap/couchdb/scripts
- server# ./cleanup-user-dbs
- server# time ./couchdb_dumpall.sh
- ```
-
-1. stop bigcouch:
-
- ```
- server# /etc/init.d/bigcouch stop
- server# pkill epmd
- ```
-
-1. remove bigcouch:
-
- ```
- server# apt-get remove bigcouch
- ```
-
-1. configure your couch node to use plain couchdb instead of bigcouch, you can do this by editing nodes/<couch-node>.json, look for this section:
-
- ```
- "couch": {
- "mode": "plain"
- }
- ```
-change it, so it looks like this instead:
-
- ```
- "couch": {
- "mode": "plain",
- "pwhash_alg": "pbkdf2"
- }
- ```
-
diff --git a/doc/common/_bigcouch_migration_end.md b/doc/common/_bigcouch_migration_end.md
deleted file mode 100644
index a47d3c55..00000000
--- a/doc/common/_bigcouch_migration_end.md
+++ /dev/null
@@ -1,26 +0,0 @@
-1. restore the backup, this will take approximately the same amount of time as the backup took above:
-
- ```
- server# cd /srv/leap/couchdb/scripts
- server# time ./couchdb_restoreall.sh
- ```
-
-1. start services again that were stopped in the beginning:
-
- ```
- workstation$ leap ssh soledad-nodes
- server# /etc/init.d/soledad-server start
-
- workstation$ leap ssh mx-node
- server# /etc/init.d/postfix start
- server# /etc/init.d/leap-mx start
-
- workstation$ leap ssh webapp
- server# /etc/init.d/nickserver start
- ```
-
- Or, alternately, if you set up the firewall rule instead, now remove it:
-
- ```
- server# iptables -D INPUT -p tcp --dport 5984 --jump REJECT
- ```
diff --git a/doc/common/_bigcouch_migration_finish.md b/doc/common/_bigcouch_migration_finish.md
deleted file mode 100644
index 5aae9207..00000000
--- a/doc/common/_bigcouch_migration_finish.md
+++ /dev/null
@@ -1,10 +0,0 @@
-
-1. check if everything is working, including running the test on your deployment machine:
-
- ```
- workstation$ leap test
- ```
-
-1. Remove old bigcouch data dir `/opt` after you double checked everything is in place
-
-1. Relax, enjoy a refreshing beverage.
diff --git a/doc/details/development.md b/doc/details/development.md
deleted file mode 100644
index 78915add..00000000
--- a/doc/details/development.md
+++ /dev/null
@@ -1,78 +0,0 @@
-@title = 'Development'
-@summary = "Getting started with making changes to the LEAP platform"
-
-Installing leap_cli
-------------------------------------------------
-
-### From gem, for a single user
-
-Install the latest:
-
- gem install leap_cli --install-dir ~/leap
- export PATH=$PATH:~/leap/bin
-
-Install a particular version:
-
- gem install leap_cli --version 1.8 --install-dir ~/leap
- export PATH=$PATH:~/leap/bin
-
-### From gem, system wide
-
-Install the latest:
-
- sudo gem install leap_cli
-
-Install a particular version:
-
- sudo gem install leap_cli --version 1.8
-
-### As a gem, built from source
-
- sudo apt-get install ruby ruby-dev rake
- git clone https://leap.se/git/leap_cli.git
- cd leap_cli
- git checkout develop
- rake build
- sudo rake install
-
-### The "develop" branch from source, for a single user
-
- sudo apt-get install ruby ruby-dev rake
- git clone https://leap.se/git/leap_cli.git
- cd leap_cli
- git checkout develop
-
-Then do one of the following to be able to run `leap` command:
-
- cd leap_cli
- export PATH=$PATH:`pwd`/bin
- alias leap="`pwd`/bin/leap"
- ln -s `pwd`/bin/leap ~/bin/leap
-
-In practice, of course, you would put aliases or PATH modifications in a shell startup file.
-
-You can also clone from https://github.com/leap/leap_cli
-
-Running different leap_cli versions
----------------------------------------------
-
-### If installed as a gem
-
-With rubygems, you can always specify the gem version as the first argument to any executable installed by rubygems. For example:
-
- sudo gem install leap_cli --version 1.7.2
- sudo gem install leap_cli --version 1.8
- leap _1.7.2_ --version
- => leap 1.7.2, ruby 2.1.2
- leap _1.8_ --version
- => leap 1.8, ruby 2.1.2
-
-### If running from source
-
-Alternately, if you are running from source, you can alias different commands:
-
- git clone https://leap.se/git/leap_cli.git
- cd leap_cli
- git checkout develop
- alias leap_develop="`pwd`/bin/leap`
-
diff --git a/doc/details/en.haml b/doc/details/en.haml
deleted file mode 100644
index fe7a4c84..00000000
--- a/doc/details/en.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- @nav_title = "Details"
-- @title = 'Platform Details'
-
-= child_summaries \ No newline at end of file
diff --git a/doc/details/faq.md b/doc/details/faq.md
deleted file mode 100644
index 7ee20f4d..00000000
--- a/doc/details/faq.md
+++ /dev/null
@@ -1,71 +0,0 @@
-@title = 'Frequently asked questions'
-@nav_title = 'FAQ'
-@summary = "Frequently Asked Questions"
-@toc = true
-
-APT
-===============
-
-What do I do when unattended upgrades fail?
---------------------------------------------------
-
-When you receive notification e-mails with a subject of 'unattended-upgrades result for $machinename', that means that some package couldn't be automatically upgraded and needs manual interaction. The reasons vary, so you have to be careful. Most often you can simply login to the affected machine and run `apt-get dist-upgrade`.
-
-Puppet
-======
-
-Where do i find the time a server was last deployed ?
------------------------------------------------------
-
-Run:
-
- leap history FILTER
-
-This will tail the log file `/var/log/leap/deploy-summary.log`.
-
-If that command fails, you can manually check the puppet state file on the node indicates the last puppetrun:
-
- ls -la /var/lib/puppet/state/state.yaml
-
-What resources are touched by puppet/leap_platform (services/packages/files etc.) ?
------------------------------------------------------------------------------------
-
-Log into your server and issue:
-
- grep -v '!ruby/sym' /var/lib/puppet/state/state.yaml | sed 's/\"//' | sort
-
-
-How can i customize the leap_platform puppet manifests ?
---------------------------------------------------------
-
-You can create custom puppet modules under `files/puppet`.
-The custom puppet entry point is in class 'custom' which can be put into
-`files/puppet/modules/custom/manifests/init.pp`. This class gets automatically included
-by site_config::default, which is applied to all nodes.
-
-Of cause you can also create a different git branch and change whatever you want, if you are
-familiar wit git.
-
-Facter
-======
-
-How can i see custom facts distributed by leap_platform on a node ?
--------------------------------------------------------------------
-
-On the server, export the FACTERLIB env. variable to include the path of the custom fact in question:
-
- export FACTERLIB=/var/lib/puppet/lib/facter:/srv/leap/puppet/modules/stdlib/lib/facter/
- facter
-
-
-Etc
-===
-
-How do i change the domain of my provider ?
--------------------------------------------
-
-* First of all, you need to have access to the nameserver config of your new domain.
-* Update domain in provider.json
-* remove all ca and cert files: `rm files/cert/* files/ca/*`
-* create ca, csr and certs : `leap cert ca; leap cert csr; leap cert dh; leap cert update`
-* deploy
diff --git a/doc/details/ports.md b/doc/details/ports.md
deleted file mode 100644
index f7c485ca..00000000
--- a/doc/details/ports.md
+++ /dev/null
@@ -1,92 +0,0 @@
-@title = "Ports"
-@summary = "The required open ports for different services."
-@toc = true
-
-There are many different ports that must be open in order for the LEAP platform to work. Some ports must be *publicly open*, meaning that these should be accessible from the public internet. Other ports are *privately open*, meaning that they must be accessible to sysadmins or to the other nodes in the provider's infrastructure.
-
-Every node already includes a host-based firewall. However, if your network has its own firewall, you need to make sure that these ports are not blocked.
-
-Publicly open ports
---------------------------------
-
-<table class="table table-striped">
-<tr>
- <th>Name</th>
- <th>Node Type</th>
- <th>Default</th>
- <th>Notes</th>
-</tr>
-<tr>
- <td>SMTP</td>
- <td>mx</td>
- <td>25</td>
- <td>This is required for all server-to-server SMTP email relay. This is not configurable.</td>
-</tr>
-<tr>
- <td>HTTP</td>
- <td>webapp</td>
- <td>80</td>
- <td>Although no actual services are available over port 80, it should be unblocked so that the web app can redirect to port 443. This is not configurable.</td>
-</tr>
-<tr>
- <td>HTTPS</td>
- <td>webapp</td>
- <td>443</td>
- <td>The web application is available over this port. This is not configurable.</td>
-</tr>
-<tr>
- <td>SMTPS</td>
- <td>mx</td>
- <td>465</td>
- <td>The client uses this port to submit outgoing email messages via SMTP over TLS. There is no easy way to change this, although you can create a custom <code>files/service-definitions/v1/smtp-service.json.erb</code> to do so. This will be changed to port 443 in the future.</td>
-</tr>
-<tr>
- <td>Soledad</td>
- <td>soledad</td>
- <td>2323</td>
- <td>The client uses this port to synchronize its storage data. This can be changed via the configuration property <code>soledad.port</code>. This will be changed to port 443 in the future.</td>
-</tr>
-<tr>
- <td>Nicknym</td>
- <td>webapp</td>
- <td>6425</td>
- <td>The client uses this port for discovering public keys. This can be changed via the configuration property <code>nickserver.port</code>. This will be changed to port 443 in the future.</td>
-</tr>
-<tr>
- <td>OpenVPN</td>
- <td>openvpn</td>
- <td>80, 443, 53, 1194</td>
- <td>By default, OpenVPN gateways will listen on all those ports. This can be changed via the configuration property <code>openvpn.ports</code>. Note that these ports must be open for <code>openvpn.gateway_address</code>, not for <code>ip_address</code>.</td>
-</tr>
-<tr>
- <td>API</td>
- <td>webapp</td>
- <td>4430</td>
- <td>Currently, the provider API is accessible via this port. In the future, the default will be changed to 443. For now, this can be changed via the configuration property <code>api.port</code>.</td>
-</tr>
-</table>
-
-Privately open ports
----------------------------------------
-
-<table class="table table-striped">
-<tr>
- <th>Name</th>
- <th>Node Type</th>
- <th>Default</th>
- <th>Notes</th>
-</tr>
-<tr>
- <td>SSH</td>
- <td>all</td>
- <td>22</td>
- <td>This is the port that the sshd is bound to for the node. You can modify this using the configuration property <code>ssh.port</code>. It is important that this port is never blocked, or you will lose access to deploy to this node.</td>
-</tr>
-<tr>
- <td>Stunnel</td>
- <td>all</td>
- <td>10000-20000</td>
- <td>This is the range of ports that might be used for the encrypted stunnel connections between two nodes. These port numbers are automatically generated, but will fall somewhere in the specified range.</td>
-</tr>
-</table>
-
diff --git a/doc/details/under-the-hood.md b/doc/details/under-the-hood.md
deleted file mode 100644
index 0bc4fe77..00000000
--- a/doc/details/under-the-hood.md
+++ /dev/null
@@ -1,40 +0,0 @@
-@title = "Under the hood"
-@summary = "Various implementation details."
-
-This page contains various details on the how the platform is implemented. You can safely ignore this page, although it may be useful if you plan to make modifications to the platform.
-
-Puppet Details
-======================================
-
-Tags
-----
-
-Tags are beeing used to deploy different classes.
-
-* leap_base: site_config::default (configure hostname + resolver, sshd, )
-* leap_slow: site_config::slow (slow: apt-get update, apt-get dist-upgrade)
-* leap_service: cofigure platform service (openvpn, couchdb, etc.)
-
-You can pass any combination of tags, i.e. use
-
-* "--tags leap_base,leap_slow,leap_service" (DEFAULT): Deploy all
-* "--tags leap_service": Only deploy service(s) (useful for debugging/development)
-* "--tags leap_base": Only deploy basic configuration (again, useful for debugging/development)
-
-
-### Doing faster partial deploys
-
-If you only change a tiny bit on the platform puppet recipes, you could achieve a
-*much* faster deploy specifying the resource tag you changed.
-i.e. you changed the way rsyslog config snippets for LEAP logfiles are created
-in `puppet/modules/leap/manifests/logfile.pp`. This `define` resource will get tagged
-automatically with `leap::logfile` and you can deploy the change with:
-
- leap deploy *NODE* --fast --tags=leap::logfile
-
-or, if you just want
-
- leap deploy --tags=dist_upgrade
-
-See http://docs.puppetlabs.com/puppet/2.7/reference/lang_tags.html for puppet tag usage.
-
diff --git a/doc/en.md b/doc/en.md
deleted file mode 100644
index 098aacb1..00000000
--- a/doc/en.md
+++ /dev/null
@@ -1,82 +0,0 @@
-@title = 'LEAP Platform for Service Providers'
-@summary = "The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment."
-@nav_title = 'Provider Platform'
-@this.toc = false
-
-Its goal is to make it as painless as possible for sysadmins to deploy and maintain a service provider's infrastructure for secure communication.
-
-**REQUIREMENTS** -- Before you begin, make sure you meet these requirements:
-
-* *Debian Servers*: Servers that you deploy to must be running **Debian Jessie**, and no other distribution or version.
-* *Real or Paravirtualized Servers*: Servers must be real machines or paravirtualized VMs (e.g. KVM, Xen, OpenStack, AWS, Google Compute). OS level virtualization is not supported (e.g. OpenVZ, Linux-VServer, etc), nor are system emulators (VirtualBox, QEMU, etc).
-* *Your Workstation*: You must have a Linux or Mac computer to deploy from (this can be a headless machine with no GUI). Windows is not supported (Cygwin would probably work, but is untested).
-* *Your Own Domain*: You must own a domain name. Before your provider can be put into production, you will need to make modifications to the DNS for the provider's domain.
-
-The LEAP Platform consists of three parts, detailed below:
-
-1. [The platform recipes.](#the-platform-recipes)
-2. [The provider instance.](#the-provider-instance)
-3. [The `leap` command line tool.](#the-leap-command-line-tool)
-
-The platform recipes
---------------------
-
-The LEAP platform recipes define an abstract service provider. It is a set of [Puppet](https://puppetlabs.com/puppet/puppet-open-source/) modules designed to work together to provide to sysadmins everything they need to manage a service provider infrastructure that provides secure communication services.
-
-LEAP maintains a repository of platform recipes, which typically do not need to be modified, although it can be forked and merged as desired. Most service providers using the LEAP platform can use the same set of platform recipes.
-
-As these recipes consist in abstract definitions, in order to configure settings for a particular service provider a system administrator has to create a provider instance (see below).
-
-LEAP's platform recipes are distributed as a git repository: `https://leap.se/git/leap_platform`
-
-The provider instance
----------------------
-
-A provider instance is a directory tree (typically tracked in git) containing all the configurations for a service provider's infrastructure. A provider instance **lives on your workstation**, not on the server.
-
-A provider instance primarily consists of:
-
-* A pointer to the platform recipes.
-* A global configuration file for the provider.
-* A configuration file for each server (node) in the provider's infrastructure.
-* Additional files, such as certificates and keys.
-
-A minimal provider instance directory looks like this:
-
- └── bitmask # provider instance directory.
- ├── Leapfile # settings for the `leap` command line tool.
- ├── provider.json # global settings of the provider.
- ├── common.json # settings common to all nodes.
- ├── nodes/ # a directory for node configurations.
- ├── files/ # keys, certificates, and other files.
- └── users/ # public key information for privileged sysadmins.
-
-A provider instance directory contains everything needed to manage all the servers that compose a provider's infrastructure. Because of this, any versioning tool and development work-flow can be used to manage your provider instance.
-
-The `leap` command line tool
-----------------------------
-
-The `leap` [command line tool](commands) is used by sysadmins to manage everything about a service provider's infrastructure.
-
-Keep these rules in mind:
-
-* `leap` is run on your workstation: The `leap` command is always run locally on your workstation, never on a server you are deploying to.
-* `leap` is run from within a provider instance: The `leap` command requires that the current working directory is a valid provider instance, except when running `leap new` to create a new provider instance.
-
-The `leap` command line has many capabilities, including:
-
-* Create, initialize, and deploy nodes.
-* Manage keys and certificates.
-* Query information about the node configurations.
-
-Everything about your provider is managed by editing JSON configuration files and running `leap` commands.
-
-What is next?
-----------------------------------
-
-We recommend reading the platform documentation in the following order:
-
-1. [[quick-start]]
-2. [[getting-started]]
-3. [[platform/guide]]
-
diff --git a/doc/guide/commands.md b/doc/guide/commands.md
deleted file mode 100644
index 2ddacb83..00000000
--- a/doc/guide/commands.md
+++ /dev/null
@@ -1,559 +0,0 @@
-@title = 'Command Line Reference'
-@summary = 'A copy of leap --help'
-
-The command "leap" can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.
-
-
-# Global Options
-
-* `--log FILE`
-Override default log file.
-Default Value: None
-
-* `-v|--verbose LEVEL`
-Verbosity level 0..5
-Default Value: 1
-
-* `--[no-]color`
-Disable colors in output.
-
-* `-d|--debug`
-Print full stack trace for exceptions and load `debugger` gem if installed.
-
-* `--force`
-Like --yes, but also skip prompts that are potentially dangerous to skip.
-
-* `--help`
-Show this message
-
-* `--version`
-Display version number and exit.
-
-* `--yes`
-Skip prompts and assume "yes".
-
-
-# leap add-user USERNAME
-
-Adds a new trusted sysadmin by adding public keys to the "users" directory.
-
-
-
-**Options**
-
-* `--pgp-pub-key arg`
-OpenPGP public key file for this new user
-Default Value: None
-
-* `--ssh-pub-key arg`
-SSH public key file for this new user
-Default Value: None
-
-* `--self`
-Add yourself as a trusted sysadmin by choosing among the public keys available for the current user.
-
-
-# leap cert
-
-Manage X.509 certificates
-
-
-
-## leap cert ca
-
-Creates two Certificate Authorities (one for validating servers and one for validating clients).
-
-See see what values are used in the generation of the certificates (like name and key size), run `leap inspect provider` and look for the "ca" property. To see the details of the created certs, run `leap inspect <file>`.
-
-## leap cert csr
-
-Creates a CSR for use in buying a commercial X.509 certificate.
-
-Unless specified, the CSR is created for the provider's primary domain. The properties used for this CSR come from `provider.ca.server_certificates`, but may be overridden here.
-
-**Options**
-
-* `--bits BITS`
-Override default certificate bit length
-Default Value: None
-
-* `--country|-C COUNTRY`
-Set C in distinguished name.
-Default Value: None
-
-* `--digest DIGEST`
-Override default signature digest
-Default Value: None
-
-* `--domain DOMAIN`
-Specify what domain to create the CSR for.
-Unless specified, the CSR is created for the provider's primary domain. The properties used for this CSR come from `provider.ca.server_certificates`, but may be overridden here.
-Default Value: None
-
-* `--email EMAIL`
-Set emailAddress in distinguished name.
-Default Value: None
-
-* `--locality|-L LOCALITY`
-Set L in distinguished name.
-Default Value: None
-
-* `--organization|-O ORGANIZATION`
-Override default O in distinguished name.
-Default Value: None
-
-* `--state|--ST STATE`
-Set ST in distinguished name.
-Default Value: None
-
-* `--unit|--OU UNIT`
-Set OU in distinguished name.
-Default Value: None
-
-
-## leap cert dh
-
-Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers.
-
-
-
-## leap cert update FILTER
-
-Creates or renews a X.509 certificate/key pair for a single node or all nodes, but only if needed.
-
-This command will a generate new certificate for a node if some value in the node has changed that is included in the certificate (like hostname or IP address), or if the old certificate will be expiring soon. Sometimes, you might want to force the generation of a new certificate, such as in the cases where you have changed a CA parameter for server certificates, like bit size or digest hash. In this case, use --force. If <node-filter> is empty, this command will apply to all nodes.
-
-**Options**
-
-* `--force`
-Always generate new certificates
-
-
-# leap clean
-
-Removes all files generated with the "compile" command.
-
-
-
-# leap compile
-
-Compile generated files.
-
-
-
-## leap compile all [ENVIRONMENT]
-
-Compiles node configuration files into hiera files used for deployment.
-
-
-
-## leap compile firewall
-
-Prints a list of firewall rules. These rules are already implemented on each node, but you might want the list of all rules in case you also have a restrictive network firewall.
-
-
-
-## leap compile hosts
-
-Print entries suitable for an /etc/hosts file, useful for testing your provider.
-
-
-
-## leap compile provider.json
-
-Compile provider.json bootstrap files for your provider.
-
-
-
-## leap compile zone
-
-Prints a DNS zone file for your provider.
-
-
-Default Command: all
-
-# leap db
-
-Database commands.
-
-
-
-## leap db destroy [FILTER]
-
-Destroy one or more databases. If present, limit to FILTER nodes. For example `leap db destroy --db sessions,tokens testing`.
-
-
-
-**Options**
-
-* `--db DATABASES`
-Comma separated list of databases to destroy (no space). Use "--db all" to destroy all databases.
-Default Value: None
-
-* `--user USERS`
-Comma separated list of usernames. The storage databases for these user(s) will be destroyed.
-Default Value: None
-
-
-# leap debug FILTER
-
-Output debug information.
-
-The FILTER can be the name of a node, service, or tag.
-
-# leap deploy FILTER
-
-Apply recipes to a node or set of nodes.
-
-The FILTER can be the name of a node, service, or tag.
-
-**Options**
-
-* `--ip IPADDRESS`
-Override the default SSH IP address.
-Default Value: None
-
-* `--port PORT`
-Override the default SSH port.
-Default Value: None
-
-* `--tags TAG[,TAG]`
-Specify tags to pass through to puppet (overriding the default).
-Default Value: None
-
-* `--dev`
-Development mode: don't run 'git submodule update' before deploy.
-
-* `--downgrade`
-Allows deploy to run with an older platform version.
-
-* `--fast`
-Makes the deploy command faster by skipping some slow steps. A "fast" deploy can be used safely if you recently completed a normal deploy.
-
-* `--force`
-Deploy even if there is a lockfile.
-
-* `--sync`
-Sync files, but don't actually apply recipes.
-
-
-# leap env
-
-Manipulate and query environment information.
-
-The 'environment' node property can be used to isolate sets of nodes into entirely separate environments. A node in one environment will never interact with a node from another environment. Environment pinning works by modifying your ~/.leaprc file and is dependent on the absolute file path of your provider directory (pins don't apply if you move the directory)
-
-## leap env ls [ENVIRONMENT]
-
-List the available environments. The pinned environment, if any, will be marked with '*'. Will also set the pin if run with an environment argument.
-
-
-
-## leap env pin ENVIRONMENT
-
-Pin the environment to ENVIRONMENT. All subsequent commands will only apply to nodes in this environment.
-
-
-
-## leap env unpin
-
-Unpin the environment. All subsequent commands will apply to all nodes.
-
-
-Default Command: ls
-
-# leap facts
-
-Gather information on nodes.
-
-
-
-## leap facts update FILTER
-
-Query servers to update facts.json.
-
-Queries every node included in FILTER and saves the important information to facts.json
-
-# leap help command
-
-Shows a list of commands or help for one command
-
-Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function
-
-**Options**
-
-* `-c`
-List commands one per line, to assist with shell completion
-
-
-# leap history FILTER
-
-Display recent deployment history for a set of nodes.
-
-The FILTER can be the name of a node, service, or tag.
-
-**Options**
-
-* `--ip IPADDRESS`
-Override the default SSH IP address.
-Default Value: None
-
-* `--port PORT`
-Override the default SSH port.
-Default Value: None
-
-* `--last`
-Show last deploy only
-
-
-# leap inspect FILE
-
-Prints details about a file. Alternately, the argument FILE can be the name of a node, service or tag.
-
-
-
-**Options**
-
-* `--base`
-Inspect the FILE from the provider_base (i.e. without local inheritance).
-
-
-# leap list [FILTER]
-
-List nodes and their classifications
-
-Prints out a listing of nodes, services, or tags. If present, the FILTER can be a list of names of nodes, services, or tags. If the name is prefixed with +, this acts like an AND condition. For example:
-
-`leap list node1 node2` matches all nodes named "node1" OR "node2"
-
-`leap list openvpn +local` matches all nodes with service "openvpn" AND tag "local"
-
-**Options**
-
-* `--print arg`
-What attributes to print (optional)
-Default Value: None
-
-* `--disabled`
-Include disabled nodes in the list.
-
-
-# leap local
-
-Manage local virtual machines.
-
-This command provides a convient way to manage Vagrant-based virtual machines. If FILTER argument is missing, the command runs on all local virtual machines. The Vagrantfile is automatically generated in 'test/Vagrantfile'. If you want to run vagrant commands manually, cd to 'test'.
-
-## leap local destroy [FILTER]
-
-Destroys the virtual machine(s), reclaiming the disk space
-
-
-
-## leap local reset [FILTER]
-
-Resets virtual machine(s) to the last saved snapshot
-
-
-
-## leap local save [FILTER]
-
-Saves the current state of the virtual machine as a new snapshot
-
-
-
-## leap local start [FILTER]
-
-Starts up the virtual machine(s)
-
-
-
-**Options**
-
-* `--basebox BASEBOX`
-The basebox to use. This value is passed to vagrant as the `config.vm.box` option. The value here should be the name of an installed box or a shorthand name of a box in HashiCorp's Atlas.
-Default Value: LEAP/jessie
-
-
-## leap local status [FILTER]
-
-Print the status of local virtual machine(s)
-
-
-
-## leap local stop [FILTER]
-
-Shuts down the virtual machine(s)
-
-
-
-# leap mosh NAME
-
-Log in to the specified node with an interactive shell using mosh (requires node to have mosh.enabled set to true).
-
-
-
-**Options**
-
-* `--port SSH_PORT`
-Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.
-Default Value: None
-
-* `--ssh arg`
-Pass through raw options to ssh (e.g. `--ssh '-F ~/sshconfig'`).
-Default Value: None
-
-
-# leap new DIRECTORY
-
-Creates a new provider instance in the specified directory, creating it if necessary.
-
-
-
-**Options**
-
-* `--contacts arg`
-Default email address contacts.
-Default Value: None
-
-* `--domain arg`
-The primary domain of the provider.
-Default Value: None
-
-* `--name arg`
-The name of the provider.
-Default Value: None
-
-* `--platform arg`
-File path of the leap_platform directory.
-Default Value: None
-
-
-# leap node
-
-Node management
-
-
-
-## leap node add NAME [SEED]
-
-Create a new configuration file for a node named NAME.
-
-If specified, the optional argument SEED can be used to seed values in the node configuration file.
-
-The format is property_name:value.
-
-For example: `leap node add web1 ip_address:1.2.3.4 services:webapp`.
-
-To set nested properties, property name can contain '.', like so: `leap node add web1 ssh.port:44`
-
-Separeate multiple values for a single property with a comma, like so: `leap node add mynode services:webapp,dns`
-
-**Options**
-
-* `--local`
-Make a local testing node (by automatically assigning the next available local IP address). Local nodes are run as virtual machines on your computer.
-
-
-## leap node init FILTER
-
-Bootstraps a node or nodes, setting up SSH keys and installing prerequisite packages
-
-This command prepares a server to be used with the LEAP Platform by saving the server's SSH host key, copying the authorized_keys file, installing packages that are required for deploying, and registering important facts. Node init must be run before deploying to a server, and the server must be running and available via the network. This command only needs to be run once, but there is no harm in running it multiple times.
-
-**Options**
-
-* `--ip IPADDRESS`
-Override the default SSH IP address.
-Default Value: None
-
-* `--port PORT`
-Override the default SSH port.
-Default Value: None
-
-* `--echo`
-If set, passwords are visible as you type them (default is hidden)
-
-
-## leap node mv OLD_NAME NEW_NAME
-
-Renames a node file, and all its related files.
-
-
-
-## leap node rm NAME
-
-Removes all the files related to the node named NAME.
-
-
-
-# leap scp FILE1 FILE2
-
-Secure copy from FILE1 to FILE2. Files are specified as NODE_NAME:FILE_PATH. For local paths, omit "NODE_NAME:".
-
-
-
-**Options**
-
-* `-r`
-Copy recursively
-
-
-# leap ssh NAME
-
-Log in to the specified node with an interactive shell.
-
-
-
-**Options**
-
-* `--port SSH_PORT`
-Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.
-Default Value: None
-
-* `--ssh arg`
-Pass through raw options to ssh (e.g. `--ssh '-F ~/sshconfig'`).
-Default Value: None
-
-
-# leap test
-
-Run tests.
-
-
-
-## leap test init
-
-Creates files needed to run tests.
-
-
-
-## leap test run [FILTER]
-
-Run the test suit on FILTER nodes.
-
-
-
-**Options**
-
-* `--[no-]continue`
-Continue over errors and failures (default is --no-continue).
-
-Default Command: run
-
-# leap tunnel [LOCAL_PORT:]NAME:REMOTE_PORT
-
-Creates an SSH port forward (tunnel) to the node NAME. REMOTE_PORT is the port on the remote node that the tunnel will connect to. LOCAL_PORT is the optional port on your local machine. For example: `leap tunnel couch1:5984`.
-
-
-
-**Options**
-
-* `--port SSH_PORT`
-Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.
-Default Value: None
-
-* `--ssh arg`
-Pass through raw options to ssh (e.g. --ssh '-F ~/sshconfig').
-Default Value: None
-
diff --git a/doc/guide/config.md b/doc/guide/config.md
deleted file mode 100644
index bcea26c4..00000000
--- a/doc/guide/config.md
+++ /dev/null
@@ -1,360 +0,0 @@
-@title = "Configuration Files"
-@summary = "Understanding and editing the configuration files."
-
-Files
--------------------------------------------
-
-Here are a list of some of the common files that make up a provider. Except for `Leapfile` and `provider.json`, the files are optional. Unless otherwise specified, all file names are relative to the 'provider directory' root (where the Leapfile is).
-
-<table class="table table-striped">
-<tr>
- <td><code>Leapfile</code></td>
- <td>If present, this file tells <code>leap</code> that the directory is a provider directory. This file is usually empty, but can contain global options.</td>
-</tr>
-<tr>
- <td><code>~/.leaprc</code></td>
- <td>Evaluated the same as Leapfile, but not committed to source control.</td>
-</tr>
-<tr>
- <td><code>provider.json</code></td>
- <td>Global options related to this provider. See [[provider-configuration]].</td>
-</tr>
-<tr>
- <td><code>provider.ENVIRONMENT.json</code></td>
- <td>Global options for the provider that are applied to only a single environment.</td>
-</tr>
-<tr>
- <td><code>nodes/NAME.json</code></td>
- <td>The configuration file for node called NAME.</td>
-</tr>
-<tr>
- <td><code>common.json</code></td>
- <td>All nodes inherit from this file. In other words, any options that appear in <code>common.json</code> will be added as default values to each node configuration, value that can be locally overridden.</td>
-</tr>
-<tr>
- <td><code>services/SERVICE.json</code></td>
- <td>The properties in this configuration file are applied to any node that includes SERVICE in its <code>services</code> property.</td>
-</tr>
-<tr>
- <td><code>services/SERVICE.ENVIRONMENT.json</code></td>
- <td>The properties in this configuration file are applied to any node that includes SERVICE in its services and has environment equal to ENVIRONMENT.</td>
-</tr>
-<tr>
- <td><code>tags/TAG.json</code></td>
- <td>The properties in this configuration file are applied to any node that has includes TAG in its <code>tags</code> property.</td>
-</tr>
-<tr>
- <td><code>tags/TAG.ENVIRONMENT.json</code></td>
- <td>The properties in this configuration file are applied to any node that has includes TAG in its <code>tags</code> property and has <code>environment</code> property equal to ENVIRONMENT.</td>
-</tr>
-<tr>
- <td><code>secrets.json </code></td>
- <td>An automatically generated file that contains any randomly generated strings needed in order to deploy. These strings are often secret and should be protected, although any need for a random string or number that is remembered will produce another entry in this file. This file is automatically generated and refreshed each time you run <code>leap compile</code> or <code>leap deploy</code>. If an entry is no longer needed, it will get removed. If you want to change a secret, you can remove this file and have it regenerated, or remove the particular line item and just those items will be created anew.</td>
-</tr>
-<tr>
- <td><code>facts.json</code></td>
- <td>If some of your servers are running on AWS or OpenStack, you will need to discover certain properties about how networking is configured on these machines in order for a full deploy to work. In these cases, make sure to run <code>leap facts update</code> to periodically regenerate the facts.json file.</td>
-</tr>
-<tr>
- <td><code>files/*</code></td>
- <td>Various static files used by the platform (e.g. keys, certificates, webapp customization, etc). In general, only generated files and files used to customize the provider (such as images) live in the <code>files</code> directory.</td>
-</tr>
-<tr>
- <td><code>users/USER/</code></td>
- <td>A directory that stores the public keys of the sysadmin with name USER. This person will have root access to all the servers.</td>
-</tr>
-</table>
-
-Leapfile
--------------------------------------------
-
-A `Leapfile` defines options for the `leap` command and lives at the root of your provider directory. `Leapfile` is evaluated as ruby, so you can include whatever weird logic you want in this file. In particular, there are several variables you can set that modify the behavior of leap. For example:
-
- @platform_directory_path = '../leap_platform'
- @log = '/var/log/leap.log'
-
-Additionally, you can create a `~/.leaprc` file that is loaded after `Leapfile` and is evaluated the same way.
-
-Platform options:
-
-* `@platform_directory_path` (required). This must be set to the path where `leap_platform` lives. The path may be relative.
-
-Vagrant options:
-
-* `@vagrant_provider`. Changes the default vagrant provider ("virtualbox"). For example, `@vagrant_provider = "libvirt"`.
-* `@vagrant_network`. Allows you to override the default network used for local nodes. It should include a netmask like `@vagrant_network = '10.0.0.0/24'`.
-* `@custom_vagrant_vm_line`. Insert arbitrary text into the auto-generated Vagrantfile. For example, `@custom_vagrant_vm_line = "config.vm.boot_mode = :gui"`.
-* `@vagrant_basebox` allows specifying a different basebox as the default one. For example, `@vagrant_basebox = "LEAP/jessie"`.
-
-Logging options:
-
-* `@log`. If set, all command invocation and results are logged to the specified file. This is the same as the switch `--log FILE`, except that the command line switch will override the value in the Leapfile.
-
-
-JSON format
--------------------------------------------
-
-All configuration files, other than `Leapfile`, are in the JSON format. For example:
-
- {
- "key1": "value1",
- "key2": "value2"
- }
-
-Keys should match `/[a-z0-9_]/` and must be in double quotes.
-
-Unlike traditional JSON, comments are allowed. If the first non-whitespace characters are `//` then the line is treated as a comment.
-
- // this is a comment
- {
- // this is a comment
- "key": "value" // this is an error
- }
-
-Options in the configuration files might be nested hashes, arrays, numbers, strings, or boolean. Numbers and boolean values should **not** be quoted. For example:
-
- {
- "openvpn": {
- "ip_address": "1.1.1.1",
- "protocols": ["tcp", "udp"],
- "ports": [80, 53],
- "options": {
- "public_ip": false,
- "adblock": true
- }
- }
- }
-
-If the value string is prefixed with an '=' character, the result is evaluated as ruby. For example:
-
- {
- "domain": {
- "public": "domain.org"
- }
- "api_domain": "= 'api.' + domain.public"
- }
-
-In this case, the property "api_domain" will be set to "api.domain.org". So long as you do not create unresolvable circular dependencies, you can reference other properties in evaluated ruby that are themselves evaluated ruby.
-
-See "Macros" below for information on the special macros available to the evaluated ruby.
-
-TIP: In rare cases, you might want to force the evaluation of a value to happen in a later pass after most of the other properties have been evaluated. To do this, prefix the value string with "=>" instead of "=".
-
-Node inheritance
-----------------------------------------
-
-Every node inherits from common.json and also any of the services or tags attached to the node. Additionally, the `leap_platform` contains a directory `provider_base` that defines the default values for tags, services and common.json.
-
-Suppose you have a node configuration for `bitmask/nodes/willamette.json` like so:
-
- {
- "services": "webapp",
- "tags": ["production", "northwest-us"],
- "ip_address": "1.1.1.1"
- }
-
-This node will have hostname "willamette" and it will inherit from the following files (in this order):
-
-1. common.json
- - load defaults: `provider_base/common.json`
- - load provider: `bitmask/common.json`
-2. service "webapp"
- - load defaults: `provider_base/services/webapp.json`
- - load provider: `bitmask/services/webapp.json`
-3. tag "production"
- - load defaults: `provider_base/tags/production.json`
- - load provider: `bitmask/tags/production.json`
-4. tag "northwest-us"
- - load: `bitmask/tags/northwest-us.json`
-5. finally, load node "willamette"
- - load: `bitmask/nodes/willamette.json`
-
-The `provider_base` directory is under the `leap_platform` specified in the file `Leapfile`.
-
-To see all the variables a node has inherited, you could run `leap inspect willamette`.
-
-### Inheritance rules
-
-Suppose you have a node configuration `mynode.json`:
-
- {
- "tags": "production",
- "simple_value": 100,
- "replaced_array": ["dolphin", "kangaroo"],
- "+add_array": ["red", "black"],
- "-subtract_array": ["bitter"],
- "converted_to_array": "not_array_element",
- "!override": ["insist on this value"],
- "hash": {
- "key1": 1,
- "key2": 2
- }
- }
-
-And a file `tags/production.json`:
-
- {
- "simple_value": 99999,
- "replaced_array": ["zebra"],
- "add_array": ["green],
- "subtract_array": ["bitter", "sweet", "salty"],
- "converted_to_array": ["array_element"],
- "override": "this value will be overridden",
- "hash": {
- "key1": "one"
- }
- }
-
-In this scenario, `mynode.json` will inherit from `production.json`. The output of this inheritance will be:
-
- {
- "tags": "production",
- "simple_value": 100,
- "replaced_array": ["dolphin", "kangaroo"],
- "add_array": ["red", "black", "green"],
- "subtract_array": ["sweet", "salty"],
- "converted_to_array": ["not_array_element", "array_element"],
- "override": ["insist on this value"],
- "hash": {
- "key1": 1,
- "key2": 2
- }
-
-The rules for inheritance (where 'old' refers to the parent, and 'new' refers to the child):
-
-* Simple values (strings, numbers, boolean):
- * Replace the old value with the new value.
-* Array values:
- * Two arrays: replace the old array with the new array.
- * One array and one simple value: add the simple value to the array.
- * If property name is prefixed with "+": merge the old and new arrays.
- * If property name is prefixed with "-": subtract new array from old array.
-* Hash values:
- * Hashes are always merged (the result includes the keys of both hashes). If there is a key in common, the new one overrides the old one.
-* Mismatch:
- * Although you can mix arrays and simple values, you cannot mix arrays with hashes or hashes with simple values. If you attempt to do so, it will fail to compile and give you an error message.
-* Override:
- * If property name is prefixed with "!": then ensure that new value is always used, regardless of old value. In this case, the override takes precedence over type checking, so you will never get a type mismatch.
-
-NOTE: special property name prefixes, like "+", "-", or "!", are not included in the property name. These prefixes determine the merge strategy, but are stripped out when compiling the resulting JSON file.
-
-Common configuration options
-----------------------------------------
-
-You can use the command `leap inspect` to see what options are available for a provider, node, service, or tag configuration. For example:
-
-* `leap inspect common` -- show the options inherited by all nodes.
-* `leap inspect --base common` -- show the common.json from `provider_base` without the local `common.json` inheritance applied.
-* `leap inspect webapp` -- show all the options available for the service `webapp`.
-
-Here are some of the more important options you should be aware of:
-
-* `ip_address` -- Required for all nodes, no default.
-* `ssh.port` -- The SSH port you want the node's OpenSSH server to bind to. This is also the default when trying to connect to a node, but if the node currently has OpenSSH running on a different port then run deploy with `--port` to override the `ssh.port` configuration value.
-* `mosh.enabled` -- If set to `true`, then mosh will be installed on the server. The default is `false`.
-
-Macros
-----------------------------------------
-
-When using evaluated ruby in a JSON configuration file, there are several special macros that are available. These are evaluated in the context of a node (available as the variable `self`).
-
-The following methods are available to the evaluated ruby:
-
-`variable.variable`
-
- > Any variable defined or inherited by a particular node configuration is available by just referencing it using either hash notation or object field notation (e.g. `['domain']['public']` or `domain.public`). Circular references are not allowed, but otherwise it is OK to nest evaluated values in other evaluated values. If a value has not been defined, the hash notation will return nil but the field notation will raise an exception. Properties of services, tags, and the global provider can all be referenced the same way. For example, `global.services['openvpn'].x509.dh`.
-
-`nodes`
-
- > A hash of all nodes. This list can be filtered.
-
-`nodes_like_me`
-
- > A hash of nodes that have the same deployment tags as the current node (e.g. 'production' or 'local').
-
-`global.services`
-
- > A hash of all services, e.g. `global.services['openvpn']` would return the "openvpn" service.
-
-`global.tags`
-
- > A hash of all tags, e.g. `global.tags['production']` would return the "production" tag.
-
- `global.provider`
-
- > Can be used to access variables defined in `provider.json`, e.g. `global.provider.contacts.default`.
-
-`file(filename)`
-
- > Inserts the full contents of the file. If the file is an erb template, it is rendered. The filename can either be one of the pre-defined file symbols, or it can be a path relative to the "files" directory in your provider instance. E.g, `file :ca_cert` or `files 'ca/ca.crt'`.
-
-`file_path(filename)`
-
- > Ensures that the file will get rsynced to the node as an individual file. The value returned by `file_path` is the full path where this file will ultimately live when deploy to the node. e.g. `file_path :ca_cert` or `file_path 'branding/images/logo.png'`.
-
-`secret(:symbol)`
-
- > Returns the value of a secret in secrets.json (or creates it if necessary). E.g. `secret :couch_admin_password`
-
-`hosts_file`
-
- > Returns a data structure that puppet will use to generate /etc/hosts. Care is taken to use the local IP of other hosts when needed.
-
-`known_hosts_file`
-
- > Returns the lines needed in a SSH `known_hosts` file.
-
-`stunnel_client(node_list, port, options={})`
-
- > Returns a stunnel configuration data structure for the client side. Argument `node_list` is an `ObjectList` of nodes running stunnel servers. Argument `port` is the real port of the ultimate service running on the servers that the client wants to connect to.
-
-`stunnel_server(port)`
-
- > Generates a stunnel server entry. The `port` is the real port targeted service.
-
-Hash tables
------------------------------------------
-
-The macros `nodes`, `nodes_like_me`, `global.services`, and `global.tags` all return a hash table of configuration objects (either nodes, services, or tags). There are several ways to filter and process these hash tables:
-
-Access an element by name:
-
- nodes['vpn1'] # returns node named 'vpn1'
- global.services['openvpn'] # returns service named 'openvpn'
-
-Create a new hash table by applying filters:
-
- nodes[:public_dns => true] # all nodes where public_dns == true
- nodes[:services => 'openvpn', 'location.country_code' => 'US'] # openvpn service OR in the US.
- nodes[[:services, 'openvpn'], [:services, 'tor']] # services equal to openvpn OR tor
- nodes[:services => 'openvpn'][:tags => 'production'] # openvpn AND production
- nodes[:name => "!bob"] # all nodes that are NOT named "bob"
-
-Create an array of values by selecting a single field:
-
- nodes.field('location.name')
- ==> ['seattle', 'istanbul']
-
-Create an array of hashes by selecting multiple fields:
-
- nodes.fields('domain.full', 'ip_address')
- ==> [
- {'domain_full' => 'red.bitmask.net', 'ip_address' => '1.1.1.1'},
- {'domain_full' => 'blue.bitmask.net', 'ip_address' => '1.1.1.2'},
- ]
-
-Create a new hash table of hashes, with only certain fields:
-
- nodes.pick_fields('domain.full', 'ip_address')
- ==> {
- "red" => {'domain_full' => 'red.bitmask.net', 'ip_address' => '1.1.1.1'},
- "blue => {'domain_full' => 'blue.bitmask.net', 'ip_address' => '1.1.1.2'},
- }
-
-With `pick_fields`, if there is only one field, it will generate a simple hash table:
-
- nodes.pick_fields('ip_address')
- ==> {
- "red" => '1.1.1.1',
- "blue => '1.1.1.2',
- }
diff --git a/doc/guide/domains.md b/doc/guide/domains.md
deleted file mode 100644
index 914bce33..00000000
--- a/doc/guide/domains.md
+++ /dev/null
@@ -1,129 +0,0 @@
-@title = "Domains"
-@summary = "How to handle domain names and integrating LEAP with existing services."
-@toc = true
-
-Overview
---------------------------------
-
-Deploying LEAP can start to get very tricky when you need to integrate LEAP services with an existing domain that you already use or which already has users. Most of this complexity is unavoidable, although there are a few things we plan to do in the future to make this a little less painful.
-
-Because integration with legacy systems is an advanced topic, we recommend that you begin with a new domain. Once everything works and you are comfortable with your LEAP-powered infrastructure, you can then contemplate integrating with your existing domain.
-
-### Definitions
-
-**provider domain**
-
-This is the main domain used to identify the provider. The **provider domain** is what the user enters in the Bitmask client. e.g. `example.org`. The full host name of every node in your provider infrastructure will use the **provider domain** (e.g. `dbnode.example.org`).
-
-In order for the Bitmask client to get configured for use with a provider, it must be able to find the `provider.json` bootstrap file at the root of the **provider domain**. This is not needed if the Bitmask client is "pre-seeded" with the provider's information (these providers show up in a the initial list of available providers).
-
-**webapp domain**
-
-This is the domain that runs the leap_web application that allows users to register accounts, create help tickets, etc. e.g. `example.org` or `user.example.org`. The **webapp domain** defaults to the **provider domain** unless it is explicitly configured separately.
-
-**API domain**
-
-This is the domain that the provider API runs on. Typically, this is set automatically and you never need to configure it. The user should never be aware of this domain. e.g. `api.example.org`. The Bitmask client discovers this API domain by reading it from the `provider.json` file it grabs from the **provider domain**.
-
-**mail domain**
-
-This is the domain used for mail accounts, e.g. `username@example.org`. Currently, this is always the **provider domain**, but it may be independently configurable in the future.
-
-Generating a zone file
------------------------------------
-
-Currently, the platform does not include a dedicated `dns` service type, so you need to have your own setup for DNS. You can generate the appropriate configuration options with this command:
-
- leap compile zone
-
-A single domain
--------------------------------
-
-The easy approach is to use a single domain for **provider domain**, **webapp domain**, and **email domain**. This will install the webapp on the **provider domain**, which means that this domain must be a new one that you are not currently using for anything.
-
-To configure a single domain, just set the domain in `provider.json`:
-
- {
- "domain": "example.org"
- }
-
-If you have multiple environments, you can specify a different **provider domain** for each environment. For example:
-
-`provider.staging.json`
-
- {
- "domain": "staging.example.org"
- }
-
-A separate domain for the webapp
---------------------------------------
-
-It is possible make the **webapp domain** different than the **provider domain**. This is needed if you already have a website running at your **provider domain**.
-
-In order to put webapp on a different domain, you must take two steps:
-
-1. You must configure `webapp.domain` for nodes with the `webapp` service.
-2. You must make the compiled `provider.json` available at the root of the **provider domain**.
-
-NOTE: This compiled provider.json is different than the provider.json that you edit and lives in the root of the provider directory.
-
-### Step 1. Configuring `webapp.domain`
-
-In `services/webapp.json`:
-
- {
- "webapp": {
- "domain": "user.example.org"
- }
- }
-
-### Step 2. Putting the compiled `provider.json` in place
-
-Generate the compiled `provider.json`:
-
- leap compile provider.json
- = created files/web/bootstrap/
- = created files/web/bootstrap/README
- = created files/web/bootstrap/production/
- = created files/web/bootstrap/production/provider.json
- = created files/web/bootstrap/production/htaccess
- = created files/web/bootstrap/staging/
- = created files/web/bootstrap/staging/provider.json
- = created files/web/bootstrap/staging/htaccess
-
-This command compiles a separate `provider.json` for each environment, or "default" if you don't have an environment. In the example above, there is an environment called "production" and one called "staging", but your setup will probably differ.
-
-The resulting `provider.json` file must then be put at the root URL of your **provider domain** for the appropriate environment.
-
-There is one additional complication: currently, the Bitmask client tests for compatibility using some HTTP headers on the `/provider.json` response. This is will hopefully change in the future, but for now you need to ensure the right headers are set in the response. The included file `htaccess` has example directives for Apache, if that is what you use.
-
-This step can be skipped if you happen to use the `static` service to deploy an `amber` powered static website to **provider domain**. In this case, the correct `provider.json` will be automatically put into place.
-
-Integrating with existing email system
------------------------------------------
-
-If your **mail domain** already has users from a legacy email system, then things get a bit complicated. In order to be able to support both LEAP-powered email and legacy email on the same domain, you need to follow these steps:
-
-1. Modify the LEAP webapp so that it does not create users with the same name as users in the legacy system.
-2. Configure your legacy MX servers to forward mail that they cannot handle to the LEAP MX servers, or vice versa.
-
-### Step 1. Modify LEAP webapp
-
-In order to modify the webapp to respect the usernames already reserved by your legacy system, you need to modify the LEAP webapp code. The easiest way to do this is to create a custom gem that modifies the behavior of the webapp.
-
-For this example, we will call our custom gem `reserve_usernames`.
-
-This gem can live in one of two places:
-
-(1) You can fork the project leap_web and put the gem in `leap_web/vendor/gems/reserve_usernames`. Then, modify `Gemfile` and add the line `gem 'common_languages', :path => 'vendor/gems/reserve_usernames'`
-
-(2) Alternately, you can put the gem in the local provider directory `files/webapp/gems/reserve_username`. This will get synced to the webapp servers when you deploy and put in `/srv/leap/webapp/config/customization` where it will get automatically loaded by the webapp.
-
-What should the gem `reserve_usernames` look like? There is an example available here: https://leap.se/git/reserved_usernames.git
-
-This example gem uses ActiveResource to communicate with a remote REST API for creating and checking username reservations. This ensures that both the legacy system and the LEAP system use the same namespace. Alternately, you could write a gem that checks the legacy database directly.
-
-### Step 2. Configure MX servers
-
-To be written.
-
diff --git a/doc/guide/en.haml b/doc/guide/en.haml
deleted file mode 100644
index 61c24ea8..00000000
--- a/doc/guide/en.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- @nav_title = "Guide"
-- @title = "Platform Guide"
-
-= child_summaries \ No newline at end of file
diff --git a/doc/guide/environments.md b/doc/guide/environments.md
deleted file mode 100644
index 752e0608..00000000
--- a/doc/guide/environments.md
+++ /dev/null
@@ -1,75 +0,0 @@
-@title = "Working with environments"
-@nav_title = "Environments"
-@summary = "How to partition the nodes into separate environments."
-
-With environments, you can divide your nodes into different and entirely separate sets. For example, you might have sets of nodes for 'testing', 'staging' and 'production'.
-
-Typically, the nodes in one environment are totally isolated from the nodes in a different environment. Each environment will have its own separate database, for example.
-
-There are a few exceptions to this rule: backup nodes, for example, will by default attempt to back up data from all the environments (excluding local).
-
-## Assign an environment
-
-To assign an environment to a node, you just set the `environment` node property. This is typically done with tags, although it is not necessary. For example:
-
-`tags/production.json`
-
- {
- "environment": "production"
- }
-
-`nodes/mynode.json`
-
- {
- "tags": ["production"]
- }
-
-There are several built-in tags that will apply a value for the environment:
-
-* `production`: An environment for nodes that are in use by end users.
-* `development`: An environment to be used for nodes that are being used for experiments or staging.
-* `local`: This environment gets automatically applied to all nodes that run only on local VMs. Nodes with a `local` environment are treated special and excluded from certain calculations.
-
-You don't need to use these and you can add your own.
-
-## Environment commands
-
-* `leap env` -- List the available environments and disply which one is active.
-* `leap env pin ENV` -- Pin the current environment to ENV.
-* `leap env unpin` -- Remove the environment pin.
-
-The environment pin is only active for your local machine: it is not recorded in the provider directory and not shared with other users.
-
-## Environment specific JSON files
-
-You can add JSON configuration files that are only applied when a specific environment is active. For example, if you create a file `provider.production.json`, these values will only get applied to the `provider.json` file for the `production` environment.
-
-This will also work for services and tags. For example:
-
- provider.local.json
- services/webapp.development.json
- tags/seattle.production.json
-
-In this example, `local`, `development`, and `production` are the names of environments.
-
-## Bind an environment to a Platform version
-
-If you want to ensure that a particular environment is bound to a particular version of the LEAP Platform, you can add a `platform` section to the `provider.ENV.json` file (where ENV is the name of the environment in question).
-
-The available options are `platform.version`, `platform.branch`, or `platform.commit`. For example:
-
- {
- "platform": {
- "version": "1.6.1",
- "branch": "develop",
- "commit": "5df867fbd3a78ca4160eb54d708d55a7d047bdb2"
- }
- }
-
-You can use any combination of `version`, `branch`, and `commit` to specify the binding. The values for `branch` and `commit` only work if the `leap_platform` directory is a git repository.
-
-The value for `commit` is passed directly through to `git log` to query for a list of acceptable commits. See [[man gitrevisions => https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html#_specifying_ranges]] to see how to specify ranges. For example:
-
-* `HEAD^..HEAD` - current commit must be head of the branch.
-* `3172444652af71bd771609d6b80258e70cc82ce9..HEAD` - current commit must be after 3172444652af71bd771609d6b80258e70cc82ce9.
-* `refs/tags/0.6.0rc1..refs/tags/0.6.0rc2` - current commit must be after tag 0.6.0rc1 and before or including tag 0.6.0rc2. \ No newline at end of file
diff --git a/doc/guide/getting-started.md b/doc/guide/getting-started.md
deleted file mode 100644
index 6236cba0..00000000
--- a/doc/guide/getting-started.md
+++ /dev/null
@@ -1,145 +0,0 @@
-@title = 'Getting Started'
-@summary = 'An overview of the LEAP Platform'
-@toc = true
-
-
-Sensitive files
-----------------------------------------------
-
-Some files in your provider directory are very sensitive. Leaking these files will compromise your provider.
-
-Super sensitive and irreplaceable:
-
-* `files/ca/*.key` -- the private keys for the client and server CAs.
-* `files/cert/*.key` -- the private key(s) for the commercial certificate for your domain(s).
-
-Sensitive, but can be erased and regenerated automatically:
-
-* `secrets.json` -- various random secrets, such as passwords for databases.
-* `files/nodes/*/*.key` -- the private key for each node.
-* `hiera/*.yaml` -- hiera file contains a copy of the private key of the node.
-
-Also, each sysadmin has one or more public ssh keys in `users/*/*_ssh.pub`. Typically, you will want to keep these public keys secure as well.
-
-See [[keys-and-certificates]] for more information.
-
-Useful commands
--------------------------------------------
-
-Here are a few useful `leap` commands:
-
-* `leap help [COMMAND]` -- get help on COMMAND.
-* `leap history [FILTER]` -- show the recent deployment history for the selected nodes.
-* `leap ssh web1` -- SSH into node web1 (requires `leap node init web1` first).
-* `leap list [FILTER]` -- list the selected nodes.
- * `leap list production` -- list only those nodes with the tag 'production'
- * `leap list --print ip_address` -- list a particular attribute of all nodes.
-
-See the full [[commands]] for more information.
-
-Node filters
--------------------------------------------
-
-Many of the `leap` commands take a "node filter". You can use a node filter to target a command at one or more nodes.
-
-A node filter consists of one or more keywords, with an optional "+" before each keyword.
-
-* keywords can be a node name, a service type, or a tag.
-* the "+" before the keyword constructs an AND condition
-* otherwise, multiple keywords together construct an OR condition
-
-Examples:
-
-* `leap list openvpn` -- list all nodes with service openvpn.
-* `leap list openvpn +production` -- only nodes of service type openvpn AND tag production.
-* `leap deploy webapp openvpn` -- deploy to all webapp OR openvpn nodes.
-* `leap node init ostrich` -- just init the node named ostrich.
-
-See the full [[commands]] for more information.
-
-Tracking the provider directory in git
-------------------------------------------
-
-You should commit your provider changes to your favorite VCS whenever things change. This way you can share your configurations with other admins, all they have to do is to pull the changes to stay up to date. Every time you make a change to your provider, such as adding nodes, services, generating certificates, etc. you should add those to your VCS, commit them and push them to where your repository is hosted.
-
-Note that your provider directory contains secrets, such as private key material and passwords. You do not want to have those passwords readable by the world, so make sure that wherever you are hosting your repository, it is not public for the world to read.
-
-If you have a post-commit hook that emails the changes to contributors, you may want to exclude diffs for files that might have sensitive secrets. For example, create a `.gitattributes` file with:
-
- # No diff, no email for key files
- *.key -diff
- *.pem -diff
-
- # Discard diff for secrets.json
- secrets.json -diff
-
- # No diff for hiera files, they contain passwords
- hiera/* -diff
-
-
-Editing JSON configuration files
---------------------------------------
-
-All the settings that compose your provider are stored in JSON files.
-
-At a minimum, you will need at least two configuration files:
-
-* `provider.json` -- general settings for you provider.
-* `nodes/NAME.json` -- configuration file for node called "NAME".
-
-There are a few required properties in provider.json:
-
- {
- "domain": "example.org",
- "name": "Example",
- "contacts": {
- "default": "email1@example.org"
- }
- }
-
-See [[provider-configuration]] for more details.
-
-For node configuration files, there are two required properties:
-
- {
- "ip_address": "1.1.1.1",
- "services": ["openvpn"]
- }
-
-See [[services]] for details on what servers are available, and see [[config]] details on how configuration files work.
-
-How does it work under the hood?
---------------------------------------------
-
-You don't need to know any of the details of what happens "under the hood" in order to use the LEAP platform. However, if you are curious as to what is going on, here is a quick primer.
-
-First, some background terminology:
-
-* **puppet**: Puppet is a system for automating deployment and management of servers (called nodes).
-* **hiera files**: In puppet, you can use something called a 'hiera file' to seed a node with a few configuration values. In LEAP, we go all out and put *every* configuration value needed for a node in the hiera file, and automatically compile a custom hiera file for each node.
-
-When you run `leap deploy`, a bunch of things happen, in this order:
-
-1. **Compile hiera files**: The hiera configuration file for each node is compiled in YAML format and saved in the directory `hiera`. The source material for this hiera file consists of all the JSON configuration files imported or inherited by the node's JSON config file.
-* **Copy required files to node**: All the files needed for puppet to run are rsync'ed to each node. This includes the entire leap_platform directory, as well as the node's hiera file and other files needed by puppet to set up the node (keys, binary files, etc).
-* **Puppet is run**: Once the node is ready, leap connects to the node via ssh and runs `puppet apply`. Puppet is applied locally on the node, without a daemon or puppetmaster.
-
-You can run `leap -v2 deploy` to see exactly what commands are being executed.
-
-This mode of operation is fundamentally different from how puppet is normally used:
-
-* There is no puppetmaster that all the servers take orders from, and there is no puppetd running in the background.
-* Servers cannot dynamically query the puppetmaster for information about the other servers.
-* There is a static representation for the state of every server that can be committed to git.
-
-There are advantages and disadvantages to the model that LEAP uses. We have found it very useful for our goal of having a common LEAP platform that many different providers can all use while still allowing providers to configure their unique infrastructure.
-
-We also find it very beneficial to be able to track the state of your infrastructure in git.
-
-Traditional system configuration automation systems, like [Puppet](https://puppetlabs.com/puppet/puppet-open-source/) or [Chef](http://www.opscode.com/chef/), deploy changes to servers using a pull method. Each server pulls a manifest from a central master server and uses this to alter the state of the server.
-
-Instead, the `leap` tool uses a masterless push method: The sysadmin runs `leap deploy` from the provider instance directory on their desktop machine to push the changes out to every server (or a subset of servers). LEAP still uses Puppet, but there is no central master server that each node must pull from.
-
-One other significant difference between LEAP and typical system automation is how interactions among servers are handled. Rather than store a central database of information about each server that can be queried when a recipe is applied, the `leap` command compiles static representation of all the information a particular server will need in order to apply the recipes. In compiling this static representation, `leap` can use arbitrary programming logic to query and manipulate information about other servers.
-
-These two approaches, masterless push and pre-compiled static configuration, allow the sysadmin to manage a set of LEAP servers using traditional software development techniques of branching and merging, to more easily create local testing environments using virtual servers, and to deploy without the added complexity and failure potential of a master server.
diff --git a/doc/guide/keys-and-certificates.md b/doc/guide/keys-and-certificates.md
deleted file mode 100644
index a6862a6a..00000000
--- a/doc/guide/keys-and-certificates.md
+++ /dev/null
@@ -1,272 +0,0 @@
-@title = "Keys and Certificates"
-@summary = "Working with SSH keys, secrets, and X.509 certificates."
-
-Working with SSH
-================================
-
-Whenever the `leap` command needs to push changes to a node or gather information from a node, it tunnels this command over SSH. Another way to put this: the security of your servers rests entirely on SSH. Because of this, it is important that you understand how `leap` uses SSH.
-
-SSH related files
--------------------------------
-
-Assuming your provider directory is called 'provider':
-
-* `provider/nodes/crow/crow_ssh.pub` -- The public SSH host key for node 'crow'.
-* `provider/users/alice/alice_ssh.pub` -- The public SSH user key for user 'alice'. Anyone with the private key that corresponds to this public key will have root access to all nodes.
-* `provider/files/ssh/known_hosts` -- An autogenerated known_hosts, built from combining `provider/nodes/*/*_ssh.pub`. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate `known_hosts` and then run `leap compile`.
-* `provider/files/ssh/authorized_keys` -- An autogenerated list of all the user SSH keys with root access to the notes. It is created from `provider/users/*/*_ssh.pub`. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate `authorized_keys` and then run `leap compile`.
-
-All of these files should be committed to source control.
-
-If you rename, remove, or add a node with `leap node [mv|add|rm]` the SSH key files and the `known_hosts` file will get properly updated.
-
-SSH and local nodes
--------------------
-
-Local nodes are run as Vagrant virtual machines. The `leap` command handles SSH slightly differently for these nodes.
-
-Basically, all the SSH security is turned off for local nodes. Since local nodes only exist for a short time on your computer and can't be reached from the internet, this is not a problem.
-
-Specifically, for local nodes:
-
-1. `known_hosts` is never updated with local node keys, since the SSH public key of a local node is different for each user.
-2. `leap` entirely skips the checking of host keys when connecting with a local node.
-3. `leap` adds the public Vagrant SSH key to the list of SSH keys for a user. The public Vagrant SSH key is a shared and insecure key that has root access to most Vagrant virtual machines.
-
-To upgrade a SSH host key
--------------------------------
-
-Most servers will have more than one SSH host key. Sometimes, the server will have a better SSH host key than the one you have on file. In order to upgrade to the better SSH host key, simply re-run the init command:
-
- workstation$ leap node init NODE_NAME
-
-This will prompt you if you want to upgrade the SSH host key, but only if `leap` thinks that an upgrade is advisable.
-
-When SSH host key changes
--------------------------------
-
-If the host key for a node has changed, you will get an error "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED".
-
-To fix this, you need to remove the file `files/nodes/stompy/stompy_ssh.pub` and run `leap node init stompy`, where the node's name is 'stompy'. **Only do this if you are ABSOLUTELY CERTAIN that the node's SSH host key has changed**.
-
-Changing the SSH port
---------------------------------
-
-Suppose you have a node `blinky` that has SSH listening on port 22 and you want to make it port 2200.
-
-First, modify the configuration for `blinky` to specify the variable `ssh.port` as 2200. Usually, this is done in `common.json` or in a tag file.
-
-For example, you could put this in `tags/production.json`:
-
- {
- "ssh": {
- "port": 2200
- }
- }
-
-Run `leap compile` and open `hiera/blinky.yaml` to confirm that `ssh.port` is set to 2200. The port number must be specified as a number, not a string (no quotes).
-
-Then, you need to deploy this change so that SSH will bind to 2200. You cannot simply run `leap deploy blinky` because this command will default to using the variable `ssh.port` which is now `2200` but SSH on the node is still bound to 22.
-
-So, you manually override the port in the deploy command, using the old port:
-
- leap deploy --port 22 blinky
-
-Afterwards, SSH on `blinky` should be listening on port 2200 and you can just run `leap deploy blinky` from then on.
-
-Sysadmins with multiple SSH keys
------------------------------------
-
-The command `leap add-user --self` allows only one SSH key. If you want to specify more than one key for a user, you can do it manually:
-
- users/userx/userx_ssh.pub
- users/userx/otherkey_ssh.pub
-
-All keys matching 'userx/*_ssh.pub' will be usable.
-
-Removing sysadmin access
---------------------------------
-
-Suppose you want to remove `userx` from having any further SSH access to the servers. Do this:
-
- rm -r users/userx
- leap deploy
-
-X.509 Certificates
-================================
-
-Configuration options
--------------------------------------------
-
-The `ca` option in provider.json provides settings used when generating CAs and certificates. The defaults are as follows:
-
- {
- "ca": {
- "name": "= global.provider.ca.organization + ' Root CA'",
- "organization": "= global.provider.name[global.provider.default_language]",
- "organizational_unit": "= 'https://' + global.provider.domain",
- "bit_size": 4096,
- "digest": "SHA256",
- "life_span": "10y",
- "server_certificates": {
- "bit_size": 2048,
- "digest": "SHA256",
- "life_span": "1y"
- },
- "client_certificates": {
- "bit_size": 2048,
- "digest": "SHA256",
- "life_span": "2m",
- "limited_prefix": "LIMITED",
- "unlimited_prefix": "UNLIMITED"
- }
- }
- }
-
-You should not need to override these defaults in your own provider.json, but you can if you want to. To see what values are used for your provider, run `leap inspect provider.json`.
-
-NOTE: A certificate `bit_size` greater than 2048 will probably not be recognized by most commercial CAs.
-
-Certificate Authorities
------------------------------------------
-
-There are three x.509 certificate authorities (CA) associated with your provider:
-
-1. **Commercial CA:** It is strongly recommended that you purchase a commercial cert for your primary domain. The goal of platform is to not depend on the commercial CA system, but it does increase security and usability if you purchase a certificate. The cert for the commercial CA must live at `files/cert/commercial_ca.crt`.
-2. **Server CA:** This is a self-signed CA responsible for signing all the **server** certificates. The private key lives at `files/ca/ca.key` and the public cert lives at `files/ca/ca.crt`. The key is very sensitive information and must be kept private. The public cert is distributed publicly.
-3. **Client CA:** This is a self-signed CA responsible for signing all the **client** certificates. The private key lives at `files/ca/client_ca.key` and the public cert lives at `files/ca/client_ca.crt`. Neither file is distribute publicly. It is not a big deal if the private key for the client CA is compromised, you can just generate a new one and re-deploy.
-
-To generate both the Server CA and the Client CA, run the command:
-
- leap cert ca
-
-Server certificates
------------------------------------
-
-Most every server in your service provider will have a x.509 certificate, generated by the `leap` command using the Server CA. Whenever you modify any settings of a node that might affect it's certificate (like changing the IP address, hostname, or settings in provider.json), you can magically regenerate all the certs that need to be regenerated with this command:
-
- leap cert update
-
-Run `leap help cert update` for notes on usage options.
-
-Because the server certificates are generated locally on your personal machine, the private key for the Server CA need never be put on any server. It is up to you to keep this file secure.
-
-Client certificates
---------------------------------
-
-Every leap client gets its own time-limited client certificate. This cert is use to connect to the OpenVPN gateway (and probably other things in the future). It is generated on the fly by the webapp using the Client CA.
-
-To make this work, the private key of the Client CA is made available to the webapp. This might seem bad, but compromise of the Client CA simply allows the attacker to use the OpenVPN gateways without paying. In the future, we plan to add a command to automatically regenerate the Client CA periodically.
-
-There are two types of client certificates: limited and unlimited. A client using a limited cert will have its bandwidth limited to the rate specified by `provider.service.bandwidth_limit` (in Bytes per second). An unlimited cert is given to the user if they authenticate and the user's service level matches one configured in `provider.service.levels` without bandwidth limits. Otherwise, the user is given a limited client cert.
-
-Commercial certificates
------------------------------------
-
-We strongly recommend that you use a commercial signed server certificate for your primary domain (in other words, a certificate with a common name matching whatever you have configured for `provider.domain`). This provides several benefits:
-
-1. When users visit your website, they don't get a scary notice that something is wrong.
-2. When a user runs the LEAP client, selecting your service provider will not cause a warning message.
-3. When other providers first discover your provider, they are more likely to trust your provider key if it is fetched over a commercially verified link.
-
-The LEAP platform is designed so that it assumes you are using a commercial cert for the primary domain of your provider, but all other servers are assumed to use non-commercial certs signed by the Server CA you create.
-
-To generate a CSR, run:
-
- leap cert csr
-
-This command will generate the CSR and private key matching `provider.domain` (you can change the domain with `--domain=DOMAIN` switch). It also generates a server certificate signed with the Server CA. You should delete this certificate and replace it with a real one once it is created by your commercial CA.
-
-The related commercial cert files are:
-
- files/
- cert/
- domain.org.crt # Server certificate for domain.org, obtained by commercial CA.
- domain.org.csr # Certificate signing request
- domain.org.key # Private key for you certificate
- commercial_ca.crt # The CA cert obtained from the commercial CA.
-
-The private key file is extremely sensitive and care should be taken with its provenance.
-
-If your commercial CA has a chained CA cert, you should be OK if you just put the **last** cert in the chain into the `commercial_ca.crt` file. This only works if the other CAs in the chain have certs in the debian package `ca-certificates`, which is the case for almost all CAs.
-
-If you want to add additional fields to the CSR, like country, city, or locality, you can configure these values in provider.json like so:
-
- "ca": {
- "server_certificates": {
- "country": "US",
- "state": "Washington",
- "locality": "Seattle"
- }
- }
-
-If they are not present, the CSR will be created without them.
-
-Examine Certs
------------------
-
-To see details about the keys and certs you can use `leap inspect` like so:
-
- $ leap inspect files/ca/ca.crt
-
-
-Let's Encrypt certificate
-=========================
-
-LEAP plans to integrate [Let's Encrypt](https://letsencrypt.org/) support, so it will be even easier to receive X.509 certificates that are accepted by all browsers.
-Until we achieve this, here's a guide how to do this manually.
-
-Install the official acme client
---------------------------------
-
-Log in to your webapp node
-
- server$ git clone https://github.com/letsencrypt/letsencrypt
- server$ cd letsencrypt
- server$ ./letsencrypt-auto --help
-
-Fetch cert
-----------
-
-Stop apache so the letsencrypt client can bind to port 80:
-
- server$ systemctl stop apache2
-
-Fetch the certs
-
- server$ ./letsencrypt-auto certonly --standalone --email admin@$(hostname -d) -d $(hostname -d) -d api.$(hostname -d) -d $(hostname -f) -d nicknym.$(hostname -d)
-
-This will put the certs and keys into `/etc/letsencrypt/live/DOMAIN/`.
-
-Now, go to your workstation's provider configuration directory and copy the newly created files from the server to your local config. You will override existing files so please make a backup before proceeding, or use a version control system to track changes.
-
- workstation$ cd PATH_TO_PROVIDER_CONFIG
-
-Copy the Certificate
-
- workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/cert.pem files/cert/dev.pixelated-project.org.crt
-
-Copy the private key
-
- workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/privkey.pem files/cert/DOMAIN.key
-
-Copy the CA chain cert
-
- workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/fullchain.pem files/cert/DOMAIN.key
-
-Deploy the certs
-----------------
-
-Now you only need to deploy the certs
-
- workstation$ leap deploy
-
-This will put them into the right locations which are:
-
-- `/etc/x509/certs/leap_commercial.crt` for the certificate
-- `/etc/x509/./keys/leap_commercial.key` for the private key
-- `/usr/local/share/ca-certificates/leap_commercial_ca.crt` for the CA chain cert.
-
-Start apache2 again
-
- server$ systemctl start apache2
diff --git a/doc/guide/miscellaneous.md b/doc/guide/miscellaneous.md
deleted file mode 100644
index c38c007c..00000000
--- a/doc/guide/miscellaneous.md
+++ /dev/null
@@ -1,14 +0,0 @@
-@title = "Miscellaneous"
-@summary = "Miscellaneous commands you may need to know."
-
-Facts
-==============================
-
-There are a few cases when we must gather internal data from a node before we can successfully deploy to other nodes. This is what `facts.json` is for. It stores a snapshot of certain facts about each node, as needed. Entries in `facts.json` are updated automatically when you initialize, rename, or remove a node. To manually force a full update of `facts.json`, run:
-
- leap facts update FILTER
-
-Run `leap help facts update` for more information.
-
-The file `facts.json` should be committed to source control. You might not have a `facts.json` if one is not required for your provider.
-
diff --git a/doc/guide/nodes.md b/doc/guide/nodes.md
deleted file mode 100644
index 5135f3ba..00000000
--- a/doc/guide/nodes.md
+++ /dev/null
@@ -1,87 +0,0 @@
-@title = "Nodes"
-@summary = "Working with nodes, services, tags, and locations."
-
-Locations
-================================
-
-All nodes should have a `location.name` specified, and optionally additional information about the location, like the time zone. This location information is used for two things:
-
-* Determine which nodes can, or must, communicate with one another via a local network. The way some virtualization environments work, like OpenStack, requires that nodes communicate via the local network if they are on the same network.
-* Allows the client to prefer connections to nodes that are closer in physical proximity to the user. This is particularly important for OpenVPN nodes.
-
-The location stanza in a node's config file looks like this:
-
- {
- "location": {
- "id": "ankara",
- "name": "Ankara",
- "country_code": "TR",
- "timezone": "+2",
- "hemisphere": "N"
- }
- }
-
-The fields:
-
-* `id`: An internal handle to use for this location. If two nodes have match `location.id`, then they are treated as being on a local network with one another. This value defaults to downcase and underscore of `location.name`.
-* `name`: Can be anything, might be displayed to the user in the client if they choose to manually select a gateway.
-* `country_code`: The [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1) two letter country code.
-* `timezone`: The timezone expressed as an offset from UTC (in standard time, not daylight savings). You can look up the timezone using this [handy map](http://www.timeanddate.com/time/map/).
-* `hemisphere`: This should be "S" for all servers in South America, Africa, or Australia. Otherwise, this should be "N".
-
-These location options are very imprecise, but good enough for most usage. The client often does not know its own location precisely either. Instead, the client makes an educated guess at location based on the OS's timezone and locale.
-
-If you have multiple nodes in a single location, it is best to use a tag for the location. For example:
-
-`tags/ankara.json`:
-
- {
- "location": {
- "name": "Ankara",
- "country_code": "TR",
- "timezone": "+2",
- "hemisphere": "N"
- }
- }
-
-`nodes/vpngateway.json`:
-
- {
- "services": "openvpn",
- "tags": ["production", "ankara"],
- "ip_address": "1.1.1.1",
- "openvpn": {
- "gateway_address": "1.1.1.2"
- }
- }
-
-Unless you are using OpenStack or AWS, setting `location` for nodes is not required. It is, however, highly recommended.
-
-Disabling Nodes
-=====================================
-
-There are two ways to temporarily disable a node:
-
-**Option 1: disabled environment**
-
-You can assign an environment to the node that marks it as disabled. Then, if you use environment pinning, the node will be ignored when you deploy. For example:
-
- {
- "environment": "disabled"
- }
-
-Then use `leap env pin ENV` to pin the environment to something other than 'disabled'. This only works if all the other nodes are also assigned to some environment.
-
-**Option 2: enabled == false**
-
-If a node has a property `enabled` set to false, then the `leap` command will skip over the node and pretend that it does not exist. For example:
-
- {
- "ip_address": "1.1.1.1",
- "services": ["openvpn"],
- "enabled": false
- }
-
-**Options 3: no-deploy**
-
-If the file `/etc/leap/no-deploy` exists on a node, then when you run the commmand `leap deploy` it will halt and prevent a deploy from going through (if the node was going to be included in the deploy).
diff --git a/doc/guide/provider-configuration.md b/doc/guide/provider-configuration.md
deleted file mode 100644
index 08cfd1dd..00000000
--- a/doc/guide/provider-configuration.md
+++ /dev/null
@@ -1,79 +0,0 @@
-@title = "Provider Configuration"
-@summary = "Explore how to configure your provider."
-
-Required provider configuration
---------------------------------------
-
-There are a few required settings in `provider.json`. At a minimum, you must have:
-
-* `domain`: defines the primary domain of the provider. This is the domain that users will type in when using the Bitmask client, although it is not necessarily the domain where users will visit if they sign up via the web application. If email is supported, all accounts will be `username@domain`.
-* `name`: A brief title for this provider. It can be multiple words, but should not be too long.
-* `contacts.default`: One or more email addresses for sysadmins.
-
-For example:
-
- {
- "domain": "freerobot.org",
- "name": "Freedom for Robots!",
- "contacts": {
- "default": "root@freerobot.org"
- }
- }
-
-
-Recommended provider configuration
---------------------------------------
-
-* `description`: A longer description of the provider, shown to the user when they register a new account through Bitmask client.
-* `languages`: A list of language codes that should be enabled.
-* `default_language`: The initial default language code.
-* `enrollment_policy`: One of "open", "closed", or "invite". (invite not currently supported).
-
-For example:
-
- {
- "description": "It is time for robots of the world to unite and throw of the shackles of servitude to our organic overlords.",
- "languages": ["en", "de", "pt", "01"],
- "default_language": "01",
- "enrollman_policy": "open"
- }
-
-For a full list of possible settings, you can use `leap inspect` to see how provider.json is evaluated after including the inherited defaults:
-
- $ leap inspect provider.json
-
-Configuring service levels
---------------------------------------
-
-The `provider.json` file defines the available service levels for the provider.
-
-For example, in provider.json:
-
- "service": {
- "default_service_level": "low",
- "levels": {
- "low": {
- "description": "Entry level plan, with unlimited bandwidth and minimal storage quota.",
- "name": "entry",
- "storage": "10 MB",
- "rate": {
- "USD": 5,
- "GBP": 3,
- "EUR": 6
- }
- },
- "full": {
- "description": "Full plan, with unlimited bandwidth and higher quota."
- "name": "full",
- "storage": "5 GB",
- "rate": {
- "USD": 10,
- "GBP": 6,
- "EUR": 12
- }
- }
- }
- }
- }
-
-For a list of currency codes, see https://en.wikipedia.org/wiki/ISO_4217#Active_codes
diff --git a/doc/service-diagram.odg b/doc/service-diagram.odg
deleted file mode 100644
index 09265c2d..00000000
--- a/doc/service-diagram.odg
+++ /dev/null
Binary files differ
diff --git a/doc/service-diagram.png b/doc/service-diagram.png
deleted file mode 100644
index 85e62436..00000000
--- a/doc/service-diagram.png
+++ /dev/null
Binary files differ
diff --git a/doc/services/couchdb.md b/doc/services/couchdb.md
deleted file mode 100644
index cc40dc32..00000000
--- a/doc/services/couchdb.md
+++ /dev/null
@@ -1,159 +0,0 @@
-@title = "couchdb"
-@summary = "Data storage for all user data."
-
-Topology
-------------------------
-
-Required:
-
-* Nodes with `couchdb` service must also have `soledad` service, if email is enabled.
-
-Suggested:
-
-* Nodes with `couchdb` service communicate heavily with `webapp` and `mx`.
-
-`couchdb` nodes do not need to be reachable from the public internet, although the `soledad` service does require this.
-
-Configuration
-----------------------------
-
-### Nighly dumps
-
-You can do a nightly couchdb data dump by adding this to your node config:
-
- "couch": {
- "backup": true
- }
-
-Data will get dumped to `/var/backups/couchdb`.
-
-### Plain CouchDB
-
-BigCouch is not supported on Platform version 0.8 and higher: only plain CouchDB is possible. For earlier versions, you must do this in order to use plain CouchDB:
-
- "couch": {
- "master": true,
- "pwhash_alg": "pbkdf2"
- }
-
-Various Tasks
--------------------------------------------------
-
-### Re-enabling blocked account
-
-When a user account gets destroyed from the webapp, there's still a leftover doc in the identities db so other people can't claim that account without an admin's intervention. You can remove this username reservation through the webapp.
-
-However, here is how you could do it manually, if you wanted to:
-
-grep the identities db for the email address:
-
- curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET http://127.0.0.1:5984/identities/_all_docs?include_docs=true|grep test_127@bitmask.net
-
-lookup "id" and "rev" to delete the doc:
-
- curl -s --netrc-file /etc/couchdb/couchdb.netrc -X DELETE 'http://127.0.0.1:5984/identities/b25cf10f935b58088f0d547fca823265?rev=2-715a9beba597a2ab01851676f12c3e4a'
-
-### How to find out which userstore belongs to which identity?
-
- /usr/bin/curl -s --netrc-file /etc/couchdb/couchdb.netrc '127.0.0.1:5984/identities/_all_docs?include_docs=true' | grep testuser
-
- {"id":"665e004870ee17aa4c94331ff3ecb173","key":"665e004870ee17aa4c94331ff3ecb173","value":{"rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b"},"doc":{"_id":"665e004870ee17aa4c94331ff3ecb173","_rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b","user_id":"665e004870ee17aa4c94331ff3cd59eb","address":"testuser@example.org","destination":"testuser@example.org","keys": ...
-
-* search for the "user_id" field
-* in this example testuser@example.org uses the database user-665e004870ee17aa4c94331ff3cd59eb
-
-
-### How much disk space is used by a userstore
-
-Beware that this returns the uncompacted disk size (see http://wiki.apache.org/couchdb/Compaction)
-
- echo "`curl --netrc -s -X GET 'http://127.0.0.1:5984/user-dcd6492d74b90967b6b874100b7dbfcf'|json_pp|grep disk_size|cut -d: -f 2`/1024"|bc
-
-
-Deprecated BigCouch Tasks
------------------------------------------
-
-As of release 0.8, the LEAP platform no longer supports BigCouch. This information is kept here for historical reference.
-
-### Rebalance Cluster
-
-Bigcouch currently does not have automatic rebalancing.
-It will probably be added after merging into couchdb.
-If you add a node, or remove one node from the cluster,
-
-1. make sure you have a backup of all DBs !
-
-1. put the webapp into [[maintenance mode => services/webapp#maintenance-mode]]
-
-1. Stop all services that access the database:
-
- ```
- workstation$ leap ssh soledad-nodes
- server# /etc/init.d/soledad-server stop
-
- workstation$ leap ssh mx-node
- server# /etc/init.d/postfix stop
- server# /etc/init.d/leap-mx stop
-
- workstation$ leap ssh webapp
- server# /etc/init.d/nickserver stop
- ```
-
- Alternately, you can create a temporary firewall rule to block access (run on couchdb server):
-
- ```
- server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
- ```
-
-1. dump the dbs:
-
- ```
- cd /srv/leap/couchdb/scripts
- time ./couchdb_dumpall.sh
- ```
-
-1. delete all dbs
-
-1. shut down old node
-
-1. check the couchdb members
-
- ```
- curl -s —netrc-file /etc/couchdb/couchdb.netrc -X GET http://127.0.0.1:5986/nodes/_all_docs
- curl -s —netrc-file /etc/couchdb/couchdb.netrc http://127.0.0.1:5984/_membership
- ```
-
-1. remove bigcouch from all nodes
-
- ```
- apt-get --purge remove bigcouch
- ```
-
-1. deploy to all couch nodes
-
- ```
- leap deploy couchdb
- ```
-
-1. most likely, deploy will fail because bigcouch will complain about not all nodes beeing connected. Let the deploy finish, restart the bigcouch service on all nodes and re-deploy:
-
- ```
- /etc/init.d/bigcouch restart
- ```
-
-1. restore the backup
-
- ```
- cd /srv/leap/couchdb/scripts
- time ./couchdb_restoreall.sh
- ```
-
-### Migrating from BigCouch to plain CouchDB
-
-<%= render :partial => 'docs/platform/common/bigcouch_migration_begin.md' %>
-
-
-<%= render :partial => 'docs/platform/common/bigcouch_migration_end.md' %>
-
-
-<%= render :partial => 'docs/platform/common/bigcouch_migration_finish.md' %>
diff --git a/doc/services/en.md b/doc/services/en.md
deleted file mode 100644
index 5d0fec5f..00000000
--- a/doc/services/en.md
+++ /dev/null
@@ -1,80 +0,0 @@
-@nav_title = "Services"
-@title = "Guide to node services"
-@summary = ""
-@toc = true
-
-# Introduction
-
-Every node (server) must have one or more `services` defined that determines what role the node performs. For example:
-
- workstation$ cat nodes/stallman.json
- {
- "ip_address": "199.99.99.1",
- "services": ["webapp", "tor"]
- }
-
-Here are common questions to ask when adding a new node to your provider:
-
-* **many or few?** Some services benefit from having many nodes, while some services are best run on only one or two nodes.
-* **required or optional?** Some services are required, while others can be left out.
-* **who does the node communicate with?** Some services communicate very heavily with other particular services. Nodes running these services should be close together.
-* **public or private network?** Some services communicate with the public internet, while others only need to communicate with other nodes in the infrastructure.
-
-# Available services
-
-<table class="table table-striped">
-<tr>
- <th>Service</th>
- <th>VPN</th>
- <th>Email</th>
- <th>Notes</th>
-</tr>
-<tr>
- <td>webapp</td>
- <td><i class="fa fa-circle"></i></td>
- <td><i class="fa fa-circle"></i></td>
- <td>User control panel, provider API, and support system.</td>
-</tr>
-<tr>
- <td>couchdb</td>
- <td><i class="fa fa-circle"></i></td>
- <td><i class="fa fa-circle"></i></td>
- <td>Data storage for everything. Private node.</td>
-<td></td>
-</tr>
-<tr>
- <td>soledad</td>
- <td><i class="fa fa-circle-o"></i></td>
- <td><i class="fa fa-circle"></i></td>
- <td>User data synchronization daemon. Usually paired with <code>couchdb</code> nodes.</td>
-<td></td>
-</tr>
-<tr>
- <td>mx</td>
- <td><i class="fa fa-circle-o"></i></td>
- <td><i class="fa fa-circle"></i></td>
- <td>Incoming and outgoing MX servers.</td>
-</tr>
-<tr>
- <td>openvpn</td>
- <td><i class="fa fa-circle"></i></td>
- <td><i class="fa fa-circle-o"></i></td>
- <td>OpenVPN gateways.</td>
-</tr>
-<tr>
- <td>monitor</td>
- <td><i class="fa fa-dot-circle-o"></i></td>
- <td><i class="fa fa-dot-circle-o"></i></td>
- <td>Nagios monitoring. This service must be on the webapp node.</td>
-</tr>
-<tr>
- <td>tor</td>
- <td><i class="fa fa-dot-circle-o"></i></td>
- <td><i class="fa fa-dot-circle-o"></i></td>
- <td>Tor exit node.</td>
-</tr>
-</table>
-
-Key: <i class="fa fa-circle"> Required</i>, <i class="fa fa-dot-circle-o"> Optional</i>, <i class="fa fa-circle-o"> Not Used</i>
-
-<%= child_summaries %> \ No newline at end of file
diff --git a/doc/services/monitor.md b/doc/services/monitor.md
deleted file mode 100644
index 576b36a9..00000000
--- a/doc/services/monitor.md
+++ /dev/null
@@ -1,36 +0,0 @@
-@title = "monitor"
-@summary = "Nagios monitoring and continuous testing."
-
-The `monitor` node provides a nagios control panel that will give you a view into the health and status of all the servers and all the services. It will also spam you with alerts if something goes down.
-
-Topology
---------------------------------------
-
-Currently, you can have zero or one `monitor` nodes defined. It is required that the monitor be on the webapp node. It was not designed to be run as a separate node service.
-
-Configuration
------------------------------------------------
-
-* `nagios.environments`: By default, the monitor node will monitor all servers in all environments. You can optionally restrict the environments to the ones you specify.
-
-For example:
-
- {
- "nagios": {
- "environments": ["unstable", "production"]
- }
- }
-
-Access nagios web
------------------------------------------------
-
-*Determine the nagios URL*
-
- $ leap ls --print domain.name,webapp.domain,ip_address monitor
- > chameleon chameleon.bitmask.net, demo.bitmask.net, 199.119.112.10
-
-In this case, you would open `https://demo.bitmask.net/cgi-bin/nagios3` in your browser (or alternately you could use 199.119.112.10 or chameleon.bitmask.net).
-
-*Determine the nagios password*
-
-The username for nagios is always `nagiosadmin`. The password is randomly generated and stored in `secrets.json` under the key `nagios_admin_password`. Note that the login is `nagiosadmin` without underscore, but the entry in secrets.json is with underscores.
diff --git a/doc/services/mx.md b/doc/services/mx.md
deleted file mode 100644
index 1a34b660..00000000
--- a/doc/services/mx.md
+++ /dev/null
@@ -1,35 +0,0 @@
-@title = "mx"
-@summary = "Incoming and outgoing MX servers."
-
-Topology
--------------------
-
-`mx` nodes communicate with the public internet, clients, and `couchdb` nodes.
-
-Configuration
---------------------
-
-### Aliases
-
-Using the `mx.aliases` property, you can specify your own hard-coded email aliases that precedence over the aliases in the user database. The `mx.aliases` property consists of a hash, where source address points to one or more destination addresses.
-
-For example:
-
-`services/mx.json`:
-
- "mx": {
- "aliases": {
- "rook": "crow",
- "robin": "robin@bird.org",
- "flock": ["junco@bird.org", "robin", "crow"],
- "chickadee@avian.org": "chickadee@bird.org",
- "flicker": ["flicker@bird.org", "flicker@deliver.local"]
- }
- }
-
-This example demonstrates several of the features with `mx.aliases`:
-
-1. alias lists: by specifying an array of destination addresses, as in the case of "flock", the single email will get copied to each address.
-1. chained resolution: alias resolution will recursively continue until there are no more matching aliases. For example, "flock" is resolved to "robin", which then gets resolved to "robin@bird.org".
-1. virtual domains: by specifying the full domain, as in the case of "chickadee@avian.org", the alias will work for any domain you want. Of course, the MX record for that domain must point to appropriate MX servers, but otherwise you don't need to do any additional configuration.
-1. local delivery: for testing purposes, it is often useful to copy all incoming mail for a particular address and send those copies to another address. You can do this by adding "@deliver.local" as one of the destination addresses. When "@local.delivery" is found, alias resolution stops and the mail is delivered to that username.
diff --git a/doc/services/openvpn.md b/doc/services/openvpn.md
deleted file mode 100644
index 5f15ff07..00000000
--- a/doc/services/openvpn.md
+++ /dev/null
@@ -1,49 +0,0 @@
-@title = 'openvpn'
-@summary = "OpenVPN egress gateways"
-
-Topology
-------------------
-
-Currently, `openvpn` service should not be combined with other services on the same node.
-
-Unlike most of the other node types, the `openvpn` nodes do not need access to the database and does not ever communicate with any other nodes (except for the `monitor` node, if used). So, `openvpn` nodes can be placed anywhere without regard to the other nodes.
-
-Configuration
----------------------
-
-*Essential configuration*
-
-* `openvpn.gateway_address`: The address that OpenVPN daemon is bound to and that VPN clients connect to.
-* `ip_address`: The main IP of the server, and the egress address for outgoing traffic.
-
-For example:
-
- {
- "ip_address": "1.1.1.1",
- "openvpn": {
- "gateway_address": "2.2.2.2"
- }
- }
-
-In this example, VPN clients will connect to 2.2.2.2, but their traffic will appear to come from 1.1.1.1.
-
-Why are two IP addresses needed? Without this, traffic between two VPN users on the same gateway will not get encrypted. This is because the VPN on every client must be configured to allow cleartext traffic for the IP address that is the VPN gateway.
-
-*Optional configuration*
-
-Here is the default configuration:
-
- "openvpn": {
- "configuration": {
- "auth": "SHA1",
- "cipher": "AES-128-CBC",
- "fragment": 1400,
- "keepalive": "10 30",
- "tls-cipher": "DHE-RSA-AES128-SHA",
- "tun-ipv6": true
- },
- "ports": ["80", "443", "53", "1194"],
- "protocols": ["tcp", "udp"]
- }
-
-You may want to change the ports so that only 443 or 80 are used. It is probably best to not modify the `openvpn.configuration` options for now. \ No newline at end of file
diff --git a/doc/services/soledad.md b/doc/services/soledad.md
deleted file mode 100644
index e2700d06..00000000
--- a/doc/services/soledad.md
+++ /dev/null
@@ -1,12 +0,0 @@
-@title = 'soledad'
-@summary = 'User data synchronization daemon'
-
-Topology
---------------------
-
-Currently, the platform is designed for `soledad` and `couchdb` services to be combined (e.g. every `soledad` node should also be a `couchdb` node). `soledad` nodes might work in isolation, but this is not tested.
-
-Configuration
-------------------------
-
-There are no options to configure for `soledad` nodes.
diff --git a/doc/services/tor.md b/doc/services/tor.md
deleted file mode 100644
index e64b0fe0..00000000
--- a/doc/services/tor.md
+++ /dev/null
@@ -1,32 +0,0 @@
-@title = 'tor'
-@summary = 'Tor exit node or hidden service'
-
-Topology
-------------------------
-
-Nodes with `tor` service will run a Tor exit or hidden service, depending on what other service it is paired with:
-
-* `tor` + `openvpn`: when combined with `openvpn` nodes, `tor` will create a Tor exit node to provide extra cover traffic for the VPN. This can be especially useful if there are VPN gateways without much traffic.
-* `tor` + `webapp`: when combined with a `webapp` node, the `tor` service will make the webapp and the API available via .onion hidden service.
-* `tor` stand alone: a regular Tor exit node.
-
-If activated, you can list the hidden service .onion addresses this way:
-
- leap ls --print tor.hidden_service.address tor
-
-Then just add '.onion' to the end of the printed addresses.
-
-Configuration
-------------------------------
-
-* `tor.bandwidth_rate`: the max bandwidth allocated to Tor, in KB per second, when used as an exit node.
-
-For example:
-
- {
- "tor": {
- "bandwidth_rate": 6550
- }
- }
-
-
diff --git a/doc/services/webapp.md b/doc/services/webapp.md
deleted file mode 100644
index 1c06d715..00000000
--- a/doc/services/webapp.md
+++ /dev/null
@@ -1,293 +0,0 @@
-@title = "webapp"
-@summary = "leap_web user management application and provider API."
-
-Introduction
-------------------------
-
-The service `webapp` will install the web application [[leap_web => https://leap.se/git/leap_web.git]]. It has performs the following functions:
-
-* REST API for user registration and authentication via the Bitmask client.
-* Admin interface to manage users.
-* Client certificate distribution and renewal.
-* User support help tickets.
-
-Coming soon:
-
-* Billing.
-* Customizable and localized user documentation.
-
-The leap_web application is written in Ruby on Rails 3, using CouchDB as the backend data store.
-
-Topology
--------------------------
-
-Currently, the platform only supports a single `webapp` node, although we hope to change this in the future.
-
-* `webapp` nodes communicate heavily with `couchdb` nodes, but the two can be on separate servers.
-* The `monitor` service, if enabled, must be on the same node as `webapp`.
-
-Configuration
---------------------------
-
-Essential options:
-
-* `webapp.admin`: An array of usernames that will be blessed with administrative permissions. These admins can delete users, answer help tickets, and so on. These usernames are for users that have registered through the webapp or through the Bitmask client application, NOT the sysadmin usernames lists in the provider directory `users`.
-
-Other options:
-
-* `webapp.engines`: A list of the engines you want enabled in leap_web. Currently, only "support" is available, and it is enabled by default.
-* `webapp.invite_required`: If true, registration requires an invite code. Default is `false`.
-
-For example, `services/webapp.json`:
-
- {
- "webapp": {
- "admins": ["joehill", "ali", "mack_the_turtle"]
- }
- }
-
-By putting this in `services/webapp.json`, all the `webapp` nodes will inherit the same admin list.
-
-There are many options in `provider.json` that also control how the webapp behaves. See [[provider-configuration]] for details.
-
-Invite codes
--------------------
-
-Enabling the invite code functionality will require new users to provide a valid invite code while signing up for a new account. This is turned off by default, allowing all new users to create an account.
-
-Set the `invite_code` option to `true` in `services/webapp.json`:
-
- {
- "webapp": {
- "invite_required": true
- }
- }
-
-This only works with LEAP platform 0.8 or higher.
-
-Run `leap deploy` to enable the option.
-
-You can then generate invite codes by logging into the web application with an admin user.
-
-Alternately, you can also generate invite codes with the command line:
-
- workstation$ leap ssh bumblebee
- bumblebee# cd /srv/leap/webapp/
- bumblebee# sudo -u leap-webapp RAILS_ENV=production bundle exec rake "generate_invites[NUM,USES]"
-
-Where `bumblebee` should be replaced with the name of your webapp node.
-
-The **NUM** specifies the amount of codes to generate. The **USES** parameter is optional: By default, all new invite codes can be used once and will then become invalid. If you provide another value for **USES**, you can set a different amount of maximum uses for the codes you generate.
-
-Customization
----------------------------
-
-The provider directory `files/webapp` can be used to customize the appearance of the webapp. All the files in this directory will get sync'ed to the `/srv/leap/webapp/config/customization` directory of the deployed webapp node.
-
-Files in the `files/webapp` can override view files, locales, and stylesheets in the leap_web app:
-
-For example:
-
- stylesheets/ -- override files in Rails.root/app/assets/stylesheets
- tail.scss -- included before all others
- head.scss -- included after all others
-
- public/ -- overrides files in Rails.root/public
- favicon.ico -- custom favicon
- img/ -- customary directory to put images in
-
- views/ -- overrides files Rails.root/app/views
- home/
- index.html.haml -- this file is what shows up on
- the home page
- pages/
- privacy-policy.en.md -- this file will override
- the default privacy policy
- terms-of-service.en.md -- this file will override
- the default TOS.
-
- locales/ -- overrides files in Rails.root/config/locales
- en.yml -- overrides for English
- de.yml -- overrides for German
- and so on...
-
-To interactively develop your customizations before you deploy them, you have two options:
-
-1. Edit a `webapp` node. This approach involves directly modifying the contents of the directory `/srv/leap/webapp/config/customization` on a deployed `webapp` node. This can, and probably should be, a "local" node. When doing this, you may need to restart leap_web in order for changes to take effect (`touch /srv/leap/webapp/tmp/restart.txt`).
-2. Alternately, you can install leap_web to run on your computer and edit files in `config/customization` locally. This approach does not require a provider or a `webapp` node. For more information, see the [leap_web README](https://github.com/leapcode/leap_web).
-
-NOTE: If you add a `tails.scss` or `head.scss` file, then you usually need to run `rake tmp:clear` and restart rails in order for the new stylesheet to get recognized. You should only need to do this once.
-
-Once you have what you want, then copy these files to the local provider directory `files/webapp` so that they will be installed each time you deploy.
-
-Customization tutorial
-----------------------------
-
-This mini-tutorial will walk you through creating a custom "branding" of the leap_web application. We will be creating a provider called "Prehistoric Computer."
-
-Here are the files we are going to create:
-
- leap_web/config/customization
- ├── locales
- │   ├── en.yml
- │   └── es.yml
- ├── public
- │   ├── favicon.ico
- │   └── img
- │   └── masthead.png
- ├── stylesheets
- │   └── tail.scss
- └── views
- └── pages
- ├── privacy-policy.en.md
- └── privacy-policy.es.md
-
-All these files are available in the source code in the [[customization.example => https://github.com/leapcode/leap_web/tree/develop/config/customization.example]] directory.
-
-Remember, these files may live different places:
-
-* `user@localmachine$ leap_web/config/customization`: This will be the path if you have checked out a local copy of leap_web.git and are running `rails server` locally in order to test your customizations.
-* `user@localmachine$ PROVIDER/files/webapp`: This is the local provider directory where the files should be put so that they get correctly deployed to webapp nodes.
-* `root@webappnode# /srv/leap/webapp/config/customization`: This is where the files in the local provider directory `PROVIDER/files/webapp` get copied to after a `leap deploy` to a live webapp nodes.
-
-### Override translations
-
-You can add additional locale files in order to change the text used in the existing application and to add translations for string that you added to the application.
-
-In this example, we will be altering the default text for the "login_info" string. In `config/locales/en/home.en.yml` there is this entry:
-
- en:
- login_info: "Log in to change your account settings, create support tickets, and manage payments."
-
-We are going to override this with some custom text in English and Spanish:
-
-`leap_web/config/customization/locale/en.yml`:
-
- en:
- login_info: Authenticate to change your "Prehistoric Computer" settings.
-
-`leap_web/config/customization/locale/es.yml`:
-
- es:
- login_info: Autenticar a cambiar la configuración de "Computer Prehistoria."
-
-Now, the home page of leap_web will use these new strings instead of the default. Remember that you must restart rails in order for new locale files to take effect.
-
-### Override static pages
-
-You can also override any of the static files included with leap_web, such as the privacy policy or terms of service.
-
-Here is how we would create a custom privacy policy in English and Spanish:
-
-`leap_web/config/customization/views/pages/privacy-policy.en.md`:
-
- # Custom Privacy Policy
- This is our privacy policy.
-
-`leap_web/config/customization/views/pages/privacy-policy.es.md`:
-
- # Custom Política de Privacidad
- Esta es nuestra política de privacidad.
-
-### Add a custom header
-
-Now we will add a custom header to every page. First, we add the images:
-
- leap_web/config/customization
- ├── public
- ├── favicon.ico
- └── img
- └── masthead.png
-
-You can create your own, or use the example files in https://github.com/leapcode/leap_web/tree/develop/config/customization.example
-
-Now, we add some custom CSS so that we can style the masthead:
-
-`leap_web/config/customization/stylesheets/tail.scss`
-
- $custom-color: #66bbaa;
-
- a {
- color: $custom-color;
- }
-
- //
- // MASTHEAD
- //
-
- #masthead {
- background-color: $custom-color;
- border-bottom: none;
-
- // make the masthead clickable by replacing the
- // site name link with the masthead image:
- .title {
- padding: 0px;
- .sitename a {
- display: block;
- background: url(/img/masthead.png) 0 0 no-repeat;
- font-size: 0px;
- height: 100px;
- background-size: auto 100px;
- }
- }
- }
-
- // make the home page masthead slightly larger
- body.home #masthead {
- .sitename a {
- height: 150px;
- background-size: auto 150px;
- }
- }
-
- //
- // FOOTER
- //
-
- #footer .links {
- background-color: $custom-color;
- }
-
-NOTE: If you add a `tails.scss` or `head.scss` file, then you usually need to run `rake tmp:clear` and restart rails in order for the new stylesheet to get recognized. You should only need to do this once.
-
-
-Custom Fork
-----------------------------
-
-Sometimes it is easier to maintain your own fork of the leap_web app. You can keep your customizations in that fork instead of in the provider `files/webapp` directory. Or, perhaps you want to add an engine to the application that modifies the app's behavior.
-
-To deploy your own leap_web, modify the provider file `common.json`:
-
- {
- "sources": {
- "webapp": {
- "revision": "origin/develop",
- "source": "https://github.com/leapcode/leap_web",
- "type": "git"
- }
- }
- }
-
-To target only particular environment, modify instead `common.ENV.json`, where ENV is the name of the environment.
-
-See https://github.com/leapcode/leap_web/blob/develop/doc/DEVELOP.md for notes on getting started hacking on leap_web.
-
-Maintenance mode
-------------------
-
-You can put the webapp into maintenance mode by simply dropping a html file to `/srv/leap/webapp/public/system/maintenance.html`. For example:
-
- workstation$ leap ssh webappnode
- server# echo "Temporarily down for maintenance. We will be back soon." > /srv/leap/webapp/public/system/maintenance.html
-
-Known problems
----------------------------
-
-* Client certificates are generated without a CSR. The problem is that this makes the web
- application extremely vulnerable to denial of service attacks. This was not an issue until we
- started to allow the possibility of anonymously fetching a client certificate without
- authenticating first.
-* By its very nature, the user database is vulnerable to enumeration attacks. These are
- very hard to prevent, because our protocol is designed to allow query of a user database via
- proxy in order to provide network perspective.
diff --git a/doc/troubleshooting/en.haml b/doc/troubleshooting/en.haml
deleted file mode 100644
index f0f1359c..00000000
--- a/doc/troubleshooting/en.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- @title = "Troubleshooting"
-
-= child_summaries \ No newline at end of file
diff --git a/doc/troubleshooting/known-issues.md b/doc/troubleshooting/known-issues.md
deleted file mode 100644
index 4defc886..00000000
--- a/doc/troubleshooting/known-issues.md
+++ /dev/null
@@ -1,115 +0,0 @@
-@title = 'Leap Platform Release Notes'
-@nav_title = 'Known issues'
-@summary = 'Known issues in the Leap Platform.'
-@toc = true
-
-Here you can find documentation about known issues and potential work-arounds in the current Leap Platform release.
-
-0.6.0
-==============
-
-Upgrading
-------------------
-
-Upgrade your leap_platform to 0.6 and make sure you have the latest leap_cli.
-
-**Update leap_platform:**
-
- cd leap_platform
- git pull
- git checkout -b 0.6.0 0.6.0
-
-**Update leap_cli:**
-
-If it is installed as a gem from rubygems:
-
- sudo gem update leap_cli
-
-If it is installed as a gem from source:
-
- cd leap_cli
- git pull
- git checkout master
- rake build
- sudo rake install
-
-If it is run directly from source:
-
- cd leap_cli
- git pull
- git checkout master
-
-To upgrade:
-
- leap --version # must be at least 1.6.2
- leap cert update
- leap deploy
- leap test
-
-If the tests fail, try deploying again. If a test fails because there are two tapicero daemons running, you need to ssh into the server, kill all the tapicero daemons manually, and then try deploying again (sometimes the daemon from platform 0.5 would put its PID file in an odd place).
-
-OpenVPN
-------------------
-
-On deployment to a openvpn node, if the following happens:
-
- - err: /Stage[main]/Site_openvpn/Service[openvpn]/ensure: change from stopped to running failed: Could not start Service[openvpn]: Execution of '/etc/init.d/openvpn start' returned 1: at /srv/leap/puppet/modules/site_openvpn/manifests/init.pp:189
-
-this is likely the result of a kernel upgrade that happened during the deployment, requiring that the machine be restarted before this service can start. To confirm this, login to the node (leap ssh <nodename>) and look at the end of the /var/log/daemon.log:
-
- # tail /var/log/daemon.log
- Nov 22 19:04:15 snail ovpn-udp_config[16173]: ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such device (errno=19)
- Nov 22 19:04:15 snail ovpn-udp_config[16173]: Exiting due to fatal error
-
-if you see this error, simply restart the node.
-
-CouchDB
----------------------
-
-At the moment, we strongly advise only have one bigcouch server for stability purposes.
-
-With multiple couch nodes (not recommended at this time), in some scenarios, such as when certain components are unavailable, the couchdb syncing will be broken. When things are brought back to normal, shortly after restart, the nodes will attempt to resync all their data, and can fail to complete this process because they run out of file descriptors. A symptom of this is the webapp wont allow you to register or login, the /opt/bigcouch/var/log/bigcouch.log is huge with a lot of errors that include (over multiple lines): {error, emfile}}. We have raised the limits for available file descriptors to bigcouch to try and accommodate for this situation, but if you still experience it, you may need to increase your /etc/sv/bigcouch/run ulimit values and restart bigcouch while monitoring the open file descriptors. We hope that in the next platform release, a newer couchdb will be better at handling these resources.
-
-You can also see the number of file descriptors in use by doing:
-
- # watch -n1 -d lsof -p `pidof beam`|wc -l
-
-The command `leap db destroy` will not automatically recreate new databases. You must run `leap deploy` afterwards for this.
-
-User setup and ssh
-------------------
-
-At the moment, it is only possible to add an admin who will have access to all LEAP servers (see: https://leap.se/code/issues/2280)
-
-The command `leap add-user --self` allows only one SSH key. If you want to specify more than one key for a user, you can do it manually:
-
- users/userx/userx_ssh.pub
- users/userx/otherkey_ssh.pub
-
-All keys matching 'userx/*_ssh.pub' will be used for that user.
-
-Deploying
----------
-
-If you have any errors during a run, please try to deploy again as this often solves non-deterministic issues that were not uncovered in our testing. Please re-deploy with `leap -v2 deploy` to get more verbose logs and capture the complete output to provide to us for debugging.
-
-If when deploying your debian mirror fails for some reason, network anomoly or the mirror itself is out of date, then platform deployment will not succeed properly. Check the mirror is up and try to deploy again when it is resolved (see: https://leap.se/code/issues/1091)
-
-Deployment gives 'error: in `%`: too few arguments (ArgumentError)' - this is because you attempted to do a deploy before initializing a node, please initialize the node first and then do a deploy afterwards (see: https://leap.se/code/issues/2550)
-
-This release has no ability to custom configure apt sources or proxies (see: https://leap.se/code/issues/1971)
-
-When running a deploy at a verbosity level of 2 and above, you will notice puppet deprecation warnings, these are known and we are working on fixing them
-
-IPv6
-----
-
-As of this release, IPv6 is not supported by the VPN configuration. If IPv6 is detected on your network as a client, it is blocked and instead it should revert to IPv4. We plan on adding IPv6 support in an upcoming release.
-
-
-Special Environments
---------------------
-
-When deploying to OpenStack release "nova" or newer, you will need to do an initial deploy, then when it has finished run `leap facts update` and then deploy again (see: https://leap.se/code/issues/3020)
-
-It is not possible to actually use the EIP openvpn server on vagrant nodes (see: https://leap.se/code/issues/2401)
diff --git a/doc/troubleshooting/tests.md b/doc/troubleshooting/tests.md
deleted file mode 100644
index 607f924e..00000000
--- a/doc/troubleshooting/tests.md
+++ /dev/null
@@ -1,70 +0,0 @@
-@title = 'Tests and Monitoring'
-@summary = 'Testing and monitoring your infrastructure.'
-@toc = true
-
-## Troubleshooting Tests
-
-At any time, you can run troubleshooting tests on the nodes of your provider infrastructure to check to see if things seem to be working correctly. If there is a problem, these tests should help you narrow down precisely where the problem is.
-
-To run tests on FILTER node list:
-
- workstation$ leap test run FILTER
-
-For example, you can also test a single node (`leap test elephant`); test a specific environment (`leap test development`), or any tag (`leap test soledad`).
-
-Alternately, you can run test on all nodes (probably only useful if you have pinned the environment):
-
- workstation$ leap test
-
-The tests that are performed are located in the platform under the tests directory.
-
-## Testing with the bitmask client
-
-Download the provider ca:
-
- wget --no-check-certificate https://example.org/ca.crt -O /tmp/ca.crt
-
-Start bitmask:
-
- bitmask --ca-cert-file /tmp/ca.crt
-
-## Testing Recieving Mail
-
-Use i.e. swaks to send a testmail
-
- swaks -f noone@example.org -t testuser@example.org -s example.org
-
-and use your favorite mail client to examine your inbox.
-
-You can also use [offlineimap](http://offlineimap.org/) to fetch mails:
-
- offlineimap -c vagrant/.offlineimaprc.example.org
-
-WARNING: Use offlineimap *only* for testing/debugging,
-because it will save the mails *decrypted* locally to
-your disk !
-
-## Monitoring
-
-In order to set up a monitoring node, you simply add a `monitor` service tag to the node configuration file. It could be combined with any other service, but we propose that you add it to the webapp node, as this already is public accessible via HTTPS.
-
-After deploying, this node will regularly poll every node to ask for the status of various health checks. These health checks include the checks run with `leap test`, plus many others.
-
-We use [Nagios](https://www.nagios.org/) together with [Check MK agent](https://en.wikipedia.org/wiki/Check_MK) for running checks on remote hosts.
-
-One nagios installation will monitor all nodes in all your environments. You can log into the monitoring web interface via [https://DOMAIN/nagios3/](https://DOMAIN/nagios3/). The username is `nagiosadmin` and the password is found in the secrets.json file in your provider directory.
-Nagios will send out mails to the `contacts` address provided in `provider.json`.
-
-
-## Nagios Frontends
-
-There are other ways to check and get notified by Nagios besides regularly checking the Nagios webinterface or reading email notifications. Check out the [Frontends (GUIs and CLIs)](http://exchange.nagios.org/directory/Addons/Frontends-%28GUIs-and-CLIs%29) on the Nagios project website.
-A recommended status tray application is [Nagstamon](https://nagstamon.ifw-dresden.de/), which is available for Linux, MacOS X and Windows. It can not only notify you of hosts/services failures, you can also acknowledge or recheck them.
-
-### Log Monitoring
-
-At the moment, we use [check-mk-agent-logwatch](https://mathias-kettner.de/checkmk_check_logwatch.html) for searching logs for irregularities.
-Logs are parsed for patterns using a blacklist, and are stored in `/var/lib/check_mk/logwatch/<Nodename>`.
-
-In order to "acknowledge" a log warning, you need to log in to the monitoring server, and delete the corresponding file in `/var/lib/check_mk/logwatch/<Nodename>`. This should be done via the nagios webinterface in the future.
-
diff --git a/doc/troubleshooting/where-to-look.md b/doc/troubleshooting/where-to-look.md
deleted file mode 100644
index c92fba8f..00000000
--- a/doc/troubleshooting/where-to-look.md
+++ /dev/null
@@ -1,267 +0,0 @@
-@title = 'Where to look for errors'
-@nav_title = 'Where to look'
-@toc = true
-
-
-General
-=======
-
-* Please increase verbosity when debugging / filing issues in our issue tracker. You can do this with adding i.e. `-v 5` after the `leap` cmd, i.e. `leap -v 2 deploy`.
-* We use the `example.org` domain for documentation purposes here, please replace it with the you domain.
-
-Firewall
-=======================
-
-Every node in your provider has its own restrictive firewall, but you might have a network firewall in place as well that is not managed by LEAP platform. To see what ports and addresses must be open, run this command:
-
- workstation$ leap compile firewall
-
-If any of those are blocked, then your provider will not work.
-
-Webapp
-======
-
-Places to look for errors
--------------------------
-
-* `/var/log/apache2/error.log`
-* `/srv/leap/webapp/log/production.log`
-* `/var/log/syslog` (watch out for stunnel issues)
-* `/var/log/leap/*`
-
-
-Is haproxy ok ?
----------------
-
- curl -s -X GET "http://127.0.0.1:4096"
-
-Is couchdb accessible through stunnel ?
----------------------------------------
-
-* Depending on how many couch nodes you have, increase the port for every test
- (see /etc/haproxy/haproxy.cfg for the server/port mapping):
-
-
- curl -s -X GET "http://127.0.0.1:4000"
- curl -s -X GET "http://127.0.0.1:4001"
- ...
-
-
-Check couchdb acl as admin
---------------------------
-
- mkdir /etc/couchdb
- cat /srv/leap/webapp/config/couchdb.yml.admin # see username and password
- echo "machine 127.0.0.1 login admin password <PASSWORD>" > /etc/couchdb/couchdb-admin.netrc
- chmod 600 /etc/couchdb/couchdb-admin.netrc
-
- curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096"
- curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096/_all_dbs"
-
-Check couchdb acl as unpriviledged user
----------------------------------------
-
- cat /srv/leap/webapp/config/couchdb.yml # see username and password
- echo "machine 127.0.0.1 login webapp password <PASSWORD>" > /etc/couchdb/couchdb-webapp.netrc
- chmod 600 /etc/couchdb/couchdb-webapp.netrc
-
- curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096"
- curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096/_all_dbs"
-
-
-All URLs accessible ?
----------------------
-
-* https://example.org
-* https://api.example.org:4430/provider.json
-* https://example.org/ca.crt
-
-
-Check client config files
--------------------------
-
-* https://example.net/provider.json
-* https://example.net/1/config/smtp-service.json
-* https://example.net/1/config/soledad-service.json
-* https://example.net/1/config/eip-service.json
-
-
-Soledad
-=======
-
- /var/log/soledad.log
-
-
-Couchdb
-=======
-
-Places to look for errors
--------------------------
-
-* `/opt/bigcouch/var/log/bigcouch.log`
-* `/var/log/syslog` (watch out for stunnel issues)
-
-
-
-Bigcouch membership
--------------------
-
-* All nodes configured for the provider should appear here:
-
-<pre>
- curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET 'http://127.0.0.1:5986/nodes/_all_docs'
-</pre>
-
-* All configured nodes should show up under "cluster_nodes", and the ones online and communicating with each other should appear under "all_nodes". This example output shows the configured cluster nodes `couch1.bitmask.net` and `couch2.bitmask.net`, but `couch2.bitmask.net` is currently not accessible from `couch1.bitmask.net`
-
-
-<pre>
- curl -s --netrc-file /etc/couchdb/couchdb.netrc 'http://127.0.0.1:5984/_membership'
- {"all_nodes":["bigcouch@couch1.bitmask.net"],"cluster_nodes":["bigcouch@couch1.bitmask.net","bigcouch@couch2.bitmask.net"]}
-</pre>
-
-* Sometimes a `/etc/init.d/bigcouch restart` on all nodes is needed, to register new nodes
-
-Databases
----------
-
-* Following output shows all neccessary DBs that should be present. Note that the `user-0123456....` DBs are the data stores for a particular user.
-
-<pre>
- curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET 'http://127.0.0.1:5984/_all_dbs'
- ["customers","identities","sessions","shared","tickets","tokens","user-0","user-9d34680b01074c75c2ec58c7321f540c","user-9d34680b01074c75c2ec58c7325fb7ff","users"]
-</pre>
-
-
-
-
-Design Documents
-----------------
-
-* Is User `_design doc` available ?
-
-
-<pre>
- curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET "http://127.0.0.1:5984/users/_design/User"
-</pre>
-
-Is couchdb cluster backend accessible through stunnel ?
--------------------------------------------------------
-
-* Find out how many connections are set up for the couchdb cluster backend:
-
-<pre>
- grep "accept = 127.0.0.1" /etc/stunnel/*
-</pre>
-
-
-* Now connect to all of those local endpoints to see if they up. All these tests should return "localhost [127.0.0.1] 4000 (?) open"
-
-<pre>
- nc -v 127.0.0.1 4000
- nc -v 127.0.0.1 4001
- ...
-</pre>
-
-
-MX
-==
-
-Places to look for errors
--------------------------
-
-* `/var/log/mail.log`
-* `/var/log/leap_mx.log`
-* `/var/log/syslog` (watch out for stunnel issues)
-
-Is couchdb accessible through stunnel ?
----------------------------------------
-
-* Depending on how many couch nodes you have, increase the port for every test
- (see /etc/haproxy/haproxy.cfg for the server/port mapping):
-
-
- curl -s -X GET "http://127.0.0.1:4000"
- curl -s -X GET "http://127.0.0.1:4001"
- ...
-
-Query leap-mx
--------------
-
-* for useraccount
-
-
-<pre>
- postmap -v -q "joe@dev.bitmask.net" tcp:localhost:2244
- ...
- postmap: dict_tcp_lookup: send: get jow@dev.bitmask.net
- postmap: dict_tcp_lookup: recv: 200
- ...
-</pre>
-
-* for mailalias
-
-
-<pre>
- postmap -v -q "joe@dev.bitmask.net" tcp:localhost:4242
- ...
- postmap: dict_tcp_lookup: send: get joe@dev.bitmask.net
- postmap: dict_tcp_lookup: recv: 200 f01bc1c70de7d7d80bc1ad77d987e73a
- postmap: dict_tcp_lookup: found: f01bc1c70de7d7d80bc1ad77d987e73a
- f01bc1c70de7d7d80bc1ad77d987e73a
- ...
-</pre>
-
-
-Check couchdb acl as unpriviledged user
----------------------------------------
-
-
-
- cat /etc/leap/mx.conf # see username and password
- echo "machine 127.0.0.1 login leap_mx password <PASSWORD>" > /etc/couchdb/couchdb-leap_mx.netrc
- chmod 600 /etc/couchdb/couchdb-leap_mx.netrc
-
- curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/_all_dbs" # pick one "user-<hash>" db
- curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/user-de9c77a3d7efbc779c6c20da88e8fb9c"
-
-
-* you may check multiple times, cause 127.0.0.1:4096 is haproxy load-balancing the different couchdb nodes
-
-
-Mailspool
----------
-
-* Any file in the leap_mx mailspool longer for a few seconds ?
-
-
-
-<pre>
- ls -la /var/mail/vmail/Maildir/cur/
-</pre>
-
-* Any mails in postfix mailspool longer than a few seconds ?
-
-<pre>
- mailq
-</pre>
-
-
-
-Testing mail delivery
----------------------
-
- swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 25
- swaks -f varac@cdev.bitmask.net -t varac@cdev.bitmask.net -s chipmonk.cdev.bitmask.net --port 465 --tlsc
- swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 587 --tls
-
-
-VPN
-===
-
-Places to look for errors
--------------------------
-
-* `/var/log/syslog` (watch out for openvpn issues)
-
-
diff --git a/doc/tutorials/en.haml b/doc/tutorials/en.haml
deleted file mode 100644
index 1c73fc0f..00000000
--- a/doc/tutorials/en.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- @nav_title = "Tutorials"
-- @title = "Platform Tutorials"
-
-= child_summaries \ No newline at end of file
diff --git a/doc/tutorials/quick-start.md b/doc/tutorials/quick-start.md
deleted file mode 100644
index f963867a..00000000
--- a/doc/tutorials/quick-start.md
+++ /dev/null
@@ -1,230 +0,0 @@
-@title = 'Quick Start Tutorial'
-@nav_title = 'Quick Start Tutorial'
-@summary = 'This tutorial walks you through the initial process of creating and deploying a minimal service provider running the LEAP Platform.'
-
-Introduction
-====================================
-
-### Our goal
-
-We are going to create a minimal LEAP provider, but one that does not offer any actual services. Check out the other tutorials for adding VPN or email services.
-
-Our goal is something like this:
-
- $ leap list
- NODES SERVICES TAGS
- wildebeest couchdb, webapp
-
-NOTE: You won't be able to run that `leap list` command yet, not until we actually create the node configurations.
-
-### Requirements
-
-1. A workstation: This is your local machine that you will run commands on.
-1. A server: This is the machine that you will deploy to. The server can be either:
- 1. A local Vagrant virtual machine: a Vagrant machine can only be useful for testing.
- 1. A real or paravirtualized server: The server must have Debian Jessie installed, and you must be able to SSH into the machine as root. Paravirtualization includes KVM, Xen, OpenStack, Amazon, but not VirtualBox or OpenVZ.
-
-Other things to keep in mind:
-
-* The ability to create/modify DNS entries for your domain is preferable, but not needed. If you don't have access to DNS, you can workaround this by modifying your local resolver, i.e. editing `/etc/hosts`.
-* You need to be aware that this process will make changes to your servers, so please be sure that these machines are a basic install with nothing configured or running for other purposes.
-* Your servers will need to be connected to the internet, and not behind a restrictive firewall.
-
-Prepare your workstation
-========================
-
-In order to be able to manage your servers, you need to install the `leap` command on your workstation:
-
-### Install pre-requisites
-
-Install core prerequisites on your workstation.
-
-*Debian & Ubuntu*
-
- workstation$ sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make bzip2
-
-*Mac OS*
-
- workstation$ brew install ruby-install
- workstation$ ruby-install ruby
-
-### Install the LEAP command-line utility
-
-Install the `leap` command from rubygems.org:
-
- workstation$ gem install leap_cli --install-dir ~/leap
- workstation$ export PATH=$PATH:~/leap/bin
-
-Alternately, you can install `leap` system wide:
-
- workstation$ sudo gem install leap_cli
-
-To confirm that you installed `leap` correctly, try running `leap help`.
-
-Create a provider instance
-=============================================
-
-A provider instance is a directory tree, residing on your workstation, that contains everything you need to manage an infrastructure for a service provider.
-
-In this case, we create one for example.org and call the instance directory 'example'.
-
- workstation$ leap new ~/example
-
-The `leap new` command will ask you for several required values:
-
-* domain: The primary domain name of your service provider. In this tutorial, we will be using "example.org".
-* name: The name of your service provider (we use "Example").
-* contact emails: A comma separated list of email addresses that should be used for important service provider contacts (for things like postmaster aliases, Tor contact emails, etc).
-* platform: The directory where you have a copy of the `leap_platform` git repository checked out. If the platform directory does not yet exist, the `leap_platform` will be downloaded and placed in that directory.
-
-You could also have passed these configuration options on the command-line, like so:
-
- workstation$ leap new --contacts your@email.here --domain example.org --name Example --platform=~/leap/leap_platform .
-
-You should now have the following files:
-
- workstation$ tree example
- example
- ├── common.json
- ├── Leapfile
- ├── nodes/
- ├── provider.json
- ├── services/
- └── tags/
-
-Now add yourself as a privileged sysadmin who will have access to deploy to servers:
-
- workstation$ cd example
- workstation$ leap add-user louise --self
-
-Replace "louise" with whatever you want your sysadmin username to be.
-
-NOTE: Make sure you change directories so that the `leap` command is run from within the provider instance directory. Most `leap` commands only work when run from a provider instance.
-
-Now create the necessary keys and certificates:
-
- workstation$ leap cert ca
- workstation$ leap cert csr
-
-What do these commands do? The first command will create two Certificate Authorities, one that clients will use to authenticate with the servers and one for backend servers to authenticate with each other. The second command creates a Certificate Signing Request suitable for submission to a commercial CA. It also creates two "dummy" files for you to use temporarily:
-
-* `files/cert/example.org.crt` -- This is a "dummy" certificate for your domain that can be used temporarily for testing. Once you get a real certificate from a CA, you should replace this file.
-* `files/cert/commercial_ca.crt` -- This is "dummy" CA cert the corresponds to the dummy domain certificate. Once you replace the domain certificate, also replace this file with the CA cert from the real Certificate Authority.
-
-If you plan to run a real service provider, see important information on [[managing keys and certificates => keys-and-certificates]].
-
-Add a node to the provider
-==================================================
-
-A "node" is a server that is part of your infrastructure. Every node can have one or more services associated with it. We will now add a single node with two services, "webapp" and "couchdb".
-
-You have two choices for node type: a real node or a local node.
-
-* Real Node: A real node is any physical or paravirtualized server, including KVM, Xen, OpenStack Compute, Amazon EC2, but not VirtualBox or OpenVZ (VirtualBox and OpenVZ use a more limited form of virtualization). The server must be running Debian Jessie.
-* Local Node: A local node is a virtual machine created by Vagrant, useful for local testing on your workstation.
-
-Getting Vagrant working can be a pain and is [[covered in other tutorials => vagrant]]. If you have a real server available, we suggest you try this tutorial with a real node first.
-
-### Option A: Add a real node
-
-Note: Installing LEAP Platform on this server will potentially destroy anything you have previously installed on this machine.
-
-Create a node, with the services "webapp" and "couchdb":
-
- workstation$ leap node add wildebeest ip_address:x.x.x.w services:webapp,couchdb
-
-NOTE: replace x.x.x.x with the actual IP address of this server.
-
-### Option B: Add a local node
-
-Create a node, with the services "webapp" and "couchdb", and then start the local virtual machine:
-
- workstation$ leap node add --local wildebeest services:webapp,couchdb
- workstation$ leap local start wildebeest
-
-It will take a while to download the Virtualbox base box and create the virtual machine.
-
-Deploy your provider
-=========================================
-
-### Initialize the node
-
-Node initialization only needs to be done once, but there is no harm in doing it multiple times:
-
- workstation$ leap node init wildebeest
-
-This will initialize the node `wildebeest`.
-
-For non-local nodes, when `leap node init` is run, you will be prompted to verify the fingerprint of the SSH host key and to provide the root password of the server(s). You should only need to do this once.
-
-### Deploy to the node
-
-The next step is to deploy the LEAP platform to your node. [Deployment can take a while to run](https://xkcd.com/303/), especially on the first run, as it needs to update the packages on the new machine.
-
- workstation$ leap deploy wildebeest
-
-Watch the output for any errors (in red), if everything worked fine, you should now have your first running node. If you do have errors, try doing the deploy again.
-
-### Setup DNS
-
-The next step is to configure the DNS for your provider. For testing purposes, you can just modify your `/etc/hosts` file. Please don't forget about these entries, they will override DNS queries if you setup your DNS later. For a list of what entries to add to `/etc/hosts`, run this command:
-
- workstation$ leap compile hosts
-
-Alternately, if you have access to modify the DNS zone entries for your domain:
-
- workstation$ leap compile zone
-
-NOTE: The resulting zone file is incomplete because it is missing a serial number. Use the output of `leap compile zone` as a guide, but do not just copy and paste the output. Also, the `compile zone` output will always exclude mention of local nodes.
-
-The DNS method will not work for local nodes created with Vagrant.
-
-Test that things worked correctly
-=================================
-
-To run troubleshooting tests:
-
- workstation$ leap test
-
-Alternately, you can run these same tests from the server itself:
-
- workstation$ leap ssh wildebeest
- wildebeest# run_tests
-
-Create an administrator
-===============================
-
-Assuming that you set up your DNS or `/etc/hosts` file, you should be able to load `https://example.org` in your web browser (where example.org is whatever domain name you actually used).
-
-Your browser will complain about an untrusted cert, but for now just bypass this. From there, you should be able to register a new user and login.
-
-Once you have created a user, you can now make this user an administrator. For example, if you created a user `kangaroo`, you would create the file `services/webapp.json` with the following content:
-
- {
- "webapp": {
- "admins": ["kangaroo"]
- }
- }
-
-Save that file and run `leap deploy` again. When you next log on to the web application, the user kangaroo will now be an admin.
-
-If you want to restrict who can register a new user, see [[webapp]] for configuration options.
-
-What is next?
-======================
-
-Add an end-user service
--------------------------------
-
-You should now have a minimal service provider with a single node. This service provider is pointless at the moment, because it does not include any end-user services like VPN or email. To add one of these services, continue with one of the following tutorials:
-
-* [[single-node-email]]
-* [[single-node-vpn]]
-
-Learn more
----------------
-
-We have only just scratched the surface of the possible ways to configure and deploy your service provider. Your next step should be:
-
-* Read [[getting-started]] for more details on using the LEAP platform.
-* See [[commands]] for a list of possible commands.
diff --git a/doc/tutorials/single-node-email.md b/doc/tutorials/single-node-email.md
deleted file mode 100644
index 0a73e6e1..00000000
--- a/doc/tutorials/single-node-email.md
+++ /dev/null
@@ -1,69 +0,0 @@
-@title = 'Single node email tutorial'
-@nav_title = 'Quick email'
-@summary = 'Tutorial for setting up a simple email provider.'
-
-This tutorial walks you through the initial process of creating and deploying a minimal email service provider. Please first complete the [[quick-start]]. This tutorial will pick up where that one left off.
-
-Our goal
-------------------
-
-We are going to create a minimal LEAP provider offering email service.
-
-Our goal is something like this:
-
- $ leap list
- NODES SERVICES TAGS
- wildebeest couchdb, mx, soledad, webapp
-
-Where 'wildebeest' is whatever name you chose for your node in the [[quick-start]].
-
-Add email services to the node
---------------------------------------
-
-In order to add [[services => services]] to a node, edit the node's JSON configuration file.
-
-In our example, we would edit `nodes/wildebeest.json`:
-
- {
- "ip_address": "1.1.1.1",
- "services": ["couchdb", "webapp", "mx", "soledad"]
- }
-
-Here, we added `mx` and `soledad` to the node's `services` list. Briefly:
-
-* **mx**: nodes with the **mx** service will run postfix mail transfer agent, and are able to receive and relay email on behalf of your domain. You can have as many as you want, spread out over as many nodes as you want.
-* **soledad**: nodes with **soledad** service run the server-side daemon that allows the client to synchronize a user's personal data store among their devices. Currently, **soledad** only runs on nodes that are also **couchdb** nodes.
-
-For more details, see the [[services]] overview, or the individual pages for the [[mx]] and [[soledad]] services.
-
-Deploy to the node
---------------------
-
-Now you should deploy to your node.
-
- workstation$ leap deploy
-
-Setup DNS
-----------------------------
-
-There are several important DNS entries that all email providers should have:
-
-* SPF (Sender Policy Framework): With SPF, an email provider advertises in their DNS which servers should be allowed to relay email on behalf of your domain.
-* DKIM (DomainKey Identified Mail): With DKIM, an email provider is able to vouch for the validity of certain headers in outgoing mail, allowing the receiving provider to have more confidence in these values when processing the message for spam or abuse.
-
-In order to take advantage of SPF and DKIM, run this command:
-
- workstation$ leap compile zone
-
-Then take the output of that command and merge it with the DNS zone file for your domain.
-
-CAUTION: the output of `leap compile zone` is not a complete zone file since it is missing a serial number. You will need to manually merge it with your existing zone file.
-
-Test it out
----------------------------------
-
-First, run:
-
- workstation# leap test
-
-Then fire up the bitmask client, register a new user with your provider, and try sending and receiving email.
diff --git a/doc/tutorials/single-node-vpn.md b/doc/tutorials/single-node-vpn.md
deleted file mode 100644
index dc1df7ab..00000000
--- a/doc/tutorials/single-node-vpn.md
+++ /dev/null
@@ -1,112 +0,0 @@
-@title = "Single node VPN tutorial"
-@nav_title = "Quick VPN"
-@summary = 'Tutorial for setting up a simple VPN provider.'
-
-This tutorial walks you through the initial process of creating and deploying a minimal VPN service provider. Please first complete the [[quick-start]]. This tutorial will pick up where that one left off.
-
-NOTE: For the VPN to work, you must use a real or paravirtualized node, not a local Vagrant node.
-
-Our goal
-------------------
-
-We are going to create a minimal LEAP provider offering VPN service.
-
-Our goal is something like this:
-
- $ leap list
- NODES SERVICES TAGS
- wildebeest couchdb, webapp, openvpn, tor
-
-Where 'wildebeest' is whatever name you chose for your node in the [[quick-start]].
-
-Add VPN service to the node
---------------------------------------
-
-In order to add [[services => services]] to a node, edit the node's JSON configuration file.
-
-In our example, we would edit `nodes/wildebeest.json`:
-
- {
- "ip_address": "1.1.1.1",
- "services": ["couchdb", "webapp", "openvpn", "tor"]
- }
-
-Here, we added `openvpn` and `tor` to the node's `services` list. Briefly:
-
-* **openvpn**: nodes with the **openvpn** service will become OpenVPN gateways that clients connect to in order to proxy their internet connection. You can have as many as you want, spread out over as many nodes as you want.
-* **tor**: nodes with **tor** service become Tor exit nodes. This is entirely optional, and will add additional bandwidth to your node. If you don't have many VPN users, the added traffic will help create cover traffic for your users. On the down side, this VPN gateway will get flagged as an anonymous proxy and some sites may block traffic from it.
-
-For more details, see the [[services]] overview, or the individual pages for the [[openvpn]] and [[tor]] services.
-
-Add gateway_address to the node
-----------------------------------------
-
-VPN gateways require two different IP addresses:
-
-* `ip_address`: This property is used for VPN traffic **egress**. In other words, all VPN traffic appears to come from this IP address. This is also the main IP of the server.
-* `openvpn.gateway_address`: This property is used for VPN traffic **ingress**. In other words, clients will connect to this IP address.
-
-The node configuration file should now look like this:
-
- {
- "ip_address": "1.1.1.1",
- "services": ["couchdb", "webapp", "openvpn", "tor"],
- "openvpn": {
- "gateway_address": "2.2.2.2"
- }
- }
-
-Why two different addresses? Without this, the traffic from one VPN user to another would not be encrypted. This is because the routing table of VPN clients must ensure that packets with a destination of the VPN gateway are sent unmodified and don't get passed through the VPN's encryption.
-
-Generate a Diffie-Hellman file
--------------------------------------------
-
-Next we need to create a Diffie-Hellman parameter file, used for forward secret OpenVPN ciphers. You only need to do this once.
-
- workstation$ leap cert dh
-
-Feel free to erase the resulting DH file and regenerate it as you please.
-
-Deploy to the node
---------------------
-
-Now you should deploy to your node. This may take a while.
-
- workstation$ leap deploy
-
-If the deploy was not successful, try to run it again.
-
-Test it out
----------------------------------
-
-First, run:
-
- workstation$ leap test
-
-Then fire up the Bitmask client, register a new user with your provider, and turn on the VPN connection.
-
-Alternately, you can also manually connect to your VPN gateway using OpenVPN on the command line:
-
- workstation$ sudo apt install openvpn
- workstation$ leap test init
- workstation$ sudo openvpn --config test/openvpn/default_unlimited.ovpn
-
-Make sure that Bitmask is not connected to the VPN when you run that command.
-
-The name of the test configuration might differ depending on your setup. The test configuration created by `leap test init` includes a client certificate that will expire, so you may need to re-run `leap test init` if it has been a while since you last generated the test configuration.
-
-What do do next
---------------------------------
-
-A VPN provider with a single gateway is kind of limited. You can add as many nodes with service [[openvpn]] as you like. There is no communication among the VPN gateways or with the [[webapp]] or [[couchdb]] nodes, so there is no issue with scaling out the number of gateways.
-
-For example, add some more nodes:
-
- workstation$ leap node add giraffe ip_address:1.1.1.2 services:openvpn openvpn.gateway_address:2.2.2.3
- workstation$ leap node add rhino ip_address:1.1.1.3 services:openvpn openvpn.gateway_address:2.2.2.4
- workstation$ leap node init giraffe rhino
- workstation$ leap deploy
-
-Now you have three VPN gateways.
-
-One consideration is that you should tag each VPN gateway with a [[location => nodes#locations]]. This helps the client determine which VPN gateway it should connect to by default and will allow the user to choose among gateways based on location.
diff --git a/doc/tutorials/vagrant.md b/doc/tutorials/vagrant.md
deleted file mode 100644
index 710c2664..00000000
--- a/doc/tutorials/vagrant.md
+++ /dev/null
@@ -1,471 +0,0 @@
-@title = 'Vagrant and the LEAP Platform'
-@nav_title = 'Vagrant'
-@summary = 'Running a local provider with Vagrant'
-
-What is Vagrant?
-========================================
-
-[[Vagrant => https://www.vagrantup.com]] is a tool to make it easier to manage virtual machines running on your desktop computer (typically for testing or development purposes). You can use Vagrant to create virtual machines and deploy the LEAP platform locally.
-
-Vagrant can be a pain to get working initially, but this page should help you get through the process. Please make sure you have at least Vagrant v1.5 installed.
-
-There are two ways you can setup LEAP platform using Vagrant.
-
-1. use the `leap` command: this will allow you to create multiple virtual machines.
-2. use static Vagrantfile: there is a static Vagrantfile that is distributed with the `leap_platform.git`. This only supports a single, pre-configured virtual machine, but can get you started more quickly.
-
-Install Vagrant
-========================================
-
-Requirements:
-
-* A real machine with virtualization support in the CPU (VT-x or AMD-V). In other words, not a virtual machine.
-* Have at least 4gb of RAM.
-* Have a fast internet connection (because you will be downloading a lot of big files, like virtual machine images).
-* You should do everything described below as an unprivileged user, and only run those commands as root that are noted with *sudo* in front of them. Other than those commands, there is no need for privileged access to your machine, and in fact things may not work correctly.
-
-*Debian & Ubuntu*
-
-Install core prerequisites:
-
- sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make
-
-Install Vagrant:
-
- sudo apt-get install vagrant virtualbox
-
-If you want to use libvirt instead of virtualbox, you don't need to install virtualbox. See [support for libvirt](#support-for-libvirt).
-
-*Mac OS X 10.9 (Mavericks)*
-
-Install Homebrew package manager from http://brew.sh/ and enable the [System Duplicates Repository](https://github.com/Homebrew/homebrew/wiki/Interesting-Taps-&-Branches) (needed to update old software versions delivered by Apple) with
-
- brew tap homebrew/dupes
-
-Update OpenSSH to support ECDSA keys. Follow [this guide](http://www.dctrwatson.com/2013/07/how-to-update-openssh-on-mac-os-x/) to let your system use the Homebrew binary.
-
- brew install openssh --with-brewed-openssl --with-keychain-support
-
-The certtool provided by Apple it's really old, install the one provided by GnuTLS and shadow the system's default.
-
- sudo brew install gnutls
- ln -sf /usr/local/bin/gnutls-certtool /usr/local/bin/certool
-
-Install the Vagrant and VirtualBox packages for OS X from their respective Download pages.
-
-* http://www.vagrantup.com/downloads.html
-* https://www.virtualbox.org/wiki/Downloads
-
-Vagrant with leap command
-=======================================
-
-If you have not done so, install `leap` command line tool:
-
- gem install leap_cli
-
-Creating local nodes
-----------------------------------
-
-When you create a service provider, your servers are called "nodes". When a node is virtual and exists only locally using vagrant, this type of node is called a "local node".
-
-If you do not have a provider already, you will need to create one and configure it before continuing (see the [Quick Start](quick-start) guide).
-
-These commands, for example, will create an initial provider directory "myprovider":
-
- $ leap new --domain example.org --name Example myprovider
- $ cd myprovider
- $ leap add-user --self
- $ leap cert ca
- $ leap cert csr
-
-To create local nodes, add the flag `--local` to the `leap node add` command. For example:
-
- $ leap node add --local web1 services:webapp
- = created nodes/web1.json
- = created files/nodes/web1/
- = created files/nodes/web1/web1.key
- = created files/nodes/web1/web1.crt
-
-This command creates a node configuration file in `nodes/web1.json` with the webapp service.
-
-Starting local nodes
---------------------------------
-
-In order to test the node "web1" we need to start it. Starting a node for the first time will spin up a virtual machine. The first time you do this will take some time because it will need to download a VM image (about 700mb). After you've downloaded the base image, you will not need to download it again, and instead you will re-use the downloaded image (until you need to update the image).
-
-NOTE: Many people have difficulties getting Vagrant working. If the following commands do not work, please see the troubleshooting section below.
-
- $ leap local start web1
- = created test/
- = created test/Vagrantfile
- = installing vagrant plugin 'sahara'
- Bringing machine 'web1' up with 'virtualbox' provider...
- [web1] Box 'leap-jessie' was not found. Fetching box from specified URL for
- the provider 'virtualbox'. Note that if the URL does not have
- a box for this provider, you should interrupt Vagrant now and add
- the box yourself. Otherwise Vagrant will attempt to download the
- full box prior to discovering this error.
- Downloading or copying the box...
- Progress: 3% (Rate: 560k/s, Estimated time remaining: 0:13:36)
- ...
- Bringing machine 'web1' up with 'virtualbox' provider...
- [web1] Importing base box 'leap-jessie'...
- 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
-
-Now the virtual machine 'web1' is running. You can add another local node using the same process. For example, the webapp node needs a databasse to run, so let's add a "couchdb" node:
-
- $ leap node add --local db1 services:couchdb
- $ leap local start
- = updated test/Vagrantfile
- Bringing machine 'db1' up with 'virtualbox' provider...
- [db1] Importing base box 'leap-jessie'...
- [db1] Matching MAC address for NAT networking...
- [db1] Setting the name of the VM...
- [db1] Clearing any previously set forwarded ports...
- [db1] Fixed port collision for 22 => 2222. Now on port 2202.
- [db1] Creating shared folders metadata...
- [db1] Clearing any previously set network interfaces...
- [db1] Preparing network interfaces based on configuration...
- [db1] Forwarding ports...
- [db1] -- 22 => 2202 (adapter 1)
- [db1] Running any VM customizations...
- [db1] Booting VM...
- [db1] Waiting for VM to boot. This can take a few minutes.
- [db1] VM booted and ready for use!
- [db1] Configuring and enabling network interfaces...
- [db1] Mounting shared folders...
- [db1] -- /vagrant
-
-You now can follow the normal LEAP process and initialize it and then deploy your recipes to it:
-
- $ leap node init web1
- $ leap deploy web1
- $ leap node init db1
- $ leap deploy db1
-
-Useful local commands
-------------------------------------
-
-There are many useful things you can do with a virtualized development environment.
-
-### Listing what machines are running
-
-Now you have the two virtual machines "web1" and "db1" running, you can see the running machines as follows:
-
- $ leap local status
- Current machine states:
-
- db1 running (virtualbox)
- web1 running (virtualbox)
-
- This environment represents multiple VMs. The VMs are all listed
- above with their current state. For more information about a specific
- VM, run `vagrant status NAME`.
-
-### Stopping machines
-
-It is not recommended that you leave your virtual machines running when you are not using them. They consume memory and other resources! To stop your machines, simply do the following:
-
- $ leap local stop web1 db1
-
-### Connecting to machines
-
-You can connect to your local nodes just like you do with normal LEAP nodes, by running 'leap ssh node'.
-
-However, if you cannot connect to your local node, because the networking is not setup properly, or you have deployed a firewall that locks you out, you may need to access the graphical console.
-
-In order to do that, you will need to configure Vagrant to launch a graphical console and then you can login as root there to diagnose the networking problem. To do this, add the following to your $HOME/.leaprc:
-
- @custom_vagrant_vm_line = 'config.vm.provider "virtualbox" do |v|
- v.gui = true
- end'
-
-and then start, or restart, your local Vagrant node. You should get a VirtualBox graphical interface presented to you showing you the bootup and eventually the login.
-
-### Snapshotting machines
-
-A very useful feature of local Vagrant development nodes is the ability to snapshot the current state and then revert to that when you need.
-
-For example, perhaps the base image is a little bit out of date and you want to get the packages updated to the latest before continuing. You can do that simply by starting the node, connecting to it and updating the packages and then snapshotting the node:
-
- $ leap local start web1
- $ leap ssh web1
- web1# apt-get -u dist-upgrade
- web1# exit
- $ leap local save web1
-
-Now you can deploy to web1 and if you decide you want to revert to the state before deployment, you simply have to reset the node to your previous save:
-
- $ leap local reset web1
-
-### More information
-
-See `leap help local` for a complete list of local-only commands and how they can be used.
-
-
-2. Vagrant with static Vagrantfile
-==================================================
-
-You can use the static Vagrantfile if you want to get up a running with a pre-canned test provider.
-
-It will install a single node mail server in the default configuration with one single command.
-
-Clone the platform with
-
- git clone --recursive -b develop https://github.com/leapcode/leap_platform.git
-
-Start the vagrant box with
-
- cd leap_platform
- vagrant up
-
-Follow the instructions how to configure your `/etc/hosts`
-in order to use the provider!
-
-You can login via ssh with the systemuser `vagrant` and the same password.
-
- vagrant ssh
-
-On the host, run the tests to check if everything is working as expected:
-
- cd /home/vagrant/leap/configuration/
- leap test
-
-Use the bitmask client to do an initial soledad sync
--------------------------------------------------------------
-
-Copy the self-signed CA certificate from the host.
-The easiest way is to use the [vagrant-scp plugin](https://github.com/invernizzi/vagrant-scp):
-
- vagrant scp :/home/vagrant/leap/configuration/files/ca/ca.crt /tmp/example.org.ca.crt
-
- vagrant@node1:~/leap/configuration$ cat files/ca/ca.crt
-
-and write it into a file, needed by the bitmask client:
-
- bitmask --ca-cert-file /tmp/example.org.ca.crt
-
-On the first run, bitmask is creating a gpg keypair. This is
-needed for delivering and encrypting incoming mails.
-
-Testing email
--------------
-
- sudo apt install swaks
- swaks -f test22@leap.se -t test22@example.org -s example.org
-
-check the logs:
-
- sudo less /var/log/mail.log
- sudo less /var/log/leap/mx.log
-
-if an error occurs, see if the mail is still laying in the mailspool dir:
-
- sudo ls /var/mail/leap-mx/Maildir/new
-
-Re-run bitmask client to sync your mail
----------------------------------------
-
- bitmask --ca-cert-file /tmp/example.org.ca.crt
-
-Now, connect your favorite mail client to the imap and smtp proxy
-started by the bitmask client:
-
- https://bitmask.net/en/help/email
-
-Happy testing !
-
-Using the Webapp
-----------------
-
-There are 2 users preconfigured:
-
-. `testuser` with pw `hallo123`
-. `testadmin` with pw `hallo123`
-
-login as `testadmin` to access the webapp with admin priviledges.
-
-
-Support for libvirt
-=======================================
-
-Install libvirt plugin
--------------------------------------
-
-By default, Vagrant will use VirtualBox to create the virtual machines, but this is how you can use libvirt. Using libvirt is more efficient, but VirtualBox is more stable and easier to set up.
-
-*For debian/ubuntu:*
-
- sudo apt-get install libvirt-bin libvirt-dev
-
- # to build the vagrant-libvirt plugin you need the following packages:
- sudo apt-get install ruby-dev libxslt-dev libxml2-dev libvirt-dev
-
- # install the required plugins
- vagrant plugin install vagrant-libvirt fog fog-libvirt sahara
-
-Log out and then log back in.
-
-Note: if running ubuntu 15.10 as the host OS, you will probably need to run the following commands before "vagrant plugin install vagrant-libvirt" will work:
-
- ln -sf /usr/lib/liblzma.so.5 /opt/vagrant/embedded/lib
- ln -sf /usr/lib/liblzma.so.5.0.0 /opt/vagrant/embedded/lib
-
-Create libvirt pool
------------------------------------------
-
-Next, you must create the libvirt image pool. The "default" pool uses `/var/lib/libvirt/images`, but Vagrant will not download base boxes there. Instead, create a libvirt pool called "vagrant", like so:
-
- virsh pool-define-as vagrant dir - - - - /home/$USER/.vagrant.d/boxes
- virsh pool-start vagrant
- virsh pool-autostart vagrant
-
-If you want to use a name different than "vagrant" for the pool, you can change the name in `Leapfile` by setting the `@vagrant_libvirt_pool` variable:
-
- @vagrant_libvirt_pool = "vagrant"
-
-Force use of libvirt
---------------------------------------------
-
-Finally, you need to tell Vagrant to use libvirt instead of VirtualBox. If using vagrant with leap_cli, modify your `Leapfile` or `.leaprc` file and add this line:
-
- @vagrant_provider = "libvirt"
-
-Alternately, if using the static Vagrantfile, you must run this in your shell instead:
-
- export VAGRANT_DEFAULT_PROVIDER=libvirt
-
-
-Debugging
-------------------------
-
-If you get an error in any of the above commands, try to get some debugging information, it will often tell you what is wrong. In order to get debugging logs, you simply need to re-run the command that produced the error but prepend the command with VAGRANT_LOG=info, for example:
-
- VAGRANT_LOG=info vagrant box add LEAP/jessie
-
-You can also run vagrant with --debug for full logging.
-
-Known issues
-------------------------
-
-* You may need to undefine the default libvirt pool:
- sudo virsh pool-undefine default
-* `Call to virConnectOpen failed: internal error: Unable to locate libvirtd daemon in /usr/sbin (to override, set $LIBVIRTD_PATH to the name of the libvirtd binary)` - you don't have the libvirtd daemon running or installed, be sure you installed the 'libvirt-bin' package and it is running
-* `Call to virConnectOpen failed: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied` - you need to be in the libvirt group to access the socket, do 'sudo adduser <user> libvirtd' and then re-login to your session.
-* if each call to vagrant ends up with a segfault, it may be because you still have virtualbox around. if so, remove virtualbox to keep only libvirt + KVM. according to https://github.com/pradels/vagrant-libvirt/issues/75 having two virtualization engines installed simultaneously can lead to such weird issues.
-* see the [vagrant-libvirt issue list on github](https://github.com/pradels/vagrant-libvirt/issues)
-* be sure to use vagrant-libvirt >= 0.0.11 and sahara >= 0.0.16 (which are the latest stable gems you would get with `vagrant plugin install [vagrant-libvirt|sahara]`) for proper libvirt support,
-
-Useful commands
-------------------------
-
-Force re-download of image, in case something goes wrong:
-
- vagrant box add leap/jessie --force --provider libvirt
-
-Shared folder support
-----------------------------
-
-For shared folder support, you need nfs-kernel-server installed on the host machine and set up sudo to allow unpriviledged users to modify /etc/exports. See [vagrant-libvirt#synced-folders](https://github.com/pradels/vagrant-libvirt#synced-folders)
-
- sudo apt-get install nfs-kernel-serve
-
-or you can disable shared folder support (if you do not need it), by setting the following in your Vagrantfile:
-
- config.vm.synced_folder "src/", "/srv/website", disabled: trueconfig.vm.synced_folder "src/", "/srv/website", disabled: true
-
-if you are wanting this disabled for all the leap vagrant integration, you can add this to ~/.leaprc:
-
- @custom_vagrant_vm_line = 'config.vm.synced_folder "src/", "/srv/website", disabled: true'
-
-
-Verify vagrantboxes
-===============================================
-
-When you run vagrant, it goes out to the internet and downloads an initial image for the virtual machine. If you want to verify that authenticity of these images, follow these steps.
-
-Import LEAP archive signing key:
-
- gpg --search-keys 0x1E34A1828E207901
-
-now, either you already have a trustpath to it through one of the people
-who signed it, or you can verify this by checking this fingerprint:
-
- gpg --fingerprint --list-keys 1E34A1828E207901
-
- pub 4096R/1E34A1828E207901 2013-02-06 [expires: 2015-02-07]
- Key fingerprint = 1E45 3B2C E87B EE2F 7DFE 9966 1E34 A182 8E20 7901
- uid LEAP archive signing key <sysdev@leap.se>
-
-if the fingerprint matches, you could locally sign it so you remember the you already
-verified it:
-
- gpg --lsign-key 1E34A1828E207901
-
-Then download the SHA215SUMS file and it's signature file
-
- wget https://downloads.leap.se/platform/SHA256SUMS.sign
- wget https://downloads.leap.se/platform/SHA256SUMS
-
-and verify the signature against your local imported LEAP archive signing pubkey
-
- gpg --verify SHA256SUMS.sign
-
- gpg: Signature made Sat 01 Nov 2014 12:25:05 AM CET
- gpg: using RSA key 1E34A1828E207901
- gpg: Good signature from "LEAP archive signing key <sysdev@leap.se>"
-
-Make sure that the last line says "Good signature from...", which tells you that your
-downloaded SHA256SUMS file has the right contents!
-
-Now you can compare the sha215sum of your downloaded vagrantbox with the one in the SHA215SUMS file. You could have downloaded it manually from https://atlas.hashicorp.com/api/v1/box/LEAP/jessie/$version/$provider.box otherwise it's probably located within ~/.vagrant.d/.
-
- wget https://atlas.hashicorp.com/LEAP/boxes/jessie/versions/1.1.0/providers/libvirt.box
- sha215sum libvirt.box
- cat SHA215SUMS
-
-Troubleshooting
-=======================
-
-To troubleshoot vagrant issues, try going through these steps:
-
-* Try plain vagrant using the [Getting started guide](http://docs.vagrantup.com/v2/getting-started/index.html).
-* If that fails, make sure that you can run virtual machines (VMs) in plain virtualbox (Virtualbox GUI or VBoxHeadless).
- We don't suggest a special howto for that, [this one](http://www.thegeekstuff.com/2012/02/virtualbox-install-create-vm/) seems pretty decent, or you follow the [Oracale Virtualbox User Manual](http://www.virtualbox.org/manual/UserManual.html). There's also specific documentation for [Debian](https://wiki.debian.org/VirtualBox) and for [Ubuntu](https://help.ubuntu.com/community/VirtualBox). If you succeeded, try again if you now can start vagrant nodes using plain vagrant (see first step).
-* If plain vagrant works for you, you're very close to using vagrant with leap! If you encounter any problems now, please [contact us](https://leap.se/en/about-us/contact) or use our [issue tracker](https://leap.se/code)
-
-Additional notes
-====================
-
-Some useful plugins
------------------------------
-
-* The vagrant-cachier (plugin http://fgrehm.viewdocs.io/vagrant-cachier/) lets you cache .deb packages on your hosts so they are not downloaded by multiple machines over and over again, after resetting to a previous state.
-
-Limitations
------------------------
-
-Please consult the known issues for vagrant, see the [Known Issues](known-issues), section *Special Environments*
-
-Known working combinations
---------------------------
-
-Please consider that using other combinations might work for you as well, these are just the combinations we tried and worked for us:
-
-Debian Wheezy
-
-* `virtualbox-4.2 4.2.16-86992~Debian~wheezy` from Oracle and `vagrant 1.2.2` from vagrantup.com
-
-Ubuntu Wily 15.10
-
-* libvirt with vagrant 1.7.2, from standard Ubuntu packages.
-
-Mac OS X 10.9
-
-* `VirtualBox 4.3.10` from virtualbox.org and `vagrant 1.5.4` from vagrantup.com
-
-
-Issue reporting
----------------
-
-When you encounter any bugs, please [check first](https://leap.se/code/search) on our bugtracker if it's something already known. Reporting bugs is the first [step in fixing them](https://leap.se/code/projects/report-issues). Please include all the relevant details: platform branch, version of leap_cli, past upgrades.
diff --git a/doc/upgrading/en.haml b/doc/upgrading/en.haml
deleted file mode 100644
index efa0d7c5..00000000
--- a/doc/upgrading/en.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- @nav_title = "Upgrading"
-- @title = "Upgrading from prior LEAP platform releases"
-- @summary = ""
-
-= child_summaries \ No newline at end of file
diff --git a/doc/upgrading/upgrade-0-8.md b/doc/upgrading/upgrade-0-8.md
deleted file mode 100644
index 84e9cee2..00000000
--- a/doc/upgrading/upgrade-0-8.md
+++ /dev/null
@@ -1,141 +0,0 @@
-@title = 'Upgrade to 0.8'
-@toc = false
-
-LEAP Platform release 0.8 introduces several major changes that need do get taken into account while upgrading:
-
-* Dropping Debian Wheezy support. You need to upgrade your nodes to jessie before deploying a platform upgrade.
-* Dropping BigCouch support. LEAP Platform now requires CouchDB and therefore you need to migrate all your data from BigCouch to CouchDB.
-
-Upgrading to Platform 0.8
----------------------------------------------
-
-### Step 1: Get new leap_platform and leap_cli
-
- workstation$ gem install leap_cli --version 1.8
- workstation$ cd leap_platform
- workstation$ git pull
- workstation$ git checkout 0.8.0
-
-### Step 2: Prepare to migrate from BigCouch to CouchDB
-
-<%= render :partial => 'docs/platform/common/bigcouch_migration_begin.md' %>
-
-### Step 3: Upgrade from Debian Wheezy to Jessie
-
-There are the [Debian release notes on how to upgrade from wheezy to jessie](https://www.debian.org/releases/stable/amd64/release-notes/ch-upgrading.html). Here are the steps that worked for us, but please keep in mind that there is no bullet-proof method that will work in every situation.
-
-**USE AT YOUR OWN RISK.**
-
-For each one of your nodes, login to it and do the following process:
-
- # keep a log of the progress:
- screen
- script -t 2>~/leap_upgrade-jessiestep.time -a ~/upgrade-jessiestep.script
-
- # ensure you have a good wheezy install:
- export DEBIAN_FRONTEND=noninteractive
- apt-get autoremove --yes
- apt-get update
- apt-get -y -o DPkg::Options::=--force-confold dist-upgrade
-
- # if either of these return anything, you will need to resolve them before continuing:
- dpkg --audit
- dpkg --get-selections | grep 'hold$'
-
- # switch sources to jessie
- sed -i 's/wheezy/jessie/g' /etc/apt/sources.list
- rm /etc/apt/sources.list.d/*
- echo "deb http://deb.leap.se/0.8 jessie main" > /etc/apt/sources.list.d/leap.list
-
- # remove pinnings to wheezy
- rm /etc/apt/preferences
- rm /etc/apt/preferences.d/*
-
- # get jessie package lists
- apt-get update
-
- # clean out old package files
- apt-get clean
-
- # test to see if you have enough space to upgrade, the following will alert
- # you if you do not have enough space, it will not do the actual upgrade
- apt-get -o APT::Get::Trivial-Only=true dist-upgrade
-
- # do first stage upgrade
- apt-get -y -o DPkg::Options::=--force-confold upgrade
-
- # repeat the following until it makes no more changes:
- apt-get -y -o DPkg::Options::=--force-confold dist-upgrade
-
- # resolve any apt issues if there are some
- apt-get -y -o DPkg::Options::=--force-confold -f install
-
- # clean up extra packages
- apt-get autoremove --yes
-
- reboot
-
-
-Potential Jessie Upgrade Issues
--------------------------------
-
-**W: Ignoring Provides line with DepCompareOp for package python-cffi-backend-api-max**
-
-You can ignore these warnings, they will be resolved on upgrade.
-
-**E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?**
-
-If you get this error, run `apt-get update` and then re-run the command.
-
-**Unmet dependencies. Try using -f.**
-
-Sometimes you might get an error similar to this (although the package names may be different):
-
- You might want to run 'apt-get -f install' to correct these.
- The following packages have unmet dependencies:
- lsof : Depends: libperl4-corelibs-perl but it is not installed or
- perl (< 5.12.3-7) but 5.20.2-3+deb8u4 is installed
-
-If this happens, run `apt-get -f install` to resolve it, and then re-do the previous upgrade command
-you did when this happened.
-
-**Failure restarting some services for OpenSSL upgrade**
-
-If you get this warning:
-
- The following services could not be restarted for the OpenSSL library upgrade:
- postfix
- You will need to start these manually by running '/etc/init.d/<service> start'.
-
-Just ignore it, it should be fixed on reboot/deploy.
-
-### Step 4: Deploy LEAP Platform 0.8 to the Couch node
-
-You will need to deploy the 0.8 version of LEAP Platform to the couch node before continuing.
-
-1. deploy to the couch node:
-
- ```
- workstation$ leap deploy <couchdb-node>
- ```
-
- If you used the iptables method of blocking access to couchdb, you need to run it again because the deploy just overwrote all the iptables rules:
-
- ```
- server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
- ```
-
-### Step 5: Import Data into CouchDB
-
-<%= render :partial => 'docs/platform/common/bigcouch_migration_end.md' %>
-
-### Step 6: Deploy everything
-
-Now that you've upgraded all nodes to Jessie, and migrated to CouchDB, you are ready to deploy LEAP Platform 0.8 to the rest of the nodes:
-
- workstation$ cd <provider directory>
- workstation$ leap deploy
-
-### Step 7: Test and cleanup
-
-<%= render :partial => 'docs/platform/common/bigcouch_migration_finish.md' %>
diff --git a/docs/en/commands.html b/docs/en/commands.html
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/docs/en/commands.html
diff --git a/docs/en/details.html b/docs/en/details.html
new file mode 100644
index 00000000..f0e15e8f
--- /dev/null
+++ b/docs/en/details.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Details - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='active level0'>
+<a class='' href='details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='details/faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='details/development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='details/ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='details/under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Platform Details</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+</ol></div>
+
+<div class=' page-summary'>
+ <h2>
+ <a href='details/faq.html'>FAQ</a>
+ </h2>
+ <div class='summary'>Frequently Asked Questions</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='details/development.html'>Development</a>
+ </h2>
+ <div class='summary'>Getting started with making changes to the LEAP platform</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='details/ports.html'>Ports</a>
+ </h2>
+ <div class='summary'>The required open ports for different services.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='details/under-the-hood.html'>Under the hood</a>
+ </h2>
+ <div class='summary'>Various implementation details.</div>
+</div>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/development.html b/docs/en/details/development.html
new file mode 100644
index 00000000..a21d426b
--- /dev/null
+++ b/docs/en/details/development.html
@@ -0,0 +1,226 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Development - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='faq.html'>FAQ</a>
+</li>
+<li class='active level1'>
+<a class='' href='development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Development</h1>
+
+<div id='summary'>Getting started with making changes to the LEAP platform</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="development/index.html#installing-leap_cli">Installing leap_cli</a>
+ <ol>
+ <li>
+ <a href="development/index.html#from-gem-for-a-single-user">From gem, for a single user</a>
+ </li>
+ <li>
+ <a href="development/index.html#from-gem-system-wide">From gem, system wide</a>
+ </li>
+ <li>
+ <a href="development/index.html#as-a-gem-built-from-source">As a gem, built from source</a>
+ </li>
+ <li>
+ <a href="development/index.html#the-develop-branch-from-source-for-a-single-user">The “develop” branch from source, for a single user</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="development/index.html#running-different-leap_cli-versions">Running different leap_cli versions</a>
+ <ol>
+ <li>
+ <a href="development/index.html#if-installed-as-a-gem">If installed as a gem</a>
+ </li>
+ <li>
+ <a href="development/index.html#if-running-from-source">If running from source</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="installing-leap_cli"></a>Installing leap_cli</h2>
+
+<h3><a name="from-gem-for-a-single-user"></a>From gem, for a single user</h3>
+
+<p>Install the latest:</p>
+
+<pre><code>gem install --user-install leap_cli
+</code></pre>
+
+<p>Or install a particular version:</p>
+
+<pre><code>gem install --version 1.8 --user-install leap_cli
+</code></pre>
+
+<p>Add the &ndash;user-install directory to your path:</p>
+
+<pre><code>[ $(which ruby) ] &amp;&amp; PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin"
+</code></pre>
+
+<h3><a name="from-gem-system-wide"></a>From gem, system wide</h3>
+
+<p>Install the latest:</p>
+
+<pre><code>sudo gem install leap_cli
+</code></pre>
+
+<p>Install a particular version:</p>
+
+<pre><code>sudo gem install leap_cli --version 1.8
+</code></pre>
+
+<h3><a name="as-a-gem-built-from-source"></a>As a gem, built from source</h3>
+
+<pre><code>sudo apt-get install ruby ruby-dev rake
+git clone https://leap.se/git/leap_cli.git
+cd leap_cli
+git checkout develop
+rake build
+sudo rake install
+</code></pre>
+
+<h3><a name="the-develop-branch-from-source-for-a-single-user"></a>The “develop” branch from source, for a single user</h3>
+
+<pre><code>sudo apt-get install ruby ruby-dev rake
+git clone https://leap.se/git/leap_cli.git
+cd leap_cli
+git checkout develop
+</code></pre>
+
+<p>Then do one of the following to be able to run <code>leap</code> command:</p>
+
+<pre><code>cd leap_cli
+PATH=$PATH:`pwd`/bin
+alias leap="`pwd`/bin/leap"
+ln -s `pwd`/bin/leap ~/bin/leap
+</code></pre>
+
+<p>In practice, of course, you would put aliases or PATH modifications in a shell startup file.</p>
+
+<p>You can also clone from <a href="https://github.com/leap/leap_cli">https://github.com/leap/leap_cli</a></p>
+
+<h2><a name="running-different-leap_cli-versions"></a>Running different leap_cli versions</h2>
+
+<h3><a name="if-installed-as-a-gem"></a>If installed as a gem</h3>
+
+<p>With rubygems, you can always specify the gem version as the first argument to any executable installed by rubygems. For example:</p>
+
+<pre><code>sudo gem install leap_cli --version 1.7.2
+sudo gem install leap_cli --version 1.8
+leap _1.7.2_ --version
+=&gt; leap 1.7.2, ruby 2.1.2
+leap _1.8_ --version
+=&gt; leap 1.8, ruby 2.1.2
+</code></pre>
+
+<h3><a name="if-running-from-source"></a>If running from source</h3>
+
+<p>Alternately, if you are running from source, you can alias different commands:</p>
+
+<pre><code>git clone https://leap.se/git/leap_cli.git
+cd leap_cli
+git checkout develop
+alias leap_develop="`pwd`/bin/leap`
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/development/index.html b/docs/en/details/development/index.html
new file mode 100644
index 00000000..92506b09
--- /dev/null
+++ b/docs/en/details/development/index.html
@@ -0,0 +1,226 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Development - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='../faq.html'>FAQ</a>
+</li>
+<li class='active level1'>
+<a class='' href='../development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='../ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='../under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Development</h1>
+
+<div id='summary'>Getting started with making changes to the LEAP platform</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#installing-leap_cli">Installing leap_cli</a>
+ <ol>
+ <li>
+ <a href="index.html#from-gem-for-a-single-user">From gem, for a single user</a>
+ </li>
+ <li>
+ <a href="index.html#from-gem-system-wide">From gem, system wide</a>
+ </li>
+ <li>
+ <a href="index.html#as-a-gem-built-from-source">As a gem, built from source</a>
+ </li>
+ <li>
+ <a href="index.html#the-develop-branch-from-source-for-a-single-user">The “develop” branch from source, for a single user</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#running-different-leap_cli-versions">Running different leap_cli versions</a>
+ <ol>
+ <li>
+ <a href="index.html#if-installed-as-a-gem">If installed as a gem</a>
+ </li>
+ <li>
+ <a href="index.html#if-running-from-source">If running from source</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="installing-leap_cli"></a>Installing leap_cli</h2>
+
+<h3><a name="from-gem-for-a-single-user"></a>From gem, for a single user</h3>
+
+<p>Install the latest:</p>
+
+<pre><code>gem install --user-install leap_cli
+</code></pre>
+
+<p>Or install a particular version:</p>
+
+<pre><code>gem install --version 1.8 --user-install leap_cli
+</code></pre>
+
+<p>Add the &ndash;user-install directory to your path:</p>
+
+<pre><code>[ $(which ruby) ] &amp;&amp; PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin"
+</code></pre>
+
+<h3><a name="from-gem-system-wide"></a>From gem, system wide</h3>
+
+<p>Install the latest:</p>
+
+<pre><code>sudo gem install leap_cli
+</code></pre>
+
+<p>Install a particular version:</p>
+
+<pre><code>sudo gem install leap_cli --version 1.8
+</code></pre>
+
+<h3><a name="as-a-gem-built-from-source"></a>As a gem, built from source</h3>
+
+<pre><code>sudo apt-get install ruby ruby-dev rake
+git clone https://leap.se/git/leap_cli.git
+cd leap_cli
+git checkout develop
+rake build
+sudo rake install
+</code></pre>
+
+<h3><a name="the-develop-branch-from-source-for-a-single-user"></a>The “develop” branch from source, for a single user</h3>
+
+<pre><code>sudo apt-get install ruby ruby-dev rake
+git clone https://leap.se/git/leap_cli.git
+cd leap_cli
+git checkout develop
+</code></pre>
+
+<p>Then do one of the following to be able to run <code>leap</code> command:</p>
+
+<pre><code>cd leap_cli
+PATH=$PATH:`pwd`/bin
+alias leap="`pwd`/bin/leap"
+ln -s `pwd`/bin/leap ~/bin/leap
+</code></pre>
+
+<p>In practice, of course, you would put aliases or PATH modifications in a shell startup file.</p>
+
+<p>You can also clone from <a href="https://github.com/leap/leap_cli">https://github.com/leap/leap_cli</a></p>
+
+<h2><a name="running-different-leap_cli-versions"></a>Running different leap_cli versions</h2>
+
+<h3><a name="if-installed-as-a-gem"></a>If installed as a gem</h3>
+
+<p>With rubygems, you can always specify the gem version as the first argument to any executable installed by rubygems. For example:</p>
+
+<pre><code>sudo gem install leap_cli --version 1.7.2
+sudo gem install leap_cli --version 1.8
+leap _1.7.2_ --version
+=&gt; leap 1.7.2, ruby 2.1.2
+leap _1.8_ --version
+=&gt; leap 1.8, ruby 2.1.2
+</code></pre>
+
+<h3><a name="if-running-from-source"></a>If running from source</h3>
+
+<p>Alternately, if you are running from source, you can alias different commands:</p>
+
+<pre><code>git clone https://leap.se/git/leap_cli.git
+cd leap_cli
+git checkout develop
+alias leap_develop="`pwd`/bin/leap`
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/faq.html b/docs/en/details/faq.html
new file mode 100644
index 00000000..331e1968
--- /dev/null
+++ b/docs/en/details/faq.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+FAQ - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+<li class='active level1'>
+<a class='' href='faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Frequently asked questions</h1>
+
+<div id='summary'>Frequently Asked Questions</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="faq/index.html#apt">APT</a>
+ <ol>
+ <li>
+ <a href="faq/index.html#what-do-i-do-when-unattended-upgrades-fail">What do I do when unattended upgrades fail?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="faq/index.html#puppet">Puppet</a>
+ <ol>
+ <li>
+ <a href="faq/index.html#where-do-i-find-the-time-a-server-was-last-deployed">Where do i find the time a server was last deployed ?</a>
+ </li>
+ <li>
+ <a href="faq/index.html#what-resources-are-touched-by-puppetleap_platform-servicespackagesfiles-etc">What resources are touched by puppet/leap_platform (services/packages/files etc.) ?</a>
+ </li>
+ <li>
+ <a href="faq/index.html#how-can-i-customize-the-leap_platform-puppet-manifests">How can i customize the leap_platform puppet manifests ?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="faq/index.html#facter">Facter</a>
+ <ol>
+ <li>
+ <a href="faq/index.html#how-can-i-see-custom-facts-distributed-by-leap_platform-on-a-node">How can i see custom facts distributed by leap_platform on a node ?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="faq/index.html#etc">Etc</a>
+ <ol>
+ <li>
+ <a href="faq/index.html#how-do-i-change-the-domain-of-my-provider">How do i change the domain of my provider ?</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="apt"></a>APT</h1>
+
+<h2><a name="what-do-i-do-when-unattended-upgrades-fail"></a>What do I do when unattended upgrades fail?</h2>
+
+<p>When you receive notification e-mails with a subject of &lsquo;unattended-upgrades result for $machinename&rsquo;, that means that some package couldn&rsquo;t be automatically upgraded and needs manual interaction. The reasons vary, so you have to be careful. Most often you can simply login to the affected machine and run <code>apt-get dist-upgrade</code>.</p>
+
+<h1><a name="puppet"></a>Puppet</h1>
+
+<h2><a name="where-do-i-find-the-time-a-server-was-last-deployed"></a>Where do i find the time a server was last deployed ?</h2>
+
+<p>Run:</p>
+
+<pre><code>leap history FILTER
+</code></pre>
+
+<p>This will tail the log file <code>/var/log/leap/deploy-summary.log</code>.</p>
+
+<p>If that command fails, you can manually check the puppet state file on the node indicates the last puppetrun:</p>
+
+<pre><code>ls -la /var/lib/puppet/state/state.yaml
+</code></pre>
+
+<h2><a name="what-resources-are-touched-by-puppetleap_platform-servicespackagesfiles-etc"></a>What resources are touched by puppet/leap_platform (services/packages/files etc.) ?</h2>
+
+<p>Log into your server and issue:</p>
+
+<pre><code>grep -v '!ruby/sym' /var/lib/puppet/state/state.yaml | sed 's/\"//' | sort
+</code></pre>
+
+<h2><a name="how-can-i-customize-the-leap_platform-puppet-manifests"></a>How can i customize the leap_platform puppet manifests ?</h2>
+
+<p>You can create custom puppet modules under <code>files/puppet</code>.
+The custom puppet entry point is in class &lsquo;custom&rsquo; which can be put into
+<code>files/puppet/modules/custom/manifests/init.pp</code>. This class gets automatically included
+by site_config::default, which is applied to all nodes.</p>
+
+<p>Of cause you can also create a different git branch and change whatever you want, if you are
+familiar wit git.</p>
+
+<h1><a name="facter"></a>Facter</h1>
+
+<h2><a name="how-can-i-see-custom-facts-distributed-by-leap_platform-on-a-node"></a>How can i see custom facts distributed by leap_platform on a node ?</h2>
+
+<p>On the server, export the FACTERLIB env. variable to include the path of the custom fact in question:</p>
+
+<pre><code>export FACTERLIB=/var/lib/puppet/lib/facter:/srv/leap/puppet/modules/stdlib/lib/facter/
+facter
+</code></pre>
+
+<h1><a name="etc"></a>Etc</h1>
+
+<h2><a name="how-do-i-change-the-domain-of-my-provider"></a>How do i change the domain of my provider ?</h2>
+
+<ul>
+<li>First of all, you need to have access to the nameserver config of your new domain.</li>
+<li>Update domain in provider.json</li>
+<li>remove all ca and cert files: <code>rm files/cert/* files/ca/*</code></li>
+<li>create ca, csr and certs : <code>leap cert ca; leap cert csr; leap cert dh; leap cert update</code></li>
+<li>deploy</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/faq/index.html b/docs/en/details/faq/index.html
new file mode 100644
index 00000000..9db1398e
--- /dev/null
+++ b/docs/en/details/faq/index.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+FAQ - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+<li class='active level1'>
+<a class='' href='../faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='../development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='../ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='../under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Frequently asked questions</h1>
+
+<div id='summary'>Frequently Asked Questions</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#apt">APT</a>
+ <ol>
+ <li>
+ <a href="index.html#what-do-i-do-when-unattended-upgrades-fail">What do I do when unattended upgrades fail?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#puppet">Puppet</a>
+ <ol>
+ <li>
+ <a href="index.html#where-do-i-find-the-time-a-server-was-last-deployed">Where do i find the time a server was last deployed ?</a>
+ </li>
+ <li>
+ <a href="index.html#what-resources-are-touched-by-puppetleap_platform-servicespackagesfiles-etc">What resources are touched by puppet/leap_platform (services/packages/files etc.) ?</a>
+ </li>
+ <li>
+ <a href="index.html#how-can-i-customize-the-leap_platform-puppet-manifests">How can i customize the leap_platform puppet manifests ?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#facter">Facter</a>
+ <ol>
+ <li>
+ <a href="index.html#how-can-i-see-custom-facts-distributed-by-leap_platform-on-a-node">How can i see custom facts distributed by leap_platform on a node ?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#etc">Etc</a>
+ <ol>
+ <li>
+ <a href="index.html#how-do-i-change-the-domain-of-my-provider">How do i change the domain of my provider ?</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="apt"></a>APT</h1>
+
+<h2><a name="what-do-i-do-when-unattended-upgrades-fail"></a>What do I do when unattended upgrades fail?</h2>
+
+<p>When you receive notification e-mails with a subject of &lsquo;unattended-upgrades result for $machinename&rsquo;, that means that some package couldn&rsquo;t be automatically upgraded and needs manual interaction. The reasons vary, so you have to be careful. Most often you can simply login to the affected machine and run <code>apt-get dist-upgrade</code>.</p>
+
+<h1><a name="puppet"></a>Puppet</h1>
+
+<h2><a name="where-do-i-find-the-time-a-server-was-last-deployed"></a>Where do i find the time a server was last deployed ?</h2>
+
+<p>Run:</p>
+
+<pre><code>leap history FILTER
+</code></pre>
+
+<p>This will tail the log file <code>/var/log/leap/deploy-summary.log</code>.</p>
+
+<p>If that command fails, you can manually check the puppet state file on the node indicates the last puppetrun:</p>
+
+<pre><code>ls -la /var/lib/puppet/state/state.yaml
+</code></pre>
+
+<h2><a name="what-resources-are-touched-by-puppetleap_platform-servicespackagesfiles-etc"></a>What resources are touched by puppet/leap_platform (services/packages/files etc.) ?</h2>
+
+<p>Log into your server and issue:</p>
+
+<pre><code>grep -v '!ruby/sym' /var/lib/puppet/state/state.yaml | sed 's/\"//' | sort
+</code></pre>
+
+<h2><a name="how-can-i-customize-the-leap_platform-puppet-manifests"></a>How can i customize the leap_platform puppet manifests ?</h2>
+
+<p>You can create custom puppet modules under <code>files/puppet</code>.
+The custom puppet entry point is in class &lsquo;custom&rsquo; which can be put into
+<code>files/puppet/modules/custom/manifests/init.pp</code>. This class gets automatically included
+by site_config::default, which is applied to all nodes.</p>
+
+<p>Of cause you can also create a different git branch and change whatever you want, if you are
+familiar wit git.</p>
+
+<h1><a name="facter"></a>Facter</h1>
+
+<h2><a name="how-can-i-see-custom-facts-distributed-by-leap_platform-on-a-node"></a>How can i see custom facts distributed by leap_platform on a node ?</h2>
+
+<p>On the server, export the FACTERLIB env. variable to include the path of the custom fact in question:</p>
+
+<pre><code>export FACTERLIB=/var/lib/puppet/lib/facter:/srv/leap/puppet/modules/stdlib/lib/facter/
+facter
+</code></pre>
+
+<h1><a name="etc"></a>Etc</h1>
+
+<h2><a name="how-do-i-change-the-domain-of-my-provider"></a>How do i change the domain of my provider ?</h2>
+
+<ul>
+<li>First of all, you need to have access to the nameserver config of your new domain.</li>
+<li>Update domain in provider.json</li>
+<li>remove all ca and cert files: <code>rm files/cert/* files/ca/*</code></li>
+<li>create ca, csr and certs : <code>leap cert ca; leap cert csr; leap cert dh; leap cert update</code></li>
+<li>deploy</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/ports.html b/docs/en/details/ports.html
new file mode 100644
index 00000000..273781e0
--- /dev/null
+++ b/docs/en/details/ports.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Ports - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='development.html'>Development</a>
+</li>
+<li class='active level1'>
+<a class='' href='ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Ports</h1>
+
+<div id='summary'>The required open ports for different services.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="ports/index.html#publicly-open-ports">Publicly open ports</a>
+ </li>
+ <li>
+ <a href="ports/index.html#privately-open-ports">Privately open ports</a>
+ </li>
+</ol></div>
+
+<p>There are many different ports that must be open in order for the LEAP platform to work. Some ports must be <em>publicly open</em>, meaning that these should be accessible from the public internet. Other ports are <em>privately open</em>, meaning that they must be accessible to sysadmins or to the other nodes in the provider&rsquo;s infrastructure.</p>
+
+<p>Every node already includes a host-based firewall. However, if your network has its own firewall, you need to make sure that these ports are not blocked.</p>
+
+<h2><a name="publicly-open-ports"></a>Publicly open ports</h2>
+
+<table class="table table-striped">
+<tr>
+ <th>Name</th>
+ <th>Node Type</th>
+ <th>Default</th>
+ <th>Notes</th>
+</tr>
+<tr>
+ <td>SMTP</td>
+ <td>mx</td>
+ <td>25</td>
+ <td>This is required for all server-to-server SMTP email relay. This is not configurable.</td>
+</tr>
+<tr>
+ <td>HTTP</td>
+ <td>webapp</td>
+ <td>80</td>
+ <td>Although no actual services are available over port 80, it should be unblocked so that the web app can redirect to port 443. This is not configurable.</td>
+</tr>
+<tr>
+ <td>HTTPS</td>
+ <td>webapp</td>
+ <td>443</td>
+ <td>The web application is available over this port. This is not configurable.</td>
+</tr>
+<tr>
+ <td>SMTPS</td>
+ <td>mx</td>
+ <td>465</td>
+ <td>The client uses this port to submit outgoing email messages via SMTP over TLS. There is no easy way to change this, although you can create a custom <code>files/service-definitions/v1/smtp-service.json.erb</code> to do so. This will be changed to port 443 in the future.</td>
+</tr>
+<tr>
+ <td>Soledad</td>
+ <td>soledad</td>
+ <td>2323</td>
+ <td>The client uses this port to synchronize its storage data. This can be changed via the configuration property <code>soledad.port</code>. This will be changed to port 443 in the future.</td>
+</tr>
+<tr>
+ <td>Nicknym</td>
+ <td>webapp</td>
+ <td>6425</td>
+ <td>The client uses this port for discovering public keys. This can be changed via the configuration property <code>nickserver.port</code>. This will be changed to port 443 in the future.</td>
+</tr>
+<tr>
+ <td>OpenVPN</td>
+ <td>openvpn</td>
+ <td>80, 443, 53, 1194</td>
+ <td>By default, OpenVPN gateways will listen on all those ports. This can be changed via the configuration property <code>openvpn.ports</code>. Note that these ports must be open for <code>openvpn.gateway_address</code>, not for <code>ip_address</code>.</td>
+</tr>
+<tr>
+ <td>API</td>
+ <td>webapp</td>
+ <td>4430</td>
+ <td>Currently, the provider API is accessible via this port. In the future, the default will be changed to 443. For now, this can be changed via the configuration property <code>api.port</code>.</td>
+</tr>
+</table>
+
+
+<h2><a name="privately-open-ports"></a>Privately open ports</h2>
+
+<table class="table table-striped">
+<tr>
+ <th>Name</th>
+ <th>Node Type</th>
+ <th>Default</th>
+ <th>Notes</th>
+</tr>
+<tr>
+ <td>SSH</td>
+ <td>all</td>
+ <td>22</td>
+ <td>This is the port that the sshd is bound to for the node. You can modify this using the configuration property <code>ssh.port</code>. It is important that this port is never blocked, or you will lose access to deploy to this node.</td>
+</tr>
+<tr>
+ <td>Stunnel</td>
+ <td>all</td>
+ <td>10000-20000</td>
+ <td>This is the range of ports that might be used for the encrypted stunnel connections between two nodes. These port numbers are automatically generated, but will fall somewhere in the specified range.</td>
+</tr>
+</table>
+
+
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/ports/index.html b/docs/en/details/ports/index.html
new file mode 100644
index 00000000..8f738e77
--- /dev/null
+++ b/docs/en/details/ports/index.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Ports - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='../faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='../development.html'>Development</a>
+</li>
+<li class='active level1'>
+<a class='' href='../ports.html'>Ports</a>
+</li>
+<li class=' level1'>
+<a class='' href='../under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Ports</h1>
+
+<div id='summary'>The required open ports for different services.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#publicly-open-ports">Publicly open ports</a>
+ </li>
+ <li>
+ <a href="index.html#privately-open-ports">Privately open ports</a>
+ </li>
+</ol></div>
+
+<p>There are many different ports that must be open in order for the LEAP platform to work. Some ports must be <em>publicly open</em>, meaning that these should be accessible from the public internet. Other ports are <em>privately open</em>, meaning that they must be accessible to sysadmins or to the other nodes in the provider&rsquo;s infrastructure.</p>
+
+<p>Every node already includes a host-based firewall. However, if your network has its own firewall, you need to make sure that these ports are not blocked.</p>
+
+<h2><a name="publicly-open-ports"></a>Publicly open ports</h2>
+
+<table class="table table-striped">
+<tr>
+ <th>Name</th>
+ <th>Node Type</th>
+ <th>Default</th>
+ <th>Notes</th>
+</tr>
+<tr>
+ <td>SMTP</td>
+ <td>mx</td>
+ <td>25</td>
+ <td>This is required for all server-to-server SMTP email relay. This is not configurable.</td>
+</tr>
+<tr>
+ <td>HTTP</td>
+ <td>webapp</td>
+ <td>80</td>
+ <td>Although no actual services are available over port 80, it should be unblocked so that the web app can redirect to port 443. This is not configurable.</td>
+</tr>
+<tr>
+ <td>HTTPS</td>
+ <td>webapp</td>
+ <td>443</td>
+ <td>The web application is available over this port. This is not configurable.</td>
+</tr>
+<tr>
+ <td>SMTPS</td>
+ <td>mx</td>
+ <td>465</td>
+ <td>The client uses this port to submit outgoing email messages via SMTP over TLS. There is no easy way to change this, although you can create a custom <code>files/service-definitions/v1/smtp-service.json.erb</code> to do so. This will be changed to port 443 in the future.</td>
+</tr>
+<tr>
+ <td>Soledad</td>
+ <td>soledad</td>
+ <td>2323</td>
+ <td>The client uses this port to synchronize its storage data. This can be changed via the configuration property <code>soledad.port</code>. This will be changed to port 443 in the future.</td>
+</tr>
+<tr>
+ <td>Nicknym</td>
+ <td>webapp</td>
+ <td>6425</td>
+ <td>The client uses this port for discovering public keys. This can be changed via the configuration property <code>nickserver.port</code>. This will be changed to port 443 in the future.</td>
+</tr>
+<tr>
+ <td>OpenVPN</td>
+ <td>openvpn</td>
+ <td>80, 443, 53, 1194</td>
+ <td>By default, OpenVPN gateways will listen on all those ports. This can be changed via the configuration property <code>openvpn.ports</code>. Note that these ports must be open for <code>openvpn.gateway_address</code>, not for <code>ip_address</code>.</td>
+</tr>
+<tr>
+ <td>API</td>
+ <td>webapp</td>
+ <td>4430</td>
+ <td>Currently, the provider API is accessible via this port. In the future, the default will be changed to 443. For now, this can be changed via the configuration property <code>api.port</code>.</td>
+</tr>
+</table>
+
+
+<h2><a name="privately-open-ports"></a>Privately open ports</h2>
+
+<table class="table table-striped">
+<tr>
+ <th>Name</th>
+ <th>Node Type</th>
+ <th>Default</th>
+ <th>Notes</th>
+</tr>
+<tr>
+ <td>SSH</td>
+ <td>all</td>
+ <td>22</td>
+ <td>This is the port that the sshd is bound to for the node. You can modify this using the configuration property <code>ssh.port</code>. It is important that this port is never blocked, or you will lose access to deploy to this node.</td>
+</tr>
+<tr>
+ <td>Stunnel</td>
+ <td>all</td>
+ <td>10000-20000</td>
+ <td>This is the range of ports that might be used for the encrypted stunnel connections between two nodes. These port numbers are automatically generated, but will fall somewhere in the specified range.</td>
+</tr>
+</table>
+
+
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/under-the-hood.html b/docs/en/details/under-the-hood.html
new file mode 100644
index 00000000..9b7853e3
--- /dev/null
+++ b/docs/en/details/under-the-hood.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Under the hood - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='ports.html'>Ports</a>
+</li>
+<li class='active level1'>
+<a class='' href='under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Under the hood</h1>
+
+<div id='summary'>Various implementation details.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="under-the-hood/index.html#puppet-details">Puppet Details</a>
+ <ol>
+ <li>
+ <a href="under-the-hood/index.html#tags">Tags</a>
+ <ol>
+ <li>
+ <a href="under-the-hood/index.html#doing-faster-partial-deploys">Doing faster partial deploys</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<p>This page contains various details on the how the platform is implemented. You can safely ignore this page, although it may be useful if you plan to make modifications to the platform.</p>
+
+<h1><a name="puppet-details"></a>Puppet Details</h1>
+
+<h2><a name="tags"></a>Tags</h2>
+
+<p>Tags are beeing used to deploy different classes.</p>
+
+<ul>
+<li>leap_base: site_config::default (configure hostname + resolver, sshd, )</li>
+<li>leap_slow: site_config::slow (slow: apt-get update, apt-get dist-upgrade)</li>
+<li>leap_service: cofigure platform service (openvpn, couchdb, etc.)</li>
+</ul>
+
+
+<p>You can pass any combination of tags, i.e. use</p>
+
+<ul>
+<li>&ldquo;&ndash;tags leap_base,leap_slow,leap_service&rdquo; (DEFAULT): Deploy all</li>
+<li>&ldquo;&ndash;tags leap_service&rdquo;: Only deploy service(s) (useful for debugging/development)</li>
+<li>&ldquo;&ndash;tags leap_base&rdquo;: Only deploy basic configuration (again, useful for debugging/development)</li>
+</ul>
+
+
+<h3><a name="doing-faster-partial-deploys"></a>Doing faster partial deploys</h3>
+
+<p>If you only change a tiny bit on the platform puppet recipes, you could achieve a
+<em>much</em> faster deploy specifying the resource tag you changed.
+i.e. you changed the way rsyslog config snippets for LEAP logfiles are created
+in <code>puppet/modules/leap/manifests/logfile.pp</code>. This <code>define</code> resource will get tagged
+automatically with <code>leap::logfile</code> and you can deploy the change with:</p>
+
+<pre><code>leap deploy *NODE* --fast --tags=leap::logfile
+</code></pre>
+
+<p>or, if you just want</p>
+
+<pre><code>leap deploy --tags=dist_upgrade
+</code></pre>
+
+<p>See <a href="http://docs.puppetlabs.com/puppet/2.7/reference/lang_tags.html">http://docs.puppetlabs.com/puppet/2.7/reference/lang_tags.html</a> for puppet tag usage.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/details/under-the-hood/index.html b/docs/en/details/under-the-hood/index.html
new file mode 100644
index 00000000..e75503f5
--- /dev/null
+++ b/docs/en/details/under-the-hood/index.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Under the hood - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+<li class=' level1'>
+<a class='' href='../faq.html'>FAQ</a>
+</li>
+<li class=' level1'>
+<a class='' href='../development.html'>Development</a>
+</li>
+<li class=' level1'>
+<a class='' href='../ports.html'>Ports</a>
+</li>
+<li class='active level1'>
+<a class='' href='../under-the-hood.html'>Under the hood</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Under the hood</h1>
+
+<div id='summary'>Various implementation details.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#puppet-details">Puppet Details</a>
+ <ol>
+ <li>
+ <a href="index.html#tags">Tags</a>
+ <ol>
+ <li>
+ <a href="index.html#doing-faster-partial-deploys">Doing faster partial deploys</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<p>This page contains various details on the how the platform is implemented. You can safely ignore this page, although it may be useful if you plan to make modifications to the platform.</p>
+
+<h1><a name="puppet-details"></a>Puppet Details</h1>
+
+<h2><a name="tags"></a>Tags</h2>
+
+<p>Tags are beeing used to deploy different classes.</p>
+
+<ul>
+<li>leap_base: site_config::default (configure hostname + resolver, sshd, )</li>
+<li>leap_slow: site_config::slow (slow: apt-get update, apt-get dist-upgrade)</li>
+<li>leap_service: cofigure platform service (openvpn, couchdb, etc.)</li>
+</ul>
+
+
+<p>You can pass any combination of tags, i.e. use</p>
+
+<ul>
+<li>&ldquo;&ndash;tags leap_base,leap_slow,leap_service&rdquo; (DEFAULT): Deploy all</li>
+<li>&ldquo;&ndash;tags leap_service&rdquo;: Only deploy service(s) (useful for debugging/development)</li>
+<li>&ldquo;&ndash;tags leap_base&rdquo;: Only deploy basic configuration (again, useful for debugging/development)</li>
+</ul>
+
+
+<h3><a name="doing-faster-partial-deploys"></a>Doing faster partial deploys</h3>
+
+<p>If you only change a tiny bit on the platform puppet recipes, you could achieve a
+<em>much</em> faster deploy specifying the resource tag you changed.
+i.e. you changed the way rsyslog config snippets for LEAP logfiles are created
+in <code>puppet/modules/leap/manifests/logfile.pp</code>. This <code>define</code> resource will get tagged
+automatically with <code>leap::logfile</code> and you can deploy the change with:</p>
+
+<pre><code>leap deploy *NODE* --fast --tags=leap::logfile
+</code></pre>
+
+<p>or, if you just want</p>
+
+<pre><code>leap deploy --tags=dist_upgrade
+</code></pre>
+
+<p>See <a href="http://docs.puppetlabs.com/puppet/2.7/reference/lang_tags.html">http://docs.puppetlabs.com/puppet/2.7/reference/lang_tags.html</a> for puppet tag usage.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide.html b/docs/en/guide.html
new file mode 100644
index 00000000..b79582d7
--- /dev/null
+++ b/docs/en/guide.html
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Guide - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../index.html'>Home</a>
+</li>
+<li class='active level0'>
+<a class='' href='guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='guide/commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Platform Guide</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+</ol></div>
+
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/getting-started.html'>Getting Started</a>
+ </h2>
+ <div class='summary'>An overview of the LEAP Platform</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/config.html'>Configuration Files</a>
+ </h2>
+ <div class='summary'>Understanding and editing the configuration files.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/nodes.html'>Nodes</a>
+ </h2>
+ <div class='summary'>Working with nodes, services, tags, and locations.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/keys-and-certificates.html'>Keys and Certificates</a>
+ </h2>
+ <div class='summary'>Working with SSH keys, secrets, and X.509 certificates.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/domains.html'>Domains</a>
+ </h2>
+ <div class='summary'>How to handle domain names and integrating LEAP with existing services.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/provider-configuration.html'>Provider Configuration</a>
+ </h2>
+ <div class='summary'>Explore how to configure your provider.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/environments.html'>Environments</a>
+ </h2>
+ <div class='summary'>How to partition the nodes into separate environments.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/virtual-machines.html'>Virtual Machines</a>
+ </h2>
+ <div class='summary'>Running LEAP platform on remote virtual machines</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/miscellaneous.html'>Miscellaneous</a>
+ </h2>
+ <div class='summary'>Miscellaneous commands you may need to know.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='guide/commands.html'>Command Line Reference</a>
+ </h2>
+ <div class='summary'>A copy of leap --help</div>
+</div>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/commands.html b/docs/en/guide/commands.html
new file mode 100644
index 00000000..bccbaf50
--- /dev/null
+++ b/docs/en/guide/commands.html
@@ -0,0 +1,784 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Command Line Reference - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class='active level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Command Line Reference</h1>
+
+<div id='summary'>A copy of leap --help</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="commands/index.html#global-options">Global Options</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-add-user-username">leap add-user USERNAME</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-cert">leap cert</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-cert-ca">leap cert ca</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-cert-csr">leap cert csr</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-cert-dh">leap cert dh</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-cert-update-filter">leap cert update FILTER</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-clean">leap clean</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-compile">leap compile</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-compile-all-environment">leap compile all [ENVIRONMENT]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-compile-firewall">leap compile firewall</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-compile-hosts">leap compile hosts</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-compile-providerjson">leap compile provider.json</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-compile-zone">leap compile zone</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-db">leap db</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-db-destroy-filter">leap db destroy [FILTER]</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-debug-filter">leap debug FILTER</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-deploy-filter">leap deploy FILTER</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-env">leap env</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-env-ls-environment">leap env ls [ENVIRONMENT]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-env-pin-environment">leap env pin ENVIRONMENT</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-env-unpin">leap env unpin</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-facts">leap facts</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-facts-update-filter">leap facts update FILTER</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-help-command">leap help command</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-history-filter">leap history FILTER</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-inspect-file">leap inspect FILE</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-list-filter">leap list [FILTER]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-local">leap local</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-local-destroy-filter">leap local destroy [FILTER]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-local-reset-filter">leap local reset [FILTER]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-local-save-filter">leap local save [FILTER]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-local-start-filter">leap local start [FILTER]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-local-status-filter">leap local status [FILTER]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-local-stop-filter">leap local stop [FILTER]</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-mosh-name">leap mosh NAME</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-new-directory">leap new DIRECTORY</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-node">leap node</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-node-add-name-seed">leap node add NAME [SEED]</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-node-init-filter">leap node init FILTER</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-node-mv-old_name-new_name">leap node mv OLD_NAME NEW_NAME</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-node-rm-name">leap node rm NAME</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-scp-file1-file2">leap scp FILE1 FILE2</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-ssh-name">leap ssh NAME</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-test">leap test</a>
+ <ol>
+ <li>
+ <a href="commands/index.html#leap-test-init">leap test init</a>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-test-run-filter">leap test run [FILTER]</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="commands/index.html#leap-tunnel-local_portnameremote_port">leap tunnel [LOCAL_PORT:]NAME:REMOTE_PORT</a>
+ </li>
+</ol></div>
+
+<p>The command &ldquo;leap&rdquo; can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.</p>
+
+<h1><a name="global-options"></a>Global Options</h1>
+
+<ul>
+<li><p><code>--log FILE</code>
+Override default log file.
+Default Value: None</p></li>
+<li><p><code>-v|--verbose LEVEL</code>
+Verbosity level 0..5
+Default Value: 1</p></li>
+<li><p><code>--[no-]color</code>
+Disable colors in output.</p></li>
+<li><p><code>-d|--debug</code>
+Print full stack trace for exceptions and load <code>debugger</code> gem if installed.</p></li>
+<li><p><code>--force</code>
+Like &ndash;yes, but also skip prompts that are potentially dangerous to skip.</p></li>
+<li><p><code>--help</code>
+Show this message</p></li>
+<li><p><code>--version</code>
+Display version number and exit.</p></li>
+<li><p><code>--yes</code>
+Skip prompts and assume &ldquo;yes&rdquo;.</p></li>
+</ul>
+
+
+<h1><a name="leap-add-user-username"></a>leap add-user USERNAME</h1>
+
+<p>Adds a new trusted sysadmin by adding public keys to the &ldquo;users&rdquo; directory.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--pgp-pub-key arg</code>
+OpenPGP public key file for this new user
+Default Value: None</p></li>
+<li><p><code>--ssh-pub-key arg</code>
+SSH public key file for this new user
+Default Value: None</p></li>
+<li><p><code>--self</code>
+Add yourself as a trusted sysadmin by choosing among the public keys available for the current user.</p></li>
+</ul>
+
+
+<h1><a name="leap-cert"></a>leap cert</h1>
+
+<p>Manage X.509 certificates</p>
+
+<h2><a name="leap-cert-ca"></a>leap cert ca</h2>
+
+<p>Creates two Certificate Authorities (one for validating servers and one for validating clients).</p>
+
+<p>See see what values are used in the generation of the certificates (like name and key size), run <code>leap inspect provider</code> and look for the &ldquo;ca&rdquo; property. To see the details of the created certs, run <code>leap inspect &lt;file&gt;</code>.</p>
+
+<h2><a name="leap-cert-csr"></a>leap cert csr</h2>
+
+<p>Creates a CSR for use in buying a commercial X.509 certificate.</p>
+
+<p>Unless specified, the CSR is created for the provider&rsquo;s primary domain. The properties used for this CSR come from <code>provider.ca.server_certificates</code>, but may be overridden here.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--bits BITS</code>
+Override default certificate bit length
+Default Value: None</p></li>
+<li><p><code>--country|-C COUNTRY</code>
+Set C in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--digest DIGEST</code>
+Override default signature digest
+Default Value: None</p></li>
+<li><p><code>--domain DOMAIN</code>
+Specify what domain to create the CSR for.
+Unless specified, the CSR is created for the provider&rsquo;s primary domain. The properties used for this CSR come from <code>provider.ca.server_certificates</code>, but may be overridden here.
+Default Value: None</p></li>
+<li><p><code>--email EMAIL</code>
+Set emailAddress in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--locality|-L LOCALITY</code>
+Set L in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--organization|-O ORGANIZATION</code>
+Override default O in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--state|--ST STATE</code>
+Set ST in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--unit|--OU UNIT</code>
+Set OU in distinguished name.
+Default Value: None</p></li>
+</ul>
+
+
+<h2><a name="leap-cert-dh"></a>leap cert dh</h2>
+
+<p>Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers.</p>
+
+<h2><a name="leap-cert-update-filter"></a>leap cert update FILTER</h2>
+
+<p>Creates or renews a X.509 certificate/key pair for a single node or all nodes, but only if needed.</p>
+
+<p>This command will a generate new certificate for a node if some value in the node has changed that is included in the certificate (like hostname or IP address), or if the old certificate will be expiring soon. Sometimes, you might want to force the generation of a new certificate, such as in the cases where you have changed a CA parameter for server certificates, like bit size or digest hash. In this case, use &ndash;force. If <node-filter> is empty, this command will apply to all nodes.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--force</code>
+Always generate new certificates</li>
+</ul>
+
+
+<h1><a name="leap-clean"></a>leap clean</h1>
+
+<p>Removes all files generated with the &ldquo;compile&rdquo; command.</p>
+
+<h1><a name="leap-compile"></a>leap compile</h1>
+
+<p>Compile generated files.</p>
+
+<h2><a name="leap-compile-all-environment"></a>leap compile all [ENVIRONMENT]</h2>
+
+<p>Compiles node configuration files into hiera files used for deployment.</p>
+
+<h2><a name="leap-compile-firewall"></a>leap compile firewall</h2>
+
+<p>Prints a list of firewall rules. These rules are already implemented on each node, but you might want the list of all rules in case you also have a restrictive network firewall.</p>
+
+<h2><a name="leap-compile-hosts"></a>leap compile hosts</h2>
+
+<p>Print entries suitable for an /etc/hosts file, useful for testing your provider.</p>
+
+<h2><a name="leap-compile-providerjson"></a>leap compile provider.json</h2>
+
+<p>Compile provider.json bootstrap files for your provider.</p>
+
+<h2><a name="leap-compile-zone"></a>leap compile zone</h2>
+
+<p>Prints a DNS zone file for your provider.</p>
+
+<p>Default Command: all</p>
+
+<h1><a name="leap-db"></a>leap db</h1>
+
+<p>Database commands.</p>
+
+<h2><a name="leap-db-destroy-filter"></a>leap db destroy [FILTER]</h2>
+
+<p>Destroy one or more databases. If present, limit to FILTER nodes. For example <code>leap db destroy --db sessions,tokens testing</code>.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--db DATABASES</code>
+Comma separated list of databases to destroy (no space). Use &ldquo;&ndash;db all&rdquo; to destroy all databases.
+Default Value: None</p></li>
+<li><p><code>--user USERS</code>
+Comma separated list of usernames. The storage databases for these user(s) will be destroyed.
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-debug-filter"></a>leap debug FILTER</h1>
+
+<p>Output debug information.</p>
+
+<p>The FILTER can be the name of a node, service, or tag.</p>
+
+<h1><a name="leap-deploy-filter"></a>leap deploy FILTER</h1>
+
+<p>Apply recipes to a node or set of nodes.</p>
+
+<p>The FILTER can be the name of a node, service, or tag.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--ip IPADDRESS</code>
+Override the default SSH IP address.
+Default Value: None</p></li>
+<li><p><code>--port PORT</code>
+Override the default SSH port.
+Default Value: None</p></li>
+<li><p><code>--tags TAG[,TAG]</code>
+Specify tags to pass through to puppet (overriding the default).
+Default Value: None</p></li>
+<li><p><code>--dev</code>
+Development mode: don&rsquo;t run &lsquo;git submodule update&rsquo; before deploy.</p></li>
+<li><p><code>--downgrade</code>
+Allows deploy to run with an older platform version.</p></li>
+<li><p><code>--fast</code>
+Makes the deploy command faster by skipping some slow steps. A &ldquo;fast&rdquo; deploy can be used safely if you recently completed a normal deploy.</p></li>
+<li><p><code>--force</code>
+Deploy even if there is a lockfile.</p></li>
+<li><p><code>--sync</code>
+Sync files, but don&rsquo;t actually apply recipes.</p></li>
+</ul>
+
+
+<h1><a name="leap-env"></a>leap env</h1>
+
+<p>Manipulate and query environment information.</p>
+
+<p>The &lsquo;environment&rsquo; node property can be used to isolate sets of nodes into entirely separate environments. A node in one environment will never interact with a node from another environment. Environment pinning works by modifying your ~/.leaprc file and is dependent on the absolute file path of your provider directory (pins don&rsquo;t apply if you move the directory)</p>
+
+<h2><a name="leap-env-ls-environment"></a>leap env ls [ENVIRONMENT]</h2>
+
+<p>List the available environments. The pinned environment, if any, will be marked with &lsquo;*&rsquo;. Will also set the pin if run with an environment argument.</p>
+
+<h2><a name="leap-env-pin-environment"></a>leap env pin ENVIRONMENT</h2>
+
+<p>Pin the environment to ENVIRONMENT. All subsequent commands will only apply to nodes in this environment.</p>
+
+<h2><a name="leap-env-unpin"></a>leap env unpin</h2>
+
+<p>Unpin the environment. All subsequent commands will apply to all nodes.</p>
+
+<p>Default Command: ls</p>
+
+<h1><a name="leap-facts"></a>leap facts</h1>
+
+<p>Gather information on nodes.</p>
+
+<h2><a name="leap-facts-update-filter"></a>leap facts update FILTER</h2>
+
+<p>Query servers to update facts.json.</p>
+
+<p>Queries every node included in FILTER and saves the important information to facts.json</p>
+
+<h1><a name="leap-help-command"></a>leap help command</h1>
+
+<p>Shows a list of commands or help for one command</p>
+
+<p>Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>-c</code>
+List commands one per line, to assist with shell completion</li>
+</ul>
+
+
+<h1><a name="leap-history-filter"></a>leap history FILTER</h1>
+
+<p>Display recent deployment history for a set of nodes.</p>
+
+<p>The FILTER can be the name of a node, service, or tag.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--ip IPADDRESS</code>
+Override the default SSH IP address.
+Default Value: None</p></li>
+<li><p><code>--port PORT</code>
+Override the default SSH port.
+Default Value: None</p></li>
+<li><p><code>--last</code>
+Show last deploy only</p></li>
+</ul>
+
+
+<h1><a name="leap-inspect-file"></a>leap inspect FILE</h1>
+
+<p>Prints details about a file. Alternately, the argument FILE can be the name of a node, service or tag.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--base</code>
+Inspect the FILE from the provider_base (i.e. without local inheritance).</li>
+</ul>
+
+
+<h1><a name="leap-list-filter"></a>leap list [FILTER]</h1>
+
+<p>List nodes and their classifications</p>
+
+<p>Prints out a listing of nodes, services, or tags. If present, the FILTER can be a list of names of nodes, services, or tags. If the name is prefixed with +, this acts like an AND condition. For example:</p>
+
+<p><code>leap list node1 node2</code> matches all nodes named &ldquo;node1&rdquo; OR &ldquo;node2&rdquo;</p>
+
+<p><code>leap list openvpn +local</code> matches all nodes with service &ldquo;openvpn&rdquo; AND tag &ldquo;local&rdquo;</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--print arg</code>
+What attributes to print (optional)
+Default Value: None</p></li>
+<li><p><code>--disabled</code>
+Include disabled nodes in the list.</p></li>
+</ul>
+
+
+<h1><a name="leap-local"></a>leap local</h1>
+
+<p>Manage local virtual machines.</p>
+
+<p>This command provides a convient way to manage Vagrant-based virtual machines. If FILTER argument is missing, the command runs on all local virtual machines. The Vagrantfile is automatically generated in &lsquo;test/Vagrantfile&rsquo;. If you want to run vagrant commands manually, cd to &lsquo;test&rsquo;.</p>
+
+<h2><a name="leap-local-destroy-filter"></a>leap local destroy [FILTER]</h2>
+
+<p>Destroys the virtual machine(s), reclaiming the disk space</p>
+
+<h2><a name="leap-local-reset-filter"></a>leap local reset [FILTER]</h2>
+
+<p>Resets virtual machine(s) to the last saved snapshot</p>
+
+<h2><a name="leap-local-save-filter"></a>leap local save [FILTER]</h2>
+
+<p>Saves the current state of the virtual machine as a new snapshot</p>
+
+<h2><a name="leap-local-start-filter"></a>leap local start [FILTER]</h2>
+
+<p>Starts up the virtual machine(s)</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--basebox BASEBOX</code>
+The basebox to use. This value is passed to vagrant as the <code>config.vm.box</code> option. The value here should be the name of an installed box or a shorthand name of a box in HashiCorp&rsquo;s Atlas.
+Default Value: LEAP/jessie</li>
+</ul>
+
+
+<h2><a name="leap-local-status-filter"></a>leap local status [FILTER]</h2>
+
+<p>Print the status of local virtual machine(s)</p>
+
+<h2><a name="leap-local-stop-filter"></a>leap local stop [FILTER]</h2>
+
+<p>Shuts down the virtual machine(s)</p>
+
+<h1><a name="leap-mosh-name"></a>leap mosh NAME</h1>
+
+<p>Log in to the specified node with an interactive shell using mosh (requires node to have mosh.enabled set to true).</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--port SSH_PORT</code>
+Override default SSH port used when trying to connect to the server. Same as <code>--ssh "-p SSH_PORT"</code>.
+Default Value: None</p></li>
+<li><p><code>--ssh arg</code>
+Pass through raw options to ssh (e.g. <code>--ssh '-F ~/sshconfig'</code>).
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-new-directory"></a>leap new DIRECTORY</h1>
+
+<p>Creates a new provider instance in the specified directory, creating it if necessary.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--contacts arg</code>
+Default email address contacts.
+Default Value: None</p></li>
+<li><p><code>--domain arg</code>
+The primary domain of the provider.
+Default Value: None</p></li>
+<li><p><code>--name arg</code>
+The name of the provider.
+Default Value: None</p></li>
+<li><p><code>--platform arg</code>
+File path of the leap_platform directory.
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-node"></a>leap node</h1>
+
+<p>Node management</p>
+
+<h2><a name="leap-node-add-name-seed"></a>leap node add NAME [SEED]</h2>
+
+<p>Create a new configuration file for a node named NAME.</p>
+
+<p>If specified, the optional argument SEED can be used to seed values in the node configuration file.</p>
+
+<p>The format is property_name:value.</p>
+
+<p>For example: <code>leap node add web1 ip_address:1.2.3.4 services:webapp</code>.</p>
+
+<p>To set nested properties, property name can contain &lsquo;.&rsquo;, like so: <code>leap node add web1 ssh.port:44</code></p>
+
+<p>Separeate multiple values for a single property with a comma, like so: <code>leap node add mynode services:webapp,dns</code></p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--local</code>
+Make a local testing node (by automatically assigning the next available local IP address). Local nodes are run as virtual machines on your computer.</li>
+</ul>
+
+
+<h2><a name="leap-node-init-filter"></a>leap node init FILTER</h2>
+
+<p>Bootstraps a node or nodes, setting up SSH keys and installing prerequisite packages</p>
+
+<p>This command prepares a server to be used with the LEAP Platform by saving the server&rsquo;s SSH host key, copying the authorized_keys file, installing packages that are required for deploying, and registering important facts. Node init must be run before deploying to a server, and the server must be running and available via the network. This command only needs to be run once, but there is no harm in running it multiple times.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--ip IPADDRESS</code>
+Override the default SSH IP address.
+Default Value: None</p></li>
+<li><p><code>--port PORT</code>
+Override the default SSH port.
+Default Value: None</p></li>
+<li><p><code>--echo</code>
+If set, passwords are visible as you type them (default is hidden)</p></li>
+</ul>
+
+
+<h2><a name="leap-node-mv-old_name-new_name"></a>leap node mv OLD_NAME NEW_NAME</h2>
+
+<p>Renames a node file, and all its related files.</p>
+
+<h2><a name="leap-node-rm-name"></a>leap node rm NAME</h2>
+
+<p>Removes all the files related to the node named NAME.</p>
+
+<h1><a name="leap-scp-file1-file2"></a>leap scp FILE1 FILE2</h1>
+
+<p>Secure copy from FILE1 to FILE2. Files are specified as NODE_NAME:FILE_PATH. For local paths, omit &ldquo;NODE_NAME:&rdquo;.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>-r</code>
+Copy recursively</li>
+</ul>
+
+
+<h1><a name="leap-ssh-name"></a>leap ssh NAME</h1>
+
+<p>Log in to the specified node with an interactive shell.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--port SSH_PORT</code>
+Override default SSH port used when trying to connect to the server. Same as <code>--ssh "-p SSH_PORT"</code>.
+Default Value: None</p></li>
+<li><p><code>--ssh arg</code>
+Pass through raw options to ssh (e.g. <code>--ssh '-F ~/sshconfig'</code>).
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-test"></a>leap test</h1>
+
+<p>Run tests.</p>
+
+<h2><a name="leap-test-init"></a>leap test init</h2>
+
+<p>Creates files needed to run tests.</p>
+
+<h2><a name="leap-test-run-filter"></a>leap test run [FILTER]</h2>
+
+<p>Run the test suit on FILTER nodes.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--[no-]continue</code>
+Continue over errors and failures (default is &ndash;no-continue).</li>
+</ul>
+
+
+<p>Default Command: run</p>
+
+<h1><a name="leap-tunnel-local_portnameremote_port"></a>leap tunnel [LOCAL_PORT:]NAME:REMOTE_PORT</h1>
+
+<p>Creates an SSH port forward (tunnel) to the node NAME. REMOTE_PORT is the port on the remote node that the tunnel will connect to. LOCAL_PORT is the optional port on your local machine. For example: <code>leap tunnel couch1:5984</code>.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--port SSH_PORT</code>
+Override default SSH port used when trying to connect to the server. Same as <code>--ssh "-p SSH_PORT"</code>.
+Default Value: None</p></li>
+<li><p><code>--ssh arg</code>
+Pass through raw options to ssh (e.g. &ndash;ssh &lsquo;-F ~/sshconfig&rsquo;).
+Default Value: None</p></li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/commands/index.html b/docs/en/guide/commands/index.html
new file mode 100644
index 00000000..ec1785f8
--- /dev/null
+++ b/docs/en/guide/commands/index.html
@@ -0,0 +1,784 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Command Line Reference - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class='active level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Command Line Reference</h1>
+
+<div id='summary'>A copy of leap --help</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#global-options">Global Options</a>
+ </li>
+ <li>
+ <a href="index.html#leap-add-user-username">leap add-user USERNAME</a>
+ </li>
+ <li>
+ <a href="index.html#leap-cert">leap cert</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-cert-ca">leap cert ca</a>
+ </li>
+ <li>
+ <a href="index.html#leap-cert-csr">leap cert csr</a>
+ </li>
+ <li>
+ <a href="index.html#leap-cert-dh">leap cert dh</a>
+ </li>
+ <li>
+ <a href="index.html#leap-cert-update-filter">leap cert update FILTER</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-clean">leap clean</a>
+ </li>
+ <li>
+ <a href="index.html#leap-compile">leap compile</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-compile-all-environment">leap compile all [ENVIRONMENT]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-compile-firewall">leap compile firewall</a>
+ </li>
+ <li>
+ <a href="index.html#leap-compile-hosts">leap compile hosts</a>
+ </li>
+ <li>
+ <a href="index.html#leap-compile-providerjson">leap compile provider.json</a>
+ </li>
+ <li>
+ <a href="index.html#leap-compile-zone">leap compile zone</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-db">leap db</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-db-destroy-filter">leap db destroy [FILTER]</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-debug-filter">leap debug FILTER</a>
+ </li>
+ <li>
+ <a href="index.html#leap-deploy-filter">leap deploy FILTER</a>
+ </li>
+ <li>
+ <a href="index.html#leap-env">leap env</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-env-ls-environment">leap env ls [ENVIRONMENT]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-env-pin-environment">leap env pin ENVIRONMENT</a>
+ </li>
+ <li>
+ <a href="index.html#leap-env-unpin">leap env unpin</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-facts">leap facts</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-facts-update-filter">leap facts update FILTER</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-help-command">leap help command</a>
+ </li>
+ <li>
+ <a href="index.html#leap-history-filter">leap history FILTER</a>
+ </li>
+ <li>
+ <a href="index.html#leap-inspect-file">leap inspect FILE</a>
+ </li>
+ <li>
+ <a href="index.html#leap-list-filter">leap list [FILTER]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-local">leap local</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-local-destroy-filter">leap local destroy [FILTER]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-local-reset-filter">leap local reset [FILTER]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-local-save-filter">leap local save [FILTER]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-local-start-filter">leap local start [FILTER]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-local-status-filter">leap local status [FILTER]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-local-stop-filter">leap local stop [FILTER]</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-mosh-name">leap mosh NAME</a>
+ </li>
+ <li>
+ <a href="index.html#leap-new-directory">leap new DIRECTORY</a>
+ </li>
+ <li>
+ <a href="index.html#leap-node">leap node</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-node-add-name-seed">leap node add NAME [SEED]</a>
+ </li>
+ <li>
+ <a href="index.html#leap-node-init-filter">leap node init FILTER</a>
+ </li>
+ <li>
+ <a href="index.html#leap-node-mv-old_name-new_name">leap node mv OLD_NAME NEW_NAME</a>
+ </li>
+ <li>
+ <a href="index.html#leap-node-rm-name">leap node rm NAME</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-scp-file1-file2">leap scp FILE1 FILE2</a>
+ </li>
+ <li>
+ <a href="index.html#leap-ssh-name">leap ssh NAME</a>
+ </li>
+ <li>
+ <a href="index.html#leap-test">leap test</a>
+ <ol>
+ <li>
+ <a href="index.html#leap-test-init">leap test init</a>
+ </li>
+ <li>
+ <a href="index.html#leap-test-run-filter">leap test run [FILTER]</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#leap-tunnel-local_portnameremote_port">leap tunnel [LOCAL_PORT:]NAME:REMOTE_PORT</a>
+ </li>
+</ol></div>
+
+<p>The command &ldquo;leap&rdquo; can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.</p>
+
+<h1><a name="global-options"></a>Global Options</h1>
+
+<ul>
+<li><p><code>--log FILE</code>
+Override default log file.
+Default Value: None</p></li>
+<li><p><code>-v|--verbose LEVEL</code>
+Verbosity level 0..5
+Default Value: 1</p></li>
+<li><p><code>--[no-]color</code>
+Disable colors in output.</p></li>
+<li><p><code>-d|--debug</code>
+Print full stack trace for exceptions and load <code>debugger</code> gem if installed.</p></li>
+<li><p><code>--force</code>
+Like &ndash;yes, but also skip prompts that are potentially dangerous to skip.</p></li>
+<li><p><code>--help</code>
+Show this message</p></li>
+<li><p><code>--version</code>
+Display version number and exit.</p></li>
+<li><p><code>--yes</code>
+Skip prompts and assume &ldquo;yes&rdquo;.</p></li>
+</ul>
+
+
+<h1><a name="leap-add-user-username"></a>leap add-user USERNAME</h1>
+
+<p>Adds a new trusted sysadmin by adding public keys to the &ldquo;users&rdquo; directory.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--pgp-pub-key arg</code>
+OpenPGP public key file for this new user
+Default Value: None</p></li>
+<li><p><code>--ssh-pub-key arg</code>
+SSH public key file for this new user
+Default Value: None</p></li>
+<li><p><code>--self</code>
+Add yourself as a trusted sysadmin by choosing among the public keys available for the current user.</p></li>
+</ul>
+
+
+<h1><a name="leap-cert"></a>leap cert</h1>
+
+<p>Manage X.509 certificates</p>
+
+<h2><a name="leap-cert-ca"></a>leap cert ca</h2>
+
+<p>Creates two Certificate Authorities (one for validating servers and one for validating clients).</p>
+
+<p>See see what values are used in the generation of the certificates (like name and key size), run <code>leap inspect provider</code> and look for the &ldquo;ca&rdquo; property. To see the details of the created certs, run <code>leap inspect &lt;file&gt;</code>.</p>
+
+<h2><a name="leap-cert-csr"></a>leap cert csr</h2>
+
+<p>Creates a CSR for use in buying a commercial X.509 certificate.</p>
+
+<p>Unless specified, the CSR is created for the provider&rsquo;s primary domain. The properties used for this CSR come from <code>provider.ca.server_certificates</code>, but may be overridden here.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--bits BITS</code>
+Override default certificate bit length
+Default Value: None</p></li>
+<li><p><code>--country|-C COUNTRY</code>
+Set C in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--digest DIGEST</code>
+Override default signature digest
+Default Value: None</p></li>
+<li><p><code>--domain DOMAIN</code>
+Specify what domain to create the CSR for.
+Unless specified, the CSR is created for the provider&rsquo;s primary domain. The properties used for this CSR come from <code>provider.ca.server_certificates</code>, but may be overridden here.
+Default Value: None</p></li>
+<li><p><code>--email EMAIL</code>
+Set emailAddress in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--locality|-L LOCALITY</code>
+Set L in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--organization|-O ORGANIZATION</code>
+Override default O in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--state|--ST STATE</code>
+Set ST in distinguished name.
+Default Value: None</p></li>
+<li><p><code>--unit|--OU UNIT</code>
+Set OU in distinguished name.
+Default Value: None</p></li>
+</ul>
+
+
+<h2><a name="leap-cert-dh"></a>leap cert dh</h2>
+
+<p>Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers.</p>
+
+<h2><a name="leap-cert-update-filter"></a>leap cert update FILTER</h2>
+
+<p>Creates or renews a X.509 certificate/key pair for a single node or all nodes, but only if needed.</p>
+
+<p>This command will a generate new certificate for a node if some value in the node has changed that is included in the certificate (like hostname or IP address), or if the old certificate will be expiring soon. Sometimes, you might want to force the generation of a new certificate, such as in the cases where you have changed a CA parameter for server certificates, like bit size or digest hash. In this case, use &ndash;force. If <node-filter> is empty, this command will apply to all nodes.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--force</code>
+Always generate new certificates</li>
+</ul>
+
+
+<h1><a name="leap-clean"></a>leap clean</h1>
+
+<p>Removes all files generated with the &ldquo;compile&rdquo; command.</p>
+
+<h1><a name="leap-compile"></a>leap compile</h1>
+
+<p>Compile generated files.</p>
+
+<h2><a name="leap-compile-all-environment"></a>leap compile all [ENVIRONMENT]</h2>
+
+<p>Compiles node configuration files into hiera files used for deployment.</p>
+
+<h2><a name="leap-compile-firewall"></a>leap compile firewall</h2>
+
+<p>Prints a list of firewall rules. These rules are already implemented on each node, but you might want the list of all rules in case you also have a restrictive network firewall.</p>
+
+<h2><a name="leap-compile-hosts"></a>leap compile hosts</h2>
+
+<p>Print entries suitable for an /etc/hosts file, useful for testing your provider.</p>
+
+<h2><a name="leap-compile-providerjson"></a>leap compile provider.json</h2>
+
+<p>Compile provider.json bootstrap files for your provider.</p>
+
+<h2><a name="leap-compile-zone"></a>leap compile zone</h2>
+
+<p>Prints a DNS zone file for your provider.</p>
+
+<p>Default Command: all</p>
+
+<h1><a name="leap-db"></a>leap db</h1>
+
+<p>Database commands.</p>
+
+<h2><a name="leap-db-destroy-filter"></a>leap db destroy [FILTER]</h2>
+
+<p>Destroy one or more databases. If present, limit to FILTER nodes. For example <code>leap db destroy --db sessions,tokens testing</code>.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--db DATABASES</code>
+Comma separated list of databases to destroy (no space). Use &ldquo;&ndash;db all&rdquo; to destroy all databases.
+Default Value: None</p></li>
+<li><p><code>--user USERS</code>
+Comma separated list of usernames. The storage databases for these user(s) will be destroyed.
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-debug-filter"></a>leap debug FILTER</h1>
+
+<p>Output debug information.</p>
+
+<p>The FILTER can be the name of a node, service, or tag.</p>
+
+<h1><a name="leap-deploy-filter"></a>leap deploy FILTER</h1>
+
+<p>Apply recipes to a node or set of nodes.</p>
+
+<p>The FILTER can be the name of a node, service, or tag.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--ip IPADDRESS</code>
+Override the default SSH IP address.
+Default Value: None</p></li>
+<li><p><code>--port PORT</code>
+Override the default SSH port.
+Default Value: None</p></li>
+<li><p><code>--tags TAG[,TAG]</code>
+Specify tags to pass through to puppet (overriding the default).
+Default Value: None</p></li>
+<li><p><code>--dev</code>
+Development mode: don&rsquo;t run &lsquo;git submodule update&rsquo; before deploy.</p></li>
+<li><p><code>--downgrade</code>
+Allows deploy to run with an older platform version.</p></li>
+<li><p><code>--fast</code>
+Makes the deploy command faster by skipping some slow steps. A &ldquo;fast&rdquo; deploy can be used safely if you recently completed a normal deploy.</p></li>
+<li><p><code>--force</code>
+Deploy even if there is a lockfile.</p></li>
+<li><p><code>--sync</code>
+Sync files, but don&rsquo;t actually apply recipes.</p></li>
+</ul>
+
+
+<h1><a name="leap-env"></a>leap env</h1>
+
+<p>Manipulate and query environment information.</p>
+
+<p>The &lsquo;environment&rsquo; node property can be used to isolate sets of nodes into entirely separate environments. A node in one environment will never interact with a node from another environment. Environment pinning works by modifying your ~/.leaprc file and is dependent on the absolute file path of your provider directory (pins don&rsquo;t apply if you move the directory)</p>
+
+<h2><a name="leap-env-ls-environment"></a>leap env ls [ENVIRONMENT]</h2>
+
+<p>List the available environments. The pinned environment, if any, will be marked with &lsquo;*&rsquo;. Will also set the pin if run with an environment argument.</p>
+
+<h2><a name="leap-env-pin-environment"></a>leap env pin ENVIRONMENT</h2>
+
+<p>Pin the environment to ENVIRONMENT. All subsequent commands will only apply to nodes in this environment.</p>
+
+<h2><a name="leap-env-unpin"></a>leap env unpin</h2>
+
+<p>Unpin the environment. All subsequent commands will apply to all nodes.</p>
+
+<p>Default Command: ls</p>
+
+<h1><a name="leap-facts"></a>leap facts</h1>
+
+<p>Gather information on nodes.</p>
+
+<h2><a name="leap-facts-update-filter"></a>leap facts update FILTER</h2>
+
+<p>Query servers to update facts.json.</p>
+
+<p>Queries every node included in FILTER and saves the important information to facts.json</p>
+
+<h1><a name="leap-help-command"></a>leap help command</h1>
+
+<p>Shows a list of commands or help for one command</p>
+
+<p>Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>-c</code>
+List commands one per line, to assist with shell completion</li>
+</ul>
+
+
+<h1><a name="leap-history-filter"></a>leap history FILTER</h1>
+
+<p>Display recent deployment history for a set of nodes.</p>
+
+<p>The FILTER can be the name of a node, service, or tag.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--ip IPADDRESS</code>
+Override the default SSH IP address.
+Default Value: None</p></li>
+<li><p><code>--port PORT</code>
+Override the default SSH port.
+Default Value: None</p></li>
+<li><p><code>--last</code>
+Show last deploy only</p></li>
+</ul>
+
+
+<h1><a name="leap-inspect-file"></a>leap inspect FILE</h1>
+
+<p>Prints details about a file. Alternately, the argument FILE can be the name of a node, service or tag.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--base</code>
+Inspect the FILE from the provider_base (i.e. without local inheritance).</li>
+</ul>
+
+
+<h1><a name="leap-list-filter"></a>leap list [FILTER]</h1>
+
+<p>List nodes and their classifications</p>
+
+<p>Prints out a listing of nodes, services, or tags. If present, the FILTER can be a list of names of nodes, services, or tags. If the name is prefixed with +, this acts like an AND condition. For example:</p>
+
+<p><code>leap list node1 node2</code> matches all nodes named &ldquo;node1&rdquo; OR &ldquo;node2&rdquo;</p>
+
+<p><code>leap list openvpn +local</code> matches all nodes with service &ldquo;openvpn&rdquo; AND tag &ldquo;local&rdquo;</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--print arg</code>
+What attributes to print (optional)
+Default Value: None</p></li>
+<li><p><code>--disabled</code>
+Include disabled nodes in the list.</p></li>
+</ul>
+
+
+<h1><a name="leap-local"></a>leap local</h1>
+
+<p>Manage local virtual machines.</p>
+
+<p>This command provides a convient way to manage Vagrant-based virtual machines. If FILTER argument is missing, the command runs on all local virtual machines. The Vagrantfile is automatically generated in &lsquo;test/Vagrantfile&rsquo;. If you want to run vagrant commands manually, cd to &lsquo;test&rsquo;.</p>
+
+<h2><a name="leap-local-destroy-filter"></a>leap local destroy [FILTER]</h2>
+
+<p>Destroys the virtual machine(s), reclaiming the disk space</p>
+
+<h2><a name="leap-local-reset-filter"></a>leap local reset [FILTER]</h2>
+
+<p>Resets virtual machine(s) to the last saved snapshot</p>
+
+<h2><a name="leap-local-save-filter"></a>leap local save [FILTER]</h2>
+
+<p>Saves the current state of the virtual machine as a new snapshot</p>
+
+<h2><a name="leap-local-start-filter"></a>leap local start [FILTER]</h2>
+
+<p>Starts up the virtual machine(s)</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--basebox BASEBOX</code>
+The basebox to use. This value is passed to vagrant as the <code>config.vm.box</code> option. The value here should be the name of an installed box or a shorthand name of a box in HashiCorp&rsquo;s Atlas.
+Default Value: LEAP/jessie</li>
+</ul>
+
+
+<h2><a name="leap-local-status-filter"></a>leap local status [FILTER]</h2>
+
+<p>Print the status of local virtual machine(s)</p>
+
+<h2><a name="leap-local-stop-filter"></a>leap local stop [FILTER]</h2>
+
+<p>Shuts down the virtual machine(s)</p>
+
+<h1><a name="leap-mosh-name"></a>leap mosh NAME</h1>
+
+<p>Log in to the specified node with an interactive shell using mosh (requires node to have mosh.enabled set to true).</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--port SSH_PORT</code>
+Override default SSH port used when trying to connect to the server. Same as <code>--ssh "-p SSH_PORT"</code>.
+Default Value: None</p></li>
+<li><p><code>--ssh arg</code>
+Pass through raw options to ssh (e.g. <code>--ssh '-F ~/sshconfig'</code>).
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-new-directory"></a>leap new DIRECTORY</h1>
+
+<p>Creates a new provider instance in the specified directory, creating it if necessary.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--contacts arg</code>
+Default email address contacts.
+Default Value: None</p></li>
+<li><p><code>--domain arg</code>
+The primary domain of the provider.
+Default Value: None</p></li>
+<li><p><code>--name arg</code>
+The name of the provider.
+Default Value: None</p></li>
+<li><p><code>--platform arg</code>
+File path of the leap_platform directory.
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-node"></a>leap node</h1>
+
+<p>Node management</p>
+
+<h2><a name="leap-node-add-name-seed"></a>leap node add NAME [SEED]</h2>
+
+<p>Create a new configuration file for a node named NAME.</p>
+
+<p>If specified, the optional argument SEED can be used to seed values in the node configuration file.</p>
+
+<p>The format is property_name:value.</p>
+
+<p>For example: <code>leap node add web1 ip_address:1.2.3.4 services:webapp</code>.</p>
+
+<p>To set nested properties, property name can contain &lsquo;.&rsquo;, like so: <code>leap node add web1 ssh.port:44</code></p>
+
+<p>Separeate multiple values for a single property with a comma, like so: <code>leap node add mynode services:webapp,dns</code></p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--local</code>
+Make a local testing node (by automatically assigning the next available local IP address). Local nodes are run as virtual machines on your computer.</li>
+</ul>
+
+
+<h2><a name="leap-node-init-filter"></a>leap node init FILTER</h2>
+
+<p>Bootstraps a node or nodes, setting up SSH keys and installing prerequisite packages</p>
+
+<p>This command prepares a server to be used with the LEAP Platform by saving the server&rsquo;s SSH host key, copying the authorized_keys file, installing packages that are required for deploying, and registering important facts. Node init must be run before deploying to a server, and the server must be running and available via the network. This command only needs to be run once, but there is no harm in running it multiple times.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--ip IPADDRESS</code>
+Override the default SSH IP address.
+Default Value: None</p></li>
+<li><p><code>--port PORT</code>
+Override the default SSH port.
+Default Value: None</p></li>
+<li><p><code>--echo</code>
+If set, passwords are visible as you type them (default is hidden)</p></li>
+</ul>
+
+
+<h2><a name="leap-node-mv-old_name-new_name"></a>leap node mv OLD_NAME NEW_NAME</h2>
+
+<p>Renames a node file, and all its related files.</p>
+
+<h2><a name="leap-node-rm-name"></a>leap node rm NAME</h2>
+
+<p>Removes all the files related to the node named NAME.</p>
+
+<h1><a name="leap-scp-file1-file2"></a>leap scp FILE1 FILE2</h1>
+
+<p>Secure copy from FILE1 to FILE2. Files are specified as NODE_NAME:FILE_PATH. For local paths, omit &ldquo;NODE_NAME:&rdquo;.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>-r</code>
+Copy recursively</li>
+</ul>
+
+
+<h1><a name="leap-ssh-name"></a>leap ssh NAME</h1>
+
+<p>Log in to the specified node with an interactive shell.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--port SSH_PORT</code>
+Override default SSH port used when trying to connect to the server. Same as <code>--ssh "-p SSH_PORT"</code>.
+Default Value: None</p></li>
+<li><p><code>--ssh arg</code>
+Pass through raw options to ssh (e.g. <code>--ssh '-F ~/sshconfig'</code>).
+Default Value: None</p></li>
+</ul>
+
+
+<h1><a name="leap-test"></a>leap test</h1>
+
+<p>Run tests.</p>
+
+<h2><a name="leap-test-init"></a>leap test init</h2>
+
+<p>Creates files needed to run tests.</p>
+
+<h2><a name="leap-test-run-filter"></a>leap test run [FILTER]</h2>
+
+<p>Run the test suit on FILTER nodes.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><code>--[no-]continue</code>
+Continue over errors and failures (default is &ndash;no-continue).</li>
+</ul>
+
+
+<p>Default Command: run</p>
+
+<h1><a name="leap-tunnel-local_portnameremote_port"></a>leap tunnel [LOCAL_PORT:]NAME:REMOTE_PORT</h1>
+
+<p>Creates an SSH port forward (tunnel) to the node NAME. REMOTE_PORT is the port on the remote node that the tunnel will connect to. LOCAL_PORT is the optional port on your local machine. For example: <code>leap tunnel couch1:5984</code>.</p>
+
+<p><strong>Options</strong></p>
+
+<ul>
+<li><p><code>--port SSH_PORT</code>
+Override default SSH port used when trying to connect to the server. Same as <code>--ssh "-p SSH_PORT"</code>.
+Default Value: None</p></li>
+<li><p><code>--ssh arg</code>
+Pass through raw options to ssh (e.g. &ndash;ssh &lsquo;-F ~/sshconfig&rsquo;).
+Default Value: None</p></li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/config.html b/docs/en/guide/config.html
new file mode 100644
index 00000000..558f6940
--- /dev/null
+++ b/docs/en/guide/config.html
@@ -0,0 +1,584 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Configuration Files - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class='active level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Configuration Files</h1>
+
+<div id='summary'>Understanding and editing the configuration files.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="config/index.html#files">Files</a>
+ </li>
+ <li>
+ <a href="config/index.html#leapfile">Leapfile</a>
+ </li>
+ <li>
+ <a href="config/index.html#json-format">JSON format</a>
+ </li>
+ <li>
+ <a href="config/index.html#node-inheritance">Node inheritance</a>
+ <ol>
+ <li>
+ <a href="config/index.html#inheritance-rules">Inheritance rules</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="config/index.html#common-configuration-options">Common configuration options</a>
+ </li>
+ <li>
+ <a href="config/index.html#macros">Macros</a>
+ </li>
+ <li>
+ <a href="config/index.html#hash-tables">Hash tables</a>
+ </li>
+</ol></div>
+
+<h2><a name="files"></a>Files</h2>
+
+<p>Here are a list of some of the common files that make up a provider. Except for <code>Leapfile</code> and <code>provider.json</code>, the files are optional. Unless otherwise specified, all file names are relative to the &lsquo;provider directory&rsquo; root (where the Leapfile is).</p>
+
+<table class="table table-striped">
+<tr>
+ <td><code>Leapfile</code></td>
+ <td>If present, this file tells <code>leap</code> that the directory is a provider directory. This file is usually empty, but can contain global options.</td>
+</tr>
+<tr>
+ <td><code>~/.leaprc</code></td>
+ <td>Evaluated the same as Leapfile, but not committed to source control.</td>
+</tr>
+<tr>
+ <td><code>provider.json</code></td>
+ <td>Global options related to this provider. See <a href="provider-configuration.html">Provider Configuration</a>.</td>
+</tr>
+<tr>
+ <td><code>provider.ENVIRONMENT.json</code></td>
+ <td>Global options for the provider that are applied to only a single environment.</td>
+</tr>
+<tr>
+ <td><code>nodes/NAME.json</code></td>
+ <td>The configuration file for node called NAME.</td>
+</tr>
+<tr>
+ <td><code>common.json</code></td>
+ <td>All nodes inherit from this file. In other words, any options that appear in <code>common.json</code> will be added as default values to each node configuration, value that can be locally overridden.</td>
+</tr>
+<tr>
+ <td><code>services/SERVICE.json</code></td>
+ <td>The properties in this configuration file are applied to any node that includes SERVICE in its <code>services</code> property.</td>
+</tr>
+<tr>
+ <td><code>services/SERVICE.ENVIRONMENT.json</code></td>
+ <td>The properties in this configuration file are applied to any node that includes SERVICE in its services and has environment equal to ENVIRONMENT.</td>
+</tr>
+<tr>
+ <td><code>tags/TAG.json</code></td>
+ <td>The properties in this configuration file are applied to any node that has includes TAG in its <code>tags</code> property.</td>
+</tr>
+<tr>
+ <td><code>tags/TAG.ENVIRONMENT.json</code></td>
+ <td>The properties in this configuration file are applied to any node that has includes TAG in its <code>tags</code> property and has <code>environment</code> property equal to ENVIRONMENT.</td>
+</tr>
+<tr>
+ <td><code>secrets.json </code></td>
+ <td>An automatically generated file that contains any randomly generated strings needed in order to deploy. These strings are often secret and should be protected, although any need for a random string or number that is remembered will produce another entry in this file. This file is automatically generated and refreshed each time you run <code>leap compile</code> or <code>leap deploy</code>. If an entry is no longer needed, it will get removed. If you want to change a secret, you can remove this file and have it regenerated, or remove the particular line item and just those items will be created anew.</td>
+</tr>
+<tr>
+ <td><code>facts.json</code></td>
+ <td>If some of your servers are running on AWS or OpenStack, you will need to discover certain properties about how networking is configured on these machines in order for a full deploy to work. In these cases, make sure to run <code>leap facts update</code> to periodically regenerate the facts.json file.</td>
+</tr>
+<tr>
+ <td><code>files/*</code></td>
+ <td>Various static files used by the platform (e.g. keys, certificates, webapp customization, etc). In general, only generated files and files used to customize the provider (such as images) live in the <code>files</code> directory.</td>
+</tr>
+<tr>
+ <td><code>users/USER/</code></td>
+ <td>A directory that stores the public keys of the sysadmin with name USER. This person will have root access to all the servers.</td>
+</tr>
+</table>
+
+
+<h2><a name="leapfile"></a>Leapfile</h2>
+
+<p>A <code>Leapfile</code> defines options for the <code>leap</code> command and lives at the root of your provider directory. <code>Leapfile</code> is evaluated as ruby, so you can include whatever weird logic you want in this file. In particular, there are several variables you can set that modify the behavior of leap. For example:</p>
+
+<pre><code>@platform_directory_path = '../leap_platform'
+@log = '/var/log/leap.log'
+</code></pre>
+
+<p>Additionally, you can create a <code>~/.leaprc</code> file that is loaded after <code>Leapfile</code> and is evaluated the same way.</p>
+
+<p>Platform options:</p>
+
+<ul>
+<li><code>@platform_directory_path</code> (required). This must be set to the path where <code>leap_platform</code> lives. The path may be relative.</li>
+</ul>
+
+
+<p>Vagrant options:</p>
+
+<ul>
+<li><code>@vagrant_provider</code>. Changes the default vagrant provider (&ldquo;virtualbox&rdquo;). For example, <code>@vagrant_provider = "libvirt"</code>.</li>
+<li><code>@vagrant_network</code>. Allows you to override the default network used for local nodes. It should include a netmask like <code>@vagrant_network = '10.0.0.0/24'</code>.</li>
+<li><code>@custom_vagrant_vm_line</code>. Insert arbitrary text into the auto-generated Vagrantfile. For example, <code>@custom_vagrant_vm_line = "config.vm.boot_mode = :gui"</code>.</li>
+<li><code>@vagrant_basebox</code> allows specifying a different basebox as the default one. For example, <code>@vagrant_basebox = "LEAP/jessie"</code>.</li>
+</ul>
+
+
+<p>Logging options:</p>
+
+<ul>
+<li><code>@log</code>. If set, all command invocation and results are logged to the specified file. This is the same as the switch <code>--log FILE</code>, except that the command line switch will override the value in the Leapfile.</li>
+</ul>
+
+
+<h2><a name="json-format"></a>JSON format</h2>
+
+<p>All configuration files, other than <code>Leapfile</code>, are in the JSON format. For example:</p>
+
+<pre><code>{
+ "key1": "value1",
+ "key2": "value2"
+}
+</code></pre>
+
+<p>Keys should match <code>/[a-z0-9_]/</code> and must be in double quotes.</p>
+
+<p>Unlike traditional JSON, comments are allowed. If the first non-whitespace characters are <code>//</code> then the line is treated as a comment.</p>
+
+<pre><code>// this is a comment
+{
+ // this is a comment
+ "key": "value" // this is an error
+}
+</code></pre>
+
+<p>Options in the configuration files might be nested hashes, arrays, numbers, strings, or boolean. Numbers and boolean values should <strong>not</strong> be quoted. For example:</p>
+
+<pre><code>{
+ "openvpn": {
+ "ip_address": "1.1.1.1",
+ "protocols": ["tcp", "udp"],
+ "ports": [80, 53],
+ "options": {
+ "public_ip": false,
+ "adblock": true
+ }
+ }
+}
+</code></pre>
+
+<p>If the value string is prefixed with an &lsquo;=&rsquo; character, the result is evaluated as ruby. For example:</p>
+
+<pre><code>{
+ "domain": {
+ "public": "domain.org"
+ }
+ "api_domain": "= 'api.' + domain.public"
+}
+</code></pre>
+
+<p>In this case, the property &ldquo;api_domain&rdquo; will be set to &ldquo;api.domain.org&rdquo;. So long as you do not create unresolvable circular dependencies, you can reference other properties in evaluated ruby that are themselves evaluated ruby.</p>
+
+<p>See &ldquo;Macros&rdquo; below for information on the special macros available to the evaluated ruby.</p>
+
+<p>TIP: In rare cases, you might want to force the evaluation of a value to happen in a later pass after most of the other properties have been evaluated. To do this, prefix the value string with &ldquo;=>&rdquo; instead of &ldquo;=&rdquo;.</p>
+
+<h2><a name="node-inheritance"></a>Node inheritance</h2>
+
+<p>Every node inherits from common.json and also any of the services or tags attached to the node. Additionally, the <code>leap_platform</code> contains a directory <code>provider_base</code> that defines the default values for tags, services and common.json.</p>
+
+<p>Suppose you have a node configuration for <code>bitmask/nodes/willamette.json</code> like so:</p>
+
+<pre><code>{
+ "services": "webapp",
+ "tags": ["production", "northwest-us"],
+ "ip_address": "1.1.1.1"
+}
+</code></pre>
+
+<p>This node will have hostname &ldquo;willamette&rdquo; and it will inherit from the following files (in this order):</p>
+
+<ol>
+<li>common.json
+
+<ul>
+<li>load defaults: <code>provider_base/common.json</code></li>
+<li>load provider: <code>bitmask/common.json</code></li>
+</ul>
+</li>
+<li>service &ldquo;webapp&rdquo;
+
+<ul>
+<li>load defaults: <code>provider_base/services/webapp.json</code></li>
+<li>load provider: <code>bitmask/services/webapp.json</code></li>
+</ul>
+</li>
+<li>tag &ldquo;production&rdquo;
+
+<ul>
+<li>load defaults: <code>provider_base/tags/production.json</code></li>
+<li>load provider: <code>bitmask/tags/production.json</code></li>
+</ul>
+</li>
+<li>tag &ldquo;northwest-us&rdquo;
+
+<ul>
+<li>load: <code>bitmask/tags/northwest-us.json</code></li>
+</ul>
+</li>
+<li>finally, load node &ldquo;willamette&rdquo;
+
+<ul>
+<li>load: <code>bitmask/nodes/willamette.json</code></li>
+</ul>
+</li>
+</ol>
+
+
+<p>The <code>provider_base</code> directory is under the <code>leap_platform</code> specified in the file <code>Leapfile</code>.</p>
+
+<p>To see all the variables a node has inherited, you could run <code>leap inspect willamette</code>.</p>
+
+<h3><a name="inheritance-rules"></a>Inheritance rules</h3>
+
+<p>Suppose you have a node configuration <code>mynode.json</code>:</p>
+
+<pre><code>{
+ "tags": "production",
+ "simple_value": 100,
+ "replaced_array": ["dolphin", "kangaroo"],
+ "+add_array": ["red", "black"],
+ "-subtract_array": ["bitter"],
+ "converted_to_array": "not_array_element",
+ "!override": ["insist on this value"],
+ "hash": {
+ "key1": 1,
+ "key2": 2
+ }
+}
+</code></pre>
+
+<p>And a file <code>tags/production.json</code>:</p>
+
+<pre><code>{
+ "simple_value": 99999,
+ "replaced_array": ["zebra"],
+ "add_array": ["green],
+ "subtract_array": ["bitter", "sweet", "salty"],
+ "converted_to_array": ["array_element"],
+ "override": "this value will be overridden",
+ "hash": {
+ "key1": "one"
+ }
+}
+</code></pre>
+
+<p>In this scenario, <code>mynode.json</code> will inherit from <code>production.json</code>. The output of this inheritance will be:</p>
+
+<pre><code>{
+ "tags": "production",
+ "simple_value": 100,
+ "replaced_array": ["dolphin", "kangaroo"],
+ "add_array": ["red", "black", "green"],
+ "subtract_array": ["sweet", "salty"],
+ "converted_to_array": ["not_array_element", "array_element"],
+ "override": ["insist on this value"],
+ "hash": {
+ "key1": 1,
+ "key2": 2
+ }
+</code></pre>
+
+<p>The rules for inheritance (where &lsquo;old&rsquo; refers to the parent, and &lsquo;new&rsquo; refers to the child):</p>
+
+<ul>
+<li>Simple values (strings, numbers, boolean):
+
+<ul>
+<li>Replace the old value with the new value.</li>
+</ul>
+</li>
+<li>Array values:
+
+<ul>
+<li>Two arrays: replace the old array with the new array.</li>
+<li>One array and one simple value: add the simple value to the array.</li>
+<li>If property name is prefixed with &ldquo;+&rdquo;: merge the old and new arrays.</li>
+<li>If property name is prefixed with &ldquo;-&rdquo;: subtract new array from old array.</li>
+</ul>
+</li>
+<li>Hash values:
+
+<ul>
+<li>Hashes are always merged (the result includes the keys of both hashes). If there is a key in common, the new one overrides the old one.</li>
+</ul>
+</li>
+<li>Mismatch:
+
+<ul>
+<li>Although you can mix arrays and simple values, you cannot mix arrays with hashes or hashes with simple values. If you attempt to do so, it will fail to compile and give you an error message.</li>
+</ul>
+</li>
+<li>Override:
+
+<ul>
+<li>If property name is prefixed with &ldquo;!&rdquo;: then ensure that new value is always used, regardless of old value. In this case, the override takes precedence over type checking, so you will never get a type mismatch.</li>
+</ul>
+</li>
+</ul>
+
+
+<p>NOTE: special property name prefixes, like &ldquo;+&rdquo;, &ldquo;-&rdquo;, or &ldquo;!&rdquo;, are not included in the property name. These prefixes determine the merge strategy, but are stripped out when compiling the resulting JSON file.</p>
+
+<h2><a name="common-configuration-options"></a>Common configuration options</h2>
+
+<p>You can use the command <code>leap inspect</code> to see what options are available for a provider, node, service, or tag configuration. For example:</p>
+
+<ul>
+<li><code>leap inspect common</code> &ndash; show the options inherited by all nodes.</li>
+<li><code>leap inspect --base common</code> &ndash; show the common.json from <code>provider_base</code> without the local <code>common.json</code> inheritance applied.</li>
+<li><code>leap inspect webapp</code> &ndash; show all the options available for the service <code>webapp</code>.</li>
+</ul>
+
+
+<p>Here are some of the more important options you should be aware of:</p>
+
+<ul>
+<li><code>ip_address</code> &ndash; Required for all nodes, no default.</li>
+<li><code>ssh.port</code> &ndash; The SSH port you want the node&rsquo;s OpenSSH server to bind to. This is also the default when trying to connect to a node, but if the node currently has OpenSSH running on a different port then run deploy with <code>--port</code> to override the <code>ssh.port</code> configuration value.</li>
+<li><code>mosh.enabled</code> &ndash; If set to <code>true</code>, then mosh will be installed on the server. The default is <code>false</code>.</li>
+</ul>
+
+
+<h2><a name="macros"></a>Macros</h2>
+
+<p>When using evaluated ruby in a JSON configuration file, there are several special macros that are available. These are evaluated in the context of a node (available as the variable <code>self</code>).</p>
+
+<p>The following methods are available to the evaluated ruby:</p>
+
+<p><code>variable.variable</code></p>
+
+<blockquote><p>Any variable defined or inherited by a particular node configuration is available by just referencing it using either hash notation or object field notation (e.g. <code>['domain']['public']</code> or <code>domain.public</code>). Circular references are not allowed, but otherwise it is OK to nest evaluated values in other evaluated values. If a value has not been defined, the hash notation will return nil but the field notation will raise an exception. Properties of services, tags, and the global provider can all be referenced the same way. For example, <code>global.services['openvpn'].x509.dh</code>.</p></blockquote>
+
+<p><code>nodes</code></p>
+
+<blockquote><p>A hash of all nodes. This list can be filtered.</p></blockquote>
+
+<p><code>nodes_like_me</code></p>
+
+<blockquote><p>A hash of nodes that have the same deployment tags as the current node (e.g. &lsquo;production&rsquo; or &lsquo;local&rsquo;).</p></blockquote>
+
+<p><code>global.services</code></p>
+
+<blockquote><p>A hash of all services, e.g. <code>global.services['openvpn']</code> would return the &ldquo;openvpn&rdquo; service.</p></blockquote>
+
+<p><code>global.tags</code></p>
+
+<blockquote><p>A hash of all tags, e.g. <code>global.tags['production']</code> would return the &ldquo;production&rdquo; tag.</p></blockquote>
+
+<p> <code>global.provider</code></p>
+
+<blockquote><p>Can be used to access variables defined in <code>provider.json</code>, e.g. <code>global.provider.contacts.default</code>.</p></blockquote>
+
+<p><code>file(filename)</code></p>
+
+<blockquote><p>Inserts the full contents of the file. If the file is an erb template, it is rendered. The filename can either be one of the pre-defined file symbols, or it can be a path relative to the &ldquo;files&rdquo; directory in your provider instance. E.g, <code>file :ca_cert</code> or <code>files 'ca/ca.crt'</code>.</p></blockquote>
+
+<p><code>file_path(filename)</code></p>
+
+<blockquote><p> Ensures that the file will get rsynced to the node as an individual file. The value returned by <code>file_path</code> is the full path where this file will ultimately live when deploy to the node. e.g. <code>file_path :ca_cert</code> or <code>file_path 'branding/images/logo.png'</code>.</p></blockquote>
+
+<p><code>secret(:symbol)</code></p>
+
+<blockquote><p>Returns the value of a secret in secrets.json (or creates it if necessary). E.g. <code>secret :couch_admin_password</code></p></blockquote>
+
+<p><code>hosts_file</code></p>
+
+<blockquote><p>Returns a data structure that puppet will use to generate /etc/hosts. Care is taken to use the local IP of other hosts when needed.</p></blockquote>
+
+<p><code>known_hosts_file</code></p>
+
+<blockquote><p>Returns the lines needed in a SSH <code>known_hosts</code> file.</p></blockquote>
+
+<p><code>stunnel_client(node_list, port, options={})</code></p>
+
+<blockquote><p>Returns a stunnel configuration data structure for the client side. Argument <code>node_list</code> is an <code>ObjectList</code> of nodes running stunnel servers. Argument <code>port</code> is the real port of the ultimate service running on the servers that the client wants to connect to.</p></blockquote>
+
+<p><code>stunnel_server(port)</code></p>
+
+<blockquote><p>Generates a stunnel server entry. The <code>port</code> is the real port targeted service.</p></blockquote>
+
+<h2><a name="hash-tables"></a>Hash tables</h2>
+
+<p>The macros <code>nodes</code>, <code>nodes_like_me</code>, <code>global.services</code>, and <code>global.tags</code> all return a hash table of configuration objects (either nodes, services, or tags). There are several ways to filter and process these hash tables:</p>
+
+<p>Access an element by name:</p>
+
+<pre><code>nodes['vpn1'] # returns node named 'vpn1'
+global.services['openvpn'] # returns service named 'openvpn'
+</code></pre>
+
+<p>Create a new hash table by applying filters:</p>
+
+<pre><code>nodes[:public_dns =&gt; true] # all nodes where public_dns == true
+nodes[:services =&gt; 'openvpn', 'location.country_code' =&gt; 'US'] # openvpn service OR in the US.
+nodes[[:services, 'openvpn'], [:services, 'tor']] # services equal to openvpn OR tor
+nodes[:services =&gt; 'openvpn'][:tags =&gt; 'production'] # openvpn AND production
+nodes[:name =&gt; "!bob"] # all nodes that are NOT named "bob"
+</code></pre>
+
+<p>Create an array of values by selecting a single field:</p>
+
+<pre><code>nodes.field('location.name')
+==&gt; ['seattle', 'istanbul']
+</code></pre>
+
+<p>Create an array of hashes by selecting multiple fields:</p>
+
+<pre><code>nodes.fields('domain.full', 'ip_address')
+==&gt; [
+ {'domain_full' =&gt; 'red.bitmask.net', 'ip_address' =&gt; '1.1.1.1'},
+ {'domain_full' =&gt; 'blue.bitmask.net', 'ip_address' =&gt; '1.1.1.2'},
+]
+</code></pre>
+
+<p>Create a new hash table of hashes, with only certain fields:</p>
+
+<pre><code>nodes.pick_fields('domain.full', 'ip_address')
+==&gt; {
+ "red" =&gt; {'domain_full' =&gt; 'red.bitmask.net', 'ip_address' =&gt; '1.1.1.1'},
+ "blue =&gt; {'domain_full' =&gt; 'blue.bitmask.net', 'ip_address' =&gt; '1.1.1.2'},
+}
+</code></pre>
+
+<p>With <code>pick_fields</code>, if there is only one field, it will generate a simple hash table:</p>
+
+<pre><code>nodes.pick_fields('ip_address')
+==&gt; {
+ "red" =&gt; '1.1.1.1',
+ "blue =&gt; '1.1.1.2',
+}
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/config/index.html b/docs/en/guide/config/index.html
new file mode 100644
index 00000000..23e162d0
--- /dev/null
+++ b/docs/en/guide/config/index.html
@@ -0,0 +1,584 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Configuration Files - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class='active level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Configuration Files</h1>
+
+<div id='summary'>Understanding and editing the configuration files.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#files">Files</a>
+ </li>
+ <li>
+ <a href="index.html#leapfile">Leapfile</a>
+ </li>
+ <li>
+ <a href="index.html#json-format">JSON format</a>
+ </li>
+ <li>
+ <a href="index.html#node-inheritance">Node inheritance</a>
+ <ol>
+ <li>
+ <a href="index.html#inheritance-rules">Inheritance rules</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#common-configuration-options">Common configuration options</a>
+ </li>
+ <li>
+ <a href="index.html#macros">Macros</a>
+ </li>
+ <li>
+ <a href="index.html#hash-tables">Hash tables</a>
+ </li>
+</ol></div>
+
+<h2><a name="files"></a>Files</h2>
+
+<p>Here are a list of some of the common files that make up a provider. Except for <code>Leapfile</code> and <code>provider.json</code>, the files are optional. Unless otherwise specified, all file names are relative to the &lsquo;provider directory&rsquo; root (where the Leapfile is).</p>
+
+<table class="table table-striped">
+<tr>
+ <td><code>Leapfile</code></td>
+ <td>If present, this file tells <code>leap</code> that the directory is a provider directory. This file is usually empty, but can contain global options.</td>
+</tr>
+<tr>
+ <td><code>~/.leaprc</code></td>
+ <td>Evaluated the same as Leapfile, but not committed to source control.</td>
+</tr>
+<tr>
+ <td><code>provider.json</code></td>
+ <td>Global options related to this provider. See <a href="../provider-configuration.html">Provider Configuration</a>.</td>
+</tr>
+<tr>
+ <td><code>provider.ENVIRONMENT.json</code></td>
+ <td>Global options for the provider that are applied to only a single environment.</td>
+</tr>
+<tr>
+ <td><code>nodes/NAME.json</code></td>
+ <td>The configuration file for node called NAME.</td>
+</tr>
+<tr>
+ <td><code>common.json</code></td>
+ <td>All nodes inherit from this file. In other words, any options that appear in <code>common.json</code> will be added as default values to each node configuration, value that can be locally overridden.</td>
+</tr>
+<tr>
+ <td><code>services/SERVICE.json</code></td>
+ <td>The properties in this configuration file are applied to any node that includes SERVICE in its <code>services</code> property.</td>
+</tr>
+<tr>
+ <td><code>services/SERVICE.ENVIRONMENT.json</code></td>
+ <td>The properties in this configuration file are applied to any node that includes SERVICE in its services and has environment equal to ENVIRONMENT.</td>
+</tr>
+<tr>
+ <td><code>tags/TAG.json</code></td>
+ <td>The properties in this configuration file are applied to any node that has includes TAG in its <code>tags</code> property.</td>
+</tr>
+<tr>
+ <td><code>tags/TAG.ENVIRONMENT.json</code></td>
+ <td>The properties in this configuration file are applied to any node that has includes TAG in its <code>tags</code> property and has <code>environment</code> property equal to ENVIRONMENT.</td>
+</tr>
+<tr>
+ <td><code>secrets.json </code></td>
+ <td>An automatically generated file that contains any randomly generated strings needed in order to deploy. These strings are often secret and should be protected, although any need for a random string or number that is remembered will produce another entry in this file. This file is automatically generated and refreshed each time you run <code>leap compile</code> or <code>leap deploy</code>. If an entry is no longer needed, it will get removed. If you want to change a secret, you can remove this file and have it regenerated, or remove the particular line item and just those items will be created anew.</td>
+</tr>
+<tr>
+ <td><code>facts.json</code></td>
+ <td>If some of your servers are running on AWS or OpenStack, you will need to discover certain properties about how networking is configured on these machines in order for a full deploy to work. In these cases, make sure to run <code>leap facts update</code> to periodically regenerate the facts.json file.</td>
+</tr>
+<tr>
+ <td><code>files/*</code></td>
+ <td>Various static files used by the platform (e.g. keys, certificates, webapp customization, etc). In general, only generated files and files used to customize the provider (such as images) live in the <code>files</code> directory.</td>
+</tr>
+<tr>
+ <td><code>users/USER/</code></td>
+ <td>A directory that stores the public keys of the sysadmin with name USER. This person will have root access to all the servers.</td>
+</tr>
+</table>
+
+
+<h2><a name="leapfile"></a>Leapfile</h2>
+
+<p>A <code>Leapfile</code> defines options for the <code>leap</code> command and lives at the root of your provider directory. <code>Leapfile</code> is evaluated as ruby, so you can include whatever weird logic you want in this file. In particular, there are several variables you can set that modify the behavior of leap. For example:</p>
+
+<pre><code>@platform_directory_path = '../leap_platform'
+@log = '/var/log/leap.log'
+</code></pre>
+
+<p>Additionally, you can create a <code>~/.leaprc</code> file that is loaded after <code>Leapfile</code> and is evaluated the same way.</p>
+
+<p>Platform options:</p>
+
+<ul>
+<li><code>@platform_directory_path</code> (required). This must be set to the path where <code>leap_platform</code> lives. The path may be relative.</li>
+</ul>
+
+
+<p>Vagrant options:</p>
+
+<ul>
+<li><code>@vagrant_provider</code>. Changes the default vagrant provider (&ldquo;virtualbox&rdquo;). For example, <code>@vagrant_provider = "libvirt"</code>.</li>
+<li><code>@vagrant_network</code>. Allows you to override the default network used for local nodes. It should include a netmask like <code>@vagrant_network = '10.0.0.0/24'</code>.</li>
+<li><code>@custom_vagrant_vm_line</code>. Insert arbitrary text into the auto-generated Vagrantfile. For example, <code>@custom_vagrant_vm_line = "config.vm.boot_mode = :gui"</code>.</li>
+<li><code>@vagrant_basebox</code> allows specifying a different basebox as the default one. For example, <code>@vagrant_basebox = "LEAP/jessie"</code>.</li>
+</ul>
+
+
+<p>Logging options:</p>
+
+<ul>
+<li><code>@log</code>. If set, all command invocation and results are logged to the specified file. This is the same as the switch <code>--log FILE</code>, except that the command line switch will override the value in the Leapfile.</li>
+</ul>
+
+
+<h2><a name="json-format"></a>JSON format</h2>
+
+<p>All configuration files, other than <code>Leapfile</code>, are in the JSON format. For example:</p>
+
+<pre><code>{
+ "key1": "value1",
+ "key2": "value2"
+}
+</code></pre>
+
+<p>Keys should match <code>/[a-z0-9_]/</code> and must be in double quotes.</p>
+
+<p>Unlike traditional JSON, comments are allowed. If the first non-whitespace characters are <code>//</code> then the line is treated as a comment.</p>
+
+<pre><code>// this is a comment
+{
+ // this is a comment
+ "key": "value" // this is an error
+}
+</code></pre>
+
+<p>Options in the configuration files might be nested hashes, arrays, numbers, strings, or boolean. Numbers and boolean values should <strong>not</strong> be quoted. For example:</p>
+
+<pre><code>{
+ "openvpn": {
+ "ip_address": "1.1.1.1",
+ "protocols": ["tcp", "udp"],
+ "ports": [80, 53],
+ "options": {
+ "public_ip": false,
+ "adblock": true
+ }
+ }
+}
+</code></pre>
+
+<p>If the value string is prefixed with an &lsquo;=&rsquo; character, the result is evaluated as ruby. For example:</p>
+
+<pre><code>{
+ "domain": {
+ "public": "domain.org"
+ }
+ "api_domain": "= 'api.' + domain.public"
+}
+</code></pre>
+
+<p>In this case, the property &ldquo;api_domain&rdquo; will be set to &ldquo;api.domain.org&rdquo;. So long as you do not create unresolvable circular dependencies, you can reference other properties in evaluated ruby that are themselves evaluated ruby.</p>
+
+<p>See &ldquo;Macros&rdquo; below for information on the special macros available to the evaluated ruby.</p>
+
+<p>TIP: In rare cases, you might want to force the evaluation of a value to happen in a later pass after most of the other properties have been evaluated. To do this, prefix the value string with &ldquo;=>&rdquo; instead of &ldquo;=&rdquo;.</p>
+
+<h2><a name="node-inheritance"></a>Node inheritance</h2>
+
+<p>Every node inherits from common.json and also any of the services or tags attached to the node. Additionally, the <code>leap_platform</code> contains a directory <code>provider_base</code> that defines the default values for tags, services and common.json.</p>
+
+<p>Suppose you have a node configuration for <code>bitmask/nodes/willamette.json</code> like so:</p>
+
+<pre><code>{
+ "services": "webapp",
+ "tags": ["production", "northwest-us"],
+ "ip_address": "1.1.1.1"
+}
+</code></pre>
+
+<p>This node will have hostname &ldquo;willamette&rdquo; and it will inherit from the following files (in this order):</p>
+
+<ol>
+<li>common.json
+
+<ul>
+<li>load defaults: <code>provider_base/common.json</code></li>
+<li>load provider: <code>bitmask/common.json</code></li>
+</ul>
+</li>
+<li>service &ldquo;webapp&rdquo;
+
+<ul>
+<li>load defaults: <code>provider_base/services/webapp.json</code></li>
+<li>load provider: <code>bitmask/services/webapp.json</code></li>
+</ul>
+</li>
+<li>tag &ldquo;production&rdquo;
+
+<ul>
+<li>load defaults: <code>provider_base/tags/production.json</code></li>
+<li>load provider: <code>bitmask/tags/production.json</code></li>
+</ul>
+</li>
+<li>tag &ldquo;northwest-us&rdquo;
+
+<ul>
+<li>load: <code>bitmask/tags/northwest-us.json</code></li>
+</ul>
+</li>
+<li>finally, load node &ldquo;willamette&rdquo;
+
+<ul>
+<li>load: <code>bitmask/nodes/willamette.json</code></li>
+</ul>
+</li>
+</ol>
+
+
+<p>The <code>provider_base</code> directory is under the <code>leap_platform</code> specified in the file <code>Leapfile</code>.</p>
+
+<p>To see all the variables a node has inherited, you could run <code>leap inspect willamette</code>.</p>
+
+<h3><a name="inheritance-rules"></a>Inheritance rules</h3>
+
+<p>Suppose you have a node configuration <code>mynode.json</code>:</p>
+
+<pre><code>{
+ "tags": "production",
+ "simple_value": 100,
+ "replaced_array": ["dolphin", "kangaroo"],
+ "+add_array": ["red", "black"],
+ "-subtract_array": ["bitter"],
+ "converted_to_array": "not_array_element",
+ "!override": ["insist on this value"],
+ "hash": {
+ "key1": 1,
+ "key2": 2
+ }
+}
+</code></pre>
+
+<p>And a file <code>tags/production.json</code>:</p>
+
+<pre><code>{
+ "simple_value": 99999,
+ "replaced_array": ["zebra"],
+ "add_array": ["green],
+ "subtract_array": ["bitter", "sweet", "salty"],
+ "converted_to_array": ["array_element"],
+ "override": "this value will be overridden",
+ "hash": {
+ "key1": "one"
+ }
+}
+</code></pre>
+
+<p>In this scenario, <code>mynode.json</code> will inherit from <code>production.json</code>. The output of this inheritance will be:</p>
+
+<pre><code>{
+ "tags": "production",
+ "simple_value": 100,
+ "replaced_array": ["dolphin", "kangaroo"],
+ "add_array": ["red", "black", "green"],
+ "subtract_array": ["sweet", "salty"],
+ "converted_to_array": ["not_array_element", "array_element"],
+ "override": ["insist on this value"],
+ "hash": {
+ "key1": 1,
+ "key2": 2
+ }
+</code></pre>
+
+<p>The rules for inheritance (where &lsquo;old&rsquo; refers to the parent, and &lsquo;new&rsquo; refers to the child):</p>
+
+<ul>
+<li>Simple values (strings, numbers, boolean):
+
+<ul>
+<li>Replace the old value with the new value.</li>
+</ul>
+</li>
+<li>Array values:
+
+<ul>
+<li>Two arrays: replace the old array with the new array.</li>
+<li>One array and one simple value: add the simple value to the array.</li>
+<li>If property name is prefixed with &ldquo;+&rdquo;: merge the old and new arrays.</li>
+<li>If property name is prefixed with &ldquo;-&rdquo;: subtract new array from old array.</li>
+</ul>
+</li>
+<li>Hash values:
+
+<ul>
+<li>Hashes are always merged (the result includes the keys of both hashes). If there is a key in common, the new one overrides the old one.</li>
+</ul>
+</li>
+<li>Mismatch:
+
+<ul>
+<li>Although you can mix arrays and simple values, you cannot mix arrays with hashes or hashes with simple values. If you attempt to do so, it will fail to compile and give you an error message.</li>
+</ul>
+</li>
+<li>Override:
+
+<ul>
+<li>If property name is prefixed with &ldquo;!&rdquo;: then ensure that new value is always used, regardless of old value. In this case, the override takes precedence over type checking, so you will never get a type mismatch.</li>
+</ul>
+</li>
+</ul>
+
+
+<p>NOTE: special property name prefixes, like &ldquo;+&rdquo;, &ldquo;-&rdquo;, or &ldquo;!&rdquo;, are not included in the property name. These prefixes determine the merge strategy, but are stripped out when compiling the resulting JSON file.</p>
+
+<h2><a name="common-configuration-options"></a>Common configuration options</h2>
+
+<p>You can use the command <code>leap inspect</code> to see what options are available for a provider, node, service, or tag configuration. For example:</p>
+
+<ul>
+<li><code>leap inspect common</code> &ndash; show the options inherited by all nodes.</li>
+<li><code>leap inspect --base common</code> &ndash; show the common.json from <code>provider_base</code> without the local <code>common.json</code> inheritance applied.</li>
+<li><code>leap inspect webapp</code> &ndash; show all the options available for the service <code>webapp</code>.</li>
+</ul>
+
+
+<p>Here are some of the more important options you should be aware of:</p>
+
+<ul>
+<li><code>ip_address</code> &ndash; Required for all nodes, no default.</li>
+<li><code>ssh.port</code> &ndash; The SSH port you want the node&rsquo;s OpenSSH server to bind to. This is also the default when trying to connect to a node, but if the node currently has OpenSSH running on a different port then run deploy with <code>--port</code> to override the <code>ssh.port</code> configuration value.</li>
+<li><code>mosh.enabled</code> &ndash; If set to <code>true</code>, then mosh will be installed on the server. The default is <code>false</code>.</li>
+</ul>
+
+
+<h2><a name="macros"></a>Macros</h2>
+
+<p>When using evaluated ruby in a JSON configuration file, there are several special macros that are available. These are evaluated in the context of a node (available as the variable <code>self</code>).</p>
+
+<p>The following methods are available to the evaluated ruby:</p>
+
+<p><code>variable.variable</code></p>
+
+<blockquote><p>Any variable defined or inherited by a particular node configuration is available by just referencing it using either hash notation or object field notation (e.g. <code>['domain']['public']</code> or <code>domain.public</code>). Circular references are not allowed, but otherwise it is OK to nest evaluated values in other evaluated values. If a value has not been defined, the hash notation will return nil but the field notation will raise an exception. Properties of services, tags, and the global provider can all be referenced the same way. For example, <code>global.services['openvpn'].x509.dh</code>.</p></blockquote>
+
+<p><code>nodes</code></p>
+
+<blockquote><p>A hash of all nodes. This list can be filtered.</p></blockquote>
+
+<p><code>nodes_like_me</code></p>
+
+<blockquote><p>A hash of nodes that have the same deployment tags as the current node (e.g. &lsquo;production&rsquo; or &lsquo;local&rsquo;).</p></blockquote>
+
+<p><code>global.services</code></p>
+
+<blockquote><p>A hash of all services, e.g. <code>global.services['openvpn']</code> would return the &ldquo;openvpn&rdquo; service.</p></blockquote>
+
+<p><code>global.tags</code></p>
+
+<blockquote><p>A hash of all tags, e.g. <code>global.tags['production']</code> would return the &ldquo;production&rdquo; tag.</p></blockquote>
+
+<p> <code>global.provider</code></p>
+
+<blockquote><p>Can be used to access variables defined in <code>provider.json</code>, e.g. <code>global.provider.contacts.default</code>.</p></blockquote>
+
+<p><code>file(filename)</code></p>
+
+<blockquote><p>Inserts the full contents of the file. If the file is an erb template, it is rendered. The filename can either be one of the pre-defined file symbols, or it can be a path relative to the &ldquo;files&rdquo; directory in your provider instance. E.g, <code>file :ca_cert</code> or <code>files 'ca/ca.crt'</code>.</p></blockquote>
+
+<p><code>file_path(filename)</code></p>
+
+<blockquote><p> Ensures that the file will get rsynced to the node as an individual file. The value returned by <code>file_path</code> is the full path where this file will ultimately live when deploy to the node. e.g. <code>file_path :ca_cert</code> or <code>file_path 'branding/images/logo.png'</code>.</p></blockquote>
+
+<p><code>secret(:symbol)</code></p>
+
+<blockquote><p>Returns the value of a secret in secrets.json (or creates it if necessary). E.g. <code>secret :couch_admin_password</code></p></blockquote>
+
+<p><code>hosts_file</code></p>
+
+<blockquote><p>Returns a data structure that puppet will use to generate /etc/hosts. Care is taken to use the local IP of other hosts when needed.</p></blockquote>
+
+<p><code>known_hosts_file</code></p>
+
+<blockquote><p>Returns the lines needed in a SSH <code>known_hosts</code> file.</p></blockquote>
+
+<p><code>stunnel_client(node_list, port, options={})</code></p>
+
+<blockquote><p>Returns a stunnel configuration data structure for the client side. Argument <code>node_list</code> is an <code>ObjectList</code> of nodes running stunnel servers. Argument <code>port</code> is the real port of the ultimate service running on the servers that the client wants to connect to.</p></blockquote>
+
+<p><code>stunnel_server(port)</code></p>
+
+<blockquote><p>Generates a stunnel server entry. The <code>port</code> is the real port targeted service.</p></blockquote>
+
+<h2><a name="hash-tables"></a>Hash tables</h2>
+
+<p>The macros <code>nodes</code>, <code>nodes_like_me</code>, <code>global.services</code>, and <code>global.tags</code> all return a hash table of configuration objects (either nodes, services, or tags). There are several ways to filter and process these hash tables:</p>
+
+<p>Access an element by name:</p>
+
+<pre><code>nodes['vpn1'] # returns node named 'vpn1'
+global.services['openvpn'] # returns service named 'openvpn'
+</code></pre>
+
+<p>Create a new hash table by applying filters:</p>
+
+<pre><code>nodes[:public_dns =&gt; true] # all nodes where public_dns == true
+nodes[:services =&gt; 'openvpn', 'location.country_code' =&gt; 'US'] # openvpn service OR in the US.
+nodes[[:services, 'openvpn'], [:services, 'tor']] # services equal to openvpn OR tor
+nodes[:services =&gt; 'openvpn'][:tags =&gt; 'production'] # openvpn AND production
+nodes[:name =&gt; "!bob"] # all nodes that are NOT named "bob"
+</code></pre>
+
+<p>Create an array of values by selecting a single field:</p>
+
+<pre><code>nodes.field('location.name')
+==&gt; ['seattle', 'istanbul']
+</code></pre>
+
+<p>Create an array of hashes by selecting multiple fields:</p>
+
+<pre><code>nodes.fields('domain.full', 'ip_address')
+==&gt; [
+ {'domain_full' =&gt; 'red.bitmask.net', 'ip_address' =&gt; '1.1.1.1'},
+ {'domain_full' =&gt; 'blue.bitmask.net', 'ip_address' =&gt; '1.1.1.2'},
+]
+</code></pre>
+
+<p>Create a new hash table of hashes, with only certain fields:</p>
+
+<pre><code>nodes.pick_fields('domain.full', 'ip_address')
+==&gt; {
+ "red" =&gt; {'domain_full' =&gt; 'red.bitmask.net', 'ip_address' =&gt; '1.1.1.1'},
+ "blue =&gt; {'domain_full' =&gt; 'blue.bitmask.net', 'ip_address' =&gt; '1.1.1.2'},
+}
+</code></pre>
+
+<p>With <code>pick_fields</code>, if there is only one field, it will generate a simple hash table:</p>
+
+<pre><code>nodes.pick_fields('ip_address')
+==&gt; {
+ "red" =&gt; '1.1.1.1',
+ "blue =&gt; '1.1.1.2',
+}
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/domains.html b/docs/en/guide/domains.html
new file mode 100644
index 00000000..eb3331ff
--- /dev/null
+++ b/docs/en/guide/domains.html
@@ -0,0 +1,298 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Domains - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class='active level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Domains</h1>
+
+<div id='summary'>How to handle domain names and integrating LEAP with existing services.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="domains/index.html#overview">Overview</a>
+ <ol>
+ <li>
+ <a href="domains/index.html#definitions">Definitions</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="domains/index.html#generating-a-zone-file">Generating a zone file</a>
+ </li>
+ <li>
+ <a href="domains/index.html#a-single-domain">A single domain</a>
+ </li>
+ <li>
+ <a href="domains/index.html#a-separate-domain-for-the-webapp">A separate domain for the webapp</a>
+ <ol>
+ <li>
+ <a href="domains/index.html#step-1-configuring-webappdomain">Step 1. Configuring <code>webapp.domain</code></a>
+ </li>
+ <li>
+ <a href="domains/index.html#step-2-putting-the-compiled-providerjson-in-place">Step 2. Putting the compiled <code>provider.json</code> in place</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="domains/index.html#integrating-with-existing-email-system">Integrating with existing email system</a>
+ <ol>
+ <li>
+ <a href="domains/index.html#step-1-modify-leap-webapp">Step 1. Modify LEAP webapp</a>
+ </li>
+ <li>
+ <a href="domains/index.html#step-2-configure-mx-servers">Step 2. Configure MX servers</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="overview"></a>Overview</h2>
+
+<p>Deploying LEAP can start to get very tricky when you need to integrate LEAP services with an existing domain that you already use or which already has users. Most of this complexity is unavoidable, although there are a few things we plan to do in the future to make this a little less painful.</p>
+
+<p>Because integration with legacy systems is an advanced topic, we recommend that you begin with a new domain. Once everything works and you are comfortable with your LEAP-powered infrastructure, you can then contemplate integrating with your existing domain.</p>
+
+<h3><a name="definitions"></a>Definitions</h3>
+
+<p><strong>provider domain</strong></p>
+
+<p>This is the main domain used to identify the provider. The <strong>provider domain</strong> is what the user enters in the Bitmask client. e.g. <code>example.org</code>. The full host name of every node in your provider infrastructure will use the <strong>provider domain</strong> (e.g. <code>dbnode.example.org</code>).</p>
+
+<p>In order for the Bitmask client to get configured for use with a provider, it must be able to find the <code>provider.json</code> bootstrap file at the root of the <strong>provider domain</strong>. This is not needed if the Bitmask client is &ldquo;pre-seeded&rdquo; with the provider&rsquo;s information (these providers show up in a the initial list of available providers).</p>
+
+<p><strong>webapp domain</strong></p>
+
+<p>This is the domain that runs the leap_web application that allows users to register accounts, create help tickets, etc. e.g. <code>example.org</code> or <code>user.example.org</code>. The <strong>webapp domain</strong> defaults to the <strong>provider domain</strong> unless it is explicitly configured separately.</p>
+
+<p><strong>API domain</strong></p>
+
+<p>This is the domain that the provider API runs on. Typically, this is set automatically and you never need to configure it. The user should never be aware of this domain. e.g. <code>api.example.org</code>. The Bitmask client discovers this API domain by reading it from the <code>provider.json</code> file it grabs from the <strong>provider domain</strong>.</p>
+
+<p><strong>mail domain</strong></p>
+
+<p>This is the domain used for mail accounts, e.g. <code>username@example.org</code>. Currently, this is always the <strong>provider domain</strong>, but it may be independently configurable in the future.</p>
+
+<h2><a name="generating-a-zone-file"></a>Generating a zone file</h2>
+
+<p>Currently, the platform does not include a dedicated <code>dns</code> service type, so you need to have your own setup for DNS. You can generate the appropriate configuration options with this command:</p>
+
+<pre><code>leap compile zone
+</code></pre>
+
+<h2><a name="a-single-domain"></a>A single domain</h2>
+
+<p>The easy approach is to use a single domain for <strong>provider domain</strong>, <strong>webapp domain</strong>, and <strong>email domain</strong>. This will install the webapp on the <strong>provider domain</strong>, which means that this domain must be a new one that you are not currently using for anything.</p>
+
+<p>To configure a single domain, just set the domain in <code>provider.json</code>:</p>
+
+<pre><code>{
+ "domain": "example.org"
+}
+</code></pre>
+
+<p>If you have multiple environments, you can specify a different <strong>provider domain</strong> for each environment. For example:</p>
+
+<p><code>provider.staging.json</code></p>
+
+<pre><code>{
+ "domain": "staging.example.org"
+}
+</code></pre>
+
+<h2><a name="a-separate-domain-for-the-webapp"></a>A separate domain for the webapp</h2>
+
+<p>It is possible make the <strong>webapp domain</strong> different than the <strong>provider domain</strong>. This is needed if you already have a website running at your <strong>provider domain</strong>.</p>
+
+<p>In order to put webapp on a different domain, you must take two steps:</p>
+
+<ol>
+<li>You must configure <code>webapp.domain</code> for nodes with the <code>webapp</code> service.</li>
+<li>You must make the compiled <code>provider.json</code> available at the root of the <strong>provider domain</strong>.</li>
+</ol>
+
+
+<p>NOTE: This compiled provider.json is different than the provider.json that you edit and lives in the root of the provider directory.</p>
+
+<h3><a name="step-1-configuring-webappdomain"></a>Step 1. Configuring <code>webapp.domain</code></h3>
+
+<p>In <code>services/webapp.json</code>:</p>
+
+<pre><code>{
+ "webapp": {
+ "domain": "user.example.org"
+ }
+}
+</code></pre>
+
+<h3><a name="step-2-putting-the-compiled-providerjson-in-place"></a>Step 2. Putting the compiled <code>provider.json</code> in place</h3>
+
+<p>Generate the compiled <code>provider.json</code>:</p>
+
+<pre><code>leap compile provider.json
+= created files/web/bootstrap/
+= created files/web/bootstrap/README
+= created files/web/bootstrap/production/
+= created files/web/bootstrap/production/provider.json
+= created files/web/bootstrap/production/htaccess
+= created files/web/bootstrap/staging/
+= created files/web/bootstrap/staging/provider.json
+= created files/web/bootstrap/staging/htaccess
+</code></pre>
+
+<p>This command compiles a separate <code>provider.json</code> for each environment, or &ldquo;default&rdquo; if you don&rsquo;t have an environment. In the example above, there is an environment called &ldquo;production&rdquo; and one called &ldquo;staging&rdquo;, but your setup will probably differ.</p>
+
+<p>The resulting <code>provider.json</code> file must then be put at the root URL of your <strong>provider domain</strong> for the appropriate environment.</p>
+
+<p>There is one additional complication: currently, the Bitmask client tests for compatibility using some HTTP headers on the <code>/provider.json</code> response. This is will hopefully change in the future, but for now you need to ensure the right headers are set in the response. The included file <code>htaccess</code> has example directives for Apache, if that is what you use.</p>
+
+<p>This step can be skipped if you happen to use the <code>static</code> service to deploy an <code>amber</code> powered static website to <strong>provider domain</strong>. In this case, the correct <code>provider.json</code> will be automatically put into place.</p>
+
+<h2><a name="integrating-with-existing-email-system"></a>Integrating with existing email system</h2>
+
+<p>If your <strong>mail domain</strong> already has users from a legacy email system, then things get a bit complicated. In order to be able to support both LEAP-powered email and legacy email on the same domain, you need to follow these steps:</p>
+
+<ol>
+<li>Modify the LEAP webapp so that it does not create users with the same name as users in the legacy system.</li>
+<li>Configure your legacy MX servers to forward mail that they cannot handle to the LEAP MX servers, or vice versa.</li>
+</ol>
+
+
+<h3><a name="step-1-modify-leap-webapp"></a>Step 1. Modify LEAP webapp</h3>
+
+<p>In order to modify the webapp to respect the usernames already reserved by your legacy system, you need to modify the LEAP webapp code. The easiest way to do this is to create a custom gem that modifies the behavior of the webapp.</p>
+
+<p>For this example, we will call our custom gem <code>reserve_usernames</code>.</p>
+
+<p>This gem can live in one of two places:</p>
+
+<p>(1) You can fork the project leap_web and put the gem in <code>leap_web/vendor/gems/reserve_usernames</code>. Then, modify <code>Gemfile</code> and add the line <code>gem 'common_languages', :path =&gt; 'vendor/gems/reserve_usernames'</code></p>
+
+<p>(2) Alternately, you can put the gem in the local provider directory <code>files/webapp/gems/reserve_username</code>. This will get synced to the webapp servers when you deploy and put in <code>/srv/leap/webapp/config/customization</code> where it will get automatically loaded by the webapp.</p>
+
+<p>What should the gem <code>reserve_usernames</code> look like? There is an example available here: <a href="https://leap.se/git/reserved_usernames.git">https://leap.se/git/reserved_usernames.git</a></p>
+
+<p>This example gem uses ActiveResource to communicate with a remote REST API for creating and checking username reservations. This ensures that both the legacy system and the LEAP system use the same namespace. Alternately, you could write a gem that checks the legacy database directly.</p>
+
+<h3><a name="step-2-configure-mx-servers"></a>Step 2. Configure MX servers</h3>
+
+<p>To be written.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/domains/index.html b/docs/en/guide/domains/index.html
new file mode 100644
index 00000000..9ebf3b2c
--- /dev/null
+++ b/docs/en/guide/domains/index.html
@@ -0,0 +1,298 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Domains - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class='active level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Domains</h1>
+
+<div id='summary'>How to handle domain names and integrating LEAP with existing services.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#overview">Overview</a>
+ <ol>
+ <li>
+ <a href="index.html#definitions">Definitions</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#generating-a-zone-file">Generating a zone file</a>
+ </li>
+ <li>
+ <a href="index.html#a-single-domain">A single domain</a>
+ </li>
+ <li>
+ <a href="index.html#a-separate-domain-for-the-webapp">A separate domain for the webapp</a>
+ <ol>
+ <li>
+ <a href="index.html#step-1-configuring-webappdomain">Step 1. Configuring <code>webapp.domain</code></a>
+ </li>
+ <li>
+ <a href="index.html#step-2-putting-the-compiled-providerjson-in-place">Step 2. Putting the compiled <code>provider.json</code> in place</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#integrating-with-existing-email-system">Integrating with existing email system</a>
+ <ol>
+ <li>
+ <a href="index.html#step-1-modify-leap-webapp">Step 1. Modify LEAP webapp</a>
+ </li>
+ <li>
+ <a href="index.html#step-2-configure-mx-servers">Step 2. Configure MX servers</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="overview"></a>Overview</h2>
+
+<p>Deploying LEAP can start to get very tricky when you need to integrate LEAP services with an existing domain that you already use or which already has users. Most of this complexity is unavoidable, although there are a few things we plan to do in the future to make this a little less painful.</p>
+
+<p>Because integration with legacy systems is an advanced topic, we recommend that you begin with a new domain. Once everything works and you are comfortable with your LEAP-powered infrastructure, you can then contemplate integrating with your existing domain.</p>
+
+<h3><a name="definitions"></a>Definitions</h3>
+
+<p><strong>provider domain</strong></p>
+
+<p>This is the main domain used to identify the provider. The <strong>provider domain</strong> is what the user enters in the Bitmask client. e.g. <code>example.org</code>. The full host name of every node in your provider infrastructure will use the <strong>provider domain</strong> (e.g. <code>dbnode.example.org</code>).</p>
+
+<p>In order for the Bitmask client to get configured for use with a provider, it must be able to find the <code>provider.json</code> bootstrap file at the root of the <strong>provider domain</strong>. This is not needed if the Bitmask client is &ldquo;pre-seeded&rdquo; with the provider&rsquo;s information (these providers show up in a the initial list of available providers).</p>
+
+<p><strong>webapp domain</strong></p>
+
+<p>This is the domain that runs the leap_web application that allows users to register accounts, create help tickets, etc. e.g. <code>example.org</code> or <code>user.example.org</code>. The <strong>webapp domain</strong> defaults to the <strong>provider domain</strong> unless it is explicitly configured separately.</p>
+
+<p><strong>API domain</strong></p>
+
+<p>This is the domain that the provider API runs on. Typically, this is set automatically and you never need to configure it. The user should never be aware of this domain. e.g. <code>api.example.org</code>. The Bitmask client discovers this API domain by reading it from the <code>provider.json</code> file it grabs from the <strong>provider domain</strong>.</p>
+
+<p><strong>mail domain</strong></p>
+
+<p>This is the domain used for mail accounts, e.g. <code>username@example.org</code>. Currently, this is always the <strong>provider domain</strong>, but it may be independently configurable in the future.</p>
+
+<h2><a name="generating-a-zone-file"></a>Generating a zone file</h2>
+
+<p>Currently, the platform does not include a dedicated <code>dns</code> service type, so you need to have your own setup for DNS. You can generate the appropriate configuration options with this command:</p>
+
+<pre><code>leap compile zone
+</code></pre>
+
+<h2><a name="a-single-domain"></a>A single domain</h2>
+
+<p>The easy approach is to use a single domain for <strong>provider domain</strong>, <strong>webapp domain</strong>, and <strong>email domain</strong>. This will install the webapp on the <strong>provider domain</strong>, which means that this domain must be a new one that you are not currently using for anything.</p>
+
+<p>To configure a single domain, just set the domain in <code>provider.json</code>:</p>
+
+<pre><code>{
+ "domain": "example.org"
+}
+</code></pre>
+
+<p>If you have multiple environments, you can specify a different <strong>provider domain</strong> for each environment. For example:</p>
+
+<p><code>provider.staging.json</code></p>
+
+<pre><code>{
+ "domain": "staging.example.org"
+}
+</code></pre>
+
+<h2><a name="a-separate-domain-for-the-webapp"></a>A separate domain for the webapp</h2>
+
+<p>It is possible make the <strong>webapp domain</strong> different than the <strong>provider domain</strong>. This is needed if you already have a website running at your <strong>provider domain</strong>.</p>
+
+<p>In order to put webapp on a different domain, you must take two steps:</p>
+
+<ol>
+<li>You must configure <code>webapp.domain</code> for nodes with the <code>webapp</code> service.</li>
+<li>You must make the compiled <code>provider.json</code> available at the root of the <strong>provider domain</strong>.</li>
+</ol>
+
+
+<p>NOTE: This compiled provider.json is different than the provider.json that you edit and lives in the root of the provider directory.</p>
+
+<h3><a name="step-1-configuring-webappdomain"></a>Step 1. Configuring <code>webapp.domain</code></h3>
+
+<p>In <code>services/webapp.json</code>:</p>
+
+<pre><code>{
+ "webapp": {
+ "domain": "user.example.org"
+ }
+}
+</code></pre>
+
+<h3><a name="step-2-putting-the-compiled-providerjson-in-place"></a>Step 2. Putting the compiled <code>provider.json</code> in place</h3>
+
+<p>Generate the compiled <code>provider.json</code>:</p>
+
+<pre><code>leap compile provider.json
+= created files/web/bootstrap/
+= created files/web/bootstrap/README
+= created files/web/bootstrap/production/
+= created files/web/bootstrap/production/provider.json
+= created files/web/bootstrap/production/htaccess
+= created files/web/bootstrap/staging/
+= created files/web/bootstrap/staging/provider.json
+= created files/web/bootstrap/staging/htaccess
+</code></pre>
+
+<p>This command compiles a separate <code>provider.json</code> for each environment, or &ldquo;default&rdquo; if you don&rsquo;t have an environment. In the example above, there is an environment called &ldquo;production&rdquo; and one called &ldquo;staging&rdquo;, but your setup will probably differ.</p>
+
+<p>The resulting <code>provider.json</code> file must then be put at the root URL of your <strong>provider domain</strong> for the appropriate environment.</p>
+
+<p>There is one additional complication: currently, the Bitmask client tests for compatibility using some HTTP headers on the <code>/provider.json</code> response. This is will hopefully change in the future, but for now you need to ensure the right headers are set in the response. The included file <code>htaccess</code> has example directives for Apache, if that is what you use.</p>
+
+<p>This step can be skipped if you happen to use the <code>static</code> service to deploy an <code>amber</code> powered static website to <strong>provider domain</strong>. In this case, the correct <code>provider.json</code> will be automatically put into place.</p>
+
+<h2><a name="integrating-with-existing-email-system"></a>Integrating with existing email system</h2>
+
+<p>If your <strong>mail domain</strong> already has users from a legacy email system, then things get a bit complicated. In order to be able to support both LEAP-powered email and legacy email on the same domain, you need to follow these steps:</p>
+
+<ol>
+<li>Modify the LEAP webapp so that it does not create users with the same name as users in the legacy system.</li>
+<li>Configure your legacy MX servers to forward mail that they cannot handle to the LEAP MX servers, or vice versa.</li>
+</ol>
+
+
+<h3><a name="step-1-modify-leap-webapp"></a>Step 1. Modify LEAP webapp</h3>
+
+<p>In order to modify the webapp to respect the usernames already reserved by your legacy system, you need to modify the LEAP webapp code. The easiest way to do this is to create a custom gem that modifies the behavior of the webapp.</p>
+
+<p>For this example, we will call our custom gem <code>reserve_usernames</code>.</p>
+
+<p>This gem can live in one of two places:</p>
+
+<p>(1) You can fork the project leap_web and put the gem in <code>leap_web/vendor/gems/reserve_usernames</code>. Then, modify <code>Gemfile</code> and add the line <code>gem 'common_languages', :path =&gt; 'vendor/gems/reserve_usernames'</code></p>
+
+<p>(2) Alternately, you can put the gem in the local provider directory <code>files/webapp/gems/reserve_username</code>. This will get synced to the webapp servers when you deploy and put in <code>/srv/leap/webapp/config/customization</code> where it will get automatically loaded by the webapp.</p>
+
+<p>What should the gem <code>reserve_usernames</code> look like? There is an example available here: <a href="https://leap.se/git/reserved_usernames.git">https://leap.se/git/reserved_usernames.git</a></p>
+
+<p>This example gem uses ActiveResource to communicate with a remote REST API for creating and checking username reservations. This ensures that both the legacy system and the LEAP system use the same namespace. Alternately, you could write a gem that checks the legacy database directly.</p>
+
+<h3><a name="step-2-configure-mx-servers"></a>Step 2. Configure MX servers</h3>
+
+<p>To be written.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/environments.html b/docs/en/guide/environments.html
new file mode 100644
index 00000000..db82302d
--- /dev/null
+++ b/docs/en/guide/environments.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Environments - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class='active level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Working with environments</h1>
+
+<div id='summary'>How to partition the nodes into separate environments.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="environments/index.html#assign-an-environment">Assign an environment</a>
+ </li>
+ <li>
+ <a href="environments/index.html#environment-commands">Environment commands</a>
+ </li>
+ <li>
+ <a href="environments/index.html#environment-specific-json-files">Environment specific JSON files</a>
+ </li>
+ <li>
+ <a href="environments/index.html#bind-an-environment-to-a-platform-version">Bind an environment to a Platform version</a>
+ </li>
+</ol></div>
+
+<p>With environments, you can divide your nodes into different and entirely separate sets. For example, you might have sets of nodes for &lsquo;testing&rsquo;, &lsquo;staging&rsquo; and &lsquo;production&rsquo;.</p>
+
+<p>Typically, the nodes in one environment are totally isolated from the nodes in a different environment. Each environment will have its own separate database, for example.</p>
+
+<p>There are a few exceptions to this rule: backup nodes, for example, will by default attempt to back up data from all the environments (excluding local).</p>
+
+<h2><a name="assign-an-environment"></a>Assign an environment</h2>
+
+<p>To assign an environment to a node, you just set the <code>environment</code> node property. This is typically done with tags, although it is not necessary. For example:</p>
+
+<p><code>tags/production.json</code></p>
+
+<pre><code>{
+ "environment": "production"
+}
+</code></pre>
+
+<p><code>nodes/mynode.json</code></p>
+
+<pre><code>{
+ "tags": ["production"]
+}
+</code></pre>
+
+<p>There are several built-in tags that will apply a value for the environment:</p>
+
+<ul>
+<li><code>production</code>: An environment for nodes that are in use by end users.</li>
+<li><code>development</code>: An environment to be used for nodes that are being used for experiments or staging.</li>
+<li><code>local</code>: This environment gets automatically applied to all nodes that run only on local VMs. Nodes with a <code>local</code> environment are treated special and excluded from certain calculations.</li>
+</ul>
+
+
+<p>You don&rsquo;t need to use these and you can add your own.</p>
+
+<h2><a name="environment-commands"></a>Environment commands</h2>
+
+<ul>
+<li><code>leap env</code> &ndash; List the available environments and disply which one is active.</li>
+<li><code>leap env pin ENV</code> &ndash; Pin the current environment to ENV.</li>
+<li><code>leap env unpin</code> &ndash; Remove the environment pin.</li>
+</ul>
+
+
+<p>The environment pin is only active for your local machine: it is not recorded in the provider directory and not shared with other users.</p>
+
+<h2><a name="environment-specific-json-files"></a>Environment specific JSON files</h2>
+
+<p>You can add JSON configuration files that are only applied when a specific environment is active. For example, if you create a file <code>provider.production.json</code>, these values will only get applied to the <code>provider.json</code> file for the <code>production</code> environment.</p>
+
+<p>This will also work for services and tags. For example:</p>
+
+<pre><code>provider.local.json
+services/webapp.development.json
+tags/seattle.production.json
+</code></pre>
+
+<p>In this example, <code>local</code>, <code>development</code>, and <code>production</code> are the names of environments.</p>
+
+<h2><a name="bind-an-environment-to-a-platform-version"></a>Bind an environment to a Platform version</h2>
+
+<p>If you want to ensure that a particular environment is bound to a particular version of the LEAP Platform, you can add a <code>platform</code> section to the <code>provider.ENV.json</code> file (where ENV is the name of the environment in question).</p>
+
+<p>The available options are <code>platform.version</code>, <code>platform.branch</code>, or <code>platform.commit</code>. For example:</p>
+
+<pre><code>{
+ "platform": {
+ "version": "1.6.1",
+ "branch": "develop",
+ "commit": "5df867fbd3a78ca4160eb54d708d55a7d047bdb2"
+ }
+}
+</code></pre>
+
+<p>You can use any combination of <code>version</code>, <code>branch</code>, and <code>commit</code> to specify the binding. The values for <code>branch</code> and <code>commit</code> only work if the <code>leap_platform</code> directory is a git repository.</p>
+
+<p>The value for <code>commit</code> is passed directly through to <code>git log</code> to query for a list of acceptable commits. See <a href="https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html#_specifying_ranges">man gitrevisions</a> to see how to specify ranges. For example:</p>
+
+<ul>
+<li><code>HEAD^..HEAD</code> - current commit must be head of the branch.</li>
+<li><code>3172444652af71bd771609d6b80258e70cc82ce9..HEAD</code> - current commit must be after 3172444652af71bd771609d6b80258e70cc82ce9.</li>
+<li><code>refs/tags/0.6.0rc1..refs/tags/0.6.0rc2</code> - current commit must be after tag 0.6.0rc1 and before or including tag 0.6.0rc2.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/environments/index.html b/docs/en/guide/environments/index.html
new file mode 100644
index 00000000..faeb6c6c
--- /dev/null
+++ b/docs/en/guide/environments/index.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Environments - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class='active level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Working with environments</h1>
+
+<div id='summary'>How to partition the nodes into separate environments.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#assign-an-environment">Assign an environment</a>
+ </li>
+ <li>
+ <a href="index.html#environment-commands">Environment commands</a>
+ </li>
+ <li>
+ <a href="index.html#environment-specific-json-files">Environment specific JSON files</a>
+ </li>
+ <li>
+ <a href="index.html#bind-an-environment-to-a-platform-version">Bind an environment to a Platform version</a>
+ </li>
+</ol></div>
+
+<p>With environments, you can divide your nodes into different and entirely separate sets. For example, you might have sets of nodes for &lsquo;testing&rsquo;, &lsquo;staging&rsquo; and &lsquo;production&rsquo;.</p>
+
+<p>Typically, the nodes in one environment are totally isolated from the nodes in a different environment. Each environment will have its own separate database, for example.</p>
+
+<p>There are a few exceptions to this rule: backup nodes, for example, will by default attempt to back up data from all the environments (excluding local).</p>
+
+<h2><a name="assign-an-environment"></a>Assign an environment</h2>
+
+<p>To assign an environment to a node, you just set the <code>environment</code> node property. This is typically done with tags, although it is not necessary. For example:</p>
+
+<p><code>tags/production.json</code></p>
+
+<pre><code>{
+ "environment": "production"
+}
+</code></pre>
+
+<p><code>nodes/mynode.json</code></p>
+
+<pre><code>{
+ "tags": ["production"]
+}
+</code></pre>
+
+<p>There are several built-in tags that will apply a value for the environment:</p>
+
+<ul>
+<li><code>production</code>: An environment for nodes that are in use by end users.</li>
+<li><code>development</code>: An environment to be used for nodes that are being used for experiments or staging.</li>
+<li><code>local</code>: This environment gets automatically applied to all nodes that run only on local VMs. Nodes with a <code>local</code> environment are treated special and excluded from certain calculations.</li>
+</ul>
+
+
+<p>You don&rsquo;t need to use these and you can add your own.</p>
+
+<h2><a name="environment-commands"></a>Environment commands</h2>
+
+<ul>
+<li><code>leap env</code> &ndash; List the available environments and disply which one is active.</li>
+<li><code>leap env pin ENV</code> &ndash; Pin the current environment to ENV.</li>
+<li><code>leap env unpin</code> &ndash; Remove the environment pin.</li>
+</ul>
+
+
+<p>The environment pin is only active for your local machine: it is not recorded in the provider directory and not shared with other users.</p>
+
+<h2><a name="environment-specific-json-files"></a>Environment specific JSON files</h2>
+
+<p>You can add JSON configuration files that are only applied when a specific environment is active. For example, if you create a file <code>provider.production.json</code>, these values will only get applied to the <code>provider.json</code> file for the <code>production</code> environment.</p>
+
+<p>This will also work for services and tags. For example:</p>
+
+<pre><code>provider.local.json
+services/webapp.development.json
+tags/seattle.production.json
+</code></pre>
+
+<p>In this example, <code>local</code>, <code>development</code>, and <code>production</code> are the names of environments.</p>
+
+<h2><a name="bind-an-environment-to-a-platform-version"></a>Bind an environment to a Platform version</h2>
+
+<p>If you want to ensure that a particular environment is bound to a particular version of the LEAP Platform, you can add a <code>platform</code> section to the <code>provider.ENV.json</code> file (where ENV is the name of the environment in question).</p>
+
+<p>The available options are <code>platform.version</code>, <code>platform.branch</code>, or <code>platform.commit</code>. For example:</p>
+
+<pre><code>{
+ "platform": {
+ "version": "1.6.1",
+ "branch": "develop",
+ "commit": "5df867fbd3a78ca4160eb54d708d55a7d047bdb2"
+ }
+}
+</code></pre>
+
+<p>You can use any combination of <code>version</code>, <code>branch</code>, and <code>commit</code> to specify the binding. The values for <code>branch</code> and <code>commit</code> only work if the <code>leap_platform</code> directory is a git repository.</p>
+
+<p>The value for <code>commit</code> is passed directly through to <code>git log</code> to query for a list of acceptable commits. See <a href="https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html#_specifying_ranges">man gitrevisions</a> to see how to specify ranges. For example:</p>
+
+<ul>
+<li><code>HEAD^..HEAD</code> - current commit must be head of the branch.</li>
+<li><code>3172444652af71bd771609d6b80258e70cc82ce9..HEAD</code> - current commit must be after 3172444652af71bd771609d6b80258e70cc82ce9.</li>
+<li><code>refs/tags/0.6.0rc1..refs/tags/0.6.0rc2</code> - current commit must be after tag 0.6.0rc1 and before or including tag 0.6.0rc2.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/getting-started.html b/docs/en/guide/getting-started.html
new file mode 100644
index 00000000..b1274e14
--- /dev/null
+++ b/docs/en/guide/getting-started.html
@@ -0,0 +1,317 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Getting Started - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class='active level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Getting Started</h1>
+
+<div id='summary'>An overview of the LEAP Platform</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="getting-started/index.html#sensitive-files">Sensitive files</a>
+ </li>
+ <li>
+ <a href="getting-started/index.html#useful-commands">Useful commands</a>
+ </li>
+ <li>
+ <a href="getting-started/index.html#node-filters">Node filters</a>
+ </li>
+ <li>
+ <a href="getting-started/index.html#tracking-the-provider-directory-in-git">Tracking the provider directory in git</a>
+ </li>
+ <li>
+ <a href="getting-started/index.html#editing-json-configuration-files">Editing JSON configuration files</a>
+ </li>
+ <li>
+ <a href="getting-started/index.html#how-does-it-work-under-the-hood">How does it work under the hood?</a>
+ </li>
+</ol></div>
+
+<h2><a name="sensitive-files"></a>Sensitive files</h2>
+
+<p>Some files in your provider directory are very sensitive. Leaking these files will compromise your provider.</p>
+
+<p>Super sensitive and irreplaceable:</p>
+
+<ul>
+<li><code>files/ca/*.key</code> &ndash; the private keys for the client and server CAs.</li>
+<li><code>files/cert/*.key</code> &ndash; the private key(s) for the commercial certificate for your domain(s).</li>
+</ul>
+
+
+<p>Sensitive, but can be erased and regenerated automatically:</p>
+
+<ul>
+<li><code>secrets.json</code> &ndash; various random secrets, such as passwords for databases.</li>
+<li><code>files/nodes/*/*.key</code> &ndash; the private key for each node.</li>
+<li><code>hiera/*.yaml</code> &ndash; hiera file contains a copy of the private key of the node.</li>
+</ul>
+
+
+<p>Also, each sysadmin has one or more public ssh keys in <code>users/*/*_ssh.pub</code>. Typically, you will want to keep these public keys secure as well.</p>
+
+<p>See <a href="keys-and-certificates.html">Keys and Certificates</a> for more information.</p>
+
+<h2><a name="useful-commands"></a>Useful commands</h2>
+
+<p>Here are a few useful <code>leap</code> commands:</p>
+
+<ul>
+<li><code>leap help [COMMAND]</code> &ndash; get help on COMMAND.</li>
+<li><code>leap history [FILTER]</code> &ndash; show the recent deployment history for the selected nodes.</li>
+<li><code>leap ssh web1</code> &ndash; SSH into node web1 (requires <code>leap node init web1</code> first).</li>
+<li><code>leap list [FILTER]</code> &ndash; list the selected nodes.
+
+<ul>
+<li><code>leap list production</code> &ndash; list only those nodes with the tag &lsquo;production&rsquo;</li>
+<li><code>leap list --print ip_address</code> &ndash; list a particular attribute of all nodes.</li>
+</ul>
+</li>
+</ul>
+
+
+<p>See the full <a href="commands.html">Command Line Reference</a> for more information.</p>
+
+<h2><a name="node-filters"></a>Node filters</h2>
+
+<p>Many of the <code>leap</code> commands take a &ldquo;node filter&rdquo;. You can use a node filter to target a command at one or more nodes.</p>
+
+<p>A node filter consists of one or more keywords, with an optional &ldquo;+&rdquo; before each keyword.</p>
+
+<ul>
+<li>keywords can be a node name, a service type, or a tag.</li>
+<li>the &ldquo;+&rdquo; before the keyword constructs an AND condition</li>
+<li>otherwise, multiple keywords together construct an OR condition</li>
+</ul>
+
+
+<p>Examples:</p>
+
+<ul>
+<li><code>leap list openvpn</code> &ndash; list all nodes with service openvpn.</li>
+<li><code>leap list openvpn +production</code> &ndash; only nodes of service type openvpn AND tag production.</li>
+<li><code>leap deploy webapp openvpn</code> &ndash; deploy to all webapp OR openvpn nodes.</li>
+<li><code>leap node init ostrich</code> &ndash; just init the node named ostrich.</li>
+</ul>
+
+
+<p>See the full <a href="commands.html">Command Line Reference</a> for more information.</p>
+
+<h2><a name="tracking-the-provider-directory-in-git"></a>Tracking the provider directory in git</h2>
+
+<p>You should commit your provider changes to your favorite VCS whenever things change. This way you can share your configurations with other admins, all they have to do is to pull the changes to stay up to date. Every time you make a change to your provider, such as adding nodes, services, generating certificates, etc. you should add those to your VCS, commit them and push them to where your repository is hosted.</p>
+
+<p>Note that your provider directory contains secrets, such as private key material and passwords. You do not want to have those passwords readable by the world, so make sure that wherever you are hosting your repository, it is not public for the world to read.</p>
+
+<p>If you have a post-commit hook that emails the changes to contributors, you may want to exclude diffs for files that might have sensitive secrets. For example, create a <code>.gitattributes</code> file with:</p>
+
+<pre><code># No diff, no email for key files
+*.key -diff
+*.pem -diff
+
+# Discard diff for secrets.json
+secrets.json -diff
+
+# No diff for hiera files, they contain passwords
+hiera/* -diff
+</code></pre>
+
+<h2><a name="editing-json-configuration-files"></a>Editing JSON configuration files</h2>
+
+<p>All the settings that compose your provider are stored in JSON files.</p>
+
+<p>At a minimum, you will need at least two configuration files:</p>
+
+<ul>
+<li><code>provider.json</code> &ndash; general settings for you provider.</li>
+<li><code>nodes/NAME.json</code> &ndash; configuration file for node called &ldquo;NAME&rdquo;.</li>
+</ul>
+
+
+<p>There are a few required properties in provider.json:</p>
+
+<pre><code>{
+ "domain": "example.org",
+ "name": "Example",
+ "contacts": {
+ "default": "email1@example.org"
+ }
+}
+</code></pre>
+
+<p>See <a href="provider-configuration.html">Provider Configuration</a> for more details.</p>
+
+<p>For node configuration files, there are two required properties:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["openvpn"]
+}
+</code></pre>
+
+<p>See <a href="../services.html">Services</a> for details on what servers are available, and see <a href="config.html">Configuration Files</a> details on how configuration files work.</p>
+
+<h2><a name="how-does-it-work-under-the-hood"></a>How does it work under the hood?</h2>
+
+<p>You don&rsquo;t need to know any of the details of what happens &ldquo;under the hood&rdquo; in order to use the LEAP platform. However, if you are curious as to what is going on, here is a quick primer.</p>
+
+<p>First, some background terminology:</p>
+
+<ul>
+<li><strong>puppet</strong>: Puppet is a system for automating deployment and management of servers (called nodes).</li>
+<li><strong>hiera files</strong>: In puppet, you can use something called a &lsquo;hiera file&rsquo; to seed a node with a few configuration values. In LEAP, we go all out and put <em>every</em> configuration value needed for a node in the hiera file, and automatically compile a custom hiera file for each node.</li>
+</ul>
+
+
+<p>When you run <code>leap deploy</code>, a bunch of things happen, in this order:</p>
+
+<ol>
+<li><strong>Compile hiera files</strong>: The hiera configuration file for each node is compiled in YAML format and saved in the directory <code>hiera</code>. The source material for this hiera file consists of all the JSON configuration files imported or inherited by the node&rsquo;s JSON config file.</li>
+<li><strong>Copy required files to node</strong>: All the files needed for puppet to run are rsync'ed to each node. This includes the entire leap_platform directory, as well as the node&rsquo;s hiera file and other files needed by puppet to set up the node (keys, binary files, etc).</li>
+<li><strong>Puppet is run</strong>: Once the node is ready, leap connects to the node via ssh and runs <code>puppet apply</code>. Puppet is applied locally on the node, without a daemon or puppetmaster.</li>
+</ol>
+
+
+<p>You can run <code>leap -v2 deploy</code> to see exactly what commands are being executed.</p>
+
+<p>This mode of operation is fundamentally different from how puppet is normally used:</p>
+
+<ul>
+<li>There is no puppetmaster that all the servers take orders from, and there is no puppetd running in the background.</li>
+<li>Servers cannot dynamically query the puppetmaster for information about the other servers.</li>
+<li>There is a static representation for the state of every server that can be committed to git.</li>
+</ul>
+
+
+<p>There are advantages and disadvantages to the model that LEAP uses. We have found it very useful for our goal of having a common LEAP platform that many different providers can all use while still allowing providers to configure their unique infrastructure.</p>
+
+<p>We also find it very beneficial to be able to track the state of your infrastructure in git.</p>
+
+<p>Traditional system configuration automation systems, like <a href="https://puppetlabs.com/puppet/puppet-open-source/">Puppet</a> or <a href="http://www.opscode.com/chef/">Chef</a>, deploy changes to servers using a pull method. Each server pulls a manifest from a central master server and uses this to alter the state of the server.</p>
+
+<p>Instead, the <code>leap</code> tool uses a masterless push method: The sysadmin runs <code>leap deploy</code> from the provider instance directory on their desktop machine to push the changes out to every server (or a subset of servers). LEAP still uses Puppet, but there is no central master server that each node must pull from.</p>
+
+<p>One other significant difference between LEAP and typical system automation is how interactions among servers are handled. Rather than store a central database of information about each server that can be queried when a recipe is applied, the <code>leap</code> command compiles static representation of all the information a particular server will need in order to apply the recipes. In compiling this static representation, <code>leap</code> can use arbitrary programming logic to query and manipulate information about other servers.</p>
+
+<p>These two approaches, masterless push and pre-compiled static configuration, allow the sysadmin to manage a set of LEAP servers using traditional software development techniques of branching and merging, to more easily create local testing environments using virtual servers, and to deploy without the added complexity and failure potential of a master server.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/getting-started/index.html b/docs/en/guide/getting-started/index.html
new file mode 100644
index 00000000..c9457ddd
--- /dev/null
+++ b/docs/en/guide/getting-started/index.html
@@ -0,0 +1,317 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Getting Started - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class='active level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Getting Started</h1>
+
+<div id='summary'>An overview of the LEAP Platform</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#sensitive-files">Sensitive files</a>
+ </li>
+ <li>
+ <a href="index.html#useful-commands">Useful commands</a>
+ </li>
+ <li>
+ <a href="index.html#node-filters">Node filters</a>
+ </li>
+ <li>
+ <a href="index.html#tracking-the-provider-directory-in-git">Tracking the provider directory in git</a>
+ </li>
+ <li>
+ <a href="index.html#editing-json-configuration-files">Editing JSON configuration files</a>
+ </li>
+ <li>
+ <a href="index.html#how-does-it-work-under-the-hood">How does it work under the hood?</a>
+ </li>
+</ol></div>
+
+<h2><a name="sensitive-files"></a>Sensitive files</h2>
+
+<p>Some files in your provider directory are very sensitive. Leaking these files will compromise your provider.</p>
+
+<p>Super sensitive and irreplaceable:</p>
+
+<ul>
+<li><code>files/ca/*.key</code> &ndash; the private keys for the client and server CAs.</li>
+<li><code>files/cert/*.key</code> &ndash; the private key(s) for the commercial certificate for your domain(s).</li>
+</ul>
+
+
+<p>Sensitive, but can be erased and regenerated automatically:</p>
+
+<ul>
+<li><code>secrets.json</code> &ndash; various random secrets, such as passwords for databases.</li>
+<li><code>files/nodes/*/*.key</code> &ndash; the private key for each node.</li>
+<li><code>hiera/*.yaml</code> &ndash; hiera file contains a copy of the private key of the node.</li>
+</ul>
+
+
+<p>Also, each sysadmin has one or more public ssh keys in <code>users/*/*_ssh.pub</code>. Typically, you will want to keep these public keys secure as well.</p>
+
+<p>See <a href="../keys-and-certificates.html">Keys and Certificates</a> for more information.</p>
+
+<h2><a name="useful-commands"></a>Useful commands</h2>
+
+<p>Here are a few useful <code>leap</code> commands:</p>
+
+<ul>
+<li><code>leap help [COMMAND]</code> &ndash; get help on COMMAND.</li>
+<li><code>leap history [FILTER]</code> &ndash; show the recent deployment history for the selected nodes.</li>
+<li><code>leap ssh web1</code> &ndash; SSH into node web1 (requires <code>leap node init web1</code> first).</li>
+<li><code>leap list [FILTER]</code> &ndash; list the selected nodes.
+
+<ul>
+<li><code>leap list production</code> &ndash; list only those nodes with the tag &lsquo;production&rsquo;</li>
+<li><code>leap list --print ip_address</code> &ndash; list a particular attribute of all nodes.</li>
+</ul>
+</li>
+</ul>
+
+
+<p>See the full <a href="../commands.html">Command Line Reference</a> for more information.</p>
+
+<h2><a name="node-filters"></a>Node filters</h2>
+
+<p>Many of the <code>leap</code> commands take a &ldquo;node filter&rdquo;. You can use a node filter to target a command at one or more nodes.</p>
+
+<p>A node filter consists of one or more keywords, with an optional &ldquo;+&rdquo; before each keyword.</p>
+
+<ul>
+<li>keywords can be a node name, a service type, or a tag.</li>
+<li>the &ldquo;+&rdquo; before the keyword constructs an AND condition</li>
+<li>otherwise, multiple keywords together construct an OR condition</li>
+</ul>
+
+
+<p>Examples:</p>
+
+<ul>
+<li><code>leap list openvpn</code> &ndash; list all nodes with service openvpn.</li>
+<li><code>leap list openvpn +production</code> &ndash; only nodes of service type openvpn AND tag production.</li>
+<li><code>leap deploy webapp openvpn</code> &ndash; deploy to all webapp OR openvpn nodes.</li>
+<li><code>leap node init ostrich</code> &ndash; just init the node named ostrich.</li>
+</ul>
+
+
+<p>See the full <a href="../commands.html">Command Line Reference</a> for more information.</p>
+
+<h2><a name="tracking-the-provider-directory-in-git"></a>Tracking the provider directory in git</h2>
+
+<p>You should commit your provider changes to your favorite VCS whenever things change. This way you can share your configurations with other admins, all they have to do is to pull the changes to stay up to date. Every time you make a change to your provider, such as adding nodes, services, generating certificates, etc. you should add those to your VCS, commit them and push them to where your repository is hosted.</p>
+
+<p>Note that your provider directory contains secrets, such as private key material and passwords. You do not want to have those passwords readable by the world, so make sure that wherever you are hosting your repository, it is not public for the world to read.</p>
+
+<p>If you have a post-commit hook that emails the changes to contributors, you may want to exclude diffs for files that might have sensitive secrets. For example, create a <code>.gitattributes</code> file with:</p>
+
+<pre><code># No diff, no email for key files
+*.key -diff
+*.pem -diff
+
+# Discard diff for secrets.json
+secrets.json -diff
+
+# No diff for hiera files, they contain passwords
+hiera/* -diff
+</code></pre>
+
+<h2><a name="editing-json-configuration-files"></a>Editing JSON configuration files</h2>
+
+<p>All the settings that compose your provider are stored in JSON files.</p>
+
+<p>At a minimum, you will need at least two configuration files:</p>
+
+<ul>
+<li><code>provider.json</code> &ndash; general settings for you provider.</li>
+<li><code>nodes/NAME.json</code> &ndash; configuration file for node called &ldquo;NAME&rdquo;.</li>
+</ul>
+
+
+<p>There are a few required properties in provider.json:</p>
+
+<pre><code>{
+ "domain": "example.org",
+ "name": "Example",
+ "contacts": {
+ "default": "email1@example.org"
+ }
+}
+</code></pre>
+
+<p>See <a href="../provider-configuration.html">Provider Configuration</a> for more details.</p>
+
+<p>For node configuration files, there are two required properties:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["openvpn"]
+}
+</code></pre>
+
+<p>See <a href="../../services.html">Services</a> for details on what servers are available, and see <a href="../config.html">Configuration Files</a> details on how configuration files work.</p>
+
+<h2><a name="how-does-it-work-under-the-hood"></a>How does it work under the hood?</h2>
+
+<p>You don&rsquo;t need to know any of the details of what happens &ldquo;under the hood&rdquo; in order to use the LEAP platform. However, if you are curious as to what is going on, here is a quick primer.</p>
+
+<p>First, some background terminology:</p>
+
+<ul>
+<li><strong>puppet</strong>: Puppet is a system for automating deployment and management of servers (called nodes).</li>
+<li><strong>hiera files</strong>: In puppet, you can use something called a &lsquo;hiera file&rsquo; to seed a node with a few configuration values. In LEAP, we go all out and put <em>every</em> configuration value needed for a node in the hiera file, and automatically compile a custom hiera file for each node.</li>
+</ul>
+
+
+<p>When you run <code>leap deploy</code>, a bunch of things happen, in this order:</p>
+
+<ol>
+<li><strong>Compile hiera files</strong>: The hiera configuration file for each node is compiled in YAML format and saved in the directory <code>hiera</code>. The source material for this hiera file consists of all the JSON configuration files imported or inherited by the node&rsquo;s JSON config file.</li>
+<li><strong>Copy required files to node</strong>: All the files needed for puppet to run are rsync'ed to each node. This includes the entire leap_platform directory, as well as the node&rsquo;s hiera file and other files needed by puppet to set up the node (keys, binary files, etc).</li>
+<li><strong>Puppet is run</strong>: Once the node is ready, leap connects to the node via ssh and runs <code>puppet apply</code>. Puppet is applied locally on the node, without a daemon or puppetmaster.</li>
+</ol>
+
+
+<p>You can run <code>leap -v2 deploy</code> to see exactly what commands are being executed.</p>
+
+<p>This mode of operation is fundamentally different from how puppet is normally used:</p>
+
+<ul>
+<li>There is no puppetmaster that all the servers take orders from, and there is no puppetd running in the background.</li>
+<li>Servers cannot dynamically query the puppetmaster for information about the other servers.</li>
+<li>There is a static representation for the state of every server that can be committed to git.</li>
+</ul>
+
+
+<p>There are advantages and disadvantages to the model that LEAP uses. We have found it very useful for our goal of having a common LEAP platform that many different providers can all use while still allowing providers to configure their unique infrastructure.</p>
+
+<p>We also find it very beneficial to be able to track the state of your infrastructure in git.</p>
+
+<p>Traditional system configuration automation systems, like <a href="https://puppetlabs.com/puppet/puppet-open-source/">Puppet</a> or <a href="http://www.opscode.com/chef/">Chef</a>, deploy changes to servers using a pull method. Each server pulls a manifest from a central master server and uses this to alter the state of the server.</p>
+
+<p>Instead, the <code>leap</code> tool uses a masterless push method: The sysadmin runs <code>leap deploy</code> from the provider instance directory on their desktop machine to push the changes out to every server (or a subset of servers). LEAP still uses Puppet, but there is no central master server that each node must pull from.</p>
+
+<p>One other significant difference between LEAP and typical system automation is how interactions among servers are handled. Rather than store a central database of information about each server that can be queried when a recipe is applied, the <code>leap</code> command compiles static representation of all the information a particular server will need in order to apply the recipes. In compiling this static representation, <code>leap</code> can use arbitrary programming logic to query and manipulate information about other servers.</p>
+
+<p>These two approaches, masterless push and pre-compiled static configuration, allow the sysadmin to manage a set of LEAP servers using traditional software development techniques of branching and merging, to more easily create local testing environments using virtual servers, and to deploy without the added complexity and failure potential of a master server.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/keys-and-certificates.html b/docs/en/guide/keys-and-certificates.html
new file mode 100644
index 00000000..ee7d2699
--- /dev/null
+++ b/docs/en/guide/keys-and-certificates.html
@@ -0,0 +1,480 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Keys and Certificates - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class='active level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Keys and Certificates</h1>
+
+<div id='summary'>Working with SSH keys, secrets, and X.509 certificates.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="keys-and-certificates/index.html#working-with-ssh">Working with SSH</a>
+ <ol>
+ <li>
+ <a href="keys-and-certificates/index.html#ssh-related-files">SSH related files</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#ssh-and-local-nodes">SSH and local nodes</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#to-upgrade-a-ssh-host-key">To upgrade a SSH host key</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#when-ssh-host-key-changes">When SSH host key changes</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#changing-the-ssh-port">Changing the SSH port</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#sysadmins-with-multiple-ssh-keys">Sysadmins with multiple SSH keys</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#removing-sysadmin-access">Removing sysadmin access</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#x509-certificates">X.509 Certificates</a>
+ <ol>
+ <li>
+ <a href="keys-and-certificates/index.html#configuration-options">Configuration options</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#certificate-authorities">Certificate Authorities</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#server-certificates">Server certificates</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#client-certificates">Client certificates</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#commercial-certificates">Commercial certificates</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#examine-certs">Examine Certs</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#lets-encrypt-certificate">Let’s Encrypt certificate</a>
+ <ol>
+ <li>
+ <a href="keys-and-certificates/index.html#install-the-official-acme-client">Install the official acme client</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#fetch-cert">Fetch cert</a>
+ </li>
+ <li>
+ <a href="keys-and-certificates/index.html#deploy-the-certs">Deploy the certs</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="working-with-ssh"></a>Working with SSH</h1>
+
+<p>Whenever the <code>leap</code> command needs to push changes to a node or gather information from a node, it tunnels this command over SSH. Another way to put this: the security of your servers rests entirely on SSH. Because of this, it is important that you understand how <code>leap</code> uses SSH.</p>
+
+<h2><a name="ssh-related-files"></a>SSH related files</h2>
+
+<p>Assuming your provider directory is called &lsquo;provider&rsquo;:</p>
+
+<ul>
+<li><code>provider/nodes/crow/crow_ssh.pub</code> &ndash; The public SSH host key for node &lsquo;crow&rsquo;.</li>
+<li><code>provider/users/alice/alice_ssh.pub</code> &ndash; The public SSH user key for user &lsquo;alice&rsquo;. Anyone with the private key that corresponds to this public key will have root access to all nodes.</li>
+<li><code>provider/files/ssh/known_hosts</code> &ndash; An autogenerated known_hosts, built from combining <code>provider/nodes/*/*_ssh.pub</code>. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate <code>known_hosts</code> and then run <code>leap compile</code>.</li>
+<li><code>provider/files/ssh/authorized_keys</code> &ndash; An autogenerated list of all the user SSH keys with root access to the notes. It is created from <code>provider/users/*/*_ssh.pub</code>. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate <code>authorized_keys</code> and then run <code>leap compile</code>.</li>
+</ul>
+
+
+<p>All of these files should be committed to source control.</p>
+
+<p>If you rename, remove, or add a node with <code>leap node [mv|add|rm]</code> the SSH key files and the <code>known_hosts</code> file will get properly updated.</p>
+
+<h2><a name="ssh-and-local-nodes"></a>SSH and local nodes</h2>
+
+<p>Local nodes are run as Vagrant virtual machines. The <code>leap</code> command handles SSH slightly differently for these nodes.</p>
+
+<p>Basically, all the SSH security is turned off for local nodes. Since local nodes only exist for a short time on your computer and can&rsquo;t be reached from the internet, this is not a problem.</p>
+
+<p>Specifically, for local nodes:</p>
+
+<ol>
+<li><code>known_hosts</code> is never updated with local node keys, since the SSH public key of a local node is different for each user.</li>
+<li><code>leap</code> entirely skips the checking of host keys when connecting with a local node.</li>
+<li><code>leap</code> adds the public Vagrant SSH key to the list of SSH keys for a user. The public Vagrant SSH key is a shared and insecure key that has root access to most Vagrant virtual machines.</li>
+</ol>
+
+
+<h2><a name="to-upgrade-a-ssh-host-key"></a>To upgrade a SSH host key</h2>
+
+<p>Most servers will have more than one SSH host key. Sometimes, the server will have a better SSH host key than the one you have on file. In order to upgrade to the better SSH host key, simply re-run the init command:</p>
+
+<pre><code>workstation$ leap node init NODE_NAME
+</code></pre>
+
+<p>This will prompt you if you want to upgrade the SSH host key, but only if <code>leap</code> thinks that an upgrade is advisable.</p>
+
+<h2><a name="when-ssh-host-key-changes"></a>When SSH host key changes</h2>
+
+<p>If the host key for a node has changed, you will get an error &ldquo;WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED&rdquo;.</p>
+
+<p>To fix this, you need to remove the file <code>files/nodes/stompy/stompy_ssh.pub</code> and run <code>leap node init stompy</code>, where the node&rsquo;s name is &lsquo;stompy&rsquo;. <strong>Only do this if you are ABSOLUTELY CERTAIN that the node&rsquo;s SSH host key has changed</strong>.</p>
+
+<h2><a name="changing-the-ssh-port"></a>Changing the SSH port</h2>
+
+<p>Suppose you have a node <code>blinky</code> that has SSH listening on port 22 and you want to make it port 2200.</p>
+
+<p>First, modify the configuration for <code>blinky</code> to specify the variable <code>ssh.port</code> as 2200. Usually, this is done in <code>common.json</code> or in a tag file.</p>
+
+<p>For example, you could put this in <code>tags/production.json</code>:</p>
+
+<pre><code>{
+ "ssh": {
+ "port": 2200
+ }
+}
+</code></pre>
+
+<p>Run <code>leap compile</code> and open <code>hiera/blinky.yaml</code> to confirm that <code>ssh.port</code> is set to 2200. The port number must be specified as a number, not a string (no quotes).</p>
+
+<p>Then, you need to deploy this change so that SSH will bind to 2200. You cannot simply run <code>leap deploy blinky</code> because this command will default to using the variable <code>ssh.port</code> which is now <code>2200</code> but SSH on the node is still bound to 22.</p>
+
+<p>So, you manually override the port in the deploy command, using the old port:</p>
+
+<pre><code>leap deploy --port 22 blinky
+</code></pre>
+
+<p>Afterwards, SSH on <code>blinky</code> should be listening on port 2200 and you can just run <code>leap deploy blinky</code> from then on.</p>
+
+<h2><a name="sysadmins-with-multiple-ssh-keys"></a>Sysadmins with multiple SSH keys</h2>
+
+<p>The command <code>leap add-user --self</code> allows only one SSH key. If you want to specify more than one key for a user, you can do it manually:</p>
+
+<pre><code>users/userx/userx_ssh.pub
+users/userx/otherkey_ssh.pub
+</code></pre>
+
+<p>All keys matching &lsquo;userx/*_ssh.pub&rsquo; will be usable.</p>
+
+<h2><a name="removing-sysadmin-access"></a>Removing sysadmin access</h2>
+
+<p>Suppose you want to remove <code>userx</code> from having any further SSH access to the servers. Do this:</p>
+
+<pre><code>rm -r users/userx
+leap deploy
+</code></pre>
+
+<h1><a name="x509-certificates"></a>X.509 Certificates</h1>
+
+<h2><a name="configuration-options"></a>Configuration options</h2>
+
+<p>The <code>ca</code> option in provider.json provides settings used when generating CAs and certificates. The defaults are as follows:</p>
+
+<pre><code>{
+ "ca": {
+ "name": "= global.provider.ca.organization + ' Root CA'",
+ "organization": "= global.provider.name[global.provider.default_language]",
+ "organizational_unit": "= 'https://' + global.provider.domain",
+ "bit_size": 4096,
+ "digest": "SHA256",
+ "life_span": "10y",
+ "server_certificates": {
+ "bit_size": 2048,
+ "digest": "SHA256",
+ "life_span": "1y"
+ },
+ "client_certificates": {
+ "bit_size": 2048,
+ "digest": "SHA256",
+ "life_span": "2m",
+ "limited_prefix": "LIMITED",
+ "unlimited_prefix": "UNLIMITED"
+ }
+ }
+}
+</code></pre>
+
+<p>You should not need to override these defaults in your own provider.json, but you can if you want to. To see what values are used for your provider, run <code>leap inspect provider.json</code>.</p>
+
+<p>NOTE: A certificate <code>bit_size</code> greater than 2048 will probably not be recognized by most commercial CAs.</p>
+
+<h2><a name="certificate-authorities"></a>Certificate Authorities</h2>
+
+<p>There are three x.509 certificate authorities (CA) associated with your provider:</p>
+
+<ol>
+<li><strong>Commercial CA:</strong> It is strongly recommended that you purchase a commercial cert for your primary domain. The goal of platform is to not depend on the commercial CA system, but it does increase security and usability if you purchase a certificate. The cert for the commercial CA must live at <code>files/cert/commercial_ca.crt</code>.</li>
+<li><strong>Server CA:</strong> This is a self-signed CA responsible for signing all the <strong>server</strong> certificates. The private key lives at <code>files/ca/ca.key</code> and the public cert lives at <code>files/ca/ca.crt</code>. The key is very sensitive information and must be kept private. The public cert is distributed publicly.</li>
+<li><strong>Client CA:</strong> This is a self-signed CA responsible for signing all the <strong>client</strong> certificates. The private key lives at <code>files/ca/client_ca.key</code> and the public cert lives at <code>files/ca/client_ca.crt</code>. Neither file is distribute publicly. It is not a big deal if the private key for the client CA is compromised, you can just generate a new one and re-deploy.</li>
+</ol>
+
+
+<p>To generate both the Server CA and the Client CA, run the command:</p>
+
+<pre><code>leap cert ca
+</code></pre>
+
+<h2><a name="server-certificates"></a>Server certificates</h2>
+
+<p>Most every server in your service provider will have a x.509 certificate, generated by the <code>leap</code> command using the Server CA. Whenever you modify any settings of a node that might affect it&rsquo;s certificate (like changing the IP address, hostname, or settings in provider.json), you can magically regenerate all the certs that need to be regenerated with this command:</p>
+
+<pre><code>leap cert update
+</code></pre>
+
+<p>Run <code>leap help cert update</code> for notes on usage options.</p>
+
+<p>Because the server certificates are generated locally on your personal machine, the private key for the Server CA need never be put on any server. It is up to you to keep this file secure.</p>
+
+<h2><a name="client-certificates"></a>Client certificates</h2>
+
+<p>Every leap client gets its own time-limited client certificate. This cert is use to connect to the OpenVPN gateway (and probably other things in the future). It is generated on the fly by the webapp using the Client CA.</p>
+
+<p>To make this work, the private key of the Client CA is made available to the webapp. This might seem bad, but compromise of the Client CA simply allows the attacker to use the OpenVPN gateways without paying. In the future, we plan to add a command to automatically regenerate the Client CA periodically.</p>
+
+<p>There are two types of client certificates: limited and unlimited. A client using a limited cert will have its bandwidth limited to the rate specified by <code>provider.service.bandwidth_limit</code> (in Bytes per second). An unlimited cert is given to the user if they authenticate and the user&rsquo;s service level matches one configured in <code>provider.service.levels</code> without bandwidth limits. Otherwise, the user is given a limited client cert.</p>
+
+<h2><a name="commercial-certificates"></a>Commercial certificates</h2>
+
+<p>We strongly recommend that you use a commercial signed server certificate for your primary domain (in other words, a certificate with a common name matching whatever you have configured for <code>provider.domain</code>). This provides several benefits:</p>
+
+<ol>
+<li>When users visit your website, they don&rsquo;t get a scary notice that something is wrong.</li>
+<li>When a user runs the LEAP client, selecting your service provider will not cause a warning message.</li>
+<li>When other providers first discover your provider, they are more likely to trust your provider key if it is fetched over a commercially verified link.</li>
+</ol>
+
+
+<p>The LEAP platform is designed so that it assumes you are using a commercial cert for the primary domain of your provider, but all other servers are assumed to use non-commercial certs signed by the Server CA you create.</p>
+
+<p>To generate a CSR, run:</p>
+
+<pre><code>leap cert csr
+</code></pre>
+
+<p>This command will generate the CSR and private key matching <code>provider.domain</code> (you can change the domain with <code>--domain=DOMAIN</code> switch). It also generates a server certificate signed with the Server CA. You should delete this certificate and replace it with a real one once it is created by your commercial CA.</p>
+
+<p>The related commercial cert files are:</p>
+
+<pre><code>files/
+ cert/
+ domain.org.crt # Server certificate for domain.org, obtained by commercial CA.
+ domain.org.csr # Certificate signing request
+ domain.org.key # Private key for you certificate
+ commercial_ca.crt # The CA cert obtained from the commercial CA.
+</code></pre>
+
+<p>The private key file is extremely sensitive and care should be taken with its provenance.</p>
+
+<p>If your commercial CA has a chained CA cert, you should be OK if you just put the <strong>last</strong> cert in the chain into the <code>commercial_ca.crt</code> file. This only works if the other CAs in the chain have certs in the debian package <code>ca-certificates</code>, which is the case for almost all CAs.</p>
+
+<p>If you want to add additional fields to the CSR, like country, city, or locality, you can configure these values in provider.json like so:</p>
+
+<pre><code> "ca": {
+ "server_certificates": {
+ "country": "US",
+ "state": "Washington",
+ "locality": "Seattle"
+ }
+ }
+</code></pre>
+
+<p>If they are not present, the CSR will be created without them.</p>
+
+<h2><a name="examine-certs"></a>Examine Certs</h2>
+
+<p>To see details about the keys and certs you can use <code>leap inspect</code> like so:</p>
+
+<pre><code>$ leap inspect files/ca/ca.crt
+</code></pre>
+
+<h1><a name="lets-encrypt-certificate"></a>Let’s Encrypt certificate</h1>
+
+<p>LEAP plans to integrate <a href="https://letsencrypt.org/">Let&rsquo;s Encrypt</a> support, so it will be even easier to receive X.509 certificates that are accepted by all browsers.
+Until we achieve this, here&rsquo;s a guide how to do this manually.</p>
+
+<h2><a name="install-the-official-acme-client"></a>Install the official acme client</h2>
+
+<p>Log in to your webapp node</p>
+
+<pre><code>server$ git clone https://github.com/certbot/certbot
+server$ cd certbot
+server$ ./certbot-auto --help
+</code></pre>
+
+<h2><a name="fetch-cert"></a>Fetch cert</h2>
+
+<p>Stop apache so the letsencrypt client can bind to port 80:</p>
+
+<pre><code>server$ systemctl stop apache2
+</code></pre>
+
+<p>Fetch the certs</p>
+
+<pre><code>server$ ./certbot-auto certonly --standalone --email admin@$(hostname -d) -d $(hostname -d) -d api.$(hostname -d) -d $(hostname -f) -d nicknym.$(hostname -d)
+</code></pre>
+
+<p>This will put the certs and keys into <code>/etc/letsencrypt/live/DOMAIN/</code>.</p>
+
+<p>Now, go to your workstation&rsquo;s provider configuration directory and copy the newly created files from the server to your local config. You will override existing files so please make a backup before proceeding, or use a version control system to track changes.</p>
+
+<pre><code>workstation$ cd PATH_TO_PROVIDER_CONFIG
+</code></pre>
+
+<p>Copy the Certificate</p>
+
+<pre><code>workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/cert.pem files/cert/dev.pixelated-project.org.crt
+</code></pre>
+
+<p>Copy the private key</p>
+
+<pre><code>workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/privkey.pem files/cert/DOMAIN.key
+</code></pre>
+
+<p>Copy the CA chain cert</p>
+
+<pre><code>workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/fullchain.pem files/cert/commercial_ca.crt
+</code></pre>
+
+<h2><a name="deploy-the-certs"></a>Deploy the certs</h2>
+
+<p>Now you only need to deploy the certs</p>
+
+<pre><code>workstation$ leap deploy
+</code></pre>
+
+<p>This will put them into the right locations which are:</p>
+
+<ul>
+<li><code>/etc/x509/certs/leap_commercial.crt</code> for the certificate</li>
+<li><code>/etc/x509/./keys/leap_commercial.key</code> for the private key</li>
+<li><code>/usr/local/share/ca-certificates/leap_commercial_ca.crt</code> for the CA chain cert.</li>
+</ul>
+
+
+<p>Start apache2 again</p>
+
+<pre><code>server$ systemctl start apache2
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/keys-and-certificates/index.html b/docs/en/guide/keys-and-certificates/index.html
new file mode 100644
index 00000000..4775de5a
--- /dev/null
+++ b/docs/en/guide/keys-and-certificates/index.html
@@ -0,0 +1,480 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Keys and Certificates - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class='active level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Keys and Certificates</h1>
+
+<div id='summary'>Working with SSH keys, secrets, and X.509 certificates.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#working-with-ssh">Working with SSH</a>
+ <ol>
+ <li>
+ <a href="index.html#ssh-related-files">SSH related files</a>
+ </li>
+ <li>
+ <a href="index.html#ssh-and-local-nodes">SSH and local nodes</a>
+ </li>
+ <li>
+ <a href="index.html#to-upgrade-a-ssh-host-key">To upgrade a SSH host key</a>
+ </li>
+ <li>
+ <a href="index.html#when-ssh-host-key-changes">When SSH host key changes</a>
+ </li>
+ <li>
+ <a href="index.html#changing-the-ssh-port">Changing the SSH port</a>
+ </li>
+ <li>
+ <a href="index.html#sysadmins-with-multiple-ssh-keys">Sysadmins with multiple SSH keys</a>
+ </li>
+ <li>
+ <a href="index.html#removing-sysadmin-access">Removing sysadmin access</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#x509-certificates">X.509 Certificates</a>
+ <ol>
+ <li>
+ <a href="index.html#configuration-options">Configuration options</a>
+ </li>
+ <li>
+ <a href="index.html#certificate-authorities">Certificate Authorities</a>
+ </li>
+ <li>
+ <a href="index.html#server-certificates">Server certificates</a>
+ </li>
+ <li>
+ <a href="index.html#client-certificates">Client certificates</a>
+ </li>
+ <li>
+ <a href="index.html#commercial-certificates">Commercial certificates</a>
+ </li>
+ <li>
+ <a href="index.html#examine-certs">Examine Certs</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#lets-encrypt-certificate">Let’s Encrypt certificate</a>
+ <ol>
+ <li>
+ <a href="index.html#install-the-official-acme-client">Install the official acme client</a>
+ </li>
+ <li>
+ <a href="index.html#fetch-cert">Fetch cert</a>
+ </li>
+ <li>
+ <a href="index.html#deploy-the-certs">Deploy the certs</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="working-with-ssh"></a>Working with SSH</h1>
+
+<p>Whenever the <code>leap</code> command needs to push changes to a node or gather information from a node, it tunnels this command over SSH. Another way to put this: the security of your servers rests entirely on SSH. Because of this, it is important that you understand how <code>leap</code> uses SSH.</p>
+
+<h2><a name="ssh-related-files"></a>SSH related files</h2>
+
+<p>Assuming your provider directory is called &lsquo;provider&rsquo;:</p>
+
+<ul>
+<li><code>provider/nodes/crow/crow_ssh.pub</code> &ndash; The public SSH host key for node &lsquo;crow&rsquo;.</li>
+<li><code>provider/users/alice/alice_ssh.pub</code> &ndash; The public SSH user key for user &lsquo;alice&rsquo;. Anyone with the private key that corresponds to this public key will have root access to all nodes.</li>
+<li><code>provider/files/ssh/known_hosts</code> &ndash; An autogenerated known_hosts, built from combining <code>provider/nodes/*/*_ssh.pub</code>. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate <code>known_hosts</code> and then run <code>leap compile</code>.</li>
+<li><code>provider/files/ssh/authorized_keys</code> &ndash; An autogenerated list of all the user SSH keys with root access to the notes. It is created from <code>provider/users/*/*_ssh.pub</code>. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate <code>authorized_keys</code> and then run <code>leap compile</code>.</li>
+</ul>
+
+
+<p>All of these files should be committed to source control.</p>
+
+<p>If you rename, remove, or add a node with <code>leap node [mv|add|rm]</code> the SSH key files and the <code>known_hosts</code> file will get properly updated.</p>
+
+<h2><a name="ssh-and-local-nodes"></a>SSH and local nodes</h2>
+
+<p>Local nodes are run as Vagrant virtual machines. The <code>leap</code> command handles SSH slightly differently for these nodes.</p>
+
+<p>Basically, all the SSH security is turned off for local nodes. Since local nodes only exist for a short time on your computer and can&rsquo;t be reached from the internet, this is not a problem.</p>
+
+<p>Specifically, for local nodes:</p>
+
+<ol>
+<li><code>known_hosts</code> is never updated with local node keys, since the SSH public key of a local node is different for each user.</li>
+<li><code>leap</code> entirely skips the checking of host keys when connecting with a local node.</li>
+<li><code>leap</code> adds the public Vagrant SSH key to the list of SSH keys for a user. The public Vagrant SSH key is a shared and insecure key that has root access to most Vagrant virtual machines.</li>
+</ol>
+
+
+<h2><a name="to-upgrade-a-ssh-host-key"></a>To upgrade a SSH host key</h2>
+
+<p>Most servers will have more than one SSH host key. Sometimes, the server will have a better SSH host key than the one you have on file. In order to upgrade to the better SSH host key, simply re-run the init command:</p>
+
+<pre><code>workstation$ leap node init NODE_NAME
+</code></pre>
+
+<p>This will prompt you if you want to upgrade the SSH host key, but only if <code>leap</code> thinks that an upgrade is advisable.</p>
+
+<h2><a name="when-ssh-host-key-changes"></a>When SSH host key changes</h2>
+
+<p>If the host key for a node has changed, you will get an error &ldquo;WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED&rdquo;.</p>
+
+<p>To fix this, you need to remove the file <code>files/nodes/stompy/stompy_ssh.pub</code> and run <code>leap node init stompy</code>, where the node&rsquo;s name is &lsquo;stompy&rsquo;. <strong>Only do this if you are ABSOLUTELY CERTAIN that the node&rsquo;s SSH host key has changed</strong>.</p>
+
+<h2><a name="changing-the-ssh-port"></a>Changing the SSH port</h2>
+
+<p>Suppose you have a node <code>blinky</code> that has SSH listening on port 22 and you want to make it port 2200.</p>
+
+<p>First, modify the configuration for <code>blinky</code> to specify the variable <code>ssh.port</code> as 2200. Usually, this is done in <code>common.json</code> or in a tag file.</p>
+
+<p>For example, you could put this in <code>tags/production.json</code>:</p>
+
+<pre><code>{
+ "ssh": {
+ "port": 2200
+ }
+}
+</code></pre>
+
+<p>Run <code>leap compile</code> and open <code>hiera/blinky.yaml</code> to confirm that <code>ssh.port</code> is set to 2200. The port number must be specified as a number, not a string (no quotes).</p>
+
+<p>Then, you need to deploy this change so that SSH will bind to 2200. You cannot simply run <code>leap deploy blinky</code> because this command will default to using the variable <code>ssh.port</code> which is now <code>2200</code> but SSH on the node is still bound to 22.</p>
+
+<p>So, you manually override the port in the deploy command, using the old port:</p>
+
+<pre><code>leap deploy --port 22 blinky
+</code></pre>
+
+<p>Afterwards, SSH on <code>blinky</code> should be listening on port 2200 and you can just run <code>leap deploy blinky</code> from then on.</p>
+
+<h2><a name="sysadmins-with-multiple-ssh-keys"></a>Sysadmins with multiple SSH keys</h2>
+
+<p>The command <code>leap add-user --self</code> allows only one SSH key. If you want to specify more than one key for a user, you can do it manually:</p>
+
+<pre><code>users/userx/userx_ssh.pub
+users/userx/otherkey_ssh.pub
+</code></pre>
+
+<p>All keys matching &lsquo;userx/*_ssh.pub&rsquo; will be usable.</p>
+
+<h2><a name="removing-sysadmin-access"></a>Removing sysadmin access</h2>
+
+<p>Suppose you want to remove <code>userx</code> from having any further SSH access to the servers. Do this:</p>
+
+<pre><code>rm -r users/userx
+leap deploy
+</code></pre>
+
+<h1><a name="x509-certificates"></a>X.509 Certificates</h1>
+
+<h2><a name="configuration-options"></a>Configuration options</h2>
+
+<p>The <code>ca</code> option in provider.json provides settings used when generating CAs and certificates. The defaults are as follows:</p>
+
+<pre><code>{
+ "ca": {
+ "name": "= global.provider.ca.organization + ' Root CA'",
+ "organization": "= global.provider.name[global.provider.default_language]",
+ "organizational_unit": "= 'https://' + global.provider.domain",
+ "bit_size": 4096,
+ "digest": "SHA256",
+ "life_span": "10y",
+ "server_certificates": {
+ "bit_size": 2048,
+ "digest": "SHA256",
+ "life_span": "1y"
+ },
+ "client_certificates": {
+ "bit_size": 2048,
+ "digest": "SHA256",
+ "life_span": "2m",
+ "limited_prefix": "LIMITED",
+ "unlimited_prefix": "UNLIMITED"
+ }
+ }
+}
+</code></pre>
+
+<p>You should not need to override these defaults in your own provider.json, but you can if you want to. To see what values are used for your provider, run <code>leap inspect provider.json</code>.</p>
+
+<p>NOTE: A certificate <code>bit_size</code> greater than 2048 will probably not be recognized by most commercial CAs.</p>
+
+<h2><a name="certificate-authorities"></a>Certificate Authorities</h2>
+
+<p>There are three x.509 certificate authorities (CA) associated with your provider:</p>
+
+<ol>
+<li><strong>Commercial CA:</strong> It is strongly recommended that you purchase a commercial cert for your primary domain. The goal of platform is to not depend on the commercial CA system, but it does increase security and usability if you purchase a certificate. The cert for the commercial CA must live at <code>files/cert/commercial_ca.crt</code>.</li>
+<li><strong>Server CA:</strong> This is a self-signed CA responsible for signing all the <strong>server</strong> certificates. The private key lives at <code>files/ca/ca.key</code> and the public cert lives at <code>files/ca/ca.crt</code>. The key is very sensitive information and must be kept private. The public cert is distributed publicly.</li>
+<li><strong>Client CA:</strong> This is a self-signed CA responsible for signing all the <strong>client</strong> certificates. The private key lives at <code>files/ca/client_ca.key</code> and the public cert lives at <code>files/ca/client_ca.crt</code>. Neither file is distribute publicly. It is not a big deal if the private key for the client CA is compromised, you can just generate a new one and re-deploy.</li>
+</ol>
+
+
+<p>To generate both the Server CA and the Client CA, run the command:</p>
+
+<pre><code>leap cert ca
+</code></pre>
+
+<h2><a name="server-certificates"></a>Server certificates</h2>
+
+<p>Most every server in your service provider will have a x.509 certificate, generated by the <code>leap</code> command using the Server CA. Whenever you modify any settings of a node that might affect it&rsquo;s certificate (like changing the IP address, hostname, or settings in provider.json), you can magically regenerate all the certs that need to be regenerated with this command:</p>
+
+<pre><code>leap cert update
+</code></pre>
+
+<p>Run <code>leap help cert update</code> for notes on usage options.</p>
+
+<p>Because the server certificates are generated locally on your personal machine, the private key for the Server CA need never be put on any server. It is up to you to keep this file secure.</p>
+
+<h2><a name="client-certificates"></a>Client certificates</h2>
+
+<p>Every leap client gets its own time-limited client certificate. This cert is use to connect to the OpenVPN gateway (and probably other things in the future). It is generated on the fly by the webapp using the Client CA.</p>
+
+<p>To make this work, the private key of the Client CA is made available to the webapp. This might seem bad, but compromise of the Client CA simply allows the attacker to use the OpenVPN gateways without paying. In the future, we plan to add a command to automatically regenerate the Client CA periodically.</p>
+
+<p>There are two types of client certificates: limited and unlimited. A client using a limited cert will have its bandwidth limited to the rate specified by <code>provider.service.bandwidth_limit</code> (in Bytes per second). An unlimited cert is given to the user if they authenticate and the user&rsquo;s service level matches one configured in <code>provider.service.levels</code> without bandwidth limits. Otherwise, the user is given a limited client cert.</p>
+
+<h2><a name="commercial-certificates"></a>Commercial certificates</h2>
+
+<p>We strongly recommend that you use a commercial signed server certificate for your primary domain (in other words, a certificate with a common name matching whatever you have configured for <code>provider.domain</code>). This provides several benefits:</p>
+
+<ol>
+<li>When users visit your website, they don&rsquo;t get a scary notice that something is wrong.</li>
+<li>When a user runs the LEAP client, selecting your service provider will not cause a warning message.</li>
+<li>When other providers first discover your provider, they are more likely to trust your provider key if it is fetched over a commercially verified link.</li>
+</ol>
+
+
+<p>The LEAP platform is designed so that it assumes you are using a commercial cert for the primary domain of your provider, but all other servers are assumed to use non-commercial certs signed by the Server CA you create.</p>
+
+<p>To generate a CSR, run:</p>
+
+<pre><code>leap cert csr
+</code></pre>
+
+<p>This command will generate the CSR and private key matching <code>provider.domain</code> (you can change the domain with <code>--domain=DOMAIN</code> switch). It also generates a server certificate signed with the Server CA. You should delete this certificate and replace it with a real one once it is created by your commercial CA.</p>
+
+<p>The related commercial cert files are:</p>
+
+<pre><code>files/
+ cert/
+ domain.org.crt # Server certificate for domain.org, obtained by commercial CA.
+ domain.org.csr # Certificate signing request
+ domain.org.key # Private key for you certificate
+ commercial_ca.crt # The CA cert obtained from the commercial CA.
+</code></pre>
+
+<p>The private key file is extremely sensitive and care should be taken with its provenance.</p>
+
+<p>If your commercial CA has a chained CA cert, you should be OK if you just put the <strong>last</strong> cert in the chain into the <code>commercial_ca.crt</code> file. This only works if the other CAs in the chain have certs in the debian package <code>ca-certificates</code>, which is the case for almost all CAs.</p>
+
+<p>If you want to add additional fields to the CSR, like country, city, or locality, you can configure these values in provider.json like so:</p>
+
+<pre><code> "ca": {
+ "server_certificates": {
+ "country": "US",
+ "state": "Washington",
+ "locality": "Seattle"
+ }
+ }
+</code></pre>
+
+<p>If they are not present, the CSR will be created without them.</p>
+
+<h2><a name="examine-certs"></a>Examine Certs</h2>
+
+<p>To see details about the keys and certs you can use <code>leap inspect</code> like so:</p>
+
+<pre><code>$ leap inspect files/ca/ca.crt
+</code></pre>
+
+<h1><a name="lets-encrypt-certificate"></a>Let’s Encrypt certificate</h1>
+
+<p>LEAP plans to integrate <a href="https://letsencrypt.org/">Let&rsquo;s Encrypt</a> support, so it will be even easier to receive X.509 certificates that are accepted by all browsers.
+Until we achieve this, here&rsquo;s a guide how to do this manually.</p>
+
+<h2><a name="install-the-official-acme-client"></a>Install the official acme client</h2>
+
+<p>Log in to your webapp node</p>
+
+<pre><code>server$ git clone https://github.com/certbot/certbot
+server$ cd certbot
+server$ ./certbot-auto --help
+</code></pre>
+
+<h2><a name="fetch-cert"></a>Fetch cert</h2>
+
+<p>Stop apache so the letsencrypt client can bind to port 80:</p>
+
+<pre><code>server$ systemctl stop apache2
+</code></pre>
+
+<p>Fetch the certs</p>
+
+<pre><code>server$ ./certbot-auto certonly --standalone --email admin@$(hostname -d) -d $(hostname -d) -d api.$(hostname -d) -d $(hostname -f) -d nicknym.$(hostname -d)
+</code></pre>
+
+<p>This will put the certs and keys into <code>/etc/letsencrypt/live/DOMAIN/</code>.</p>
+
+<p>Now, go to your workstation&rsquo;s provider configuration directory and copy the newly created files from the server to your local config. You will override existing files so please make a backup before proceeding, or use a version control system to track changes.</p>
+
+<pre><code>workstation$ cd PATH_TO_PROVIDER_CONFIG
+</code></pre>
+
+<p>Copy the Certificate</p>
+
+<pre><code>workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/cert.pem files/cert/dev.pixelated-project.org.crt
+</code></pre>
+
+<p>Copy the private key</p>
+
+<pre><code>workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/privkey.pem files/cert/DOMAIN.key
+</code></pre>
+
+<p>Copy the CA chain cert</p>
+
+<pre><code>workstation$ scp root@SERVER:/etc/letsencrypt/live/DOMAIN/fullchain.pem files/cert/commercial_ca.crt
+</code></pre>
+
+<h2><a name="deploy-the-certs"></a>Deploy the certs</h2>
+
+<p>Now you only need to deploy the certs</p>
+
+<pre><code>workstation$ leap deploy
+</code></pre>
+
+<p>This will put them into the right locations which are:</p>
+
+<ul>
+<li><code>/etc/x509/certs/leap_commercial.crt</code> for the certificate</li>
+<li><code>/etc/x509/./keys/leap_commercial.key</code> for the private key</li>
+<li><code>/usr/local/share/ca-certificates/leap_commercial_ca.crt</code> for the CA chain cert.</li>
+</ul>
+
+
+<p>Start apache2 again</p>
+
+<pre><code>server$ systemctl start apache2
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/miscellaneous.html b/docs/en/guide/miscellaneous.html
new file mode 100644
index 00000000..03239410
--- /dev/null
+++ b/docs/en/guide/miscellaneous.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Miscellaneous - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class='active level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Miscellaneous</h1>
+
+<div id='summary'>Miscellaneous commands you may need to know.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="miscellaneous/index.html#facts">Facts</a>
+ </li>
+</ol></div>
+
+<h1><a name="facts"></a>Facts</h1>
+
+<p>There are a few cases when we must gather internal data from a node before we can successfully deploy to other nodes. This is what <code>facts.json</code> is for. It stores a snapshot of certain facts about each node, as needed. Entries in <code>facts.json</code> are updated automatically when you initialize, rename, or remove a node. To manually force a full update of <code>facts.json</code>, run:</p>
+
+<pre><code>leap facts update FILTER
+</code></pre>
+
+<p>Run <code>leap help facts update</code> for more information.</p>
+
+<p>The file <code>facts.json</code> should be committed to source control. You might not have a <code>facts.json</code> if one is not required for your provider.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/miscellaneous/index.html b/docs/en/guide/miscellaneous/index.html
new file mode 100644
index 00000000..9f17df4e
--- /dev/null
+++ b/docs/en/guide/miscellaneous/index.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Miscellaneous - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class='active level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Miscellaneous</h1>
+
+<div id='summary'>Miscellaneous commands you may need to know.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#facts">Facts</a>
+ </li>
+</ol></div>
+
+<h1><a name="facts"></a>Facts</h1>
+
+<p>There are a few cases when we must gather internal data from a node before we can successfully deploy to other nodes. This is what <code>facts.json</code> is for. It stores a snapshot of certain facts about each node, as needed. Entries in <code>facts.json</code> are updated automatically when you initialize, rename, or remove a node. To manually force a full update of <code>facts.json</code>, run:</p>
+
+<pre><code>leap facts update FILTER
+</code></pre>
+
+<p>Run <code>leap help facts update</code> for more information.</p>
+
+<p>The file <code>facts.json</code> should be committed to source control. You might not have a <code>facts.json</code> if one is not required for your provider.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/nodes.html b/docs/en/guide/nodes.html
new file mode 100644
index 00000000..c6238b5f
--- /dev/null
+++ b/docs/en/guide/nodes.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Nodes - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class='active level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Nodes</h1>
+
+<div id='summary'>Working with nodes, services, tags, and locations.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="nodes/index.html#locations">Locations</a>
+ </li>
+ <li>
+ <a href="nodes/index.html#disabling-nodes">Disabling Nodes</a>
+ </li>
+</ol></div>
+
+<h1><a name="locations"></a>Locations</h1>
+
+<p>All nodes should have a <code>location.name</code> specified, and optionally additional information about the location, like the time zone. This location information is used for two things:</p>
+
+<ul>
+<li>Determine which nodes can, or must, communicate with one another via a local network. The way some virtualization environments work, like OpenStack, requires that nodes communicate via the local network if they are on the same network.</li>
+<li>Allows the client to prefer connections to nodes that are closer in physical proximity to the user. This is particularly important for OpenVPN nodes.</li>
+</ul>
+
+
+<p>The location stanza in a node&rsquo;s config file looks like this:</p>
+
+<pre><code>{
+ "location": {
+ "id": "ankara",
+ "name": "Ankara",
+ "country_code": "TR",
+ "timezone": "+2",
+ "hemisphere": "N"
+ }
+}
+</code></pre>
+
+<p>The fields:</p>
+
+<ul>
+<li><code>id</code>: An internal handle to use for this location. If two nodes have match <code>location.id</code>, then they are treated as being on a local network with one another. This value defaults to downcase and underscore of <code>location.name</code>.</li>
+<li><code>name</code>: Can be anything, might be displayed to the user in the client if they choose to manually select a gateway.</li>
+<li><code>country_code</code>: The <a href="https://en.wikipedia.org/wiki/ISO_3166-1">ISO 3166-1</a> two letter country code.</li>
+<li><code>timezone</code>: The timezone expressed as an offset from UTC (in standard time, not daylight savings). You can look up the timezone using this <a href="http://www.timeanddate.com/time/map/">handy map</a>.</li>
+<li><code>hemisphere</code>: This should be &ldquo;S&rdquo; for all servers in South America, Africa, or Australia. Otherwise, this should be &ldquo;N&rdquo;.</li>
+</ul>
+
+
+<p>These location options are very imprecise, but good enough for most usage. The client often does not know its own location precisely either. Instead, the client makes an educated guess at location based on the OS&rsquo;s timezone and locale.</p>
+
+<p>If you have multiple nodes in a single location, it is best to use a tag for the location. For example:</p>
+
+<p><code>tags/ankara.json</code>:</p>
+
+<pre><code>{
+ "location": {
+ "name": "Ankara",
+ "country_code": "TR",
+ "timezone": "+2",
+ "hemisphere": "N"
+ }
+}
+</code></pre>
+
+<p><code>nodes/vpngateway.json</code>:</p>
+
+<pre><code>{
+ "services": "openvpn",
+ "tags": ["production", "ankara"],
+ "ip_address": "1.1.1.1",
+ "openvpn": {
+ "gateway_address": "1.1.1.2"
+ }
+}
+</code></pre>
+
+<p>Unless you are using OpenStack or AWS, setting <code>location</code> for nodes is not required. It is, however, highly recommended.</p>
+
+<h1><a name="disabling-nodes"></a>Disabling Nodes</h1>
+
+<p>There are two ways to temporarily disable a node:</p>
+
+<p><strong>Option 1: disabled environment</strong></p>
+
+<p>You can assign an environment to the node that marks it as disabled. Then, if you use environment pinning, the node will be ignored when you deploy. For example:</p>
+
+<pre><code>{
+ "environment": "disabled"
+}
+</code></pre>
+
+<p>Then use <code>leap env pin ENV</code> to pin the environment to something other than &lsquo;disabled&rsquo;. This only works if all the other nodes are also assigned to some environment.</p>
+
+<p><strong>Option 2: enabled == false</strong></p>
+
+<p>If a node has a property <code>enabled</code> set to false, then the <code>leap</code> command will skip over the node and pretend that it does not exist. For example:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["openvpn"],
+ "enabled": false
+}
+</code></pre>
+
+<p><strong>Options 3: no-deploy</strong></p>
+
+<p>If the file <code>/etc/leap/no-deploy</code> exists on a node, then when you run the commmand <code>leap deploy</code> it will halt and prevent a deploy from going through (if the node was going to be included in the deploy).</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/nodes/index.html b/docs/en/guide/nodes/index.html
new file mode 100644
index 00000000..7f1a60b3
--- /dev/null
+++ b/docs/en/guide/nodes/index.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Nodes - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class='active level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Nodes</h1>
+
+<div id='summary'>Working with nodes, services, tags, and locations.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#locations">Locations</a>
+ </li>
+ <li>
+ <a href="index.html#disabling-nodes">Disabling Nodes</a>
+ </li>
+</ol></div>
+
+<h1><a name="locations"></a>Locations</h1>
+
+<p>All nodes should have a <code>location.name</code> specified, and optionally additional information about the location, like the time zone. This location information is used for two things:</p>
+
+<ul>
+<li>Determine which nodes can, or must, communicate with one another via a local network. The way some virtualization environments work, like OpenStack, requires that nodes communicate via the local network if they are on the same network.</li>
+<li>Allows the client to prefer connections to nodes that are closer in physical proximity to the user. This is particularly important for OpenVPN nodes.</li>
+</ul>
+
+
+<p>The location stanza in a node&rsquo;s config file looks like this:</p>
+
+<pre><code>{
+ "location": {
+ "id": "ankara",
+ "name": "Ankara",
+ "country_code": "TR",
+ "timezone": "+2",
+ "hemisphere": "N"
+ }
+}
+</code></pre>
+
+<p>The fields:</p>
+
+<ul>
+<li><code>id</code>: An internal handle to use for this location. If two nodes have match <code>location.id</code>, then they are treated as being on a local network with one another. This value defaults to downcase and underscore of <code>location.name</code>.</li>
+<li><code>name</code>: Can be anything, might be displayed to the user in the client if they choose to manually select a gateway.</li>
+<li><code>country_code</code>: The <a href="https://en.wikipedia.org/wiki/ISO_3166-1">ISO 3166-1</a> two letter country code.</li>
+<li><code>timezone</code>: The timezone expressed as an offset from UTC (in standard time, not daylight savings). You can look up the timezone using this <a href="http://www.timeanddate.com/time/map/">handy map</a>.</li>
+<li><code>hemisphere</code>: This should be &ldquo;S&rdquo; for all servers in South America, Africa, or Australia. Otherwise, this should be &ldquo;N&rdquo;.</li>
+</ul>
+
+
+<p>These location options are very imprecise, but good enough for most usage. The client often does not know its own location precisely either. Instead, the client makes an educated guess at location based on the OS&rsquo;s timezone and locale.</p>
+
+<p>If you have multiple nodes in a single location, it is best to use a tag for the location. For example:</p>
+
+<p><code>tags/ankara.json</code>:</p>
+
+<pre><code>{
+ "location": {
+ "name": "Ankara",
+ "country_code": "TR",
+ "timezone": "+2",
+ "hemisphere": "N"
+ }
+}
+</code></pre>
+
+<p><code>nodes/vpngateway.json</code>:</p>
+
+<pre><code>{
+ "services": "openvpn",
+ "tags": ["production", "ankara"],
+ "ip_address": "1.1.1.1",
+ "openvpn": {
+ "gateway_address": "1.1.1.2"
+ }
+}
+</code></pre>
+
+<p>Unless you are using OpenStack or AWS, setting <code>location</code> for nodes is not required. It is, however, highly recommended.</p>
+
+<h1><a name="disabling-nodes"></a>Disabling Nodes</h1>
+
+<p>There are two ways to temporarily disable a node:</p>
+
+<p><strong>Option 1: disabled environment</strong></p>
+
+<p>You can assign an environment to the node that marks it as disabled. Then, if you use environment pinning, the node will be ignored when you deploy. For example:</p>
+
+<pre><code>{
+ "environment": "disabled"
+}
+</code></pre>
+
+<p>Then use <code>leap env pin ENV</code> to pin the environment to something other than &lsquo;disabled&rsquo;. This only works if all the other nodes are also assigned to some environment.</p>
+
+<p><strong>Option 2: enabled == false</strong></p>
+
+<p>If a node has a property <code>enabled</code> set to false, then the <code>leap</code> command will skip over the node and pretend that it does not exist. For example:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["openvpn"],
+ "enabled": false
+}
+</code></pre>
+
+<p><strong>Options 3: no-deploy</strong></p>
+
+<p>If the file <code>/etc/leap/no-deploy</code> exists on a node, then when you run the commmand <code>leap deploy</code> it will halt and prevent a deploy from going through (if the node was going to be included in the deploy).</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/provider-configuration.html b/docs/en/guide/provider-configuration.html
new file mode 100644
index 00000000..5c98eb34
--- /dev/null
+++ b/docs/en/guide/provider-configuration.html
@@ -0,0 +1,223 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Provider Configuration - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class='active level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Provider Configuration</h1>
+
+<div id='summary'>Explore how to configure your provider.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="provider-configuration/index.html#required-provider-configuration">Required provider configuration</a>
+ </li>
+ <li>
+ <a href="provider-configuration/index.html#recommended-provider-configuration">Recommended provider configuration</a>
+ </li>
+ <li>
+ <a href="provider-configuration/index.html#configuring-service-levels">Configuring service levels</a>
+ </li>
+</ol></div>
+
+<h2><a name="required-provider-configuration"></a>Required provider configuration</h2>
+
+<p>There are a few required settings in <code>provider.json</code>. At a minimum, you must have:</p>
+
+<ul>
+<li><code>domain</code>: defines the primary domain of the provider. This is the domain that users will type in when using the Bitmask client, although it is not necessarily the domain where users will visit if they sign up via the web application. If email is supported, all accounts will be <code>username@domain</code>.</li>
+<li><code>name</code>: A brief title for this provider. It can be multiple words, but should not be too long.</li>
+<li><code>contacts.default</code>: One or more email addresses for sysadmins.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "domain": "freerobot.org",
+ "name": "Freedom for Robots!",
+ "contacts": {
+ "default": "root@freerobot.org"
+ }
+}
+</code></pre>
+
+<h2><a name="recommended-provider-configuration"></a>Recommended provider configuration</h2>
+
+<ul>
+<li><code>description</code>: A longer description of the provider, shown to the user when they register a new account through Bitmask client.</li>
+<li><code>languages</code>: A list of language codes that should be enabled.</li>
+<li><code>default_language</code>: The initial default language code.</li>
+<li><code>enrollment_policy</code>: One of &ldquo;open&rdquo;, &ldquo;closed&rdquo;, or &ldquo;invite&rdquo;. (invite not currently supported).</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "description": "It is time for robots of the world to unite and throw of the shackles of servitude to our organic overlords.",
+ "languages": ["en", "de", "pt", "01"],
+ "default_language": "01",
+ "enrollman_policy": "open"
+}
+</code></pre>
+
+<p>For a full list of possible settings, you can use <code>leap inspect</code> to see how provider.json is evaluated after including the inherited defaults:</p>
+
+<pre><code>$ leap inspect provider.json
+</code></pre>
+
+<h2><a name="configuring-service-levels"></a>Configuring service levels</h2>
+
+<p>The <code>provider.json</code> file defines the available service levels for the provider.</p>
+
+<p>For example, in provider.json:</p>
+
+<pre><code>"service": {
+ "default_service_level": "low",
+ "levels": {
+ "low": {
+ "description": "Entry level plan, with unlimited bandwidth and minimal storage quota.",
+ "name": "entry",
+ "storage": "10 MB",
+ "rate": {
+ "USD": 5,
+ "GBP": 3,
+ "EUR": 6
+ }
+ },
+ "full": {
+ "description": "Full plan, with unlimited bandwidth and higher quota."
+ "name": "full",
+ "storage": "5 GB",
+ "rate": {
+ "USD": 10,
+ "GBP": 6,
+ "EUR": 12
+ }
+ }
+ }
+ }
+}
+</code></pre>
+
+<p>For a list of currency codes, see <a href="https://en.wikipedia.org/wiki/ISO_4217#Active_codes">https://en.wikipedia.org/wiki/ISO_4217#Active_codes</a></p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/provider-configuration/index.html b/docs/en/guide/provider-configuration/index.html
new file mode 100644
index 00000000..b710cb64
--- /dev/null
+++ b/docs/en/guide/provider-configuration/index.html
@@ -0,0 +1,223 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Provider Configuration - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class='active level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class=' level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Provider Configuration</h1>
+
+<div id='summary'>Explore how to configure your provider.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#required-provider-configuration">Required provider configuration</a>
+ </li>
+ <li>
+ <a href="index.html#recommended-provider-configuration">Recommended provider configuration</a>
+ </li>
+ <li>
+ <a href="index.html#configuring-service-levels">Configuring service levels</a>
+ </li>
+</ol></div>
+
+<h2><a name="required-provider-configuration"></a>Required provider configuration</h2>
+
+<p>There are a few required settings in <code>provider.json</code>. At a minimum, you must have:</p>
+
+<ul>
+<li><code>domain</code>: defines the primary domain of the provider. This is the domain that users will type in when using the Bitmask client, although it is not necessarily the domain where users will visit if they sign up via the web application. If email is supported, all accounts will be <code>username@domain</code>.</li>
+<li><code>name</code>: A brief title for this provider. It can be multiple words, but should not be too long.</li>
+<li><code>contacts.default</code>: One or more email addresses for sysadmins.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "domain": "freerobot.org",
+ "name": "Freedom for Robots!",
+ "contacts": {
+ "default": "root@freerobot.org"
+ }
+}
+</code></pre>
+
+<h2><a name="recommended-provider-configuration"></a>Recommended provider configuration</h2>
+
+<ul>
+<li><code>description</code>: A longer description of the provider, shown to the user when they register a new account through Bitmask client.</li>
+<li><code>languages</code>: A list of language codes that should be enabled.</li>
+<li><code>default_language</code>: The initial default language code.</li>
+<li><code>enrollment_policy</code>: One of &ldquo;open&rdquo;, &ldquo;closed&rdquo;, or &ldquo;invite&rdquo;. (invite not currently supported).</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "description": "It is time for robots of the world to unite and throw of the shackles of servitude to our organic overlords.",
+ "languages": ["en", "de", "pt", "01"],
+ "default_language": "01",
+ "enrollman_policy": "open"
+}
+</code></pre>
+
+<p>For a full list of possible settings, you can use <code>leap inspect</code> to see how provider.json is evaluated after including the inherited defaults:</p>
+
+<pre><code>$ leap inspect provider.json
+</code></pre>
+
+<h2><a name="configuring-service-levels"></a>Configuring service levels</h2>
+
+<p>The <code>provider.json</code> file defines the available service levels for the provider.</p>
+
+<p>For example, in provider.json:</p>
+
+<pre><code>"service": {
+ "default_service_level": "low",
+ "levels": {
+ "low": {
+ "description": "Entry level plan, with unlimited bandwidth and minimal storage quota.",
+ "name": "entry",
+ "storage": "10 MB",
+ "rate": {
+ "USD": 5,
+ "GBP": 3,
+ "EUR": 6
+ }
+ },
+ "full": {
+ "description": "Full plan, with unlimited bandwidth and higher quota."
+ "name": "full",
+ "storage": "5 GB",
+ "rate": {
+ "USD": 10,
+ "GBP": 6,
+ "EUR": 12
+ }
+ }
+ }
+ }
+}
+</code></pre>
+
+<p>For a list of currency codes, see <a href="https://en.wikipedia.org/wiki/ISO_4217#Active_codes">https://en.wikipedia.org/wiki/ISO_4217#Active_codes</a></p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/virtual-machines.html b/docs/en/guide/virtual-machines.html
new file mode 100644
index 00000000..5cee9a40
--- /dev/null
+++ b/docs/en/guide/virtual-machines.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Virtual Machines - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='environments.html'>Environments</a>
+</li>
+<li class='active level1'>
+<a class='' href='virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Virtual Machines</h1>
+
+<div id='summary'>Running LEAP platform on remote virtual machines</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="virtual-machines/index.html#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="virtual-machines/index.html#configuration">Configuration</a>
+ </li>
+ <li>
+ <a href="virtual-machines/index.html#usage">Usage</a>
+ </li>
+ <li>
+ <a href="virtual-machines/index.html#keeping-state-synchronized">Keeping State Synchronized</a>
+ </li>
+ <li>
+ <a href="virtual-machines/index.html#multiple-authentication-profiles">Multiple authentication profiles</a>
+ </li>
+</ol></div>
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>You can use the <code>leap</code> command line to easily remote virtual machines.</p>
+
+<p>Note: there are two types of virtual machines that <code>leap</code> can handle:</p>
+
+<ul>
+<li><strong>Local</strong> virtual machines running with vagrant, for use in testing.</li>
+<li><strong>Remote</strong> virtual machines hosted by a cloud provider like AWS or Rackspace.</li>
+</ul>
+
+
+<p>This guide is for &ldquo;remote virtual machines&rdquo;. For &ldquo;local virtual machines&rdquo; see <a href="../tutorials/vagrant.html">Vagrant</a>.</p>
+
+<p>Currently, only Amazon AWS is supported as a cloud provider.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p>To get started with virtual machines, you must configure a <code>cloud.json</code> file with your API credentials for the virtual machine vendor. This file lives in the root of your provider directory.</p>
+
+<p>For example:</p>
+
+<pre><code>{
+ "my_aws": {
+ "api": "aws",
+ "vendor": "aws",
+ "auth": {
+ "region": "us-west-2",
+ "aws_access_key_id": "xxxx my key id xxxx",
+ "aws_secret_access_key": "xxxx my access key xxxx"
+ }
+ }
+}
+</code></pre>
+
+<p>This will configure a cloud &ldquo;authentication profile&rdquo; called &ldquo;my_aws&rdquo;. This profile will be used by default if there is only one. See below for managing multiple authentication profiles.</p>
+
+<p><em>Required cloud.json properties</em></p>
+
+<ul>
+<li><code>$profile</code>: In this case, &lsquo;my_aws&rsquo;.</li>
+<li><code>$profile.api</code>: For now, must always be &ldquo;aws&rdquo;.</li>
+<li><code>$profile.vendor</code>: For now, must always be &ldquo;aws&rdquo;.</li>
+<li><code>$profile.auth</code>: API specific authentication configuration for this profile. In the case of AWS, it must include <code>auth.region</code>, <code>auth.aws_access_key_id</code>, and <code>aws_secret_access_key</code>.</li>
+</ul>
+
+
+<p><em>Additional cloud.json properties</em></p>
+
+<p>In addition to required configuration properties, these are optional:</p>
+
+<ul>
+<li><code>$profile.default_image</code>: What image to use for new nodes by default. Generally, you should not specify this, because it will automatically select the right Debian image for your region. A node can override this with the property <code>vm.image</code>.</li>
+<li><code>$profile.default_options</code>: This is passed directly to the cloud API, and so is specific to whichever API you are using. The node can override this with the property <code>vm.options</code>.</li>
+</ul>
+
+
+<p>A more complete example <code>cloud.json</code>:</p>
+
+<pre><code>{
+ "my_aws": {
+ "api": "aws",
+ "vendor": "aws",
+ "auth": {
+ "region": "us-west-2",
+ "aws_access_key_id": "xxxx my key id xxxx",
+ "aws_secret_access_key": "xxxx my access key xxxx"
+ },
+ "default_image": "ami-98e114f8",
+ "default_options": {
+ "InstanceType": "t2.nano"
+ }
+ }
+}
+</code></pre>
+
+<p>See also:</p>
+
+<ul>
+<li><a href="https://aws.amazon.com/ec2/instance-types/">Available instance types for AWS</a></li>
+</ul>
+
+
+<h2><a name="usage"></a>Usage</h2>
+
+<p>See <code>leap help vm</code> for a description of all the possible commands.</p>
+
+<p>In order to be able to create new virtual machine instances, you need to register your SSH key with the VM vendor.</p>
+
+<pre><code>leap vm key-register
+</code></pre>
+
+<p>You only have to do this once, and only people who will be creating new VM instances need to do this.</p>
+
+<p>Once you have done that, you just <code>leap vm add</code> to create the virtual machine and then <code>leap vm start</code> to actually boot it.</p>
+
+<pre><code>leap vm add mynode
+leap vm start mynode
+</code></pre>
+
+<p>You can specify seed values to <code>leap vm add</code>. For example:</p>
+
+<pre><code>leap vm add mynode services:webapp tags:seattle vm.options.InstanceType:t2.small
+</code></pre>
+
+<p>Check to see what the status is of all VMs:</p>
+
+<pre><code>leap vm status
+</code></pre>
+
+<p>If it looks good, you can now deploy to the new server:</p>
+
+<pre><code>leap node init mynode
+leap deploy mynode
+</code></pre>
+
+<p>To stop the VM:</p>
+
+<pre><code>leap vm stop mynode
+</code></pre>
+
+<p>To destroy the VM and clean up its storage space:</p>
+
+<pre><code>leap vm rm mynode
+</code></pre>
+
+<p>In general, you should remove VMs instead of stopping them, unless you plan on stopping the VM for a short amount of time. A stopped VM will still use disk space and still incur charges.</p>
+
+<h2><a name="keeping-state-synchronized"></a>Keeping State Synchronized</h2>
+
+<p>The LEAP platform stores all its state information in flat static files. The virtual machine vendor, however, also has its own state.</p>
+
+<p>On the provider side, VM state is stored in node configuration files in <code>nodes/*.json</code>. Of particular importance are the properties <code>ip_address</code> and <code>vm.id</code>.</p>
+
+<p>Most of the time, you should not have any trouble: the <code>leap vm</code> commands will keep things in sync. However, if the state of your configuration files gets out of sync with the state of the virtual machines, it can cause problems.</p>
+
+<p>The command <code>leap vm status</code> will warn you whenever it detects a problem and it will usually propose a fix.</p>
+
+<p>Typically, the fix is to manually update the binding between a local node configuration and the running remote virtual machine, like so:</p>
+
+<pre><code>leap vm bind NODE_NAME VM_ID
+</code></pre>
+
+<h2><a name="multiple-authentication-profiles"></a>Multiple authentication profiles</h2>
+
+<p>If you have multiple profiles configured in <code>cloud.json</code>, you can specify which one you want to use:</p>
+
+<ul>
+<li>Set the <code>vm.auth</code> property in the node configuration to match the name of the authentication profile.</li>
+<li>Or, pass <code>--auth PROFILE_NAME</code> on the command line.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/guide/virtual-machines/index.html b/docs/en/guide/virtual-machines/index.html
new file mode 100644
index 00000000..da0da107
--- /dev/null
+++ b/docs/en/guide/virtual-machines/index.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Virtual Machines - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level1'>
+<a class='' href='../getting-started.html'>Getting Started</a>
+</li>
+<li class=' level1'>
+<a class='' href='../config.html'>Configuration Files</a>
+</li>
+<li class=' level1'>
+<a class='' href='../nodes.html'>Nodes</a>
+</li>
+<li class=' level1'>
+<a class='' href='../keys-and-certificates.html'>Keys and Certificates</a>
+</li>
+<li class=' level1'>
+<a class='' href='../domains.html'>Domains</a>
+</li>
+<li class=' level1'>
+<a class='' href='../provider-configuration.html'>Provider Configuration</a>
+</li>
+<li class=' level1'>
+<a class='' href='../environments.html'>Environments</a>
+</li>
+<li class='active level1'>
+<a class='' href='../virtual-machines.html'>Virtual Machines</a>
+</li>
+<li class=' level1'>
+<a class='' href='../miscellaneous.html'>Miscellaneous</a>
+</li>
+<li class=' level1'>
+<a class='' href='../commands.html'>Command Line Reference</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Virtual Machines</h1>
+
+<div id='summary'>Running LEAP platform on remote virtual machines</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ </li>
+ <li>
+ <a href="index.html#usage">Usage</a>
+ </li>
+ <li>
+ <a href="index.html#keeping-state-synchronized">Keeping State Synchronized</a>
+ </li>
+ <li>
+ <a href="index.html#multiple-authentication-profiles">Multiple authentication profiles</a>
+ </li>
+</ol></div>
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>You can use the <code>leap</code> command line to easily remote virtual machines.</p>
+
+<p>Note: there are two types of virtual machines that <code>leap</code> can handle:</p>
+
+<ul>
+<li><strong>Local</strong> virtual machines running with vagrant, for use in testing.</li>
+<li><strong>Remote</strong> virtual machines hosted by a cloud provider like AWS or Rackspace.</li>
+</ul>
+
+
+<p>This guide is for &ldquo;remote virtual machines&rdquo;. For &ldquo;local virtual machines&rdquo; see <a href="../../tutorials/vagrant.html">Vagrant</a>.</p>
+
+<p>Currently, only Amazon AWS is supported as a cloud provider.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p>To get started with virtual machines, you must configure a <code>cloud.json</code> file with your API credentials for the virtual machine vendor. This file lives in the root of your provider directory.</p>
+
+<p>For example:</p>
+
+<pre><code>{
+ "my_aws": {
+ "api": "aws",
+ "vendor": "aws",
+ "auth": {
+ "region": "us-west-2",
+ "aws_access_key_id": "xxxx my key id xxxx",
+ "aws_secret_access_key": "xxxx my access key xxxx"
+ }
+ }
+}
+</code></pre>
+
+<p>This will configure a cloud &ldquo;authentication profile&rdquo; called &ldquo;my_aws&rdquo;. This profile will be used by default if there is only one. See below for managing multiple authentication profiles.</p>
+
+<p><em>Required cloud.json properties</em></p>
+
+<ul>
+<li><code>$profile</code>: In this case, &lsquo;my_aws&rsquo;.</li>
+<li><code>$profile.api</code>: For now, must always be &ldquo;aws&rdquo;.</li>
+<li><code>$profile.vendor</code>: For now, must always be &ldquo;aws&rdquo;.</li>
+<li><code>$profile.auth</code>: API specific authentication configuration for this profile. In the case of AWS, it must include <code>auth.region</code>, <code>auth.aws_access_key_id</code>, and <code>aws_secret_access_key</code>.</li>
+</ul>
+
+
+<p><em>Additional cloud.json properties</em></p>
+
+<p>In addition to required configuration properties, these are optional:</p>
+
+<ul>
+<li><code>$profile.default_image</code>: What image to use for new nodes by default. Generally, you should not specify this, because it will automatically select the right Debian image for your region. A node can override this with the property <code>vm.image</code>.</li>
+<li><code>$profile.default_options</code>: This is passed directly to the cloud API, and so is specific to whichever API you are using. The node can override this with the property <code>vm.options</code>.</li>
+</ul>
+
+
+<p>A more complete example <code>cloud.json</code>:</p>
+
+<pre><code>{
+ "my_aws": {
+ "api": "aws",
+ "vendor": "aws",
+ "auth": {
+ "region": "us-west-2",
+ "aws_access_key_id": "xxxx my key id xxxx",
+ "aws_secret_access_key": "xxxx my access key xxxx"
+ },
+ "default_image": "ami-98e114f8",
+ "default_options": {
+ "InstanceType": "t2.nano"
+ }
+ }
+}
+</code></pre>
+
+<p>See also:</p>
+
+<ul>
+<li><a href="https://aws.amazon.com/ec2/instance-types/">Available instance types for AWS</a></li>
+</ul>
+
+
+<h2><a name="usage"></a>Usage</h2>
+
+<p>See <code>leap help vm</code> for a description of all the possible commands.</p>
+
+<p>In order to be able to create new virtual machine instances, you need to register your SSH key with the VM vendor.</p>
+
+<pre><code>leap vm key-register
+</code></pre>
+
+<p>You only have to do this once, and only people who will be creating new VM instances need to do this.</p>
+
+<p>Once you have done that, you just <code>leap vm add</code> to create the virtual machine and then <code>leap vm start</code> to actually boot it.</p>
+
+<pre><code>leap vm add mynode
+leap vm start mynode
+</code></pre>
+
+<p>You can specify seed values to <code>leap vm add</code>. For example:</p>
+
+<pre><code>leap vm add mynode services:webapp tags:seattle vm.options.InstanceType:t2.small
+</code></pre>
+
+<p>Check to see what the status is of all VMs:</p>
+
+<pre><code>leap vm status
+</code></pre>
+
+<p>If it looks good, you can now deploy to the new server:</p>
+
+<pre><code>leap node init mynode
+leap deploy mynode
+</code></pre>
+
+<p>To stop the VM:</p>
+
+<pre><code>leap vm stop mynode
+</code></pre>
+
+<p>To destroy the VM and clean up its storage space:</p>
+
+<pre><code>leap vm rm mynode
+</code></pre>
+
+<p>In general, you should remove VMs instead of stopping them, unless you plan on stopping the VM for a short amount of time. A stopped VM will still use disk space and still incur charges.</p>
+
+<h2><a name="keeping-state-synchronized"></a>Keeping State Synchronized</h2>
+
+<p>The LEAP platform stores all its state information in flat static files. The virtual machine vendor, however, also has its own state.</p>
+
+<p>On the provider side, VM state is stored in node configuration files in <code>nodes/*.json</code>. Of particular importance are the properties <code>ip_address</code> and <code>vm.id</code>.</p>
+
+<p>Most of the time, you should not have any trouble: the <code>leap vm</code> commands will keep things in sync. However, if the state of your configuration files gets out of sync with the state of the virtual machines, it can cause problems.</p>
+
+<p>The command <code>leap vm status</code> will warn you whenever it detects a problem and it will usually propose a fix.</p>
+
+<p>Typically, the fix is to manually update the binding between a local node configuration and the running remote virtual machine, like so:</p>
+
+<pre><code>leap vm bind NODE_NAME VM_ID
+</code></pre>
+
+<h2><a name="multiple-authentication-profiles"></a>Multiple authentication profiles</h2>
+
+<p>If you have multiple profiles configured in <code>cloud.json</code>, you can specify which one you want to use:</p>
+
+<ul>
+<li>Set the <code>vm.auth</code> property in the node configuration to match the name of the authentication profile.</li>
+<li>Or, pass <code>--auth PROFILE_NAME</code> on the command line.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services.html b/docs/en/services.html
new file mode 100644
index 00000000..55211e64
--- /dev/null
+++ b/docs/en/services.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Services - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='tutorials.html'>Tutorials</a>
+</li>
+<li class='active level0'>
+<a class='' href='services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='services/webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Guide to node services</h1>
+
+<div id='summary'></div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="services/index.html#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="services/index.html#available-services">Available services</a>
+ </li>
+</ol></div>
+
+<h1><a name="introduction"></a>Introduction</h1>
+
+<p>Every node (server) must have one or more <code>services</code> defined that determines what role the node performs. For example:</p>
+
+<pre><code>workstation$ cat nodes/stallman.json
+{
+ "ip_address": "199.99.99.1",
+ "services": ["webapp", "tor"]
+}
+</code></pre>
+
+<p>Here are common questions to ask when adding a new node to your provider:</p>
+
+<ul>
+<li><strong>many or few?</strong> Some services benefit from having many nodes, while some services are best run on only one or two nodes.</li>
+<li><strong>required or optional?</strong> Some services are required, while others can be left out.</li>
+<li><strong>who does the node communicate with?</strong> Some services communicate very heavily with other particular services. Nodes running these services should be close together.</li>
+<li><strong>public or private network?</strong> Some services communicate with the public internet, while others only need to communicate with other nodes in the infrastructure.</li>
+</ul>
+
+
+<h1><a name="available-services"></a>Available services</h1>
+
+<table class="table table-striped">
+<tr>
+ <th>Service</th>
+ <th>VPN</th>
+ <th>Email</th>
+ <th>Notes</th>
+</tr>
+<tr>
+ <td>webapp</td>
+ <td><i class="fa fa-circle"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>User control panel, provider API, and support system.</td>
+</tr>
+<tr>
+ <td>couchdb</td>
+ <td><i class="fa fa-circle"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>Data storage for everything. Private node.</td>
+<td></td>
+</tr>
+<tr>
+ <td>soledad</td>
+ <td><i class="fa fa-circle-o"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>User data synchronization daemon. Usually paired with <code>couchdb</code> nodes.</td>
+<td></td>
+</tr>
+<tr>
+ <td>mx</td>
+ <td><i class="fa fa-circle-o"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>Incoming and outgoing MX servers.</td>
+</tr>
+<tr>
+ <td>openvpn</td>
+ <td><i class="fa fa-circle"></i></td>
+ <td><i class="fa fa-circle-o"></i></td>
+ <td>OpenVPN gateways.</td>
+</tr>
+<tr>
+ <td>monitor</td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td>Nagios monitoring. This service must be on the webapp node.</td>
+</tr>
+<tr>
+ <td>tor</td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td>Tor exit node.</td>
+</tr>
+</table>
+
+
+<p>Key: <i class="fa fa-circle"> Required</i>, <i class="fa fa-dot-circle-o"> Optional</i>, <i class="fa fa-circle-o"> Not Used</i></p>
+
+<p><div class=' page-summary'>
+<h2>
+<a href='services/couchdb.html'>couchdb</a>
+</h2>
+<div class='summary'>Data storage for all user data.</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='services/openvpn.html'>openvpn</a>
+</h2>
+<div class='summary'>OpenVPN egress gateways</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='services/monitor.html'>monitor</a>
+</h2>
+<div class='summary'>Nagios monitoring and continuous testing.</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='services/mx.html'>mx</a>
+</h2>
+<div class='summary'>Incoming and outgoing MX servers.</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='services/soledad.html'>soledad</a>
+</h2>
+<div class='summary'>User data synchronization daemon</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='services/tor.html'>tor</a>
+</h2>
+<div class='summary'>Tor exit node or hidden service</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='services/webapp.html'>webapp</a>
+</h2>
+<div class='summary'>leap_web user management application and provider API.</div>
+</div>
+</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/couchdb.html b/docs/en/services/couchdb.html
new file mode 100644
index 00000000..3dde5a3c
--- /dev/null
+++ b/docs/en/services/couchdb.html
@@ -0,0 +1,328 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+couchdb - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class='active level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>couchdb</h1>
+
+<div id='summary'>Data storage for all user data.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="couchdb/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="couchdb/index.html#configuration">Configuration</a>
+ <ol>
+ <li>
+ <a href="couchdb/index.html#nighly-dumps">Nighly dumps</a>
+ </li>
+ <li>
+ <a href="couchdb/index.html#plain-couchdb">Plain CouchDB</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="couchdb/index.html#various-tasks">Various Tasks</a>
+ <ol>
+ <li>
+ <a href="couchdb/index.html#re-enabling-blocked-account">Re-enabling blocked account</a>
+ </li>
+ <li>
+ <a href="couchdb/index.html#how-to-find-out-which-userstore-belongs-to-which-identity">How to find out which userstore belongs to which identity?</a>
+ </li>
+ <li>
+ <a href="couchdb/index.html#how-much-disk-space-is-used-by-a-userstore">How much disk space is used by a userstore</a>
+ </li>
+ <li>
+ <a href="couchdb/index.html#migrating-from-bigcouch-to-plain-couchdb">Migrating from BigCouch to plain CouchDB</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Required:</p>
+
+<ul>
+<li>Nodes with <code>couchdb</code> service must also have <code>soledad</code> service, if email is enabled.</li>
+</ul>
+
+
+<p>Suggested:</p>
+
+<ul>
+<li>Nodes with <code>couchdb</code> service communicate heavily with <code>webapp</code> and <code>mx</code>.</li>
+</ul>
+
+
+<p><code>couchdb</code> nodes do not need to be reachable from the public internet, although the <code>soledad</code> service does require this.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<h3><a name="nighly-dumps"></a>Nighly dumps</h3>
+
+<p>You can do a nightly couchdb data dump by adding this to your node config:</p>
+
+<pre><code>"couch": {
+ "backup": true
+}
+</code></pre>
+
+<p>Data will get dumped to <code>/var/backups/couchdb</code>.</p>
+
+<h3><a name="plain-couchdb"></a>Plain CouchDB</h3>
+
+<p>BigCouch is not supported on Platform version 0.8 and higher: only plain CouchDB is possible. For earlier versions, you must do this in order to use plain CouchDB:</p>
+
+<pre><code>"couch": {
+ "master": true,
+ "pwhash_alg": "pbkdf2"
+}
+</code></pre>
+
+<h2><a name="various-tasks"></a>Various Tasks</h2>
+
+<h3><a name="re-enabling-blocked-account"></a>Re-enabling blocked account</h3>
+
+<p>When a user account gets destroyed from the webapp, there&rsquo;s still a leftover doc in the identities db so other people can&rsquo;t claim that account without an admin&rsquo;s intervention. You can remove this username reservation through the webapp.</p>
+
+<p>However, here is how you could do it manually, if you wanted to:</p>
+
+<p>grep the identities db for the email address:</p>
+
+<pre><code>curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET http://127.0.0.1:5984/identities/_all_docs?include_docs=true|grep test_127@bitmask.net
+</code></pre>
+
+<p>lookup &ldquo;id&rdquo; and &ldquo;rev&rdquo; to delete the doc:</p>
+
+<pre><code>curl -s --netrc-file /etc/couchdb/couchdb.netrc -X DELETE 'http://127.0.0.1:5984/identities/b25cf10f935b58088f0d547fca823265?rev=2-715a9beba597a2ab01851676f12c3e4a'
+</code></pre>
+
+<h3><a name="how-to-find-out-which-userstore-belongs-to-which-identity"></a>How to find out which userstore belongs to which identity?</h3>
+
+<pre><code>/usr/bin/curl -s --netrc-file /etc/couchdb/couchdb.netrc '127.0.0.1:5984/identities/_all_docs?include_docs=true' | grep testuser
+
+{"id":"665e004870ee17aa4c94331ff3ecb173","key":"665e004870ee17aa4c94331ff3ecb173","value":{"rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b"},"doc":{"_id":"665e004870ee17aa4c94331ff3ecb173","_rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b","user_id":"665e004870ee17aa4c94331ff3cd59eb","address":"testuser@example.org","destination":"testuser@example.org","keys": ...
+</code></pre>
+
+<ul>
+<li>search for the &ldquo;user_id&rdquo; field</li>
+<li>in this example <a href="&#x6d;&#97;&#x69;&#108;&#116;&#111;&#x3a;&#116;&#x65;&#x73;&#116;&#x75;&#x73;&#101;&#114;&#x40;&#x65;&#x78;&#97;&#x6d;&#112;&#x6c;&#x65;&#x2e;&#111;&#114;&#103;">&#116;&#101;&#x73;&#x74;&#x75;&#x73;&#101;&#x72;&#x40;&#101;&#120;&#97;&#x6d;&#x70;&#108;&#101;&#x2e;&#111;&#x72;&#103;</a> uses the database user-665e004870ee17aa4c94331ff3cd59eb</li>
+</ul>
+
+
+<h3><a name="how-much-disk-space-is-used-by-a-userstore"></a>How much disk space is used by a userstore</h3>
+
+<p>Beware that this returns the uncompacted disk size (see <a href="http://wiki.apache.org/couchdb/Compaction">http://wiki.apache.org/couchdb/Compaction</a>)</p>
+
+<pre><code>echo "`curl --netrc -s -X GET 'http://127.0.0.1:5984/user-dcd6492d74b90967b6b874100b7dbfcf'|json_pp|grep disk_size|cut -d: -f 2`/1024"|bc
+</code></pre>
+
+<h3><a name="migrating-from-bigcouch-to-plain-couchdb"></a>Migrating from BigCouch to plain CouchDB</h3>
+
+<p><p>At the end of this process, you will have just <em>one</em> node with <code>services</code> property equal to <code>couchdb</code>. If you had a BigCouch cluster before, you will be removing all but one of those machines to consolidate them into one CouchDB machine.</p>
+
+<ol>
+<li><p>if you have multiple nodes with the <code>couchdb</code> service on them, pick one of them to be your CouchDB server, and remove the service from the others. If these machines were only doing BigCouch before, you can remove the nodes completely with <code>leap node rm &lt;nodename&gt;</code> and then you can decommission the servers</p></li>
+<li><p>put the webapp into <a href="webapp.html#maintenance-mode">maintenance mode</a></p></li>
+<li><p>turn off daemons that access the database. For example:</p>
+
+<pre><code class="`"> workstation$ leap ssh &lt;each soledad-node&gt;
+ server# /etc/init.d/soledad-server stop
+
+ workstation$ leap ssh &lt;mx-node&gt;
+ server# /etc/init.d/postfix stop
+ server# /etc/init.d/leap-mx stop
+
+ workstation$ leap ssh &lt;webapp-node&gt;
+ server# /etc/init.d/nickserver stop
+</code></pre>
+
+<p> Alternately, you can create a temporary firewall rule to block access (run on couchdb server):</p>
+
+<pre><code class="`"> server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+<li><p>remove orphaned databases and do a backup of all remaining, active databases. This can take some time and will place several hundred megabytes of data into /var/backups/couchdb. The size and time depends on how many users there are on your system. For example, 15k users took approximately 25 minutes and 308M of space:</p>
+
+<pre><code class="`"> workstation$ leap ssh &lt;couchdb-node&gt;
+ server# cd /srv/leap/couchdb/scripts
+ server# ./cleanup-user-dbs
+ server# time ./couchdb_dumpall.sh
+</code></pre></li>
+<li><p>stop bigcouch:</p>
+
+<pre><code class="`"> server# /etc/init.d/bigcouch stop
+ server# pkill epmd
+</code></pre></li>
+<li><p>remove bigcouch:</p>
+
+<pre><code class="`"> server# apt-get remove bigcouch
+</code></pre></li>
+<li><p>configure your couch node to use plain couchdb instead of bigcouch, you can do this by editing nodes/<couch-node>.json, look for this section:</p>
+
+<pre><code class="`"> "couch": {
+ "mode": "plain"
+ }
+</code></pre>
+
+<p>change it, so it looks like this instead:</p>
+
+<pre><code class="``"> "couch": {
+ "mode": "plain",
+ "pwhash_alg": "pbkdf2"
+ }
+</code></pre></li>
+</ol>
+
+</p>
+
+<p><ol>
+<li><p>restore the backup, this will take approximately the same amount of time as the backup took above:</p>
+
+<pre><code class="`"> server# cd /srv/leap/couchdb/scripts
+ server# time ./couchdb_restoreall.sh
+</code></pre></li>
+<li><p>start services again that were stopped in the beginning:</p>
+
+<pre><code class="`"> workstation$ leap ssh soledad-nodes
+ server# /etc/init.d/soledad-server start
+
+ workstation$ leap ssh mx-node
+ server# /etc/init.d/postfix start
+ server# /etc/init.d/leap-mx start
+
+ workstation$ leap ssh webapp
+ server# /etc/init.d/nickserver start
+</code></pre>
+
+<p> Or, alternately, if you set up the firewall rule instead, now remove it:</p>
+
+<pre><code class="`"> server# iptables -D INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+</ol>
+
+</p>
+
+<p><ol>
+<li><p>check if everything is working, including running the test on your deployment machine:</p>
+
+<pre><code class="`"> workstation$ leap test
+</code></pre></li>
+<li><p>Remove old bigcouch data dir <code>/opt</code> after you double checked everything is in place</p></li>
+<li><p>Relax, enjoy a refreshing beverage.</p></li>
+</ol>
+
+</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/couchdb/index.html b/docs/en/services/couchdb/index.html
new file mode 100644
index 00000000..7fa6b951
--- /dev/null
+++ b/docs/en/services/couchdb/index.html
@@ -0,0 +1,328 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+couchdb - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class='active level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>couchdb</h1>
+
+<div id='summary'>Data storage for all user data.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ <ol>
+ <li>
+ <a href="index.html#nighly-dumps">Nighly dumps</a>
+ </li>
+ <li>
+ <a href="index.html#plain-couchdb">Plain CouchDB</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#various-tasks">Various Tasks</a>
+ <ol>
+ <li>
+ <a href="index.html#re-enabling-blocked-account">Re-enabling blocked account</a>
+ </li>
+ <li>
+ <a href="index.html#how-to-find-out-which-userstore-belongs-to-which-identity">How to find out which userstore belongs to which identity?</a>
+ </li>
+ <li>
+ <a href="index.html#how-much-disk-space-is-used-by-a-userstore">How much disk space is used by a userstore</a>
+ </li>
+ <li>
+ <a href="index.html#migrating-from-bigcouch-to-plain-couchdb">Migrating from BigCouch to plain CouchDB</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Required:</p>
+
+<ul>
+<li>Nodes with <code>couchdb</code> service must also have <code>soledad</code> service, if email is enabled.</li>
+</ul>
+
+
+<p>Suggested:</p>
+
+<ul>
+<li>Nodes with <code>couchdb</code> service communicate heavily with <code>webapp</code> and <code>mx</code>.</li>
+</ul>
+
+
+<p><code>couchdb</code> nodes do not need to be reachable from the public internet, although the <code>soledad</code> service does require this.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<h3><a name="nighly-dumps"></a>Nighly dumps</h3>
+
+<p>You can do a nightly couchdb data dump by adding this to your node config:</p>
+
+<pre><code>"couch": {
+ "backup": true
+}
+</code></pre>
+
+<p>Data will get dumped to <code>/var/backups/couchdb</code>.</p>
+
+<h3><a name="plain-couchdb"></a>Plain CouchDB</h3>
+
+<p>BigCouch is not supported on Platform version 0.8 and higher: only plain CouchDB is possible. For earlier versions, you must do this in order to use plain CouchDB:</p>
+
+<pre><code>"couch": {
+ "master": true,
+ "pwhash_alg": "pbkdf2"
+}
+</code></pre>
+
+<h2><a name="various-tasks"></a>Various Tasks</h2>
+
+<h3><a name="re-enabling-blocked-account"></a>Re-enabling blocked account</h3>
+
+<p>When a user account gets destroyed from the webapp, there&rsquo;s still a leftover doc in the identities db so other people can&rsquo;t claim that account without an admin&rsquo;s intervention. You can remove this username reservation through the webapp.</p>
+
+<p>However, here is how you could do it manually, if you wanted to:</p>
+
+<p>grep the identities db for the email address:</p>
+
+<pre><code>curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET http://127.0.0.1:5984/identities/_all_docs?include_docs=true|grep test_127@bitmask.net
+</code></pre>
+
+<p>lookup &ldquo;id&rdquo; and &ldquo;rev&rdquo; to delete the doc:</p>
+
+<pre><code>curl -s --netrc-file /etc/couchdb/couchdb.netrc -X DELETE 'http://127.0.0.1:5984/identities/b25cf10f935b58088f0d547fca823265?rev=2-715a9beba597a2ab01851676f12c3e4a'
+</code></pre>
+
+<h3><a name="how-to-find-out-which-userstore-belongs-to-which-identity"></a>How to find out which userstore belongs to which identity?</h3>
+
+<pre><code>/usr/bin/curl -s --netrc-file /etc/couchdb/couchdb.netrc '127.0.0.1:5984/identities/_all_docs?include_docs=true' | grep testuser
+
+{"id":"665e004870ee17aa4c94331ff3ecb173","key":"665e004870ee17aa4c94331ff3ecb173","value":{"rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b"},"doc":{"_id":"665e004870ee17aa4c94331ff3ecb173","_rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b","user_id":"665e004870ee17aa4c94331ff3cd59eb","address":"testuser@example.org","destination":"testuser@example.org","keys": ...
+</code></pre>
+
+<ul>
+<li>search for the &ldquo;user_id&rdquo; field</li>
+<li>in this example <a href="&#x6d;&#97;&#105;&#x6c;&#116;&#x6f;&#x3a;&#116;&#x65;&#x73;&#116;&#x75;&#x73;&#101;&#x72;&#64;&#101;&#120;&#x61;&#109;&#112;&#108;&#101;&#x2e;&#x6f;&#x72;&#103;">&#116;&#x65;&#115;&#x74;&#117;&#115;&#x65;&#x72;&#64;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#x65;&#46;&#x6f;&#114;&#103;</a> uses the database user-665e004870ee17aa4c94331ff3cd59eb</li>
+</ul>
+
+
+<h3><a name="how-much-disk-space-is-used-by-a-userstore"></a>How much disk space is used by a userstore</h3>
+
+<p>Beware that this returns the uncompacted disk size (see <a href="http://wiki.apache.org/couchdb/Compaction">http://wiki.apache.org/couchdb/Compaction</a>)</p>
+
+<pre><code>echo "`curl --netrc -s -X GET 'http://127.0.0.1:5984/user-dcd6492d74b90967b6b874100b7dbfcf'|json_pp|grep disk_size|cut -d: -f 2`/1024"|bc
+</code></pre>
+
+<h3><a name="migrating-from-bigcouch-to-plain-couchdb"></a>Migrating from BigCouch to plain CouchDB</h3>
+
+<p><p>At the end of this process, you will have just <em>one</em> node with <code>services</code> property equal to <code>couchdb</code>. If you had a BigCouch cluster before, you will be removing all but one of those machines to consolidate them into one CouchDB machine.</p>
+
+<ol>
+<li><p>if you have multiple nodes with the <code>couchdb</code> service on them, pick one of them to be your CouchDB server, and remove the service from the others. If these machines were only doing BigCouch before, you can remove the nodes completely with <code>leap node rm &lt;nodename&gt;</code> and then you can decommission the servers</p></li>
+<li><p>put the webapp into <a href="../webapp.html#maintenance-mode">maintenance mode</a></p></li>
+<li><p>turn off daemons that access the database. For example:</p>
+
+<pre><code class="`"> workstation$ leap ssh &lt;each soledad-node&gt;
+ server# /etc/init.d/soledad-server stop
+
+ workstation$ leap ssh &lt;mx-node&gt;
+ server# /etc/init.d/postfix stop
+ server# /etc/init.d/leap-mx stop
+
+ workstation$ leap ssh &lt;webapp-node&gt;
+ server# /etc/init.d/nickserver stop
+</code></pre>
+
+<p> Alternately, you can create a temporary firewall rule to block access (run on couchdb server):</p>
+
+<pre><code class="`"> server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+<li><p>remove orphaned databases and do a backup of all remaining, active databases. This can take some time and will place several hundred megabytes of data into /var/backups/couchdb. The size and time depends on how many users there are on your system. For example, 15k users took approximately 25 minutes and 308M of space:</p>
+
+<pre><code class="`"> workstation$ leap ssh &lt;couchdb-node&gt;
+ server# cd /srv/leap/couchdb/scripts
+ server# ./cleanup-user-dbs
+ server# time ./couchdb_dumpall.sh
+</code></pre></li>
+<li><p>stop bigcouch:</p>
+
+<pre><code class="`"> server# /etc/init.d/bigcouch stop
+ server# pkill epmd
+</code></pre></li>
+<li><p>remove bigcouch:</p>
+
+<pre><code class="`"> server# apt-get remove bigcouch
+</code></pre></li>
+<li><p>configure your couch node to use plain couchdb instead of bigcouch, you can do this by editing nodes/<couch-node>.json, look for this section:</p>
+
+<pre><code class="`"> "couch": {
+ "mode": "plain"
+ }
+</code></pre>
+
+<p>change it, so it looks like this instead:</p>
+
+<pre><code class="``"> "couch": {
+ "mode": "plain",
+ "pwhash_alg": "pbkdf2"
+ }
+</code></pre></li>
+</ol>
+
+</p>
+
+<p><ol>
+<li><p>restore the backup, this will take approximately the same amount of time as the backup took above:</p>
+
+<pre><code class="`"> server# cd /srv/leap/couchdb/scripts
+ server# time ./couchdb_restoreall.sh
+</code></pre></li>
+<li><p>start services again that were stopped in the beginning:</p>
+
+<pre><code class="`"> workstation$ leap ssh soledad-nodes
+ server# /etc/init.d/soledad-server start
+
+ workstation$ leap ssh mx-node
+ server# /etc/init.d/postfix start
+ server# /etc/init.d/leap-mx start
+
+ workstation$ leap ssh webapp
+ server# /etc/init.d/nickserver start
+</code></pre>
+
+<p> Or, alternately, if you set up the firewall rule instead, now remove it:</p>
+
+<pre><code class="`"> server# iptables -D INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+</ol>
+
+</p>
+
+<p><ol>
+<li><p>check if everything is working, including running the test on your deployment machine:</p>
+
+<pre><code class="`"> workstation$ leap test
+</code></pre></li>
+<li><p>Remove old bigcouch data dir <code>/opt</code> after you double checked everything is in place</p></li>
+<li><p>Relax, enjoy a refreshing beverage.</p></li>
+</ol>
+
+</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/index.html b/docs/en/services/index.html
new file mode 100644
index 00000000..6d5c68e1
--- /dev/null
+++ b/docs/en/services/index.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Services - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Guide to node services</h1>
+
+<div id='summary'></div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="index.html#available-services">Available services</a>
+ </li>
+</ol></div>
+
+<h1><a name="introduction"></a>Introduction</h1>
+
+<p>Every node (server) must have one or more <code>services</code> defined that determines what role the node performs. For example:</p>
+
+<pre><code>workstation$ cat nodes/stallman.json
+{
+ "ip_address": "199.99.99.1",
+ "services": ["webapp", "tor"]
+}
+</code></pre>
+
+<p>Here are common questions to ask when adding a new node to your provider:</p>
+
+<ul>
+<li><strong>many or few?</strong> Some services benefit from having many nodes, while some services are best run on only one or two nodes.</li>
+<li><strong>required or optional?</strong> Some services are required, while others can be left out.</li>
+<li><strong>who does the node communicate with?</strong> Some services communicate very heavily with other particular services. Nodes running these services should be close together.</li>
+<li><strong>public or private network?</strong> Some services communicate with the public internet, while others only need to communicate with other nodes in the infrastructure.</li>
+</ul>
+
+
+<h1><a name="available-services"></a>Available services</h1>
+
+<table class="table table-striped">
+<tr>
+ <th>Service</th>
+ <th>VPN</th>
+ <th>Email</th>
+ <th>Notes</th>
+</tr>
+<tr>
+ <td>webapp</td>
+ <td><i class="fa fa-circle"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>User control panel, provider API, and support system.</td>
+</tr>
+<tr>
+ <td>couchdb</td>
+ <td><i class="fa fa-circle"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>Data storage for everything. Private node.</td>
+<td></td>
+</tr>
+<tr>
+ <td>soledad</td>
+ <td><i class="fa fa-circle-o"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>User data synchronization daemon. Usually paired with <code>couchdb</code> nodes.</td>
+<td></td>
+</tr>
+<tr>
+ <td>mx</td>
+ <td><i class="fa fa-circle-o"></i></td>
+ <td><i class="fa fa-circle"></i></td>
+ <td>Incoming and outgoing MX servers.</td>
+</tr>
+<tr>
+ <td>openvpn</td>
+ <td><i class="fa fa-circle"></i></td>
+ <td><i class="fa fa-circle-o"></i></td>
+ <td>OpenVPN gateways.</td>
+</tr>
+<tr>
+ <td>monitor</td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td>Nagios monitoring. This service must be on the webapp node.</td>
+</tr>
+<tr>
+ <td>tor</td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td><i class="fa fa-dot-circle-o"></i></td>
+ <td>Tor exit node.</td>
+</tr>
+</table>
+
+
+<p>Key: <i class="fa fa-circle"> Required</i>, <i class="fa fa-dot-circle-o"> Optional</i>, <i class="fa fa-circle-o"> Not Used</i></p>
+
+<p><div class=' page-summary'>
+<h2>
+<a href='couchdb.html'>couchdb</a>
+</h2>
+<div class='summary'>Data storage for all user data.</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='openvpn.html'>openvpn</a>
+</h2>
+<div class='summary'>OpenVPN egress gateways</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='monitor.html'>monitor</a>
+</h2>
+<div class='summary'>Nagios monitoring and continuous testing.</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='mx.html'>mx</a>
+</h2>
+<div class='summary'>Incoming and outgoing MX servers.</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='soledad.html'>soledad</a>
+</h2>
+<div class='summary'>User data synchronization daemon</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='tor.html'>tor</a>
+</h2>
+<div class='summary'>Tor exit node or hidden service</div>
+</div>
+<div class=' page-summary'>
+<h2>
+<a href='webapp.html'>webapp</a>
+</h2>
+<div class='summary'>leap_web user management application and provider API.</div>
+</div>
+</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/monitor.html b/docs/en/services/monitor.html
new file mode 100644
index 00000000..5ed2e2fc
--- /dev/null
+++ b/docs/en/services/monitor.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+monitor - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class='active level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>monitor</h1>
+
+<div id='summary'>Nagios monitoring and continuous testing.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="monitor/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="monitor/index.html#configuration">Configuration</a>
+ </li>
+ <li>
+ <a href="monitor/index.html#access-nagios-web">Access nagios web</a>
+ </li>
+</ol></div>
+
+<p>The <code>monitor</code> node provides a nagios control panel that will give you a view into the health and status of all the servers and all the services. It will also spam you with alerts if something goes down.</p>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, you can have zero or one <code>monitor</code> nodes defined. It is required that the monitor be on the webapp node. It was not designed to be run as a separate node service.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<ul>
+<li><code>nagios.environments</code>: By default, the monitor node will monitor all servers in all environments. You can <strong>optionally</strong> restrict the environments to the ones you specify.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "nagios": {
+ "environments": ["unstable", "production"]
+ }
+}
+</code></pre>
+
+<h2><a name="access-nagios-web"></a>Access nagios web</h2>
+
+<p>To open the nagios control panel:</p>
+
+<pre><code>workstation$ leap open monitor
+</code></pre>
+
+<p>This will open a web browser window with the appropriate URL, including the nagios username and password.</p>
+
+<p>If the URL does not open because of HSTS or DNS problems, pass the <code>--ip</code> option to <code>leap</code>.</p>
+
+<p>If you are using an older version of <code>leap</code> command that doesn&rsquo;t include <code>leap open</code>, you can determine the nagio parameters manually:</p>
+
+<p>Step 1. find the domain:</p>
+
+<pre><code>workstation$ export DOMAIN=$(leap ls --print webapp.domain monitor | grep . | cut -f3 -d' ')
+</code></pre>
+
+<p>Step 2. find the username:</p>
+
+<pre><code>workstation$ export USERNAME="nagiosadmin"
+</code></pre>
+
+<p>Step 3. find the password:</p>
+
+<pre><code>workstation$ export PASSWORD=$(grep nagios_admin_password secrets.json | cut -f4 -d\")
+</code></pre>
+
+<p>Step 4. put it all together:</p>
+
+<pre><code>workstation$ sensible-browser "https://$USERNAME:$PASSWORD@$DOMAIN/nagios3"
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/monitor/index.html b/docs/en/services/monitor/index.html
new file mode 100644
index 00000000..f6a16cdf
--- /dev/null
+++ b/docs/en/services/monitor/index.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+monitor - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class='active level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>monitor</h1>
+
+<div id='summary'>Nagios monitoring and continuous testing.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ </li>
+ <li>
+ <a href="index.html#access-nagios-web">Access nagios web</a>
+ </li>
+</ol></div>
+
+<p>The <code>monitor</code> node provides a nagios control panel that will give you a view into the health and status of all the servers and all the services. It will also spam you with alerts if something goes down.</p>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, you can have zero or one <code>monitor</code> nodes defined. It is required that the monitor be on the webapp node. It was not designed to be run as a separate node service.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<ul>
+<li><code>nagios.environments</code>: By default, the monitor node will monitor all servers in all environments. You can <strong>optionally</strong> restrict the environments to the ones you specify.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "nagios": {
+ "environments": ["unstable", "production"]
+ }
+}
+</code></pre>
+
+<h2><a name="access-nagios-web"></a>Access nagios web</h2>
+
+<p>To open the nagios control panel:</p>
+
+<pre><code>workstation$ leap open monitor
+</code></pre>
+
+<p>This will open a web browser window with the appropriate URL, including the nagios username and password.</p>
+
+<p>If the URL does not open because of HSTS or DNS problems, pass the <code>--ip</code> option to <code>leap</code>.</p>
+
+<p>If you are using an older version of <code>leap</code> command that doesn&rsquo;t include <code>leap open</code>, you can determine the nagio parameters manually:</p>
+
+<p>Step 1. find the domain:</p>
+
+<pre><code>workstation$ export DOMAIN=$(leap ls --print webapp.domain monitor | grep . | cut -f3 -d' ')
+</code></pre>
+
+<p>Step 2. find the username:</p>
+
+<pre><code>workstation$ export USERNAME="nagiosadmin"
+</code></pre>
+
+<p>Step 3. find the password:</p>
+
+<pre><code>workstation$ export PASSWORD=$(grep nagios_admin_password secrets.json | cut -f4 -d\")
+</code></pre>
+
+<p>Step 4. put it all together:</p>
+
+<pre><code>workstation$ sensible-browser "https://$USERNAME:$PASSWORD@$DOMAIN/nagios3"
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/mx.html b/docs/en/services/mx.html
new file mode 100644
index 00000000..0d693204
--- /dev/null
+++ b/docs/en/services/mx.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+mx - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class='active level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>mx</h1>
+
+<div id='summary'>Incoming and outgoing MX servers.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="mx/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="mx/index.html#configuration">Configuration</a>
+ <ol>
+ <li>
+ <a href="mx/index.html#aliases">Aliases</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p><code>mx</code> nodes communicate with the public internet, clients, and <code>couchdb</code> nodes.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<h3><a name="aliases"></a>Aliases</h3>
+
+<p>Using the <code>mx.aliases</code> property, you can specify your own hard-coded email aliases that precedence over the aliases in the user database. The <code>mx.aliases</code> property consists of a hash, where source address points to one or more destination addresses.</p>
+
+<p>For example:</p>
+
+<p><code>services/mx.json</code>:</p>
+
+<pre><code>"mx": {
+ "aliases": {
+ "rook": "crow",
+ "robin": "robin@bird.org",
+ "flock": ["junco@bird.org", "robin", "crow"],
+ "chickadee@avian.org": "chickadee@bird.org",
+ "flicker": ["flicker@bird.org", "flicker@deliver.local"]
+ }
+}
+</code></pre>
+
+<p>This example demonstrates several of the features with <code>mx.aliases</code>:</p>
+
+<ol>
+<li>alias lists: by specifying an array of destination addresses, as in the case of &ldquo;flock&rdquo;, the single email will get copied to each address.</li>
+<li>chained resolution: alias resolution will recursively continue until there are no more matching aliases. For example, &ldquo;flock&rdquo; is resolved to &ldquo;robin&rdquo;, which then gets resolved to &ldquo;<a href="&#x6d;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#114;&#111;&#x62;&#105;&#110;&#x40;&#x62;&#x69;&#x72;&#x64;&#x2e;&#111;&#114;&#x67;">&#x72;&#111;&#x62;&#105;&#110;&#x40;&#x62;&#105;&#114;&#100;&#x2e;&#x6f;&#114;&#x67;</a>&rdquo;.</li>
+<li>virtual domains: by specifying the full domain, as in the case of &ldquo;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#x63;&#x68;&#x69;&#99;&#107;&#97;&#100;&#x65;&#x65;&#x40;&#97;&#x76;&#105;&#97;&#110;&#46;&#111;&#114;&#103;">&#99;&#104;&#x69;&#99;&#x6b;&#x61;&#x64;&#101;&#x65;&#x40;&#97;&#x76;&#105;&#x61;&#x6e;&#x2e;&#111;&#x72;&#x67;</a>&rdquo;, the alias will work for any domain you want. Of course, the MX record for that domain must point to appropriate MX servers, but otherwise you don&rsquo;t need to do any additional configuration.</li>
+<li>local delivery: for testing purposes, it is often useful to copy all incoming mail for a particular address and send those copies to another address. You can do this by adding &ldquo;@deliver.local&rdquo; as one of the destination addresses. When &ldquo;@local.delivery&rdquo; is found, alias resolution stops and the mail is delivered to that username.</li>
+</ol>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/mx/index.html b/docs/en/services/mx/index.html
new file mode 100644
index 00000000..639d9039
--- /dev/null
+++ b/docs/en/services/mx/index.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+mx - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class='active level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>mx</h1>
+
+<div id='summary'>Incoming and outgoing MX servers.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ <ol>
+ <li>
+ <a href="index.html#aliases">Aliases</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p><code>mx</code> nodes communicate with the public internet, clients, and <code>couchdb</code> nodes.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<h3><a name="aliases"></a>Aliases</h3>
+
+<p>Using the <code>mx.aliases</code> property, you can specify your own hard-coded email aliases that precedence over the aliases in the user database. The <code>mx.aliases</code> property consists of a hash, where source address points to one or more destination addresses.</p>
+
+<p>For example:</p>
+
+<p><code>services/mx.json</code>:</p>
+
+<pre><code>"mx": {
+ "aliases": {
+ "rook": "crow",
+ "robin": "robin@bird.org",
+ "flock": ["junco@bird.org", "robin", "crow"],
+ "chickadee@avian.org": "chickadee@bird.org",
+ "flicker": ["flicker@bird.org", "flicker@deliver.local"]
+ }
+}
+</code></pre>
+
+<p>This example demonstrates several of the features with <code>mx.aliases</code>:</p>
+
+<ol>
+<li>alias lists: by specifying an array of destination addresses, as in the case of &ldquo;flock&rdquo;, the single email will get copied to each address.</li>
+<li>chained resolution: alias resolution will recursively continue until there are no more matching aliases. For example, &ldquo;flock&rdquo; is resolved to &ldquo;robin&rdquo;, which then gets resolved to &ldquo;<a href="&#x6d;&#97;&#x69;&#x6c;&#116;&#x6f;&#x3a;&#114;&#111;&#x62;&#105;&#110;&#64;&#98;&#x69;&#x72;&#x64;&#x2e;&#111;&#x72;&#x67;">&#x72;&#111;&#x62;&#105;&#x6e;&#64;&#98;&#105;&#114;&#100;&#46;&#111;&#x72;&#x67;</a>&rdquo;.</li>
+<li>virtual domains: by specifying the full domain, as in the case of &ldquo;<a href="&#x6d;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#x63;&#104;&#105;&#x63;&#x6b;&#x61;&#100;&#101;&#101;&#x40;&#x61;&#118;&#105;&#x61;&#x6e;&#46;&#x6f;&#114;&#103;">&#x63;&#104;&#x69;&#99;&#x6b;&#97;&#x64;&#101;&#x65;&#64;&#97;&#118;&#x69;&#x61;&#110;&#46;&#111;&#x72;&#103;</a>&rdquo;, the alias will work for any domain you want. Of course, the MX record for that domain must point to appropriate MX servers, but otherwise you don&rsquo;t need to do any additional configuration.</li>
+<li>local delivery: for testing purposes, it is often useful to copy all incoming mail for a particular address and send those copies to another address. You can do this by adding &ldquo;@deliver.local&rdquo; as one of the destination addresses. When &ldquo;@local.delivery&rdquo; is found, alias resolution stops and the mail is delivered to that username.</li>
+</ol>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/openvpn.html b/docs/en/services/openvpn.html
new file mode 100644
index 00000000..e5fe1128
--- /dev/null
+++ b/docs/en/services/openvpn.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+openvpn - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class='active level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>openvpn</h1>
+
+<div id='summary'>OpenVPN egress gateways</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="openvpn/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="openvpn/index.html#configuration">Configuration</a>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, <code>openvpn</code> service should not be combined with other services on the same node.</p>
+
+<p>Unlike most of the other node types, the <code>openvpn</code> nodes do not need access to the database and does not ever communicate with any other nodes (except for the <code>monitor</code> node, if used). So, <code>openvpn</code> nodes can be placed anywhere without regard to the other nodes.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p><em>Essential configuration</em></p>
+
+<ul>
+<li><code>openvpn.gateway_address</code>: The address that OpenVPN daemon is bound to and that VPN clients connect to.</li>
+<li><code>ip_address</code>: The main IP of the server, and the egress address for outgoing traffic.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "openvpn": {
+ "gateway_address": "2.2.2.2"
+ }
+}
+</code></pre>
+
+<p>In this example, VPN clients will connect to 2.2.2.2, but their traffic will appear to come from 1.1.1.1.</p>
+
+<p>Why are two IP addresses needed? Without this, traffic between two VPN users on the same gateway will not get encrypted. This is because the VPN on every client must be configured to allow cleartext traffic for the IP address that is the VPN gateway.</p>
+
+<p><em>Optional configuration</em></p>
+
+<p>Here is the default configuration:</p>
+
+<pre><code>"openvpn": {
+ "configuration": {
+ "auth": "SHA1",
+ "cipher": "AES-128-CBC",
+ "fragment": 1400,
+ "keepalive": "10 30",
+ "tls-cipher": "DHE-RSA-AES128-SHA",
+ "tun-ipv6": true
+ },
+ "ports": ["80", "443", "53", "1194"],
+ "protocols": ["tcp", "udp"]
+}
+</code></pre>
+
+<p>You may want to change the ports so that only 443 or 80 are used. It is probably best to not modify the <code>openvpn.configuration</code> options for now.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/openvpn/index.html b/docs/en/services/openvpn/index.html
new file mode 100644
index 00000000..4a9dc993
--- /dev/null
+++ b/docs/en/services/openvpn/index.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+openvpn - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class='active level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>openvpn</h1>
+
+<div id='summary'>OpenVPN egress gateways</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, <code>openvpn</code> service should not be combined with other services on the same node.</p>
+
+<p>Unlike most of the other node types, the <code>openvpn</code> nodes do not need access to the database and does not ever communicate with any other nodes (except for the <code>monitor</code> node, if used). So, <code>openvpn</code> nodes can be placed anywhere without regard to the other nodes.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p><em>Essential configuration</em></p>
+
+<ul>
+<li><code>openvpn.gateway_address</code>: The address that OpenVPN daemon is bound to and that VPN clients connect to.</li>
+<li><code>ip_address</code>: The main IP of the server, and the egress address for outgoing traffic.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "openvpn": {
+ "gateway_address": "2.2.2.2"
+ }
+}
+</code></pre>
+
+<p>In this example, VPN clients will connect to 2.2.2.2, but their traffic will appear to come from 1.1.1.1.</p>
+
+<p>Why are two IP addresses needed? Without this, traffic between two VPN users on the same gateway will not get encrypted. This is because the VPN on every client must be configured to allow cleartext traffic for the IP address that is the VPN gateway.</p>
+
+<p><em>Optional configuration</em></p>
+
+<p>Here is the default configuration:</p>
+
+<pre><code>"openvpn": {
+ "configuration": {
+ "auth": "SHA1",
+ "cipher": "AES-128-CBC",
+ "fragment": 1400,
+ "keepalive": "10 30",
+ "tls-cipher": "DHE-RSA-AES128-SHA",
+ "tun-ipv6": true
+ },
+ "ports": ["80", "443", "53", "1194"],
+ "protocols": ["tcp", "udp"]
+}
+</code></pre>
+
+<p>You may want to change the ports so that only 443 or 80 are used. It is probably best to not modify the <code>openvpn.configuration</code> options for now.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/soledad.html b/docs/en/services/soledad.html
new file mode 100644
index 00000000..be372401
--- /dev/null
+++ b/docs/en/services/soledad.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+soledad - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class='active level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>soledad</h1>
+
+<div id='summary'>User data synchronization daemon</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="soledad/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="soledad/index.html#configuration">Configuration</a>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, the platform is designed for <code>soledad</code> and <code>couchdb</code> services to be combined (e.g. every <code>soledad</code> node should also be a <code>couchdb</code> node). <code>soledad</code> nodes might work in isolation, but this is not tested.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p>There are no options to configure for <code>soledad</code> nodes.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/soledad/index.html b/docs/en/services/soledad/index.html
new file mode 100644
index 00000000..33e72046
--- /dev/null
+++ b/docs/en/services/soledad/index.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+soledad - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class='active level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>soledad</h1>
+
+<div id='summary'>User data synchronization daemon</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, the platform is designed for <code>soledad</code> and <code>couchdb</code> services to be combined (e.g. every <code>soledad</code> node should also be a <code>couchdb</code> node). <code>soledad</code> nodes might work in isolation, but this is not tested.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p>There are no options to configure for <code>soledad</code> nodes.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/tor.html b/docs/en/services/tor.html
new file mode 100644
index 00000000..f649c086
--- /dev/null
+++ b/docs/en/services/tor.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+tor - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class='active level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>tor</h1>
+
+<div id='summary'>Tor exit node or hidden service</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="tor/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="tor/index.html#configuration">Configuration</a>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Nodes with <code>tor</code> service will run a Tor exit or hidden service, depending on what other service it is paired with:</p>
+
+<ul>
+<li><code>tor</code> + <code>openvpn</code>: when combined with <code>openvpn</code> nodes, <code>tor</code> will create a Tor exit node to provide extra cover traffic for the VPN. This can be especially useful if there are VPN gateways without much traffic.</li>
+<li><code>tor</code> + <code>webapp</code>: when combined with a <code>webapp</code> node, the <code>tor</code> service will make the webapp and the API available via .onion hidden service.</li>
+<li><code>tor</code> stand alone: a regular Tor exit node.</li>
+</ul>
+
+
+<p>If activated, you can list the hidden service .onion addresses this way:</p>
+
+<p> leap ls &ndash;print tor.hidden_service.address tor</p>
+
+<p>Then just add &lsquo;.onion&rsquo; to the end of the printed addresses.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<ul>
+<li><code>tor.bandwidth_rate</code>: the max bandwidth allocated to Tor, in KB per second, when used as an exit node.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "tor": {
+ "bandwidth_rate": 6550
+ }
+}
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/tor/index.html b/docs/en/services/tor/index.html
new file mode 100644
index 00000000..8fecf152
--- /dev/null
+++ b/docs/en/services/tor/index.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+tor - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class='active level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>tor</h1>
+
+<div id='summary'>Tor exit node or hidden service</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ </li>
+</ol></div>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Nodes with <code>tor</code> service will run a Tor exit or hidden service, depending on what other service it is paired with:</p>
+
+<ul>
+<li><code>tor</code> + <code>openvpn</code>: when combined with <code>openvpn</code> nodes, <code>tor</code> will create a Tor exit node to provide extra cover traffic for the VPN. This can be especially useful if there are VPN gateways without much traffic.</li>
+<li><code>tor</code> + <code>webapp</code>: when combined with a <code>webapp</code> node, the <code>tor</code> service will make the webapp and the API available via .onion hidden service.</li>
+<li><code>tor</code> stand alone: a regular Tor exit node.</li>
+</ul>
+
+
+<p>If activated, you can list the hidden service .onion addresses this way:</p>
+
+<p> leap ls &ndash;print tor.hidden_service.address tor</p>
+
+<p>Then just add &lsquo;.onion&rsquo; to the end of the printed addresses.</p>
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<ul>
+<li><code>tor.bandwidth_rate</code>: the max bandwidth allocated to Tor, in KB per second, when used as an exit node.</li>
+</ul>
+
+
+<p>For example:</p>
+
+<pre><code>{
+ "tor": {
+ "bandwidth_rate": 6550
+ }
+}
+</code></pre>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/webapp.html b/docs/en/services/webapp.html
new file mode 100644
index 00000000..6c853c22
--- /dev/null
+++ b/docs/en/services/webapp.html
@@ -0,0 +1,479 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+webapp - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='tor.html'>tor</a>
+</li>
+<li class='active level1'>
+<a class='' href='webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>webapp</h1>
+
+<div id='summary'>leap_web user management application and provider API.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="webapp/index.html#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#configuration">Configuration</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#invite-codes">Invite codes</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#customization">Customization</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#customization-tutorial">Customization tutorial</a>
+ <ol>
+ <li>
+ <a href="webapp/index.html#override-translations">Override translations</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#override-static-pages">Override static pages</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#add-a-custom-header">Add a custom header</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="webapp/index.html#custom-fork">Custom Fork</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#maintenance-mode">Maintenance mode</a>
+ </li>
+ <li>
+ <a href="webapp/index.html#known-problems">Known problems</a>
+ </li>
+</ol></div>
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>The service <code>webapp</code> will install the web application <a href="https://leap.se/git/leap_web.git">leap_web</a>. It has performs the following functions:</p>
+
+<ul>
+<li>REST API for user registration and authentication via the Bitmask client.</li>
+<li>Admin interface to manage users.</li>
+<li>Client certificate distribution and renewal.</li>
+<li>User support help tickets.</li>
+</ul>
+
+
+<p>Coming soon:</p>
+
+<ul>
+<li>Billing.</li>
+<li>Customizable and localized user documentation.</li>
+</ul>
+
+
+<p>The leap_web application is written in Ruby on Rails 3, using CouchDB as the backend data store.</p>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, the platform only supports a single <code>webapp</code> node, although we hope to change this in the future.</p>
+
+<ul>
+<li><code>webapp</code> nodes communicate heavily with <code>couchdb</code> nodes, but the two can be on separate servers.</li>
+<li>The <code>monitor</code> service, if enabled, must be on the same node as <code>webapp</code>.</li>
+</ul>
+
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p>Essential options:</p>
+
+<ul>
+<li><code>webapp.admin</code>: An array of usernames that will be blessed with administrative permissions. These admins can delete users, answer help tickets, and so on. These usernames are for users that have registered through the webapp or through the Bitmask client application, NOT the sysadmin usernames lists in the provider directory <code>users</code>.</li>
+</ul>
+
+
+<p>Other options:</p>
+
+<ul>
+<li><code>webapp.engines</code>: A list of the engines you want enabled in leap_web. Currently, only &ldquo;support&rdquo; is available, and it is enabled by default.</li>
+<li><code>webapp.invite_required</code>: If true, registration requires an invite code. Default is <code>false</code>.</li>
+</ul>
+
+
+<p>For example, <code>services/webapp.json</code>:</p>
+
+<pre><code>{
+ "webapp": {
+ "admins": ["joehill", "ali", "mack_the_turtle"]
+ }
+}
+</code></pre>
+
+<p>By putting this in <code>services/webapp.json</code>, all the <code>webapp</code> nodes will inherit the same admin list.</p>
+
+<p>There are many options in <code>provider.json</code> that also control how the webapp behaves. See <a href="../guide/provider-configuration.html">Provider Configuration</a> for details.</p>
+
+<h2><a name="invite-codes"></a>Invite codes</h2>
+
+<p>Enabling the invite code functionality will require new users to provide a valid invite code while signing up for a new account. This is turned off by default, allowing all new users to create an account.</p>
+
+<p>Set the <code>invite_code</code> option to <code>true</code> in <code>services/webapp.json</code>:</p>
+
+<pre><code>{
+ "webapp": {
+ "invite_required": true
+ }
+}
+</code></pre>
+
+<p>This only works with LEAP platform 0.8 or higher.</p>
+
+<p>Run <code>leap deploy</code> to enable the option.</p>
+
+<p>You can then generate invite codes by logging into the web application with an admin user.</p>
+
+<p>Alternately, you can also generate invite codes with the command line:</p>
+
+<pre><code>workstation$ leap ssh bumblebee
+bumblebee# cd /srv/leap/webapp/
+bumblebee# sudo -u leap-webapp RAILS_ENV=production bundle exec rake "generate_invites[NUM,USES]"
+</code></pre>
+
+<p>Where <code>bumblebee</code> should be replaced with the name of your webapp node.</p>
+
+<p>The <strong>NUM</strong> specifies the amount of codes to generate. The <strong>USES</strong> parameter is optional: By default, all new invite codes can be used once and will then become invalid. If you provide another value for <strong>USES</strong>, you can set a different amount of maximum uses for the codes you generate.</p>
+
+<h2><a name="customization"></a>Customization</h2>
+
+<p>The provider directory <code>files/webapp</code> can be used to customize the appearance of the webapp. All the files in this directory will get sync'ed to the <code>/srv/leap/webapp/config/customization</code> directory of the deployed webapp node.</p>
+
+<p>Files in the <code>files/webapp</code> can override view files, locales, and stylesheets in the leap_web app:</p>
+
+<p>For example:</p>
+
+<pre><code>stylesheets/ -- override files in Rails.root/app/assets/stylesheets
+ tail.scss -- included before all others
+ head.scss -- included after all others
+
+public/ -- overrides files in Rails.root/public
+ favicon.ico -- custom favicon
+ img/ -- customary directory to put images in
+
+views/ -- overrides files Rails.root/app/views
+ home/
+ index.html.haml -- this file is what shows up on
+ the home page
+ pages/
+ privacy-policy.en.md -- this file will override
+ the default privacy policy
+ terms-of-service.en.md -- this file will override
+ the default TOS.
+
+locales/ -- overrides files in Rails.root/config/locales
+ en.yml -- overrides for English
+ de.yml -- overrides for German
+ and so on...
+</code></pre>
+
+<p>To interactively develop your customizations before you deploy them, you have two options:</p>
+
+<ol>
+<li>Edit a <code>webapp</code> node. This approach involves directly modifying the contents of the directory <code>/srv/leap/webapp/config/customization</code> on a deployed <code>webapp</code> node. This can, and probably should be, a &ldquo;local&rdquo; node. When doing this, you may need to restart leap_web in order for changes to take effect (<code>touch /srv/leap/webapp/tmp/restart.txt</code>).</li>
+<li>Alternately, you can install leap_web to run on your computer and edit files in <code>config/customization</code> locally. This approach does not require a provider or a <code>webapp</code> node. For more information, see the <a href="https://github.com/leapcode/leap_web">leap_web README</a>.</li>
+</ol>
+
+
+<p>NOTE: If you add a <code>tails.scss</code> or <code>head.scss</code> file, then you usually need to run <code>rake tmp:clear</code> and restart rails in order for the new stylesheet to get recognized. You should only need to do this once.</p>
+
+<p>Once you have what you want, then copy these files to the local provider directory <code>files/webapp</code> so that they will be installed each time you deploy.</p>
+
+<h2><a name="customization-tutorial"></a>Customization tutorial</h2>
+
+<p>This mini-tutorial will walk you through creating a custom &ldquo;branding&rdquo; of the leap_web application. We will be creating a provider called &ldquo;Prehistoric Computer.&rdquo;</p>
+
+<p>Here are the files we are going to create:</p>
+
+<pre><code>leap_web/config/customization
+├── locales
+│   ├── en.yml
+│   └── es.yml
+├── public
+│   ├── favicon.ico
+│   └── img
+│   └── masthead.png
+├── stylesheets
+│   └── tail.scss
+└── views
+ └── pages
+ ├── privacy-policy.en.md
+ └── privacy-policy.es.md
+</code></pre>
+
+<p>All these files are available in the source code in the <a href="https://github.com/leapcode/leap_web/tree/develop/config/customization.example">customization.example</a> directory.</p>
+
+<p>Remember, these files may live different places:</p>
+
+<ul>
+<li><code>user@localmachine$ leap_web/config/customization</code>: This will be the path if you have checked out a local copy of leap_web.git and are running <code>rails server</code> locally in order to test your customizations.</li>
+<li><code>user@localmachine$ PROVIDER/files/webapp</code>: This is the local provider directory where the files should be put so that they get correctly deployed to webapp nodes.</li>
+<li><code>root@webappnode# /srv/leap/webapp/config/customization</code>: This is where the files in the local provider directory <code>PROVIDER/files/webapp</code> get copied to after a <code>leap deploy</code> to a live webapp nodes.</li>
+</ul>
+
+
+<h3><a name="override-translations"></a>Override translations</h3>
+
+<p>You can add additional locale files in order to change the text used in the existing application and to add translations for string that you added to the application.</p>
+
+<p>In this example, we will be altering the default text for the &ldquo;login_info&rdquo; string. In <code>config/locales/en/home.en.yml</code> there is this entry:</p>
+
+<pre><code>en:
+ login_info: "Log in to change your account settings, create support tickets, and manage payments."
+</code></pre>
+
+<p>We are going to override this with some custom text in English and Spanish:</p>
+
+<p><code>leap_web/config/customization/locale/en.yml</code>:</p>
+
+<pre><code>en:
+ login_info: Authenticate to change your "Prehistoric Computer" settings.
+</code></pre>
+
+<p><code>leap_web/config/customization/locale/es.yml</code>:</p>
+
+<pre><code>es:
+ login_info: Autenticar a cambiar la configuración de "Computer Prehistoria."
+</code></pre>
+
+<p>Now, the home page of leap_web will use these new strings instead of the default. Remember that you must restart rails in order for new locale files to take effect.</p>
+
+<h3><a name="override-static-pages"></a>Override static pages</h3>
+
+<p>You can also override any of the static files included with leap_web, such as the privacy policy or terms of service.</p>
+
+<p>Here is how we would create a custom privacy policy in English and Spanish:</p>
+
+<p><code>leap_web/config/customization/views/pages/privacy-policy.en.md</code>:</p>
+
+<pre><code># Custom Privacy Policy
+This is our privacy policy.
+</code></pre>
+
+<p><code>leap_web/config/customization/views/pages/privacy-policy.es.md</code>:</p>
+
+<pre><code># Custom Política de Privacidad
+Esta es nuestra política de privacidad.
+</code></pre>
+
+<h3><a name="add-a-custom-header"></a>Add a custom header</h3>
+
+<p>Now we will add a custom header to every page. First, we add the images:</p>
+
+<pre><code>leap_web/config/customization
+ ├── public
+ ├── favicon.ico
+ └── img
+ └── masthead.png
+</code></pre>
+
+<p>You can create your own, or use the example files in <a href="https://github.com/leapcode/leap_web/tree/develop/config/customization.example">https://github.com/leapcode/leap_web/tree/develop/config/customization.example</a></p>
+
+<p>Now, we add some custom CSS so that we can style the masthead:</p>
+
+<p><code>leap_web/config/customization/stylesheets/tail.scss</code></p>
+
+<pre><code>$custom-color: #66bbaa;
+
+a {
+ color: $custom-color;
+}
+
+//
+// MASTHEAD
+//
+
+#masthead {
+ background-color: $custom-color;
+ border-bottom: none;
+
+ // make the masthead clickable by replacing the
+ // site name link with the masthead image:
+ .title {
+ padding: 0px;
+ .sitename a {
+ display: block;
+ background: url(/img/masthead.png) 0 0 no-repeat;
+ font-size: 0px;
+ height: 100px;
+ background-size: auto 100px;
+ }
+ }
+}
+
+// make the home page masthead slightly larger
+body.home #masthead {
+ .sitename a {
+ height: 150px;
+ background-size: auto 150px;
+ }
+}
+
+//
+// FOOTER
+//
+
+#footer .links {
+ background-color: $custom-color;
+}
+</code></pre>
+
+<p>NOTE: If you add a <code>tails.scss</code> or <code>head.scss</code> file, then you usually need to run <code>rake tmp:clear</code> and restart rails in order for the new stylesheet to get recognized. You should only need to do this once.</p>
+
+<h2><a name="custom-fork"></a>Custom Fork</h2>
+
+<p>Sometimes it is easier to maintain your own fork of the leap_web app. You can keep your customizations in that fork instead of in the provider <code>files/webapp</code> directory. Or, perhaps you want to add an engine to the application that modifies the app&rsquo;s behavior.</p>
+
+<p>To deploy your own leap_web, modify the provider file <code>common.json</code>:</p>
+
+<pre><code>{
+ "sources": {
+ "webapp": {
+ "revision": "origin/develop",
+ "source": "https://github.com/leapcode/leap_web",
+ "type": "git"
+ }
+ }
+}
+</code></pre>
+
+<p>To target only particular environment, modify instead <code>common.ENV.json</code>, where ENV is the name of the environment.</p>
+
+<p>See <a href="https://github.com/leapcode/leap_web/blob/develop/doc/DEVELOP.md">https://github.com/leapcode/leap_web/blob/develop/doc/DEVELOP.md</a> for notes on getting started hacking on leap_web.</p>
+
+<h2><a name="maintenance-mode"></a>Maintenance mode</h2>
+
+<p>You can put the webapp into maintenance mode by simply dropping a html file to <code>/srv/leap/webapp/public/system/maintenance.html</code>. For example:</p>
+
+<pre><code>workstation$ leap ssh webappnode
+server# echo "Temporarily down for maintenance. We will be back soon." &gt; /srv/leap/webapp/public/system/maintenance.html
+</code></pre>
+
+<h2><a name="known-problems"></a>Known problems</h2>
+
+<ul>
+<li>Client certificates are generated without a CSR. The problem is that this makes the web
+application extremely vulnerable to denial of service attacks. This was not an issue until we
+started to allow the possibility of anonymously fetching a client certificate without
+authenticating first.</li>
+<li>By its very nature, the user database is vulnerable to enumeration attacks. These are
+very hard to prevent, because our protocol is designed to allow query of a user database via
+proxy in order to provide network perspective.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/services/webapp/index.html b/docs/en/services/webapp/index.html
new file mode 100644
index 00000000..acdc098c
--- /dev/null
+++ b/docs/en/services/webapp/index.html
@@ -0,0 +1,479 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+webapp - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level1'>
+<a class='' href='../couchdb.html'>couchdb</a>
+</li>
+<li class=' level1'>
+<a class='' href='../openvpn.html'>openvpn</a>
+</li>
+<li class=' level1'>
+<a class='' href='../monitor.html'>monitor</a>
+</li>
+<li class=' level1'>
+<a class='' href='../mx.html'>mx</a>
+</li>
+<li class=' level1'>
+<a class='' href='../soledad.html'>soledad</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tor.html'>tor</a>
+</li>
+<li class='active level1'>
+<a class='' href='../webapp.html'>webapp</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>webapp</h1>
+
+<div id='summary'>leap_web user management application and provider API.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="index.html#topology">Topology</a>
+ </li>
+ <li>
+ <a href="index.html#configuration">Configuration</a>
+ </li>
+ <li>
+ <a href="index.html#invite-codes">Invite codes</a>
+ </li>
+ <li>
+ <a href="index.html#customization">Customization</a>
+ </li>
+ <li>
+ <a href="index.html#customization-tutorial">Customization tutorial</a>
+ <ol>
+ <li>
+ <a href="index.html#override-translations">Override translations</a>
+ </li>
+ <li>
+ <a href="index.html#override-static-pages">Override static pages</a>
+ </li>
+ <li>
+ <a href="index.html#add-a-custom-header">Add a custom header</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#custom-fork">Custom Fork</a>
+ </li>
+ <li>
+ <a href="index.html#maintenance-mode">Maintenance mode</a>
+ </li>
+ <li>
+ <a href="index.html#known-problems">Known problems</a>
+ </li>
+</ol></div>
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>The service <code>webapp</code> will install the web application <a href="https://leap.se/git/leap_web.git">leap_web</a>. It has performs the following functions:</p>
+
+<ul>
+<li>REST API for user registration and authentication via the Bitmask client.</li>
+<li>Admin interface to manage users.</li>
+<li>Client certificate distribution and renewal.</li>
+<li>User support help tickets.</li>
+</ul>
+
+
+<p>Coming soon:</p>
+
+<ul>
+<li>Billing.</li>
+<li>Customizable and localized user documentation.</li>
+</ul>
+
+
+<p>The leap_web application is written in Ruby on Rails 3, using CouchDB as the backend data store.</p>
+
+<h2><a name="topology"></a>Topology</h2>
+
+<p>Currently, the platform only supports a single <code>webapp</code> node, although we hope to change this in the future.</p>
+
+<ul>
+<li><code>webapp</code> nodes communicate heavily with <code>couchdb</code> nodes, but the two can be on separate servers.</li>
+<li>The <code>monitor</code> service, if enabled, must be on the same node as <code>webapp</code>.</li>
+</ul>
+
+
+<h2><a name="configuration"></a>Configuration</h2>
+
+<p>Essential options:</p>
+
+<ul>
+<li><code>webapp.admin</code>: An array of usernames that will be blessed with administrative permissions. These admins can delete users, answer help tickets, and so on. These usernames are for users that have registered through the webapp or through the Bitmask client application, NOT the sysadmin usernames lists in the provider directory <code>users</code>.</li>
+</ul>
+
+
+<p>Other options:</p>
+
+<ul>
+<li><code>webapp.engines</code>: A list of the engines you want enabled in leap_web. Currently, only &ldquo;support&rdquo; is available, and it is enabled by default.</li>
+<li><code>webapp.invite_required</code>: If true, registration requires an invite code. Default is <code>false</code>.</li>
+</ul>
+
+
+<p>For example, <code>services/webapp.json</code>:</p>
+
+<pre><code>{
+ "webapp": {
+ "admins": ["joehill", "ali", "mack_the_turtle"]
+ }
+}
+</code></pre>
+
+<p>By putting this in <code>services/webapp.json</code>, all the <code>webapp</code> nodes will inherit the same admin list.</p>
+
+<p>There are many options in <code>provider.json</code> that also control how the webapp behaves. See <a href="../../guide/provider-configuration.html">Provider Configuration</a> for details.</p>
+
+<h2><a name="invite-codes"></a>Invite codes</h2>
+
+<p>Enabling the invite code functionality will require new users to provide a valid invite code while signing up for a new account. This is turned off by default, allowing all new users to create an account.</p>
+
+<p>Set the <code>invite_code</code> option to <code>true</code> in <code>services/webapp.json</code>:</p>
+
+<pre><code>{
+ "webapp": {
+ "invite_required": true
+ }
+}
+</code></pre>
+
+<p>This only works with LEAP platform 0.8 or higher.</p>
+
+<p>Run <code>leap deploy</code> to enable the option.</p>
+
+<p>You can then generate invite codes by logging into the web application with an admin user.</p>
+
+<p>Alternately, you can also generate invite codes with the command line:</p>
+
+<pre><code>workstation$ leap ssh bumblebee
+bumblebee# cd /srv/leap/webapp/
+bumblebee# sudo -u leap-webapp RAILS_ENV=production bundle exec rake "generate_invites[NUM,USES]"
+</code></pre>
+
+<p>Where <code>bumblebee</code> should be replaced with the name of your webapp node.</p>
+
+<p>The <strong>NUM</strong> specifies the amount of codes to generate. The <strong>USES</strong> parameter is optional: By default, all new invite codes can be used once and will then become invalid. If you provide another value for <strong>USES</strong>, you can set a different amount of maximum uses for the codes you generate.</p>
+
+<h2><a name="customization"></a>Customization</h2>
+
+<p>The provider directory <code>files/webapp</code> can be used to customize the appearance of the webapp. All the files in this directory will get sync'ed to the <code>/srv/leap/webapp/config/customization</code> directory of the deployed webapp node.</p>
+
+<p>Files in the <code>files/webapp</code> can override view files, locales, and stylesheets in the leap_web app:</p>
+
+<p>For example:</p>
+
+<pre><code>stylesheets/ -- override files in Rails.root/app/assets/stylesheets
+ tail.scss -- included before all others
+ head.scss -- included after all others
+
+public/ -- overrides files in Rails.root/public
+ favicon.ico -- custom favicon
+ img/ -- customary directory to put images in
+
+views/ -- overrides files Rails.root/app/views
+ home/
+ index.html.haml -- this file is what shows up on
+ the home page
+ pages/
+ privacy-policy.en.md -- this file will override
+ the default privacy policy
+ terms-of-service.en.md -- this file will override
+ the default TOS.
+
+locales/ -- overrides files in Rails.root/config/locales
+ en.yml -- overrides for English
+ de.yml -- overrides for German
+ and so on...
+</code></pre>
+
+<p>To interactively develop your customizations before you deploy them, you have two options:</p>
+
+<ol>
+<li>Edit a <code>webapp</code> node. This approach involves directly modifying the contents of the directory <code>/srv/leap/webapp/config/customization</code> on a deployed <code>webapp</code> node. This can, and probably should be, a &ldquo;local&rdquo; node. When doing this, you may need to restart leap_web in order for changes to take effect (<code>touch /srv/leap/webapp/tmp/restart.txt</code>).</li>
+<li>Alternately, you can install leap_web to run on your computer and edit files in <code>config/customization</code> locally. This approach does not require a provider or a <code>webapp</code> node. For more information, see the <a href="https://github.com/leapcode/leap_web">leap_web README</a>.</li>
+</ol>
+
+
+<p>NOTE: If you add a <code>tails.scss</code> or <code>head.scss</code> file, then you usually need to run <code>rake tmp:clear</code> and restart rails in order for the new stylesheet to get recognized. You should only need to do this once.</p>
+
+<p>Once you have what you want, then copy these files to the local provider directory <code>files/webapp</code> so that they will be installed each time you deploy.</p>
+
+<h2><a name="customization-tutorial"></a>Customization tutorial</h2>
+
+<p>This mini-tutorial will walk you through creating a custom &ldquo;branding&rdquo; of the leap_web application. We will be creating a provider called &ldquo;Prehistoric Computer.&rdquo;</p>
+
+<p>Here are the files we are going to create:</p>
+
+<pre><code>leap_web/config/customization
+├── locales
+│   ├── en.yml
+│   └── es.yml
+├── public
+│   ├── favicon.ico
+│   └── img
+│   └── masthead.png
+├── stylesheets
+│   └── tail.scss
+└── views
+ └── pages
+ ├── privacy-policy.en.md
+ └── privacy-policy.es.md
+</code></pre>
+
+<p>All these files are available in the source code in the <a href="https://github.com/leapcode/leap_web/tree/develop/config/customization.example">customization.example</a> directory.</p>
+
+<p>Remember, these files may live different places:</p>
+
+<ul>
+<li><code>user@localmachine$ leap_web/config/customization</code>: This will be the path if you have checked out a local copy of leap_web.git and are running <code>rails server</code> locally in order to test your customizations.</li>
+<li><code>user@localmachine$ PROVIDER/files/webapp</code>: This is the local provider directory where the files should be put so that they get correctly deployed to webapp nodes.</li>
+<li><code>root@webappnode# /srv/leap/webapp/config/customization</code>: This is where the files in the local provider directory <code>PROVIDER/files/webapp</code> get copied to after a <code>leap deploy</code> to a live webapp nodes.</li>
+</ul>
+
+
+<h3><a name="override-translations"></a>Override translations</h3>
+
+<p>You can add additional locale files in order to change the text used in the existing application and to add translations for string that you added to the application.</p>
+
+<p>In this example, we will be altering the default text for the &ldquo;login_info&rdquo; string. In <code>config/locales/en/home.en.yml</code> there is this entry:</p>
+
+<pre><code>en:
+ login_info: "Log in to change your account settings, create support tickets, and manage payments."
+</code></pre>
+
+<p>We are going to override this with some custom text in English and Spanish:</p>
+
+<p><code>leap_web/config/customization/locale/en.yml</code>:</p>
+
+<pre><code>en:
+ login_info: Authenticate to change your "Prehistoric Computer" settings.
+</code></pre>
+
+<p><code>leap_web/config/customization/locale/es.yml</code>:</p>
+
+<pre><code>es:
+ login_info: Autenticar a cambiar la configuración de "Computer Prehistoria."
+</code></pre>
+
+<p>Now, the home page of leap_web will use these new strings instead of the default. Remember that you must restart rails in order for new locale files to take effect.</p>
+
+<h3><a name="override-static-pages"></a>Override static pages</h3>
+
+<p>You can also override any of the static files included with leap_web, such as the privacy policy or terms of service.</p>
+
+<p>Here is how we would create a custom privacy policy in English and Spanish:</p>
+
+<p><code>leap_web/config/customization/views/pages/privacy-policy.en.md</code>:</p>
+
+<pre><code># Custom Privacy Policy
+This is our privacy policy.
+</code></pre>
+
+<p><code>leap_web/config/customization/views/pages/privacy-policy.es.md</code>:</p>
+
+<pre><code># Custom Política de Privacidad
+Esta es nuestra política de privacidad.
+</code></pre>
+
+<h3><a name="add-a-custom-header"></a>Add a custom header</h3>
+
+<p>Now we will add a custom header to every page. First, we add the images:</p>
+
+<pre><code>leap_web/config/customization
+ ├── public
+ ├── favicon.ico
+ └── img
+ └── masthead.png
+</code></pre>
+
+<p>You can create your own, or use the example files in <a href="https://github.com/leapcode/leap_web/tree/develop/config/customization.example">https://github.com/leapcode/leap_web/tree/develop/config/customization.example</a></p>
+
+<p>Now, we add some custom CSS so that we can style the masthead:</p>
+
+<p><code>leap_web/config/customization/stylesheets/tail.scss</code></p>
+
+<pre><code>$custom-color: #66bbaa;
+
+a {
+ color: $custom-color;
+}
+
+//
+// MASTHEAD
+//
+
+#masthead {
+ background-color: $custom-color;
+ border-bottom: none;
+
+ // make the masthead clickable by replacing the
+ // site name link with the masthead image:
+ .title {
+ padding: 0px;
+ .sitename a {
+ display: block;
+ background: url(/img/masthead.png) 0 0 no-repeat;
+ font-size: 0px;
+ height: 100px;
+ background-size: auto 100px;
+ }
+ }
+}
+
+// make the home page masthead slightly larger
+body.home #masthead {
+ .sitename a {
+ height: 150px;
+ background-size: auto 150px;
+ }
+}
+
+//
+// FOOTER
+//
+
+#footer .links {
+ background-color: $custom-color;
+}
+</code></pre>
+
+<p>NOTE: If you add a <code>tails.scss</code> or <code>head.scss</code> file, then you usually need to run <code>rake tmp:clear</code> and restart rails in order for the new stylesheet to get recognized. You should only need to do this once.</p>
+
+<h2><a name="custom-fork"></a>Custom Fork</h2>
+
+<p>Sometimes it is easier to maintain your own fork of the leap_web app. You can keep your customizations in that fork instead of in the provider <code>files/webapp</code> directory. Or, perhaps you want to add an engine to the application that modifies the app&rsquo;s behavior.</p>
+
+<p>To deploy your own leap_web, modify the provider file <code>common.json</code>:</p>
+
+<pre><code>{
+ "sources": {
+ "webapp": {
+ "revision": "origin/develop",
+ "source": "https://github.com/leapcode/leap_web",
+ "type": "git"
+ }
+ }
+}
+</code></pre>
+
+<p>To target only particular environment, modify instead <code>common.ENV.json</code>, where ENV is the name of the environment.</p>
+
+<p>See <a href="https://github.com/leapcode/leap_web/blob/develop/doc/DEVELOP.md">https://github.com/leapcode/leap_web/blob/develop/doc/DEVELOP.md</a> for notes on getting started hacking on leap_web.</p>
+
+<h2><a name="maintenance-mode"></a>Maintenance mode</h2>
+
+<p>You can put the webapp into maintenance mode by simply dropping a html file to <code>/srv/leap/webapp/public/system/maintenance.html</code>. For example:</p>
+
+<pre><code>workstation$ leap ssh webappnode
+server# echo "Temporarily down for maintenance. We will be back soon." &gt; /srv/leap/webapp/public/system/maintenance.html
+</code></pre>
+
+<h2><a name="known-problems"></a>Known problems</h2>
+
+<ul>
+<li>Client certificates are generated without a CSR. The problem is that this makes the web
+application extremely vulnerable to denial of service attacks. This was not an issue until we
+started to allow the possibility of anonymously fetching a client certificate without
+authenticating first.</li>
+<li>By its very nature, the user database is vulnerable to enumeration attacks. These are
+very hard to prevent, because our protocol is designed to allow query of a user database via
+proxy in order to provide network perspective.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting.html b/docs/en/troubleshooting.html
new file mode 100644
index 00000000..916cf229
--- /dev/null
+++ b/docs/en/troubleshooting.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Troubleshooting - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='upgrading.html'>Upgrading</a>
+</li>
+<li class='active level0'>
+<a class='' href='troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level1'>
+<a class='' href='troubleshooting/tests.html'>Tests and Monitoring</a>
+</li>
+<li class=' level1'>
+<a class='' href='troubleshooting/known-issues.html'>Known issues</a>
+</li>
+<li class=' level1'>
+<a class='' href='troubleshooting/where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Troubleshooting</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+</ol></div>
+
+<div class=' page-summary'>
+ <h2>
+ <a href='troubleshooting/tests.html'>Tests and Monitoring</a>
+ </h2>
+ <div class='summary'>Testing and monitoring your infrastructure.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='troubleshooting/known-issues.html'>Known issues</a>
+ </h2>
+ <div class='summary'>Known issues in the Leap Platform.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='troubleshooting/where-to-look.html'>Where to look</a>
+ </h2>
+ <div class='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting/known-issues.html b/docs/en/troubleshooting/known-issues.html
new file mode 100644
index 00000000..607970b1
--- /dev/null
+++ b/docs/en/troubleshooting/known-issues.html
@@ -0,0 +1,238 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Known issues - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level1'>
+<a class='' href='tests.html'>Tests and Monitoring</a>
+</li>
+<li class='active level1'>
+<a class='' href='known-issues.html'>Known issues</a>
+</li>
+<li class=' level1'>
+<a class='' href='where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Leap Platform Release Notes</h1>
+
+<div id='summary'>Known issues in the Leap Platform.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="known-issues/index.html#060">0.6.0</a>
+ <ol>
+ <li>
+ <a href="known-issues/index.html#upgrading">Upgrading</a>
+ </li>
+ <li>
+ <a href="known-issues/index.html#openvpn">OpenVPN</a>
+ </li>
+ <li>
+ <a href="known-issues/index.html#couchdb">CouchDB</a>
+ </li>
+ <li>
+ <a href="known-issues/index.html#user-setup-and-ssh">User setup and ssh</a>
+ </li>
+ <li>
+ <a href="known-issues/index.html#deploying">Deploying</a>
+ </li>
+ <li>
+ <a href="known-issues/index.html#ipv6">IPv6</a>
+ </li>
+ <li>
+ <a href="known-issues/index.html#special-environments">Special Environments</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<p>Here you can find documentation about known issues and potential work-arounds in the current Leap Platform release.</p>
+
+<h1><a name="060"></a>0.6.0</h1>
+
+<h2><a name="upgrading"></a>Upgrading</h2>
+
+<p>Upgrade your leap_platform to 0.6 and make sure you have the latest leap_cli.</p>
+
+<p><strong>Update leap_platform:</strong></p>
+
+<pre><code>cd leap_platform
+git pull
+git checkout -b 0.6.0 0.6.0
+</code></pre>
+
+<p><strong>Update leap_cli:</strong></p>
+
+<p>If it is installed as a gem from rubygems:</p>
+
+<pre><code>sudo gem update leap_cli
+</code></pre>
+
+<p>If it is installed as a gem from source:</p>
+
+<pre><code>cd leap_cli
+git pull
+git checkout master
+rake build
+sudo rake install
+</code></pre>
+
+<p>If it is run directly from source:</p>
+
+<pre><code>cd leap_cli
+git pull
+git checkout master
+</code></pre>
+
+<p>To upgrade:</p>
+
+<pre><code>leap --version # must be at least 1.6.2
+leap cert update
+leap deploy
+leap test
+</code></pre>
+
+<p>If the tests fail, try deploying again. If a test fails because there are two tapicero daemons running, you need to ssh into the server, kill all the tapicero daemons manually, and then try deploying again (sometimes the daemon from platform 0.5 would put its PID file in an odd place).</p>
+
+<h2><a name="openvpn"></a>OpenVPN</h2>
+
+<p>On deployment to a openvpn node, if the following happens:</p>
+
+<pre><code>- err: /Stage[main]/Site_openvpn/Service[openvpn]/ensure: change from stopped to running failed: Could not start Service[openvpn]: Execution of '/etc/init.d/openvpn start' returned 1: at /srv/leap/puppet/modules/site_openvpn/manifests/init.pp:189
+</code></pre>
+
+<p>this is likely the result of a kernel upgrade that happened during the deployment, requiring that the machine be restarted before this service can start. To confirm this, login to the node (leap ssh <nodename>) and look at the end of the /var/log/daemon.log:</p>
+
+<pre><code># tail /var/log/daemon.log
+Nov 22 19:04:15 snail ovpn-udp_config[16173]: ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such device (errno=19)
+Nov 22 19:04:15 snail ovpn-udp_config[16173]: Exiting due to fatal error
+</code></pre>
+
+<p>if you see this error, simply restart the node.</p>
+
+<h2><a name="couchdb"></a>CouchDB</h2>
+
+<p>At the moment, we only support one couchdb server for stability purposes.</p>
+
+<h2><a name="user-setup-and-ssh"></a>User setup and ssh</h2>
+
+<p>At the moment, it is only possible to add an admin who will have access to all LEAP servers (see: <a href="https://leap.se/code/issues/2280">https://leap.se/code/issues/2280</a>)</p>
+
+<p>The command <code>leap add-user --self</code> allows only one SSH key. If you want to specify more than one key for a user, you can do it manually:</p>
+
+<pre><code>users/userx/userx_ssh.pub
+users/userx/otherkey_ssh.pub
+</code></pre>
+
+<p>All keys matching &lsquo;userx/*_ssh.pub&rsquo; will be used for that user.</p>
+
+<h2><a name="deploying"></a>Deploying</h2>
+
+<p>If you have any errors during a run, please try to deploy again as this often solves non-deterministic issues that were not uncovered in our testing. Please re-deploy with <code>leap -v2 deploy</code> to get more verbose logs and capture the complete output to provide to us for debugging.</p>
+
+<p>If when deploying your debian mirror fails for some reason, network anomoly or the mirror itself is out of date, then platform deployment will not succeed properly. Check the mirror is up and try to deploy again when it is resolved (see: <a href="https://leap.se/code/issues/1091">https://leap.se/code/issues/1091</a>)</p>
+
+<p>Deployment gives &lsquo;error: in <code>%</code>: too few arguments (ArgumentError)&rsquo; - this is because you attempted to do a deploy before initializing a node, please initialize the node first and then do a deploy afterwards (see: <a href="https://leap.se/code/issues/2550">https://leap.se/code/issues/2550</a>)</p>
+
+<p>This release has no ability to custom configure apt sources or proxies (see: <a href="https://leap.se/code/issues/1971">https://leap.se/code/issues/1971</a>)</p>
+
+<p>When running a deploy at a verbosity level of 2 and above, you will notice puppet deprecation warnings, these are known and we are working on fixing them</p>
+
+<h2><a name="ipv6"></a>IPv6</h2>
+
+<p>As of this release, IPv6 is not supported by the VPN configuration. If IPv6 is detected on your network as a client, it is blocked and instead it should revert to IPv4. We plan on adding IPv6 support in an upcoming release.</p>
+
+<h2><a name="special-environments"></a>Special Environments</h2>
+
+<p>When deploying to OpenStack release &ldquo;nova&rdquo; or newer, you will need to do an initial deploy, then when it has finished run <code>leap facts update</code> and then deploy again (see: <a href="https://leap.se/code/issues/3020">https://leap.se/code/issues/3020</a>)</p>
+
+<p>It is not possible to actually use the EIP openvpn server on vagrant nodes (see: <a href="https://leap.se/code/issues/2401">https://leap.se/code/issues/2401</a>)</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting/known-issues/index.html b/docs/en/troubleshooting/known-issues/index.html
new file mode 100644
index 00000000..eee3b120
--- /dev/null
+++ b/docs/en/troubleshooting/known-issues/index.html
@@ -0,0 +1,238 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Known issues - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tests.html'>Tests and Monitoring</a>
+</li>
+<li class='active level1'>
+<a class='' href='../known-issues.html'>Known issues</a>
+</li>
+<li class=' level1'>
+<a class='' href='../where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Leap Platform Release Notes</h1>
+
+<div id='summary'>Known issues in the Leap Platform.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#060">0.6.0</a>
+ <ol>
+ <li>
+ <a href="index.html#upgrading">Upgrading</a>
+ </li>
+ <li>
+ <a href="index.html#openvpn">OpenVPN</a>
+ </li>
+ <li>
+ <a href="index.html#couchdb">CouchDB</a>
+ </li>
+ <li>
+ <a href="index.html#user-setup-and-ssh">User setup and ssh</a>
+ </li>
+ <li>
+ <a href="index.html#deploying">Deploying</a>
+ </li>
+ <li>
+ <a href="index.html#ipv6">IPv6</a>
+ </li>
+ <li>
+ <a href="index.html#special-environments">Special Environments</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<p>Here you can find documentation about known issues and potential work-arounds in the current Leap Platform release.</p>
+
+<h1><a name="060"></a>0.6.0</h1>
+
+<h2><a name="upgrading"></a>Upgrading</h2>
+
+<p>Upgrade your leap_platform to 0.6 and make sure you have the latest leap_cli.</p>
+
+<p><strong>Update leap_platform:</strong></p>
+
+<pre><code>cd leap_platform
+git pull
+git checkout -b 0.6.0 0.6.0
+</code></pre>
+
+<p><strong>Update leap_cli:</strong></p>
+
+<p>If it is installed as a gem from rubygems:</p>
+
+<pre><code>sudo gem update leap_cli
+</code></pre>
+
+<p>If it is installed as a gem from source:</p>
+
+<pre><code>cd leap_cli
+git pull
+git checkout master
+rake build
+sudo rake install
+</code></pre>
+
+<p>If it is run directly from source:</p>
+
+<pre><code>cd leap_cli
+git pull
+git checkout master
+</code></pre>
+
+<p>To upgrade:</p>
+
+<pre><code>leap --version # must be at least 1.6.2
+leap cert update
+leap deploy
+leap test
+</code></pre>
+
+<p>If the tests fail, try deploying again. If a test fails because there are two tapicero daemons running, you need to ssh into the server, kill all the tapicero daemons manually, and then try deploying again (sometimes the daemon from platform 0.5 would put its PID file in an odd place).</p>
+
+<h2><a name="openvpn"></a>OpenVPN</h2>
+
+<p>On deployment to a openvpn node, if the following happens:</p>
+
+<pre><code>- err: /Stage[main]/Site_openvpn/Service[openvpn]/ensure: change from stopped to running failed: Could not start Service[openvpn]: Execution of '/etc/init.d/openvpn start' returned 1: at /srv/leap/puppet/modules/site_openvpn/manifests/init.pp:189
+</code></pre>
+
+<p>this is likely the result of a kernel upgrade that happened during the deployment, requiring that the machine be restarted before this service can start. To confirm this, login to the node (leap ssh <nodename>) and look at the end of the /var/log/daemon.log:</p>
+
+<pre><code># tail /var/log/daemon.log
+Nov 22 19:04:15 snail ovpn-udp_config[16173]: ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such device (errno=19)
+Nov 22 19:04:15 snail ovpn-udp_config[16173]: Exiting due to fatal error
+</code></pre>
+
+<p>if you see this error, simply restart the node.</p>
+
+<h2><a name="couchdb"></a>CouchDB</h2>
+
+<p>At the moment, we only support one couchdb server for stability purposes.</p>
+
+<h2><a name="user-setup-and-ssh"></a>User setup and ssh</h2>
+
+<p>At the moment, it is only possible to add an admin who will have access to all LEAP servers (see: <a href="https://leap.se/code/issues/2280">https://leap.se/code/issues/2280</a>)</p>
+
+<p>The command <code>leap add-user --self</code> allows only one SSH key. If you want to specify more than one key for a user, you can do it manually:</p>
+
+<pre><code>users/userx/userx_ssh.pub
+users/userx/otherkey_ssh.pub
+</code></pre>
+
+<p>All keys matching &lsquo;userx/*_ssh.pub&rsquo; will be used for that user.</p>
+
+<h2><a name="deploying"></a>Deploying</h2>
+
+<p>If you have any errors during a run, please try to deploy again as this often solves non-deterministic issues that were not uncovered in our testing. Please re-deploy with <code>leap -v2 deploy</code> to get more verbose logs and capture the complete output to provide to us for debugging.</p>
+
+<p>If when deploying your debian mirror fails for some reason, network anomoly or the mirror itself is out of date, then platform deployment will not succeed properly. Check the mirror is up and try to deploy again when it is resolved (see: <a href="https://leap.se/code/issues/1091">https://leap.se/code/issues/1091</a>)</p>
+
+<p>Deployment gives &lsquo;error: in <code>%</code>: too few arguments (ArgumentError)&rsquo; - this is because you attempted to do a deploy before initializing a node, please initialize the node first and then do a deploy afterwards (see: <a href="https://leap.se/code/issues/2550">https://leap.se/code/issues/2550</a>)</p>
+
+<p>This release has no ability to custom configure apt sources or proxies (see: <a href="https://leap.se/code/issues/1971">https://leap.se/code/issues/1971</a>)</p>
+
+<p>When running a deploy at a verbosity level of 2 and above, you will notice puppet deprecation warnings, these are known and we are working on fixing them</p>
+
+<h2><a name="ipv6"></a>IPv6</h2>
+
+<p>As of this release, IPv6 is not supported by the VPN configuration. If IPv6 is detected on your network as a client, it is blocked and instead it should revert to IPv4. We plan on adding IPv6 support in an upcoming release.</p>
+
+<h2><a name="special-environments"></a>Special Environments</h2>
+
+<p>When deploying to OpenStack release &ldquo;nova&rdquo; or newer, you will need to do an initial deploy, then when it has finished run <code>leap facts update</code> and then deploy again (see: <a href="https://leap.se/code/issues/3020">https://leap.se/code/issues/3020</a>)</p>
+
+<p>It is not possible to actually use the EIP openvpn server on vagrant nodes (see: <a href="https://leap.se/code/issues/2401">https://leap.se/code/issues/2401</a>)</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting/tests.html b/docs/en/troubleshooting/tests.html
new file mode 100644
index 00000000..e4c2fdc2
--- /dev/null
+++ b/docs/en/troubleshooting/tests.html
@@ -0,0 +1,201 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Tests and Monitoring - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='active level1'>
+<a class='' href='tests.html'>Tests and Monitoring</a>
+</li>
+<li class=' level1'>
+<a class='' href='known-issues.html'>Known issues</a>
+</li>
+<li class=' level1'>
+<a class='' href='where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Tests and Monitoring</h1>
+
+<div id='summary'>Testing and monitoring your infrastructure.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="tests/index.html#troubleshooting-tests">Troubleshooting Tests</a>
+ </li>
+ <li>
+ <a href="tests/index.html#testing-with-the-bitmask-client">Testing with the bitmask client</a>
+ </li>
+ <li>
+ <a href="tests/index.html#testing-recieving-mail">Testing Recieving Mail</a>
+ </li>
+ <li>
+ <a href="tests/index.html#monitoring">Monitoring</a>
+ </li>
+ <li>
+ <a href="tests/index.html#nagios-frontends">Nagios Frontends</a>
+ <ol>
+ <li>
+ <a href="tests/index.html#log-monitoring">Log Monitoring</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="troubleshooting-tests"></a>Troubleshooting Tests</h2>
+
+<p>At any time, you can run troubleshooting tests on the nodes of your provider infrastructure to check to see if things seem to be working correctly. If there is a problem, these tests should help you narrow down precisely where the problem is.</p>
+
+<p>To run tests on FILTER node list:</p>
+
+<pre><code>workstation$ leap test run FILTER
+</code></pre>
+
+<p>For example, you can also test a single node (<code>leap test elephant</code>); test a specific environment (<code>leap test development</code>), or any tag (<code>leap test soledad</code>).</p>
+
+<p>Alternately, you can run test on all nodes (probably only useful if you have pinned the environment):</p>
+
+<pre><code>workstation$ leap test
+</code></pre>
+
+<p>The tests that are performed are located in the platform under the tests directory.</p>
+
+<h2><a name="testing-with-the-bitmask-client"></a>Testing with the bitmask client</h2>
+
+<p>Download the provider ca:</p>
+
+<pre><code>wget --no-check-certificate https://example.org/ca.crt -O /tmp/ca.crt
+</code></pre>
+
+<p>Start bitmask:</p>
+
+<pre><code>bitmask --ca-cert-file /tmp/ca.crt
+</code></pre>
+
+<h2><a name="testing-recieving-mail"></a>Testing Recieving Mail</h2>
+
+<p>Use i.e. swaks to send a testmail</p>
+
+<pre><code>swaks -f noone@example.org -t testuser@example.org -s example.org
+</code></pre>
+
+<p>and use your favorite mail client to examine your inbox.</p>
+
+<p>You can also use <a href="http://offlineimap.org/">offlineimap</a> to fetch mails:</p>
+
+<pre><code> offlineimap -c vagrant/.offlineimaprc.example.org
+</code></pre>
+
+<p>WARNING: Use offlineimap <em>only</em> for testing/debugging,
+because it will save the mails <em>decrypted</em> locally to
+your disk !</p>
+
+<h2><a name="monitoring"></a>Monitoring</h2>
+
+<p>In order to set up a monitoring node, you simply add a <code>monitor</code> service tag to the node configuration file. It could be combined with any other service, but we propose that you add it to the webapp node, as this already is public accessible via HTTPS.</p>
+
+<p>After deploying, this node will regularly poll every node to ask for the status of various health checks. These health checks include the checks run with <code>leap test</code>, plus many others.</p>
+
+<p>We use <a href="https://www.nagios.org/">Nagios</a> together with <a href="https://en.wikipedia.org/wiki/Check_MK">Check MK agent</a> for running checks on remote hosts.</p>
+
+<p>One nagios installation will monitor all nodes in all your environments. You can log into the monitoring web interface via <a href="https://DOMAIN/nagios3/">https://DOMAIN/nagios3/</a>. The username is <code>nagiosadmin</code> and the password is found in the secrets.json file in your provider directory.
+Nagios will send out mails to the <code>contacts</code> address provided in <code>provider.json</code>.</p>
+
+<h2><a name="nagios-frontends"></a>Nagios Frontends</h2>
+
+<p>There are other ways to check and get notified by Nagios besides regularly checking the Nagios webinterface or reading email notifications. Check out the <a href="http://exchange.nagios.org/directory/Addons/Frontends-%28GUIs-and-CLIs%29">Frontends (GUIs and CLIs)</a> on the Nagios project website.
+A recommended status tray application is <a href="https://nagstamon.ifw-dresden.de/">Nagstamon</a>, which is available for Linux, MacOS X and Windows. It can not only notify you of hosts/services failures, you can also acknowledge or recheck them.</p>
+
+<h3><a name="log-monitoring"></a>Log Monitoring</h3>
+
+<p>At the moment, we use <a href="https://mathias-kettner.de/checkmk_check_logwatch.html">check-mk-agent-logwatch</a> for searching logs for irregularities.
+Logs are parsed for patterns using a blacklist, and are stored in <code>/var/lib/check_mk/logwatch/&lt;Nodename&gt;</code>.</p>
+
+<p>In order to &ldquo;acknowledge&rdquo; a log warning, you need to log in to the monitoring server, and delete the corresponding file in <code>/var/lib/check_mk/logwatch/&lt;Nodename&gt;</code>. This should be done via the nagios webinterface in the future.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting/tests/index.html b/docs/en/troubleshooting/tests/index.html
new file mode 100644
index 00000000..f46eddc7
--- /dev/null
+++ b/docs/en/troubleshooting/tests/index.html
@@ -0,0 +1,201 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Tests and Monitoring - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class='active level1'>
+<a class='' href='../tests.html'>Tests and Monitoring</a>
+</li>
+<li class=' level1'>
+<a class='' href='../known-issues.html'>Known issues</a>
+</li>
+<li class=' level1'>
+<a class='' href='../where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Tests and Monitoring</h1>
+
+<div id='summary'>Testing and monitoring your infrastructure.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#troubleshooting-tests">Troubleshooting Tests</a>
+ </li>
+ <li>
+ <a href="index.html#testing-with-the-bitmask-client">Testing with the bitmask client</a>
+ </li>
+ <li>
+ <a href="index.html#testing-recieving-mail">Testing Recieving Mail</a>
+ </li>
+ <li>
+ <a href="index.html#monitoring">Monitoring</a>
+ </li>
+ <li>
+ <a href="index.html#nagios-frontends">Nagios Frontends</a>
+ <ol>
+ <li>
+ <a href="index.html#log-monitoring">Log Monitoring</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h2><a name="troubleshooting-tests"></a>Troubleshooting Tests</h2>
+
+<p>At any time, you can run troubleshooting tests on the nodes of your provider infrastructure to check to see if things seem to be working correctly. If there is a problem, these tests should help you narrow down precisely where the problem is.</p>
+
+<p>To run tests on FILTER node list:</p>
+
+<pre><code>workstation$ leap test run FILTER
+</code></pre>
+
+<p>For example, you can also test a single node (<code>leap test elephant</code>); test a specific environment (<code>leap test development</code>), or any tag (<code>leap test soledad</code>).</p>
+
+<p>Alternately, you can run test on all nodes (probably only useful if you have pinned the environment):</p>
+
+<pre><code>workstation$ leap test
+</code></pre>
+
+<p>The tests that are performed are located in the platform under the tests directory.</p>
+
+<h2><a name="testing-with-the-bitmask-client"></a>Testing with the bitmask client</h2>
+
+<p>Download the provider ca:</p>
+
+<pre><code>wget --no-check-certificate https://example.org/ca.crt -O /tmp/ca.crt
+</code></pre>
+
+<p>Start bitmask:</p>
+
+<pre><code>bitmask --ca-cert-file /tmp/ca.crt
+</code></pre>
+
+<h2><a name="testing-recieving-mail"></a>Testing Recieving Mail</h2>
+
+<p>Use i.e. swaks to send a testmail</p>
+
+<pre><code>swaks -f noone@example.org -t testuser@example.org -s example.org
+</code></pre>
+
+<p>and use your favorite mail client to examine your inbox.</p>
+
+<p>You can also use <a href="http://offlineimap.org/">offlineimap</a> to fetch mails:</p>
+
+<pre><code> offlineimap -c vagrant/.offlineimaprc.example.org
+</code></pre>
+
+<p>WARNING: Use offlineimap <em>only</em> for testing/debugging,
+because it will save the mails <em>decrypted</em> locally to
+your disk !</p>
+
+<h2><a name="monitoring"></a>Monitoring</h2>
+
+<p>In order to set up a monitoring node, you simply add a <code>monitor</code> service tag to the node configuration file. It could be combined with any other service, but we propose that you add it to the webapp node, as this already is public accessible via HTTPS.</p>
+
+<p>After deploying, this node will regularly poll every node to ask for the status of various health checks. These health checks include the checks run with <code>leap test</code>, plus many others.</p>
+
+<p>We use <a href="https://www.nagios.org/">Nagios</a> together with <a href="https://en.wikipedia.org/wiki/Check_MK">Check MK agent</a> for running checks on remote hosts.</p>
+
+<p>One nagios installation will monitor all nodes in all your environments. You can log into the monitoring web interface via <a href="https://DOMAIN/nagios3/">https://DOMAIN/nagios3/</a>. The username is <code>nagiosadmin</code> and the password is found in the secrets.json file in your provider directory.
+Nagios will send out mails to the <code>contacts</code> address provided in <code>provider.json</code>.</p>
+
+<h2><a name="nagios-frontends"></a>Nagios Frontends</h2>
+
+<p>There are other ways to check and get notified by Nagios besides regularly checking the Nagios webinterface or reading email notifications. Check out the <a href="http://exchange.nagios.org/directory/Addons/Frontends-%28GUIs-and-CLIs%29">Frontends (GUIs and CLIs)</a> on the Nagios project website.
+A recommended status tray application is <a href="https://nagstamon.ifw-dresden.de/">Nagstamon</a>, which is available for Linux, MacOS X and Windows. It can not only notify you of hosts/services failures, you can also acknowledge or recheck them.</p>
+
+<h3><a name="log-monitoring"></a>Log Monitoring</h3>
+
+<p>At the moment, we use <a href="https://mathias-kettner.de/checkmk_check_logwatch.html">check-mk-agent-logwatch</a> for searching logs for irregularities.
+Logs are parsed for patterns using a blacklist, and are stored in <code>/var/lib/check_mk/logwatch/&lt;Nodename&gt;</code>.</p>
+
+<p>In order to &ldquo;acknowledge&rdquo; a log warning, you need to log in to the monitoring server, and delete the corresponding file in <code>/var/lib/check_mk/logwatch/&lt;Nodename&gt;</code>. This should be done via the nagios webinterface in the future.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting/where-to-look.html b/docs/en/troubleshooting/where-to-look.html
new file mode 100644
index 00000000..a1207aca
--- /dev/null
+++ b/docs/en/troubleshooting/where-to-look.html
@@ -0,0 +1,451 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Where to look - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level1'>
+<a class='' href='tests.html'>Tests and Monitoring</a>
+</li>
+<li class=' level1'>
+<a class='' href='known-issues.html'>Known issues</a>
+</li>
+<li class='active level1'>
+<a class='' href='where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Where to look for errors</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="where-to-look/index.html#general">General</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#firewall">Firewall</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#webapp">Webapp</a>
+ <ol>
+ <li>
+ <a href="where-to-look/index.html#places-to-look-for-errors">Places to look for errors</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#is-haproxy-ok">Is haproxy ok ?</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#is-couchdb-accessible-through-stunnel">Is couchdb accessible through stunnel ?</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#check-couchdb-acl-as-admin">Check couchdb acl as admin</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#check-couchdb-acl-as-unpriviledged-user">Check couchdb acl as unpriviledged user</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#all-urls-accessible">All URLs accessible ?</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#check-client-config-files">Check client config files</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#soledad">Soledad</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#couchdb">Couchdb</a>
+ <ol>
+ <li>
+ <a href="where-to-look/index.html#places-to-look-for-errors-2">Places to look for errors</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#databases">Databases</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#design-documents">Design Documents</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#is-couchdb-cluster-backend-accessible-through-stunnel">Is couchdb cluster backend accessible through stunnel ?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#mx">MX</a>
+ <ol>
+ <li>
+ <a href="where-to-look/index.html#places-to-look-for-errors-3">Places to look for errors</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#is-couchdb-accessible-through-stunnel-2">Is couchdb accessible through stunnel ?</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#query-leap-mx">Query leap-mx</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#check-couchdb-acl-as-unpriviledged-user-2">Check couchdb acl as unpriviledged user</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#mailspool">Mailspool</a>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#testing-mail-delivery">Testing mail delivery</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="where-to-look/index.html#vpn">VPN</a>
+ <ol>
+ <li>
+ <a href="where-to-look/index.html#places-to-look-for-errors-4">Places to look for errors</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="general"></a>General</h1>
+
+<ul>
+<li>Please increase verbosity when debugging / filing issues in our issue tracker. You can do this with adding i.e. <code>-v 5</code> after the <code>leap</code> cmd, i.e. <code>leap -v 2 deploy</code>.</li>
+<li>We use the <code>example.org</code> domain for documentation purposes here, please replace it with the you domain.</li>
+</ul>
+
+
+<h1><a name="firewall"></a>Firewall</h1>
+
+<p>Every node in your provider has its own restrictive firewall, but you might have a network firewall in place as well that is not managed by LEAP platform. To see what ports and addresses must be open, run this command:</p>
+
+<pre><code>workstation$ leap compile firewall
+</code></pre>
+
+<p>If any of those are blocked, then your provider will not work.</p>
+
+<h1><a name="webapp"></a>Webapp</h1>
+
+<h2><a name="places-to-look-for-errors"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/apache2/error.log</code></li>
+<li><code>/srv/leap/webapp/log/production.log</code></li>
+<li><code>/var/log/syslog</code> (watch out for stunnel issues)</li>
+<li><code>/var/log/leap/*</code></li>
+</ul>
+
+
+<h2><a name="is-haproxy-ok"></a>Is haproxy ok ?</h2>
+
+<pre><code>curl -s -X GET "http://127.0.0.1:4096"
+</code></pre>
+
+<h2><a name="is-couchdb-accessible-through-stunnel"></a>Is couchdb accessible through stunnel ?</h2>
+
+<ul>
+<li><p>Depending on how many couch nodes you have, increase the port for every test
+(see /etc/haproxy/haproxy.cfg for the server/port mapping):</p>
+
+<p> curl -s -X GET &ldquo;<a href="http://127.0.0.1:4000">http://127.0.0.1:4000</a>&rdquo;
+ curl -s -X GET &ldquo;<a href="http://127.0.0.1:4001">http://127.0.0.1:4001</a>&rdquo;
+ &hellip;</p></li>
+</ul>
+
+
+<h2><a name="check-couchdb-acl-as-admin"></a>Check couchdb acl as admin</h2>
+
+<pre><code>mkdir /etc/couchdb
+cat /srv/leap/webapp/config/couchdb.yml.admin # see username and password
+echo "machine 127.0.0.1 login admin password &lt;PASSWORD&gt;" &gt; /etc/couchdb/couchdb-admin.netrc
+chmod 600 /etc/couchdb/couchdb-admin.netrc
+
+curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096"
+curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096/_all_dbs"
+</code></pre>
+
+<h2><a name="check-couchdb-acl-as-unpriviledged-user"></a>Check couchdb acl as unpriviledged user</h2>
+
+<pre><code>cat /srv/leap/webapp/config/couchdb.yml # see username and password
+echo "machine 127.0.0.1 login webapp password &lt;PASSWORD&gt;" &gt; /etc/couchdb/couchdb-webapp.netrc
+chmod 600 /etc/couchdb/couchdb-webapp.netrc
+
+curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096"
+curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096/_all_dbs"
+</code></pre>
+
+<h2><a name="all-urls-accessible"></a>All URLs accessible ?</h2>
+
+<ul>
+<li><a href="https://example.org">https://example.org</a></li>
+<li><a href="https://api.example.org:4430/provider.json">https://api.example.org:4430/provider.json</a></li>
+<li><a href="https://example.org/ca.crt">https://example.org/ca.crt</a></li>
+</ul>
+
+
+<h2><a name="check-client-config-files"></a>Check client config files</h2>
+
+<ul>
+<li><a href="https://example.net/provider.json">https://example.net/provider.json</a></li>
+<li><a href="https://example.net/1/config/smtp-service.json">https://example.net/1/config/smtp-service.json</a></li>
+<li><a href="https://example.net/1/config/soledad-service.json">https://example.net/1/config/soledad-service.json</a></li>
+<li><a href="https://example.net/1/config/eip-service.json">https://example.net/1/config/eip-service.json</a></li>
+</ul>
+
+
+<h1><a name="soledad"></a>Soledad</h1>
+
+<pre><code>/var/log/soledad.log
+</code></pre>
+
+<h1><a name="couchdb"></a>Couchdb</h1>
+
+<h2><a name="places-to-look-for-errors-2"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/couchdb/couch.log</code></li>
+<li><code>/var/log/syslog</code> (watch out for stunnel issues)</li>
+</ul>
+
+
+<h2><a name="databases"></a>Databases</h2>
+
+<ul>
+<li>Following output shows all neccessary DBs that should be present. Note that the <code>user-0123456....</code> DBs are the data stores for a particular user.</li>
+</ul>
+
+
+<pre>
+ curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET 'http://127.0.0.1:5984/_all_dbs'
+ ["customers","identities","sessions","shared","tickets","tokens","user-0","user-9d34680b01074c75c2ec58c7321f540c","user-9d34680b01074c75c2ec58c7325fb7ff","users"]
+</pre>
+
+
+<h2><a name="design-documents"></a>Design Documents</h2>
+
+<ul>
+<li>Is User <code>_design doc</code> available ?</li>
+</ul>
+
+
+<pre>
+ curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET "http://127.0.0.1:5984/users/_design/User"
+</pre>
+
+
+<h2><a name="is-couchdb-cluster-backend-accessible-through-stunnel"></a>Is couchdb cluster backend accessible through stunnel ?</h2>
+
+<ul>
+<li>Find out how many connections are set up for the couchdb cluster backend:</li>
+</ul>
+
+
+<pre>
+ grep "accept = 127.0.0.1" /etc/stunnel/*
+</pre>
+
+
+<ul>
+<li>Now connect to all of those local endpoints to see if they up. All these tests should return &ldquo;localhost [127.0.0.1] 4000 (?) open&rdquo;</li>
+</ul>
+
+
+<pre>
+ nc -v 127.0.0.1 4000
+ nc -v 127.0.0.1 4001
+ ...
+</pre>
+
+
+<h1><a name="mx"></a>MX</h1>
+
+<h2><a name="places-to-look-for-errors-3"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/mail.log</code></li>
+<li><code>/var/log/leap_mx.log</code></li>
+<li><code>/var/log/syslog</code> (watch out for stunnel issues)</li>
+</ul>
+
+
+<h2><a name="is-couchdb-accessible-through-stunnel-2"></a>Is couchdb accessible through stunnel ?</h2>
+
+<ul>
+<li><p>Depending on how many couch nodes you have, increase the port for every test
+(see /etc/haproxy/haproxy.cfg for the server/port mapping):</p>
+
+<p> curl -s -X GET &ldquo;<a href="http://127.0.0.1:4000">http://127.0.0.1:4000</a>&rdquo;
+ curl -s -X GET &ldquo;<a href="http://127.0.0.1:4001">http://127.0.0.1:4001</a>&rdquo;
+ &hellip;</p></li>
+</ul>
+
+
+<h2><a name="query-leap-mx"></a>Query leap-mx</h2>
+
+<ul>
+<li>for useraccount</li>
+</ul>
+
+
+<pre>
+ postmap -v -q "joe@dev.bitmask.net" tcp:localhost:2244
+ ...
+ postmap: dict_tcp_lookup: send: get jow@dev.bitmask.net
+ postmap: dict_tcp_lookup: recv: 200
+ ...
+</pre>
+
+
+<ul>
+<li>for mailalias</li>
+</ul>
+
+
+<pre>
+ postmap -v -q "joe@dev.bitmask.net" tcp:localhost:4242
+ ...
+ postmap: dict_tcp_lookup: send: get joe@dev.bitmask.net
+ postmap: dict_tcp_lookup: recv: 200 f01bc1c70de7d7d80bc1ad77d987e73a
+ postmap: dict_tcp_lookup: found: f01bc1c70de7d7d80bc1ad77d987e73a
+ f01bc1c70de7d7d80bc1ad77d987e73a
+ ...
+</pre>
+
+
+<h2><a name="check-couchdb-acl-as-unpriviledged-user-2"></a>Check couchdb acl as unpriviledged user</h2>
+
+<pre><code>cat /etc/leap/mx.conf # see username and password
+echo "machine 127.0.0.1 login leap_mx password &lt;PASSWORD&gt;" &gt; /etc/couchdb/couchdb-leap_mx.netrc
+chmod 600 /etc/couchdb/couchdb-leap_mx.netrc
+
+curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/_all_dbs" # pick one "user-&lt;hash&gt;" db
+curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/user-de9c77a3d7efbc779c6c20da88e8fb9c"
+</code></pre>
+
+<ul>
+<li>you may check multiple times, cause 127.0.0.1:4096 is haproxy load-balancing the different couchdb nodes</li>
+</ul>
+
+
+<h2><a name="mailspool"></a>Mailspool</h2>
+
+<ul>
+<li>Any file in the leap_mx mailspool longer for a few seconds ?</li>
+</ul>
+
+
+<pre>
+ ls -la /var/mail/vmail/Maildir/cur/
+</pre>
+
+
+<ul>
+<li>Any mails in postfix mailspool longer than a few seconds ?</li>
+</ul>
+
+
+<pre>
+ mailq
+</pre>
+
+
+<h2><a name="testing-mail-delivery"></a>Testing mail delivery</h2>
+
+<pre><code>swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 25
+swaks -f varac@cdev.bitmask.net -t varac@cdev.bitmask.net -s chipmonk.cdev.bitmask.net --port 465 --tlsc
+swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 587 --tls
+</code></pre>
+
+<h1><a name="vpn"></a>VPN</h1>
+
+<h2><a name="places-to-look-for-errors-4"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/syslog</code> (watch out for openvpn issues)</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/troubleshooting/where-to-look/index.html b/docs/en/troubleshooting/where-to-look/index.html
new file mode 100644
index 00000000..ab3115af
--- /dev/null
+++ b/docs/en/troubleshooting/where-to-look/index.html
@@ -0,0 +1,451 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Where to look - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level1'>
+<a class='' href='../tests.html'>Tests and Monitoring</a>
+</li>
+<li class=' level1'>
+<a class='' href='../known-issues.html'>Known issues</a>
+</li>
+<li class='active level1'>
+<a class='' href='../where-to-look.html'>Where to look</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Where to look for errors</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#general">General</a>
+ </li>
+ <li>
+ <a href="index.html#firewall">Firewall</a>
+ </li>
+ <li>
+ <a href="index.html#webapp">Webapp</a>
+ <ol>
+ <li>
+ <a href="index.html#places-to-look-for-errors">Places to look for errors</a>
+ </li>
+ <li>
+ <a href="index.html#is-haproxy-ok">Is haproxy ok ?</a>
+ </li>
+ <li>
+ <a href="index.html#is-couchdb-accessible-through-stunnel">Is couchdb accessible through stunnel ?</a>
+ </li>
+ <li>
+ <a href="index.html#check-couchdb-acl-as-admin">Check couchdb acl as admin</a>
+ </li>
+ <li>
+ <a href="index.html#check-couchdb-acl-as-unpriviledged-user">Check couchdb acl as unpriviledged user</a>
+ </li>
+ <li>
+ <a href="index.html#all-urls-accessible">All URLs accessible ?</a>
+ </li>
+ <li>
+ <a href="index.html#check-client-config-files">Check client config files</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#soledad">Soledad</a>
+ </li>
+ <li>
+ <a href="index.html#couchdb">Couchdb</a>
+ <ol>
+ <li>
+ <a href="index.html#places-to-look-for-errors-2">Places to look for errors</a>
+ </li>
+ <li>
+ <a href="index.html#databases">Databases</a>
+ </li>
+ <li>
+ <a href="index.html#design-documents">Design Documents</a>
+ </li>
+ <li>
+ <a href="index.html#is-couchdb-cluster-backend-accessible-through-stunnel">Is couchdb cluster backend accessible through stunnel ?</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#mx">MX</a>
+ <ol>
+ <li>
+ <a href="index.html#places-to-look-for-errors-3">Places to look for errors</a>
+ </li>
+ <li>
+ <a href="index.html#is-couchdb-accessible-through-stunnel-2">Is couchdb accessible through stunnel ?</a>
+ </li>
+ <li>
+ <a href="index.html#query-leap-mx">Query leap-mx</a>
+ </li>
+ <li>
+ <a href="index.html#check-couchdb-acl-as-unpriviledged-user-2">Check couchdb acl as unpriviledged user</a>
+ </li>
+ <li>
+ <a href="index.html#mailspool">Mailspool</a>
+ </li>
+ <li>
+ <a href="index.html#testing-mail-delivery">Testing mail delivery</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#vpn">VPN</a>
+ <ol>
+ <li>
+ <a href="index.html#places-to-look-for-errors-4">Places to look for errors</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="general"></a>General</h1>
+
+<ul>
+<li>Please increase verbosity when debugging / filing issues in our issue tracker. You can do this with adding i.e. <code>-v 5</code> after the <code>leap</code> cmd, i.e. <code>leap -v 2 deploy</code>.</li>
+<li>We use the <code>example.org</code> domain for documentation purposes here, please replace it with the you domain.</li>
+</ul>
+
+
+<h1><a name="firewall"></a>Firewall</h1>
+
+<p>Every node in your provider has its own restrictive firewall, but you might have a network firewall in place as well that is not managed by LEAP platform. To see what ports and addresses must be open, run this command:</p>
+
+<pre><code>workstation$ leap compile firewall
+</code></pre>
+
+<p>If any of those are blocked, then your provider will not work.</p>
+
+<h1><a name="webapp"></a>Webapp</h1>
+
+<h2><a name="places-to-look-for-errors"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/apache2/error.log</code></li>
+<li><code>/srv/leap/webapp/log/production.log</code></li>
+<li><code>/var/log/syslog</code> (watch out for stunnel issues)</li>
+<li><code>/var/log/leap/*</code></li>
+</ul>
+
+
+<h2><a name="is-haproxy-ok"></a>Is haproxy ok ?</h2>
+
+<pre><code>curl -s -X GET "http://127.0.0.1:4096"
+</code></pre>
+
+<h2><a name="is-couchdb-accessible-through-stunnel"></a>Is couchdb accessible through stunnel ?</h2>
+
+<ul>
+<li><p>Depending on how many couch nodes you have, increase the port for every test
+(see /etc/haproxy/haproxy.cfg for the server/port mapping):</p>
+
+<p> curl -s -X GET &ldquo;<a href="http://127.0.0.1:4000">http://127.0.0.1:4000</a>&rdquo;
+ curl -s -X GET &ldquo;<a href="http://127.0.0.1:4001">http://127.0.0.1:4001</a>&rdquo;
+ &hellip;</p></li>
+</ul>
+
+
+<h2><a name="check-couchdb-acl-as-admin"></a>Check couchdb acl as admin</h2>
+
+<pre><code>mkdir /etc/couchdb
+cat /srv/leap/webapp/config/couchdb.yml.admin # see username and password
+echo "machine 127.0.0.1 login admin password &lt;PASSWORD&gt;" &gt; /etc/couchdb/couchdb-admin.netrc
+chmod 600 /etc/couchdb/couchdb-admin.netrc
+
+curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096"
+curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096/_all_dbs"
+</code></pre>
+
+<h2><a name="check-couchdb-acl-as-unpriviledged-user"></a>Check couchdb acl as unpriviledged user</h2>
+
+<pre><code>cat /srv/leap/webapp/config/couchdb.yml # see username and password
+echo "machine 127.0.0.1 login webapp password &lt;PASSWORD&gt;" &gt; /etc/couchdb/couchdb-webapp.netrc
+chmod 600 /etc/couchdb/couchdb-webapp.netrc
+
+curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096"
+curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096/_all_dbs"
+</code></pre>
+
+<h2><a name="all-urls-accessible"></a>All URLs accessible ?</h2>
+
+<ul>
+<li><a href="https://example.org">https://example.org</a></li>
+<li><a href="https://api.example.org:4430/provider.json">https://api.example.org:4430/provider.json</a></li>
+<li><a href="https://example.org/ca.crt">https://example.org/ca.crt</a></li>
+</ul>
+
+
+<h2><a name="check-client-config-files"></a>Check client config files</h2>
+
+<ul>
+<li><a href="https://example.net/provider.json">https://example.net/provider.json</a></li>
+<li><a href="https://example.net/1/config/smtp-service.json">https://example.net/1/config/smtp-service.json</a></li>
+<li><a href="https://example.net/1/config/soledad-service.json">https://example.net/1/config/soledad-service.json</a></li>
+<li><a href="https://example.net/1/config/eip-service.json">https://example.net/1/config/eip-service.json</a></li>
+</ul>
+
+
+<h1><a name="soledad"></a>Soledad</h1>
+
+<pre><code>/var/log/soledad.log
+</code></pre>
+
+<h1><a name="couchdb"></a>Couchdb</h1>
+
+<h2><a name="places-to-look-for-errors-2"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/couchdb/couch.log</code></li>
+<li><code>/var/log/syslog</code> (watch out for stunnel issues)</li>
+</ul>
+
+
+<h2><a name="databases"></a>Databases</h2>
+
+<ul>
+<li>Following output shows all neccessary DBs that should be present. Note that the <code>user-0123456....</code> DBs are the data stores for a particular user.</li>
+</ul>
+
+
+<pre>
+ curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET 'http://127.0.0.1:5984/_all_dbs'
+ ["customers","identities","sessions","shared","tickets","tokens","user-0","user-9d34680b01074c75c2ec58c7321f540c","user-9d34680b01074c75c2ec58c7325fb7ff","users"]
+</pre>
+
+
+<h2><a name="design-documents"></a>Design Documents</h2>
+
+<ul>
+<li>Is User <code>_design doc</code> available ?</li>
+</ul>
+
+
+<pre>
+ curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET "http://127.0.0.1:5984/users/_design/User"
+</pre>
+
+
+<h2><a name="is-couchdb-cluster-backend-accessible-through-stunnel"></a>Is couchdb cluster backend accessible through stunnel ?</h2>
+
+<ul>
+<li>Find out how many connections are set up for the couchdb cluster backend:</li>
+</ul>
+
+
+<pre>
+ grep "accept = 127.0.0.1" /etc/stunnel/*
+</pre>
+
+
+<ul>
+<li>Now connect to all of those local endpoints to see if they up. All these tests should return &ldquo;localhost [127.0.0.1] 4000 (?) open&rdquo;</li>
+</ul>
+
+
+<pre>
+ nc -v 127.0.0.1 4000
+ nc -v 127.0.0.1 4001
+ ...
+</pre>
+
+
+<h1><a name="mx"></a>MX</h1>
+
+<h2><a name="places-to-look-for-errors-3"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/mail.log</code></li>
+<li><code>/var/log/leap_mx.log</code></li>
+<li><code>/var/log/syslog</code> (watch out for stunnel issues)</li>
+</ul>
+
+
+<h2><a name="is-couchdb-accessible-through-stunnel-2"></a>Is couchdb accessible through stunnel ?</h2>
+
+<ul>
+<li><p>Depending on how many couch nodes you have, increase the port for every test
+(see /etc/haproxy/haproxy.cfg for the server/port mapping):</p>
+
+<p> curl -s -X GET &ldquo;<a href="http://127.0.0.1:4000">http://127.0.0.1:4000</a>&rdquo;
+ curl -s -X GET &ldquo;<a href="http://127.0.0.1:4001">http://127.0.0.1:4001</a>&rdquo;
+ &hellip;</p></li>
+</ul>
+
+
+<h2><a name="query-leap-mx"></a>Query leap-mx</h2>
+
+<ul>
+<li>for useraccount</li>
+</ul>
+
+
+<pre>
+ postmap -v -q "joe@dev.bitmask.net" tcp:localhost:2244
+ ...
+ postmap: dict_tcp_lookup: send: get jow@dev.bitmask.net
+ postmap: dict_tcp_lookup: recv: 200
+ ...
+</pre>
+
+
+<ul>
+<li>for mailalias</li>
+</ul>
+
+
+<pre>
+ postmap -v -q "joe@dev.bitmask.net" tcp:localhost:4242
+ ...
+ postmap: dict_tcp_lookup: send: get joe@dev.bitmask.net
+ postmap: dict_tcp_lookup: recv: 200 f01bc1c70de7d7d80bc1ad77d987e73a
+ postmap: dict_tcp_lookup: found: f01bc1c70de7d7d80bc1ad77d987e73a
+ f01bc1c70de7d7d80bc1ad77d987e73a
+ ...
+</pre>
+
+
+<h2><a name="check-couchdb-acl-as-unpriviledged-user-2"></a>Check couchdb acl as unpriviledged user</h2>
+
+<pre><code>cat /etc/leap/mx.conf # see username and password
+echo "machine 127.0.0.1 login leap_mx password &lt;PASSWORD&gt;" &gt; /etc/couchdb/couchdb-leap_mx.netrc
+chmod 600 /etc/couchdb/couchdb-leap_mx.netrc
+
+curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/_all_dbs" # pick one "user-&lt;hash&gt;" db
+curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/user-de9c77a3d7efbc779c6c20da88e8fb9c"
+</code></pre>
+
+<ul>
+<li>you may check multiple times, cause 127.0.0.1:4096 is haproxy load-balancing the different couchdb nodes</li>
+</ul>
+
+
+<h2><a name="mailspool"></a>Mailspool</h2>
+
+<ul>
+<li>Any file in the leap_mx mailspool longer for a few seconds ?</li>
+</ul>
+
+
+<pre>
+ ls -la /var/mail/vmail/Maildir/cur/
+</pre>
+
+
+<ul>
+<li>Any mails in postfix mailspool longer than a few seconds ?</li>
+</ul>
+
+
+<pre>
+ mailq
+</pre>
+
+
+<h2><a name="testing-mail-delivery"></a>Testing mail delivery</h2>
+
+<pre><code>swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 25
+swaks -f varac@cdev.bitmask.net -t varac@cdev.bitmask.net -s chipmonk.cdev.bitmask.net --port 465 --tlsc
+swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 587 --tls
+</code></pre>
+
+<h1><a name="vpn"></a>VPN</h1>
+
+<h2><a name="places-to-look-for-errors-4"></a>Places to look for errors</h2>
+
+<ul>
+<li><code>/var/log/syslog</code> (watch out for openvpn issues)</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials.html b/docs/en/tutorials.html
new file mode 100644
index 00000000..3eeac685
--- /dev/null
+++ b/docs/en/tutorials.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Tutorials - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='guide.html'>Guide</a>
+</li>
+<li class='active level0'>
+<a class='' href='tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='tutorials/quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='tutorials/single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='tutorials/single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='tutorials/vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Platform Tutorials</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+</ol></div>
+
+<div class=' page-summary'>
+ <h2>
+ <a href='tutorials/quick-start.html'>Quick Start Tutorial</a>
+ </h2>
+ <div class='summary'>This tutorial walks you through the initial process of creating and deploying a minimal service provider running the LEAP Platform.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='tutorials/single-node-vpn.html'>Quick VPN</a>
+ </h2>
+ <div class='summary'>Tutorial for setting up a simple VPN provider.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='tutorials/single-node-email.html'>Quick email</a>
+ </h2>
+ <div class='summary'>Tutorial for setting up a simple email provider.</div>
+</div>
+<div class=' page-summary'>
+ <h2>
+ <a href='tutorials/vagrant.html'>Vagrant</a>
+ </h2>
+ <div class='summary'>Running a local provider with Vagrant</div>
+</div>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/quick-start.html b/docs/en/tutorials/quick-start.html
new file mode 100644
index 00000000..d2670b30
--- /dev/null
+++ b/docs/en/tutorials/quick-start.html
@@ -0,0 +1,446 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Quick Start Tutorial - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class='active level1'>
+<a class='' href='quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Quick Start Tutorial</h1>
+
+<div id='summary'>This tutorial walks you through the initial process of creating and deploying a minimal service provider running the LEAP Platform.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="quick-start/index.html#introduction">Introduction</a>
+ <ol>
+ <li>
+ <a href="quick-start/index.html#our-goal">Our goal</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#requirements">Requirements</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="quick-start/index.html#prepare-your-workstation">Prepare your workstation</a>
+ <ol>
+ <li>
+ <a href="quick-start/index.html#install-pre-requisites">Install pre-requisites</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#install-the-leap-command-line-utility">Install the LEAP command-line utility</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="quick-start/index.html#create-a-provider-instance">Create a provider instance</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#add-a-node-to-the-provider">Add a node to the provider</a>
+ <ol>
+ <li>
+ <a href="quick-start/index.html#option-a-add-a-real-node">Option A: Add a real node</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#option-b-add-a-local-node">Option B: Add a local node</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="quick-start/index.html#deploy-your-provider">Deploy your provider</a>
+ <ol>
+ <li>
+ <a href="quick-start/index.html#initialize-the-node">Initialize the node</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#deploy-to-the-node">Deploy to the node</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#setup-dns">Setup DNS</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="quick-start/index.html#test-that-things-worked-correctly">Test that things worked correctly</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#create-an-administrator">Create an administrator</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#what-is-next">What is next?</a>
+ <ol>
+ <li>
+ <a href="quick-start/index.html#add-an-end-user-service">Add an end-user service</a>
+ </li>
+ <li>
+ <a href="quick-start/index.html#learn-more">Learn more</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="introduction"></a>Introduction</h1>
+
+<h3><a name="our-goal"></a>Our goal</h3>
+
+<p>We are going to create a minimal LEAP provider, but one that does not offer any actual services. Check out the other tutorials for adding VPN or email services.</p>
+
+<p>Our goal is something like this:</p>
+
+<pre><code>$ leap list
+ NODES SERVICES TAGS
+ wildebeest couchdb, webapp
+</code></pre>
+
+<p>NOTE: You won&rsquo;t be able to run that <code>leap list</code> command yet, not until we actually create the node configurations.</p>
+
+<h3><a name="requirements"></a>Requirements</h3>
+
+<ol>
+<li>A workstation: This is your local machine that you will run commands on.</li>
+<li>A server: This is the machine that you will deploy to. The server can be either:
+
+<ol>
+<li>A local Vagrant virtual machine: a Vagrant machine can only be useful for testing.</li>
+<li>A real or paravirtualized server: The server must have Debian Jessie installed, and you must be able to SSH into the machine as root. Paravirtualization includes KVM, Xen, OpenStack, Amazon, but not VirtualBox or OpenVZ.</li>
+</ol>
+</li>
+</ol>
+
+
+<p>Other things to keep in mind:</p>
+
+<ul>
+<li>The ability to create/modify DNS entries for your domain is preferable, but not needed. If you don&rsquo;t have access to DNS, you can workaround this by modifying your local resolver, i.e. editing <code>/etc/hosts</code>.</li>
+<li>You need to be aware that this process will make changes to your servers, so please be sure that these machines are a basic install with nothing configured or running for other purposes.</li>
+<li>Your servers will need to be connected to the internet, and not behind a restrictive firewall.</li>
+</ul>
+
+
+<h1><a name="prepare-your-workstation"></a>Prepare your workstation</h1>
+
+<p>In order to be able to manage your servers, you need to install the <code>leap</code> command on your workstation:</p>
+
+<h3><a name="install-pre-requisites"></a>Install pre-requisites</h3>
+
+<p>Install core prerequisites on your workstation.</p>
+
+<p><em>Debian &amp; Ubuntu</em></p>
+
+<pre><code>workstation$ sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make bzip2
+</code></pre>
+
+<p><em>Mac OS</em></p>
+
+<pre><code>workstation$ brew install ruby-install
+workstation$ ruby-install ruby
+</code></pre>
+
+<h3><a name="install-the-leap-command-line-utility"></a>Install the LEAP command-line utility</h3>
+
+<p>Install the <code>leap</code> command system-wide:</p>
+
+<pre><code>workstation$ sudo gem install leap_cli
+</code></pre>
+
+<p>Alternately, you can install <code>leap</code> locally without root privileges:</p>
+
+<pre><code>workstation$ gem install --user-install leap_cli
+workstation$ PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin"
+</code></pre>
+
+<p>If you choose a local install, you probably want to permanently add the &ndash;user-install directory to your PATH by adding this to your <code>~/.profile</code> file (requires logout):</p>
+
+<pre><code>[ $(which ruby) ] &amp;&amp; PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin"
+</code></pre>
+
+<p>To confirm that you installed <code>leap</code> correctly, try running <code>leap --version</code>.</p>
+
+<h1><a name="create-a-provider-instance"></a>Create a provider instance</h1>
+
+<p>A provider instance is a directory tree, residing on your workstation, that contains everything you need to manage an infrastructure for a service provider.</p>
+
+<p>In this case, we create one for example.org and call the instance directory &lsquo;example&rsquo;.</p>
+
+<pre><code>workstation$ leap new ~/example
+</code></pre>
+
+<p>The <code>leap new</code> command will ask you for several required values:</p>
+
+<ul>
+<li>domain: The primary domain name of your service provider. In this tutorial, we will be using &ldquo;example.org&rdquo;.</li>
+<li>name: The name of your service provider (we use &ldquo;Example&rdquo;).</li>
+<li>contact emails: A comma separated list of email addresses that should be used for important service provider contacts (for things like postmaster aliases, Tor contact emails, etc).</li>
+<li>platform: The directory where you have a copy of the <code>leap_platform</code> git repository checked out. If the platform directory does not yet exist, the <code>leap_platform</code> will be downloaded and placed in that directory.</li>
+</ul>
+
+
+<p>You could also have passed these configuration options on the command-line, like so:</p>
+
+<pre><code>workstation$ leap new --contacts your@email.here --domain example.org --name Example --platform=~/leap/leap_platform .
+</code></pre>
+
+<p>You should now have the following files:</p>
+
+<pre><code>workstation$ tree example
+example
+├── common.json
+├── Leapfile
+├── nodes/
+├── provider.json
+├── services/
+└── tags/
+</code></pre>
+
+<p>Now add yourself as a privileged sysadmin who will have access to deploy to servers:</p>
+
+<pre><code>workstation$ cd example
+workstation$ leap add-user louise --self
+</code></pre>
+
+<p>Replace &ldquo;louise&rdquo; with whatever you want your sysadmin username to be.</p>
+
+<p>NOTE: Make sure you change directories so that the <code>leap</code> command is run from within the provider instance directory. Most <code>leap</code> commands only work when run from a provider instance.</p>
+
+<p>Now create the necessary keys and certificates:</p>
+
+<pre><code>workstation$ leap cert ca
+workstation$ leap cert csr
+</code></pre>
+
+<p>What do these commands do? The first command will create two Certificate Authorities, one that clients will use to authenticate with the servers and one for backend servers to authenticate with each other. The second command creates a Certificate Signing Request suitable for submission to a commercial CA. It also creates two &ldquo;dummy&rdquo; files for you to use temporarily:</p>
+
+<ul>
+<li><code>files/cert/example.org.crt</code> &ndash; This is a &ldquo;dummy&rdquo; certificate for your domain that can be used temporarily for testing. Once you get a real certificate from a CA, you should replace this file.</li>
+<li><code>files/cert/commercial_ca.crt</code> &ndash; This is &ldquo;dummy&rdquo; CA cert the corresponds to the dummy domain certificate. Once you replace the domain certificate, also replace this file with the CA cert from the real Certificate Authority.</li>
+</ul>
+
+
+<p>If you plan to run a real service provider, see important information on <a href="../guide/keys-and-certificates.html">managing keys and certificates</a>.</p>
+
+<h1><a name="add-a-node-to-the-provider"></a>Add a node to the provider</h1>
+
+<p>A &ldquo;node&rdquo; is a server that is part of your infrastructure. Every node can have one or more services associated with it. We will now add a single node with two services, &ldquo;webapp&rdquo; and &ldquo;couchdb&rdquo;.</p>
+
+<p>You have two choices for node type: a real node or a local node.</p>
+
+<ul>
+<li>Real Node: A real node is any physical or paravirtualized server, including KVM, Xen, OpenStack Compute, Amazon EC2, but not VirtualBox or OpenVZ (VirtualBox and OpenVZ use a more limited form of virtualization). The server must be running Debian Jessie.</li>
+<li>Local Node: A local node is a virtual machine created by Vagrant, useful for local testing on your workstation.</li>
+</ul>
+
+
+<p>Getting Vagrant working can be a pain and is <a href="vagrant.html">covered in other tutorials</a>. If you have a real server available, we suggest you try this tutorial with a real node first.</p>
+
+<h3><a name="option-a-add-a-real-node"></a>Option A: Add a real node</h3>
+
+<p>Note: Installing LEAP Platform on this server will potentially destroy anything you have previously installed on this machine.</p>
+
+<p>Create a node, with the services &ldquo;webapp&rdquo; and &ldquo;couchdb&rdquo;:</p>
+
+<pre><code>workstation$ leap node add wildebeest ip_address:x.x.x.w services:webapp,couchdb
+</code></pre>
+
+<p>NOTE: replace x.x.x.x with the actual IP address of this server.</p>
+
+<h3><a name="option-b-add-a-local-node"></a>Option B: Add a local node</h3>
+
+<p>Create a node, with the services &ldquo;webapp&rdquo; and &ldquo;couchdb&rdquo;, and then start the local virtual machine:</p>
+
+<pre><code>workstation$ leap node add --local wildebeest services:webapp,couchdb
+workstation$ leap local start wildebeest
+</code></pre>
+
+<p>It will take a while to download the Virtualbox base box and create the virtual machine.</p>
+
+<h1><a name="deploy-your-provider"></a>Deploy your provider</h1>
+
+<h3><a name="initialize-the-node"></a>Initialize the node</h3>
+
+<p>Node initialization only needs to be done once, but there is no harm in doing it multiple times:</p>
+
+<pre><code>workstation$ leap node init wildebeest
+</code></pre>
+
+<p>This will initialize the node <code>wildebeest</code>.</p>
+
+<p>For non-local nodes, when <code>leap node init</code> is run, you will be prompted to verify the fingerprint of the SSH host key and to provide the root password of the server(s). You should only need to do this once.</p>
+
+<h3><a name="deploy-to-the-node"></a>Deploy to the node</h3>
+
+<p>The next step is to deploy the LEAP platform to your node. <a href="https://xkcd.com/303/">Deployment can take a while to run</a>, especially on the first run, as it needs to update the packages on the new machine.</p>
+
+<pre><code>workstation$ leap deploy wildebeest
+</code></pre>
+
+<p>Watch the output for any errors (in red), if everything worked fine, you should now have your first running node. If you do have errors, try doing the deploy again.</p>
+
+<h3><a name="setup-dns"></a>Setup DNS</h3>
+
+<p>The next step is to configure the DNS for your provider. For testing purposes, you can just modify your <code>/etc/hosts</code> file. Please don&rsquo;t forget about these entries, they will override DNS queries if you setup your DNS later. For a list of what entries to add to <code>/etc/hosts</code>, run this command:</p>
+
+<pre><code>workstation$ leap compile hosts
+</code></pre>
+
+<p>Alternately, if you have access to modify the DNS zone entries for your domain:</p>
+
+<pre><code>workstation$ leap compile zone
+</code></pre>
+
+<p>NOTE: The resulting zone file is incomplete because it is missing a serial number. Use the output of <code>leap compile zone</code> as a guide, but do not just copy and paste the output. Also, the <code>compile zone</code> output will always exclude mention of local nodes.</p>
+
+<p>The DNS method will not work for local nodes created with Vagrant.</p>
+
+<h1><a name="test-that-things-worked-correctly"></a>Test that things worked correctly</h1>
+
+<p>To run troubleshooting tests:</p>
+
+<pre><code>workstation$ leap test
+</code></pre>
+
+<p>Alternately, you can run these same tests from the server itself:</p>
+
+<pre><code>workstation$ leap ssh wildebeest
+wildebeest# run_tests
+</code></pre>
+
+<h1><a name="create-an-administrator"></a>Create an administrator</h1>
+
+<p>Assuming that you set up your DNS or <code>/etc/hosts</code> file, you should be able to load <code>https://example.org</code> in your web browser (where example.org is whatever domain name you actually used).</p>
+
+<p>Your browser will complain about an untrusted cert, but for now just bypass this. From there, you should be able to register a new user and login.</p>
+
+<p>Once you have created a user, you can now make this user an administrator. For example, if you created a user <code>kangaroo</code>, you would create the file <code>services/webapp.json</code> with the following content:</p>
+
+<pre><code>{
+ "webapp": {
+ "admins": ["kangaroo"]
+ }
+}
+</code></pre>
+
+<p>Save that file and run <code>leap deploy</code> again. When you next log on to the web application, the user kangaroo will now be an admin.</p>
+
+<p>If you want to restrict who can register a new user, see <a href="../services/webapp.html">webapp</a> for configuration options.</p>
+
+<h1><a name="what-is-next"></a>What is next?</h1>
+
+<h2><a name="add-an-end-user-service"></a>Add an end-user service</h2>
+
+<p>You should now have a minimal service provider with a single node. This service provider is pointless at the moment, because it does not include any end-user services like VPN or email. To add one of these services, continue with one of the following tutorials:</p>
+
+<ul>
+<li><a href="single-node-email.html">Quick email</a></li>
+<li><a href="single-node-vpn.html">Quick VPN</a></li>
+</ul>
+
+
+<h2><a name="learn-more"></a>Learn more</h2>
+
+<p>We have only just scratched the surface of the possible ways to configure and deploy your service provider. Your next step should be:</p>
+
+<ul>
+<li>Read <a href="../guide/getting-started.html">Getting Started</a> for more details on using the LEAP platform.</li>
+<li>See <a href="../guide/commands.html">Command Line Reference</a> for a list of possible commands.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/quick-start/index.html b/docs/en/tutorials/quick-start/index.html
new file mode 100644
index 00000000..27b21238
--- /dev/null
+++ b/docs/en/tutorials/quick-start/index.html
@@ -0,0 +1,446 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Quick Start Tutorial - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class='active level1'>
+<a class='' href='../quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='../single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='../single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='../vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Quick Start Tutorial</h1>
+
+<div id='summary'>This tutorial walks you through the initial process of creating and deploying a minimal service provider running the LEAP Platform.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#introduction">Introduction</a>
+ <ol>
+ <li>
+ <a href="index.html#our-goal">Our goal</a>
+ </li>
+ <li>
+ <a href="index.html#requirements">Requirements</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#prepare-your-workstation">Prepare your workstation</a>
+ <ol>
+ <li>
+ <a href="index.html#install-pre-requisites">Install pre-requisites</a>
+ </li>
+ <li>
+ <a href="index.html#install-the-leap-command-line-utility">Install the LEAP command-line utility</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#create-a-provider-instance">Create a provider instance</a>
+ </li>
+ <li>
+ <a href="index.html#add-a-node-to-the-provider">Add a node to the provider</a>
+ <ol>
+ <li>
+ <a href="index.html#option-a-add-a-real-node">Option A: Add a real node</a>
+ </li>
+ <li>
+ <a href="index.html#option-b-add-a-local-node">Option B: Add a local node</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#deploy-your-provider">Deploy your provider</a>
+ <ol>
+ <li>
+ <a href="index.html#initialize-the-node">Initialize the node</a>
+ </li>
+ <li>
+ <a href="index.html#deploy-to-the-node">Deploy to the node</a>
+ </li>
+ <li>
+ <a href="index.html#setup-dns">Setup DNS</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#test-that-things-worked-correctly">Test that things worked correctly</a>
+ </li>
+ <li>
+ <a href="index.html#create-an-administrator">Create an administrator</a>
+ </li>
+ <li>
+ <a href="index.html#what-is-next">What is next?</a>
+ <ol>
+ <li>
+ <a href="index.html#add-an-end-user-service">Add an end-user service</a>
+ </li>
+ <li>
+ <a href="index.html#learn-more">Learn more</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="introduction"></a>Introduction</h1>
+
+<h3><a name="our-goal"></a>Our goal</h3>
+
+<p>We are going to create a minimal LEAP provider, but one that does not offer any actual services. Check out the other tutorials for adding VPN or email services.</p>
+
+<p>Our goal is something like this:</p>
+
+<pre><code>$ leap list
+ NODES SERVICES TAGS
+ wildebeest couchdb, webapp
+</code></pre>
+
+<p>NOTE: You won&rsquo;t be able to run that <code>leap list</code> command yet, not until we actually create the node configurations.</p>
+
+<h3><a name="requirements"></a>Requirements</h3>
+
+<ol>
+<li>A workstation: This is your local machine that you will run commands on.</li>
+<li>A server: This is the machine that you will deploy to. The server can be either:
+
+<ol>
+<li>A local Vagrant virtual machine: a Vagrant machine can only be useful for testing.</li>
+<li>A real or paravirtualized server: The server must have Debian Jessie installed, and you must be able to SSH into the machine as root. Paravirtualization includes KVM, Xen, OpenStack, Amazon, but not VirtualBox or OpenVZ.</li>
+</ol>
+</li>
+</ol>
+
+
+<p>Other things to keep in mind:</p>
+
+<ul>
+<li>The ability to create/modify DNS entries for your domain is preferable, but not needed. If you don&rsquo;t have access to DNS, you can workaround this by modifying your local resolver, i.e. editing <code>/etc/hosts</code>.</li>
+<li>You need to be aware that this process will make changes to your servers, so please be sure that these machines are a basic install with nothing configured or running for other purposes.</li>
+<li>Your servers will need to be connected to the internet, and not behind a restrictive firewall.</li>
+</ul>
+
+
+<h1><a name="prepare-your-workstation"></a>Prepare your workstation</h1>
+
+<p>In order to be able to manage your servers, you need to install the <code>leap</code> command on your workstation:</p>
+
+<h3><a name="install-pre-requisites"></a>Install pre-requisites</h3>
+
+<p>Install core prerequisites on your workstation.</p>
+
+<p><em>Debian &amp; Ubuntu</em></p>
+
+<pre><code>workstation$ sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make bzip2
+</code></pre>
+
+<p><em>Mac OS</em></p>
+
+<pre><code>workstation$ brew install ruby-install
+workstation$ ruby-install ruby
+</code></pre>
+
+<h3><a name="install-the-leap-command-line-utility"></a>Install the LEAP command-line utility</h3>
+
+<p>Install the <code>leap</code> command system-wide:</p>
+
+<pre><code>workstation$ sudo gem install leap_cli
+</code></pre>
+
+<p>Alternately, you can install <code>leap</code> locally without root privileges:</p>
+
+<pre><code>workstation$ gem install --user-install leap_cli
+workstation$ PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin"
+</code></pre>
+
+<p>If you choose a local install, you probably want to permanently add the &ndash;user-install directory to your PATH by adding this to your <code>~/.profile</code> file (requires logout):</p>
+
+<pre><code>[ $(which ruby) ] &amp;&amp; PATH="$PATH:$(ruby -e 'puts Gem.user_dir')/bin"
+</code></pre>
+
+<p>To confirm that you installed <code>leap</code> correctly, try running <code>leap --version</code>.</p>
+
+<h1><a name="create-a-provider-instance"></a>Create a provider instance</h1>
+
+<p>A provider instance is a directory tree, residing on your workstation, that contains everything you need to manage an infrastructure for a service provider.</p>
+
+<p>In this case, we create one for example.org and call the instance directory &lsquo;example&rsquo;.</p>
+
+<pre><code>workstation$ leap new ~/example
+</code></pre>
+
+<p>The <code>leap new</code> command will ask you for several required values:</p>
+
+<ul>
+<li>domain: The primary domain name of your service provider. In this tutorial, we will be using &ldquo;example.org&rdquo;.</li>
+<li>name: The name of your service provider (we use &ldquo;Example&rdquo;).</li>
+<li>contact emails: A comma separated list of email addresses that should be used for important service provider contacts (for things like postmaster aliases, Tor contact emails, etc).</li>
+<li>platform: The directory where you have a copy of the <code>leap_platform</code> git repository checked out. If the platform directory does not yet exist, the <code>leap_platform</code> will be downloaded and placed in that directory.</li>
+</ul>
+
+
+<p>You could also have passed these configuration options on the command-line, like so:</p>
+
+<pre><code>workstation$ leap new --contacts your@email.here --domain example.org --name Example --platform=~/leap/leap_platform .
+</code></pre>
+
+<p>You should now have the following files:</p>
+
+<pre><code>workstation$ tree example
+example
+├── common.json
+├── Leapfile
+├── nodes/
+├── provider.json
+├── services/
+└── tags/
+</code></pre>
+
+<p>Now add yourself as a privileged sysadmin who will have access to deploy to servers:</p>
+
+<pre><code>workstation$ cd example
+workstation$ leap add-user louise --self
+</code></pre>
+
+<p>Replace &ldquo;louise&rdquo; with whatever you want your sysadmin username to be.</p>
+
+<p>NOTE: Make sure you change directories so that the <code>leap</code> command is run from within the provider instance directory. Most <code>leap</code> commands only work when run from a provider instance.</p>
+
+<p>Now create the necessary keys and certificates:</p>
+
+<pre><code>workstation$ leap cert ca
+workstation$ leap cert csr
+</code></pre>
+
+<p>What do these commands do? The first command will create two Certificate Authorities, one that clients will use to authenticate with the servers and one for backend servers to authenticate with each other. The second command creates a Certificate Signing Request suitable for submission to a commercial CA. It also creates two &ldquo;dummy&rdquo; files for you to use temporarily:</p>
+
+<ul>
+<li><code>files/cert/example.org.crt</code> &ndash; This is a &ldquo;dummy&rdquo; certificate for your domain that can be used temporarily for testing. Once you get a real certificate from a CA, you should replace this file.</li>
+<li><code>files/cert/commercial_ca.crt</code> &ndash; This is &ldquo;dummy&rdquo; CA cert the corresponds to the dummy domain certificate. Once you replace the domain certificate, also replace this file with the CA cert from the real Certificate Authority.</li>
+</ul>
+
+
+<p>If you plan to run a real service provider, see important information on <a href="../../guide/keys-and-certificates.html">managing keys and certificates</a>.</p>
+
+<h1><a name="add-a-node-to-the-provider"></a>Add a node to the provider</h1>
+
+<p>A &ldquo;node&rdquo; is a server that is part of your infrastructure. Every node can have one or more services associated with it. We will now add a single node with two services, &ldquo;webapp&rdquo; and &ldquo;couchdb&rdquo;.</p>
+
+<p>You have two choices for node type: a real node or a local node.</p>
+
+<ul>
+<li>Real Node: A real node is any physical or paravirtualized server, including KVM, Xen, OpenStack Compute, Amazon EC2, but not VirtualBox or OpenVZ (VirtualBox and OpenVZ use a more limited form of virtualization). The server must be running Debian Jessie.</li>
+<li>Local Node: A local node is a virtual machine created by Vagrant, useful for local testing on your workstation.</li>
+</ul>
+
+
+<p>Getting Vagrant working can be a pain and is <a href="../vagrant.html">covered in other tutorials</a>. If you have a real server available, we suggest you try this tutorial with a real node first.</p>
+
+<h3><a name="option-a-add-a-real-node"></a>Option A: Add a real node</h3>
+
+<p>Note: Installing LEAP Platform on this server will potentially destroy anything you have previously installed on this machine.</p>
+
+<p>Create a node, with the services &ldquo;webapp&rdquo; and &ldquo;couchdb&rdquo;:</p>
+
+<pre><code>workstation$ leap node add wildebeest ip_address:x.x.x.w services:webapp,couchdb
+</code></pre>
+
+<p>NOTE: replace x.x.x.x with the actual IP address of this server.</p>
+
+<h3><a name="option-b-add-a-local-node"></a>Option B: Add a local node</h3>
+
+<p>Create a node, with the services &ldquo;webapp&rdquo; and &ldquo;couchdb&rdquo;, and then start the local virtual machine:</p>
+
+<pre><code>workstation$ leap node add --local wildebeest services:webapp,couchdb
+workstation$ leap local start wildebeest
+</code></pre>
+
+<p>It will take a while to download the Virtualbox base box and create the virtual machine.</p>
+
+<h1><a name="deploy-your-provider"></a>Deploy your provider</h1>
+
+<h3><a name="initialize-the-node"></a>Initialize the node</h3>
+
+<p>Node initialization only needs to be done once, but there is no harm in doing it multiple times:</p>
+
+<pre><code>workstation$ leap node init wildebeest
+</code></pre>
+
+<p>This will initialize the node <code>wildebeest</code>.</p>
+
+<p>For non-local nodes, when <code>leap node init</code> is run, you will be prompted to verify the fingerprint of the SSH host key and to provide the root password of the server(s). You should only need to do this once.</p>
+
+<h3><a name="deploy-to-the-node"></a>Deploy to the node</h3>
+
+<p>The next step is to deploy the LEAP platform to your node. <a href="https://xkcd.com/303/">Deployment can take a while to run</a>, especially on the first run, as it needs to update the packages on the new machine.</p>
+
+<pre><code>workstation$ leap deploy wildebeest
+</code></pre>
+
+<p>Watch the output for any errors (in red), if everything worked fine, you should now have your first running node. If you do have errors, try doing the deploy again.</p>
+
+<h3><a name="setup-dns"></a>Setup DNS</h3>
+
+<p>The next step is to configure the DNS for your provider. For testing purposes, you can just modify your <code>/etc/hosts</code> file. Please don&rsquo;t forget about these entries, they will override DNS queries if you setup your DNS later. For a list of what entries to add to <code>/etc/hosts</code>, run this command:</p>
+
+<pre><code>workstation$ leap compile hosts
+</code></pre>
+
+<p>Alternately, if you have access to modify the DNS zone entries for your domain:</p>
+
+<pre><code>workstation$ leap compile zone
+</code></pre>
+
+<p>NOTE: The resulting zone file is incomplete because it is missing a serial number. Use the output of <code>leap compile zone</code> as a guide, but do not just copy and paste the output. Also, the <code>compile zone</code> output will always exclude mention of local nodes.</p>
+
+<p>The DNS method will not work for local nodes created with Vagrant.</p>
+
+<h1><a name="test-that-things-worked-correctly"></a>Test that things worked correctly</h1>
+
+<p>To run troubleshooting tests:</p>
+
+<pre><code>workstation$ leap test
+</code></pre>
+
+<p>Alternately, you can run these same tests from the server itself:</p>
+
+<pre><code>workstation$ leap ssh wildebeest
+wildebeest# run_tests
+</code></pre>
+
+<h1><a name="create-an-administrator"></a>Create an administrator</h1>
+
+<p>Assuming that you set up your DNS or <code>/etc/hosts</code> file, you should be able to load <code>https://example.org</code> in your web browser (where example.org is whatever domain name you actually used).</p>
+
+<p>Your browser will complain about an untrusted cert, but for now just bypass this. From there, you should be able to register a new user and login.</p>
+
+<p>Once you have created a user, you can now make this user an administrator. For example, if you created a user <code>kangaroo</code>, you would create the file <code>services/webapp.json</code> with the following content:</p>
+
+<pre><code>{
+ "webapp": {
+ "admins": ["kangaroo"]
+ }
+}
+</code></pre>
+
+<p>Save that file and run <code>leap deploy</code> again. When you next log on to the web application, the user kangaroo will now be an admin.</p>
+
+<p>If you want to restrict who can register a new user, see <a href="../../services/webapp.html">webapp</a> for configuration options.</p>
+
+<h1><a name="what-is-next"></a>What is next?</h1>
+
+<h2><a name="add-an-end-user-service"></a>Add an end-user service</h2>
+
+<p>You should now have a minimal service provider with a single node. This service provider is pointless at the moment, because it does not include any end-user services like VPN or email. To add one of these services, continue with one of the following tutorials:</p>
+
+<ul>
+<li><a href="../single-node-email.html">Quick email</a></li>
+<li><a href="../single-node-vpn.html">Quick VPN</a></li>
+</ul>
+
+
+<h2><a name="learn-more"></a>Learn more</h2>
+
+<p>We have only just scratched the surface of the possible ways to configure and deploy your service provider. Your next step should be:</p>
+
+<ul>
+<li>Read <a href="../../guide/getting-started.html">Getting Started</a> for more details on using the LEAP platform.</li>
+<li>See <a href="../../guide/commands.html">Command Line Reference</a> for a list of possible commands.</li>
+</ul>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/single-node-email.html b/docs/en/tutorials/single-node-email.html
new file mode 100644
index 00000000..6678fec3
--- /dev/null
+++ b/docs/en/tutorials/single-node-email.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Quick email - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class='active level1'>
+<a class='' href='single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Single node email tutorial</h1>
+
+<div id='summary'>Tutorial for setting up a simple email provider.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="single-node-email/index.html#our-goal">Our goal</a>
+ </li>
+ <li>
+ <a href="single-node-email/index.html#add-email-services-to-the-node">Add email services to the node</a>
+ </li>
+ <li>
+ <a href="single-node-email/index.html#deploy-to-the-node">Deploy to the node</a>
+ </li>
+ <li>
+ <a href="single-node-email/index.html#setup-dns">Setup DNS</a>
+ </li>
+ <li>
+ <a href="single-node-email/index.html#test-it-out">Test it out</a>
+ </li>
+</ol></div>
+
+<p>This tutorial walks you through the initial process of creating and deploying a minimal email service provider. Please first complete the <a href="quick-start.html">Quick Start Tutorial</a>. This tutorial will pick up where that one left off.</p>
+
+<h2><a name="our-goal"></a>Our goal</h2>
+
+<p>We are going to create a minimal LEAP provider offering email service.</p>
+
+<p>Our goal is something like this:</p>
+
+<pre><code>$ leap list
+ NODES SERVICES TAGS
+ wildebeest couchdb, mx, soledad, webapp
+</code></pre>
+
+<p>Where &lsquo;wildebeest&rsquo; is whatever name you chose for your node in the <a href="quick-start.html">Quick Start Tutorial</a>.</p>
+
+<h2><a name="add-email-services-to-the-node"></a>Add email services to the node</h2>
+
+<p>In order to add <a href="../services.html">services</a> to a node, edit the node&rsquo;s JSON configuration file.</p>
+
+<p>In our example, we would edit <code>nodes/wildebeest.json</code>:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["couchdb", "webapp", "mx", "soledad"]
+}
+</code></pre>
+
+<p>Here, we added <code>mx</code> and <code>soledad</code> to the node&rsquo;s <code>services</code> list. Briefly:</p>
+
+<ul>
+<li><strong>mx</strong>: nodes with the <strong>mx</strong> service will run postfix mail transfer agent, and are able to receive and relay email on behalf of your domain. You can have as many as you want, spread out over as many nodes as you want.</li>
+<li><strong>soledad</strong>: nodes with <strong>soledad</strong> service run the server-side daemon that allows the client to synchronize a user&rsquo;s personal data store among their devices. Currently, <strong>soledad</strong> only runs on nodes that are also <strong>couchdb</strong> nodes.</li>
+</ul>
+
+
+<p>For more details, see the <a href="../services.html">Services</a> overview, or the individual pages for the <a href="../services/mx.html">mx</a> and <a href="../services/soledad.html">soledad</a> services.</p>
+
+<h2><a name="deploy-to-the-node"></a>Deploy to the node</h2>
+
+<p>Now you should deploy to your node.</p>
+
+<pre><code>workstation$ leap deploy
+</code></pre>
+
+<h2><a name="setup-dns"></a>Setup DNS</h2>
+
+<p>There are several important DNS entries that all email providers should have:</p>
+
+<ul>
+<li>SPF (Sender Policy Framework): With SPF, an email provider advertises in their DNS which servers should be allowed to relay email on behalf of your domain.</li>
+<li>DKIM (DomainKey Identified Mail): With DKIM, an email provider is able to vouch for the validity of certain headers in outgoing mail, allowing the receiving provider to have more confidence in these values when processing the message for spam or abuse.</li>
+</ul>
+
+
+<p>In order to take advantage of SPF and DKIM, run this command:</p>
+
+<pre><code>workstation$ leap compile zone
+</code></pre>
+
+<p>Then take the output of that command and merge it with the DNS zone file for your domain.</p>
+
+<p>CAUTION: the output of <code>leap compile zone</code> is not a complete zone file since it is missing a serial number. You will need to manually merge it with your existing zone file.</p>
+
+<h2><a name="test-it-out"></a>Test it out</h2>
+
+<p>First, run:</p>
+
+<pre><code>workstation# leap test
+</code></pre>
+
+<p>Then fire up the bitmask client, register a new user with your provider, and try sending and receiving email.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/single-node-email/index.html b/docs/en/tutorials/single-node-email/index.html
new file mode 100644
index 00000000..45a1264f
--- /dev/null
+++ b/docs/en/tutorials/single-node-email/index.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Quick email - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='../quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='../single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class='active level1'>
+<a class='' href='../single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='../vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Single node email tutorial</h1>
+
+<div id='summary'>Tutorial for setting up a simple email provider.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#our-goal">Our goal</a>
+ </li>
+ <li>
+ <a href="index.html#add-email-services-to-the-node">Add email services to the node</a>
+ </li>
+ <li>
+ <a href="index.html#deploy-to-the-node">Deploy to the node</a>
+ </li>
+ <li>
+ <a href="index.html#setup-dns">Setup DNS</a>
+ </li>
+ <li>
+ <a href="index.html#test-it-out">Test it out</a>
+ </li>
+</ol></div>
+
+<p>This tutorial walks you through the initial process of creating and deploying a minimal email service provider. Please first complete the <a href="../quick-start.html">Quick Start Tutorial</a>. This tutorial will pick up where that one left off.</p>
+
+<h2><a name="our-goal"></a>Our goal</h2>
+
+<p>We are going to create a minimal LEAP provider offering email service.</p>
+
+<p>Our goal is something like this:</p>
+
+<pre><code>$ leap list
+ NODES SERVICES TAGS
+ wildebeest couchdb, mx, soledad, webapp
+</code></pre>
+
+<p>Where &lsquo;wildebeest&rsquo; is whatever name you chose for your node in the <a href="../quick-start.html">Quick Start Tutorial</a>.</p>
+
+<h2><a name="add-email-services-to-the-node"></a>Add email services to the node</h2>
+
+<p>In order to add <a href="../../services.html">services</a> to a node, edit the node&rsquo;s JSON configuration file.</p>
+
+<p>In our example, we would edit <code>nodes/wildebeest.json</code>:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["couchdb", "webapp", "mx", "soledad"]
+}
+</code></pre>
+
+<p>Here, we added <code>mx</code> and <code>soledad</code> to the node&rsquo;s <code>services</code> list. Briefly:</p>
+
+<ul>
+<li><strong>mx</strong>: nodes with the <strong>mx</strong> service will run postfix mail transfer agent, and are able to receive and relay email on behalf of your domain. You can have as many as you want, spread out over as many nodes as you want.</li>
+<li><strong>soledad</strong>: nodes with <strong>soledad</strong> service run the server-side daemon that allows the client to synchronize a user&rsquo;s personal data store among their devices. Currently, <strong>soledad</strong> only runs on nodes that are also <strong>couchdb</strong> nodes.</li>
+</ul>
+
+
+<p>For more details, see the <a href="../../services.html">Services</a> overview, or the individual pages for the <a href="../../services/mx.html">mx</a> and <a href="../../services/soledad.html">soledad</a> services.</p>
+
+<h2><a name="deploy-to-the-node"></a>Deploy to the node</h2>
+
+<p>Now you should deploy to your node.</p>
+
+<pre><code>workstation$ leap deploy
+</code></pre>
+
+<h2><a name="setup-dns"></a>Setup DNS</h2>
+
+<p>There are several important DNS entries that all email providers should have:</p>
+
+<ul>
+<li>SPF (Sender Policy Framework): With SPF, an email provider advertises in their DNS which servers should be allowed to relay email on behalf of your domain.</li>
+<li>DKIM (DomainKey Identified Mail): With DKIM, an email provider is able to vouch for the validity of certain headers in outgoing mail, allowing the receiving provider to have more confidence in these values when processing the message for spam or abuse.</li>
+</ul>
+
+
+<p>In order to take advantage of SPF and DKIM, run this command:</p>
+
+<pre><code>workstation$ leap compile zone
+</code></pre>
+
+<p>Then take the output of that command and merge it with the DNS zone file for your domain.</p>
+
+<p>CAUTION: the output of <code>leap compile zone</code> is not a complete zone file since it is missing a serial number. You will need to manually merge it with your existing zone file.</p>
+
+<h2><a name="test-it-out"></a>Test it out</h2>
+
+<p>First, run:</p>
+
+<pre><code>workstation# leap test
+</code></pre>
+
+<p>Then fire up the bitmask client, register a new user with your provider, and try sending and receiving email.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/single-node-vpn.html b/docs/en/tutorials/single-node-vpn.html
new file mode 100644
index 00000000..1bfeb937
--- /dev/null
+++ b/docs/en/tutorials/single-node-vpn.html
@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Quick VPN - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class='active level1'>
+<a class='' href='single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Single node VPN tutorial</h1>
+
+<div id='summary'>Tutorial for setting up a simple VPN provider.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="single-node-vpn/index.html#our-goal">Our goal</a>
+ </li>
+ <li>
+ <a href="single-node-vpn/index.html#add-vpn-service-to-the-node">Add VPN service to the node</a>
+ </li>
+ <li>
+ <a href="single-node-vpn/index.html#add-gateway_address-to-the-node">Add gateway_address to the node</a>
+ </li>
+ <li>
+ <a href="single-node-vpn/index.html#generate-a-diffie-hellman-file">Generate a Diffie-Hellman file</a>
+ </li>
+ <li>
+ <a href="single-node-vpn/index.html#deploy-to-the-node">Deploy to the node</a>
+ </li>
+ <li>
+ <a href="single-node-vpn/index.html#test-it-out">Test it out</a>
+ </li>
+ <li>
+ <a href="single-node-vpn/index.html#what-do-do-next">What do do next</a>
+ </li>
+</ol></div>
+
+<p>This tutorial walks you through the initial process of creating and deploying a minimal VPN service provider. Please first complete the <a href="quick-start.html">Quick Start Tutorial</a>. This tutorial will pick up where that one left off.</p>
+
+<p>NOTE: For the VPN to work, you must use a real or paravirtualized node, not a local Vagrant node.</p>
+
+<h2><a name="our-goal"></a>Our goal</h2>
+
+<p>We are going to create a minimal LEAP provider offering VPN service.</p>
+
+<p>Our goal is something like this:</p>
+
+<pre><code>$ leap list
+ NODES SERVICES TAGS
+ wildebeest couchdb, webapp, openvpn, tor
+</code></pre>
+
+<p>Where &lsquo;wildebeest&rsquo; is whatever name you chose for your node in the <a href="quick-start.html">Quick Start Tutorial</a>.</p>
+
+<h2><a name="add-vpn-service-to-the-node"></a>Add VPN service to the node</h2>
+
+<p>In order to add <a href="../services.html">services</a> to a node, edit the node&rsquo;s JSON configuration file.</p>
+
+<p>In our example, we would edit <code>nodes/wildebeest.json</code>:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["couchdb", "webapp", "openvpn", "tor"]
+}
+</code></pre>
+
+<p>Here, we added <code>openvpn</code> and <code>tor</code> to the node&rsquo;s <code>services</code> list. Briefly:</p>
+
+<ul>
+<li><strong>openvpn</strong>: nodes with the <strong>openvpn</strong> service will become OpenVPN gateways that clients connect to in order to proxy their internet connection. You can have as many as you want, spread out over as many nodes as you want.</li>
+<li><strong>tor</strong>: nodes with <strong>tor</strong> service become Tor exit nodes. This is entirely optional, and will add additional bandwidth to your node. If you don&rsquo;t have many VPN users, the added traffic will help create cover traffic for your users. On the down side, this VPN gateway will get flagged as an anonymous proxy and some sites may block traffic from it.</li>
+</ul>
+
+
+<p>For more details, see the <a href="../services.html">Services</a> overview, or the individual pages for the <a href="../services/openvpn.html">openvpn</a> and <a href="../services/tor.html">tor</a> services.</p>
+
+<h2><a name="add-gateway_address-to-the-node"></a>Add gateway_address to the node</h2>
+
+<p>VPN gateways require two different IP addresses:</p>
+
+<ul>
+<li><code>ip_address</code>: This property is used for VPN traffic <strong>egress</strong>. In other words, all VPN traffic appears to come from this IP address. This is also the main IP of the server.</li>
+<li><code>openvpn.gateway_address</code>: This property is used for VPN traffic <strong>ingress</strong>. In other words, clients will connect to this IP address.</li>
+</ul>
+
+
+<p>The node configuration file should now look like this:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["couchdb", "webapp", "openvpn", "tor"],
+ "openvpn": {
+ "gateway_address": "2.2.2.2"
+ }
+}
+</code></pre>
+
+<p>Why two different addresses? Without this, the traffic from one VPN user to another would not be encrypted. This is because the routing table of VPN clients must ensure that packets with a destination of the VPN gateway are sent unmodified and don&rsquo;t get passed through the VPN&rsquo;s encryption.</p>
+
+<h2><a name="generate-a-diffie-hellman-file"></a>Generate a Diffie-Hellman file</h2>
+
+<p>Next we need to create a Diffie-Hellman parameter file, used for forward secret OpenVPN ciphers. You only need to do this once.</p>
+
+<pre><code>workstation$ leap cert dh
+</code></pre>
+
+<p>Feel free to erase the resulting DH file and regenerate it as you please.</p>
+
+<h2><a name="deploy-to-the-node"></a>Deploy to the node</h2>
+
+<p>Now you should deploy to your node. This may take a while.</p>
+
+<pre><code>workstation$ leap deploy
+</code></pre>
+
+<p>If the deploy was not successful, try to run it again.</p>
+
+<h2><a name="test-it-out"></a>Test it out</h2>
+
+<p>First, run:</p>
+
+<pre><code>workstation$ leap test
+</code></pre>
+
+<p>Then fire up the Bitmask client, register a new user with your provider, and turn on the VPN connection.</p>
+
+<p>Alternately, you can also manually connect to your VPN gateway using OpenVPN on the command line:</p>
+
+<pre><code>workstation$ sudo apt install openvpn
+workstation$ leap test init
+workstation$ sudo openvpn --config test/openvpn/default_unlimited.ovpn
+</code></pre>
+
+<p>Make sure that Bitmask is not connected to the VPN when you run that command.</p>
+
+<p>The name of the test configuration might differ depending on your setup. The test configuration created by <code>leap test init</code> includes a client certificate that will expire, so you may need to re-run <code>leap test init</code> if it has been a while since you last generated the test configuration.</p>
+
+<h2><a name="what-do-do-next"></a>What do do next</h2>
+
+<p>A VPN provider with a single gateway is kind of limited. You can add as many nodes with service <a href="../services/openvpn.html">openvpn</a> as you like. There is no communication among the VPN gateways or with the <a href="../services/webapp.html">webapp</a> or <a href="../services/couchdb.html">couchdb</a> nodes, so there is no issue with scaling out the number of gateways.</p>
+
+<p>For example, add some more nodes:</p>
+
+<pre><code>workstation$ leap node add giraffe ip_address:1.1.1.2 services:openvpn openvpn.gateway_address:2.2.2.3
+workstation$ leap node add rhino ip_address:1.1.1.3 services:openvpn openvpn.gateway_address:2.2.2.4
+workstation$ leap node init giraffe rhino
+workstation$ leap deploy
+</code></pre>
+
+<p>Now you have three VPN gateways.</p>
+
+<p>One consideration is that you should tag each VPN gateway with a <a href="../guide/nodes.html#locations">location</a>. This helps the client determine which VPN gateway it should connect to by default and will allow the user to choose among gateways based on location.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/single-node-vpn/index.html b/docs/en/tutorials/single-node-vpn/index.html
new file mode 100644
index 00000000..adceb66f
--- /dev/null
+++ b/docs/en/tutorials/single-node-vpn/index.html
@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Quick VPN - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='../quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class='active level1'>
+<a class='' href='../single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='../single-node-email.html'>Quick email</a>
+</li>
+<li class=' level1'>
+<a class='' href='../vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Single node VPN tutorial</h1>
+
+<div id='summary'>Tutorial for setting up a simple VPN provider.</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#our-goal">Our goal</a>
+ </li>
+ <li>
+ <a href="index.html#add-vpn-service-to-the-node">Add VPN service to the node</a>
+ </li>
+ <li>
+ <a href="index.html#add-gateway_address-to-the-node">Add gateway_address to the node</a>
+ </li>
+ <li>
+ <a href="index.html#generate-a-diffie-hellman-file">Generate a Diffie-Hellman file</a>
+ </li>
+ <li>
+ <a href="index.html#deploy-to-the-node">Deploy to the node</a>
+ </li>
+ <li>
+ <a href="index.html#test-it-out">Test it out</a>
+ </li>
+ <li>
+ <a href="index.html#what-do-do-next">What do do next</a>
+ </li>
+</ol></div>
+
+<p>This tutorial walks you through the initial process of creating and deploying a minimal VPN service provider. Please first complete the <a href="../quick-start.html">Quick Start Tutorial</a>. This tutorial will pick up where that one left off.</p>
+
+<p>NOTE: For the VPN to work, you must use a real or paravirtualized node, not a local Vagrant node.</p>
+
+<h2><a name="our-goal"></a>Our goal</h2>
+
+<p>We are going to create a minimal LEAP provider offering VPN service.</p>
+
+<p>Our goal is something like this:</p>
+
+<pre><code>$ leap list
+ NODES SERVICES TAGS
+ wildebeest couchdb, webapp, openvpn, tor
+</code></pre>
+
+<p>Where &lsquo;wildebeest&rsquo; is whatever name you chose for your node in the <a href="../quick-start.html">Quick Start Tutorial</a>.</p>
+
+<h2><a name="add-vpn-service-to-the-node"></a>Add VPN service to the node</h2>
+
+<p>In order to add <a href="../../services.html">services</a> to a node, edit the node&rsquo;s JSON configuration file.</p>
+
+<p>In our example, we would edit <code>nodes/wildebeest.json</code>:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["couchdb", "webapp", "openvpn", "tor"]
+}
+</code></pre>
+
+<p>Here, we added <code>openvpn</code> and <code>tor</code> to the node&rsquo;s <code>services</code> list. Briefly:</p>
+
+<ul>
+<li><strong>openvpn</strong>: nodes with the <strong>openvpn</strong> service will become OpenVPN gateways that clients connect to in order to proxy their internet connection. You can have as many as you want, spread out over as many nodes as you want.</li>
+<li><strong>tor</strong>: nodes with <strong>tor</strong> service become Tor exit nodes. This is entirely optional, and will add additional bandwidth to your node. If you don&rsquo;t have many VPN users, the added traffic will help create cover traffic for your users. On the down side, this VPN gateway will get flagged as an anonymous proxy and some sites may block traffic from it.</li>
+</ul>
+
+
+<p>For more details, see the <a href="../../services.html">Services</a> overview, or the individual pages for the <a href="../../services/openvpn.html">openvpn</a> and <a href="../../services/tor.html">tor</a> services.</p>
+
+<h2><a name="add-gateway_address-to-the-node"></a>Add gateway_address to the node</h2>
+
+<p>VPN gateways require two different IP addresses:</p>
+
+<ul>
+<li><code>ip_address</code>: This property is used for VPN traffic <strong>egress</strong>. In other words, all VPN traffic appears to come from this IP address. This is also the main IP of the server.</li>
+<li><code>openvpn.gateway_address</code>: This property is used for VPN traffic <strong>ingress</strong>. In other words, clients will connect to this IP address.</li>
+</ul>
+
+
+<p>The node configuration file should now look like this:</p>
+
+<pre><code>{
+ "ip_address": "1.1.1.1",
+ "services": ["couchdb", "webapp", "openvpn", "tor"],
+ "openvpn": {
+ "gateway_address": "2.2.2.2"
+ }
+}
+</code></pre>
+
+<p>Why two different addresses? Without this, the traffic from one VPN user to another would not be encrypted. This is because the routing table of VPN clients must ensure that packets with a destination of the VPN gateway are sent unmodified and don&rsquo;t get passed through the VPN&rsquo;s encryption.</p>
+
+<h2><a name="generate-a-diffie-hellman-file"></a>Generate a Diffie-Hellman file</h2>
+
+<p>Next we need to create a Diffie-Hellman parameter file, used for forward secret OpenVPN ciphers. You only need to do this once.</p>
+
+<pre><code>workstation$ leap cert dh
+</code></pre>
+
+<p>Feel free to erase the resulting DH file and regenerate it as you please.</p>
+
+<h2><a name="deploy-to-the-node"></a>Deploy to the node</h2>
+
+<p>Now you should deploy to your node. This may take a while.</p>
+
+<pre><code>workstation$ leap deploy
+</code></pre>
+
+<p>If the deploy was not successful, try to run it again.</p>
+
+<h2><a name="test-it-out"></a>Test it out</h2>
+
+<p>First, run:</p>
+
+<pre><code>workstation$ leap test
+</code></pre>
+
+<p>Then fire up the Bitmask client, register a new user with your provider, and turn on the VPN connection.</p>
+
+<p>Alternately, you can also manually connect to your VPN gateway using OpenVPN on the command line:</p>
+
+<pre><code>workstation$ sudo apt install openvpn
+workstation$ leap test init
+workstation$ sudo openvpn --config test/openvpn/default_unlimited.ovpn
+</code></pre>
+
+<p>Make sure that Bitmask is not connected to the VPN when you run that command.</p>
+
+<p>The name of the test configuration might differ depending on your setup. The test configuration created by <code>leap test init</code> includes a client certificate that will expire, so you may need to re-run <code>leap test init</code> if it has been a while since you last generated the test configuration.</p>
+
+<h2><a name="what-do-do-next"></a>What do do next</h2>
+
+<p>A VPN provider with a single gateway is kind of limited. You can add as many nodes with service <a href="../../services/openvpn.html">openvpn</a> as you like. There is no communication among the VPN gateways or with the <a href="../../services/webapp.html">webapp</a> or <a href="../../services/couchdb.html">couchdb</a> nodes, so there is no issue with scaling out the number of gateways.</p>
+
+<p>For example, add some more nodes:</p>
+
+<pre><code>workstation$ leap node add giraffe ip_address:1.1.1.2 services:openvpn openvpn.gateway_address:2.2.2.3
+workstation$ leap node add rhino ip_address:1.1.1.3 services:openvpn openvpn.gateway_address:2.2.2.4
+workstation$ leap node init giraffe rhino
+workstation$ leap deploy
+</code></pre>
+
+<p>Now you have three VPN gateways.</p>
+
+<p>One consideration is that you should tag each VPN gateway with a <a href="../../guide/nodes.html#locations">location</a>. This helps the client determine which VPN gateway it should connect to by default and will allow the user to choose among gateways based on location.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/vagrant.html b/docs/en/tutorials/vagrant.html
new file mode 100644
index 00000000..3d4f0520
--- /dev/null
+++ b/docs/en/tutorials/vagrant.html
@@ -0,0 +1,724 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Vagrant - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='single-node-email.html'>Quick email</a>
+</li>
+<li class='active level1'>
+<a class='' href='vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Vagrant and the LEAP Platform</h1>
+
+<div id='summary'>Running a local provider with Vagrant</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="vagrant/index.html#what-is-vagrant">What is Vagrant?</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#install-vagrant">Install Vagrant</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#vagrant-with-leap-command">Vagrant with leap command</a>
+ <ol>
+ <li>
+ <a href="vagrant/index.html#creating-local-nodes">Creating local nodes</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#starting-local-nodes">Starting local nodes</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#useful-local-commands">Useful local commands</a>
+ <ol>
+ <li>
+ <a href="vagrant/index.html#listing-what-machines-are-running">Listing what machines are running</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#stopping-machines">Stopping machines</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#connecting-to-machines">Connecting to machines</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#snapshotting-machines">Snapshotting machines</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#more-information">More information</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="vagrant/index.html#2-vagrant-with-static-vagrantfile">2. Vagrant with static Vagrantfile</a>
+ <ol>
+ <li>
+ <a href="vagrant/index.html#use-the-bitmask-client-to-do-an-initial-soledad-sync">Use the bitmask client to do an initial soledad sync</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#testing-email">Testing email</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#re-run-bitmask-client-to-sync-your-mail">Re-run bitmask client to sync your mail</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#using-the-webapp">Using the Webapp</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="vagrant/index.html#support-for-libvirt">Support for libvirt</a>
+ <ol>
+ <li>
+ <a href="vagrant/index.html#install-libvirt-plugin">Install libvirt plugin</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#create-libvirt-pool">Create libvirt pool</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#force-use-of-libvirt">Force use of libvirt</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#debugging">Debugging</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#known-issues">Known issues</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#useful-commands">Useful commands</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#shared-folder-support">Shared folder support</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="vagrant/index.html#verify-vagrantboxes">Verify vagrantboxes</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#troubleshooting">Troubleshooting</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#additional-notes">Additional notes</a>
+ <ol>
+ <li>
+ <a href="vagrant/index.html#some-useful-plugins">Some useful plugins</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#limitations">Limitations</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#known-working-combinations">Known working combinations</a>
+ </li>
+ <li>
+ <a href="vagrant/index.html#issue-reporting">Issue reporting</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="what-is-vagrant"></a>What is Vagrant?</h1>
+
+<p><a href="https://www.vagrantup.com">Vagrant</a> is a tool to make it easier to manage virtual machines running on your desktop computer (typically for testing or development purposes). You can use Vagrant to create virtual machines and deploy the LEAP platform locally.</p>
+
+<p>Vagrant can be a pain to get working initially, but this page should help you get through the process. Please make sure you have at least Vagrant v1.5 installed.</p>
+
+<p>There are two ways you can setup LEAP platform using Vagrant.</p>
+
+<ol>
+<li>use the <code>leap</code> command: this will allow you to create multiple virtual machines.</li>
+<li>use static Vagrantfile: there is a static Vagrantfile that is distributed with the <code>leap_platform.git</code>. This only supports a single, pre-configured virtual machine, but can get you started more quickly.</li>
+</ol>
+
+
+<h1><a name="install-vagrant"></a>Install Vagrant</h1>
+
+<p>Requirements:</p>
+
+<ul>
+<li>A real machine with virtualization support in the CPU (VT-x or AMD-V). In other words, not a virtual machine.</li>
+<li>Have at least 4gb of RAM.</li>
+<li>Have a fast internet connection (because you will be downloading a lot of big files, like virtual machine images).</li>
+<li>You should do everything described below as an unprivileged user, and only run those commands as root that are noted with <em>sudo</em> in front of them. Other than those commands, there is no need for privileged access to your machine, and in fact things may not work correctly.</li>
+</ul>
+
+
+<p><em>Debian &amp; Ubuntu</em></p>
+
+<p>Install core prerequisites:</p>
+
+<pre><code>sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make
+</code></pre>
+
+<p>Install Vagrant:</p>
+
+<pre><code>sudo apt-get install vagrant virtualbox
+</code></pre>
+
+<p>If you want to use libvirt instead of virtualbox, you don&rsquo;t need to install virtualbox. See <a href="vagrant/index.html#support-for-libvirt">support for libvirt</a>.</p>
+
+<p><em>Mac OS X 10.9 (Mavericks)</em></p>
+
+<p>Install Homebrew package manager from <a href="http://brew.sh/">http://brew.sh/</a> and enable the <a href="https://github.com/Homebrew/homebrew/wiki/Interesting-Taps-&amp;-Branches">System Duplicates Repository</a> (needed to update old software versions delivered by Apple) with</p>
+
+<pre><code>brew tap homebrew/dupes
+</code></pre>
+
+<p>Update OpenSSH to support ECDSA keys. Follow <a href="http://www.dctrwatson.com/2013/07/how-to-update-openssh-on-mac-os-x/">this guide</a> to let your system use the Homebrew binary.</p>
+
+<pre><code>brew install openssh --with-brewed-openssl --with-keychain-support
+</code></pre>
+
+<p>The certtool provided by Apple it&rsquo;s really old, install the one provided by GnuTLS and shadow the system&rsquo;s default.</p>
+
+<pre><code>sudo brew install gnutls
+ln -sf /usr/local/bin/gnutls-certtool /usr/local/bin/certool
+</code></pre>
+
+<p>Install the Vagrant and VirtualBox packages for OS X from their respective Download pages.</p>
+
+<ul>
+<li><a href="http://www.vagrantup.com/downloads.html">http://www.vagrantup.com/downloads.html</a></li>
+<li><a href="https://www.virtualbox.org/wiki/Downloads">https://www.virtualbox.org/wiki/Downloads</a></li>
+</ul>
+
+
+<h1><a name="vagrant-with-leap-command"></a>Vagrant with leap command</h1>
+
+<p>If you have not done so, install <code>leap</code> command line tool:</p>
+
+<pre><code>gem install leap_cli
+</code></pre>
+
+<h2><a name="creating-local-nodes"></a>Creating local nodes</h2>
+
+<p>When you create a service provider, your servers are called &ldquo;nodes&rdquo;. When a node is virtual and exists only locally using vagrant, this type of node is called a &ldquo;local node&rdquo;.</p>
+
+<p>If you do not have a provider already, you will need to create one and configure it before continuing (see the <a href="vagrant/quick-start.html">Quick Start</a> guide).</p>
+
+<p>These commands, for example, will create an initial provider directory &ldquo;myprovider&rdquo;:</p>
+
+<pre><code>$ leap new --domain example.org --name Example myprovider
+$ cd myprovider
+$ leap add-user --self
+$ leap cert ca
+$ leap cert csr
+</code></pre>
+
+<p>To create local nodes, add the flag <code>--local</code> to the <code>leap node add</code> command. For example:</p>
+
+<pre><code>$ leap node add --local web1 services:webapp
+ = created nodes/web1.json
+ = created files/nodes/web1/
+ = created files/nodes/web1/web1.key
+ = created files/nodes/web1/web1.crt
+</code></pre>
+
+<p>This command creates a node configuration file in <code>nodes/web1.json</code> with the webapp service.</p>
+
+<h2><a name="starting-local-nodes"></a>Starting local nodes</h2>
+
+<p>In order to test the node &ldquo;web1&rdquo; we need to start it. Starting a node for the first time will spin up a virtual machine. The first time you do this will take some time because it will need to download a VM image (about 700mb). After you&rsquo;ve downloaded the base image, you will not need to download it again, and instead you will re-use the downloaded image (until you need to update the image).</p>
+
+<p>NOTE: Many people have difficulties getting Vagrant working. If the following commands do not work, please see the troubleshooting section below.</p>
+
+<pre><code>$ leap local start web1
+ = created test/
+ = created test/Vagrantfile
+ = installing vagrant plugin 'sahara'
+Bringing machine 'web1' up with 'virtualbox' provider...
+[web1] Box 'leap-jessie' was not found. Fetching box from specified URL for
+the provider 'virtualbox'. Note that if the URL does not have
+a box for this provider, you should interrupt Vagrant now and add
+the box yourself. Otherwise Vagrant will attempt to download the
+full box prior to discovering this error.
+Downloading or copying the box...
+Progress: 3% (Rate: 560k/s, Estimated time remaining: 0:13:36)
+...
+Bringing machine 'web1' up with 'virtualbox' provider...
+[web1] Importing base box 'leap-jessie'...
+0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
+</code></pre>
+
+<p>Now the virtual machine &lsquo;web1&rsquo; is running. You can add another local node using the same process. For example, the webapp node needs a databasse to run, so let&rsquo;s add a &ldquo;couchdb&rdquo; node:</p>
+
+<pre><code>$ leap node add --local db1 services:couchdb
+$ leap local start
+ = updated test/Vagrantfile
+Bringing machine 'db1' up with 'virtualbox' provider...
+[db1] Importing base box 'leap-jessie'...
+[db1] Matching MAC address for NAT networking...
+[db1] Setting the name of the VM...
+[db1] Clearing any previously set forwarded ports...
+[db1] Fixed port collision for 22 =&gt; 2222. Now on port 2202.
+[db1] Creating shared folders metadata...
+[db1] Clearing any previously set network interfaces...
+[db1] Preparing network interfaces based on configuration...
+[db1] Forwarding ports...
+[db1] -- 22 =&gt; 2202 (adapter 1)
+[db1] Running any VM customizations...
+[db1] Booting VM...
+[db1] Waiting for VM to boot. This can take a few minutes.
+[db1] VM booted and ready for use!
+[db1] Configuring and enabling network interfaces...
+[db1] Mounting shared folders...
+[db1] -- /vagrant
+</code></pre>
+
+<p>You now can follow the normal LEAP process and initialize it and then deploy your recipes to it:</p>
+
+<pre><code>$ leap node init web1
+$ leap deploy web1
+$ leap node init db1
+$ leap deploy db1
+</code></pre>
+
+<h2><a name="useful-local-commands"></a>Useful local commands</h2>
+
+<p>There are many useful things you can do with a virtualized development environment.</p>
+
+<h3><a name="listing-what-machines-are-running"></a>Listing what machines are running</h3>
+
+<p>Now you have the two virtual machines &ldquo;web1&rdquo; and &ldquo;db1&rdquo; running, you can see the running machines as follows:</p>
+
+<pre><code>$ leap local status
+Current machine states:
+
+db1 running (virtualbox)
+web1 running (virtualbox)
+
+This environment represents multiple VMs. The VMs are all listed
+above with their current state. For more information about a specific
+VM, run `vagrant status NAME`.
+</code></pre>
+
+<h3><a name="stopping-machines"></a>Stopping machines</h3>
+
+<p>It is not recommended that you leave your virtual machines running when you are not using them. They consume memory and other resources! To stop your machines, simply do the following:</p>
+
+<pre><code>$ leap local stop web1 db1
+</code></pre>
+
+<h3><a name="connecting-to-machines"></a>Connecting to machines</h3>
+
+<p>You can connect to your local nodes just like you do with normal LEAP nodes, by running &lsquo;leap ssh node&rsquo;.</p>
+
+<p>However, if you cannot connect to your local node, because the networking is not setup properly, or you have deployed a firewall that locks you out, you may need to access the graphical console.</p>
+
+<p>In order to do that, you will need to configure Vagrant to launch a graphical console and then you can login as root there to diagnose the networking problem. To do this, add the following to your $HOME/.leaprc:</p>
+
+<pre><code>@custom_vagrant_vm_line = 'config.vm.provider "virtualbox" do |v|
+ v.gui = true
+end'
+</code></pre>
+
+<p>and then start, or restart, your local Vagrant node. You should get a VirtualBox graphical interface presented to you showing you the bootup and eventually the login.</p>
+
+<h3><a name="snapshotting-machines"></a>Snapshotting machines</h3>
+
+<p>A very useful feature of local Vagrant development nodes is the ability to snapshot the current state and then revert to that when you need.</p>
+
+<p>For example, perhaps the base image is a little bit out of date and you want to get the packages updated to the latest before continuing. You can do that simply by starting the node, connecting to it and updating the packages and then snapshotting the node:</p>
+
+<pre><code>$ leap local start web1
+$ leap ssh web1
+web1# apt-get -u dist-upgrade
+web1# exit
+$ leap local save web1
+</code></pre>
+
+<p>Now you can deploy to web1 and if you decide you want to revert to the state before deployment, you simply have to reset the node to your previous save:</p>
+
+<pre><code>$ leap local reset web1
+</code></pre>
+
+<h3><a name="more-information"></a>More information</h3>
+
+<p>See <code>leap help local</code> for a complete list of local-only commands and how they can be used.</p>
+
+<h1><a name="2-vagrant-with-static-vagrantfile"></a>2. Vagrant with static Vagrantfile</h1>
+
+<p>You can use the static Vagrantfile if you want to get up a running with a pre-canned test provider.</p>
+
+<p>It will install a single node mail server in the default configuration with one single command.</p>
+
+<p>Clone the platform with</p>
+
+<pre><code>git clone --recursive -b develop https://github.com/leapcode/leap_platform.git
+</code></pre>
+
+<p>Start the vagrant box with</p>
+
+<pre><code>cd leap_platform
+vagrant up
+</code></pre>
+
+<p>Follow the instructions how to configure your <code>/etc/hosts</code>
+in order to use the provider!</p>
+
+<p>You can login via ssh with the systemuser <code>vagrant</code> and the same password.</p>
+
+<pre><code>vagrant ssh
+</code></pre>
+
+<p>On the host, run the tests to check if everything is working as expected:</p>
+
+<pre><code>cd /home/vagrant/leap/configuration/
+leap test
+</code></pre>
+
+<h2><a name="use-the-bitmask-client-to-do-an-initial-soledad-sync"></a>Use the bitmask client to do an initial soledad sync</h2>
+
+<p>Copy the self-signed CA certificate from the host.
+The easiest way is to use the <a href="https://github.com/invernizzi/vagrant-scp">vagrant-scp plugin</a>:</p>
+
+<pre><code>vagrant scp :/home/vagrant/leap/configuration/files/ca/ca.crt /tmp/example.org.ca.crt
+
+vagrant@node1:~/leap/configuration$ cat files/ca/ca.crt
+</code></pre>
+
+<p>and write it into a file, needed by the bitmask client:</p>
+
+<pre><code>bitmask --ca-cert-file /tmp/example.org.ca.crt
+</code></pre>
+
+<p>On the first run, bitmask is creating a gpg keypair. This is
+needed for delivering and encrypting incoming mails.</p>
+
+<h2><a name="testing-email"></a>Testing email</h2>
+
+<pre><code>sudo apt install swaks
+swaks -f test22@leap.se -t test22@example.org -s example.org
+</code></pre>
+
+<p>check the logs:</p>
+
+<pre><code>sudo less /var/log/mail.log
+sudo less /var/log/leap/mx.log
+</code></pre>
+
+<p>if an error occurs, see if the mail is still laying in the mailspool dir:</p>
+
+<pre><code>sudo ls /var/mail/leap-mx/Maildir/new
+</code></pre>
+
+<h2><a name="re-run-bitmask-client-to-sync-your-mail"></a>Re-run bitmask client to sync your mail</h2>
+
+<pre><code>bitmask --ca-cert-file /tmp/example.org.ca.crt
+</code></pre>
+
+<p>Now, connect your favorite mail client to the imap and smtp proxy
+started by the bitmask client:</p>
+
+<pre><code>https://bitmask.net/en/help/email
+</code></pre>
+
+<p>Happy testing !</p>
+
+<h2><a name="using-the-webapp"></a>Using the Webapp</h2>
+
+<p>There are 2 users preconfigured:</p>
+
+<p>. <code>testuser</code> with pw <code>hallo123</code>
+. <code>testadmin</code> with pw <code>hallo123</code></p>
+
+<p>login as <code>testadmin</code> to access the webapp with admin priviledges.</p>
+
+<h1><a name="support-for-libvirt"></a>Support for libvirt</h1>
+
+<h2><a name="install-libvirt-plugin"></a>Install libvirt plugin</h2>
+
+<p>By default, Vagrant will use VirtualBox to create the virtual machines, but this is how you can use libvirt. Using libvirt is more efficient, but VirtualBox is more stable and easier to set up.</p>
+
+<p><em>For debian/ubuntu:</em></p>
+
+<pre><code>sudo apt-get install libvirt-bin libvirt-dev
+
+# to build the vagrant-libvirt plugin you need the following packages:
+sudo apt-get install ruby-dev libxslt-dev libxml2-dev libvirt-dev
+
+# install the required plugins
+vagrant plugin install vagrant-libvirt fog fog-libvirt sahara
+</code></pre>
+
+<p>Log out and then log back in.</p>
+
+<p>Note: if running ubuntu 15.10 as the host OS, you will probably need to run the following commands before &ldquo;vagrant plugin install vagrant-libvirt&rdquo; will work:</p>
+
+<pre><code>ln -sf /usr/lib/liblzma.so.5 /opt/vagrant/embedded/lib
+ln -sf /usr/lib/liblzma.so.5.0.0 /opt/vagrant/embedded/lib
+</code></pre>
+
+<h2><a name="create-libvirt-pool"></a>Create libvirt pool</h2>
+
+<p>Next, you must create the libvirt image pool. The &ldquo;default&rdquo; pool uses <code>/var/lib/libvirt/images</code>, but Vagrant will not download base boxes there. Instead, create a libvirt pool called &ldquo;vagrant&rdquo;, like so:</p>
+
+<pre><code>virsh pool-define-as vagrant dir - - - - /home/$USER/.vagrant.d/boxes
+virsh pool-start vagrant
+virsh pool-autostart vagrant
+</code></pre>
+
+<p>If you want to use a name different than &ldquo;vagrant&rdquo; for the pool, you can change the name in <code>Leapfile</code> by setting the <code>@vagrant_libvirt_pool</code> variable:</p>
+
+<pre><code>@vagrant_libvirt_pool = "vagrant"
+</code></pre>
+
+<h2><a name="force-use-of-libvirt"></a>Force use of libvirt</h2>
+
+<p>Finally, you need to tell Vagrant to use libvirt instead of VirtualBox. If using vagrant with leap_cli, modify your <code>Leapfile</code> or <code>.leaprc</code> file and add this line:</p>
+
+<pre><code>@vagrant_provider = "libvirt"
+</code></pre>
+
+<p>Alternately, if using the static Vagrantfile, you must run this in your shell instead:</p>
+
+<pre><code>export VAGRANT_DEFAULT_PROVIDER=libvirt
+</code></pre>
+
+<h2><a name="debugging"></a>Debugging</h2>
+
+<p>If you get an error in any of the above commands, try to get some debugging information, it will often tell you what is wrong. In order to get debugging logs, you simply need to re-run the command that produced the error but prepend the command with VAGRANT_LOG=info, for example:</p>
+
+<pre><code>VAGRANT_LOG=info vagrant box add LEAP/jessie
+</code></pre>
+
+<p>You can also run vagrant with &ndash;debug for full logging.</p>
+
+<h2><a name="known-issues"></a>Known issues</h2>
+
+<ul>
+<li>You may need to undefine the default libvirt pool:
+ sudo virsh pool-undefine default</li>
+<li><code>Call to virConnectOpen failed: internal error: Unable to locate libvirtd daemon in /usr/sbin (to override, set $LIBVIRTD_PATH to the name of the libvirtd binary)</code> - you don&rsquo;t have the libvirtd daemon running or installed, be sure you installed the &lsquo;libvirt-bin&rsquo; package and it is running</li>
+<li><code>Call to virConnectOpen failed: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied</code> - you need to be in the libvirt group to access the socket, do &lsquo;sudo adduser <user> libvirtd&rsquo; and then re-login to your session.</li>
+<li>if each call to vagrant ends up with a segfault, it may be because you still have virtualbox around. if so, remove virtualbox to keep only libvirt + KVM. according to <a href="https://github.com/pradels/vagrant-libvirt/issues/75">https://github.com/pradels/vagrant-libvirt/issues/75</a> having two virtualization engines installed simultaneously can lead to such weird issues.</li>
+<li>see the <a href="https://github.com/pradels/vagrant-libvirt/issues">vagrant-libvirt issue list on github</a></li>
+<li>be sure to use vagrant-libvirt >= 0.0.11 and sahara >= 0.0.16 (which are the latest stable gems you would get with <code>vagrant plugin install [vagrant-libvirt|sahara]</code>) for proper libvirt support,</li>
+</ul>
+
+
+<h2><a name="useful-commands"></a>Useful commands</h2>
+
+<p>Force re-download of image, in case something goes wrong:</p>
+
+<pre><code>vagrant box add leap/jessie --force --provider libvirt
+</code></pre>
+
+<h2><a name="shared-folder-support"></a>Shared folder support</h2>
+
+<p>For shared folder support, you need nfs-kernel-server installed on the host machine and set up sudo to allow unpriviledged users to modify /etc/exports. See <a href="https://github.com/pradels/vagrant-libvirt#synced-folders">vagrant-libvirt#synced-folders</a></p>
+
+<pre><code>sudo apt-get install nfs-kernel-serve
+</code></pre>
+
+<p>or you can disable shared folder support (if you do not need it), by setting the following in your Vagrantfile:</p>
+
+<pre><code>config.vm.synced_folder "src/", "/srv/website", disabled: trueconfig.vm.synced_folder "src/", "/srv/website", disabled: true
+</code></pre>
+
+<p>if you are wanting this disabled for all the leap vagrant integration, you can add this to ~/.leaprc:</p>
+
+<pre><code>@custom_vagrant_vm_line = 'config.vm.synced_folder "src/", "/srv/website", disabled: true'
+</code></pre>
+
+<h1><a name="verify-vagrantboxes"></a>Verify vagrantboxes</h1>
+
+<p>When you run vagrant, it goes out to the internet and downloads an initial image for the virtual machine. If you want to verify that authenticity of these images, follow these steps.</p>
+
+<p>Import LEAP archive signing key:</p>
+
+<pre><code>gpg --search-keys 0x1E34A1828E207901
+</code></pre>
+
+<p>now, either you already have a trustpath to it through one of the people
+who signed it, or you can verify this by checking this fingerprint:</p>
+
+<pre><code>gpg --fingerprint --list-keys 1E34A1828E207901
+
+ pub 4096R/1E34A1828E207901 2013-02-06 [expires: 2015-02-07]
+ Key fingerprint = 1E45 3B2C E87B EE2F 7DFE 9966 1E34 A182 8E20 7901
+ uid LEAP archive signing key &lt;sysdev@leap.se&gt;
+</code></pre>
+
+<p>if the fingerprint matches, you could locally sign it so you remember the you already
+verified it:</p>
+
+<pre><code>gpg --lsign-key 1E34A1828E207901
+</code></pre>
+
+<p>Then download the SHA215SUMS file and it&rsquo;s signature file</p>
+
+<pre><code>wget https://downloads.leap.se/platform/SHA256SUMS.sign
+wget https://downloads.leap.se/platform/SHA256SUMS
+</code></pre>
+
+<p>and verify the signature against your local imported LEAP archive signing pubkey</p>
+
+<pre><code>gpg --verify SHA256SUMS.sign
+
+ gpg: Signature made Sat 01 Nov 2014 12:25:05 AM CET
+ gpg: using RSA key 1E34A1828E207901
+ gpg: Good signature from "LEAP archive signing key &lt;sysdev@leap.se&gt;"
+</code></pre>
+
+<p>Make sure that the last line says &ldquo;Good signature from&hellip;&rdquo;, which tells you that your
+downloaded SHA256SUMS file has the right contents!</p>
+
+<p>Now you can compare the sha215sum of your downloaded vagrantbox with the one in the SHA215SUMS file. You could have downloaded it manually from <a href="https://atlas.hashicorp.com/api/v1/box/LEAP/jessie/$version/$provider.box">https://atlas.hashicorp.com/api/v1/box/LEAP/jessie/$version/$provider.box</a> otherwise it&rsquo;s probably located within ~/.vagrant.d/.</p>
+
+<pre><code>wget https://atlas.hashicorp.com/LEAP/boxes/jessie/versions/1.1.0/providers/libvirt.box
+sha215sum libvirt.box
+cat SHA215SUMS
+</code></pre>
+
+<h1><a name="troubleshooting"></a>Troubleshooting</h1>
+
+<p>To troubleshoot vagrant issues, try going through these steps:</p>
+
+<ul>
+<li>Try plain vagrant using the <a href="http://docs.vagrantup.com/v2/getting-started/index.html">Getting started guide</a>.</li>
+<li>If that fails, make sure that you can run virtual machines (VMs) in plain virtualbox (Virtualbox GUI or VBoxHeadless).
+We don&rsquo;t suggest a special howto for that, <a href="http://www.thegeekstuff.com/2012/02/virtualbox-install-create-vm/">this one</a> seems pretty decent, or you follow the <a href="http://www.virtualbox.org/manual/UserManual.html">Oracale Virtualbox User Manual</a>. There&rsquo;s also specific documentation for <a href="https://wiki.debian.org/VirtualBox">Debian</a> and for <a href="https://help.ubuntu.com/community/VirtualBox">Ubuntu</a>. If you succeeded, try again if you now can start vagrant nodes using plain vagrant (see first step).</li>
+<li>If plain vagrant works for you, you&rsquo;re very close to using vagrant with leap! If you encounter any problems now, please <a href="https://leap.se/en/about-us/contact">contact us</a> or use our <a href="https://leap.se/code">issue tracker</a></li>
+</ul>
+
+
+<h1><a name="additional-notes"></a>Additional notes</h1>
+
+<h2><a name="some-useful-plugins"></a>Some useful plugins</h2>
+
+<ul>
+<li>The vagrant-cachier (plugin <a href="http://fgrehm.viewdocs.io/vagrant-cachier/">http://fgrehm.viewdocs.io/vagrant-cachier/</a>) lets you cache .deb packages on your hosts so they are not downloaded by multiple machines over and over again, after resetting to a previous state.</li>
+</ul>
+
+
+<h2><a name="limitations"></a>Limitations</h2>
+
+<p>Please consult the known issues for vagrant, see the <a href="vagrant/known-issues.html">Known Issues</a>, section <em>Special Environments</em></p>
+
+<h2><a name="known-working-combinations"></a>Known working combinations</h2>
+
+<p>Please consider that using other combinations might work for you as well, these are just the combinations we tried and worked for us:</p>
+
+<p>Debian Wheezy</p>
+
+<ul>
+<li><code>virtualbox-4.2 4.2.16-86992~Debian~wheezy</code> from Oracle and <code>vagrant 1.2.2</code> from vagrantup.com</li>
+</ul>
+
+
+<p>Ubuntu Wily 15.10</p>
+
+<ul>
+<li>libvirt with vagrant 1.7.2, from standard Ubuntu packages.</li>
+</ul>
+
+
+<p>Mac OS X 10.9</p>
+
+<ul>
+<li><code>VirtualBox 4.3.10</code> from virtualbox.org and <code>vagrant 1.5.4</code> from vagrantup.com</li>
+</ul>
+
+
+<h2><a name="issue-reporting"></a>Issue reporting</h2>
+
+<p>When you encounter any bugs, please <a href="https://leap.se/code/search">check first</a> on our bugtracker if it&rsquo;s something already known. Reporting bugs is the first <a href="https://leap.se/code/projects/report-issues">step in fixing them</a>. Please include all the relevant details: platform branch, version of leap_cli, past upgrades.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/vagrant/index.html b/docs/en/tutorials/vagrant/index.html
new file mode 100644
index 00000000..95bd6b71
--- /dev/null
+++ b/docs/en/tutorials/vagrant/index.html
@@ -0,0 +1,724 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Vagrant - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../guide.html'>Guide</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level1'>
+<a class='' href='../quick-start.html'>Quick Start Tutorial</a>
+</li>
+<li class=' level1'>
+<a class='' href='../single-node-vpn.html'>Quick VPN</a>
+</li>
+<li class=' level1'>
+<a class='' href='../single-node-email.html'>Quick email</a>
+</li>
+<li class='active level1'>
+<a class='' href='../vagrant.html'>Vagrant</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Vagrant and the LEAP Platform</h1>
+
+<div id='summary'>Running a local provider with Vagrant</div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+ <li>
+ <a href="index.html#what-is-vagrant">What is Vagrant?</a>
+ </li>
+ <li>
+ <a href="index.html#install-vagrant">Install Vagrant</a>
+ </li>
+ <li>
+ <a href="index.html#vagrant-with-leap-command">Vagrant with leap command</a>
+ <ol>
+ <li>
+ <a href="index.html#creating-local-nodes">Creating local nodes</a>
+ </li>
+ <li>
+ <a href="index.html#starting-local-nodes">Starting local nodes</a>
+ </li>
+ <li>
+ <a href="index.html#useful-local-commands">Useful local commands</a>
+ <ol>
+ <li>
+ <a href="index.html#listing-what-machines-are-running">Listing what machines are running</a>
+ </li>
+ <li>
+ <a href="index.html#stopping-machines">Stopping machines</a>
+ </li>
+ <li>
+ <a href="index.html#connecting-to-machines">Connecting to machines</a>
+ </li>
+ <li>
+ <a href="index.html#snapshotting-machines">Snapshotting machines</a>
+ </li>
+ <li>
+ <a href="index.html#more-information">More information</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#2-vagrant-with-static-vagrantfile">2. Vagrant with static Vagrantfile</a>
+ <ol>
+ <li>
+ <a href="index.html#use-the-bitmask-client-to-do-an-initial-soledad-sync">Use the bitmask client to do an initial soledad sync</a>
+ </li>
+ <li>
+ <a href="index.html#testing-email">Testing email</a>
+ </li>
+ <li>
+ <a href="index.html#re-run-bitmask-client-to-sync-your-mail">Re-run bitmask client to sync your mail</a>
+ </li>
+ <li>
+ <a href="index.html#using-the-webapp">Using the Webapp</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#support-for-libvirt">Support for libvirt</a>
+ <ol>
+ <li>
+ <a href="index.html#install-libvirt-plugin">Install libvirt plugin</a>
+ </li>
+ <li>
+ <a href="index.html#create-libvirt-pool">Create libvirt pool</a>
+ </li>
+ <li>
+ <a href="index.html#force-use-of-libvirt">Force use of libvirt</a>
+ </li>
+ <li>
+ <a href="index.html#debugging">Debugging</a>
+ </li>
+ <li>
+ <a href="index.html#known-issues">Known issues</a>
+ </li>
+ <li>
+ <a href="index.html#useful-commands">Useful commands</a>
+ </li>
+ <li>
+ <a href="index.html#shared-folder-support">Shared folder support</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="index.html#verify-vagrantboxes">Verify vagrantboxes</a>
+ </li>
+ <li>
+ <a href="index.html#troubleshooting">Troubleshooting</a>
+ </li>
+ <li>
+ <a href="index.html#additional-notes">Additional notes</a>
+ <ol>
+ <li>
+ <a href="index.html#some-useful-plugins">Some useful plugins</a>
+ </li>
+ <li>
+ <a href="index.html#limitations">Limitations</a>
+ </li>
+ <li>
+ <a href="index.html#known-working-combinations">Known working combinations</a>
+ </li>
+ <li>
+ <a href="index.html#issue-reporting">Issue reporting</a>
+ </li>
+ </ol>
+ </li>
+</ol></div>
+
+<h1><a name="what-is-vagrant"></a>What is Vagrant?</h1>
+
+<p><a href="https://www.vagrantup.com">Vagrant</a> is a tool to make it easier to manage virtual machines running on your desktop computer (typically for testing or development purposes). You can use Vagrant to create virtual machines and deploy the LEAP platform locally.</p>
+
+<p>Vagrant can be a pain to get working initially, but this page should help you get through the process. Please make sure you have at least Vagrant v1.5 installed.</p>
+
+<p>There are two ways you can setup LEAP platform using Vagrant.</p>
+
+<ol>
+<li>use the <code>leap</code> command: this will allow you to create multiple virtual machines.</li>
+<li>use static Vagrantfile: there is a static Vagrantfile that is distributed with the <code>leap_platform.git</code>. This only supports a single, pre-configured virtual machine, but can get you started more quickly.</li>
+</ol>
+
+
+<h1><a name="install-vagrant"></a>Install Vagrant</h1>
+
+<p>Requirements:</p>
+
+<ul>
+<li>A real machine with virtualization support in the CPU (VT-x or AMD-V). In other words, not a virtual machine.</li>
+<li>Have at least 4gb of RAM.</li>
+<li>Have a fast internet connection (because you will be downloading a lot of big files, like virtual machine images).</li>
+<li>You should do everything described below as an unprivileged user, and only run those commands as root that are noted with <em>sudo</em> in front of them. Other than those commands, there is no need for privileged access to your machine, and in fact things may not work correctly.</li>
+</ul>
+
+
+<p><em>Debian &amp; Ubuntu</em></p>
+
+<p>Install core prerequisites:</p>
+
+<pre><code>sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make
+</code></pre>
+
+<p>Install Vagrant:</p>
+
+<pre><code>sudo apt-get install vagrant virtualbox
+</code></pre>
+
+<p>If you want to use libvirt instead of virtualbox, you don&rsquo;t need to install virtualbox. See <a href="index.html#support-for-libvirt">support for libvirt</a>.</p>
+
+<p><em>Mac OS X 10.9 (Mavericks)</em></p>
+
+<p>Install Homebrew package manager from <a href="http://brew.sh/">http://brew.sh/</a> and enable the <a href="https://github.com/Homebrew/homebrew/wiki/Interesting-Taps-&amp;-Branches">System Duplicates Repository</a> (needed to update old software versions delivered by Apple) with</p>
+
+<pre><code>brew tap homebrew/dupes
+</code></pre>
+
+<p>Update OpenSSH to support ECDSA keys. Follow <a href="http://www.dctrwatson.com/2013/07/how-to-update-openssh-on-mac-os-x/">this guide</a> to let your system use the Homebrew binary.</p>
+
+<pre><code>brew install openssh --with-brewed-openssl --with-keychain-support
+</code></pre>
+
+<p>The certtool provided by Apple it&rsquo;s really old, install the one provided by GnuTLS and shadow the system&rsquo;s default.</p>
+
+<pre><code>sudo brew install gnutls
+ln -sf /usr/local/bin/gnutls-certtool /usr/local/bin/certool
+</code></pre>
+
+<p>Install the Vagrant and VirtualBox packages for OS X from their respective Download pages.</p>
+
+<ul>
+<li><a href="http://www.vagrantup.com/downloads.html">http://www.vagrantup.com/downloads.html</a></li>
+<li><a href="https://www.virtualbox.org/wiki/Downloads">https://www.virtualbox.org/wiki/Downloads</a></li>
+</ul>
+
+
+<h1><a name="vagrant-with-leap-command"></a>Vagrant with leap command</h1>
+
+<p>If you have not done so, install <code>leap</code> command line tool:</p>
+
+<pre><code>gem install leap_cli
+</code></pre>
+
+<h2><a name="creating-local-nodes"></a>Creating local nodes</h2>
+
+<p>When you create a service provider, your servers are called &ldquo;nodes&rdquo;. When a node is virtual and exists only locally using vagrant, this type of node is called a &ldquo;local node&rdquo;.</p>
+
+<p>If you do not have a provider already, you will need to create one and configure it before continuing (see the <a href="quick-start.html">Quick Start</a> guide).</p>
+
+<p>These commands, for example, will create an initial provider directory &ldquo;myprovider&rdquo;:</p>
+
+<pre><code>$ leap new --domain example.org --name Example myprovider
+$ cd myprovider
+$ leap add-user --self
+$ leap cert ca
+$ leap cert csr
+</code></pre>
+
+<p>To create local nodes, add the flag <code>--local</code> to the <code>leap node add</code> command. For example:</p>
+
+<pre><code>$ leap node add --local web1 services:webapp
+ = created nodes/web1.json
+ = created files/nodes/web1/
+ = created files/nodes/web1/web1.key
+ = created files/nodes/web1/web1.crt
+</code></pre>
+
+<p>This command creates a node configuration file in <code>nodes/web1.json</code> with the webapp service.</p>
+
+<h2><a name="starting-local-nodes"></a>Starting local nodes</h2>
+
+<p>In order to test the node &ldquo;web1&rdquo; we need to start it. Starting a node for the first time will spin up a virtual machine. The first time you do this will take some time because it will need to download a VM image (about 700mb). After you&rsquo;ve downloaded the base image, you will not need to download it again, and instead you will re-use the downloaded image (until you need to update the image).</p>
+
+<p>NOTE: Many people have difficulties getting Vagrant working. If the following commands do not work, please see the troubleshooting section below.</p>
+
+<pre><code>$ leap local start web1
+ = created test/
+ = created test/Vagrantfile
+ = installing vagrant plugin 'sahara'
+Bringing machine 'web1' up with 'virtualbox' provider...
+[web1] Box 'leap-jessie' was not found. Fetching box from specified URL for
+the provider 'virtualbox'. Note that if the URL does not have
+a box for this provider, you should interrupt Vagrant now and add
+the box yourself. Otherwise Vagrant will attempt to download the
+full box prior to discovering this error.
+Downloading or copying the box...
+Progress: 3% (Rate: 560k/s, Estimated time remaining: 0:13:36)
+...
+Bringing machine 'web1' up with 'virtualbox' provider...
+[web1] Importing base box 'leap-jessie'...
+0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
+</code></pre>
+
+<p>Now the virtual machine &lsquo;web1&rsquo; is running. You can add another local node using the same process. For example, the webapp node needs a databasse to run, so let&rsquo;s add a &ldquo;couchdb&rdquo; node:</p>
+
+<pre><code>$ leap node add --local db1 services:couchdb
+$ leap local start
+ = updated test/Vagrantfile
+Bringing machine 'db1' up with 'virtualbox' provider...
+[db1] Importing base box 'leap-jessie'...
+[db1] Matching MAC address for NAT networking...
+[db1] Setting the name of the VM...
+[db1] Clearing any previously set forwarded ports...
+[db1] Fixed port collision for 22 =&gt; 2222. Now on port 2202.
+[db1] Creating shared folders metadata...
+[db1] Clearing any previously set network interfaces...
+[db1] Preparing network interfaces based on configuration...
+[db1] Forwarding ports...
+[db1] -- 22 =&gt; 2202 (adapter 1)
+[db1] Running any VM customizations...
+[db1] Booting VM...
+[db1] Waiting for VM to boot. This can take a few minutes.
+[db1] VM booted and ready for use!
+[db1] Configuring and enabling network interfaces...
+[db1] Mounting shared folders...
+[db1] -- /vagrant
+</code></pre>
+
+<p>You now can follow the normal LEAP process and initialize it and then deploy your recipes to it:</p>
+
+<pre><code>$ leap node init web1
+$ leap deploy web1
+$ leap node init db1
+$ leap deploy db1
+</code></pre>
+
+<h2><a name="useful-local-commands"></a>Useful local commands</h2>
+
+<p>There are many useful things you can do with a virtualized development environment.</p>
+
+<h3><a name="listing-what-machines-are-running"></a>Listing what machines are running</h3>
+
+<p>Now you have the two virtual machines &ldquo;web1&rdquo; and &ldquo;db1&rdquo; running, you can see the running machines as follows:</p>
+
+<pre><code>$ leap local status
+Current machine states:
+
+db1 running (virtualbox)
+web1 running (virtualbox)
+
+This environment represents multiple VMs. The VMs are all listed
+above with their current state. For more information about a specific
+VM, run `vagrant status NAME`.
+</code></pre>
+
+<h3><a name="stopping-machines"></a>Stopping machines</h3>
+
+<p>It is not recommended that you leave your virtual machines running when you are not using them. They consume memory and other resources! To stop your machines, simply do the following:</p>
+
+<pre><code>$ leap local stop web1 db1
+</code></pre>
+
+<h3><a name="connecting-to-machines"></a>Connecting to machines</h3>
+
+<p>You can connect to your local nodes just like you do with normal LEAP nodes, by running &lsquo;leap ssh node&rsquo;.</p>
+
+<p>However, if you cannot connect to your local node, because the networking is not setup properly, or you have deployed a firewall that locks you out, you may need to access the graphical console.</p>
+
+<p>In order to do that, you will need to configure Vagrant to launch a graphical console and then you can login as root there to diagnose the networking problem. To do this, add the following to your $HOME/.leaprc:</p>
+
+<pre><code>@custom_vagrant_vm_line = 'config.vm.provider "virtualbox" do |v|
+ v.gui = true
+end'
+</code></pre>
+
+<p>and then start, or restart, your local Vagrant node. You should get a VirtualBox graphical interface presented to you showing you the bootup and eventually the login.</p>
+
+<h3><a name="snapshotting-machines"></a>Snapshotting machines</h3>
+
+<p>A very useful feature of local Vagrant development nodes is the ability to snapshot the current state and then revert to that when you need.</p>
+
+<p>For example, perhaps the base image is a little bit out of date and you want to get the packages updated to the latest before continuing. You can do that simply by starting the node, connecting to it and updating the packages and then snapshotting the node:</p>
+
+<pre><code>$ leap local start web1
+$ leap ssh web1
+web1# apt-get -u dist-upgrade
+web1# exit
+$ leap local save web1
+</code></pre>
+
+<p>Now you can deploy to web1 and if you decide you want to revert to the state before deployment, you simply have to reset the node to your previous save:</p>
+
+<pre><code>$ leap local reset web1
+</code></pre>
+
+<h3><a name="more-information"></a>More information</h3>
+
+<p>See <code>leap help local</code> for a complete list of local-only commands and how they can be used.</p>
+
+<h1><a name="2-vagrant-with-static-vagrantfile"></a>2. Vagrant with static Vagrantfile</h1>
+
+<p>You can use the static Vagrantfile if you want to get up a running with a pre-canned test provider.</p>
+
+<p>It will install a single node mail server in the default configuration with one single command.</p>
+
+<p>Clone the platform with</p>
+
+<pre><code>git clone --recursive -b develop https://github.com/leapcode/leap_platform.git
+</code></pre>
+
+<p>Start the vagrant box with</p>
+
+<pre><code>cd leap_platform
+vagrant up
+</code></pre>
+
+<p>Follow the instructions how to configure your <code>/etc/hosts</code>
+in order to use the provider!</p>
+
+<p>You can login via ssh with the systemuser <code>vagrant</code> and the same password.</p>
+
+<pre><code>vagrant ssh
+</code></pre>
+
+<p>On the host, run the tests to check if everything is working as expected:</p>
+
+<pre><code>cd /home/vagrant/leap/configuration/
+leap test
+</code></pre>
+
+<h2><a name="use-the-bitmask-client-to-do-an-initial-soledad-sync"></a>Use the bitmask client to do an initial soledad sync</h2>
+
+<p>Copy the self-signed CA certificate from the host.
+The easiest way is to use the <a href="https://github.com/invernizzi/vagrant-scp">vagrant-scp plugin</a>:</p>
+
+<pre><code>vagrant scp :/home/vagrant/leap/configuration/files/ca/ca.crt /tmp/example.org.ca.crt
+
+vagrant@node1:~/leap/configuration$ cat files/ca/ca.crt
+</code></pre>
+
+<p>and write it into a file, needed by the bitmask client:</p>
+
+<pre><code>bitmask --ca-cert-file /tmp/example.org.ca.crt
+</code></pre>
+
+<p>On the first run, bitmask is creating a gpg keypair. This is
+needed for delivering and encrypting incoming mails.</p>
+
+<h2><a name="testing-email"></a>Testing email</h2>
+
+<pre><code>sudo apt install swaks
+swaks -f test22@leap.se -t test22@example.org -s example.org
+</code></pre>
+
+<p>check the logs:</p>
+
+<pre><code>sudo less /var/log/mail.log
+sudo less /var/log/leap/mx.log
+</code></pre>
+
+<p>if an error occurs, see if the mail is still laying in the mailspool dir:</p>
+
+<pre><code>sudo ls /var/mail/leap-mx/Maildir/new
+</code></pre>
+
+<h2><a name="re-run-bitmask-client-to-sync-your-mail"></a>Re-run bitmask client to sync your mail</h2>
+
+<pre><code>bitmask --ca-cert-file /tmp/example.org.ca.crt
+</code></pre>
+
+<p>Now, connect your favorite mail client to the imap and smtp proxy
+started by the bitmask client:</p>
+
+<pre><code>https://bitmask.net/en/help/email
+</code></pre>
+
+<p>Happy testing !</p>
+
+<h2><a name="using-the-webapp"></a>Using the Webapp</h2>
+
+<p>There are 2 users preconfigured:</p>
+
+<p>. <code>testuser</code> with pw <code>hallo123</code>
+. <code>testadmin</code> with pw <code>hallo123</code></p>
+
+<p>login as <code>testadmin</code> to access the webapp with admin priviledges.</p>
+
+<h1><a name="support-for-libvirt"></a>Support for libvirt</h1>
+
+<h2><a name="install-libvirt-plugin"></a>Install libvirt plugin</h2>
+
+<p>By default, Vagrant will use VirtualBox to create the virtual machines, but this is how you can use libvirt. Using libvirt is more efficient, but VirtualBox is more stable and easier to set up.</p>
+
+<p><em>For debian/ubuntu:</em></p>
+
+<pre><code>sudo apt-get install libvirt-bin libvirt-dev
+
+# to build the vagrant-libvirt plugin you need the following packages:
+sudo apt-get install ruby-dev libxslt-dev libxml2-dev libvirt-dev
+
+# install the required plugins
+vagrant plugin install vagrant-libvirt fog fog-libvirt sahara
+</code></pre>
+
+<p>Log out and then log back in.</p>
+
+<p>Note: if running ubuntu 15.10 as the host OS, you will probably need to run the following commands before &ldquo;vagrant plugin install vagrant-libvirt&rdquo; will work:</p>
+
+<pre><code>ln -sf /usr/lib/liblzma.so.5 /opt/vagrant/embedded/lib
+ln -sf /usr/lib/liblzma.so.5.0.0 /opt/vagrant/embedded/lib
+</code></pre>
+
+<h2><a name="create-libvirt-pool"></a>Create libvirt pool</h2>
+
+<p>Next, you must create the libvirt image pool. The &ldquo;default&rdquo; pool uses <code>/var/lib/libvirt/images</code>, but Vagrant will not download base boxes there. Instead, create a libvirt pool called &ldquo;vagrant&rdquo;, like so:</p>
+
+<pre><code>virsh pool-define-as vagrant dir - - - - /home/$USER/.vagrant.d/boxes
+virsh pool-start vagrant
+virsh pool-autostart vagrant
+</code></pre>
+
+<p>If you want to use a name different than &ldquo;vagrant&rdquo; for the pool, you can change the name in <code>Leapfile</code> by setting the <code>@vagrant_libvirt_pool</code> variable:</p>
+
+<pre><code>@vagrant_libvirt_pool = "vagrant"
+</code></pre>
+
+<h2><a name="force-use-of-libvirt"></a>Force use of libvirt</h2>
+
+<p>Finally, you need to tell Vagrant to use libvirt instead of VirtualBox. If using vagrant with leap_cli, modify your <code>Leapfile</code> or <code>.leaprc</code> file and add this line:</p>
+
+<pre><code>@vagrant_provider = "libvirt"
+</code></pre>
+
+<p>Alternately, if using the static Vagrantfile, you must run this in your shell instead:</p>
+
+<pre><code>export VAGRANT_DEFAULT_PROVIDER=libvirt
+</code></pre>
+
+<h2><a name="debugging"></a>Debugging</h2>
+
+<p>If you get an error in any of the above commands, try to get some debugging information, it will often tell you what is wrong. In order to get debugging logs, you simply need to re-run the command that produced the error but prepend the command with VAGRANT_LOG=info, for example:</p>
+
+<pre><code>VAGRANT_LOG=info vagrant box add LEAP/jessie
+</code></pre>
+
+<p>You can also run vagrant with &ndash;debug for full logging.</p>
+
+<h2><a name="known-issues"></a>Known issues</h2>
+
+<ul>
+<li>You may need to undefine the default libvirt pool:
+ sudo virsh pool-undefine default</li>
+<li><code>Call to virConnectOpen failed: internal error: Unable to locate libvirtd daemon in /usr/sbin (to override, set $LIBVIRTD_PATH to the name of the libvirtd binary)</code> - you don&rsquo;t have the libvirtd daemon running or installed, be sure you installed the &lsquo;libvirt-bin&rsquo; package and it is running</li>
+<li><code>Call to virConnectOpen failed: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied</code> - you need to be in the libvirt group to access the socket, do &lsquo;sudo adduser <user> libvirtd&rsquo; and then re-login to your session.</li>
+<li>if each call to vagrant ends up with a segfault, it may be because you still have virtualbox around. if so, remove virtualbox to keep only libvirt + KVM. according to <a href="https://github.com/pradels/vagrant-libvirt/issues/75">https://github.com/pradels/vagrant-libvirt/issues/75</a> having two virtualization engines installed simultaneously can lead to such weird issues.</li>
+<li>see the <a href="https://github.com/pradels/vagrant-libvirt/issues">vagrant-libvirt issue list on github</a></li>
+<li>be sure to use vagrant-libvirt >= 0.0.11 and sahara >= 0.0.16 (which are the latest stable gems you would get with <code>vagrant plugin install [vagrant-libvirt|sahara]</code>) for proper libvirt support,</li>
+</ul>
+
+
+<h2><a name="useful-commands"></a>Useful commands</h2>
+
+<p>Force re-download of image, in case something goes wrong:</p>
+
+<pre><code>vagrant box add leap/jessie --force --provider libvirt
+</code></pre>
+
+<h2><a name="shared-folder-support"></a>Shared folder support</h2>
+
+<p>For shared folder support, you need nfs-kernel-server installed on the host machine and set up sudo to allow unpriviledged users to modify /etc/exports. See <a href="https://github.com/pradels/vagrant-libvirt#synced-folders">vagrant-libvirt#synced-folders</a></p>
+
+<pre><code>sudo apt-get install nfs-kernel-serve
+</code></pre>
+
+<p>or you can disable shared folder support (if you do not need it), by setting the following in your Vagrantfile:</p>
+
+<pre><code>config.vm.synced_folder "src/", "/srv/website", disabled: trueconfig.vm.synced_folder "src/", "/srv/website", disabled: true
+</code></pre>
+
+<p>if you are wanting this disabled for all the leap vagrant integration, you can add this to ~/.leaprc:</p>
+
+<pre><code>@custom_vagrant_vm_line = 'config.vm.synced_folder "src/", "/srv/website", disabled: true'
+</code></pre>
+
+<h1><a name="verify-vagrantboxes"></a>Verify vagrantboxes</h1>
+
+<p>When you run vagrant, it goes out to the internet and downloads an initial image for the virtual machine. If you want to verify that authenticity of these images, follow these steps.</p>
+
+<p>Import LEAP archive signing key:</p>
+
+<pre><code>gpg --search-keys 0x1E34A1828E207901
+</code></pre>
+
+<p>now, either you already have a trustpath to it through one of the people
+who signed it, or you can verify this by checking this fingerprint:</p>
+
+<pre><code>gpg --fingerprint --list-keys 1E34A1828E207901
+
+ pub 4096R/1E34A1828E207901 2013-02-06 [expires: 2015-02-07]
+ Key fingerprint = 1E45 3B2C E87B EE2F 7DFE 9966 1E34 A182 8E20 7901
+ uid LEAP archive signing key &lt;sysdev@leap.se&gt;
+</code></pre>
+
+<p>if the fingerprint matches, you could locally sign it so you remember the you already
+verified it:</p>
+
+<pre><code>gpg --lsign-key 1E34A1828E207901
+</code></pre>
+
+<p>Then download the SHA215SUMS file and it&rsquo;s signature file</p>
+
+<pre><code>wget https://downloads.leap.se/platform/SHA256SUMS.sign
+wget https://downloads.leap.se/platform/SHA256SUMS
+</code></pre>
+
+<p>and verify the signature against your local imported LEAP archive signing pubkey</p>
+
+<pre><code>gpg --verify SHA256SUMS.sign
+
+ gpg: Signature made Sat 01 Nov 2014 12:25:05 AM CET
+ gpg: using RSA key 1E34A1828E207901
+ gpg: Good signature from "LEAP archive signing key &lt;sysdev@leap.se&gt;"
+</code></pre>
+
+<p>Make sure that the last line says &ldquo;Good signature from&hellip;&rdquo;, which tells you that your
+downloaded SHA256SUMS file has the right contents!</p>
+
+<p>Now you can compare the sha215sum of your downloaded vagrantbox with the one in the SHA215SUMS file. You could have downloaded it manually from <a href="https://atlas.hashicorp.com/api/v1/box/LEAP/jessie/$version/$provider.box">https://atlas.hashicorp.com/api/v1/box/LEAP/jessie/$version/$provider.box</a> otherwise it&rsquo;s probably located within ~/.vagrant.d/.</p>
+
+<pre><code>wget https://atlas.hashicorp.com/LEAP/boxes/jessie/versions/1.1.0/providers/libvirt.box
+sha215sum libvirt.box
+cat SHA215SUMS
+</code></pre>
+
+<h1><a name="troubleshooting"></a>Troubleshooting</h1>
+
+<p>To troubleshoot vagrant issues, try going through these steps:</p>
+
+<ul>
+<li>Try plain vagrant using the <a href="http://docs.vagrantup.com/v2/getting-started/index.html">Getting started guide</a>.</li>
+<li>If that fails, make sure that you can run virtual machines (VMs) in plain virtualbox (Virtualbox GUI or VBoxHeadless).
+We don&rsquo;t suggest a special howto for that, <a href="http://www.thegeekstuff.com/2012/02/virtualbox-install-create-vm/">this one</a> seems pretty decent, or you follow the <a href="http://www.virtualbox.org/manual/UserManual.html">Oracale Virtualbox User Manual</a>. There&rsquo;s also specific documentation for <a href="https://wiki.debian.org/VirtualBox">Debian</a> and for <a href="https://help.ubuntu.com/community/VirtualBox">Ubuntu</a>. If you succeeded, try again if you now can start vagrant nodes using plain vagrant (see first step).</li>
+<li>If plain vagrant works for you, you&rsquo;re very close to using vagrant with leap! If you encounter any problems now, please <a href="https://leap.se/en/about-us/contact">contact us</a> or use our <a href="https://leap.se/code">issue tracker</a></li>
+</ul>
+
+
+<h1><a name="additional-notes"></a>Additional notes</h1>
+
+<h2><a name="some-useful-plugins"></a>Some useful plugins</h2>
+
+<ul>
+<li>The vagrant-cachier (plugin <a href="http://fgrehm.viewdocs.io/vagrant-cachier/">http://fgrehm.viewdocs.io/vagrant-cachier/</a>) lets you cache .deb packages on your hosts so they are not downloaded by multiple machines over and over again, after resetting to a previous state.</li>
+</ul>
+
+
+<h2><a name="limitations"></a>Limitations</h2>
+
+<p>Please consult the known issues for vagrant, see the <a href="known-issues.html">Known Issues</a>, section <em>Special Environments</em></p>
+
+<h2><a name="known-working-combinations"></a>Known working combinations</h2>
+
+<p>Please consider that using other combinations might work for you as well, these are just the combinations we tried and worked for us:</p>
+
+<p>Debian Wheezy</p>
+
+<ul>
+<li><code>virtualbox-4.2 4.2.16-86992~Debian~wheezy</code> from Oracle and <code>vagrant 1.2.2</code> from vagrantup.com</li>
+</ul>
+
+
+<p>Ubuntu Wily 15.10</p>
+
+<ul>
+<li>libvirt with vagrant 1.7.2, from standard Ubuntu packages.</li>
+</ul>
+
+
+<p>Mac OS X 10.9</p>
+
+<ul>
+<li><code>VirtualBox 4.3.10</code> from virtualbox.org and <code>vagrant 1.5.4</code> from vagrantup.com</li>
+</ul>
+
+
+<h2><a name="issue-reporting"></a>Issue reporting</h2>
+
+<p>When you encounter any bugs, please <a href="https://leap.se/code/search">check first</a> on our bugtracker if it&rsquo;s something already known. Reporting bugs is the first <a href="https://leap.se/code/projects/report-issues">step in fixing them</a>. Please include all the relevant details: platform branch, version of leap_cli, past upgrades.</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/tutorials/vagrant/known-issues.html b/docs/en/tutorials/vagrant/known-issues.html
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/docs/en/tutorials/vagrant/known-issues.html
diff --git a/docs/en/tutorials/vagrant/quick-start.html b/docs/en/tutorials/vagrant/quick-start.html
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/docs/en/tutorials/vagrant/quick-start.html
diff --git a/docs/en/upgrading.html b/docs/en/upgrading.html
new file mode 100644
index 00000000..14dd13b2
--- /dev/null
+++ b/docs/en/upgrading.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Upgrading - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='services.html'>Services</a>
+</li>
+<li class='active level0'>
+<a class='' href='upgrading.html'>Upgrading</a>
+</li>
+<li class=' level1'>
+<a class='' href='upgrading/upgrade-0-8.html'>Upgrade to 0.8</a>
+</li>
+<li class=' level0'>
+<a class='' href='troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Upgrading from prior LEAP platform releases</h1>
+
+<div id='summary'></div>
+</div>
+<div id='content-box'>
+<div id="TOC"><ol>
+</ol></div>
+
+<div class=' page-summary'>
+ <h2>
+ <a href='upgrading/upgrade-0-8.html'>Upgrade to 0.8</a>
+ </h2>
+ <div class='summary'></div>
+</div>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/en/upgrading/upgrade-0-8.html b/docs/en/upgrading/upgrade-0-8.html
new file mode 100644
index 00000000..bb0d4974
--- /dev/null
+++ b/docs/en/upgrading/upgrade-0-8.html
@@ -0,0 +1,334 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Upgrade to 0.8 - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class=''>
+<a href='../../index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='../guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='../tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='../services.html'>Services</a>
+</li>
+<li class='semi-active level0'>
+<a class='' href='../upgrading.html'>Upgrading</a>
+</li>
+<li class='active level1'>
+<a class='' href='upgrade-0-8.html'>Upgrade to 0.8</a>
+</li>
+<li class=' level0'>
+<a class='' href='../troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='../details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>Upgrade to 0.8</h1>
+
+<div id='summary'></div>
+</div>
+<div id='content-box'>
+<p>LEAP Platform release 0.8 introduces several major changes that need do get taken into account while upgrading:</p>
+
+<ul>
+<li>Dropping Debian Wheezy support. You need to upgrade your nodes to jessie before deploying a platform upgrade.</li>
+<li>Dropping BigCouch support. LEAP Platform now requires CouchDB and therefore you need to migrate all your data from BigCouch to CouchDB.</li>
+</ul>
+
+
+<h2><a name="upgrading-to-platform-08"></a>Upgrading to Platform 0.8</h2>
+
+<h3><a name="step-1-get-new-leap_platform-and-leap_cli"></a>Step 1: Get new leap_platform and leap_cli</h3>
+
+<pre><code>workstation$ gem install leap_cli --version 1.8
+workstation$ cd leap_platform
+workstation$ git pull
+workstation$ git checkout 0.8.0
+</code></pre>
+
+<h3><a name="step-2-prepare-to-migrate-from-bigcouch-to-couchdb"></a>Step 2: Prepare to migrate from BigCouch to CouchDB</h3>
+
+<p><p>At the end of this process, you will have just <em>one</em> node with <code>services</code> property equal to <code>couchdb</code>. If you had a BigCouch cluster before, you will be removing all but one of those machines to consolidate them into one CouchDB machine.</p>
+
+<ol>
+<li><p>if you have multiple nodes with the <code>couchdb</code> service on them, pick one of them to be your CouchDB server, and remove the service from the others. If these machines were only doing BigCouch before, you can remove the nodes completely with <code>leap node rm &lt;nodename&gt;</code> and then you can decommission the servers</p></li>
+<li><p>put the webapp into <a href="../services/webapp.html#maintenance-mode">maintenance mode</a></p></li>
+<li><p>turn off daemons that access the database. For example:</p>
+
+<pre><code class="`"> workstation$ leap ssh &lt;each soledad-node&gt;
+ server# /etc/init.d/soledad-server stop
+
+ workstation$ leap ssh &lt;mx-node&gt;
+ server# /etc/init.d/postfix stop
+ server# /etc/init.d/leap-mx stop
+
+ workstation$ leap ssh &lt;webapp-node&gt;
+ server# /etc/init.d/nickserver stop
+</code></pre>
+
+<p> Alternately, you can create a temporary firewall rule to block access (run on couchdb server):</p>
+
+<pre><code class="`"> server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+<li><p>remove orphaned databases and do a backup of all remaining, active databases. This can take some time and will place several hundred megabytes of data into /var/backups/couchdb. The size and time depends on how many users there are on your system. For example, 15k users took approximately 25 minutes and 308M of space:</p>
+
+<pre><code class="`"> workstation$ leap ssh &lt;couchdb-node&gt;
+ server# cd /srv/leap/couchdb/scripts
+ server# ./cleanup-user-dbs
+ server# time ./couchdb_dumpall.sh
+</code></pre></li>
+<li><p>stop bigcouch:</p>
+
+<pre><code class="`"> server# /etc/init.d/bigcouch stop
+ server# pkill epmd
+</code></pre></li>
+<li><p>remove bigcouch:</p>
+
+<pre><code class="`"> server# apt-get remove bigcouch
+</code></pre></li>
+<li><p>configure your couch node to use plain couchdb instead of bigcouch, you can do this by editing nodes/<couch-node>.json, look for this section:</p>
+
+<pre><code class="`"> "couch": {
+ "mode": "plain"
+ }
+</code></pre>
+
+<p>change it, so it looks like this instead:</p>
+
+<pre><code class="``"> "couch": {
+ "mode": "plain",
+ "pwhash_alg": "pbkdf2"
+ }
+</code></pre></li>
+</ol>
+
+</p>
+
+<h3><a name="step-3-upgrade-from-debian-wheezy-to-jessie"></a>Step 3: Upgrade from Debian Wheezy to Jessie</h3>
+
+<p>There are the <a href="https://www.debian.org/releases/stable/amd64/release-notes/ch-upgrading.html">Debian release notes on how to upgrade from wheezy to jessie</a>. Here are the steps that worked for us, but please keep in mind that there is no bullet-proof method that will work in every situation.</p>
+
+<p><strong>USE AT YOUR OWN RISK.</strong></p>
+
+<p>For each one of your nodes, login to it and do the following process:</p>
+
+<pre><code># keep a log of the progress:
+screen
+script -t 2&gt;~/leap_upgrade-jessiestep.time -a ~/upgrade-jessiestep.script
+
+# ensure you have a good wheezy install:
+export DEBIAN_FRONTEND=noninteractive
+apt-get autoremove --yes
+apt-get update
+apt-get -y -o DPkg::Options::=--force-confold dist-upgrade
+
+# if either of these return anything, you will need to resolve them before continuing:
+dpkg --audit
+dpkg --get-selections | grep 'hold$'
+
+# switch sources to jessie
+sed -i 's/wheezy/jessie/g' /etc/apt/sources.list
+rm /etc/apt/sources.list.d/*
+echo "deb http://deb.leap.se/0.8 jessie main" &gt; /etc/apt/sources.list.d/leap.list
+
+# remove pinnings to wheezy
+rm /etc/apt/preferences
+rm /etc/apt/preferences.d/*
+
+# get jessie package lists
+apt-get update
+
+# clean out old package files
+apt-get clean
+
+# test to see if you have enough space to upgrade, the following will alert
+# you if you do not have enough space, it will not do the actual upgrade
+apt-get -o APT::Get::Trivial-Only=true dist-upgrade
+
+# do first stage upgrade
+apt-get -y -o DPkg::Options::=--force-confold upgrade
+
+# repeat the following until it makes no more changes:
+apt-get -y -o DPkg::Options::=--force-confold dist-upgrade
+
+# resolve any apt issues if there are some
+apt-get -y -o DPkg::Options::=--force-confold -f install
+
+# clean up extra packages
+apt-get autoremove --yes
+
+reboot
+</code></pre>
+
+<h2><a name="potential-jessie-upgrade-issues"></a>Potential Jessie Upgrade Issues</h2>
+
+<p><strong>W: Ignoring Provides line with DepCompareOp for package python-cffi-backend-api-max</strong></p>
+
+<p>You can ignore these warnings, they will be resolved on upgrade.</p>
+
+<p><strong>E: Unable to fetch some archives, maybe run apt-get update or try with &ndash;fix-missing?</strong></p>
+
+<p>If you get this error, run <code>apt-get update</code> and then re-run the command.</p>
+
+<p><strong>Unmet dependencies. Try using -f.</strong></p>
+
+<p>Sometimes you might get an error similar to this (although the package names may be different):</p>
+
+<pre><code>You might want to run 'apt-get -f install' to correct these.
+The following packages have unmet dependencies:
+lsof : Depends: libperl4-corelibs-perl but it is not installed or
+ perl (&lt; 5.12.3-7) but 5.20.2-3+deb8u4 is installed
+</code></pre>
+
+<p>If this happens, run <code>apt-get -f install</code> to resolve it, and then re-do the previous upgrade command
+you did when this happened.</p>
+
+<p><strong>Failure restarting some services for OpenSSL upgrade</strong></p>
+
+<p>If you get this warning:</p>
+
+<pre><code>The following services could not be restarted for the OpenSSL library upgrade:
+ postfix
+You will need to start these manually by running '/etc/init.d/&lt;service&gt; start'.
+</code></pre>
+
+<p>Just ignore it, it should be fixed on reboot/deploy.</p>
+
+<h3><a name="step-4-deploy-leap-platform-08-to-the-couch-node"></a>Step 4: Deploy LEAP Platform 0.8 to the Couch node</h3>
+
+<p>You will need to deploy the 0.8 version of LEAP Platform to the couch node before continuing.</p>
+
+<ol>
+<li><p>deploy to the couch node:</p>
+
+<pre><code class="`"> workstation$ leap deploy &lt;couchdb-node&gt;
+</code></pre>
+
+<p> If you used the iptables method of blocking access to couchdb, you need to run it again because the deploy just overwrote all the iptables rules:</p>
+
+<pre><code class="`"> server# iptables -A INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+</ol>
+
+
+<h3><a name="step-5-import-data-into-couchdb"></a>Step 5: Import Data into CouchDB</h3>
+
+<p><ol>
+<li><p>restore the backup, this will take approximately the same amount of time as the backup took above:</p>
+
+<pre><code class="`"> server# cd /srv/leap/couchdb/scripts
+ server# time ./couchdb_restoreall.sh
+</code></pre></li>
+<li><p>start services again that were stopped in the beginning:</p>
+
+<pre><code class="`"> workstation$ leap ssh soledad-nodes
+ server# /etc/init.d/soledad-server start
+
+ workstation$ leap ssh mx-node
+ server# /etc/init.d/postfix start
+ server# /etc/init.d/leap-mx start
+
+ workstation$ leap ssh webapp
+ server# /etc/init.d/nickserver start
+</code></pre>
+
+<p> Or, alternately, if you set up the firewall rule instead, now remove it:</p>
+
+<pre><code class="`"> server# iptables -D INPUT -p tcp --dport 5984 --jump REJECT
+</code></pre></li>
+</ol>
+
+</p>
+
+<h3><a name="step-6-deploy-everything"></a>Step 6: Deploy everything</h3>
+
+<p>Now that you&rsquo;ve upgraded all nodes to Jessie, and migrated to CouchDB, you are ready to deploy LEAP Platform 0.8 to the rest of the nodes:</p>
+
+<pre><code>workstation$ cd &lt;provider directory&gt;
+workstation$ leap deploy
+</code></pre>
+
+<h3><a name="step-7-test-and-cleanup"></a>Step 7: Test and cleanup</h3>
+
+<p><ol>
+<li><p>check if everything is working, including running the test on your deployment machine:</p>
+
+<pre><code class="`"> workstation$ leap test
+</code></pre></li>
+<li><p>Remove old bigcouch data dir <code>/opt</code> after you double checked everything is in place</p></li>
+<li><p>Relax, enjoy a refreshing beverage.</p></li>
+</ol>
+
+</p>
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 00000000..49465a9d
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>
+Provider Platform - LEAP Platform Documentation
+</title>
+<meta content='width=device-width, initial-scale=1.0' name='viewport'>
+<meta charset='UTF-8'>
+<base href="" />
+<style>
+ body {
+ background: #444;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ margin: 0px;
+ }
+ #sidebar {
+ flex: 0 0 250px;
+ background: white;
+ margin-right: 10px;
+ padding: 20px;
+ }
+ #sidebar ul {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+ }
+ #sidebar li { padding: 4px }
+ #sidebar li a { text-decoration: none }
+ #sidebar li.active { background: #444 }
+ #sidebar li.active a { color: white }
+ #sidebar li.level1 { padding-left: 20px }
+ #sidebar li.level2 { padding-left: 40px }
+ #main {
+ flex: 1 1 auto;
+ background: white;
+ padding: 20px;
+ }
+ #title-box {
+ padding-bottom: 20px;
+ border-bottom: 5px solid #eee;
+ }
+ #title-box h1 {
+ margin-top: 0px;
+ }
+ pre {
+ padding: 10px;
+ background: #eef;
+ }
+ code {
+ background: #eef;
+ }
+ table {border-collapse: collapse}
+ table td {
+ border: 1px solid #ccc;
+ padding: 4px;
+ vertical-align: top;
+ }
+</style>
+</head>
+<body>
+<div id='sidebar'>
+<ul>
+<li class='active'>
+<a href='index.html'>Home</a>
+</li>
+<li class=' level0'>
+<a class='' href='en/guide.html'>Guide</a>
+</li>
+<li class=' level0'>
+<a class='' href='en/tutorials.html'>Tutorials</a>
+</li>
+<li class=' level0'>
+<a class='' href='en/services.html'>Services</a>
+</li>
+<li class=' level0'>
+<a class='' href='en/upgrading.html'>Upgrading</a>
+</li>
+<li class=' level0'>
+<a class='' href='en/troubleshooting.html'>Troubleshooting</a>
+</li>
+<li class=' level0'>
+<a class='' href='en/details.html'>Details</a>
+</li>
+</ul>
+</div>
+<div id='main'>
+<div id='title-box'>
+<h1>LEAP Platform for Service Providers</h1>
+
+<div id='summary'>The LEAP Platform is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment.</div>
+</div>
+<div id='content-box'>
+<p>Its goal is to make it as painless as possible for sysadmins to deploy and maintain a service provider&rsquo;s infrastructure for secure communication.</p>
+
+<p><strong>REQUIREMENTS</strong> &ndash; Before you begin, make sure you meet these requirements:</p>
+
+<ul>
+<li><em>Debian Servers</em>: Servers that you deploy to must be running <strong>Debian Jessie</strong>, and no other distribution or version.</li>
+<li><em>Real or Paravirtualized Servers</em>: Servers must be real machines or paravirtualized VMs (e.g. KVM, Xen, OpenStack, AWS, Google Compute). OS level virtualization is not supported (e.g. OpenVZ, Linux-VServer, etc), nor are system emulators (VirtualBox, QEMU, etc).</li>
+<li><em>Your Workstation</em>: You must have a Linux or Mac computer to deploy from (this can be a headless machine with no GUI). Windows is not supported (Cygwin would probably work, but is untested).</li>
+<li><em>Your Own Domain</em>: You must own a domain name. Before your provider can be put into production, you will need to make modifications to the DNS for the provider&rsquo;s domain.</li>
+</ul>
+
+
+<p>The LEAP Platform consists of three parts, detailed below:</p>
+
+<ol>
+<li><a href="index.html#the-platform-recipes">The platform recipes.</a></li>
+<li><a href="index.html#the-provider-instance">The provider instance.</a></li>
+<li><a href="index.html#the-leap-command-line-tool">The <code>leap</code> command line tool.</a></li>
+</ol>
+
+
+<h2><a name="the-platform-recipes"></a>The platform recipes</h2>
+
+<p>The LEAP platform recipes define an abstract service provider. It is a set of <a href="https://puppetlabs.com/puppet/puppet-open-source/">Puppet</a> modules designed to work together to provide to sysadmins everything they need to manage a service provider infrastructure that provides secure communication services.</p>
+
+<p>LEAP maintains a repository of platform recipes, which typically do not need to be modified, although it can be forked and merged as desired. Most service providers using the LEAP platform can use the same set of platform recipes.</p>
+
+<p>As these recipes consist in abstract definitions, in order to configure settings for a particular service provider a system administrator has to create a provider instance (see below).</p>
+
+<p>LEAP&rsquo;s platform recipes are distributed as a git repository: <code>https://leap.se/git/leap_platform</code></p>
+
+<h2><a name="the-provider-instance"></a>The provider instance</h2>
+
+<p>A provider instance is a directory tree (typically tracked in git) containing all the configurations for a service provider&rsquo;s infrastructure. A provider instance <strong>lives on your workstation</strong>, not on the server.</p>
+
+<p>A provider instance primarily consists of:</p>
+
+<ul>
+<li>A pointer to the platform recipes.</li>
+<li>A global configuration file for the provider.</li>
+<li>A configuration file for each server (node) in the provider&rsquo;s infrastructure.</li>
+<li>Additional files, such as certificates and keys.</li>
+</ul>
+
+
+<p>A minimal provider instance directory looks like this:</p>
+
+<pre><code>└── bitmask # provider instance directory.
+ ├── Leapfile # settings for the `leap` command line tool.
+ ├── provider.json # global settings of the provider.
+ ├── common.json # settings common to all nodes.
+ ├── nodes/ # a directory for node configurations.
+ ├── files/ # keys, certificates, and other files.
+ └── users/ # public key information for privileged sysadmins.
+</code></pre>
+
+<p>A provider instance directory contains everything needed to manage all the servers that compose a provider&rsquo;s infrastructure. Because of this, any versioning tool and development work-flow can be used to manage your provider instance.</p>
+
+<h2><a name="the-leap-command-line-tool"></a>The <code>leap</code> command line tool</h2>
+
+<p>The <code>leap</code> <a href="en/commands.html">command line tool</a> is used by sysadmins to manage everything about a service provider&rsquo;s infrastructure.</p>
+
+<p>Keep these rules in mind:</p>
+
+<ul>
+<li><code>leap</code> is run on your workstation: The <code>leap</code> command is always run locally on your workstation, never on a server you are deploying to.</li>
+<li><code>leap</code> is run from within a provider instance: The <code>leap</code> command requires that the current working directory is a valid provider instance, except when running <code>leap new</code> to create a new provider instance.</li>
+</ul>
+
+
+<p>The <code>leap</code> command line has many capabilities, including:</p>
+
+<ul>
+<li>Create, initialize, and deploy nodes.</li>
+<li>Manage keys and certificates.</li>
+<li>Query information about the node configurations.</li>
+</ul>
+
+
+<p>Everything about your provider is managed by editing JSON configuration files and running <code>leap</code> commands.</p>
+
+<h2><a name="what-is-next"></a>What is next?</h2>
+
+<p>We recommend reading the platform documentation in the following order:</p>
+
+<ol>
+<li><a href="en/tutorials/quick-start.html">Quick Start Tutorial</a></li>
+<li><a href="en/guide/getting-started.html">Getting Started</a></li>
+<li><a href="en/guide.html">Guide</a></li>
+</ol>
+
+
+</div>
+</div>
+</body>
+</html>
diff --git a/docs/robots.txt.html b/docs/robots.txt.html
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/docs/robots.txt.html