ansible
install
# apt install ansible
$ ansible -i hosts_init playbook.yml --ask-become-password
hosts
hosts_sshd
---
servers:
hosts:
<HOSTNAME>:
ansible_host: <IP>
ansible_user: <USERNAME>
ansible_private_key_file: ~/.ssh/<PRIVATE_KEY>
ansible_port: 22
apps:
- name: test_app
mode: dev
version: "1.0"
python_minor: 12
hosts_users
---
servers:
hosts:
<HOSTNAME>:
ansible_host: <IP>
ansible_user: <USERNAME>
ansible_private_key_file: ~/.ssh/<PRIVATE_KEY>
ansible_port: <SSHD_PORT>
hosts
---
servers:
hosts:
<HOSTNAME>:
ansible_host: <IP>
ansible_become_method: su
ansible_become_exe: "su -"
ansible_become_user: root
ansible_user: <USERNAME>
ansible_private_key_file: ~/.ssh/<PRIVATE_KEY>
ansible_port: <SSHD_PORT>
apps:
- name: test_app
mode: dev
version: "1.0"
python_minor: 12
system
sshd config
sshd.yml
---
- name: Change sshd config
hosts: all
become: true
vars:
sshd_config_path: "/etc/ssh/sshd_config"
sshd_port: <PORT>
tasks:
- name: Update SSHD config to change port
ansible.builtin.lineinfile:
path: "{{ sshd_config_path }}"
regexp: '^#?Port '
line: "Port {{ sshd_port }}"
state: present
- name: Restart SSH service to apply changes
ansible.builtin.service:
name: ssh
state: restarted
nftables
nftables.yml
---
- name: Configure nftables (+remove iptables)
hosts: all
become: true
tasks:
- name: Remove iptables if present
ansible.builtin.package:
name: iptables
state: absent
- name: Remove iptables-persistent if present
ansible.builtin.package:
name: iptables-persistent
state: absent
- name: Install nftables
ansible.builtin.package:
name: nftables
state: present
- name: Configure nftables rules
ansible.builtin.template:
src: templates/nftables_conf.j2
dest: /etc/nftables.conf
mode: '0644'
- name: Enable nftables service
ansible.builtin.systemd:
name: nftables
enabled: true
state: started
- name: Apply nftables rules
ansible.builtin.command:
cmd: nft -f /etc/nftables.conf
templates/nftables_conf.j2
table ip filter {
chain INPUT {
type filter hook input priority 0; policy drop;
iifname "lo" counter accept
{% for interface in ansible_facts['interfaces'] if 'lo' not in interface %}
iifname "{{ interface }}" tcp dport 53 counter accept
iifname "{{ interface }}" udp dport 53 counter accept
iifname "{{ interface }}" tcp dport 80 counter accept
iifname "{{ interface }}" tcp dport 443 counter accept
iifname "{{ interface }}" tcp dport <SSHD_PORT> counter accept
iifname "{{ interface }}" tcp dport smtp counter accept
iifname "{{ interface }}" udp dport ntp counter accept
iifname "{{ interface }}" icmp type echo-request counter accept
iifname "{{ interface }}" ct state established,related counter accept
iifname "{{ interface }}" counter log prefix "[NFTABLES IN] : " level debug
{% endfor %}
}
chain FORWARD {
type filter hook forward priority 0; policy drop;
{% for interface in ansible_facts['interfaces'] if 'lo' not in interface %}
iifname "{{ interface }}" counter log prefix "[NFTABLES FWD] : " level debug
{% endfor %}
}
chain OUTPUT {
type filter hook output priority 0; policy drop;
oifname "lo" counter accept
{% for interface in ansible_facts['interfaces'] if 'lo' not in interface %}
oifname "{{ interface }}" udp dport ntp counter accept
oifname "{{ interface }}" tcp dport domain counter accept
oifname "{{ interface }}" udp dport domain counter accept
oifname "{{ interface }}" tcp dport http counter accept
oifname "{{ interface }}" tcp dport https counter accept
oifname "{{ interface }}" tcp dport ssh counter accept
oifname "{{ interface }}" tcp dport smtp counter accept
oifname "{{ interface }}" tcp dport imaps counter accept
oifname "{{ interface }}" tcp dport postgresql counter accept
oifname "{{ interface }}" tcp dport <SSHD_PORT> counter accept
oifname "{{ interface }}" ct state established,related counter accept
oifname "{{ interface }}" icmp type echo-request counter accept
oifname "{{ interface }}" counter log prefix "[NFTABLES OUT] : " level debug
{% endfor %}
}
}
setup users
users.yml
---
- name: Configure root/non-root users
hosts: all
become: true
vars:
new_root_pwd: <PASSWD>
new_user: <NON_ROOT_USER>
ssh_public_key: "{{ lookup('file', '~/.ssh/<FILE_PUBKEY>.pub') }}"
tasks:
- name: Set root password
ansible.builtin.command:
cmd: echo "root:{{ new_root_pwd }}" | chpasswd
- name: Add new user
ansible.builtin.user:
name: "{{ new_user }}"
shell: /bin/bash
state: present
- name: Create .ssh directory for the new user
ansible.builtin.file:
path: "/home/{{ new_user }}/.ssh"
state: directory
owner: "{{ new_user }}"
group: "{{ new_user }}"
mode: '0700'
- name: Add public key to authorized_keys for the new user
ansible.builtin.copy:
dest: "/home/{{ new_user }}/.ssh/authorized_keys"
content: "{{ ssh_public_key }}"
owner: "{{ new_user }}"
group: "{{ new_user }}"
mode: '0600'
- name: Remove sudo package
ansible.builtin.package:
name: sudo
state: absent
remove "debian" user
remove_debian.yml
---
- name: Configure root/non-root users
hosts: all
become: true
- name: Remove user debian
ansible.builtin.user:
name: "debian"
state: absent
remove ipv6
sys_ipv6_off.yml
---
- name: Disable IPv6
hosts: all
become: yes
tasks:
- name: Disable IPv6
ansible.builtin.lineinfile:
path: /etc/sysctl.conf
line: 'net.ipv6.conf.all.disable_ipv6 = 1'
state: present
notify:
- Sysctl reload
handlers:
- name: Sysctl reload
ansible.builtin.command:
cmd: sysctl -p
postgreSQL
postgresql.yml
---
- name: Install and configure postgreSQL
hosts: all
become: yes
tasks:
- name: Update apt
apt:
update_cache: yes
- name: Install package
apt:
name:
- postgres
state: present
uwsgi
uwsgi.yml
---
- name: Config uwsgi
hosts: all
become: yes
tasks:
- name: Create virtualenv directory
ansible.builtin.file:
path: /var/srvr/{{ item.name }}
state: directory
owner: {{ ansible_user }}
group: {{ ansible_user }}
loop: "{{ apps }}"
- name: Create socket directory
ansible.builtin.file:
path: /var/uwsgi
state: directory
owner: nginx
group: nginx
- name: Check if sockets exist
ansible.builtin.stat:
path: /var/uwsgi/{{ item}}.socket
loop: "{{ apps }}"
register: sockets_stats
- name: Create socket
ansible.builtin.file:
path: /var/uwsgi/{{ item.item.name }}.socket
state: touch
owner: nginx
group: nginx
when: not item.stat.exists
loop: "{{ sockets_stats.results }}"
- name: Check if log files exist
ansible.builtin.stat:
path: /var/log/uwsgi/{{ item.name }}.log
loop: "{{ apps }}"
register: logfiles_stats
- name: Create log file
ansible.builtin.file:
path: /var/log/uwsgi/{{ item.item.name }}.log
state: touch
owner: nginx
group: nginx
when: not item.stat.exists
loop: "{{ logfiles_stats.results }}"
- name: Config emperor.ini
ansible.builtin.template:
src: /home/rico/ansible/templates/uwsgi_emperor.j2
dest: /etc/uwsgi-emperor/emperor.ini
owner: root
group: root
- name: Config app.ini
ansible.builtin.template:
src: /home/rico/ansible/templates/uwsgi_app.j2
dest: /etc/uwsgi-emperor/vassals/{{ item.name }}.ini
loop: "{{ apps }}"
templates
templates/uwsgi_emperor.j2
[uwsgi]
master = true
workers = {{ ansible_processor_vcpus }}
no-orphans = true
log-data = true
uid = nginx
gid = nginx
emperor = /etc/uwsgi-emperor/vassals
templates/uwsgi_app.j2
[uwsgi]
env = APP_HOST={{ ansible_hostname}}
env = APP_ENV={{ item.mode }}
env = APP_VERSION={{ item.version }}
virtualenv = /var/srvr/{{ item.name }}
chdir = /var/srvr/{{ item.name }}
socket = /var/uwsgi/{{ item.name }}.socket
plugins-dir = /usr/lib/uwsgi/plugins/
plugins = python3{{ python_minor }}
wsgi-file = main.py
callable = application
logto = /var/log/{{ item.name }}.log
stats = /tmp/stats_%n
{% if item.mode == 'dev' %}py-autoreload = 3{% endif %}