summaryrefslogtreecommitdiff
path: root/docs/en/guide
diff options
context:
space:
mode:
Diffstat (limited to 'docs/en/guide')
-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
20 files changed, 7178 insertions, 0 deletions
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>