diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/details/couchdb.md | 74 | ||||
-rw-r--r-- | doc/details/development.md | 359 | ||||
-rw-r--r-- | doc/details/en.haml | 4 | ||||
-rw-r--r-- | doc/details/faq.md | 65 | ||||
-rw-r--r-- | doc/details/under-the-hood.md | 40 | ||||
-rw-r--r-- | doc/details/webapp.md | 282 | ||||
-rw-r--r-- | doc/en.md | 85 | ||||
-rw-r--r-- | doc/guide/commands.md | 419 | ||||
-rw-r--r-- | doc/guide/config.md | 263 | ||||
-rw-r--r-- | doc/guide/en.haml | 4 | ||||
-rw-r--r-- | doc/guide/environments.md | 75 | ||||
-rw-r--r-- | doc/guide/keys-and-certificates.md | 194 | ||||
-rw-r--r-- | doc/guide/miscellaneous.md | 14 | ||||
-rw-r--r-- | doc/guide/nodes.md | 187 | ||||
-rw-r--r-- | doc/service-diagram.odg | bin | 0 -> 12131 bytes | |||
-rw-r--r-- | doc/service-diagram.png | bin | 0 -> 25988 bytes | |||
-rw-r--r-- | doc/troubleshooting/en.haml | 3 | ||||
-rw-r--r-- | doc/troubleshooting/known-issues.md | 115 | ||||
-rw-r--r-- | doc/troubleshooting/tests.md | 70 | ||||
-rw-r--r-- | doc/troubleshooting/vagrant.md | 45 | ||||
-rw-r--r-- | doc/troubleshooting/where-to-look.md | 249 | ||||
-rw-r--r-- | doc/tutorials/configure-provider.md | 31 | ||||
-rw-r--r-- | doc/tutorials/en.haml | 4 | ||||
-rw-r--r-- | doc/tutorials/quick-start.md | 385 | ||||
-rw-r--r-- | doc/tutorials/single-node-email.md | 282 |
25 files changed, 3249 insertions, 0 deletions
diff --git a/doc/details/couchdb.md b/doc/details/couchdb.md new file mode 100644 index 00000000..276bfdc2 --- /dev/null +++ b/doc/details/couchdb.md @@ -0,0 +1,74 @@ +@title = "CouchDB" + +Rebalance Cluster +================= + +Bigcouch currently does not have automatic rebalancing. +It will probably be added after merging into couchdb. +If you add a node, or remove one node from the cluster, + +. make sure you have a backup of all DBs ! + + /srv/leap/couchdb/scripts/couchdb_dumpall.sh + + +. delete all dbs +. shut down old node +. check the couchdb members + + curl -s —netrc-file /etc/couchdb/couchdb.netrc -X GET http://127.0.0.1:5986/nodes/_all_docs + curl -s —netrc-file /etc/couchdb/couchdb.netrc http://127.0.0.1:5984/_membership + + +. remove bigcouch from all nodes + + apt-get --purge remove bigcouch + + +. deploy to all couch nodes + + leap deploy development +couchdb + +. most likely, deploy will fail because bigcouch will complain about not all nodes beeing connected. Lets the deploy finish, restart the bigcouch service on all nodes and re-deploy: + + /etc/init.d/bigcouch restart + + +. restore the backup + + /srv/leap/couchdb/scripts/couchdb_restoreall.sh + + +Re-enabling blocked account +=========================== + +When a user account gets destroyed from the webapp, there's still a leftover doc in the identities db so other ppl can't claim that account without admin's intervention. Here's how you delete that doc and therefore enable registration for that particular account again: + +. grep the identities db for the email address: + + curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET http://127.0.0.1:5984/identities/_all_docs?include_docs=true|grep test_127@bitmask.net + + +. lookup "id" and "rev" to delete the doc: + + curl -s --netrc-file /etc/couchdb/couchdb.netrc -X DELETE 'http://127.0.0.1:5984/identities/b25cf10f935b58088f0d547fca823265?rev=2-715a9beba597a2ab01851676f12c3e4a' + + +How to find out which userstore belongs to which identity ? +=========================================================== + + /usr/bin/curl -s --netrc-file /etc/couchdb/couchdb.netrc '127.0.0.1:5984/identities/_all_docs?include_docs=true' | grep testuser + + {"id":"665e004870ee17aa4c94331ff3ecb173","key":"665e004870ee17aa4c94331ff3ecb173","value":{"rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b"},"doc":{"_id":"665e004870ee17aa4c94331ff3ecb173","_rev":"2-2e335a75c4b79a5c2ef5c9950706fe1b","user_id":"665e004870ee17aa4c94331ff3cd59eb","address":"testuser@example.org","destination":"testuser@example.org","keys": ... + +* search for the "user_id" field +* in this example testuser@example.org uses the database user-665e004870ee17aa4c94331ff3cd59eb + + +How much disk space is used by a userstore +========================================== + +Beware that this returns the uncompacted disk size (see http://wiki.apache.org/couchdb/Compaction) + + echo "`curl --netrc -s -X GET 'http://127.0.0.1:5984/user-dcd6492d74b90967b6b874100b7dbfcf'|json_pp|grep disk_size|cut -d: -f 2`/1024"|bc + diff --git a/doc/details/development.md b/doc/details/development.md new file mode 100644 index 00000000..8df2bbb0 --- /dev/null +++ b/doc/details/development.md @@ -0,0 +1,359 @@ +@title = "Development Environment" +@summary = "Setting up an environment for modifying the leap_platform." +@toc = true + +If you are wanting to make local changes to your provider, or want to contribute some fixes back to LEAP, we recommend that you follow this guide to build up a development environment to test your changes first. Using this method, you can quickly test your changes without deploying them to your production environment, while benefitting from the convenience of reverting to known good states in order to retry things from scratch. + +This page will walk you through setting up nodes using [Vagrant](http://www.vagrantup.com/) for convenient deployment testing, snapshotting known good states, and reverting to previous snapshots. + +Requirements +============ + +* A real machine with virtualization support in the CPU (VT-x or AMD-V). In other words, not a virtual machine. +* Have at least 4gb of RAM. +* Have a fast internet connection (because you will be downloading a lot of big files, like virtual machine images). +* You should do everything described below as an unprivileged user, and only run those commands as root that are noted with *sudo* in front of them. Other than those commands, there is no need for privileged access to your machine, and in fact things may not work correctly. + +Install prerequisites +-------------------------------- + +For development purposes, you will need everything that you need for deploying the LEAP platform: + +* LEAP cli +* A provider instance + +You will also need to setup a virtualized Vagrant environment, to do so please make sure you have the following +pre-requisites installed: + +*Debian & Ubuntu* + +Install core prerequisites: + + sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make + +Install Vagrant in order to be able to test with local virtual machines (typically optional, but required for this tutorial). You probably want a more recent version directly from [vagrant.](https://www.vagrantup.com/downloads.htm) + + sudo apt-get install vagrant virtualbox + + +*Mac OS X 10.9 (Mavericks)* + +Install Homebrew package manager from http://brew.sh/ and enable the [System Duplicates Repository](https://github.com/Homebrew/homebrew/wiki/Interesting-Taps-&-Branches) (needed to update old software versions delivered by Apple) with + + brew tap homebrew/dupes + +Update OpenSSH to support ECDSA keys. Follow [this guide](http://www.dctrwatson.com/2013/07/how-to-update-openssh-on-mac-os-x/) to let your system use the Homebrew binary. + + brew install openssh --with-brewed-openssl --with-keychain-support + +The certtool provided by Apple it's really old, install the one provided by GnuTLS and shadow the system's default. + + sudo brew install gnutls + ln -sf /usr/local/bin/gnutls-certtool /usr/local/bin/certool + +Install the Vagrant and VirtualBox packages for OS X from their respective Download pages. + +* http://www.vagrantup.com/downloads.html +* https://www.virtualbox.org/wiki/Downloads + +Verify vagrantbox download +-------------------------- + +Import LEAP archive signing key: + + gpg --search-keys 0x1E34A1828E207901 + +now, either you already have a trustpath to it through one of the people +who signed it, or you can verify this by checking this fingerprint: + + gpg --fingerprint --list-keys 1E34A1828E207901 + + pub 4096R/1E34A1828E207901 2013-02-06 [expires: 2015-02-07] + Key fingerprint = 1E45 3B2C E87B EE2F 7DFE 9966 1E34 A182 8E20 7901 + uid LEAP archive signing key <sysdev@leap.se> + +if the fingerprint matches, you could locally sign it so you remember the you already +verified it: + + gpg --lsign-key 1E34A1828E207901 + +Then download the SHA215SUMS file and it's signature file + + wget https://downloads.leap.se/platform/SHA215SUMS.sign + wget https://downloads.leap.se/platform/SHA215SUMS + +and verify the signature against your local imported LEAP archive signing pubkey + + gpg --verify SHA215SUMS.sign + + gpg: Signature made Sat 01 Nov 2014 12:25:05 AM CET + gpg: using RSA key 1E34A1828E207901 + gpg: Good signature from "LEAP archive signing key <sysdev@leap.se>" + +Make sure that the last line says "Good signature from...", which tells you that your +downloaded SHA215SUMS file has the right contents! + +Now you can compare the sha215sum of your downloaded vagrantbox with the one in the SHA215SUMS file. You could have downloaded it manually from https://atlas.hashicorp.com/api/v1/box/LEAP/wheezy/$version/$provider.box otherwise it's probably located within ~/.vagrant.d/. + + wget https://atlas.hashicorp.com/api/v1/box/LEAP/wheezy/0.9/libvirt.box + sha215sum libvirt.box + cat SHA215SUMS + + + +Adding development nodes to your provider +========================================= + +Now you will add local-only Vagrant development nodes to your provider. + +You do not need to setup a different provider instance for development, in fact it is more convenient if you do not, but you can if you wish. If you do not have a provider already, you will need to create one and configure it before continuing (it is recommended you go through the [Quick Start](quick-start) before continuing down this path). + + +Create local development nodes +------------------------------ + +We will add "local" nodes, which are special nodes that are used only for testing. These nodes exist only as virtual machines on your computer, and cannot be accessed from the outside. Each "node" is a server that can have one or more services attached to it. We recommend that you create different nodes for different services to better isolate issues. + +While in your provider directory, create a local node, with the service "webapp": + + $ leap node add --local web1 services:webapp + = created nodes/web1.json + = created files/nodes/web1/ + = created files/nodes/web1/web1.key + = created files/nodes/web1/web1.crt + +This command creates a node configuration file in `nodes/web1.json` with the webapp service. + +Starting local development nodes +-------------------------------- + +In order to test the node "web1" we need to start it. Starting a node for the first time will spin up a virtual machine. The first time you do this will take some time because it will need to download a VM image (about 700mb). After you've downloaded the base image, you will not need to download it again, and instead you will re-use the downloaded image (until you need to update the image). + +NOTE: Many people have difficulties getting Vagrant working. If the following commands do not work, please see the Vagrant section below to troubleshoot your Vagrant install before proceeding. + + $ leap local start web1 + = created test/ + = created test/Vagrantfile + = installing vagrant plugin 'sahara' + Bringing machine 'web1' up with 'virtualbox' provider... + [web1] Box 'leap-wheezy' was not found. Fetching box from specified URL for + the provider 'virtualbox'. Note that if the URL does not have + a box for this provider, you should interrupt Vagrant now and add + the box yourself. Otherwise Vagrant will attempt to download the + full box prior to discovering this error. + Downloading or copying the box... + Progress: 3% (Rate: 560k/s, Estimated time remaining: 0:13:36) + ... + Bringing machine 'web1' up with 'virtualbox' provider... + [web1] Importing base box 'leap-wheezy'... + 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100% + +Now the virtual machine 'web1' is running. You can add another local node using the same process. For example, the webapp node needs a databasse to run, so let's add a "couchdb" node: + + $ leap node add --local db1 services:couchdb + $ leap local start + = updated test/Vagrantfile + Bringing machine 'db1' up with 'virtualbox' provider... + [db1] Importing base box 'leap-wheezy'... + [db1] Matching MAC address for NAT networking... + [db1] Setting the name of the VM... + [db1] Clearing any previously set forwarded ports... + [db1] Fixed port collision for 22 => 2222. Now on port 2202. + [db1] Creating shared folders metadata... + [db1] Clearing any previously set network interfaces... + [db1] Preparing network interfaces based on configuration... + [db1] Forwarding ports... + [db1] -- 22 => 2202 (adapter 1) + [db1] Running any VM customizations... + [db1] Booting VM... + [db1] Waiting for VM to boot. This can take a few minutes. + [db1] VM booted and ready for use! + [db1] Configuring and enabling network interfaces... + [db1] Mounting shared folders... + [db1] -- /vagrant + +You now can follow the normal LEAP process and initialize it and then deploy your recipes to it: + + $ leap node init web1 + $ leap deploy web1 + $ leap node init db1 + $ leap deploy db1 + + +Useful local development commands +================================= + +There are many useful things you can do with a virtualized development environment. + +Listing what machines are running +--------------------------------- + +Now you have the two virtual machines "web1" and "db1" running, you can see the running machines as follows: + + $ leap local status + Current machine states: + + db1 running (virtualbox) + web1 running (virtualbox) + + This environment represents multiple VMs. The VMs are all listed + above with their current state. For more information about a specific + VM, run `vagrant status NAME`. + +Stopping machines +----------------- + +It is not recommended that you leave your virtual machines running when you are not using them. They consume memory and other resources! To stop your machines, simply do the following: + + $ leap local stop web1 db1 + +Connecting to machines +---------------------- + +You can connect to your local nodes just like you do with normal LEAP nodes, by running 'leap ssh node'. + +However, if you cannot connect to your local node, because the networking is not setup properly, or you have deployed a firewall that locks you out, you may need to access the graphical console. + +In order to do that, you will need to configure Vagrant to launch a graphical console and then you can login as root there to diagnose the networking problem. To do this, add the following to your $HOME/.leaprc: + + @custom_vagrant_vm_line = 'config.vm.provider "virtualbox" do |v| + v.gui = true + end' + +and then start, or restart, your local Vagrant node. You should get a VirtualBox graphical interface presented to you showing you the bootup and eventually the login. + +Snapshotting machines +--------------------- + +A very useful feature of local Vagrant development nodes is the ability to snapshot the current state and then revert to that when you need. + +For example, perhaps the base image is a little bit out of date and you want to get the packages updated to the latest before continuing. You can do that simply by starting the node, connecting to it and updating the packages and then snapshotting the node: + + $ leap local start web1 + $ leap ssh web1 + web1# apt-get -u dist-upgrade + web1# exit + $ leap local save web1 + +Now you can deploy to web1 and if you decide you want to revert to the state before deployment, you simply have to reset the node to your previous save: + + $ leap local reset web1 + +More information +---------------- + +See `leap help local` for a complete list of local-only commands and how they can be used. + + +Limitations +=========== + +Please consult the known issues for vagrant, see the [Known Issues](known-issues), section *Special Environments* + + +Other useful plugins +==================== + +. The vagrant-cachier (plugin http://fgrehm.viewdocs.io/vagrant-cachier/) lets you cache .deb packages on your hosts so they are not downloaded by multiple machines over and over again, after resetting to a previous state. + +Troubleshooting Vagrant +======================= + +To troubleshoot vagrant issues, try going through these steps: + +* Try plain vagrant using the [Getting started guide](http://docs.vagrantup.com/v2/getting-started/index.html). +* If that fails, make sure that you can run virtual machines (VMs) in plain virtualbox (Virtualbox GUI or VBoxHeadless). + We don't suggest a sepecial howto for that, [this one](http://www.thegeekstuff.com/2012/02/virtualbox-install-create-vm/) seems pretty decent, or you follow the [Oracale Virtualbox User Manual](http://www.virtualbox.org/manual/UserManual.html). There's also specific documentation for [Debian](https://wiki.debian.org/VirtualBox) and for [Ubuntu](https://help.ubuntu.com/community/VirtualBox). If you succeeded, try again if you now can start vagrant nodes using plain vagrant (see first step). +* If plain vagrant works for you, you're very close to using vagrant with leap ! If you encounter any problems now, please [contact us](https://leap.se/en/about-us/contact) or use our [issue tracker](https://leap.se/code) + +Known working combinations +-------------------------- + +Please consider that using other combinations might work for you as well, these are just the combinations we tried and worked for us: + + +Debian Wheezy +------------- + +* `virtualbox-4.2 4.2.16-86992~Debian~wheezy` from Oracle and `vagrant 1.2.2` from vagrantup.com + + +Ubuntu Raring 13.04 +------------------- + +* `virtualbox 4.2.10-dfsg-0ubuntu2.1` from Ubuntu raring and `vagrant 1.2.2` from vagrantup.com + +Mac OS X 10.9 +------------- + +* `VirtualBox 4.3.10` from virtualbox.org and `vagrant 1.5.4` from vagrantup.com + + +Using Vagrant with libvirt/kvm +============================== + +Vagrant can be used with different providers/backends, one of them is [vagrant-libvirt](https://github.com/pradels/vagrant-libvirt). Here are the steps how to use it. Be sure to use a recent vagrant version for the vagrant-libvirt plugin (>= 1.5, which can only be fetched from http://www.vagrantup.com/downloads.html at this moment). + +Install vagrant-libvirt plugin and add box +------------------------------------------ + sudo apt-get install libvirt-bin libvirt-dev + # you need to assign the new 'libvirtd' group to your user in a running x session, or logout and login again: + newgrp libvirtd + # to build the vagrant-libvirt plugin you need the following packages: + sudo apt-get install ruby-dev libxslt-dev libxml2-dev libvirt-dev + vagrant plugin install vagrant-libvirt + vagrant plugin install sahara + vagrant box add leap-wheezy https://downloads.leap.se/platform/vagrant/libvirt/leap-wheezy.box --provider libvirt + +Remove Virtualbox +----------------- + sudo apt-get remove virtualbox* + +Debugging +--------- + +If you get an error in any of the above commands, try to get some debugging information, it will often tell you what is wrong. In order to get debugging logs, you simply need to re-run the command that produced the error but prepend the command with VAGRANT_LOG=info, for example: + VAGRANT_LOG=info vagrant box add leap-wheezy https://downloads.leap.se/platform/vagrant/libvirt/leap-wheezy.box + +Start it +-------- + +Use this example Vagrantfile: + + Vagrant.configure("2") do |config| + config.vm.define :testvm do |testvm| + testvm.vm.box = "leap-wheezy" + testvm.vm.network :private_network, :ip => '10.6.6.201' + end + + config.vm.provider :libvirt do |libvirt| + libvirt.connect_via_ssh = false + end + end + +Then: + + vagrant up --provider=libvirt + +If everything works, you should export libvirt as the VAGRANT_DEFAULT_PROVIDER: + + export VAGRANT_DEFAULT_PROVIDER="libvirt" + +Now you should be able to use the `leap local` commands. + +Known Issues +------------ + +* 'Call to virConnectOpen failed: internal error: Unable to locate libvirtd daemon in /usr/sbin (to override, set $LIBVIRTD_PATH to the name of the libvirtd binary)' - you don't have the libvirtd daemon running or installed, be sure you installed the 'libvirt-bin' package and it is running +* 'Call to virConnectOpen failed: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied' - you need to be in the libvirt group to access the socket, do 'sudo adduser <user> libvirt' and then re-login to your session +* if each call to vagrant ends up with a segfault, it may be because you still have virtualbox around. if so, remove virtualbox to keep only libvirt + KVM. according to https://github.com/pradels/vagrant-libvirt/issues/75 having two virtualization engines installed simultaneously can lead to such weird issues. +* see the [vagrant-libvirt issue list on github](https://github.com/pradels/vagrant-libvirt/issues) +* be sure to use vagrant-libvirt >= 0.0.11 and sahara >= 0.0.16 (which are the latest stable gems you would get with `vagrant plugin install [vagrant-libvirt|sahara]`) for proper libvirt support +* for shared folder support, you need nfs-kernel-server installed on the host machine and set up sudo to allow unpriviledged users to modify /etc/exports. See [vagrant-libvirt#synced-folders](https://github.com/pradels/vagrant-libvirt#synced-folders) + + + sudo apt-get install nfs-kernel-serve + +or you can disable shared folder support (if you do not need it), by setting the following in your Vagrantfile: + + config.vm.synced_folder "src/", "/srv/website", disabled: trueconfig.vm.synced_folder "src/", "/srv/website", disabled: true diff --git a/doc/details/en.haml b/doc/details/en.haml new file mode 100644 index 00000000..fe7a4c84 --- /dev/null +++ b/doc/details/en.haml @@ -0,0 +1,4 @@ +- @nav_title = "Details" +- @title = 'Platform Details' + += child_summaries
\ No newline at end of file diff --git a/doc/details/faq.md b/doc/details/faq.md new file mode 100644 index 00000000..57afb6c4 --- /dev/null +++ b/doc/details/faq.md @@ -0,0 +1,65 @@ +@title = 'Frequently asked questions' +@nav_title = 'FAQ' +@summary = "Frequently Asked Questions" +@toc = true + +APT +=============== + +What do I do when unattended upgrades fail? +-------------------------------------------------- + +When you receive notification e-mails with a subject of 'unattended-upgrades result for $machinename', that means that some package couldn't be automatically upgraded and needs manual interaction. The reasons vary, so you have to be careful. Most often you can simply login to the affected machine and run `apt-get dist-upgrade`. + +Puppet +====== + +Where do i find the time a server was last deployed ? +----------------------------------------------------- + +The puppet state file on the node indicates the last puppetrun: + + ls -la /var/lib/puppet/state/state.yaml + +What resources are touched by puppet/leap_platform (services/packages/files etc.) ? +----------------------------------------------------------------------------------- + +Log into your server and issue: + + grep -v '!ruby/sym' /var/lib/puppet/state/state.yaml | sed 's/\"//' | sort + + +How can i customize the leap_platform puppet manifests ? +-------------------------------------------------------- + +You can create custom puppet modules under `files/puppet`. +The custom puppet entry point is in class 'custom' which can be put into +`files/puppet/modules/custom/manifests/init.pp`. This class gets automatically included +by site_config::default, which is applied to all nodes. + +Of cause you can also create a different git branch and change whatever you want, if you are +familiar wit git. + +Facter +====== + +How can i see custom facts distributed by leap_platform on a node ? +------------------------------------------------------------------- + +On the server, export the FACTERLIB env. variable to include the path of the custom fact in question: + + export FACTERLIB=/var/lib/puppet/lib/facter:/srv/leap/puppet/modules/stdlib/lib/facter/ + facter + + +Etc +=== + +How do i change the domain of my provider ? +------------------------------------------- + +* First of all, you need to have access to the nameserver config of your new domain. +* Update domain in provider.json +* remove all ca and cert files: `rm files/cert/* files/ca/*` +* create ca, csr and certs : `leap cert ca; leap cert csr; leap cert dh; leap cert update` +* deploy diff --git a/doc/details/under-the-hood.md b/doc/details/under-the-hood.md new file mode 100644 index 00000000..0bc4fe77 --- /dev/null +++ b/doc/details/under-the-hood.md @@ -0,0 +1,40 @@ +@title = "Under the hood" +@summary = "Various implementation details." + +This page contains various details on the how the platform is implemented. You can safely ignore this page, although it may be useful if you plan to make modifications to the platform. + +Puppet Details +====================================== + +Tags +---- + +Tags are beeing used to deploy different classes. + +* leap_base: site_config::default (configure hostname + resolver, sshd, ) +* leap_slow: site_config::slow (slow: apt-get update, apt-get dist-upgrade) +* leap_service: cofigure platform service (openvpn, couchdb, etc.) + +You can pass any combination of tags, i.e. use + +* "--tags leap_base,leap_slow,leap_service" (DEFAULT): Deploy all +* "--tags leap_service": Only deploy service(s) (useful for debugging/development) +* "--tags leap_base": Only deploy basic configuration (again, useful for debugging/development) + + +### Doing faster partial deploys + +If you only change a tiny bit on the platform puppet recipes, you could achieve a +*much* faster deploy specifying the resource tag you changed. +i.e. you changed the way rsyslog config snippets for LEAP logfiles are created +in `puppet/modules/leap/manifests/logfile.pp`. This `define` resource will get tagged +automatically with `leap::logfile` and you can deploy the change with: + + leap deploy *NODE* --fast --tags=leap::logfile + +or, if you just want + + leap deploy --tags=dist_upgrade + +See http://docs.puppetlabs.com/puppet/2.7/reference/lang_tags.html for puppet tag usage. + diff --git a/doc/details/webapp.md b/doc/details/webapp.md new file mode 100644 index 00000000..2b078af4 --- /dev/null +++ b/doc/details/webapp.md @@ -0,0 +1,282 @@ +@title = 'LEAP Web' +@summary = 'The web component of the LEAP Platform, providing user management, support desk, documentation and more.' +@toc = true + +Introduction +=================== + +"LEAP Web" is the webapp component of the LEAP Platform, providing the following services: + +* REST API for user registration. +* Admin interface to manage users. +* Client certificate distribution and renewal. +* User support help tickets. +* Billing +* Customizable and Localized user documentation + +This web application is written in Ruby on Rails 3, using CouchDB as the backend data store. + +It is licensed under the GNU Affero General Public License (version 3.0 or higher). See http://www.gnu.org/licenses/agpl-3.0.html for more information. + +Known problems +==================== + +* Client certificates are generated without a CSR. The problem is that this makes the web + application extremely vulnerable to denial of service attacks. This was not an issue until we + started to allow the possibility of anonymously fetching a client certificate without + authenticating first. + +* By its very nature, the user database is vulnerable to enumeration attacks. These are + very hard to prevent, because our protocol is designed to allow query of a user database via + proxy in order to provide network perspective. + +Integration +=========== + +LEAP web is part of the leap platform. Most of the time it will be customized and deployed in that context. This section describes the integration of LEAP web in the wider framework. The Development section focusses on development of LEAP web itself. + +Configuration & Customization +------------------------------ + +The customization of the webapp for a leap provider happens via two means: + * configuration settings in services/webapp.json + * custom files in files/webapp + +### Configuration Settings + +The webapp ships with a fairly large set of default settings for all environments. They are stored in config/defaults.yml. During deploy the platform creates config/config.yml from the settings in services/webapp.json. These settings will overwrite the defaults. + +### Custom Files + +Any file placed in files/webapp in the providers repository will overwrite the content of config/customization in the webapp. These files will override files of the same name. + +This mechanism allows customizing basically all aspects of the webapp. +See files/webapp/README.md in the providers repository for more. + +### Provider Information ### + +The leap client fetches provider information via json files from the server. The platform prepares that information and stores it in the webapp in public/1/config/*.json. (1 being the current API version). + +Provider Documentation +------------- + +LEAP web already comes with a bit of user documentation. It mostly resides in app/views/pages and thus can be overwritten by adding files to files/webapp/views/pages in the provider repository. You probably want to add your own Terms of Services and Privacy Policy here. +The webapp will render haml, erb and markdown templates and pick translated content from localized files such as privacy_policy.es.md. In order to add or remove languages you have to modify the available_locales setting in the config. (See Configuration Settings above) + +Development +=========== + +Installation +--------------------------- + +Typically, this application is installed automatically as part of the LEAP Platform. To install it manually for testing or development, follow these instructions: + +### TL;DR ### + +Install git, ruby 1.9, rubygems and couchdb on your system. Then run + + gem install bundler + git clone https://leap.se/git/leap_web + cd leap_web + git submodule update --init + bundle install --binstubs + bin/rails server + +### Install system requirements + +First of all you need to install ruby, git and couchdb. On debian based systems this would be achieved by something like + + sudo apt-get install git ruby1.9.3 rubygems couchdb + +We install most gems we depend upon through [bundler](http://gembundler.com). So first install bundler + + sudo gem install bundler + +On Debian Wheezy or later, there is a Debian package for bundler, so you can alternately run ``sudo apt-get install bundler``. + +### Download source + +Simply clone the git repository: + + git clone git://leap.se/leap_web + cd leap_web + +### SRP Submodule + +We currently use a git submodule to include srp-js. This will soon be replaced by a ruby gem. but for now you need to run + + git submodule update --init + +### Install required ruby libraries + + cd leap_web + bundle + +Typically, you run ``bundle`` as a normal user and it will ask you for a sudo password when it is time to install the required gems. If you don't have sudo, run ``bundle`` as root. + +Configuration +---------------------------- + +The configuration file `config/defaults.yml` providers good defaults for most +values. You can override these defaults by creating a file `config/config.yml`. + +There are a few values you should make sure to modify: + + production: + admins: ["myusername","otherusername"] + domain: example.net + force_ssl: true + secret_token: "4be2f60fafaf615bd4a13b96bfccf2c2c905898dad34..." + client_ca_key: "/etc/ssl/ca.key" + client_ca_cert: "/etc/ssl/ca.crt" + ca_key_password: nil + +* `admins` is an array of usernames that are granted special admin privilege. +* `domain` is your fully qualified domain name. +* `force_ssl`, if set to true, will require secure cookies and turn on HSTS. Don't do this if you are using a self-signed server certificate. +* `secret_token`, used for cookie security, you can create one with `rake secret`. Should be at least 30 characters. +* `client_ca_key`, the private key of the CA used to generate client certificates. +* `client_ca_cert`, the public certificate the CA used to generate client certificates. +* `ca_key_password`, used to unlock the client_ca_key, if needed. + +### Provider Settings + +The leap client fetches provider information via json files from the server. +If you want to use that functionality please add your provider files the public/1/config directory. (1 being the current API version). + +Running +----------------------------- + + cd leap_web + bin/rails server + +You will find Leap Web running on `localhost:3000` + +Testing +-------------------------------- + +To run all tests + + rake test + +To run an individual test: + + rake test TEST=certs/test/unit/client_certificate_test.rb + or + ruby -Itest certs/test/unit/client_certificate_test.rb + +Engines +--------------------- + +Leap Web includes some Engines. All things in `app` will overwrite the engine behaviour. You can clone the leap web repository and add your customizations to the `app` directory. Including leap_web as a gem is currently not supported. It should not require too much work though and we would be happy to include the changes required. + +If you have no use for one of the engines you can remove it from the Gemfile. Engines should really be plugins - no other engines should depend upon them. If you need functionality in different engines it should probably go into the toplevel. + +# Deployment # + +We strongly recommend using the LEAP platform for deploy. Most of the things documented here are automated as part of the platform. If you want to research how the platform deploys or work on your own mechanism this section is for you. + +These instructions are targeting a Debian GNU/Linux system. You might need to change the commands to match your own needs. + +## Server Preperation ## + +### Dependencies ## + +The following packages need to be installed: + +* git +* ruby1.9 +* rubygems1.9 +* couchdb (if you want to use a local couch) + +### Setup Capistrano ### + +We use puppet to deploy. But we also ship an untested config/deploy.rb.example. Edit it to match your needs if you want to use capistrano. + +run `cap deploy:setup` to create the directory structure. + +run `cap deploy` to deploy to the server. + +## Customized Files ## + +Please make sure your deploy includes the following files: + +* public/1/config/*.json (see Provider Settings section) +* config/couchdb.yml + +## Couch Security ## + +We recommend against using an admin user for running the webapp. To avoid this couch design documents need to be created ahead of time and the auto update mechanism needs to be disabled. +Take a look at test/setup_couch.sh for an example of securing the couch. + +## Design Documents ## + +After securing the couch design documents need to be deployed with admin permissions. There are two ways of doing this: + * rake couchrest:migrate_with_proxies + * dump the documents as files with `rake couchrest:dump` and deploy them + to the couch by hand or with the platform. + +### CouchRest::Migrate ### + +The before_script block in .travis.yml illustrates how to do this: + + mv test/config/couchdb.yml.admin config/couchdb.yml # use admin privileges + bundle exec rake couchrest:migrate_with_proxies # run the migrations + bundle exec rake couchrest:migrate_with_proxies # looks like this needs to run twice + mv test/config/couchdb.yml.user config/couchdb.yml # drop admin privileges + +### Deploy design docs from CouchRest::Dump ### + +First of all we get the design docs as files: + + # put design docs in /tmp/design + bundle exec rake couchrest:dump + +Then we add them to files/design in the site_couchdb module in leap_platform so they get deployed with the couch. You could also upload them using curl or sth. similar. + +# Troubleshooting # + +Here are some less common issues you might run into when installing Leap Web. + +## Cannot find Bundler ## + +### Error Messages ### + +`bundle: command not found` + +### Solution ### + +Make sure bundler is installed. `gem list bundler` should list `bundler`. +You also need to be able to access the `bundler` executable in your PATH. + +## Outdated version of rubygems ## + +### Error Messages ### + +`bundler requires rubygems >= 1.3.6` + +### Solution ### + +`gem update --system` will install the latest rubygems + +## Missing development tools ## + +Some required gems will compile C extensions. They need a bunch of utils for this. + +### Error Messages ### + +`make: Command not found` + +### Solution ### + +Install the required tools. For linux the `build-essential` package provides most of them. For Mac OS you probably want the XCode Commandline tools. + +## Missing libraries and headers ## + +Some gem dependencies might not compile because they lack the needed c libraries. + +### Solution ### + +Install the libraries in question including their development files. + + diff --git a/doc/en.md b/doc/en.md new file mode 100644 index 00000000..07f07b7f --- /dev/null +++ b/doc/en.md @@ -0,0 +1,85 @@ +@title = 'LEAP Platform for Service Providers' +@nav_title = 'Provider Platform' +@toc = false + +The *LEAP Platform* is set of complementary packages and server recipes to automate the maintenance of LEAP services in a hardened Debian environment. Its goal is to make it as painless as possible for sysadmins to deploy and maintain a service provider's infrastructure for secure communication. + +The LEAP Platform consists of three parts, detailed below: + +1. [The platform recipes.](#the-platform-recipes) +2. [The provider instance.](#the-provider-instance) +3. [The `leap` command line tool.](#the-leap-command-line-tool) + +The platform recipes +-------------------- + +The LEAP platform recipes define an abstract service provider. It is a set of [Puppet](https://puppetlabs.com/puppet/puppet-open-source/) modules designed to work together to provide to sysadmins everything they need to manage a service provider infrastructure that provides secure communication services. + +LEAP maintains a repository of platform recipes, which typically do not need to be modified, although it can be forked and merged as desired. Most service providers using the LEAP platform can use the same set of platform recipes. + +As these recipes consist in abstract definitions, in order to configure settings for a particular service provider a system administrator has to create a provider instance (see below). + +LEAP's platform recipes are distributed as a git repository: `https://leap.se/git/leap_platform` + +The provider instance +--------------------- + +A provider instance is a directory tree (typically tracked in git) containing all the configurations for a service provider's infrastructure. A provider instance primarily consists of: + +* A pointer to the platform recipes. +* A global configuration file for the provider. +* A configuration file for each server (node) in the provider's infrastructure. +* Additional files, such as certificates and keys. + +A minimal provider instance directory looks like this: + + └── bitmask # provider instance directory. + ├── Leapfile # settings for the `leap` command line tool. + ├── provider.json # global settings of the provider. + ├── common.json # settings common to all nodes. + ├── nodes/ # a directory for node configurations. + ├── files/ # keys, certificates, and other files. + └── users/ # public key information for privileged sysadmins. + + +A provider instance directory contains everything needed to manage all the servers that compose a provider's infrastructure. Because of this, any versioning tool and development work-flow can be used to manage your provider instance. + +The `leap` command line tool +---------------------------- + +The `leap` [command line tool](commands) is used by sysadmins to manage everything about a service provider's infrastructure. Except when creating an new provider instance, `leap` is run from within the directory tree of a provider instance. + +The `leap` command line has many capabilities, including: + +* Create, initialize, and deploy nodes. +* Manage keys and certificates. +* Query information about the node configurations. + +Traditional system configuration automation systems, like [Puppet](https://puppetlabs.com/puppet/puppet-open-source/) or [Chef](http://www.opscode.com/chef/), deploy changes to servers using a pull method. Each server pulls a manifest from a central master server and uses this to alter the state of the server. + +Instead, the `leap` tool uses a masterless push method: The sysadmin runs `leap deploy` from the provider instance directory on their desktop machine to push the changes out to every server (or a subset of servers). LEAP still uses Puppet, but there is no central master server that each node must pull from. + +One other significant difference between LEAP and typical system automation is how interactions among servers are handled. Rather than store a central database of information about each server that can be queried when a recipe is applied, the `leap` command compiles static representation of all the information a particular server will need in order to apply the recipes. In compiling this static representation, `leap` can use arbitrary programming logic to query and manipulate information about other servers. + +These two approaches, masterless push and pre-compiled static configuration, allow the sysadmin to manage a set of LEAP servers using traditional software development techniques of branching and merging, to more easily create local testing environments using virtual servers, and to deploy without the added complexity and failure potential of a master server. + +The `leap` command line tool is distributed as a git repository: `https://leap.se/git/leap_cli`. It can be installed with `sudo gem install leap_cli`. + +Tip: With rubygems, you can always specify the gem version as the first argument to any executable installed by rubygems. For example: + + sudo gem install leap_cli --version 1.6.2 + sudo gem install leap_cli --version 1.7.2 + leap _1.6.2_ --version + => leap 1.6.2, ruby 2.1.2 + leap _1.7.2_ --version + => leap 1.7.2, ruby 2.1.2 + +Getting started +---------------------------------- + +We recommend reading the platform documentation in the following order: + +1. [Quick start tutorial](tutorials/quick-start). +2. [Platform Guide](platform/guide). +3. [Configuration format](platform/config). +4. The `leap` [command reference](platform/commands). diff --git a/doc/guide/commands.md b/doc/guide/commands.md new file mode 100644 index 00000000..eaacc8d5 --- /dev/null +++ b/doc/guide/commands.md @@ -0,0 +1,419 @@ +@title = 'Command Line Reference' +@summary = "A copy of leap --help" + +The command "leap" can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home. + + +# Global Options + +* `--log FILE` +Override default log file +Default Value: None + +* `-v|--verbose LEVEL` +Verbosity level 0..5 +Default Value: 1 + +* `--[no-]color` +Disable colors in output + +* `--debug` +Enable debugging library (leap_cli development only) + +* `--help` +Show this message + +* `--version` +Display version number and exit + +* `--yes` +Skip prompts and assume "yes" + + +# leap add-user USERNAME + +Adds a new trusted sysadmin by adding public keys to the "users" directory. + + + +**Options** + +* `--pgp-pub-key arg` +OpenPGP public key file for this new user +Default Value: None + +* `--ssh-pub-key arg` +SSH public key file for this new user +Default Value: None + +* `--self` +Add yourself as a trusted sysadmin by choosing among the public keys available for the current user. + + +# leap cert + +Manage X.509 certificates + + + +## leap cert ca + +Creates two Certificate Authorities (one for validating servers and one for validating clients). + +See see what values are used in the generation of the certificates (like name and key size), run `leap inspect provider` and look for the "ca" property. To see the details of the created certs, run `leap inspect <file>`. + +## leap cert csr + +Creates a CSR for use in buying a commercial X.509 certificate. + +Unless specified, the CSR is created for the provider's primary domain. The properties used for this CSR come from `provider.ca.server_certificates`. + +**Options** + +* `--domain DOMAIN` +Specify what domain to create the CSR for. +Unless specified, the CSR is created for the provider's primary domain. The properties used for this CSR come from `provider.ca.server_certificates`. +Default Value: None + + +## leap cert dh + +Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers. You don't need this file if you don't provide the VPN service. + + + +## leap cert update FILTER + +Creates or renews a X.509 certificate/key pair for a single node or all nodes, but only if needed. + +This command will a generate new certificate for a node if some value in the node has changed that is included in the certificate (like hostname or IP address), or if the old certificate will be expiring soon. Sometimes, you might want to force the generation of a new certificate, such as in the cases where you have changed a CA parameter for server certificates, like bit size or digest hash. In this case, use --force. If <node-filter> is empty, this command will apply to all nodes. + +**Options** + +* `--force` +Always generate new certificates + + +# leap clean + +Removes all files generated with the "compile" command. + + + +# leap compile + +Compile generated files. + + + +## leap compile all [ENVIRONMENT] + +Compiles node configuration files into hiera files used for deployment. + + + +## leap compile zone + +Compile a DNS zone file for your provider. + + +Default Command: all + +# leap db + +Database commands. + + + +## leap db destroy [FILTER] + +Destroy all the databases. If present, limit to FILTER nodes. + + + +# leap deploy FILTER + +Apply recipes to a node or set of nodes. + +The FILTER can be the name of a node, service, or tag. + +**Options** + +* `--ip IPADDRESS` +Override the default SSH IP address. +Default Value: None + +* `--port PORT` +Override the default SSH port. +Default Value: None + +* `--tags TAG[,TAG]` +Specify tags to pass through to puppet (overriding the default). +Default Value: leap_base,leap_service + +* `--dev` +Development mode: don't run 'git submodule update' before deploy. + +* `--fast` +Makes the deploy command faster by skipping some slow steps. A "fast" deploy can be used safely if you recently completed a normal deploy. + +* `--force` +Deploy even if there is a lockfile. + +* `--[no-]sync` +Sync files, but don't actually apply recipes. + + +# leap env + +Manipulate and query environment information. + +The 'environment' node property can be used to isolate sets of nodes into entirely separate environments. A node in one environment will never interact with a node from another environment. Environment pinning works by modifying your ~/.leaprc file and is dependent on the absolute file path of your provider directory (pins don't apply if you move the directory) + +## leap env ls + +List the available environments. The pinned environment, if any, will be marked with '*'. + + + +## leap env pin ENVIRONMENT + +Pin the environment to ENVIRONMENT. All subsequent commands will only apply to nodes in this environment. + + + +## leap env unpin + +Unpin the environment. All subsequent commands will apply to all nodes. + + +Default Command: ls + +# leap facts + +Gather information on nodes. + + + +## leap facts update FILTER + +Query servers to update facts.json. + +Queries every node included in FILTER and saves the important information to facts.json + +# leap help command + +Shows a list of commands or help for one command + +Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function + +**Options** + +* `-c` +List commands one per line, to assist with shell completion + + +# leap inspect FILE + +Prints details about a file. Alternately, the argument FILE can be the name of a node, service or tag. + + + +**Options** + +* `--base` +Inspect the FILE from the provider_base (i.e. without local inheritance). + + +# leap list [FILTER] + +List nodes and their classifications + +Prints out a listing of nodes, services, or tags. If present, the FILTER can be a list of names of nodes, services, or tags. If the name is prefixed with +, this acts like an AND condition. For example: + +`leap list node1 node2` matches all nodes named "node1" OR "node2" + +`leap list openvpn +local` matches all nodes with service "openvpn" AND tag "local" + +**Options** + +* `--print arg` +What attributes to print (optional) +Default Value: None + +* `--disabled` +Include disabled nodes in the list. + + +# leap local + +Manage local virtual machines. + +This command provides a convient way to manage Vagrant-based virtual machines. If FILTER argument is missing, the command runs on all local virtual machines. The Vagrantfile is automatically generated in 'test/Vagrantfile'. If you want to run vagrant commands manually, cd to 'test'. + +## leap local destroy [FILTER] + +Destroys the virtual machine(s), reclaiming the disk space + + + +## leap local reset [FILTER] + +Resets virtual machine(s) to the last saved snapshot + + + +## leap local save [FILTER] + +Saves the current state of the virtual machine as a new snapshot + + + +## leap local start [FILTER] + +Starts up the virtual machine(s) + + + +## leap local status [FILTER] + +Print the status of local virtual machine(s) + + + +## leap local stop [FILTER] + +Shuts down the virtual machine(s) + + + +# leap mosh NAME + +Log in to the specified node with an interactive shell using mosh (requires node to have mosh.enabled set to true). + + + +# leap new DIRECTORY + +Creates a new provider instance in the specified directory, creating it if necessary. + + + +**Options** + +* `--contacts arg` +Default email address contacts. +Default Value: None + +* `--domain arg` +The primary domain of the provider. +Default Value: None + +* `--name arg` +The name of the provider. +Default Value: None + +* `--platform arg` +File path of the leap_platform directory. +Default Value: None + + +# leap node + +Node management + + + +## leap node add NAME [SEED] + +Create a new configuration file for a node named NAME. + +If specified, the optional argument SEED can be used to seed values in the node configuration file. + +The format is property_name:value. + +For example: `leap node add web1 ip_address:1.2.3.4 services:webapp`. + +To set nested properties, property name can contain '.', like so: `leap node add web1 ssh.port:44` + +Separeate multiple values for a single property with a comma, like so: `leap node add mynode services:webapp,dns` + +**Options** + +* `--local` +Make a local testing node (by automatically assigning the next available local IP address). Local nodes are run as virtual machines on your computer. + + +## leap node init FILTER + +Bootstraps a node or nodes, setting up SSH keys and installing prerequisite packages + +This command prepares a server to be used with the LEAP Platform by saving the server's SSH host key, copying the authorized_keys file, installing packages that are required for deploying, and registering important facts. Node init must be run before deploying to a server, and the server must be running and available via the network. This command only needs to be run once, but there is no harm in running it multiple times. + +**Options** + +* `--ip IPADDRESS` +Override the default SSH IP address. +Default Value: None + +* `--port PORT` +Override the default SSH port. +Default Value: None + +* `--echo` +If set, passwords are visible as you type them (default is hidden) + + +## leap node mv OLD_NAME NEW_NAME + +Renames a node file, and all its related files. + + + +## leap node rm NAME + +Removes all the files related to the node named NAME. + + + +# leap ssh NAME + +Log in to the specified node with an interactive shell. + + + +**Options** + +* `--port arg` +Override ssh port for remote host +Default Value: None + +* `--ssh arg` +Pass through raw options to ssh (e.g. --ssh '-F ~/sshconfig') +Default Value: None + + +# leap test + +Run tests. + + + +## leap test init + +Creates files needed to run tests. + + + +## leap test run + +Run tests. + + + +**Options** + +* `--[no-]continue` +Continue over errors and failures (default is --no-continue). + +Default Command: run diff --git a/doc/guide/config.md b/doc/guide/config.md new file mode 100644 index 00000000..be67e6bd --- /dev/null +++ b/doc/guide/config.md @@ -0,0 +1,263 @@ +@title = "Configuration Files" +@summary = "How to edit configuration files." + +Files +------------------------------------------- + +Here are a list of some of the common files that make up a provider. Except for Leapfile and provider.json, the files are optional. Unless otherwise specified, all file names are relative to the 'provider directory' root (where the Leapfile is). + +`Leapfile` -- If present, this file tells `leap` that the directory is a provider directory. This file is usually empty, but can contain global options. + +`~/.leaprc` -- Evaluated the same as Leapfile, but not committed to source control. + +`provider.json` -- Global options related to this provider. + +`provider.ENVIRONMENT.json` -- Global options for the provider that are applied to only a single environment. + +`common.json` -- All nodes inherit from this file. + +`secrets.json` -- 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 `leap compile` or `leap deploy`. 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. + +`facts.json` -- 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 `leap facts update` to periodically regenerate the facts.json file. + +`nodes/NAME.json` -- The configuration file for node called NAME. + +`services/SERVICE.json` -- The properties in this configuration file are applied to any node that includes SERVICE in its `services` property. + +`services/SERVICE.ENVIRONMENT.json` -- The properties in this configuration file are applied to any node that includes SERVICE in its services and has environment equal to ENVIRONMENT. + +`services/TAG.json` -- The properties in this configuration file are applied to any node that has includes TAG in its `tags` property. + +`services/TAG.ENVIRONMENT.json` -- The properties in this configuration file are applied to any node that has includes TAG in its `tags` property and has `environment` property equal to ENVIRONMENT. + +`files/*` -- Various static files used by the platform (e.g. keys, certificates, webapp customization, etc). + +`users/USER/` -- A directory that stores the public keys of the sysadmin with name USER. This person will have root access to all the servers. + + +Leapfile +------------------------------------------- + +A `Leapfile` defines options for the `leap` command and lives at the root of your provider directory. `Leapfile` is evaluated as ruby, so you can include whatever weird logic you want in this file. In particular, there are several variables you can set that modify the behavior of leap. For example: + + @platform_directory_path = '../leap_platform' + @log = '/var/log/leap.log' + +Additionally, you can create a `~/.leaprc` file that is loaded after `Leapfile` and is evaluated the same way. + +Platform options: + +* `@platform_directory_path` (required). This must be set to the path where `leap_platform` lives. The path may be relative. + +Vagrant options: + +* `@vagrant_network`. Allows you to override the default network used for local nodes. It should include a netmask like `@vagrant_network = '10.0.0.0/24'`. +* `@custom_vagrant_vm_line`. Insert arbitrary text into the auto-generated Vagrantfile. For example, `@custom_vagrant_vm_line = "config.vm.boot_mode = :gui"`. + +Logging options: + +* `@log`. If set, all command invocation and results are logged to the specified file. This is the same as the switch `--log FILE`, except that the command line switch will override the value in the Leapfile. + + +JSON format +------------------------------------------- + +All configuration files, other than `Leapfile`, are in the JSON format. For example: + + { + "key1": "value1", + "key2": "value2" + } + +Keys should match `/[a-z0-9_]/` + +Unlike traditional JSON, comments are allowed. If the first non-whitespace characters are `//` then the line is treated as a comment. + + // this is a comment + { + // this is a comment + "key": "value" // this is an error + } + +Options in the configuration files might be nested hashes, arrays, numbers, strings, or boolean. Numbers and boolean values should **not** be quoted. For example: + + { + "openvpn": { + "ip_address": "1.1.1.1", + "protocols": ["tcp", "udp"], + "ports": [80, 53], + "options": { + "public_ip": false, + "adblock": true + } + } + } + +If the value string is prefixed with an '=' character, the result is evaluated as ruby. For example: + + { + "domain": { + "public": "domain.org" + } + "api_domain": "= 'api.' + domain.public" + } + +In this case, the property "api_domain" will be set to "api.domain.org". So long as you do not create unresolvable circular dependencies, you can reference other properties in evaluated ruby that are themselves evaluated ruby. + +See "Macros" below for information on the special macros available to the evaluated ruby. + +TIP: In rare cases, you might want to force the evaluation of a value to happen in a later pass after most of the other properties have been evaluated. To do this, prefix the value string with "=>" instead of "=". + +Node inheritance +---------------------------------------- + +Every node inherits from common.json and also any of the services or tags attached to the node. Additionally, the `leap_platform` contains a directory `provider_base` that defines the default values for tags, services and common.json. + +Suppose you have a node configuration for `bitmask/nodes/willamette.json` like so: + + { + "services": "webapp", + "tags": ["production", "northwest-us"], + "ip_address": "1.1.1.1" + } + +This node will have hostname "willamette" and it will inherit from the following files (in this order): + +1. common.json + - load defaults: `provider_base/common.json` + - load provider: `bitmask/common.json` +2. service "webapp" + - load defaults: `provider_base/services/webapp.json` + - load provider: `bitmask/services/webapp.json` +3. tag "production" + - load defaults: `provider_base/tags/production.json` + - load provider: `bitmask/tags/production.json` +4. tag "northwest-us" + - load: `bitmask/tags/northwest-us.json` +5. finally, load node "willamette" + - load: `bitmask/nodes/willamette.json` + +The `provider_base` directory is under the `leap_platform` specified in the file `Leapfile`. + +To see all the variables a node has inherited, you could run `leap inspect willamette`. + +Common configuration options +---------------------------------------- + +You can use the command `leap inspect` to see what options are available for a provider, node, service, or tag configuration. For example: + +* `leap inspect common` -- show the options inherited by all nodes. +* `leap inspect --base common` -- show the common.json from `provider_base` without the local `common.json` inheritance applied. +* `leap inspect webapp` -- show all the options available for the service `webapp`. + +Here are some of the more important options you should be aware of: + +* `ip_address` -- Required for all nodes, no default. +* `ssh.port` -- The SSH port you want the node's OpenSSH server to bind to. This is also the default when trying to connect to a node, but if the node currently has OpenSSH running on a different port then run deploy with `--port` to override the `ssh.port` configuration value. +* `mosh.enabled` -- If set to `true`, then mosh will be installed on the server. The default is `false`. + +Macros +---------------------------------------- + +When using evaluated ruby in a JSON configuration file, there are several special macros that are available. These are evaluated in the context of a node (available as the variable `self`). + +The following methods are available to the evaluated ruby: + +`variable.variable` + + > Any variable defined or inherited by a particular node configuration is available by just referencing it using either hash notation or object field notation (e.g. `['domain']['public']` or `domain.public`). Circular references are not allowed, but otherwise it is OK to nest evaluated values in other evaluated values. If a value has not been defined, the hash notation will return nil but the field notation will raise an exception. Properties of services, tags, and the global provider can all be referenced the same way. For example, `global.services['openvpn'].x509.dh`. + +`nodes` + + > A hash of all nodes. This list can be filtered. + +`nodes_like_me` + + > A hash of nodes that have the same deployment tags as the current node (e.g. 'production' or 'local'). + +`global.services` + + > A hash of all services, e.g. `global.services['openvpn']` would return the "openvpn" service. + +`global.tags` + + > A hash of all tags, e.g. `global.tags['production']` would return the "production" tag. + + `global.provider` + + > Can be used to access variables defined in `provider.json`, e.g. `global.provider.contacts.default`. + +`file(filename)` + + > Inserts the full contents of the file. If the file is an erb template, it is rendered. The filename can either be one of the pre-defined file symbols, or it can be a path relative to the "files" directory in your provider instance. E.g, `file :ca_cert` or `files 'ca/ca.crt'`. + +`file_path(filename)` + + > Ensures that the file will get rsynced to the node as an individual file. The value returned by `file_path` is the full path where this file will ultimately live when deploy to the node. e.g. `file_path :ca_cert` or `file_path 'branding/images/logo.png'`. + +`secret(:symbol)` + + > Returns the value of a secret in secrets.json (or creates it if necessary). E.g. `secret :couch_admin_password` + +`hosts_file` + + > Returns a data structure that puppet will use to generate /etc/hosts. Care is taken to use the local IP of other hosts when needed. + +`known_hosts_file` + + > Returns the lines needed in a SSH `known_hosts` file. + +`stunnel_client(node_list, port, options={})` + + > Returns a stunnel configuration data structure for the client side. Argument `node_list` is an `ObjectList` of nodes running stunnel servers. Argument `port` is the real port of the ultimate service running on the servers that the client wants to connect to. + +`stunnel_server(port)` + + > Generates a stunnel server entry. The `port` is the real port targeted service. + +Hash tables +----------------------------------------- + +The macros `nodes`, `nodes_like_me`, `global.services`, and `global.tags` all return a hash table of configuration objects (either nodes, services, or tags). There are several ways to filter and process these hash tables: + +Access an element by name: + + nodes['vpn1'] # returns node named 'vpn1' + global.services['openvpn'] # returns service named 'openvpn' + +Create a new hash table by applying filters: + + nodes[:public_dns => true] # all nodes where public_dns == true + nodes[:services => 'openvpn', 'location.country_code' => 'US'] # openvpn service OR in the US. + nodes[[:services, 'openvpn'], [:services, 'tor']] # services equal to openvpn OR tor + nodes[:services => 'openvpn'][:tags => 'production'] # openvpn AND production + nodes[:name => "!bob"] # all nodes that are NOT named "bob" + +Create an array of values by selecting a single field: + + nodes.field('location.name') + ==> ['seattle', 'istanbul'] + +Create an array of hashes by selecting multiple fields: + + nodes.fields('domain.full', 'ip_address') + ==> [ + {'domain_full' => 'red.bitmask.net', 'ip_address' => '1.1.1.1'}, + {'domain_full' => 'blue.bitmask.net', 'ip_address' => '1.1.1.2'}, + ] + +Create a new hash table of hashes, with only certain fields: + + nodes.pick_fields('domain.full', 'ip_address') + ==> { + "red" => {'domain_full' => 'red.bitmask.net', 'ip_address' => '1.1.1.1'}, + "blue => {'domain_full' => 'blue.bitmask.net', 'ip_address' => '1.1.1.2'}, + } + +With `pick_fields`, if there is only one field, it will generate a simple hash table: + + nodes.pick_fields('ip_address') + ==> { + "red" => '1.1.1.1', + "blue => '1.1.1.2', + } diff --git a/doc/guide/en.haml b/doc/guide/en.haml new file mode 100644 index 00000000..61c24ea8 --- /dev/null +++ b/doc/guide/en.haml @@ -0,0 +1,4 @@ +- @nav_title = "Guide" +- @title = "Platform Guide" + += child_summaries
\ No newline at end of file diff --git a/doc/guide/environments.md b/doc/guide/environments.md new file mode 100644 index 00000000..752e0608 --- /dev/null +++ b/doc/guide/environments.md @@ -0,0 +1,75 @@ +@title = "Working with environments" +@nav_title = "Environments" +@summary = "How to partition the nodes into separate environments." + +With environments, you can divide your nodes into different and entirely separate sets. For example, you might have sets of nodes for 'testing', 'staging' and 'production'. + +Typically, the nodes in one environment are totally isolated from the nodes in a different environment. Each environment will have its own separate database, for example. + +There are a few exceptions to this rule: backup nodes, for example, will by default attempt to back up data from all the environments (excluding local). + +## Assign an environment + +To assign an environment to a node, you just set the `environment` node property. This is typically done with tags, although it is not necessary. For example: + +`tags/production.json` + + { + "environment": "production" + } + +`nodes/mynode.json` + + { + "tags": ["production"] + } + +There are several built-in tags that will apply a value for the environment: + +* `production`: An environment for nodes that are in use by end users. +* `development`: An environment to be used for nodes that are being used for experiments or staging. +* `local`: This environment gets automatically applied to all nodes that run only on local VMs. Nodes with a `local` environment are treated special and excluded from certain calculations. + +You don't need to use these and you can add your own. + +## Environment commands + +* `leap env` -- List the available environments and disply which one is active. +* `leap env pin ENV` -- Pin the current environment to ENV. +* `leap env unpin` -- Remove the environment pin. + +The environment pin is only active for your local machine: it is not recorded in the provider directory and not shared with other users. + +## Environment specific JSON files + +You can add JSON configuration files that are only applied when a specific environment is active. For example, if you create a file `provider.production.json`, these values will only get applied to the `provider.json` file for the `production` environment. + +This will also work for services and tags. For example: + + provider.local.json + services/webapp.development.json + tags/seattle.production.json + +In this example, `local`, `development`, and `production` are the names of environments. + +## Bind an environment to a Platform version + +If you want to ensure that a particular environment is bound to a particular version of the LEAP Platform, you can add a `platform` section to the `provider.ENV.json` file (where ENV is the name of the environment in question). + +The available options are `platform.version`, `platform.branch`, or `platform.commit`. For example: + + { + "platform": { + "version": "1.6.1", + "branch": "develop", + "commit": "5df867fbd3a78ca4160eb54d708d55a7d047bdb2" + } + } + +You can use any combination of `version`, `branch`, and `commit` to specify the binding. The values for `branch` and `commit` only work if the `leap_platform` directory is a git repository. + +The value for `commit` is passed directly through to `git log` to query for a list of acceptable commits. See [[man gitrevisions => https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html#_specifying_ranges]] to see how to specify ranges. For example: + +* `HEAD^..HEAD` - current commit must be head of the branch. +* `3172444652af71bd771609d6b80258e70cc82ce9..HEAD` - current commit must be after 3172444652af71bd771609d6b80258e70cc82ce9. +* `refs/tags/0.6.0rc1..refs/tags/0.6.0rc2` - current commit must be after tag 0.6.0rc1 and before or including tag 0.6.0rc2.
\ No newline at end of file diff --git a/doc/guide/keys-and-certificates.md b/doc/guide/keys-and-certificates.md new file mode 100644 index 00000000..aef02ac6 --- /dev/null +++ b/doc/guide/keys-and-certificates.md @@ -0,0 +1,194 @@ +@title = "Keys and Certificates" +@summary = "Working with SSH keys, secrets, and X.509 certificates." + +Working with SSH +================================ + +Whenever the `leap` command nees to push changes to a node or gather information from a node, it tunnels this command over SSH. Another way to put this: the security of your servers rests entirely on SSH. Because of this, it is important that you understand how `leap` uses SSH. + +SSH related files +------------------------------- + +Assuming your provider directory is called 'provider': + +* `provider/nodes/crow/crow_ssh.pub` -- The public SSH host key for node 'crow'. +* `provider/users/alice/alice_ssh.pub` -- The public SSH user key for user 'alice'. Anyone with the private key that corresponds to this public key will have root access to all nodes. +* `provider/files/ssh/known_hosts` -- An autogenerated known_hosts, built from combining `provider/nodes/*/*_ssh.pub`. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate `known_hosts` and then run `leap compile`. +* `provider/files/ssh/authorized_keys` -- An autogenerated list of all the user SSH keys with root access to the notes. It is created from `provider/users/*/*_ssh.pub`. You must not edit this file directly. If you need to change it, remove or change one of the files that is used to generate `authorized_keys` and then run `leap compile`. + +All of these files should be committed to source control. + +If you rename, remove, or add a node with `leap node [mv|add|rm]` the SSH key files and the `known_hosts` file will get properly updated. + +SSH and local nodes +----------------------------- + +Local nodes are run as Vagrant virtual machines. The `leap` command handles SSH slightly differently for these nodes. + +Basically, all the SSH security is turned off for local nodes. Since local nodes only exist for a short time on your computer and can't be reached from the internet, this is not a problem. + +Specifically, for local nodes: + +1. `known_hosts` is never updated with local node keys, since the SSH public key of a local node is different for each user. +2. `leap` entirely skips the checking of host keys when connecting with a local node. +3. `leap` adds the public Vagrant SSH key to the list of SSH keys for a user. The public Vagrant SSH key is a shared and insecure key that has root access to most Vagrant virtual machines. + +When SSH host key changes +------------------------------- + +If the host key for a node has changed, you will get an error "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED". + +To fix this, you need to remove the file `files/nodes/stompy/stompy_ssh.pub` and run `leap node init stompy`, where the node's name is 'stompy'. **Only do this if you are ABSOLUTELY CERTAIN that the node's SSH host key has changed**. + +Changing the SSH port +-------------------------------- + +Suppose you have a node `blinky` that has SSH listening on port 22 and you want to make it port 2200. + +First, modify the configuration for `blinky` to specify the variable `ssh.port` as 2200. Usually, this is done in `common.json` or in a tag file. + +For example, you could put this in `tags/production.json`: + + { + "ssh": { + "port": 2200 + } + } + +Run `leap compile` and open `hiera/blinky.yaml` to confirm that `ssh.port` is set to 2200. The port number must be specified as a number, not a string (no quotes). + +Then, you need to deploy this change so that SSH will bind to 2200. You cannot simply run `leap deploy blinky` because this command will default to using the variable `ssh.port` which is now `2200` but SSH on the node is still bound to 22. + +So, you manually override the port in the deploy command, using the old port: + + leap deploy --port 22 blinky + +Afterwards, SSH on `blinky` should be listening on port 2200 and you can just run `leap deploy blinky` from then on. + +Sysadmins with multiple SSH keys +----------------------------------- + +The command `leap add-user --self` allows only one SSH key. If you want to specify more than one key for a user, you can do it manually: + + users/userx/userx_ssh.pub + users/userx/otherkey_ssh.pub + +All keys matching 'userx/*_ssh.pub' will be usable. + +Removing sysadmin access +-------------------------------- + +Suppose you want to remove `userx` from having any further ssh access to the servers. Do this: + + rm -r users/userx + leap deploy + +X.509 Certificates +================================ + +Configuration options +------------------------------------------- + +The `ca` option in provider.json provides settings used when generating CAs and certificates. The defaults are as follows: + + { + "ca": { + "name": "= global.provider.ca.organization + ' Root CA'", + "organization": "= global.provider.name[global.provider.default_language]", + "organizational_unit": "= 'https://' + global.provider.domain", + "bit_size": 4096, + "digest": "SHA256", + "life_span": "10y", + "server_certificates": { + "bit_size": 2048, + "digest": "SHA256", + "life_span": "1y" + }, + "client_certificates": { + "bit_size": 2048, + "digest": "SHA256", + "life_span": "2m", + "limited_prefix": "LIMITED", + "unlimited_prefix": "UNLIMITED" + } + } + } + +You should not need to override these defaults in your own provider.json, but you can if you want to. To see what values are used for your provider, run `leap inspect provider.json`. + +NOTE: A certificate `bit_size` greater than 2048 will probably not be recognized by most commercial CAs. + +Certificate Authorities +----------------------------------------- + +There are three x.509 certificate authorities (CA) associated with your provider: + +1. **Commercial CA:** It is strongly recommended that you purchase a commercial cert for your primary domain. The goal of platform is to not depend on the commercial CA system, but it does increase security and usability if you purchase a certificate. The cert for the commercial CA must live at `files/cert/commercial_ca.crt`. +2. **Server CA:** This is a self-signed CA responsible for signing all the **server** certificates. The private key lives at `files/ca/ca.key` and the public cert lives at `files/ca/ca.crt`. The key is very sensitive information and must be kept private. The public cert is distributed publicly. +3. **Client CA:** This is a self-signed CA responsible for signing all the **client** certificates. The private key lives at `files/ca/client_ca.key` and the public cert lives at `files/ca/client_ca.crt`. Neither file is distribute publicly. It is not a big deal if the private key for the client CA is compromised, you can just generate a new one and re-deploy. + +To generate both the Server CA and the Client CA, run the command: + + leap cert ca + +Server certificates +----------------------------------- + +Most every server in your service provider will have a x.509 certificate, generated by the `leap` command using the Server CA. Whenever you modify any settings of a node that might affect it's certificate (like changing the IP address, hostname, or settings in provider.json), you can magically regenerate all the certs that need to be regenerated with this command: + + leap cert update + +Run `leap help cert update` for notes on usage options. + +Because the server certificates are generated locally on your personal machine, the private key for the Server CA need never be put on any server. It is up to you to keep this file secure. + +Client certificates +-------------------------------- + +Every leap client gets its own time-limited client certificate. This cert is use to connect to the OpenVPN gateway (and probably other things in the future). It is generated on the fly by the webapp using the Client CA. + +To make this work, the private key of the Client CA is made available to the webapp. This might seem bad, but compromise of the Client CA simply allows the attacker to use the OpenVPN gateways without paying. In the future, we plan to add a command to automatically regenerate the Client CA periodically. + +There are two types of client certificates: limited and unlimited. A client using a limited cert will have its bandwidth limited to the rate specified by `provider.service.bandwidth_limit` (in Bytes per second). An unlimited cert is given to the user if they authenticate and the user's service level matches one configured in `provider.service.levels` without bandwidth limits. Otherwise, the user is given a limited client cert. + +Commercial certificates +----------------------------------- + +We strongly recommend that you use a commercial signed server certificate for your primary domain (in other words, a certificate with a common name matching whatever you have configured for `provider.domain`). This provides several benefits: + +1. When users visit your website, they don't get a scary notice that something is wrong. +2. When a user runs the LEAP client, selecting your service provider will not cause a warning message. +3. When other providers first discover your provider, they are more likely to trust your provider key if it is fetched over a commercially verified link. + +The LEAP platform is designed so that it assumes you are using a commercial cert for the primary domain of your provider, but all other servers are assumed to use non-commercial certs signed by the Server CA you create. + +To generate a CSR, run: + + leap cert csr + +This command will generate the CSR and private key matching `provider.domain` (you can change the domain with `--domain=DOMAIN` switch). It also generates a server certificate signed with the Server CA. You should delete this certificate and replace it with a real one once it is created by your commercial CA. + +The related commercial cert files are: + + files/ + cert/ + domain.org.crt # Server certificate for domain.org, obtained by commercial CA. + domain.org.csr # Certificate signing request + domain.org.key # Private key for you certificate + commercial_ca.crt # The CA cert obtained from the commercial CA. + +The private key file is extremely sensitive and care should be taken with its provenance. + +If your commercial CA has a chained CA cert, you should be OK if you just put the **last** cert in the chain into the `commercial_ca.crt` file. This only works if the other CAs in the chain have certs in the debian package `ca-certificates`, which is the case for almost all CAs. + +If you want to add additional fields to the CSR, like country, city, or locality, you can configure these values in provider.json like so: + + "ca": { + "server_certificates": { + "country": "US", + "state": "Washington", + "locality": "Seattle" + } + } + +If they are not present, the CSR will be created without them. diff --git a/doc/guide/miscellaneous.md b/doc/guide/miscellaneous.md new file mode 100644 index 00000000..c38c007c --- /dev/null +++ b/doc/guide/miscellaneous.md @@ -0,0 +1,14 @@ +@title = "Miscellaneous" +@summary = "Miscellaneous commands you may need to know." + +Facts +============================== + +There are a few cases when we must gather internal data from a node before we can successfully deploy to other nodes. This is what `facts.json` is for. It stores a snapshot of certain facts about each node, as needed. Entries in `facts.json` are updated automatically when you initialize, rename, or remove a node. To manually force a full update of `facts.json`, run: + + leap facts update FILTER + +Run `leap help facts update` for more information. + +The file `facts.json` should be committed to source control. You might not have a `facts.json` if one is not required for your provider. + diff --git a/doc/guide/nodes.md b/doc/guide/nodes.md new file mode 100644 index 00000000..cf225449 --- /dev/null +++ b/doc/guide/nodes.md @@ -0,0 +1,187 @@ +@title = "Nodes" +@summary = "Working with nodes, services, tags, and locations." + +Node types +================================ + +Every node has one or more services that determines the node's function within your provider's infrastructure. + +When adding a new node to your provider, you should ask yourself four questions: + +* **many or few?** Some services benefit from having many nodes, while some services are best run on only one or two nodes. +* **required or optional?** Some services are required, while others can be left out. +* **who does the node communicate with?** Some services communicate very heavily with other particular services. Nodes running these services should be close together. +* **public or private?** Some services communicate with the public internet, while others only need to communicate with other nodes in the infrastructure. + +Brief overview of the services: + +* **webapp**: The web application. Runs both webapp control panel for users and admins as well as the REST API that the client uses. Needs to communicate heavily with `couchdb` nodes. You need at least one, good to have two for redundancy. The webapp does not get a lot of traffic, so you will not need many. +* **couchdb**: The database for users and user data. You can get away with just one, but for proper redundancy you should have at least three. Communicates heavily with `webapp`, `mx`, and `soledad` nodes. +* **soledad**: Handles the data syncing with clients. Typically combined with `couchdb` service, since it communicates heavily with couchdb. +* **mx**: Incoming and outgoing MX servers. Communicates with the public internet, clients, and `couchdb` nodes. +* **openvpn**: OpenVPN gateway for clients. You need at least one, but want as many as needed to support the bandwidth your users are doing. The `openvpn` nodes are autonomous and don't need to communicate with any other nodes. Often combined with `tor` service. +* **monitor**: Internal service to monitor all the other nodes. Currently, you can have zero or one `monitor` service defined. It is required that the monitor be on the webapp node. It was not designed to be run as a separate node service. +* **tor**: Sets up a tor exit node, unconnected to any other service. +* **dns**: Not yet implemented. + +Webapp +----------------------------------- + +The webapp node is responsible for both the user face web application and the API that the client interacts with. + +Some users can be "admins" with special powers to answer tickets and close accounts. To make an account into an administrator, you need to configure the `webapp.admins` property with an array of user names. + +For example, to make users `alice` and `bob` into admins, create a file `services/webapp.json` with the following content: + + { + "webapp": { + "admins": ["bob", "alice"] + } + } + +And then redeploy to all webapp nodes: + + leap deploy webapp + +By putting this in `services/webapp.json`, you will ensure that all webapp nodes inherit the value for `webapp.admins`. + +Services +================================ + +What nodes do you need for a provider that offers particular services? + +<table class="table table-striped"> +<tr> + <th>Node Type</th> + <th>VPN Service</th> + <th>Email Service</th> + <th>Notes</th> +</tr> +<tr> + <td>webapp</td> + <td>required</td> + <td>required</td> + <td></td> +</tr> +<tr> + <td>couchdb</td> + <td>required</td> + <td>required</td> +<td></td> +</tr> +<tr> + <td>soledad</td> + <td>not used</td> + <td>required</td> +<td></td> +</tr> +<tr> + <td>mx</td> + <td>not used</td> + <td>required</td> + <td></td> +</tr> +<tr> + <td>openvpn</td> + <td>required</td> + <td>not used</td> + <td></td> +</tr> +<tr> + <td>monitor</td> + <td>optional</td> + <td>optional</td> + <td>This service must be on the webapp node</td> +</tr> +<tr> + <td>tor</td> + <td>optional</td> + <td>optional</td> + <td></td> +</tr> +</table> + +Locations +================================ + +All nodes should have a `location.name` specified, and optionally additional information about the location, like the time zone. This location information is used for two things: + +* Determine which nodes can, or must, communicate with one another via a local network. The way some virtualization environments work, like OpenStack, requires that nodes communicate via the local network if they are on the same network. +* Allows the client to prefer connections to nodes that are closer in physical proximity to the user. This is particularly important for OpenVPN nodes. + +The location stanza in a node's config file looks like this: + + { + "location": { + "id": "ankara", + "name": "Ankara", + "country_code": "TR", + "timezone": "+2", + "hemisphere": "N" + } + } + +The fields: + +* `id`: An internal handle to use for this location. If two nodes have match `location.id`, then they are treated as being on a local network with one another. This value defaults to downcase and underscore of `location.name`. +* `name`: Can be anything, might be displayed to the user in the client if they choose to manually select a gateway. +* `country_code`: The [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1) two letter country code. +* `timezone`: The timezone expressed as an offset from UTC (in standard time, not daylight savings). You can look up the timezone using this [handy map](http://www.timeanddate.com/time/map/). +* `hemisphere`: This should be "S" for all servers in South America, Africa, or Australia. Otherwise, this should be "N". + +These location options are very imprecise, but good enough for most usage. The client often does not know its own location precisely either. Instead, the client makes an educated guess at location based on the OS's timezone and locale. + +If you have multiple nodes in a single location, it is best to use a tag for the location. For example: + +`tags/ankara.json`: + + { + "location": { + "name": "Ankara", + "country_code": "TR", + "timezone": "+2", + "hemisphere": "N" + } + } + +`nodes/vpngateway.json`: + + { + "services": "openvpn", + "tags": ["production", "ankara"], + "ip_address": "1.1.1.1", + "openvpn": { + "gateway_address": "1.1.1.2" + } + } + +Unless you are using OpenStack or AWS, setting `location` for nodes is not required. It is, however, highly recommended. + +Disabling Nodes +===================================== + +There are two ways to temporarily disable a node: + +**Option 1: disabled environment** + +You can assign an environment to the node that marks it as disabled. Then, if you use environment pinning, the node will be ignored when you deploy. For example: + + { + "environment": "disabled" + } + +Then use `leap env pin ENV` to pin the environment to something other than 'disabled'. This only works if all the other nodes are also assigned to some environment. + +**Option 2: enabled == false** + +If a node has a property `enabled` set to false, then the `leap` command will skip over the node and pretend that it does not exist. For example: + + { + "ip_address": "1.1.1.1", + "services": ["openvpn"], + "enabled": false + } + +**Options 3: no-deploy** + +If the file `/etc/leap/no-deploy` exists on a node, then when you run the commmand `leap deploy` it will halt and prevent a deploy from going through (if the node was going to be included in the deploy). diff --git a/doc/service-diagram.odg b/doc/service-diagram.odg Binary files differnew file mode 100644 index 00000000..09265c2d --- /dev/null +++ b/doc/service-diagram.odg diff --git a/doc/service-diagram.png b/doc/service-diagram.png Binary files differnew file mode 100644 index 00000000..85e62436 --- /dev/null +++ b/doc/service-diagram.png diff --git a/doc/troubleshooting/en.haml b/doc/troubleshooting/en.haml new file mode 100644 index 00000000..f0f1359c --- /dev/null +++ b/doc/troubleshooting/en.haml @@ -0,0 +1,3 @@ +- @title = "Troubleshooting" + += child_summaries
\ No newline at end of file diff --git a/doc/troubleshooting/known-issues.md b/doc/troubleshooting/known-issues.md new file mode 100644 index 00000000..4defc886 --- /dev/null +++ b/doc/troubleshooting/known-issues.md @@ -0,0 +1,115 @@ +@title = 'Leap Platform Release Notes' +@nav_title = 'Known issues' +@summary = 'Known issues in the Leap Platform.' +@toc = true + +Here you can find documentation about known issues and potential work-arounds in the current Leap Platform release. + +0.6.0 +============== + +Upgrading +------------------ + +Upgrade your leap_platform to 0.6 and make sure you have the latest leap_cli. + +**Update leap_platform:** + + cd leap_platform + git pull + git checkout -b 0.6.0 0.6.0 + +**Update leap_cli:** + +If it is installed as a gem from rubygems: + + sudo gem update leap_cli + +If it is installed as a gem from source: + + cd leap_cli + git pull + git checkout master + rake build + sudo rake install + +If it is run directly from source: + + cd leap_cli + git pull + git checkout master + +To upgrade: + + leap --version # must be at least 1.6.2 + leap cert update + leap deploy + leap test + +If the tests fail, try deploying again. If a test fails because there are two tapicero daemons running, you need to ssh into the server, kill all the tapicero daemons manually, and then try deploying again (sometimes the daemon from platform 0.5 would put its PID file in an odd place). + +OpenVPN +------------------ + +On deployment to a openvpn node, if the following happens: + + - err: /Stage[main]/Site_openvpn/Service[openvpn]/ensure: change from stopped to running failed: Could not start Service[openvpn]: Execution of '/etc/init.d/openvpn start' returned 1: at /srv/leap/puppet/modules/site_openvpn/manifests/init.pp:189 + +this is likely the result of a kernel upgrade that happened during the deployment, requiring that the machine be restarted before this service can start. To confirm this, login to the node (leap ssh <nodename>) and look at the end of the /var/log/daemon.log: + + # tail /var/log/daemon.log + Nov 22 19:04:15 snail ovpn-udp_config[16173]: ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such device (errno=19) + Nov 22 19:04:15 snail ovpn-udp_config[16173]: Exiting due to fatal error + +if you see this error, simply restart the node. + +CouchDB +--------------------- + +At the moment, we strongly advise only have one bigcouch server for stability purposes. + +With multiple couch nodes (not recommended at this time), in some scenarios, such as when certain components are unavailable, the couchdb syncing will be broken. When things are brought back to normal, shortly after restart, the nodes will attempt to resync all their data, and can fail to complete this process because they run out of file descriptors. A symptom of this is the webapp wont allow you to register or login, the /opt/bigcouch/var/log/bigcouch.log is huge with a lot of errors that include (over multiple lines): {error, emfile}}. We have raised the limits for available file descriptors to bigcouch to try and accommodate for this situation, but if you still experience it, you may need to increase your /etc/sv/bigcouch/run ulimit values and restart bigcouch while monitoring the open file descriptors. We hope that in the next platform release, a newer couchdb will be better at handling these resources. + +You can also see the number of file descriptors in use by doing: + + # watch -n1 -d lsof -p `pidof beam`|wc -l + +The command `leap db destroy` will not automatically recreate new databases. You must run `leap deploy` afterwards for this. + +User setup and ssh +------------------ + +At the moment, it is only possible to add an admin who will have access to all LEAP servers (see: https://leap.se/code/issues/2280) + +The command `leap add-user --self` allows only one SSH key. If you want to specify more than one key for a user, you can do it manually: + + users/userx/userx_ssh.pub + users/userx/otherkey_ssh.pub + +All keys matching 'userx/*_ssh.pub' will be used for that user. + +Deploying +--------- + +If you have any errors during a run, please try to deploy again as this often solves non-deterministic issues that were not uncovered in our testing. Please re-deploy with `leap -v2 deploy` to get more verbose logs and capture the complete output to provide to us for debugging. + +If when deploying your debian mirror fails for some reason, network anomoly or the mirror itself is out of date, then platform deployment will not succeed properly. Check the mirror is up and try to deploy again when it is resolved (see: https://leap.se/code/issues/1091) + +Deployment gives 'error: in `%`: too few arguments (ArgumentError)' - this is because you attempted to do a deploy before initializing a node, please initialize the node first and then do a deploy afterwards (see: https://leap.se/code/issues/2550) + +This release has no ability to custom configure apt sources or proxies (see: https://leap.se/code/issues/1971) + +When running a deploy at a verbosity level of 2 and above, you will notice puppet deprecation warnings, these are known and we are working on fixing them + +IPv6 +---- + +As of this release, IPv6 is not supported by the VPN configuration. If IPv6 is detected on your network as a client, it is blocked and instead it should revert to IPv4. We plan on adding IPv6 support in an upcoming release. + + +Special Environments +-------------------- + +When deploying to OpenStack release "nova" or newer, you will need to do an initial deploy, then when it has finished run `leap facts update` and then deploy again (see: https://leap.se/code/issues/3020) + +It is not possible to actually use the EIP openvpn server on vagrant nodes (see: https://leap.se/code/issues/2401) diff --git a/doc/troubleshooting/tests.md b/doc/troubleshooting/tests.md new file mode 100644 index 00000000..b85c19d2 --- /dev/null +++ b/doc/troubleshooting/tests.md @@ -0,0 +1,70 @@ +@title = 'Tests and Monitoring' +@summary = 'Testing and monitoring your infrastructure.' +@toc = true + +## Troubleshooting Tests + +At any time, you can run troubleshooting tests on the nodes of your provider infrastructure to check to see if things seem to be working correctly. If there is a problem, these tests should help you narrow down precisely where the problem is. + +To run tests on FILTER node list: + + leap test run FILTER + +For example, you can also test a single node (`leap test elephant`); test a specific environment (`leap test development`), or any tag (`leap test soledad`). + +Alternately, you can run test on all nodes (probably only useful if you have pinned the environment): + + leap test + +The tests that are performed are located in the platform under the tests directory. + +## Testing with the bitmask client + +Download the provider ca: + + wget --no-check-certificate https://example.org/ca.crt -O /tmp/ca.crt + +Start bitmask: + + bitmask --ca-cert-file /tmp/ca.crt + +## Testing Recieving Mail + +Use i.e. swaks to send a testmail + + swaks -f noone@example.org -t testuser@example.org -s example.org + +and use your favorite mail client to examine your inbox. + +You can also use [offlineimap](http://offlineimap.org/) to fetch mails: + + offlineimap -c vagrant/.offlineimaprc.example.org + +WARNING: Use offlineimap *only* for testing/debugging, +because it will save the mails *decrypted* locally to +your disk ! + +## Monitoring + +In order to set up a monitoring node, you simply add a `monitor` service tag to the node configuration file. It could be combined with any other service, but we propose that you add it to the webapp node, as this already is public accessible via HTTPS. + +After deploying, this node will regularly poll every node to ask for the status of various health checks. These health checks include the checks run with `leap test`, plus many others. + +We use [Nagios](http://www.nagios.org/) together with [Check MK agent](https://en.wikipedia.org/wiki/Check_MK) for running checks on remote hosts. + +One nagios installation will monitor all nodes in all your environments. You can log into the monitoring web interface via [https://DOMAIN/nagios3/](https://DOMAIN/nagios3/). The username is `nagiosadmin` and the password is found in the secrets.json file in your provider directory. +Nagios will send out mails to the `contacts` address provided in `provider.json`. + + +## Nagios Frontents + +There are other ways to check and get notified by Nagios besides regularly checking the Nagios webinterface or reading email notifications. Check out the [Frontends (GUIs and CLIs)](http://exchange.nagios.org/directory/Addons/Frontends-%28GUIs-and-CLIs%29) on the Nagios project website. +A recommended status tray application is [Nagstamon](https://nagstamon.ifw-dresden.de/), which is available for Linux, MacOS X and Windows. It can not only notify you of hosts/services failures, you can also acknoledge or recheck these with it. + +### Log Monitoring + +At the moment, we use [check-mk-agent-logwatch](https://mathias-kettner.de/checkmk_check_logwatch.html) for searching logs for irregularities. +Logs are parsed for patterns using a blacklist, and are stored in `/var/lib/check_mk/logwatch/<Nodename>`. + +In order to "acknowledge" a log warning, you need to log in to the monitoring server, and delete the corresponding file in `/var/lib/check_mk/logwatch/<Nodename>`. This should be done via the nagios webinterface in the future. + diff --git a/doc/troubleshooting/vagrant.md b/doc/troubleshooting/vagrant.md new file mode 100644 index 00000000..ad284161 --- /dev/null +++ b/doc/troubleshooting/vagrant.md @@ -0,0 +1,45 @@ +@title = 'LEAP Platform Vagrant testing' +@nav_title = 'Vagrant Integration' +@summary = 'Testing your provider with Vagrant' + +Setting up Vagrant for a testing the platform +============================================= + +There are two ways you can setup leap platform using vagrant. + +Using the Vagrantfile provided by Leap Platform +----------------------------------------------- + +This is by far the easiest way. It will install a single node mail server in the default +configuration with one single command. + +Clone the platform with + + git clone https://github.com/leapcode/leap_platform.git + +Start the vagrant box with + + cd leap_platform + vagrant up + +Follow the instructions how to configure your `/etc/hosts` +in order to use the provider! + +You can login via ssh with the systemuser `vagrant` and the same password. + +There are 2 users preconfigured: + +. `testuser` with pw `hallo123` +. `testadmin` with pw `hallo123` + + +Use the leap_cli vagrant integration +------------------------------------ + +Install leap_cli and leap_platform on your host, configure a provider from scratch and use the `leap local` commands to manage your vagrant node(s). + +See https://leap.se/en/docs/platform/development how to use the leap_cli vagrant +integration and https://leap.se/en/docs/platform/tutorials/single-node-email how +to setup a single node mail server. + + diff --git a/doc/troubleshooting/where-to-look.md b/doc/troubleshooting/where-to-look.md new file mode 100644 index 00000000..fbd95931 --- /dev/null +++ b/doc/troubleshooting/where-to-look.md @@ -0,0 +1,249 @@ +@title = 'Where to look for errors' +@nav_title = 'Where to look' +@toc = true + + +General +======= + +* Please increase verbosity when debugging / filing issues in our issue tracker. You can do this with adding i.e. `-v 5` after the `leap` cmd, i.e. `leap -v 2 deploy`. + +Webapp +====== + +Places to look for errors +------------------------- + +* `/var/log/apache2/error.log` +* `/srv/leap/webapp/log/production.log` +* `/var/log/syslog` (watch out for stunnel issues) +* `/var/log/leap/*` + +Is haproxy ok ? +--------------- + + + curl -s -X GET "http://127.0.0.1:4096" + +Is couchdb accessible through stunnel ? +--------------------------------------- + +* Depending on how many couch nodes you have, increase the port for every test + (see /etc/haproxy/haproxy.cfg for the server/port mapping): + + + curl -s -X GET "http://127.0.0.1:4000" + curl -s -X GET "http://127.0.0.1:4001" + ... + + +Check couchdb acl as admin +-------------------------- + + mkdir /etc/couchdb + cat /srv/leap/webapp/config/couchdb.yml.admin # see username and password + echo "machine 127.0.0.1 login admin password <PASSWORD>" > /etc/couchdb/couchdb-admin.netrc + chmod 600 /etc/couchdb/couchdb-admin.netrc + + curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096" + curl -s --netrc-file /etc/couchdb/couchdb-admin.netrc -X GET "http://127.0.0.1:4096/_all_dbs" + +Check couchdb acl as unpriviledged user +--------------------------------------- + + cat /srv/leap/webapp/config/couchdb.yml # see username and password + echo "machine 127.0.0.1 login webapp password <PASSWORD>" > /etc/couchdb/couchdb-webapp.netrc + chmod 600 /etc/couchdb/couchdb-webapp.netrc + + curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096" + curl -s --netrc-file /etc/couchdb/couchdb-webapp.netrc -X GET "http://127.0.0.1:4096/_all_dbs" + + +Check client config files +------------------------- + + https://example.net/provider.json + https://example.net/1/config/smtp-service.json + https://example.net/1/config/soledad-service.json + https://example.net/1/config/eip-service.json + + +Soledad +======= + + /var/log/soledad.log + + +Couchdb +======= + +Places to look for errors +------------------------- + +* `/opt/bigcouch/var/log/bigcouch.log` +* `/var/log/syslog` (watch out for stunnel issues) + + + +Bigcouch membership +------------------- + +* All nodes configured for the provider should appear here: + +<pre> + curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET 'http://127.0.0.1:5986/nodes/_all_docs' +</pre> + +* All configured nodes should show up under "cluster_nodes", and the ones online and communicating with each other should appear under "all_nodes". This example output shows the configured cluster nodes `couch1.bitmask.net` and `couch2.bitmask.net`, but `couch2.bitmask.net` is currently not accessible from `couch1.bitmask.net` + + +<pre> + curl -s --netrc-file /etc/couchdb/couchdb.netrc 'http://127.0.0.1:5984/_membership' + {"all_nodes":["bigcouch@couch1.bitmask.net"],"cluster_nodes":["bigcouch@couch1.bitmask.net","bigcouch@couch2.bitmask.net"]} +</pre> + +* Sometimes a `/etc/init.d/bigcouch restart` on all nodes is needed, to register new nodes + +Databases +--------- + +* Following output shows all neccessary DBs that should be present. Note that the `user-0123456....` DBs are the data stores for a particular user. + +<pre> + curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET 'http://127.0.0.1:5984/_all_dbs' + ["customers","identities","sessions","shared","tickets","tokens","user-0","user-9d34680b01074c75c2ec58c7321f540c","user-9d34680b01074c75c2ec58c7325fb7ff","users"] +</pre> + + + + +Design Documents +---------------- + +* Is User `_design doc` available ? + + +<pre> + curl -s --netrc-file /etc/couchdb/couchdb.netrc -X GET "http://127.0.0.1:5984/users/_design/User" +</pre> + +Is couchdb cluster backend accessible through stunnel ? +------------------------------------------------------- + +* Find out how many connections are set up for the couchdb cluster backend: + +<pre> + grep "accept = 127.0.0.1" /etc/stunnel/* +</pre> + + +* Now connect to all of those local endpoints to see if they up. All these tests should return "localhost [127.0.0.1] 4000 (?) open" + +<pre> + nc -v 127.0.0.1 4000 + nc -v 127.0.0.1 4001 + ... +</pre> + + +MX +== + +Places to look for errors +------------------------- + +* `/var/log/mail.log` +* `/var/log/leap_mx.log` +* `/var/log/syslog` (watch out for stunnel issues) + +Is couchdb accessible through stunnel ? +--------------------------------------- + +* Depending on how many couch nodes you have, increase the port for every test + (see /etc/haproxy/haproxy.cfg for the server/port mapping): + + + curl -s -X GET "http://127.0.0.1:4000" + curl -s -X GET "http://127.0.0.1:4001" + ... + +Query leap-mx +------------- + +* for useraccount + + +<pre> + postmap -v -q "joe@dev.bitmask.net" tcp:localhost:2244 + ... + postmap: dict_tcp_lookup: send: get jow@dev.bitmask.net + postmap: dict_tcp_lookup: recv: 200 + ... +</pre> + +* for mailalias + + +<pre> + postmap -v -q "joe@dev.bitmask.net" tcp:localhost:4242 + ... + postmap: dict_tcp_lookup: send: get joe@dev.bitmask.net + postmap: dict_tcp_lookup: recv: 200 f01bc1c70de7d7d80bc1ad77d987e73a + postmap: dict_tcp_lookup: found: f01bc1c70de7d7d80bc1ad77d987e73a + f01bc1c70de7d7d80bc1ad77d987e73a + ... +</pre> + + +Check couchdb acl as unpriviledged user +--------------------------------------- + + + + cat /etc/leap/mx.conf # see username and password + echo "machine 127.0.0.1 login leap_mx password <PASSWORD>" > /etc/couchdb/couchdb-leap_mx.netrc + chmod 600 /etc/couchdb/couchdb-leap_mx.netrc + + curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/_all_dbs" # pick one "user-<hash>" db + curl -s --netrc-file /etc/couchdb/couchdb-leap_mx.netrc -X GET "http://127.0.0.1:4096/user-de9c77a3d7efbc779c6c20da88e8fb9c" + + +* you may check multiple times, cause 127.0.0.1:4096 is haproxy load-balancing the different couchdb nodes + + +Mailspool +--------- + +* Any file in the leap_mx mailspool longer for a few seconds ? + + + +<pre> + ls -la /var/mail/vmail/Maildir/cur/ +</pre> + +* Any mails in postfix mailspool longer than a few seconds ? + +<pre> + mailq +</pre> + + + +Testing mail delivery +--------------------- + + swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 25 + swaks -f varac@cdev.bitmask.net -t varac@cdev.bitmask.net -s chipmonk.cdev.bitmask.net --port 465 --tlsc + swaks -f alice@example.org -t bob@example.net -s mx1.example.net --port 587 --tls + + +VPN +=== + +Places to look for errors +------------------------- + +* `/var/log/syslog` (watch out for openvpn issues) + + diff --git a/doc/tutorials/configure-provider.md b/doc/tutorials/configure-provider.md new file mode 100644 index 00000000..969d541b --- /dev/null +++ b/doc/tutorials/configure-provider.md @@ -0,0 +1,31 @@ +@title = 'Configure provider tutorial' +@nav_title = 'Configure Provider' +@summary = 'Explore how to configure your provider after the initial setup' + + +Edit provider.json configuration +-------------------------------------- + +There are a few required settings in provider.json. At a minimum, you must have: + + { + "domain": "example.org", + "name": "Example", + "contacts": { + "default": "email1@example.org" + } + } + +For a full list of possible settings, you can use `leap inspect` to see how provider.json is evaluated after including the inherited defaults: + + $ leap inspect provider.json + + +Examine Certs +============= + +To see details about the keys and certs that the prior two commands created, you can use `leap inspect` like so: + + $ leap inspect files/ca/ca.crt + +NOTE: the files `files/ca/*.key` are extremely sensitive and must be carefully protected. The other key files are much less sensitive and can simply be regenerated if needed. diff --git a/doc/tutorials/en.haml b/doc/tutorials/en.haml new file mode 100644 index 00000000..1c73fc0f --- /dev/null +++ b/doc/tutorials/en.haml @@ -0,0 +1,4 @@ +- @nav_title = "Tutorials" +- @title = "Platform Tutorials" + += child_summaries
\ No newline at end of file diff --git a/doc/tutorials/quick-start.md b/doc/tutorials/quick-start.md new file mode 100644 index 00000000..a92cc9da --- /dev/null +++ b/doc/tutorials/quick-start.md @@ -0,0 +1,385 @@ +@title = 'Quick Start Tutorial' +@nav_title = 'Quick Start Tutorial' +@summary = 'This tutorial walks you through the initial process of creating and deploying a minimal service provider running the LEAP Platform. This Quick Start guide will guide you through building a three node OpenVPN provider.' + + +Our goal +------------------ + +We are going to create a minimal LEAP provider offering OpenVPN service. This basic setup can be expanded by adding more OpenVPN nodes to increase capacity or geographical diversity, or more webapp nodes to increase availability (at the moment, a single couchdb and single webapp server are all that is supported, and performance wise, are more than enough for most usage, since they are only lightly used). At the moment, we strongly advise only have one couchdb server for stability purposes. + +Our goal is something like this: + + $ leap list + NODES SERVICES TAGS + cheetah couchdb production + wildebeest webapp production + ostrich openvpn production + +NOTE: You won't be able to run that `leap list` command yet, not until we actually create the node configurations. + +Requirements +------------ + +In order to complete this Quick Start, you will need a few things: + +* You will need three real or paravirtualized virtual machines (KVM, Xen, Openstack, Amazon, but not Vagrant - sorry) that have a basic Debian Stable installed. If you allocate 20G of disk space to each node for the system, after this process is completed, you will have used less than 10% of that disk space. If you allocate 2 CPUs and 8G of memory to each node, that should be more than enough to begin with. +* You should be able to SSH into them remotely, and know their root password, IP addresses and their SSH host keys +* You will need four different IPs. Each node gets a primary IP, and the OpenVPN gateway additionally needs a gateway IP. +* The ability to create/modify DNS entries for your domain is preferable, but not needed. If you don't have access to DNS, you can workaround this by modifying your local resolver, i.e. editing `/etc/hosts`. +* You need to be aware that this process will make changes to your systems, so please be sure that these machines are a basic install with nothing configured or running for other purposes +* Your machines will need to be connected to the internet, and not behind a restrictive firewall. +* You should work locally on your laptop/workstation (one that you trust and that is ideally full-disk encrypted) while going through this guide. This is important because the provider configurations you are creating contain sensitive data that should not reside on a remote machine. The `leap` command will login to your servers and configure the services. +* You should do everything described below as an unprivileged user, and only run those commands as root that are noted with *sudo* in front of them. Other than those commands, there is no need for privileged access to your machine, and in fact things may not work correctly. + +All the commands in this tutorial are run on your sysadmin machine. In order to complete the tutorial, the sysadmin will do the following: + +* Install pre-requisites +* Install the LEAP command-line utility +* Check out the LEAP platform +* Create a provider and its certificates +* Setup the provider's nodes and the services that will reside on those nodes +* Initialize the nodes +* Deploy the LEAP platform to the nodes +* Test that things worked correctly +* Some additional commands + +We will walk you through each of these steps. + + +Prepare your environment +======================== + +There are a few things you need to setup before you can get going. Just some packages, the LEAP cli and the platform. + +Install pre-requisites +-------------------------------- + +*Debian & Ubuntu* + +Install core prerequisites: + + $ sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make bzip2 + +<!-- +*Mac OS* + +1. Install rubygems from https://rubygems.org/pages/download (unless the `gem` command is already installed). +--> + +NOTE: leap_cli requires ruby 1.9 or later. + + +Install the LEAP command-line utility +------------------------------------------------- + +Install the `leap` command from rubygems.org: + + $ sudo gem install leap_cli + +Alternately, you can install `leap` from source: + + $ git clone https://leap.se/git/leap_cli + $ cd leap_cli + $ rake build + $ sudo rake install + +You can also install from source as an unprivileged user, if you want. For example, instead of `sudo rake install` you can do something like this: + + $ rake install + # watch out for the directory leap is installed to, then i.e. + $ sudo ln -s ~/.gem/ruby/1.9.1/bin/leap /usr/local/bin/leap + +With either `rake install` or `sudo rake install`, you can use now /usr/local/bin/leap, which in most cases will be in your $PATH. + +If you have successfully installed the `leap` command, then you should be able to do the following: + + $ leap --help + +This will list the command-line help options. If you receive an error when doing this, please read through the README.md in the `leap_cli` source to try and resolve any problems before going forwards. + +Check out the platform +-------------------------- + +The LEAP Platform is a series of puppet recipes and modules that will be used to configure your provider. You will need a local copy of the platform that will be used to setup your nodes and manage your services. To begin with, you will not need to modify the LEAP Platform. + +First we'll create a directory for LEAP things, and then we'll check out the platform code and initalize the modules: + + $ mkdir ~/leap + $ cd ~/leap + $ git clone https://leap.se/git/leap_platform.git + $ cd leap_platform + $ git submodule sync; git submodule update --init + + +Provider Setup +============== + +A provider instance is a directory tree, usually stored in git, that contains everything you need to manage an infrastructure for a service provider. In this case, we create one for example.org and call the instance directory 'example'. + + $ mkdir -p ~/leap/example + +Bootstrap the provider +----------------------- + +Now, we will initialize this directory to make it a provider instance. Your provider instance will need to know where it can find the local copy of the git repository leap_platform, which we setup in the previous step. + + $ cd ~/leap/example + $ leap new . + +NOTES: + . make sure you include that trailing dot! + +The `leap new` command will ask you for several required values: + +* domain: The primary domain name of your service provider. In this tutorial, we will be using "example.org". +* name: The name of your service provider (we use "Example"). +* contact emails: A comma separated list of email addresses that should be used for important service provider contacts (for things like postmaster aliases, Tor contact emails, etc). +* platform: The directory where you have a copy of the `leap_platform` git repository checked out. + +You could also have passed these configuration options on the command-line, like so: + + $ leap new --contacts your@email.here --domain leap.example.org --name Example --platform=~/leap/leap_platform . + +You may want to poke around and see what is in the files we just created. For example: + + $ cat provider.json + +Optionally, commit your provider directory using the version control software you fancy. For example: + + $ git init + $ git add . + $ git commit -m "initial provider commit" + +Now add yourself as a privileged sysadmin who will have access to deploy to servers: + + $ leap add-user --self + +NOTE: in most cases, `leap` must be run from within a provider instance directory tree (e.g. ~/leap/example). + +Create provider certificates +---------------------------- + +Create two certificate authorities, one for server certs and one for client +certs (note: you only need to run this one command to get both): + + $ leap cert ca + +Create a temporary cert for your main domain (you should replace with a real commercial cert at some point) + + $ leap cert csr + +To see details about the keys and certs that the prior two commands created, you can use `leap inspect` like so: + + $ leap inspect files/ca/ca.crt + +Create the Diffie-Hellman parameters file, needed for forward secret OpenVPN ciphers: + + $ leap cert dh + +NOTE: the files `files/ca/*.key` are extremely sensitive and must be carefully protected. The other key files are much less sensitive and can simply be regenerated if needed. + + +Edit provider.json configuration +-------------------------------------- + +There are a few required settings in provider.json. At a minimum, you must have: + + { + "domain": "example.org", + "name": "Example", + "contacts": { + "default": "email1@example.org" + } + } + +For a full list of possible settings, you can use `leap inspect` to see how provider.json is evaluated after including the inherited defaults: + + $ leap inspect provider.json + + +Setup the provider's nodes and services +--------------------------------------- + +A "node" is a server that is part of your infrastructure. Every node can have one or more services associated with it. Some nodes are "local" and used only for testing, see [Development](development) for more information. + +Create a node, with the service "webapp": + + $ leap node add wildebeest ip_address:x.x.x.w services:webapp tags:production + +NOTE: replace x.x.x.w with the actual IP address of this node + +This created a node configuration file in `nodes/wildebeest.json`, but it did not do anything else. It also added the 'tag' called 'production' to this node. Tags allow us to conveniently group nodes together. When creating nodes, you should give them the tag 'production' if the node is to be used in your production infrastructure. + +The web application and the VPN nodes require a database, so lets create the database server node: + + $ leap node add cheetah ip_address:x.x.x.x services:couchdb tags:production + +NOTE: replace x.x.x.x with the actual IP address of this node + +Now we need the OpenVPN gateway, so lets create that node: + + $ leap node add ostrich ip_address:x.x.x.y openvpn.gateway_address:x.x.x.z services:openvpn tags:production + +NOTE: replace x.x.x.y with the IP address of the machine, and x.x.x.z with the second IP. openvpn gateways must be assigned two IP addresses, one for the host itself and one for the openvpn gateway. We do this to prevent incoming and outgoing VPN traffic on the same IP. Without this, the client might send some traffic to other VPN users in the clear, bypassing the VPN. + + +Setup DNS +--------- + +Now that you have the nodes configured, you should create the DNS entries for these nodes. + +Set up your DNS with these hostnames: + + $ leap list --print ip_address,domain.full,dns.aliases + cheetah x.x.x.w, cheetah.example.org, null + wildebeest x.x.x.x, wildebeest.example.org, api.example.org + ostrich x.x.x.y, ostrich.example.org, null + +Alternately, you can adapt this zone file snippet: + + $ leap compile zone + +If you cannot edit your DNS zone file, you can still test your provider by adding entries to your local resolver hosts file (`/etc/hosts` for linux): + + x.x.x.w cheetah.example.org + x.x.x.x wildebeest.example.org api.example.org example.org + x.x.x.y ostrich.example.org + +Please don't forget about these entries, they will override DNS queries if you setup your DNS later. + + +Initialize the nodes +-------------------- + +Node initialization only needs to be done once, but there is no harm in doing it multiple times: + + $ leap node init production + +This will initialize all nodes with the tag "production". When `leap node init` is run, you will be prompted to verify the fingerprint of the SSH host key and to provide the root password of the server(s). You should only need to do this once. + +If you prefer, you can initalize each node, one at a time: + + $ leap node init wildebeest + $ leap node init cheetah + $ leap node init ostrich + +Deploy the LEAP platform to the nodes +-------------------- + +Now you should deploy the platform recipes to the nodes. [Deployment can take a while to run](http://xkcd.com/303/), especially on the first run, as it needs to update the packages on the new machine. + +*Important notes:* currently nodes must be deployed in a certain order. The underlying couch database node(s) must be deployed first, and then all other nodes. + + $ leap deploy cheetah + +Watch the output for any errors (in red), if everything worked fine, you should now have your first running node. If you do have errors, try doing the deploy again. + +However, to deploy our three-node openvpn setup, we need the database and LEAP web application requires a database to run, so let's deploy to the couchdb and openvpn nodes: + + $ leap deploy wildebeest + $ leap deploy ostrich + + +What is going on here? +-------------------------------------------- + +First, some background terminology: + +* **puppet**: Puppet is a system for automating deployment and management of servers (called nodes). +* **hiera files**: In puppet, you can use something called a 'hiera file' to seed a node with a few configuration values. In LEAP, we go all out and put *every* configuration value needed for a node in the hiera file, and automatically compile a custom hiera file for each node. + +When you run `leap deploy`, a bunch of things happen, in this order: + +1. **Compile hiera files**: The hiera configuration file for each node is compiled in YAML format and saved in the directory `hiera`. The source material for this hiera file consists of all the JSON configuration files imported or inherited by the node's JSON config file. +* **Copy required files to node**: All the files needed for puppet to run are rsync'ed to each node. This includes the entire leap_platform directory, as well as the node's hiera file and other files needed by puppet to set up the node (keys, binary files, etc). +* **Puppet is run**: Once the node is ready, leap connects to the node via ssh and runs `puppet apply`. Puppet is applied locally on the node, without a daemon or puppetmaster. + +You can run `leap -v2 deploy` to see exactly what commands are being executed. + + +Test that things worked correctly +================================= + +You should now have three machines with the LEAP platform deployed to them, one for the web application, one for the database and one for the OpenVPN gateway. + +To run troubleshooting tests: + + leap test + +If you want to confirm for yourself that things are working, you can perform the following manual tests. + +### Access the web application + +In order to connect to the web application in your browser, you need to point your domain at the IP address of the web application node (named wildebeest in this example). + +There are a lot of different ways to do this, but one easy way is to modify your `/etc/hosts` file. First, find the IP address of the webapp node: + + $ leap list webapp --print ip_address + +Then modify `/etc/hosts` like so: + + x.x.x.w leap.example.org + +Replacing 'leap.example.org' with whatever you specified as the `domain` in the `leap new` command. + +Next, you can connect to the web application either using a web browser or via the API using the LEAP client. To use a browser, connect to https://leap.example.org (replacing that with your domain). Your browser will complain about an untrusted cert, but for now just bypass this. From there, you should be able to register a new user and login. + +### Use the VPN + +You should be able to simply test that the OpenVPN gateway works properly by doing the following: + + $ leap test init + $ sudo openvpn test/openvpn/production_unlimited.ovpn + +Or, you can use the LEAP client (called "bitmask") to connect to your new provider, create a user and then connect to the VPN. + + +Additional information +====================== + +It is useful to know a few additional things. + +Useful commands +--------------- + +Here are a few useful commands you can run on your new local nodes: + +* `leap ssh wildebeest` -- SSH into node wildebeest (requires `leap node init wildebeest` first). +* `leap list` -- list all nodes. +* `leap list production` -- list only those nodes with the tag 'production' +* `leap list --print ip_address` -- list a particular attribute of all nodes. +* `leap cert update` -- generate new certificates if needed. + +See the full command reference for more information. + +Node filters +------------------------------------------- + +Many of the `leap` commands take a "node filter". You can use a node filter to target a command at one or more nodes. + +A node filter consists of one or more keywords, with an optional "+" before each keyword. + +* keywords can be a node name, a service type, or a tag. +* the "+" before the keyword constructs an AND condition +* otherwise, multiple keywords together construct an OR condition + +Examples: + +* `leap list openvpn` -- list all nodes with service openvpn. +* `leap list openvpn +production` -- only nodes of service type openvpn AND tag production. +* `leap deploy webapp openvpn` -- deploy to all webapp OR openvpn nodes. +* `leap node init ostrich` -- just init the node named ostrich. + +Keep track of your provider configurations +------------------------------------------ + +You should commit your provider changes to your favorite VCS whenever things change. This way you can share your configurations with other admins, all they have to do is to pull the changes to stay up to date. Every time you make a change to your provider, such as adding nodes, services, generating certificates, etc. you should add those to your VCS, commit them and push them to where your repository is hosted. + +Note that your provider directory contains secrets! Those secrets include passwords for various services. 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. + +What's next +----------------------------------- + +Read the [LEAP platform guide](guide) to learn about planning and securing your infrastructure. + diff --git a/doc/tutorials/single-node-email.md b/doc/tutorials/single-node-email.md new file mode 100644 index 00000000..b47496b9 --- /dev/null +++ b/doc/tutorials/single-node-email.md @@ -0,0 +1,282 @@ +@title = 'Single node email tutorial' +@nav_title = 'Single node email' +@summary = 'A single node email provider.' + +Quick Start - Single node setup +=============================== + +This tutorial walks you through the initial process of creating and deploying a minimal service provider running the [LEAP platform](platform). +We will guide you through building a single node mail provider. + +Our goal +------------------ + +We are going to create a minimal LEAP provider offering Email service. This basic setup can be expanded by adding more webapp and couchdb nodes to increase availability (performance wise, a single couchdb and a single webapp are more than enough for most usage, since they are only lightly used, but you might want redundancy). Please note: currently it is not possible to safely add additional couchdb nodes at a later point. They should all be added in the beginning, so please consider carefully if you would like more before proceeding. + +Our goal is something like this: + + $ leap list + NODES SERVICES TAGS + node1 couchdb, mx, soledad, webapp local + +NOTE: You won't be able to run that `leap list` command yet, not until we actually create the node configurations. + +Requirements +------------ + +In order to complete this Quick Start, you will need a few things: + +* You will need `one real or paravirtualized virtual machine` (Vagrant, KVM, Xen, Openstack, Amazon, …) that have a basic Debian Stable installed. +* You should be able to `SSH into them` remotely, and know their root password, IP addresses and their SSH host keys +* The ability to `create/modify DNS entries` for your domain is preferable, but not needed. If you don't have access to DNS, you can workaround this by modifying your local resolver, i.e. editing `/etc/hosts`. +* You need to be aware that this process will make changes to your machines, so please be sure that these machines are a basic install with nothing configured or running for other purposes +* Your machines will need to be connected to the internet, and not behind a restrictive firewall. +* You should `work locally on your laptop/workstation` (one that you trust and that is ideally full-disk encrypted) while going through this guide. This is important because the provider configurations you are creating contain sensitive data that should not reside on a remote machine. The leap cli utility will login to your servers and configure the services. +* You should do everything described below as an `unprivileged user`, and only run those commands as root that are noted with *sudo* in front of them. Other than those commands, there is no need for privileged access to your machine, and in fact things may not work correctly. + +All the commands in this tutorial are run on your sysadmin machine. In order to complete the tutorial, the sysadmin will do the following: + +* Install pre-requisites +* Install the LEAP command-line utility +* Check out the LEAP platform +* Create a provider and its certificates +* Setup the provider's node and the services that will reside on it +* Initialize the node +* Deploy the LEAP platform to the node +* Test that things worked correctly +* Some additional commands + +We will walk you through each of these steps. + + +Prepare your environment +======================== + +There are a few things you need to setup before you can get going. Just some packages, the LEAP cli and the platform. + +Install pre-requisites +-------------------------------- + +*Debian & Ubuntu* + +Install core prerequisites: + + $ sudo apt-get install git ruby ruby-dev rsync openssh-client openssl rake make bzip2 + +*Mac OS* + +Install rubygems from https://rubygems.org/pages/download (unless the `gem` command is already installed). + + +NOTE: leap_cli should work with ruby1.8, but has only been tested using ruby1.9. + + +Install the LEAP command-line utility +------------------------------------------------- + +Install the LEAP command-line utility (leap_cli) from rubygems.org: + + $ sudo gem install leap_cli + +Alternately, you can install `leap_cli` from source, please refer to https://leap.se/git/leap_cli/README.md. + +If you have successfully installed `leap_cli`, then you should be able to do the following: + + $ leap --help + +This will list the command-line help options. If you receive an error when doing this, please read through the README.md in the `leap_cli` source to try and resolve any problems before going forwards. + + +Provider Setup +============== + +A provider instance is a directory tree that contains everything you need to manage an infrastructure for a service provider. In this case, we create one for example.org and call the instance directory 'example'. + + $ mkdir -p ~/leap/example + +Bootstrap the provider +----------------------- + +Now, we will initialize this directory to make it a provider instance. Your provider instance will need to know where it can find the local copy of the git repository leap_platform, which we setup in the previous step. + + $ cd ~/leap/example + $ leap new . + +NOTES: + . make sure you include that trailing dot! + +The `leap new` command will ask you for several required values: + +* domain: The primary domain name of your service provider. In this tutorial, we will be using "example.org". +* name: The name of your service provider (we use "Example"). +* contact emails: A comma separated list of email addresses that should be used for important service provider contacts (for things like postmaster aliases, Tor contact emails, etc). +* platform: The directory where you either have a copy of the `leap_platform` git repository already checked out, or where `leap_cli` should download it too. You could just accept the suggested path for this example. + The LEAP Platform is a series of puppet recipes and modules that will be used to configure your provider. You will need a local copy of the platform that will be used to setup your nodes and manage your services. To begin with, you will not need to modify the LEAP Platform. + +These steps should be sufficient for this example. If you want to configure your provider further or like to examine the files, please refer to the [Configure Provider](configure-provider) section. + +Add Users who will have administrative access +--------------------------------------------- + +Now add yourself as a privileged sysadmin who will have access to deploy to servers: + + $ leap add-user --self + +NOTE: in most cases, `leap` must be run from within a provider instance directory tree (e.g. ~/leap/example). + + +Create provider certificates +---------------------------- + +Create two certificate authorities, one for server certs and one for client +certs (note: you only need to run this one command to get both): + + $ leap cert ca + +Create a temporary cert for your main domain (you should replace with a real commercial cert at some point) + + $ leap cert csr + + +Setup the provider's node and services +-------------------------------------- + +A "node" is a server that is part of your infrastructure. Every node can have one or more services associated with it. Some nodes are "local" and used only for testing, see [Development](development) for more information. + +Create a node, with `all the services needed for Email: "couchdb", "mx", "soledad" and "webapp"` + + $ leap node add node1 ip_address:x.x.x.w services:couchdb,mx,soledad,webapp tags:production + +NOTE: replace x.x.x.w with the actual IP address of this node + +This created a node configuration file in `nodes/node1.json`, but it did not do anything else. It also added the 'tag' called 'production' to this node. Tags allow us to conveniently group nodes together. When creating nodes, you should give them the tag 'production' if the node is to be used in your production infrastructure. + +Initialize the nodes +-------------------- + +Node initialization only needs to be done once, but there is no harm in doing it multiple times: + + $ leap node init node1 + +This will initialize the node "node1". When `leap node init` is run, you will be prompted to verify the fingerprint of the SSH host key and to provide the root password of the server. You should only need to do this once. + + +Deploy the LEAP platform to the nodes +-------------------- + +Now you should deploy the platform recipes to the node. [Deployment can take a while to run](http://xkcd.com/303/), especially on the first run, as it needs to update the packages on the new machine. + + $ leap deploy + +Watch the output for any errors (in red), if everything worked fine, you should now have your first running node. If you do have errors, try doing the deploy again. + + +Setup DNS +--------- + +Now that you have the node configured, you should create the DNS entrie for this node. + +Set up your DNS with these hostnames: + + $ leap list --print ip_address,domain.full,dns.aliases + node1 x.x.x.w, node1.example.org, example.org, api.example.org, nicknym.example.org + +Alternately, you can adapt this zone file snippet: + + $ leap compile zone + +If you cannot edit your DNS zone file, you can still test your provider by adding this entry to your local resolver hosts file (`/etc/hosts` for linux): + + x.x.x.w node1.example.org example.org api.example.org nicknym.example.org + +Please don't forget about these entries, they will override DNS queries if you setup your DNS later. + + +What is going on here? +-------------------------------------------- + +First, some background terminology: + +* **puppet**: Puppet is a system for automating deployment and management of servers (called nodes). +* **hiera files**: In puppet, you can use something called a 'hiera file' to seed a node with a few configuration values. In LEAP, we go all out and put *every* configuration value needed for a node in the hiera file, and automatically compile a custom hiera file for each node. + +When you run `leap deploy`, a bunch of things happen, in this order: + +1. **Compile hiera files**: The hiera configuration file for each node is compiled in YAML format and saved in the directory `hiera`. The source material for this hiera file consists of all the JSON configuration files imported or inherited by the node's JSON config file. +* **Copy required files to node**: All the files needed for puppet to run are rsync'ed to each node. This includes the entire leap_platform directory, as well as the node's hiera file and other files needed by puppet to set up the node (keys, binary files, etc). +* **Puppet is run**: Once the node is ready, leap connects to the node via ssh and runs `puppet apply`. Puppet is applied locally on the node, without a daemon or puppetmaster. + +You can run `leap -v2 deploy` to see exactly what commands are being executed. + +<!-- See [under the hood](under-the-hood) for more details. --> + + +Test that things worked correctly +================================= + +You should now one machine with the LEAP platform email service deployed to it. + + +Access the web application +-------------------------------------------- + +In order to connect to the web application in your browser, you need to point your domain at the IP address of your new node. + +Next, you can connect to the web application either using a web browser or via the API using the LEAP client. To use a browser, connect to https://example.org (replacing that with your domain). Your browser will complain about an untrusted cert, but for now just bypass this. From there, you should be able to register a new user and login. + +Testing with leap_cli +--------------------- + +Use the test command to run a set of different tests: + + leap test + + +Additional information +====================== + +It is useful to know a few additional things. + +Useful commands +--------------- + +Here are a few useful commands you can run on your new local nodes: + +* `leap ssh web1` -- SSH into node web1 (requires `leap node init web1` first). +* `leap list` -- list all nodes. +* `leap list production` -- list only those nodes with the tag 'production' +* `leap list --print ip_address` -- list a particular attribute of all nodes. +* `leap cert update` -- generate new certificates if needed. + +See the full command reference for more information. + +Node filters +------------------------------------------- + +Many of the `leap` commands take a "node filter". You can use a node filter to target a command at one or more nodes. + +A node filter consists of one or more keywords, with an optional "+" before each keyword. + +* keywords can be a node name, a service type, or a tag. +* the "+" before the keyword constructs an AND condition +* otherwise, multiple keywords together construct an OR condition + +Examples: + +* `leap list openvpn` -- list all nodes with service openvpn. +* `leap list openvpn +production` -- only nodes of service type openvpn AND tag production. +* `leap deploy webapp openvpn` -- deploy to all webapp OR openvpn nodes. +* `leap node init vpn1` -- just init the node named vpn1. + +Keep track of your provider configurations +------------------------------------------ + +You should commit your provider changes to your favorite VCS whenever things change. This way you can share your configurations with other admins, all they have to do is to pull the changes to stay up to date. Every time you make a change to your provider, such as adding nodes, services, generating certificates, etc. you should add those to your VCS, commit them and push them to where your repository is hosted. + +Note that your provider directory contains secrets! Those secrets include passwords for various services. 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. + +What's next +----------------------------------- + +Read the [LEAP platform guide](guide) to learn about planning and securing your infrastructure. + |