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