From 71a43ccf075544b12d21c618d1e4ea2bd66cd2e1 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Fri, 7 Jul 2023 09:53:23 -0500 Subject: [PATCH] unifi: Deploy Unifi Network controller Since Ubiquiti only publishes Debian packages for the Unifi Network controller software, running it on Fedora has historically been neigh impossible. Fortunately, a modern solution is available: containers. The *linuxserver.io* project publishes a container image for the controller software, making it fairly easy to deploy on any host with an OCI runtime. I briefly considered creating my own image, since theirs must be run as root, but I decided the maintenance burden would not be worth it. Using Podman's user namespace functionality, I was able to work around this requirement anyway. --- group_vars/unifi.yml | 1 + hosts | 2 + roles/unifi/defaults/main.yml | 3 + roles/unifi/handlers/main.yml | 8 ++ roles/unifi/tasks/deploy.yml | 97 +++++++++++++++++++++++ roles/unifi/tasks/install.yml | 12 +++ roles/unifi/tasks/main.yml | 7 ++ roles/unifi/templates/unifi.container.j2 | 29 +++++++ roles/unifi/templates/unifi.nginx.conf.j2 | 9 +++ unifi.yml | 5 ++ 10 files changed, 173 insertions(+) create mode 100644 group_vars/unifi.yml create mode 100644 roles/unifi/defaults/main.yml create mode 100644 roles/unifi/handlers/main.yml create mode 100644 roles/unifi/tasks/deploy.yml create mode 100644 roles/unifi/tasks/install.yml create mode 100644 roles/unifi/tasks/main.yml create mode 100644 roles/unifi/templates/unifi.container.j2 create mode 100644 roles/unifi/templates/unifi.nginx.conf.j2 create mode 100644 unifi.yml diff --git a/group_vars/unifi.yml b/group_vars/unifi.yml new file mode 100644 index 0000000..5130ca4 --- /dev/null +++ b/group_vars/unifi.yml @@ -0,0 +1 @@ +nginx_redirect_http_https: true diff --git a/hosts b/hosts index 1dbb180..f6589c8 100644 --- a/hosts +++ b/hosts @@ -170,6 +170,8 @@ smtp1.pyrocufflink.blue [synapse] matrix0.pyrocufflink.blue +[unifi] + [victoria-metrics] [victoria-metrics:children] diff --git a/roles/unifi/defaults/main.yml b/roles/unifi/defaults/main.yml new file mode 100644 index 0000000..570f234 --- /dev/null +++ b/roles/unifi/defaults/main.yml @@ -0,0 +1,3 @@ +unifi_version: latest +unifi_container_image: lscr.io/linuxserver/unifi-controller +unifi_storage_path: /var/lib/unifi diff --git a/roles/unifi/handlers/main.yml b/roles/unifi/handlers/main.yml new file mode 100644 index 0000000..b549b6d --- /dev/null +++ b/roles/unifi/handlers/main.yml @@ -0,0 +1,8 @@ +- name: reload systemd + systemd: + daemon_reload: true + +- name: restart unifi + systemd: + name: unifi + state: restarted diff --git a/roles/unifi/tasks/deploy.yml b/roles/unifi/tasks/deploy.yml new file mode 100644 index 0000000..45d7f6a --- /dev/null +++ b/roles/unifi/tasks/deploy.yml @@ -0,0 +1,97 @@ +- name: ensure unifi group exists + group: + name: unifi + gid: 911 + system: true + state: present + tags: + - user + - group +- name: ensure unifi user exists + user: + name: unifi + uid: 911 + group: unifi + home: /var/lib/unifi + createhome: false + system: true + state: present + tags: + - user + +- name: ensure containers subuid is configured + lineinfile: + path: /etc/subuid + create: true + line: containers:39290640:1048576 + tags: + - user +- name: ensure containers subgid is configured + lineinfile: + path: /etc/subgid + line: containers:39290640:1048576 + tags: + - user + +- name: ensure unifi storage path exists + file: + path: '{{ unifi_storage_path }}' + owner: unifi + group: unifi + mode: u=rwx,go= + state: directory + tags: + - datadir + +- name: ensure unifi.container systemd unit exists + template: + src: unifi.container.j2 + dest: /etc/containers/systemd/unifi.container + owner: root + group: root + mode: u=rw,go=r + notify: + - reload systemd + - restart unifi + tags: + - systemd +- name: flush_handlers + meta: flush_handlers + +- name: ensure unifi.service is running + systemd: + name: unifi.service + state: started + tags: + - service + +- name: ensure firewall is configured for unifi + firewalld: + port: 8080/tcp + permanent: true + immediate: true + state: enabled + when: host_uses_firewalld|d(true)|bool + tags: + - firewalld + +- name: ensure nginx is configured to proxy for unifi + template: + src: unifi.nginx.conf.j2 + dest: /etc/nginx/default.d/unifi.conf + mode: u=rw,go=r + owner: root + group: root + notify: + - reload nginx + tags: + - nginx + +- name: ensure selinux allows nginx to proxy for unifi + seboolean: + name: httpd_can_network_connect + persistent: true + state: true + tags: + - nginx + - selinux diff --git a/roles/unifi/tasks/install.yml b/roles/unifi/tasks/install.yml new file mode 100644 index 0000000..4e9e437 --- /dev/null +++ b/roles/unifi/tasks/install.yml @@ -0,0 +1,12 @@ +- name: ensure podman is installed + dnf: + name: + - container-selinux + - podman + install_weak_deps: false + state: present + +- name: ensure unifi container image is present + podman_image: + name: '{{ unifi_container_image }}:{{ unifi_version }}' + state: present diff --git a/roles/unifi/tasks/main.yml b/roles/unifi/tasks/main.yml new file mode 100644 index 0000000..5072050 --- /dev/null +++ b/roles/unifi/tasks/main.yml @@ -0,0 +1,7 @@ +- block: + - import_tasks: install.yml + tags: + - install + - import_tasks: deploy.yml + tags: + - unifi diff --git a/roles/unifi/templates/unifi.container.j2 b/roles/unifi/templates/unifi.container.j2 new file mode 100644 index 0000000..ecb2569 --- /dev/null +++ b/roles/unifi/templates/unifi.container.j2 @@ -0,0 +1,29 @@ +[Unit] +Description=Unifi Network +Wants=network.target +After=network.target + +[Container] +Image={{ unifi_container_image }}:{{ unifi_version }} +Volume={{ unifi_storage_path }}:/config:rw,Z +Network=host +NoNewPrivileges=yes +UserNS=auto:gidmapping=911:911:1,uidmapping=911:911:1 +VolatileTmp=yes +Notify=yes + +[Service] +PrivateTmp=yes +ProtectClock=yes +ProtectHome=yes +ProtectKernelModules=yes +ProtectProc=invisible +ProtectSystem=strict +ReadWritePaths=/run +ReadWritePaths=/var/lib/containers/storage +ReadWritePaths={{ unifi_storage_path }} +RestrictRealtime=yes +UMask=0077 + +[Install] +WantedBy=multi-user.target diff --git a/roles/unifi/templates/unifi.nginx.conf.j2 b/roles/unifi/templates/unifi.nginx.conf.j2 new file mode 100644 index 0000000..ddc1c54 --- /dev/null +++ b/roles/unifi/templates/unifi.nginx.conf.j2 @@ -0,0 +1,9 @@ +location / { + proxy_pass https://127.0.0.1:8443/; + proxy_ssl_verify off; + client_max_body_size 50m; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} diff --git a/unifi.yml b/unifi.yml new file mode 100644 index 0000000..2055592 --- /dev/null +++ b/unifi.yml @@ -0,0 +1,5 @@ +- hosts: unifi + roles: + - role: nginx + tags: nginx + - role: unifi