Usage

Create playbook

Create a new playbook file. This can be directly in websauna.ansible root folder. In this example we call the file playbook-myapp.yml

# Playbook which ramps up myapp tutorial site inside a Vagrant virtual machine

- hosts: myapp_production
  gather_facts: true

  # These need to be set up before reading default.yml - more variables are generated based on these
  vars:
    - package_name: my.app
    - package_path: my/app
    - site_id: myapp

    # Websocket is only needed to connect to IPython Notebook running on the server
    - websocket: off

    # Install Postfix for email out
    - smtp: on

    # Is HTTPS traffic terminated by Nginx
    - ssl: off

    # Do we install Celery worker and beat to run background tasks
    - celery: on

    # Is the site proxied by Cloudflare security service
    - cloudflare: off

    # Do we need to support New Relic monitoring
    - new_relic: off

    # Do we create Let's Encrypt HTTPS certificate for the site
    - letsenrypt: off

    # Do we enable Linux firewall
    - firewall: on

    # Do we set up Duplicity backup tasks
    - backup: off

    - git_repository: [email protected]:websauna/myapp.git
    - git_branch: master
    - site_mode: production

    - ini_secrets_file: production-secrets.ini   # This file is generated by scaffold

    - server_name: myapp.example.com

    # Configured outbound domain for Postfix
    - server_email_domain: example.com

    # System outgoing email address (cron others)
    - server_email: [email protected]

    # Receive messages from Cron and system scripts to this address
    - notify_email: [email protected]

  pre_tasks:

    # Load default vars based on playbook.yml input
    - include_vars: default.yml
      tags: site, smtp, psql, uwsgi, nginx

    # Load default vars based on playbook.yml input
    - include_vars: secrets.yml
      tags: site, smtp, psql, uwsgi, nginx

  roles:

    # Sanity check
    - { role: websauna.preflight, tags: ['site'] }

    # Set up wsgi UNIX user
    - websauna.users

    # Needed to setup SSH auth socket for github/bitbucket
    - { role: websauna.ssh, tags: ['site'] }

    # Set up bash, etc. settings
    - websauna.shell

    # Install fail2ban, optionally enable Linux firewall
    - websauna.harden

    # Set up outgoing email with Postfix
    - websauna.smtp

    # Build a local PostgreSQL server for your database
    - { role: ANXS.postgresql, become: yes, become_user: root, tags: ['psql'] }

    # Set up Nginx web server for Internet facing traffic
    - { role: Stouts.nginx, become: yes, become_user: root, tags: ['site'] }

    # Set up Redis server for session data
    - { role: Stouts.redis, become: yes, become_user: root, tags: redis }

    # Set up updated Python 3.5 from deadsnakes repository
    - { role: Stouts.python, become: yes, become_user: root }

    # Core login of setting up WSGI application in /srv/pyramid
    - { role: websauna.site, tags: ['site'] }  # Core site update logic

    # Finalize: send out email of job done, update motd
    - { role: websauna.postflight, tags: ['site'] }

Production secrets

Besides having the deployment Secrets in Ansible vault locally, the running Python code may need to know some secret tokens, like API keys. An empty production-secrets.ini for these is generated by Scaffolds. You can copy this file over and start filling in information there when needed.

Create hosts inventory

Ansible inventory file tells what servers are available for the deployment. In our playbook we use a hosts inventory file called hosts.ini for the inventory.

Create a hosts.ini file. This can be directly in websauna.ansible root folder. Place the following in the file. This example is for Amazon EC2 server:

[default]
myapp_production ansible_host=1.2.3.4 ansible_user=ubuntu www_ip=172.1.2.3

For each server the information you need in this point is:

  • ansible_host: SSH IP address your server is listening to.
  • www_ip: IP address your where server accepts HTTP/HTTPS connections. For Amazon EC2 server these two are different.
  • ansible_user: What is the UNIX username SSH uses to log in. This user must have term:sudo: access.
  • Make sure your hosting provider has firewall open for inbound SSH, HTTP and HTTPS ports.

SSH agent forwarding

SSH agent forwarding enables the remote server to use your local SSH credentials. This is required e.g. from Ansible to access private GitHub repositories from the remote server.

You need to enable SSH agent forwarding, so that Ansible uses your locally configured SSH key. With this setup, the server never stores any private keys and they are safely on your own computer. Ansible uses SSH agent to make remote connections from the server to e.g. a GitHub to fetch source code of your application.

You can add any number of keys. The keys

  • Should allow you to connect to your server (hosting provider, like Amazon EC2 key)
  • Should allow you to check out source code from your repository for the deployment (GitHub, Bitbucket keys)

Usually the command to add a key into a SSH agent is along the lines:

ssh-add ~/.ssh/my_ssh_private_key_for_deployment

Likewise, you need to have set up your public key on your Git repository service like GitHub.

Run playbook

Make sure Ansible specific virtual environment is activated. Run from command line:

ansible-playbook -i hosts.ini playbook-myapp.yml

Update runs

For subsequent playbook runs: If your server configuration has not changed, and you need to only update application files and migrations, instead of building the server from a scratch, you can use site tag to run tasks specific to this:

ansible-playbook -i hosts.ini playbook-myapp.yml -t site

This considerably cuts down playbook execution time.

Playbook variables

See playbook variables reference for a detailed list of supported variables by websauna.ansible.