Files
oswald-infra/ansible/plays/machine_setup/technitium.yml
T

266 lines
8.2 KiB
YAML

---
- name: Set up technitium LXC
hosts: technitium
become: yes
vars:
dotnet_dir: /opt/dotnet
dotnet_version: "10.0"
dotnet_runtime_prefix: "Microsoft.AspNetCore.App 10.0."
dotnet_url: "https://dot.net/v1/dotnet-install.sh"
dns_config: /etc/dns
dns_log: /var/log/technitium/dns
dns_url: "https://download.technitium.com/dns/DnsServerPortable.tar.gz"
service_user: dns-server
tasks:
- name: default_packages
ansible.builtin.include_tasks: ../../templates/default_packages.yml
- name: create_user
ansible.builtin.include_tasks: ../../templates/create_user.yml
vars:
username: nick
github_user: Chewbaccalakis
# Determine dns_dir: use /etc/dns if an existing install is detected, otherwise /opt/technitium/dns
- name: Check for existing install at /etc/dns/config
ansible.builtin.stat:
path: /etc/dns/config
register: etc_dns_config
- name: Set dns_dir for existing install
ansible.builtin.set_fact:
dns_dir: /etc/dns
dns_tar: /etc/dns/DnsServerPortable.tar.gz
when: etc_dns_config.stat.exists and etc_dns_config.stat.isdir
- name: Set dns_dir for fresh install
ansible.builtin.set_fact:
dns_dir: /opt/technitium/dns
dns_tar: /opt/technitium/dns/DnsServerPortable.tar.gz
when: not (etc_dns_config.stat.exists and etc_dns_config.stat.isdir)
- name: Create required directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- "{{ dns_dir }}"
- "{{ dns_config }}"
# .NET Runtime
- name: Check installed .NET runtimes
ansible.builtin.command: dotnet --list-runtimes
register: dotnet_runtimes
changed_when: false
failed_when: false
- name: Install ASP.NET Core Runtime
when: dotnet_runtime_prefix not in (dotnet_runtimes.stdout | default(''))
block:
- name: Download dotnet-install.sh
ansible.builtin.get_url:
url: "{{ dotnet_url }}"
dest: /tmp/dotnet-install.sh
mode: '0755'
- name: Run dotnet-install.sh
ansible.builtin.command: >
bash /tmp/dotnet-install.sh
-c {{ dotnet_version }}
--runtime aspnetcore
--no-path
--install-dir {{ dotnet_dir }}
- name: Create /usr/bin/dotnet symlink
ansible.builtin.file:
src: "{{ dotnet_dir }}/dotnet"
dest: /usr/bin/dotnet
state: link
# DNS Server
- name: Download Technitium DNS Server archive
ansible.builtin.get_url:
url: "{{ dns_url }}"
dest: "{{ dns_tar }}"
mode: '0644'
- name: Extract Technitium DNS Server
ansible.builtin.unarchive:
src: "{{ dns_tar }}"
dest: "{{ dns_dir }}"
remote_src: yes
# ICU
- name: Test ICU availability for .NET
ansible.builtin.command: "dotnet {{ dns_dir }}/DnsServerApp.dll --icu-test"
register: icu_test
changed_when: false
failed_when: false
- name: Install ICU library
when: icu_test.rc != 0
block:
- name: Find available ICU package
ansible.builtin.shell: |
for pkg in libicu74 libicu72 libicu70; do
if apt-cache show $pkg >/dev/null 2>&1; then
echo $pkg
exit 0
fi
done
echo "libicu-dev"
register: icu_package
changed_when: false
- name: Install ICU package
ansible.builtin.apt:
name: "{{ icu_package.stdout }}"
state: present
update_cache: yes
- name: Verify ICU works after install
ansible.builtin.command: "dotnet {{ dns_dir }}/DnsServerApp.dll --icu-test"
# Systemd service
- name: Check if dns.service is already installed
ansible.builtin.stat:
path: /etc/systemd/system/dns.service
register: dns_service_file
- name: Restart existing dns service (update path)
ansible.builtin.systemd:
name: dns.service
state: restarted
when: dns_service_file.stat.exists
- name: First-time service setup
when: not dns_service_file.stat.exists
block:
- name: Create DNS log directory
ansible.builtin.file:
path: "{{ dns_log }}"
state: directory
mode: '0755'
- name: Create dns-server service user
ansible.builtin.user:
name: "{{ service_user }}"
system: yes
create_home: no
shell: /usr/sbin/nologin
- name: Set ownership on DNS directories
ansible.builtin.file:
path: "{{ item }}"
owner: "{{ service_user }}"
group: "{{ service_user }}"
recurse: yes
loop:
- "{{ dns_dir }}"
- "{{ dns_config }}"
- "{{ dns_log }}"
- name: Copy systemd service file
ansible.builtin.copy:
src: "{{ dns_dir }}/systemd.service"
dest: /etc/systemd/system/dns.service
remote_src: yes
- name: Enable dns.service
ansible.builtin.systemd:
name: dns.service
enabled: yes
daemon_reload: yes
- name: Stop and disable systemd-resolved
ansible.builtin.systemd:
name: systemd-resolved
state: stopped
enabled: no
failed_when: false
- name: Start dns.service
ansible.builtin.systemd:
name: dns.service
state: started
- name: Check if NetworkManager.conf exists
ansible.builtin.stat:
path: /etc/NetworkManager/NetworkManager.conf
register: nm_conf
- name: Configure NetworkManager to not manage DNS
community.general.ini_file:
path: /etc/NetworkManager/NetworkManager.conf
section: main
option: dns
value: none
no_extra_spaces: yes
when: nm_conf.stat.exists
- name: Back up existing resolv.conf
ansible.builtin.copy:
src: /etc/resolv.conf
dest: "{{ dns_dir }}/resolv.conf.bak"
remote_src: yes
force: no
- name: Configure resolv.conf to use local DNS
ansible.builtin.copy:
dest: /etc/resolv.conf
content: |
# Generated by Technitium DNS Server Installer
nameserver 127.0.0.1
# Admin user setup
- name: Prompt for Technitium admin password
ansible.builtin.pause:
prompt: "Set Technitium admin password"
echo: no
register: technitium_pass_raw
- name: Prompt to confirm Technitium admin password
ansible.builtin.pause:
prompt: "Confirm Technitium admin password"
echo: no
register: technitium_pass_confirm
- name: Fail if passwords do not match
ansible.builtin.fail:
msg: "Passwords do not match!"
when: technitium_pass_raw.user_input != technitium_pass_confirm.user_input
- name: Wait for Technitium web console to be available
ansible.builtin.wait_for:
host: localhost
port: 5380
timeout: 60
- name: Login with default admin credentials
ansible.builtin.uri:
url: "http://localhost:5380/api/user/login"
method: GET
body_format: form-urlencoded
body:
user: admin
pass: admin
includeInfo: "true"
register: technitium_login
no_log: true
failed_when: technitium_login.json.status != 'ok'
- name: Change admin password
ansible.builtin.uri:
url: "http://localhost:5380/api/user/changePassword"
method: GET
body_format: form-urlencoded
body:
token: "{{ technitium_login.json.response.token }}"
pass: "{{ technitium_pass_raw.user_input }}"
no_log: true
failed_when: technitium_change_pass.json.status != 'ok'
register: technitium_change_pass