|
| 1 | +Server Provisioning |
| 2 | +======================== |
| 3 | + |
| 4 | + |
| 5 | +Overview |
| 6 | +------------------------ |
| 7 | + |
| 8 | +{{ project_name|title }} is deployed on the following stack. |
| 9 | + |
| 10 | +- OS: Ubuntu 12.04 LTS |
| 11 | +- Python: 2.7 |
| 12 | +- Database: Postgres |
| 13 | +- Application Server: Gunicorn |
| 14 | +- Frontend Server: Nginx |
| 15 | +- Cache: Memcached |
| 16 | + |
| 17 | +These services are configured to run together on a single machine. Each environment |
| 18 | +(``staging`` or ``production``) should run on a separate machine. `Supervisord <http://supervisord.org/>`_ |
| 19 | +manages the application server process. |
| 20 | + |
| 21 | + |
| 22 | +Initial Setup |
| 23 | +------------------------ |
| 24 | + |
| 25 | +Before your project can be deployed to a server, the code needs to be |
| 26 | +accessible in a git repository. Once that is done you should update the ``env.repo`` in |
| 27 | +the ``fabfile.py``. E.g., change this:: |
| 28 | + |
| 29 | + env.repo = u'' # FIXME: Add repo URL |
| 30 | + |
| 31 | +to this:: |
| 32 | + |
| 33 | + env.repo = u'[email protected]:account/reponame.git' |
| 34 | + |
| 35 | +You also need to set the project name in `conf/pillar/project.sls``. This should |
| 36 | +match the ``env.project`` in ``fabfile.py``. For the environment you want to setup |
| 37 | +you will need to set the ``domain`` in ``conf/pillar/<environment>/env.sls``. |
| 38 | + |
| 39 | +You will also need add the developer's user names and SSH keys to ``conf/pillar/devs.sls``. Each |
| 40 | +user record should match the format:: |
| 41 | + |
| 42 | + example-user: |
| 43 | + groups: [admin, login] |
| 44 | + public_key: |
| 45 | + - ssh-rsa <Full SSH Key would go here> |
| 46 | + |
| 47 | +Additional developers can be added later but you will need to create at least on user for |
| 48 | +yourself. |
| 49 | + |
| 50 | + |
| 51 | +Managing Secrets |
| 52 | +------------------------ |
| 53 | + |
| 54 | +Secret information such as passwords and API keys should never be committed to the |
| 55 | +source repository. Instead aach environment manages is secrets in ``conf/pillar/<environment>/secrets.sls``. |
| 56 | +These ``secrets.sls`` files are excluded from the source control and need to be passed |
| 57 | +to the developers out of band. There are example files given in ``conf/pillar/<environment>/secrets.ex``. |
| 58 | +They have the format:: |
| 59 | + |
| 60 | + secrets: |
| 61 | + DB_PASSWORD: 'XXXXXX' |
| 62 | + |
| 63 | +Each key/value pair given in the ``secrets`` dictionary will be added to the OS environment |
| 64 | +and can retrieved in the Python code via:: |
| 65 | + |
| 66 | + import os |
| 67 | + |
| 68 | + password = os.environ['DB_PASSWORD'] |
| 69 | + |
| 70 | +Secrets for other environments will not be available. That is the staging server |
| 71 | +will not have access to the production secrets. As such there is no need to namespace the |
| 72 | +secrets by their environment. |
| 73 | + |
| 74 | + |
| 75 | +Setup Checklist |
| 76 | +------------------------ |
| 77 | + |
| 78 | +To summarize the steps above you can use the following checklist |
| 79 | + |
| 80 | +- ``env.repo`` is set in ``fabfile.py`` |
| 81 | +- Developer user names and SSH keys have been added to ``conf/pillar/devs.sls`` |
| 82 | +- Project name has been in ``conf/pillar/project.sls`` |
| 83 | +- Environment domain name has been set in ``conf/pillar/<environment>/env.sls`` |
| 84 | +- Environment secrets have been set in ``conf/pillar/<environment>/secrets.sls`` |
| 85 | + |
| 86 | + |
| 87 | +Provision |
| 88 | +------------------------ |
| 89 | + |
| 90 | +Once you have completed the above steps you are ready to provision a new server |
| 91 | +for a given environment. You will need to be able to connect to the server |
| 92 | +as a root user. How this is done will depend on where the server is hosted. |
| 93 | +VPS providers such as Linode will give you a username/password combination. Amazon's |
| 94 | +EC2 uses a private key. These credentials will be passed as command line arguments.:: |
| 95 | + |
| 96 | + # Template of the command |
| 97 | + fab -H <fresh-server-ip> -u <root-user> <environment> provision |
| 98 | + # Example of provisioning 33.33.33.10 as a staging machine |
| 99 | + fab -H 33.33.33.10 -u root staging provision |
| 100 | + |
| 101 | +Behind the scenes this will rsync the states/pillars in ``conf`` over to the |
| 102 | +server as well as check out the base states from the `margarita <https://github.com/caktus/margarita>`_ |
| 103 | +repo. It will then use the `masterless salt-minion <http://docs.saltstack.com/topics/tutorials/quickstart.html>`_ |
| 104 | +to ensure the states are up to date. |
| 105 | + |
| 106 | +Note that because of the use of rsync it is possible to execute configuration changes which |
| 107 | +have not yet been committed to the repo. This can be handy for testing configuration |
| 108 | +changes and allows for the secrets to be excluded from the repo but it's a double-edged sword. |
| 109 | +You should be sure to commit any configuration changes to the repo when they are ready. |
| 110 | + |
| 111 | +Once a server has been created for its environment it should be added to the ``env.hosts`` |
| 112 | +for the given environment. In our example we would add:: |
| 113 | + |
| 114 | + def staging(): |
| 115 | + env.environment = 'staging' |
| 116 | + env.hosts = ['33.33.33.10', ] |
| 117 | + |
| 118 | +At this point we can run the first deploy:: |
| 119 | + |
| 120 | + fab staging deploy |
| 121 | + |
| 122 | +This will do the initial checkout of the repo source, install the Python requirements, |
| 123 | +run syncdb/migrate and collect the static resources. |
| 124 | + |
| 125 | + |
| 126 | +Updates |
| 127 | +------------------------ |
| 128 | + |
| 129 | +During the life of the project you will likely need to make updates to the server |
| 130 | +configuration. This might include new secrets add to the pillar, new developers |
| 131 | +added to the project or new services which need to be installed. Configuration updates |
| 132 | +can be made by calling the ``provision`` command again.:: |
| 133 | + |
| 134 | + # Template of the command |
| 135 | + fab <environment> provision |
| 136 | + # Reprovision the staging server |
| 137 | + fab staging provision |
| 138 | + |
| 139 | +In this case we do not need to connect as the root user. We connect as our developer |
| 140 | +user. We also do not need to specify the host. It will use the ``env.hosts`` previously |
| 141 | +set for this environment. |
| 142 | + |
| 143 | +For more information testing the provisioning see the doc:`vagrant guide </vagrant>`. |
0 commit comments