Ansible
Setup Ansible Controle panel​
Install Ansible in Alpine​
apk add --update ansible sshpass python3 py3-pip && ln -sf python3 /usr/bin/python
pip install pywinrm # This is required If target is Windows OS
ansible-galaxy collection install community.general # Install if required
ansible-galaxy collection install ansible.posix # Install if required
Install Ansible in Ubutu​
sudo apt-get update
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible -y
Establish Connecton​
Target Windows (winrm)​
- Check whether WinRM service is running.
winrm quickconfig
- Create HTTPS listener
Run the bleow Powershell commands in Administrator mode
# List listeners
WinRM e winrm/config/listener
# Generate self signed certificate
New-SelfSignedCertificate -DnsName "<YOUR_DNS_NAME>" -CertStoreLocation Cert:\LocalMachine\My
# Create HTTPS Listeners
winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname="<YOUR_DNS_NAME>"; CertificateThumbprint="<COPIED_CERTIFICATE_THUMBPRINT>"}'
# Delete Listeners
winrm delete winrm/config/Listener?Address=*+Transport=HTTPS
- Add firewall exception
Open the port 5985
for HTTP
and 5986
for HTTPS
(recomended) in the target Windows OS
firewall and Cloud provider's Security Group / Networking
.
Validate HTTPS listener
WinRM e winrm/config/listener
Verify you can connect to the machine via HTTPS
Run the bleow Powershell commands in Administrator mode
$hostName="<DNS_NAME>" # example: "mission.westus.cloudapp.azure.com"
$winrmPort = "5986"
# Get the credentials of the machine
$cred = Get-Credential
# Connect to the machine
$soptions = New-PSSessionOption -SkipCACheck
Enter-PSSession -ComputerName $hostName -Port $winrmPort -Credential $cred -SessionOption $soptions -UseSSL
To Allow Unencrypted Password, run the following command (Not Recomended)
Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
Reference
Target Ubuntu (SSH)​
Install the
OpenSSH Server
in target OSRun the
OpenSSH Server
service in the target OSconnect using
ssh username@hostname
. Ex.ssh admin@192.168.0.1
(or)ssh -i key.pem username@hostname
TODO:
Sample Inventory file​
Target - Windows OS​
[GCP]
43.81.83.173
[GCP:vars]
ansible_connection=winrm
ansible_user=ansibleadmin
ansible_password=admin@123
ansible_port=5986
ansible_winrm_server_cert_validation=ignore
Target - Linux/Other OS​
TODO:
Ansible Vault Ref​
TODO:
Ansible Key Features​
Lookup​
INI Lookup Example​
[production]
# My production information
user=robert
pass=somerandompassword
[integration]
# My integration information
user=gertrude
pass=anotherpassword
We can use the ini plugin to lookup user configuration:
- debug: msg="User in integration is {{ lookup('ini', 'user section=integration file=users.ini') }}"
- debug: msg="User in production is {{ lookup('ini', 'user section=production file=users.ini') }}"
Java properties Lookup Example​
user.name=robert
user.pass=somerandompassword
You can retrieve the user.name field with the following lookup:
- debug: msg="user.name is {{ lookup('ini', 'user.name type=properties file=user.properties') }}"
Sample Playbooks​
Windows: Angular Application Deployed in NGINX Web Server​
(Controle plane is Ubntu -> Target OS is Windows)
Tasks​
- Install the NGINX Web Server
- Configure the NGINX Web Server by edit/copy the nginx.conf file
- Run the NGINX as windows service
- Zip the Angular distribution folder
- Copy to the target machine
- Remove existing deployment
- Unzip the file
Playbook file​
Deploy the static web application (html/css) in NGINX Web Server
playbook.yml
- hosts: {{HOSTS}}
remote_user: root
gather_facts: False
pre_tasks:
- debug: msg="Ansible is working!"
- name: ping
win_ping:
tasks:
# Install NGINX WebServer
- name: Install NGINX
win_chocolatey:
name: nginx
version: '1.12.1'
state: present
- name: Install nssm
win_chocolatey:
name: nssm
state: present
- name: Copy NGINX conf file
win_template:
src: nginx.conf.tpl
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\nginx.conf
- name: Copy Cert file 1
win_template:
src: ../cert.pem
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\cert.pem
- name: Copy Cert file 2
win_template:
src: ../cert.key
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\cert.key
- name: Create Log Folder
win_file:
path: C:\nginx
state: directory
- name: Install nginx as service
win_nssm:
name: nginx
application: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\nginx.exe
app_parameters_free_form: -c C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\nginx.conf -p C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1
stdout_file: C:\nginx\nginx_out.txt
stderr_file: C:\nginx\nginx_error.txt
start_mode: auto
- name: Start Nginx
win_service:
name: nginx
start_mode: auto
state: started
# https://docs.ansible.com/ansible/2.5/modules/win_firewall_rule_module.html
- name: Firewall rules
win_firewall_rule:
name: "{{ item.name }}"
localport: "{{ item.port }}"
action: allow
direction: in
protocol: tcp
state: present
enabled: yes
with_items:
- {name: HTTP, port: 80}
- {name: HTTPS, port: 443}
- {name: WINRM-HTTPS, port: 5986}
# Deploy the Angular Application
- name: Archive the Angular Application
archive:
path: /opt/atlassian/pipelines/agent/build/dist/Mission-web
dest: ./app.zip
format: zip
delegate_to: localhost
become: false
- name: Copy zip File to target
win_copy:
src: ./app.zip
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\
- name: Unarchive
win_unzip:
src: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\app.zip
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\
delete_archive: yes
- name: Remove existing ui deployment
win_file:
path: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\html
state: absent
- name: Create Folder
win_file:
path: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\html
state: directory
- name: Move Content
win_copy:
remote_src: yes
src: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\Mission-web\
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\html\
- name: Remove directory structure
win_file:
path: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\Mission-web
state: absent
Windeows: Spring Boot Application Deploy as Windows Service In Winsows​
Tasks​
- Install the NGINX Web Server
Playbook file​
- hosts: {{HOSTS}}
remote_user: root
gather_facts: False
pre_tasks:
- debug: msg="Ansible is working in control machine"
- name: Client machine connectivity check by Ping
win_ping:
tasks:
# PROXY Server Deployment
- name: Install NGINX
win_chocolatey:
name: nginx
version: '1.12.1'
state: present
- name: Install nssm
win_chocolatey:
name: nssm
state: present
- name: Copy NGINX conf file
win_template:
src: nginx.conf.tpl
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\nginx.conf
# Certificate (.pem & .key ) files copy to target machine
- name: Copy Cert file 1
win_template:
src: ../cert.pem
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\cert.pem
- name: Copy Cert file 2
win_template:
src: ../cert.key
dest: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\cert.key
- name: Create Log Folder
win_file:
path: C:\nginx
state: directory
- name: Install nginx as service
win_nssm:
name: nginx
application: C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\nginx.exe
app_parameters_free_form: -c C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1\conf\nginx.conf -p C:\ProgramData\chocolatey\lib\nginx\tools\nginx-1.12.1
stdout_file: C:\nginx\nginx_out.txt
stderr_file: C:\nginx\nginx_error.txt
start_mode: auto
- name: Start Nginx
win_service:
name: nginx
start_mode: auto
state: started
# https://docs.ansible.com/ansible/2.5/modules/win_firewall_rule_module.html
- name: Firewall rules
win_firewall_rule:
name: "{{ item.name }}"
localport: "{{ item.port }}"
action: allow
direction: in
protocol: tcp
state: present
enabled: yes
with_items:
- {name: HTTP, port: 80}
- {name: HTTPS, port: 443}
- {name: WINRM-HTTPS, port: 5986}
# REST API Deployment
- name: Remove Spring Boot service
win_service:
name: mission-api
state: absent
ignore_errors: yes
- name: Create Application Folder
win_file:
path: C:\Mission\App
state: directory
- name: Copy API application
copy:
src: /opt/atlassian/pipelines/agent/build/target/mission-app-core-1.0-SNAPSHOT.jar
dest: C:\Mission\App\mission-app-core-1.0-SNAPSHOT.jar
directory_mode: yes
- name: Archive the Config
archive:
path: /opt/atlassian/pipelines/agent/build/src/main/resources/config
dest: ./config.zip
format: zip
delegate_to: localhost
become: false
- name: Copy zip File to target
win_copy:
src: ./config.zip
dest: C:\Mission\
- name: Remove existing Config
win_file:
path: C:\Mission\config
state: absent
- name: Unarchive
win_unzip:
src: C:\Mission\config.zip
dest: C:\Mission\
delete_archive: yes
# - name: Install Java
# win_chocolatey:
# name: jdk8
# state: present
# version: 8.0.191
# https://community.chocolatey.org/packages/openjdk8#ansible
- name: Install openjdk8
win_chocolatey:
name: openjdk8
version: '8.312.07'
source: https://community.chocolatey.org/api/v2/
state: present
- name: Set Java_home
win_environment:
state: present
name: JAVA_HOME
value: 'C:\Program Files\java\jdk1.8.0_191'
level: machine
- name: Add Java to path
win_path:
elements:
- 'C:\Program Files\java\jdk1.8.0_191\bin'
- name: Install Spring Boot app as Windows service (via nssm)
win_nssm:
name: mission-api
application: C:\Program Files\java\jdk1.8.0_191\bin\java.exe
app_parameters_free_form: "-jar C:/Mission/App/mission-app-core-1.0-SNAPSHOT.jar"
state: stopped
- name: Set the Application path for the Spring Boot app to the folder where the needed native libraries reside
raw: nssm set mission-api AppDirectory C:/Mission/
- name: Set SPRING_DATASOURCE_URL
win_environment:
state: present
name: SPRING_DATASOURCE_URL
value: 'jdbc:postgresql://{{dburl}}:{{dbport}}/{{dbname}}'
level: machine
- name: Set SPRING_DATASOURCE_USERNAME
win_environment:
state: present
name: SPRING_DATASOURCE_USERNAME
value: '{{dbusername}}'
level: machine
- name: Set SPRING_DATASOURCE_PASSWORD
win_environment:
state: present
name: SPRING_DATASOURCE_PASSWORD
value: '{{dbpassword}}'
level: machine
- name: Set SERVER_PORT
win_environment:
state: present
name: SERVER_PORT
value: '{{serverport}}'
level: machine
- name: Fire up Spring Boot app Windows service
win_service:
name: mission-api
state: restarted
###### Smoke test, if app has booted up correctly
# - name: Wait until our Spring Boot app is up & running
# win_uri:
# url: "https://{{SUBDOMAIN}}.mission.io/miosvc/actuator/health"
# method: GET
# register: result
# until: result.status_code is defined and result.status_code == 200
# retries: 5
# delay: 5
Debian: Spring Boot Application deploy​
Tasks​
Playbook file​
playbook.yml
- hosts: all
remote_user: amazeadmin
gather_facts: false
vars:
ansible_python_interpreter: /usr/bin/python3
become: true
tasks:
- name: Install Prerequisites
apt:
name: aptitude
update_cache: yes
state: latest
force_apt_get: yes
# Sudo Group Setup
- name: Make sure we have a 'wheel' group
group:
name: wheel
state: present
- name: Allow 'wheel' group to have passwordless sudo
lineinfile:
path: /etc/sudoers
state: present
regexp: '^%wheel'
line: '%wheel ALL=(ALL) NOPASSWD: ALL'
validate: '/usr/sbin/visudo -cf %s'
# User + Key Setup
- name: Create a new regular user with sudo privileges
user:
name: amazeadmin
state: present
groups: wheel
append: true
create_home: true
shell: /bin/bash
- name: Set authorized key for remote user
authorized_key:
user: amazeadmin
state: present
key: "{{ lookup('file', './amazeadmin.pub') }}"
# key: ./amazeadmin.pub
- name: Disable password authentication for root
lineinfile:
path: /etc/ssh/sshd_config
state: present
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin prohibit-password'
# Install Packages
- name: Update apt
apt: update_cache=yes
- name: Install required system packages
apt: name=ufw state=latest
# UFW Setup
- name: UFW - Allow SSH connections
ufw:
rule: allow
name: OpenSSH
- name: UFW - Deny all other incoming traffic by default
ufw:
state: enabled
policy: deny
direction: incoming
- name: Install latest version of "openjdk-11-jdk" ignoring "install-recommends"
apt:
name: openjdk-11-jdk
state: latest
install_recommends: no