Menu
  • Home
  • About Me
  • Blog
  • Github
  • LinkedIn

Vagrant Multi Machine setup automation with Ansible Playbook

January 17, 2022June 30, 2022

I’m going to automate configuration of simple microservice architecture application by using Ansible Playbook and Vagrant.

Create 3 roles for this archtecture

1. Frontend

2. Backend

3. Database

Ansible-Galaxy Create Backend Role

ansible-galaxy role init backend
# name of the role(folder) created in my local machine

tree backend/
#tell anislble to role (folder) use playbook

tutorial.yaml

---
- hosts: backend
  vars:
    backend_user: backend
    backend_folder: /backend
  tasks:
    - name: include nodejs role
      include_role:
        name: nodejs
    - name: Include the backend role
      include_role:
        name: backend
- hosts: frontend
  tasks:
    - name: include nodejs role
      include_role:
        name: nodejs
    - name: include the frontend role
      include_role:
        name: frontend
- hosts: database
  tasks:
    - name: include the database role
      include_role:
        name: database


backend/tasks/main.yaml

---
- name: Create User
  become: true 
  user:
    name: "{{ backend_user}}"
- name: Create a directory if it doesn't exist
  become: true
  ansible.builtin.file:
    path: "{{ backend_folder}}"
    state: directory
    owner: "{{ backend_user }}"
    mode: '0755'
- name: acl package installation
  become: true
  package:
    name: acl
    state: present
- name: Clone git repo
  become: true
  become_user: "{{ backend_user }}"
  git:
    repo: https://github.com/bezkoder/nodejs-express-sequelize-mysql.git
    force: yes
    dest: /home{{ backend_folder }}/backend
- name: Install pacakages for the backend app
  become: true
  become_user: "{{ backend_user }}"
  community.general.npm:
    path: /home{{ backend_folder }}/backend

- name: Update DB configuration
  become: true
  template:
    src: db.config.js.j2
    dest: /home{{ backend_folder }}/backend/app/config/db.config.js
- name: tutorials service file
  become: true
  template:
    src: tutorials.service.j2
    dest: /etc/systemd/system/tutorials.service
- name: restart service
  become: true
  systemd:
    daemon_reload: yes
    name: tutorials
    state: started
    enabled: yes
- name: restart service
  become: true
  systemd:
    name: tutorials
    state: restarted

backend/defaults/main.yaml

---
# defaults file for backend
backend_db_host: 192.168.150.12
backend_db_name: tutorials
backend_db_user: backend
backend_db_password: acit4640

backend/template/db.config.js.j2

module.exports = {
	  HOST: "{{ backend_db_host }}",
	  USER: "{{ backend_db_user }}",
	  PASSWORD: "{{ backend_db_password }}",
	  DB: "{{ backend_db_name }}",
	  dialect: "mysql",
	  pool: {
		      max: 5,
		      min: 0,
		      acquire: 30000,
		      idle: 10000
		    }
};

backend/template/tutorials.service.js

[Unit]
Description=Tutorials backend
After=network.target

[Service]
WorkingDirectory=/home/{{ backend_user }}/backend
Type=simple
User={{ backend_user }}
ExecStart=/usr/bin/node /home/{{ backend_user }}/backend/server.js
Restart=always

[Install]
WantedBy=multi-user.target

Ansible-Galaxy Create Nodejs Role



ansible-galaxy role init nodejs
# name of the role(folder) created in my local machine

nodejs/tasks/main.yml

---
# tasks file for nodejs
- name: nodejs Installation
  get_url:
    url: https://deb.nodesource.com/setup_14.x
    dest: /home/vagrant/nodesource_install_script
  register: download_nodejs_script
- name: Run the installation script
  become: true
  command: bash /home/vagrant/nodesource_install_script
  when: download_nodejs_script.changed
- name: Make sure NodeJS is installed
  become: true
  package:
    name: nodejs

Ansible-Galaxy Create Frontend Role



ansible-galaxy role init trontend
# name of the role(folder) created in my local machine

Frontend/tasks/main.yml

---
- name: run apt-get update
  become: true
  apt:
    upgrade: yes
    update_cache: yes
- name: Install nginx
  become: true
  package:
    name: nginx
    state: present
- name: Git Clone
  git:
    repo: https://github.com/bezkoder/react-crud-web-api.git
    force: yes
    dest: /home/vagrant{{ http_static_dir }}
- name: Install packages
  npm:
    path: /home/vagrant{{ http_static_dir }}
    state: latest
- name: Run npm run-script build
  shell:
    cmd: npm run-script build
    chdir: /home/vagrant{{ http_static_dir }}
- name: http-common.js modification
  replace:
    path: /home/vagrant/{{http_static_dir}}/src/http-common.js
    regexp: 'baseURL: "http://localhost:8080/api"'
    replace: 'baseURL: "{{ http_api_location}}"'
- name: nginx default file modification
  become: true
  template:
    force: yes
    src: default.j2
    dest: /etc/nginx/sites-available/default
  register: default
- name: enable nginx and run
  become: true
  systemd:
    name: nginx
    enabled: yes
    state: started
- name: restart nginx
  become: true
  systemd:
    name: nginx
    state: restarted
  when: default.changed

Frontend/defaults/main.yml

---
# defaults file for frontend
http_static_dir: "/frontend"
http_api_location : "/api"
http_backend_url: "http://192.168.150.10:8080"

Frontend/templates/default.js

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or WordPress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /home/vagrant{{ http_static_dir}}/build;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
        
        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ /index.html;
        }

	location /api {
		proxy_pass {{ http_backend_url}};
	}

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#       listen 80;
#       listen [::]:80;
#
#       server_name example.com;
#
#       root /www;
#       index index.html;
#
#       location / {
#               try_files $uri $uri/ =404;
#       }
#}

Ansible-Galaxy Create Database Role



ansible-galaxy role init database
# name of the role(folder) created in my local machine

database/tasks/main.yml

---
- name: run apt-get update
  become: true
  apt:
    upgrade: yes
    update_cache: yes
- name: install MySQL
  become: true
  package:
    name: mysql-server
    state: present
- name: Install pymysql
  become: true
  pip:
    name: pymysql
    state: present
- name: Install python3-pip
  become: true
  package:
    name: python3-pip
    state: present
- name: Install python3-mysqldb
  become: true
  apt:
    name: python3-mysqldb
    state: present
- name: Run pymysql and create database
  become: true
  mysql_db:
    name: "{{ backend_db_name }}"
    state: present
    check_implicit_admin: yes
    login_unix_socket: /var/run/mysqld/mysqld.sock
- name: CREATE USER backend 
  become: true
  mysql_user:
    name: "{{ backend_db_user}}"
    password: "{{ backend_db_password }}"
    priv: "{{ backend_db_name }}.*:ALL"
    state: present
    check_implicit_admin: yes
    login_unix_socket: /var/run/mysqld/mysqld.sock
- name: change mysqld.cnf bind-address
  become: true
  replace:
    path: /etc/mysql/mysql.conf.d/mysqld.cnf
    regexp: '127.0.0.1'
    replace: '0.0.0.0'
  register: mysqld_cnf
- name: Enable MySQL and Run
  become: true
  systemd:
    name: mysql
    enabled: yes
    state: started
- name: restart MySQL service
  become: true
  systemd:
    name: mysql
    state: restarted
  when: mysqld_cnf.changed

database/defaults/main.yml

---
# defaults file for database
backend_db_name: tutorials
backend_db_user: backend
backend_db_password: acit4640

Vagrantfile

Vagrant.configure("2") do |config|
    config.vm.box = "ubuntu/focal64"

    config.vm.synced_folder ".", "/vagrant", disabled: true

    config.vm.boot_timeout = 60000

    config.vm.provider "virtualbox" do |vb|
        vb.gui = true
        vb.linked_clone = true
        vb.customize [ "modifyvm", :id, "--uartmode1", "disconnected" ]
    end

    config.vm.define "backend" do |backend|
        backend.vm.provider "virtualbox" do |vb|
            vb.name = "BACKEND"
	end
	backend.vm.network "private_network", ip: "192.168.150.10"
	backend.vm.network "forwarded_port", guest: 80, host: 8090
        backend.vm.provision "ansible" do |ansible|
            ansible.playbook = "tutorials.yaml"
        end
    end
    config.vm.define "frontend" do |frontend|
        frontend.vm.provider "virtualbox" do |vb|
            vb.name = "FRONTEND"
        end
	frontend.vm.network "private_network", ip: "192.168.150.11"
        frontend.vm.network "forwarded_port", guest: 80, host: 8080
	frontend.vm.provision "ansible" do |ansible|
            ansible.playbook = "tutorials.yaml"
        end
    end
    config.vm.define "database" do |database|
        database.vm.provider "virtualbox" do |vb|
            vb.name = "DATABASE"
        end
	database.vm.network "private_network", ip: "192.168.150.12"
	database.vm.network "forwarded_port", guest: 3306, host: 12002
        database.vm.provision "ansible" do |ansible|
            ansible.playbook = "tutorials.yaml"
        end
    end
end

Run Vagrantfile

vagrant up
vagrant provision

2 thoughts on “Vagrant Multi Machine setup automation with Ansible Playbook”

  1. Hairstyles says:
    May 4, 2022 at 11:25 am

    Great blog! Is your theme custom made or did you download it from somewhere? A theme like yours with a few simple tweeks would really make my blog shine. Please let me know where you got your design. Many thanks

    Reply
  2. Oren Sirmans says:
    July 19, 2022 at 10:26 pm

    Aw, this was a really good post. Taking the time and actual effort to generate a superb article… but what can I say… I procrastinate a lot and don’t manage to get nearly anything done.

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts
  • ChinguTalkBot v0.1.0: Setting up AWS Cognito with CDK for User Authentication
  • Phoenix & Elixir: Fix PostgreSQL connection refused
  • Demo: Git Log with Shell script to create a release notes
  • Metasploit
  • CyberSecurity Lab – Online Password Attack

Archives
  • March 2024
  • May 2023
  • April 2023
  • February 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
Categories
  • Amazon Interview (3)
  • Ansible (3)
  • AWS (9)
  • Azure (9)
  • Certification (2)
  • ChinguTalkBot Project (1)
  • cybersecurity (3)
  • Data analytics (6)
  • Demo Videos (6)
  • Docker (5)
  • Git (1)
  • GitLab (1)
  • Golang (3)
  • JavaScript (2)
  • Jenkins (4)
  • PowerShell (1)
  • Python (10)
  • Terraform (11)
  • Uncategorized (9)

©2025 | Powered by WordPress and Superb Themes!