on-fire-within
change
commit 138dd0e3f121bdc6a488170e1827ae014690fb5d
author Alpha Chen <alpha@kejadlen.dev>
date
parent e5b090c1
diff --git a/on-fire-within/README.md b/on-fire-within/README.md
new file mode 100644
index 0000000..31c91bf
--- /dev/null
+++ b/on-fire-within/README.md
@@ -0,0 +1,16 @@
+# On Fire Within
+
+## Setup
+
+- [Installing Hass.io](https://www.home-assistant.io/hassio/installation/)
+
+1. `ansible-playbook playbooks/pi/bootstrap.yml`
+1. `ansible-playbook on-fire-within/bootstrap.yml`
+1. `curl -fsSL get.docker.com | sh`
+  - `sudo usermod -aG docker alpha`
+1. `curl -sL "https://raw.githubusercontent.com/home-assistant/hassio-installer/master/hassio_install.sh" | bash -s -- -m raspberrypi4`
+1. `ansible-playbook on-fire-within/main.yml`
+
+## Notes
+
+- `/usr/share/hassio`
diff --git a/on-fire-within/hass-io.yml b/on-fire-within/hass-io.yml
new file mode 100644
index 0000000..fc95122
--- /dev/null
+++ b/on-fire-within/hass-io.yml
@@ -0,0 +1,33 @@
+# https://www.home-assistant.io/hassio/installation/
+
+- hosts: on-fire-within
+  become: yes
+  tasks:
+    # Forgot what I need this for...
+    - name: install software-properties-common
+      apt: name=software-properties-common
+
+    - name: install other dependencies for hass.io
+      apt:
+        name:
+          - apparmor-utils
+          - apt-transport-https
+          - avahi-daemon
+          - ca-certificates
+          - curl
+          - dbus
+          - jq
+          - network-manager
+          - socat
+
+          # https://www.home-assistant.io/integrations/bluetooth_tracker/
+          - bluetooth
+          - libbluetooth-dev
+        update_cache: yes
+    - service:
+        name: ModemManager
+        enabled: false
+
+    # homekit
+    - name: install dependenies for homekit
+      apt: name=libavahi-compat-libdnssd-dev
diff --git a/on-fire-within/main.yml b/on-fire-within/main.yml
new file mode 100644
index 0000000..bdad158
--- /dev/null
+++ b/on-fire-within/main.yml
@@ -0,0 +1,303 @@
+- import_playbook: pi.yml
+- import_playbook: hass-io.yml
+
+- hosts: on-fire-within
+  become: yes
+  tasks:
+
+    - name: Set authorized keys from GitHub
+      authorized_key:
+        user: alpha
+        state: present
+        key: https://github.com/kejadlen.keys
+
+    - name: Install dependencies
+      apt:
+        name:
+          - git
+          - vim
+
+          # Needed for Docker stuff
+          - docker-compose
+          - python3-pip
+          - python-backports-shutil-get-terminal-size
+          - python-backports.ssl-match-hostname
+
+    - name: Install python docker packages
+      pip:
+        name:
+          - docker
+          - docker-compose
+        state: latest
+
+    - name: Create necessary dirs
+      file:
+        path: "{{ item }}"
+        state: directory
+      with_items:
+        - /etc/ddclient
+        - /etc/minio
+        - /etc/mitmproxy
+        - /etc/traefik
+        - /mnt/mushu/minio
+        - /mnt/mushu/syncthing
+
+    - name: Mount USB drive
+      mount:
+        path: /mnt/mushu
+        src: /dev/sda
+        fstype: ext4
+        state: mounted
+
+    - name: Configure ddclient
+      copy:
+        content: |
+          daemon=300
+
+          use=web
+          ssl=yes
+          protocol=googledomains
+
+          {% for host in hosts %}
+          login={{ host.login }}, password={{ host.password }} {{ host.host }}
+          {% endfor %}
+        dest: /etc/ddclient/ddclient.conf
+        mode: 0600
+      vars:
+        hosts: "{{ ddclient.hosts }}"
+      notify: Restart ddclient
+
+    - name: Traefik static configuration
+      copy:
+        content: |
+          providers:
+            docker:
+              exposedByDefault: false
+            file:
+              filename: /etc/traefik/dynamic_conf.toml
+              watch: true
+
+          entryPoints:
+            http:
+              address: ":80"
+            https:
+              address: ":443"
+
+          certificatesResolvers:
+            le:
+              acme:
+                email: {{ email }}
+                storage: "/etc/traefik/acme.json"
+                httpChallenge:
+                  entryPoint: http
+
+          api:
+            insecure: true
+
+          accessLog: {}
+        dest: /etc/traefik/traefik.yml
+        mode: 0600
+
+    # https://docs.syncthing.net/users/faq.html#inotify-limits
+    - name: Increase inotify limit for syncthing
+      lineinfile:
+        path: /etc/sysctl.conf
+        regexp: '^fs.inotify.max_user_watches='
+        line: fs.inotify.max_user_watches=204800
+
+    # The docker_compose module overwrites our existing variables, so this is a
+    # workaround to save off ones that we need later on in the playbook.
+    #
+    # https://github.com/ansible/ansible/issues/33960
+    - name: Save original host facts
+      set_fact:
+        "{{ item }}_original": "{{ lookup('vars', item) }}"
+      with_items:
+        - minio
+        - traefik
+      tags:
+        - debug
+
+    # Workaround for https://github.com/pi-hole/docker-pi-hole/issues/1048
+    # - https://github.com/pi-hole/docker-pi-hole/issues/1042#issuecomment-1086728157
+    # - https://github.com/pi-hole/docker-pi-hole/issues/1043#issuecomment-1086936352
+    - name: Work around a Docker libseccomp issue w/Pi-Hole
+      block:
+        - apt_key:
+            keyserver: keyserver.ubuntu.com
+            id: "{{ item }}"
+          loop:
+            - 04EE7237B7D453EC
+            - 648ACFD622F3D138
+        - apt_repository:
+            repo: deb http://deb.debian.org/debian buster-backports main
+            filename: buster-backports
+            state: present
+        - shell: apt-cache policy libseccomp2 | grep buster-backports -B1 | head -n1 | sed -e 's/^\s*\**\s*\(\S*\).*/\1/'
+          register: libseccomp2_version
+        - apt:
+            update_cache: yes
+            name: libseccomp2={{ libseccomp2_version.stdout_lines[0] }}
+
+    - name: Docker ALL the things!
+      docker_compose:
+        project_name: on-fire-within
+        pull: yes
+        definition:
+          version: '2'
+          services:
+            ddclient:
+              image: kejadlen/ddclient:latest
+              container_name: ddclient
+              volumes:
+                - /etc/ddclient:/etc/ddclient
+              restart: unless-stopped
+            minio:
+              image: kejadlen/minio:latest
+              container_name: minio
+              environment:
+                MINIO_ACCESS_KEY: "{{ minio.access_key }}"
+                MINIO_SECRET_KEY: "{{ minio.secret_key }}"
+              volumes:
+                - /etc/minio:/root/.minio
+                - /mnt/mushu/minio:/data
+              user: 0:0 # root
+              labels:
+                - traefik.enable=true
+                - traefik.http.routers.minio.rule=Host(`{{ traefik.host_rules.minio }}`)
+                - traefik.http.routers.minio.tls=true
+                - traefik.http.routers.minio.tls.certresolver=le
+                - traefik.http.services.minio.loadbalancer.server.port=9000
+            # mitmproxy:
+            #   image: mitmproxy/mitmproxy:latest-ARMv7
+            #   container_name: mitmproxy
+            #   command: mitmweb --web-iface ""
+            #   volumes:
+            #     - /etc/mitmproxy:/home/mitmproxy/.mitmproxy
+            #   labels:
+            #     - traefik.enable=true
+            #     - traefik.tcp.routers.mitmproxy.rule=HostSNI(`{{ traefik.host_rules.mitmproxy }}`)
+            #     - traefik.tcp.routers.mitmproxy.tls.passthrough=true
+            #     - traefik.tcp.services.mitmproxy.loadbalancer.server.port=8080
+            #     - traefik.http.routers.mitmproxy-web.rule=Host(`{{ traefik.host_rules.mitmproxy_web }}`)
+            #     - traefik.http.routers.mitmproxy-web.tls.certresolver=le
+            #     - traefik.http.services.mitmproxy-web.loadbalancer.server.port=8081
+            pihole:
+              image: pihole/pihole:latest
+              container_name: pihole
+              ports:
+                - 53:53/tcp
+                - 53:53/udp
+              environment:
+                TZ: America/Los_Angeles
+                VIRTUAL_HOST: "{{ pihole.host }}"
+                WEBPASSWORD: "{{ pihole.password }}"
+                LOCAL_IPV4: "{{ ansible_default_ipv4.address }}"
+              volumes:
+                - /etc/pihole:/etc/pihole
+                - /etc/dnsmasq.d:/etc/dnsmasq.d
+              dns:
+                - 127.0.0.1
+                - 1.1.1.1
+              labels:
+                - traefik.enable=true
+                - traefik.http.routers.pihole.rule=Host(`{{ traefik.host_rules.pihole }}`)
+                - traefik.http.routers.pihole.tls=true
+                - traefik.http.routers.pihole.tls.certresolver=le
+                - traefik.http.services.pihole.loadbalancer.server.port=80
+              restart: unless-stopped
+            syncthing:
+              image: syncthing/syncthing:latest
+              container_name: syncthing
+              ports:
+                - 22000:22000/tcp # TCP file transfers
+                - 22000:22000/udp # QUIC file transfers
+                - 21027:21027/udp # Receive local discovery broadcasts
+              volumes:
+                - /etc/syncthing:/var/syncthing
+                - /mnt/mushu/syncthing:/sync
+              environment:
+                PUID: 0
+                PGID: 0
+              labels:
+                - traefik.enable=true
+                - traefik.http.routers.syncthing.rule=Host(`{{ traefik.host_rules.syncthing }}`)
+                - traefik.http.routers.syncthing.tls=true
+                - traefik.http.routers.syncthing.tls.certresolver=le
+                - traefik.http.services.syncthing.loadbalancer.server.port=8384
+              restart: unless-stopped
+            traefik:
+              image: traefik:v2.5
+              container_name: traefik
+              ports:
+                - 80:80
+                - 8080:8080
+                - 443:443
+              volumes:
+                - /var/run/docker.sock:/var/run/docker.sock
+                - /etc/traefik:/etc/traefik
+              labels:
+                - traefik.enable=true
+                - traefik.http.middlewares.auth.basicauth.users=alpha:{{ traefik.password | password_hash("md5") | replace("$", "$$") }}
+                - traefik.http.routers.traefik.rule=Host(`{{ traefik.host_rules.traefik }}`)
+                - traefik.http.routers.traefik.tls=true
+                - traefik.http.routers.traefik.tls.certresolver=le
+                - traefik.http.routers.traefik.middlewares=auth
+                - traefik.http.routers.traefik.service=api@internal
+              restart: unless-stopped
+
+    - name: Route Home Assistant through Traefik
+      block:
+        # - shell: ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+' | head -n 1
+        - shell: docker network inspect on-fire-within_default | jq --raw-output .[0].IPAM.Config[0].Gateway
+          register: docker_gateway_result
+        - shell: docker network inspect on-fire-within_default | jq --raw-output .[0].IPAM.Config[0].Gateway
+          register: docker_subnet_result
+        - set_fact:
+            docker_gateway: "{{ docker_gateway_result.stdout | trim }}"
+            docker_subnet: "{{ docker_subnet_result.stdout | trim }}"
+        - copy:
+            content: |
+              [http.routers]
+                [http.routers.appdaemon]
+                  rule = "Host(`{{ traefik_original.host_rules.appdaemon }}`)"
+                  service = "appdaemon"
+                  [http.routers.appdaemon.tls]
+                    certResolver = "le"
+                [http.routers.hassio]
+                  rule = "Host(`{{ traefik_original.host_rules.hassio }}`)"
+                  service = "hassio"
+                  [http.routers.hassio.tls]
+                    certResolver = "le"
+
+              [http.services]
+                [http.services.appdaemon.loadBalancer]
+                  [[http.services.appdaemon.loadBalancer.servers]]
+                    url = "http://{{ docker_gateway }}:5050/"
+                [http.services.hassio.loadBalancer]
+                  [[http.services.hassio.loadBalancer.servers]]
+                    url = "http://{{ docker_gateway }}:8123/"
+            dest: /etc/traefik/dynamic_conf.toml
+            mode: 0600
+      notify: Restart Traefik
+      tags:
+        - debug
+
+  handlers:
+    - name: Restart ddclient
+      docker_container:
+        name: ddclient
+        restart: yes
+      ignore_errors: yes
+
+    - name: Restart Traefik
+      docker_container:
+        name: traefik
+        restart: yes
+      ignore_errors: yes
+
+    - name: Restart Home Assistant
+      docker_container:
+        name: homeassistant
+        restart: yes
+      ignore_errors: yes
diff --git a/on-fire-within/pi.yml b/on-fire-within/pi.yml
new file mode 100644
index 0000000..96ac691
--- /dev/null
+++ b/on-fire-within/pi.yml
@@ -0,0 +1,44 @@
+# https://www.raspberrypi.org/documentation/configuration/security.md
+
+- hosts: on-fire-within
+  become: yes
+  tasks:
+    - name: disable ssh password logins
+      lineinfile:
+        path: /etc/ssh/sshd_config
+        regexp: '^(#\s*)?{{ item }} '
+        line: "{{ item }} no"
+      notify: reload ssh
+      with_items:
+        - ChallengeResponseAuthentication
+        - PasswordAuthentication
+        - UsePAM
+
+    - name: disable pi user
+      user:
+        name: pi
+        password: !
+
+    - name: install fail2ban
+      package:
+        name: fail2ban
+        state: present
+
+    - name: create jail.local
+      copy:
+        content: |
+          [sshd]
+          enabled = true
+        dest: /etc/fail2ban/jail.local
+      notify: reload fail2ban
+
+  handlers:
+    - name: reload ssh
+      service:
+        name: ssh
+        state: reloaded
+
+    - name: reload fail2ban
+      service:
+        name: fail2ban
+        state: reloaded
diff --git a/on-fire-within/tailscale.yml b/on-fire-within/tailscale.yml
new file mode 100644
index 0000000..4d74ed5
--- /dev/null
+++ b/on-fire-within/tailscale.yml
@@ -0,0 +1,36 @@
+# https://tailscale.com/download/linux/rpi
+
+- name: Install Tailscale
+  hosts: on-fire-within
+  become: true
+  tasks:
+
+    # sudo apt-get install apt-transport-https
+    - name: Install apt-transport-https
+      ansible.builtin.package:
+        name: apt-transport-https
+        state: present
+
+    # curl -fsSL https://pkgs.tailscale.com/stable/raspbian/buster.gpg | sudo apt-key add -
+    - name: Add Tailscale signing key
+      ansible.builtin.apt_key:
+        url: https://pkgs.tailscale.com/stable/raspbian/buster.gpg
+        state: present
+
+    # curl -fsSL https://pkgs.tailscale.com/stable/raspbian/buster.list | sudo tee /etc/apt/sources.list.d/tailscale.list
+    - name: Add Tailsale apt repo
+      ansible.builtin.apt_repository:
+        repo: deb https://pkgs.tailscale.com/stable/raspbian buster main
+        state: present
+        filename: tailscale
+
+    # sudo apt-get update
+    - name: Update apt-get
+      ansible.builtin.apt:
+        update_cache: true
+
+    # sudo apt-get install tailscale
+    - name: Install Tailscale
+      ansible.builtin.package:
+        name: tailscale
+        state: present