commit 968722c8d538ca2123aa118c36ee41f6400ac8e7 Author: Jim Myhrberg Date: Sat Dec 28 19:07:06 2019 +0000 feat: Initial working adguardhome role diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..ad0be76 --- /dev/null +++ b/.yamllint @@ -0,0 +1,11 @@ +extends: default + +rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + line-length: disable + truthy: disable diff --git a/README.md b/README.md new file mode 100644 index 0000000..011fba5 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should +be mentioned here. For instance, if the role uses the EC2 module, it may be a +good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including +any variables that are in defaults/main.yml, vars/main.yml, and any variables +that can/should be set via parameters to the role. Any variables that are read +from other roles and/or the global scope (ie. hostvars, group vars, etc.) should +be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in +regards to parameters that may need to be set for other roles, or variables that +are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables +passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: ansible-adguardhome, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a +website (HTML is not allowed). diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..ebb94b1 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,22 @@ +--- +adguardhome_version: '0.100.8' +adguardhome_user: root +adguardhome_system_user: yes +adguardhome_group: "{{ adguardhome_user }}" + +adguardhome_service_name: "adguardhome" +adguardhome_bin_dir: "/opt/{{ adguardhome_service_name }}/bin" +adguardhome_config_dir: "/opt/{{ adguardhome_service_name }}/config" +adguardhome_data_dir: "/opt/{{ adguardhome_service_name }}" +adguardhome_tmp_dir: /tmp + +adguardhome_bin_name: AdGuardHome +adguardhome_config_name: config.yml + +adguardhome_bin_file: "{{ adguardhome_bin_dir }}/{{ adguardhome_bin_name }}" +adguardhome_config_file: "{{ adguardhome_config_dir }}/{{ adguardhome_config_name }}" +adguardhome_unpack_dir: "{{ adguardhome_tmp_dir }}/AdGuardHome-{{ adguardhome_version }}" + +adguardhome_arch: "{% if ansible_architecture == 'x86_64' %}amd64{% elif ansible_architecture == 'aarch64' %}arm64{% else %}arm{% endif %}" +adguardhome_archive: "AdGuardHome_linux_{{ adguardhome_arch }}.tar.gz" +adguardhome_download_url: "https://github.com/AdguardTeam/AdGuardHome/releases/download/v{{ adguardhome_version }}/{{ adguardhome_archive }}" diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..aced512 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: restart adguardhome + systemd: + name: adguardhome + state: restarted + daemon_reload: yes diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..84d9637 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,21 @@ +--- +dependencies: [] +galaxy_info: + author: Jim Myhrberg + description: Install AdGuard Home + license: MIT + min_ansible_version: 2.0 + platforms: + - name: Ubuntu + versions: + - bionic + - xenial + - name: EL + versions: + - 7 + - 8 + galaxy_tags: + - adblocking + - adguard + - dns + - networking diff --git a/molecule/default/Dockerfile.j2 b/molecule/default/Dockerfile.j2 new file mode 100644 index 0000000..4fb03b5 --- /dev/null +++ b/molecule/default/Dockerfile.j2 @@ -0,0 +1,34 @@ +# Molecule managed + +{% if item.registry is defined %} +FROM {{ item.registry.url }}/{{ item.image }} +{% else %} +FROM {{ item.image }} +{% endif %} + +RUN if [ $(command -v apt-get) ]; then \ + apt-get update && \ + apt-get install -y python sudo bash ca-certificates net-tools && \ + apt-get clean; \ + elif [ $(command -v dnf) ]; then \ + dnf makecache && \ + dnf --assumeyes install \ + sudo python3 *python-devel python*-dnf bash net-tools && \ + dnf clean all; \ + elif [ $(command -v yum) ]; then \ + yum makecache fast && \ + yum install -y python3 sudo yum-plugin-ovl bash net-tools && \ + sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && \ + yum clean all; \ + elif [ $(command -v zypper) ]; then \ + zypper refresh && \ + zypper install -y python sudo bash python-xml && \ + zypper clean -a; \ + elif [ $(command -v apk) ]; then \ + apk update && \ + apk add --no-cache python sudo bash ca-certificates; \ + elif [ $(command -v xbps-install) ]; then \ + xbps-install -Syu && \ + xbps-install -y python sudo bash ca-certificates && \ + xbps-remove -O; \ + fi diff --git a/molecule/default/INSTALL.rst b/molecule/default/INSTALL.rst new file mode 100644 index 0000000..6a44bde --- /dev/null +++ b/molecule/default/INSTALL.rst @@ -0,0 +1,22 @@ +******* +Docker driver installation guide +******* + +Requirements +============ + +* Docker Engine + +Install +======= + +Please refer to the `Virtual environment`_ documentation for installation best +practices. If not using a virtual environment, please consider passing the +widely recommended `'--user' flag`_ when invoking ``pip``. + +.. _Virtual environment: https://virtualenv.pypa.io/en/latest/ +.. _'--user' flag: https://packaging.python.org/tutorials/installing-packages/#installing-to-the-user-site + +.. code-block:: bash + + $ pip install 'molecule[docker]' diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..0d59f0b --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,50 @@ +--- +dependency: + name: galaxy +driver: + name: docker +lint: + name: yamllint +platforms: + - name: centos-7 + image: centos:7 + command: /sbin/init + tmpfs: + - /run + - /tmp + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + - name: centos-8 + image: centos:8 + command: /sbin/init + tmpfs: + - /run + - /tmp + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + - name: ubuntu-16.04 + image: jrei/systemd-ubuntu:16.04 + command: /sbin/init + privileged: true + tmpfs: + - /run + - /tmp + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + - name: ubuntu-18.04 + image: jrei/systemd-ubuntu:18.04 + command: /sbin/init + privileged: true + tmpfs: + - /run + - /tmp + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro +provisioner: + name: ansible + lint: + name: ansible-lint +verifier: + name: testinfra + lint: + name: flake8 diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml new file mode 100644 index 0000000..2a711be --- /dev/null +++ b/molecule/default/playbook.yml @@ -0,0 +1,5 @@ +--- +- name: Converge + hosts: all + roles: + - role: ansible-adguardhome diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py new file mode 100644 index 0000000..00f2edb --- /dev/null +++ b/molecule/default/tests/test_default.py @@ -0,0 +1,49 @@ +import os + +import testinfra.utils.ansible_runner + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') + + +def test_adguardhome_config_dir(host): + d = host.file('/opt/adguardhome/config') + + assert d.exists + assert d.is_directory + assert d.mode == 0o755 + assert d.user == 'root' + assert d.group == 'root' + + +def test_adguardhome_data_dir(host): + d = host.file('/opt/adguardhome') + + assert d.exists + assert d.is_directory + assert d.mode == 0o755 + assert d.user == 'root' + assert d.group == 'root' + + +def test_adguardhome_binary(host): + f = host.file("/opt/adguardhome/bin/AdGuardHome") + + assert f.exists + assert f.is_file + assert f.mode == 0o755 + assert f.user == 'root' + assert f.group == 'root' + + +def test_adguardhome_service(host): + s = host.service('adguardhome') + + assert s.is_enabled + assert s.is_running + + +def test_adguardhome_http_setup(host): + socket = host.socket('tcp://127.0.0.1:3000') + + assert socket.is_listening diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5bd5db3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +ansible +ansible-lint +flake8 +molecule[docker] +yamllint diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..648d4cc --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,113 @@ +--- +- include_tasks: setup_debian.yml + when: ansible_os_family == 'Debian' + +- include_tasks: setup_redhat.yml + when: ansible_os_family == 'RedHat' + +- name: Ensure user exists + user: + name: "{{ adguardhome_user }}" + create_home: no + system: "{{ adguardhome_system_user }}" + state: present + +- name: Check if binary is installed + stat: + path: "{{ adguardhome_bin_file }}" + register: adguardhome_binary_check + +- name: Check version of installed binary + shell: >- + set -o pipefail + && "{{ adguardhome_bin_file }}" -c /dev/null --check-config 2>&1 + | grep -m 1 -E 'v[0-9.]+' -o + args: + executable: /bin/bash + register: adguardhome_version_check + check_mode: no + changed_when: >- + adguardhome_version_check.stdout.find('v' + adguardhome_version) == -1 + failed_when: >- + adguardhome_version_check.rc != 0 and adguardhome_version_check.rc != 141 + when: >- + adguardhome_binary_check.stat.exists + +- name: Install binary + block: + - name: Ensure bin directory exists + file: + dest: "{{ adguardhome_bin_dir }}" + recurse: yes + state: directory + - name: Create temporary directory + file: + dest: "{{ adguardhome_unpack_dir }}" + recurse: yes + state: directory + - name: "Download and extract {{ adguardhome_arch }} archive" + unarchive: + src: "{{ adguardhome_download_url }}" + dest: "{{ adguardhome_unpack_dir }}" + remote_src: yes + extra_opts: + - "--strip-components=1" + - name: "Copy binary to {{ adguardhome_bin_dir }}/" + copy: + src: "{{ adguardhome_unpack_dir }}/{{ adguardhome_bin_name }}" + dest: "{{ adguardhome_bin_file }}" + mode: "755" + remote_src: yes + - name: Remove temporary directory + file: + path: "{{ adguardhome_unpack_dir }}" + state: absent + when: >- + adguardhome_version_check.changed + or (not adguardhome_binary_check.stat.exists) + +- name: Ensure data directory exists and has correct permissions + file: + path: "{{ adguardhome_data_dir }}" + owner: "{{ adguardhome_user }}" + group: "{{ adguardhome_group }}" + mode: "755" + recurse: yes + state: directory + +- name: Ensure config directory exists and has correct permissions + file: + path: "{{ adguardhome_config_dir }}" + owner: "{{ adguardhome_user }}" + group: "{{ adguardhome_group }}" + mode: "755" + recurse: yes + state: directory + +- name: Allow binary to bind to ports lower than 1024 as a non-root user + capabilities: + path: "{{ adguardhome_bin_file }}" + capability: CAP_NET_BIND_SERVICE=+eip + state: present + when: >- + adguardhome_user != "root" + +- name: Disallow binary to bind to ports lower than 1024 as a non-root user + capabilities: + path: "{{ adguardhome_bin_file }}" + capability: CAP_NET_BIND_SERVICE=+eip + state: absent + when: >- + adguardhome_user == "root" + +- name: Install sytemd service + template: + src: adguardhome.service.j2 + dest: /etc/systemd/system/adguardhome.service + mode: "755" + notify: restart adguardhome + +- name: Ensure service is enabled + service: + name: adguardhome + enabled: yes diff --git a/tasks/setup_debian.yml b/tasks/setup_debian.yml new file mode 100644 index 0000000..054a1b2 --- /dev/null +++ b/tasks/setup_debian.yml @@ -0,0 +1,5 @@ +--- +- name: Install dependencies + package: + name: libcap2-bin + state: present diff --git a/tasks/setup_redhat.yml b/tasks/setup_redhat.yml new file mode 100644 index 0000000..ee8c26b --- /dev/null +++ b/tasks/setup_redhat.yml @@ -0,0 +1,5 @@ +--- +- name: Install dependencies + package: + name: libcap + state: present diff --git a/templates/adguardhome.service.j2 b/templates/adguardhome.service.j2 new file mode 100644 index 0000000..1d0aede --- /dev/null +++ b/templates/adguardhome.service.j2 @@ -0,0 +1,19 @@ +[Unit] +Description=AdGuard Home +ConditionFileIsExecutable="{{ adguardhome_bin_file }}" +After=syslog.target +After=network-online.target + +[Service] +Type=simple +User={{ adguardhome_user }} +Group={{ adguardhome_group }} +StartLimitInterval=5 +StartLimitBurst=10 +WorkingDirectory={{ adguardhome_data_dir }} +ExecStart="{{ adguardhome_bin_file }}" --work-dir "{{ adguardhome_data_dir }}" --config "{{ adguardhome_config_file }}" +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..f10f78f --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for ansible-adguardhome