Select Page

Today’s topic is automation or automatic deployment with ansible playbooks! This is a short preview with an example that will show you a real world application of the ansible playbook which can help you to deploy a LAMP Stack server for web hosting, but ansible and its playbooks can do a lot more, anything you need to automate can be done!

Lets say you have a website building company and would like to create LAMP stack server setups in a flash without doing everything manually. Repeating that process with every new server can be a time consuming task.

This is the very essence of the power and freedom that automating tasks gives you it frees up you time for other things and allows you the flexibility to control more than one server at a time like updates and restarts can be managed

We are here to tell you that you don’t have to! Using ansible you can create your own playbook or use one that has already been written and change it out with your server access information and presto you will have a working playbook! We will use one such playbook as to explain ansible playbooks in this article. First of all what you need is ansible installed on a system, this goes without saying but we are saying it anyway. The first thing we need to do is obtain the LAMP playbook and its dependencies from the do-community/ansible-playbooks repository. We need to clone this repository to a local folder inside the Ansible Control Node. In case you have cloned this repository before while following a different guide, access your existing ansible-playbooks copy and run a git pull command to make sure you have updated contents:

cd ~/ansible-playbooks git pull

If this is your first time using the do-community/ansible-playbooks repository, you should start by cloning the repository to your home folder with:

cd ~ git clone https://github.com/do-community/ansible-playbooks.git cd ansible-playbooks

The files we’re interested in are located inside the lamp_ubuntu1804 folder, which has the following structure: lamp_ubuntu1804

├── files │   ├── apache.conf.j2 │   └── info.php.j2 ├── vars │   └── default.yml ├── playbook.yml └── readme.md

Here is what each of these files are:

files/info.php.j2: Template file for setting up a PHP test page on the web server’s root files/apache.conf.j2: Template file for setting up the Apache VirtualHost. vars/default.yml: Variable file for customizing playbook settings. playbook.yml: The playbook file, containing the tasks to be executed on the remote server(s). readme.md: A text file containing information about this playbook.

We’ll edit the playbook’s variable file to customize the configurations of both MySQL and Apache. Access the lamp_ubuntu1804 directory and open the vars/default.yml file using your command line editor of choice:

cd lamp_ubuntu1804 nano vars/default.yml

This file contains a few variables that require your attention:

vars/default.yml mysql_root_password: “mysql_root_password” app_user: “user” http_host: “your_domain” http_conf: “your_domain.conf” http_port: “80” disable_default: true

The following list contains a brief explanation of each of these variables and how you might want to change them:

mysql_root_password: The desired password for the root MySQL account. app_user: A remote non-root user on the Ansible host that will be set as the owner of the application files. http_host: Your domain name. http_conf: The name of the configuration file that will be created within Apache. http_port: HTTP port for this virtual host, where 80 is the default. disable_default: Whether or not to disable the default website that comes with Apache.

Once you’re done updating the variables inside vars/default.yml, save and close this file. If you used nano, do so by pressing CTRL + X, Y, then ENTER. You’re now ready to run this playbook on one or more servers. Most playbooks are configured to be executed on every server in your inventory, by default. We can use the -l flag to make sure that only a subset of servers, or a single server, is affected by the playbook. We can also use the -u flag to specify which user on the remote server we’re using to connect and execute the playbook commands on the remote hosts. To execute the playbook only on server1, connecting as sammy, you can use the following command:

ansible-playbook playbook.yml -l server1 -u user

playbook.yml The playbook.yml file is where all tasks from this setup are defined. It starts by defining the group of servers that should be the target of this setup (all), after which it uses become: true to define that tasks should be executed with privilege escalation (sudo) by default. Then, it includes the vars/default.yml variable file to load configuration options.

---
- hosts: all
  become: true
  vars_files:
    - vars/default.yml

  tasks:
    - name: Install prerequisites
      apt: name={{ item }} update_cache=yes state=latest force_apt_get=yes
      loop: [ 'aptitude' ]

  #Apache Configuration
    - name: Install LAMP Packages
      apt: name={{ item }} update_cache=yes state=latest
      loop: [ 'apache2', 'mysql-server', 'python3-pymysql', 'php', 'php-mysql', 'libapache2-mod-php' ]

    - name: Create document root
      file:
        path: "/var/www/{{ http_host }}"
        state: directory
        owner: "{{ app_user }}"
        mode: '0755'

    - name: Set up Apache virtualhost
      template:
        src: "files/apache.conf.j2"
        dest: "/etc/apache2/sites-available/{{ http_conf }}"
      notify: Reload Apache

    - name: Enable new site
      shell: /usr/sbin/a2ensite {{ http_conf }}
      notify: Reload Apache

    - name: Disable default Apache site
      shell: /usr/sbin/a2dissite 000-default.conf
      when: disable_default
      notify: Reload Apache

  # MySQL Configuration
    - name: Sets the root password
      mysql_user:
        name: root
        password: "{{ mysql_root_password }}"
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: Removes all anonymous user accounts
      mysql_user:
        name: ''
        host_all: yes
        state: absent
        login_user: root
        login_password: "{{ mysql_root_password }}"

    - name: Removes the MySQL test database
      mysql_db:
        name: test
        state: absent
        login_user: root
        login_password: "{{ mysql_root_password }}"

  # UFW Configuration
    - name: "UFW - Allow HTTP on port {{ http_port }}"
      ufw:
        rule: allow
        port: "{{ http_port }}"
        proto: tcp

  # PHP Info Page
    - name: Sets Up PHP Info Page
      template:
        src: "files/info.php.j2"
        dest: "/var/www/{{ http_host }}/info.php"

  handlers:
    - name: Reload Apache
      service:
        name: apache2
        state: reloaded

    - name: Restart Apache
      service:
        name: apache2
        state: restarted

Feel free to modify these files to best suit your individual needs within your own workflow. I hope you take away that automation doesn’t have to be daunting and scary, but if you are interested in automation and would like to automate or build whole systems based on A.I feel free to contact us so we can talk about all the possibilities of this new amazing technology!