catching up #52
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
|
||||
airconnect_dir: "/var/lib/airconnect"
|
||||
airconnect_user:
|
||||
name: airconnect
|
||||
uid: 1337
|
||||
airconnect_group:
|
||||
name: airconnect
|
||||
gid: 1337
|
||||
|
||||
airconnect_upnp: []
|
||||
airconnect_containers:
|
||||
# UPnP/Sonos
|
||||
- prog: airupnp
|
||||
state: started
|
||||
# Chromecast
|
||||
- prog: aircast
|
||||
state: started
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
|
||||
- name: restart airconnect containers
|
||||
docker_container:
|
||||
name: airconnect-{{ item }}
|
||||
state: "{{ item.state }}"
|
||||
restart: item.state == 'started'
|
||||
with_items: "{{ airconnect_containers }}"
|
||||
when:
|
||||
- airconnect_containers is not defined or not airconnect_containers.changed
|
||||
- item.state == 'started'
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
|
||||
- name: create airconnect dir
|
||||
file:
|
||||
path: "{{ airconnect_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
owner: hass
|
||||
group: hass
|
||||
tags:
|
||||
- airconnect-dirs
|
||||
|
||||
- name: airconnect config files
|
||||
template:
|
||||
src: "{{ item.name }}.j2"
|
||||
dest: "{{ airconnect_dir }}/{{ item.name }}"
|
||||
owner: "{{ item.owner | default(systemuserlist.hass.uid) }}"
|
||||
group: "{{ item.group | default(systemuserlist.hass.gid) }}"
|
||||
mode: "{{ item.mode }}"
|
||||
notify: restart airconnect container
|
||||
with_items:
|
||||
- name: airupnp.xml
|
||||
mode: "0644"
|
||||
- name: run
|
||||
mode: "0755"
|
||||
- name: supervisord.conf
|
||||
mode: "0644"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
# needed to nuke the script that would otherwise
|
||||
# overwrite our sane supervisord.conf file
|
||||
- name: 30-install
|
||||
mode: "0755"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
tags:
|
||||
- airconnect-config
|
||||
- airconnect
|
||||
|
||||
- name: start airconnect container
|
||||
docker_container:
|
||||
name: airconnect
|
||||
hostname: airconnect
|
||||
image: 1activegeek/airconnect
|
||||
#user: "{{ systemuserlist.hass.uid }}:{{ systemuserlist.hass.gid }}"
|
||||
detach: true
|
||||
pull: true
|
||||
auto_remove: false
|
||||
restart_policy: "unless-stopped"
|
||||
state: "{{ airconnect_container_state | default('started') }}"
|
||||
network_mode: host
|
||||
env:
|
||||
# docker image uses the linuxserver base image and supervisor,
|
||||
# setting 'user:' doesnt work because of all of the custom shit
|
||||
# that the base image does: https://github.com/linuxserver/docker-baseimage-ubuntu/blob/bionic/root/etc/cont-init.d/10-adduser
|
||||
# but this image doesnt follow that properly, and supervisor starts
|
||||
# the airconnect processes as root, so we need to mount a custom
|
||||
# supervisord.conf file instead
|
||||
PUID: "{{ systemuserlist.hass.uid }}"
|
||||
PGID: "{{ systemuserlist.hass.gid }}"
|
||||
|
||||
# the image runs a script
|
||||
# AIRUPNP_VAR: "-x /etc/airconnect/airupnp.xml"
|
||||
# will create a reference config file for chromecast when found,
|
||||
# but the defaults are fine, so no need to maintain a custom file
|
||||
#AIRCAST_VAR: "-i /etc/airconnect/aircast.xml"
|
||||
mounts:
|
||||
# generate the reference config files by setting AIRUPNP_VAR and
|
||||
# AIRCAST_VAR env to '-i $PATH'
|
||||
- type: bind
|
||||
source: "{{ airconnect_dir }}/airupnp.xml"
|
||||
target: /etc/airupnp.xml
|
||||
read_only: true
|
||||
# need this to set uid/gid properly
|
||||
- type: bind
|
||||
source: "{{ airconnect_dir }}/supervisord.conf"
|
||||
target: /etc/supervisord.conf
|
||||
# needed to nuke the script that would otherwise overwrite our sane
|
||||
# version of the supervisord.conf file when the container starts
|
||||
- type: bind
|
||||
source: "{{ airconnect_dir }}/30-install"
|
||||
target: /etc/cont-init.d/30-install
|
||||
tags:
|
||||
- airconnect
|
||||
- airconnect-container
|
||||
- docker-containers
|
||||
register: airconnect_container
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
|
||||
- name: create airconnect dir
|
||||
file:
|
||||
path: "{{ airconnect_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
owner: "{{ owntone_user.uid }}"
|
||||
group: "{{ owntone_group.gid }}"
|
||||
tags:
|
||||
- airconnect-dirs
|
||||
|
||||
- name: airconnect config files
|
||||
template:
|
||||
src: "{{ item.name }}.j2"
|
||||
dest: "{{ airconnect_dir }}/{{ item.name }}"
|
||||
owner: "{{ owntone_user.uid }}"
|
||||
group: "{{ owntone_group.gid }}"
|
||||
mode: "{{ item.mode | default('0644') }}"
|
||||
notify: restart airconnect containers
|
||||
with_items:
|
||||
- name: airupnp.xml
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
tags:
|
||||
- airconnect-config
|
||||
- airconnect
|
||||
|
||||
- name: "set up the airconnect containers"
|
||||
docker_container:
|
||||
name: airconnect-{{ item.prog }}
|
||||
hostname: airconnect-{{ item.prog }}
|
||||
image: git.sudo.is/ben/airconnect
|
||||
detach: true
|
||||
pull: true
|
||||
auto_remove: false
|
||||
restart_policy: "unless-stopped"
|
||||
state: "{{ item.state | default('started') }}"
|
||||
network_mode: host
|
||||
user: "{{ owntone_user.uid }}:{{ owntone_group.gid }}"
|
||||
env:
|
||||
AIRCONNECT_PROG: "{{ item.prog }}"
|
||||
AIRCONNECT_ARGS: "{{ item.args|default() }}"
|
||||
mounts:
|
||||
- type: bind
|
||||
source: "{{ airconnect_dir }}/airupnp.xml"
|
||||
target: /etc/airupnp.xml
|
||||
read_only: true
|
||||
tags:
|
||||
- airconnect
|
||||
- airconnect-container
|
||||
- docker-containers
|
||||
register: airconnect_containers
|
||||
loop_control:
|
||||
label: airconnect-{{ item.prog }}
|
||||
with_items: "{{ airconnect_containers }}"
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
- import_tasks: airconnect.yml
|
||||
tags: airconnect
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0"?>
|
||||
<airupnp>
|
||||
<common>
|
||||
<protocolInfo>
|
||||
<pcm>http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=00;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=0d500000000000000000000000000000</pcm>
|
||||
<wav>http-get:*:audio/wav:DLNA.ORG_OP=00;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=0d500000000000000000000000000000</wav>
|
||||
<flac>http-get:*:audio/flac:DLNA.ORG_OP=00;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=0d500000000000000000000000000000</flac>
|
||||
<mp3>http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=00;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=0d500000000000000000000000000000</mp3>
|
||||
</protocolInfo>
|
||||
<enabled>1</enabled>
|
||||
<max_volume>100</max_volume>
|
||||
<http_length>-1</http_length>
|
||||
<upnp_max>1</upnp_max>
|
||||
<codec>mp3:320</codec>
|
||||
<metadata>1</metadata>
|
||||
<flush>1</flush>
|
||||
<artwork></artwork>
|
||||
<latency>0:1000</latency>
|
||||
<drift>0</drift>
|
||||
</common>
|
||||
<main_log>info</main_log>
|
||||
<upnp_log>info</upnp_log>
|
||||
<util_log>warn</util_log>
|
||||
<raop_log>info</raop_log>
|
||||
<log_limit>-1</log_limit>
|
||||
<max_players>32</max_players>
|
||||
<binding>?</binding>
|
||||
<ports>0:0</ports>
|
||||
{% for item in airconnect_upnp -%}
|
||||
<device>
|
||||
<udn>uuid:{{ item.local_uid }}</udn>
|
||||
<name>{{ item.name }}</name>
|
||||
<mac>{{ item.mac }}</mac>
|
||||
<enabled>{% if item.enabled|default(true) %}1{% else %}0{% endif %}</enabled>
|
||||
</device>
|
||||
{% endfor %}
|
||||
</airupnp>
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/with-contenv bash
|
||||
|
||||
echo "this file has been nuked, so our sane supervisord.conf file is not overwritten"
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/with-contenv bash
|
||||
|
||||
supervisord --configuration /etc/supervisord.conf
|
|
@ -0,0 +1,25 @@
|
|||
[supervisord]
|
||||
nodaemon=true
|
||||
|
||||
# the base image of the airconnect image uses the env vars $PUID and $PGID
|
||||
# to create a user, and those are set in the ansible role
|
||||
#
|
||||
# supervisord doesnt have an argument for group, uses the default
|
||||
# group of the user instead.
|
||||
#
|
||||
# but supervisor itself needs to run as root because of
|
||||
# asinine stuff that the linuxserver base image wants to do
|
||||
|
||||
[program:airupnp]
|
||||
user={{ systemuserlist.hass.uid }}
|
||||
redirect_stderr=true
|
||||
# the config file maintained in this ansible role, mounted in
|
||||
# the docker_container task
|
||||
command=/bin/airupnp-linux-x86_64 -x /etc/airupnp.xml
|
||||
process_name = airupnp-linux-x86_64
|
||||
|
||||
[program:aircast]
|
||||
user={{ systemuserlist.hass.uid }}
|
||||
redirect_stderr=true
|
||||
command=/bin/aircast-linux-x86_64
|
||||
process_name = aircast-linux-x86_64
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
|
||||
- name: reload nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: reloaded
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
|
||||
- name: create dir structure
|
||||
file:
|
||||
path: "{{ audiobookshelf_path }}/{{ item.name }}"
|
||||
mode: "{{ item.mode | default('0750') }}"
|
||||
owner: "{{ audiobookshelf_user.uid }}"
|
||||
group: "{{ audiobookshelf_group.gid }}"
|
||||
tags:
|
||||
- audiobookshelf-dirs
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
with_items:
|
||||
- name: ''
|
||||
- name: audiobooks
|
||||
- name: config
|
||||
mode: "0755"
|
||||
- name: metadata
|
||||
- name: podcasts
|
||||
|
||||
- name: install certs
|
||||
copy:
|
||||
src: "/usr/local/etc/letsencrypt/live/{{ item }}"
|
||||
dest: "/usr/local/etc/certs/"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- letsencrypt-certs
|
||||
notify: reload nginx
|
||||
vars:
|
||||
prediff_cmd: echo
|
||||
with_items:
|
||||
- "{{ audiobookshelf_url }}"
|
||||
|
||||
- name: template nginx vhost
|
||||
template:
|
||||
src: 02-audiobookshelf.conf.j2
|
||||
dest: /etc/nginx/sites-enabled/02-audiobookshelf.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
tags:
|
||||
- nginx
|
||||
- audiobookshelf-nginx
|
||||
notify: reload nginx
|
||||
|
||||
- name: start audiobookshelf container
|
||||
docker_container:
|
||||
name: audiobookshelf
|
||||
auto_remove: false
|
||||
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||
detach: true
|
||||
pull: true
|
||||
restart_policy: "no"
|
||||
state: started
|
||||
container_default_behavior: compatibility
|
||||
networks_cli_compatible: false
|
||||
network_mode: bridgewithdns
|
||||
networks:
|
||||
- name: bridgewithdns
|
||||
ipv4_address: "{{ bridgewithdns.audiobookshelf }}"
|
||||
ben marked this conversation as resolved
|
||||
env:
|
||||
AUDIOBOOKSHELF_UID: "{{ audiobookshelf_user.uid }}"
|
||||
AUDIOBOOKSHELF_GID: "{{ audiobookshelf_group.gid }}"
|
||||
user: "{{ audiobookshelf_user.uid }}:{{ audiobookshelf_group.gid }}"
|
||||
mounts:
|
||||
- type: bind
|
||||
source: "{{ audiobookshelf_path }}/audiobooks"
|
||||
target: /audiobooks
|
||||
- type: bind
|
||||
source: "{{ audiobookshelf_path }}/podcasts"
|
||||
target: /podcasts
|
||||
- type: bind
|
||||
source: "{{ audiobookshelf_path }}/config"
|
||||
target: /config
|
||||
- type: bind
|
||||
source: "{{ audiobookshelf_path }}/metadata"
|
||||
target: /metadata
|
||||
tags:
|
||||
- audiobookshelf-container
|
||||
- docker-containers
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
- import_tasks: audiobookshelf.yml
|
||||
tags: audiobookshelf
|
|
@ -0,0 +1,50 @@
|
|||
server {
|
||||
listen 443 ssl http2;
|
||||
include listen-proxy-protocol.conf;
|
||||
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
{% endif -%}
|
||||
|
||||
server_name {{ audiobookshelf_url }};
|
||||
|
||||
access_log /var/log/nginx/access_{{ audiobookshelf_url }}.log main;
|
||||
error_log /var/log/nginx/error_{{ audiobookshelf_url }}.log warn;
|
||||
|
||||
ssl_certificate /usr/local/etc/certs/{{ audiobookshelf_url }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ audiobookshelf_url }}/privkey.pem;
|
||||
|
||||
include /etc/nginx/authelia_internal.conf;
|
||||
|
||||
location /feed/ {
|
||||
include /etc/nginx/require_auth.conf;
|
||||
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_pass http://{{ bridgewithdns.audiobookshelf }}:80;
|
||||
proxy_redirect http:// https://;
|
||||
|
||||
proxy_hide_header "Content-Type";
|
||||
add_header "Content-Type" "application/rss+xml";
|
||||
|
||||
}
|
||||
location / {
|
||||
include /etc/nginx/require_auth.conf;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_pass http://{{ bridgewithdns.audiobookshelf }}:80;
|
||||
proxy_redirect http:// https://;
|
||||
}
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
---
|
||||
blink1_enabled: false
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PGP ARMORED FILE-----
|
||||
Comment: Use "gpg --dearmor" for unpacking
|
||||
|
||||
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
|
||||
=P2ir
|
||||
-----END PGP ARMORED FILE-----
|
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PGP ARMORED FILE-----
|
||||
Comment: Use "gpg --dearmor" for unpacking
|
||||
|
||||
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
|
||||
=P2ir
|
||||
-----END PGP ARMORED FILE-----
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
- sensor:
|
||||
- name: "chance_of_rain"
|
||||
unit_of_measurement: "%"
|
||||
icon: "mdi:weather-pouring"
|
||||
state: "{{ state_attr('weather.hourly', 'forecast')[:2] | map(attribute='precipitation_probability') | list | max | float }}"
|
|
@ -15,4 +15,18 @@
|
|||
name: hass
|
||||
state: started
|
||||
restart: true
|
||||
when: hass_container is not defined or not hass_container.changed
|
||||
when:
|
||||
- hass_container is not defined or not hass_container.changed
|
||||
- hass_container_state|default("stopped") == "started"
|
||||
|
||||
- name: restart zwavejs container
|
||||
docker_container:
|
||||
name: zwavejs
|
||||
state: started
|
||||
restart: true
|
||||
when:
|
||||
- zwavejs_container is not defined or not zwavejs_container.changed
|
||||
- hass_container_state|default("stopped") == "started"
|
||||
|
||||
- name: udevadm reload rules
|
||||
command: udevadm control --reload-rules
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
|
||||
- name: nmcli conn reload
|
||||
command: nmcli conn reload
|
||||
|
||||
- name: nmcli device wifi hotspot
|
||||
command: nmcli device wifi hotspot
|
|
@ -1,53 +1,5 @@
|
|||
---
|
||||
|
||||
- name: allow ssh
|
||||
ufw:
|
||||
rule: allow
|
||||
to_port: "22"
|
||||
direction: in
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: allow loopback
|
||||
ufw:
|
||||
rule: allow
|
||||
interface: lo
|
||||
direction: in
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: default policy
|
||||
ufw:
|
||||
policy: allow
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: deny hass cloud port stuff
|
||||
ufw:
|
||||
# drops packets
|
||||
rule: deny
|
||||
to_port: '42161'
|
||||
direction: in
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: reject zwavejs ws and hass ports (loopback only)
|
||||
ufw:
|
||||
# connection refused
|
||||
rule: reject
|
||||
to_port: "{{ item }}"
|
||||
direction: in
|
||||
state: enabled
|
||||
with_items:
|
||||
- "8091"
|
||||
- "8123"
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: copy ssh keys for {{ hass_config_repo_name }}
|
||||
template:
|
||||
src: "private/sshkeys/{{ item }}"
|
||||
|
@ -66,22 +18,30 @@
|
|||
|
||||
- name: create dir structure
|
||||
file:
|
||||
path: "{{ systemuserlist.hass.home }}/{{ item }}"
|
||||
path: "{{ systemuserlist.hass.home }}/{{ item.name }}"
|
||||
state: directory
|
||||
mode: 0755
|
||||
mode: "{{ item.mode | default('0755') }}"
|
||||
owner: hass
|
||||
group: hass
|
||||
tags:
|
||||
- hass-dirs
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
with_items:
|
||||
- home-assistant
|
||||
- home-assistant/config
|
||||
- home-assistant/.config
|
||||
- home-assistant/media
|
||||
- zwavejs
|
||||
- zwavejs/app
|
||||
- zwavejs/app/store
|
||||
- git
|
||||
- name: .local
|
||||
mode: "0775"
|
||||
- name: home-assistant
|
||||
- name: home-assistant/config
|
||||
- name: home-assistant/config/python_scripts
|
||||
- name: home-assistant/config/bvg
|
||||
- name: home-assistant/.config # might not be needed, misread 'cache' as 'config'
|
||||
- name: home-assistant/.cache
|
||||
- name: home-assistant/media
|
||||
mode: "0775"
|
||||
- name: zwavejs
|
||||
- name: zwavejs/app
|
||||
- name: zwavejs/app/store
|
||||
- name: git
|
||||
|
||||
- name: template gitconfig
|
||||
template:
|
||||
|
@ -108,36 +68,38 @@
|
|||
- hass-git
|
||||
- hass-git-clone
|
||||
|
||||
- name: home assistant main configuration.yaml
|
||||
|
||||
- name: home assistant config files
|
||||
template:
|
||||
src: configuration.yaml.j2
|
||||
dest: "{{ systemuserlist.hass.home }}/home-assistant/config/configuration.yaml"
|
||||
src: "{{ item }}.j2"
|
||||
dest: "{{ systemuserlist.hass.home }}/home-assistant/config/{{ item }}"
|
||||
owner: "{{ systemuserlist.hass.uid }}"
|
||||
group: "{{ systemuserlist.hass.gid }}"
|
||||
mode: 0644
|
||||
notify: restart hass container
|
||||
with_items:
|
||||
- secrets.yaml
|
||||
- configuration.yaml
|
||||
- templates.yaml
|
||||
- climate.yaml
|
||||
- automations-ansible-managed.yaml
|
||||
- scripts-ansible-managed.yaml
|
||||
- blink1.yaml
|
||||
tags:
|
||||
- hass-config
|
||||
|
||||
- name: home assistant secrets file
|
||||
template:
|
||||
src: secrets.yaml.j2
|
||||
dest: "{{ systemuserlist.hass.home }}/home-assistant/config/secrets.yaml"
|
||||
owner: "{{ systemuserlist.hass.uid }}"
|
||||
group: "{{ systemuserlist.hass.gid }}"
|
||||
mode: 0644
|
||||
notify: restart hass container
|
||||
tags:
|
||||
- hass-config
|
||||
|
||||
- name: copy home assistant templates file
|
||||
- name: copy dashboards
|
||||
copy:
|
||||
src: templates.yaml
|
||||
dest: "{{ systemuserlist.hass.home }}/home-assistant/config/templates.yaml"
|
||||
owner: "{{ systemuserlist.hass.uid }}"
|
||||
group: "{{ systemuserlist.hass.gid }}"
|
||||
mode: 0644
|
||||
src: "private/hass/{{ item }}"
|
||||
dest: "{{ systemuserlist.hass.home }}/home-assistant/config/{{ item }}"
|
||||
mode: 0755
|
||||
owner: hass
|
||||
group: hass
|
||||
notify: restart hass container
|
||||
with_items:
|
||||
- mini.yaml
|
||||
- ui-test.yaml
|
||||
- card_room.yaml
|
||||
tags:
|
||||
- hass-config
|
||||
|
||||
|
@ -163,15 +125,106 @@
|
|||
- hass-cron
|
||||
- hass-git
|
||||
|
||||
- name: udev rules
|
||||
template:
|
||||
src: "{{ item }}.j2"
|
||||
dest: /etc/udev/rules.d/{{ item }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
notify: udevadm reload rules
|
||||
with_items:
|
||||
- 20-sdr.rules
|
||||
tags:
|
||||
- hass-udev
|
||||
|
||||
# key source:
|
||||
# - http://download.ag-projects.com/agp-debian-gpg.key
|
||||
# - http://download.ag-projects.com/agp-debian-key.key
|
||||
# gpg --enarmor roles/hass/files/agp-debian-gpg.key
|
||||
# binary keys: .gpg
|
||||
# ascii armor: .asc (or .key?)
|
||||
- name: add apt key for sip tools
|
||||
copy:
|
||||
src: "{{ item }}"
|
||||
dest: /etc/apt/trusted.gpg.d/{{ item }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
with_items:
|
||||
- agp-debian-gpg.asc
|
||||
- agp-debian-key.asc
|
||||
tags:
|
||||
- packages
|
||||
- hass-sip
|
||||
- sip
|
||||
|
||||
# - debug:
|
||||
# msg: "deb [signed-by=/usr/share/keyrings/agp-debian-gpg.key] http://ag-projects.com/{{ ansible_lsb.id | lower }} {{ ansible_lsb.codename }} main"
|
||||
# tags: hass-sip
|
||||
|
||||
# [signed-by=/usr/share/keyrings/agp-debian-gpg.gpg]
|
||||
# [signed-by=/etc/apt/trusted.gpg.d/agp-debian-gpg.asc]
|
||||
- name: add repo for sip tools
|
||||
apt_repository:
|
||||
#repo: "{{ item }} [signed-by=/etc/apt/trusted.gpg.d/agp-debian-key.asc] http://ag-projects.com/{{ ansible_lsb.id | lower }} {{ ansible_lsb.codename }} main"
|
||||
repo: "{{ item }} [signed-by=/etc/apt/trusted.gpg.d/agp-debian-key.asc] http://ag-projects.com/{{ ansible_lsb.id | lower }} sid main"
|
||||
state: present
|
||||
update_cache: false
|
||||
with_items:
|
||||
- "deb"
|
||||
- "deb-src"
|
||||
register: sip_repo
|
||||
tags:
|
||||
- packages
|
||||
- hass-sip
|
||||
- sip
|
||||
when: false
|
||||
|
||||
- name: update apt if new repo was added
|
||||
apt:
|
||||
update_cache: true
|
||||
tags:
|
||||
- packages
|
||||
- hass-sip
|
||||
- sip
|
||||
when:
|
||||
- sip_repo.changed
|
||||
- false
|
||||
|
||||
# the host needs to have bluez installed for the container to use bluetooth
|
||||
- name: install bluetooth packages
|
||||
- name: install packages
|
||||
apt:
|
||||
name:
|
||||
- vlc
|
||||
- mplayer
|
||||
- bluez
|
||||
- bluetooth
|
||||
- fapg
|
||||
- podget
|
||||
- sqlite3
|
||||
- rtl-433
|
||||
- mosquitto
|
||||
- python3-paho-mqtt
|
||||
- blink1 # git.sudo.is/ben/build-blink1
|
||||
# # sip tools
|
||||
# - python3-sipsimple
|
||||
# - sipclients3
|
||||
state: latest
|
||||
tags:
|
||||
- packages
|
||||
- hass-bluetooth
|
||||
- hass-packages
|
||||
- hass-sip
|
||||
- sip
|
||||
|
||||
- name: ensure bluetooth service is started and enabled
|
||||
service:
|
||||
name: bluetooth
|
||||
state: started
|
||||
enabled: true
|
||||
tags:
|
||||
- hass-bluetooth
|
||||
|
||||
# docker run --run -it -p 8091:8091 -p 3000:3000 --network
|
||||
#bridgewithdns --device /dev/ttyACM0:/dev/zwave -v
|
||||
|
@ -186,7 +239,7 @@
|
|||
detach: true
|
||||
pull: true
|
||||
restart_policy: "unless-stopped"
|
||||
state: "{{ container_state | default('started') }}"
|
||||
state: "{{ hass_container_state | default('stopped') }}"
|
||||
container_default_behavior: compatibility
|
||||
user: "{{ systemuserlist.hass.uid }}:dialout"
|
||||
networks_cli_compatible: false
|
||||
|
@ -200,18 +253,21 @@
|
|||
# ws for hass<->zwavejs
|
||||
# hass is configured to use localhost:3000 to talk to zwavejs, but can
|
||||
# also use {{ bridgewithdns.zwavejs }}, but hass is very fragile and
|
||||
# you have to manually work around it if it cant access zwaevjs because the
|
||||
# ip/dns changed or the container moved networks. it is not configured in a
|
||||
# config file either. so using localhost is the least fragile strategy.
|
||||
# you have to manually work around it if it cant access zwaevjs because
|
||||
# the ip/dns changed or the container moved networks. it is not
|
||||
# configured in a config file either. so using localhost is the least
|
||||
# fragile strategy.
|
||||
- "127.0.0.1:3000:3000"
|
||||
env:
|
||||
#BASE_URL: "/zwavejs/"
|
||||
SESSION_SECRET: "{{ zwavejs_session_secret }}"
|
||||
ZWAVEJS_EXTERNAL_CONFIG: /usr/src/app/store/.config-db
|
||||
SERVER_SSL: "true"
|
||||
mounts:
|
||||
- type: bind
|
||||
source: "{{ systemuserlist.hass.home }}/zwavejs/app/store"
|
||||
target: /usr/src/app/store
|
||||
register: zwavejs_container
|
||||
tags:
|
||||
- zwavejs
|
||||
- zwavejs-container
|
||||
|
@ -219,20 +275,25 @@
|
|||
- docker-containers
|
||||
|
||||
# docker run --rm it --name hass -p 8123:8123 -e TZ=Etc/UTC -v
|
||||
# /home/ben/hass:/config --network-bridgewithdns
|
||||
# /home/ben/hass:/config --network=bridgewithdns
|
||||
# ghcr.io/home-assistant/home-assistant:stable
|
||||
|
||||
- name: start home-assistant container
|
||||
docker_container:
|
||||
name: hass
|
||||
image: ghcr.io/home-assistant/home-assistant:stable
|
||||
#image: git.sudo.is/ben/hass:latest
|
||||
detach: true
|
||||
pull: true
|
||||
restart_policy: "unless-stopped"
|
||||
state: "{{ container_state | default('started') }}"
|
||||
state: "{{ hass_container_state | default('stopped') }}"
|
||||
container_default_behavior: compatibility
|
||||
user: "{{ systemuserlist.hass.uid }}:{{ systemuserlist.hass.gid }}"
|
||||
network_mode: host
|
||||
privileged: true
|
||||
capabilities:
|
||||
- SYS_ADMIN
|
||||
- NET_ADMIN
|
||||
env:
|
||||
TZ: "Etc/UTC"
|
||||
mounts:
|
||||
|
@ -242,19 +303,27 @@
|
|||
- type: bind
|
||||
source: "{{ systemuserlist.hass.home }}/home-assistant/.config"
|
||||
target: /.config
|
||||
- type: bind
|
||||
source: "{{ systemuserlist.hass.home }}/home-assistant/.cache"
|
||||
target: /.cache
|
||||
- type: bind
|
||||
source: "{{ systemuserlist.hass.home }}/.local"
|
||||
target: /.local
|
||||
- type: bind
|
||||
source: "{{ systemuserlist.hass.home }}/home-assistant/media"
|
||||
target: /usr/var/media
|
||||
# for bluetooth, container needs access to the dbus socket
|
||||
# https://www.home-assistant.io/integrations/bluetooth/
|
||||
- type: bind
|
||||
source: /run/dbus/
|
||||
target: /run/dbus/
|
||||
read_only: true
|
||||
source: "{{ systemuserlist.archives.home }}/podgrab/data"
|
||||
target: /usr/var/media/podcasts
|
||||
- type: bind
|
||||
source: /etc/bluetooth/main.conf
|
||||
target: /etc/bluetooth/main.conf
|
||||
read_only: true
|
||||
read_only: false
|
||||
source: /run/dbus
|
||||
target: /run/dbus
|
||||
# - type: bind
|
||||
# source: /etc/bluetooth/main.conf
|
||||
# target: /etc/bluetooth/main.conf
|
||||
# read_only: true
|
||||
# scripts from role: common
|
||||
# only depends on requests, which hass image has
|
||||
- type: bind
|
||||
|
@ -283,20 +352,23 @@
|
|||
vars:
|
||||
prediff_cmd: echo
|
||||
with_items:
|
||||
- "{{ hass_url }}"
|
||||
- "{{ domain }}"
|
||||
|
||||
- name: template nginx vhost for hass
|
||||
- name: template nginx vhosts for hass and friends
|
||||
template:
|
||||
src: 01-hass.j2
|
||||
dest: /etc/nginx/sites-enabled/01-hass
|
||||
src: "01-{{ item }}.conf.j2"
|
||||
dest: /etc/nginx/sites-enabled/{{ item }}.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
with_items:
|
||||
- hass
|
||||
- zwavejs
|
||||
tags:
|
||||
- nginx
|
||||
- hass-nginx
|
||||
- zwave-nginx
|
||||
notify: restart nginx
|
||||
notify: reload nginx
|
||||
|
||||
# different task because its better for the hass config to restart nginx
|
||||
- name: template nginx vhost for grafana-proxy
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
- name: allow ssh
|
||||
ufw:
|
||||
rule: allow
|
||||
to_port: "22"
|
||||
direction: in
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: allow loopback
|
||||
ufw:
|
||||
rule: allow
|
||||
interface: lo
|
||||
direction: in
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: default policy
|
||||
ufw:
|
||||
policy: allow
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: deny hass cloud port stuff
|
||||
ufw:
|
||||
# drops packets
|
||||
rule: deny
|
||||
to_port: '42161'
|
||||
direction: in
|
||||
state: enabled
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: reject zwavejs ws and hass ports (loopback only)
|
||||
ufw:
|
||||
# connection refused
|
||||
rule: reject
|
||||
to_port: "{{ item }}"
|
||||
direction: in
|
||||
state: enabled
|
||||
with_items:
|
||||
- "8091"
|
||||
- "8123"
|
||||
tags:
|
||||
- ufw
|
||||
|
||||
- name: get current timestamp line
|
||||
command: grep "timestamp=" /etc/NetworkManager/system-connections/blackbox.connection
|
||||
check_mode: false
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
register: timestamp
|
||||
tags:
|
||||
- hass-wifi
|
||||
- hass-blackbox
|
||||
|
||||
|
||||
# nmcli device wifi blackbox ifname wlo1 ssid {{ hass_wifi_blackbox.ssid }} password {{ hass_wifi_blackbox.pass }}
|
||||
- name: config for blackbox wifi ap with NetworkManager
|
||||
template:
|
||||
src: blackbox.connection.j2
|
||||
dest: /etc/NetworkManager/system-connections/blackbox.connection
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0600
|
||||
tags:
|
||||
- hass-wifi
|
||||
- hass-blackbox
|
||||
notify:
|
||||
- nmcli conn reload
|
||||
- nmcli device wifi hotspot
|
||||
|
||||
# routing/forwarding should not be enabled, but block it to be sure
|
||||
- name: allow local traffic on blackbox wifi
|
||||
ufw:
|
||||
rule: allow
|
||||
interface: "{{ hass_wifi_blackbox.iface }}"
|
||||
direction: out
|
||||
dest: "{{ hass_wifi_blackbox.ip }}/{{ hass_wifi_blackbox.cidr_prefix }}"
|
||||
state: enabled
|
||||
tags:
|
||||
- hass-wifi
|
||||
- hass-blackbox
|
||||
- ufw
|
||||
|
||||
- name: reject everything else on the blackbox wifi
|
||||
ufw:
|
||||
# connection refused
|
||||
rule: reject
|
||||
interface: "{{ hass_wifi_blackbox.iface }}"
|
||||
direction: out
|
||||
dest: any
|
||||
state: enabled
|
||||
tags:
|
||||
- hass-wifi
|
||||
- hass-blackbox
|
||||
- ufw
|
|
@ -0,0 +1,144 @@
|
|||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
#default $http_connection;
|
||||
'' close;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
{% endif -%}
|
||||
|
||||
include /etc/nginx/authelia_internal.conf;
|
||||
include listen-proxy-protocol.conf;
|
||||
include /etc/nginx/sudo-known.conf;
|
||||
|
||||
server_name {{ hass_url }};
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_pass http://127.0.0.1:8123;
|
||||
}
|
||||
|
||||
# location /media {
|
||||
# root {{ systemuserlist.hass.home }}/home-assistant/media;
|
||||
# autoindex on;
|
||||
# autoindex_exact_size off;
|
||||
# }
|
||||
|
||||
{% if blink1_enabled -%}
|
||||
location /blink1/ {
|
||||
{% for cidr in my_local_cidrs -%}
|
||||
allow {{ cidr }};
|
||||
{% endfor -%}
|
||||
allow {{ my_public_ips[ansible_control_host] }}/32;
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
|
||||
{% if blink1_tiny_html|default(false) -%}
|
||||
rewrite '^/blink1(/.*)$' $1 break;
|
||||
sub_filter_once off;
|
||||
sub_filter '"/' '"./';
|
||||
{% else -%}
|
||||
add_header Content-Type 'application/json' always;
|
||||
{% endif -%}
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://localhost:{{ blink1_server_port }};
|
||||
|
||||
}
|
||||
{% endif %}
|
||||
location = {{ nginx_zwavejs_path }} {
|
||||
# zwavejs needs to be accessed with a trailing / to respond.
|
||||
#
|
||||
# temporary redirects dont get remembered by the browser
|
||||
# and redirect issues are no fun
|
||||
return 302 https://{{ hass_url }}{{ nginx_zwavejs_path }}/;
|
||||
}
|
||||
location {{ nginx_zwavejs_path }} {
|
||||
#add_header Access-Control-Allow-Origin "*" always;
|
||||
# kill cache
|
||||
add_header Last-Modified $date_gmt always;
|
||||
add_header Cache-Control 'no-store' always;
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
|
||||
# nuke the service worker cache
|
||||
# sub_filter '.js' '.js?id=$request_id';
|
||||
|
||||
include /etc/nginx/require_auth.conf;
|
||||
|
||||
rewrite ^ $request_uri;
|
||||
rewrite '^{{ nginx_zwavejs_path }}(/.*)$' $1 break;
|
||||
|
||||
proxy_set_header X-External-Path {{ nginx_zwavejs_path }};
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
#proxy_socket_keepalive on;
|
||||
|
||||
## for the special dashboard
|
||||
## https://zwave-js.github.io/zwave-js-ui/#/usage/reverse-proxy?id=using-an-http-header
|
||||
## proxy_set_header X-External-Path $http_x_ingress_path;
|
||||
|
||||
proxy_pass http://{{ bridgewithdns.zwavejs }}:8091$uri;
|
||||
#proxy_pass http://{{ bridgewithdns.zwavejs }}:8091/;
|
||||
}
|
||||
ben marked this conversation as resolved
ben
commented
remove remove
ben
commented
more or less fixed, not in this pr. more or less fixed, not in this pr.
|
||||
|
||||
location = {{ nginx_podgrab_path }} {
|
||||
return 302 https://{{ hass_url }}{{ nginx_podgrab_path }};
|
||||
}
|
||||
location {{ nginx_podgrab_path }} {
|
||||
#include /etc/nginx/require_auth.conf;
|
||||
|
||||
# json for a tag:
|
||||
# https://hass.sudo.is/podcasts/tags/${tag}
|
||||
|
||||
# add rss type or let podgrab handle it?
|
||||
# slice out the url prefix
|
||||
rewrite '^{{ nginx_podgrab_path }}(/.*)$' $1 break;
|
||||
|
||||
# rewrite html responses to add the url prefix
|
||||
sub_filter_once off;
|
||||
sub_filter 'href="/' 'href="{{ nginx_podgrab_path }}/';
|
||||
sub_filter 'src="/' 'src="{{ nginx_podgrab_path }}/';
|
||||
sub_filter '= "/' '= "{{ nginx_podgrab_path }}/';
|
||||
sub_filter ':"/' ':"{{ nginx_podgrab_path }}/';
|
||||
sub_filter ':href="\'/' ':href="\'{{ nginx_podgrab_path }}/';
|
||||
sub_filter 'return "/' 'return "{{ nginx_podgrab_path }}/';
|
||||
sub_filter '("/' '("{{ nginx_podgrab_path }}/';
|
||||
sub_filter '`/' '`{{ nginx_podgrab_path }}/';
|
||||
sub_filter '/ws' '{{ nginx_podgrab_path }}/ws';
|
||||
|
||||
# nuke the service worker cache
|
||||
sub_filter '.js' '.js?id=$request_id';
|
||||
sub_filter '.css' '.css?id=$request_id';
|
||||
|
||||
# headers for websockets
|
||||
#proxy_set_header Upgrade $http_upgrade;
|
||||
#proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
#proxy_set_header X-Forwarded-Proto $scheme;
|
||||
#proxy_set_header X-Forwarded-Host $http_host;
|
||||
#proxy_set_header Host $http_host;
|
||||
|
||||
proxy_pass http://localhost:{{ podgrab_port }}{{ nginx_podgrab_path }}/;
|
||||
}
|
||||
ben
commented
vhost vhost
|
||||
|
||||
access_log /var/log/nginx/access_{{ hass_url }}.log main;
|
||||
error_log /var/log/nginx/error_{{ hass_url }}.log warn;
|
||||
|
||||
ssl_session_timeout 5m;
|
||||
ssl_certificate /usr/local/etc/certs/{{ domain }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ domain }}/privkey.pem;
|
||||
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
#default $http_connection;
|
||||
'' close;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
{% endif -%}
|
||||
|
||||
include /etc/nginx/authelia_internal.conf;
|
||||
include listen-proxy-protocol.conf;
|
||||
include /etc/nginx/sudo-known.conf;
|
||||
|
||||
server_name {{ hass_url }};
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_pass http://127.0.0.1:8123;
|
||||
}
|
||||
|
||||
location = {{ nginx_zwavejs_path }} {
|
||||
# zwavejs needs to be accessed with a trailing / to respond.
|
||||
#
|
||||
# temporary redirects dont get remembered by the browser
|
||||
# and redirect issues are no fun
|
||||
return 302 https://{{ hass_url }}{{ nginx_zwavejs_path }}/;
|
||||
}
|
||||
|
||||
location {{ nginx_zwavejs_path }} {
|
||||
#add_header Access-Control-Allow-Origin "*" always;
|
||||
# kill cache
|
||||
add_header Last-Modified $date_gmt always;
|
||||
add_header Cache-Control 'no-store' always;
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
|
||||
include /etc/nginx/require_auth.conf;
|
||||
|
||||
rewrite ^ $request_uri;
|
||||
rewrite '^{{ nginx_zwavejs_path }}(/.*)$' $1 break;
|
||||
|
||||
proxy_set_header X-External-Path {{ nginx_zwavejs_path }};
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
#proxy_socket_keepalive on;
|
||||
|
||||
proxy_pass http://{{ bridgewithdns.zwavejs }}:8091$uri;
|
||||
#proxy_pass http://{{ bridgewithdns.zwavejs }}:8091;
|
||||
# for the special dashboard
|
||||
# https://zwave-js.github.io/zwave-js-ui/#/usage/reverse-proxy?id=using-an-http-header
|
||||
# proxy_set_header X-External-Path $http_x_ingress_path;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/access_{{ hass_url }}.log main;
|
||||
error_log /var/log/nginx/error_{{ hass_url }}.log warn;
|
||||
|
||||
ssl_session_timeout 5m;
|
||||
ssl_certificate /usr/local/etc/certs/{{ hass_url }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ hass_url }}/privkey.pem;
|
||||
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
server {
|
||||
listen 443 ssl http2;
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
{% endif -%}
|
||||
|
||||
include /etc/nginx/authelia_internal.conf;
|
||||
include listen-proxy-protocol.conf;
|
||||
include /etc/nginx/sudo-known.conf;
|
||||
|
||||
server_name {{ zwavejs_url }};
|
||||
|
||||
location / {
|
||||
include /etc/nginx/require_auth.conf;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
# nuke cache
|
||||
add_header Last-Modified $date_gmt always;
|
||||
add_header Cache-Control 'no-store' always;
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
|
||||
# nuke the service worker cache
|
||||
sub_filter '.js' '.js?id=$request_id';
|
||||
## for the special dashboard
|
||||
## https://zwave-js.github.io/zwave-js-ui/#/usage/reverse-proxy?id=using-an-http-header
|
||||
#proxy_set_header X-External-Path "/";
|
||||
proxy_set_header X-External-Path $http_x_ingress_path;
|
||||
|
||||
proxy_pass http://{{ bridgewithdns.zwavejs }}:8091;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/access_{{ zwavejs_url }}.log main;
|
||||
error_log /var/log/nginx/error_{{ zwavejs_url }}.log warn;
|
||||
|
||||
ssl_session_timeout 5m;
|
||||
ssl_certificate /usr/local/etc/certs/{{ domain }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ domain }}/privkey.pem;
|
||||
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", GROUP="adm", MODE="0666", SYMLINK+="rtl_sdr"
|
|
@ -0,0 +1,174 @@
|
|||
- alias: monitor_radiators_reporting
|
||||
description: monitor that the battery-powered radiator knobs are working
|
||||
trigger:
|
||||
{% for radiator in hass_radiators -%}
|
||||
{% if 'status' in radiator -%}
|
||||
- platform: state
|
||||
id: "radiator {{ radiator.name }}"
|
||||
entity_id:
|
||||
- binary_sensor.radiator_{{ radiator.name }}_reporting
|
||||
to: 'off'
|
||||
{% endif -%}
|
||||
{% endfor %}
|
||||
|
||||
condition: []
|
||||
mode: single
|
||||
action:
|
||||
- service: notify.persistent_notification
|
||||
data:
|
||||
title: 'device not reporting'
|
||||
message: 'stopped reporting: {%raw%}{{ trigger.id }}{%endraw%}'
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: 'device not reporting'
|
||||
message: 'stopped reporting: {%raw%}{{ trigger.id }}{%endraw%}'
|
||||
|
||||
- alias: refresh_light_switches_state
|
||||
description: the tkbhome switches dont automatically report their state
|
||||
trigger:
|
||||
- platform: time_pattern
|
||||
minutes: "/1"
|
||||
condition: []
|
||||
mode: single
|
||||
action:
|
||||
- service: zwave_js.refresh_value
|
||||
data:
|
||||
entity_id:
|
||||
{% for item in hass_light_switches -%}
|
||||
{% if item.automation_refresh|default(false) -%}
|
||||
- {{ item.entity_id }}
|
||||
{% endif -%}
|
||||
{% endfor %}
|
||||
|
||||
{% for item in hass_light_switches -%}
|
||||
{% set domain = item.entity_id.split('.')[0] %}
|
||||
{% set name = item.entity_id.split('.')[1] %}
|
||||
{% if 'auto_off' in item %}
|
||||
- alias: {{ name }}_turn_off
|
||||
description: automatically turn off {{ name }} {{ domain}}
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id:
|
||||
- {{ item.entity_id }}
|
||||
to: "on"
|
||||
for:
|
||||
minutes: {{ item.auto_off }}
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: {{ item.entity_id }}
|
||||
state: "on"
|
||||
action:
|
||||
- service: {{ domain }}.turn_off
|
||||
data: {}
|
||||
target:
|
||||
entity_id: {{ item.entity_id }}
|
||||
mode: single
|
||||
{% endif -%}
|
||||
{% endfor %}
|
||||
|
||||
{% for linux_tracker in hass_linux_presence_trackers -%}
|
||||
- alias: "webhook_presence_trackers_{{ linux_tracker.name }}"
|
||||
description: ""
|
||||
trigger:
|
||||
- platform: webhook
|
||||
webhook_id: {{ linux_tracker.name }}-{{ linux_tracker.webhook_key }}
|
||||
id: webhook
|
||||
mode: single
|
||||
action:
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{%raw -%} {% {%endraw%} set current_value = states('input_text.webhook_{{ linux_tracker.name }}') {%raw%} %} {%endraw%}
|
||||
{% raw %}
|
||||
{{ current_value != trigger.json['state'] }}
|
||||
{% endraw %}
|
||||
|
||||
then:
|
||||
- service: input_text.set_value
|
||||
target:
|
||||
entity_id: input_text.webhook_{{ linux_tracker.name }}
|
||||
data:
|
||||
value: "{% raw %}{{ trigger.json.state }}{% endraw %}"
|
||||
|
||||
- alias: "inactive_webhook_presence_trackers_{{ linux_tracker.name }}"
|
||||
description: ""
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: binary_sensor.{{ linux_tracker.name }}_webhook_triggering
|
||||
to: "off"
|
||||
action:
|
||||
- service: input_text.set_value
|
||||
target:
|
||||
entity_id: input_text.webhook_{{ linux_tracker.name }}
|
||||
data:
|
||||
value: "inactive"
|
||||
|
||||
{% endfor %}
|
||||
|
||||
- alias: flood_sensor_washing_machine
|
||||
description: ""
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id:
|
||||
- binary_sensor.flood_sensor_water_leak_detected
|
||||
to: "on"
|
||||
condition: []
|
||||
mode: single
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
data: {}
|
||||
target:
|
||||
entity_id: switch.washing_machine
|
||||
- service: notify.notify
|
||||
data:
|
||||
title: "FLOOD SENSOR BATHROOM"
|
||||
message: "WATER DETECTED! power to washing machine was cut"
|
||||
- if:
|
||||
- condition: zone
|
||||
entity_id: person.ben
|
||||
zone: zone.home
|
||||
then:
|
||||
- service: switch.turn_on
|
||||
data: {}
|
||||
target:
|
||||
entity_id: switch.nad_c370
|
||||
- service: media_player.play_media
|
||||
data:
|
||||
media_content_type: video/webm
|
||||
media_content_id: media-source://media_source/media/flood_alert.mp3
|
||||
target:
|
||||
entity_id: media_player.den_tv
|
||||
ben
commented
improve improve
|
||||
|
||||
- alias: buzzer_normally_closed
|
||||
description: "keep the buzzer switch closed"
|
||||
mode: single
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id:
|
||||
- switch.doorbell_buzzer
|
||||
to: "on"
|
||||
for:
|
||||
hours: 0
|
||||
minutes: 0
|
||||
seconds: 1
|
||||
condition: []
|
||||
action:
|
||||
- service: switch.turn_off
|
||||
data: {}
|
||||
target:
|
||||
entity_id: switch.doorbell_buzzer
|
||||
|
||||
{% for item in hass_feedreader -%}
|
||||
- alias: "podcast_parse_feed_{{ item.short_name }}"
|
||||
trigger:
|
||||
platform: event
|
||||
event_type: feedreader
|
||||
event_data:
|
||||
feed_url: "{{ item.url }}"
|
||||
action:
|
||||
service: persistent_notification.create
|
||||
data:
|
||||
title: "Podcast parsed"
|
||||
message: {% raw %}"{{ trigger.event.data }}"{% endraw %}
|
||||
|
||||
{% endfor %}
|
|
@ -0,0 +1,38 @@
|
|||
{#
|
||||
# nmcli device wifi blackbox ifname wlo1 ssid {{ hass_wifi_blackbox.ssid }} password {{ hass_wifi_blackbox.pass }}
|
||||
#}
|
||||
[connection]
|
||||
id=blackbox
|
||||
uuid={{ hass_wifi_blackbox.uuid }}
|
||||
type=wifi
|
||||
autoconnect=false
|
||||
interface-name={{ hass_wifi_blackbox.iface }}
|
||||
{% if timestamp.stdout %}
|
||||
{{ timestamp.stdout }}
|
||||
{% else %}
|
||||
timestamp={{ ansible_date_time.epoch }}
|
||||
{% endif %}
|
||||
|
||||
[wifi]
|
||||
mode=ap
|
||||
ssid={{ hass_wifi_blackbox.ssid }}
|
||||
{% if hass_wifi_blackbox.hidden|default(false) -%}
|
||||
hidden=true
|
||||
{% endif %}
|
||||
|
||||
[wifi-security]
|
||||
group=ccmp;
|
||||
key-mgmt=wpa-psk
|
||||
pairwise=ccmp;
|
||||
proto=rsn;
|
||||
psk={{ hass_wifi_blackbox.pass }}
|
||||
|
||||
[ipv4]
|
||||
address1={{ hass_wifi_blackbox.ip }}/{{ hass_wifi_blackbox.cidr_prefix }}
|
||||
method=manual
|
||||
|
||||
[ipv6]
|
||||
addr-gen-mode=stable-privacy
|
||||
method=ignore
|
||||
|
||||
[proxy]
|
|
@ -0,0 +1,71 @@
|
|||
{% if blink1_enabled -%}
|
||||
friendly_name: blink1
|
||||
value_template: >-
|
||||
{% raw -%}
|
||||
{{ state_attr('sensor.blink1', 'rgb') != "#000000" }}
|
||||
{% endraw %}
|
||||
|
||||
# color_template: >-
|
||||
# {% raw -%}
|
||||
# {{ state_attr('sensor.blink1', 'rgb') }}
|
||||
# {% endraw %}
|
||||
|
||||
turn_on:
|
||||
- service: rest_command.blink1_turn_on
|
||||
- delay:
|
||||
milliseconds: 500
|
||||
- service: homeassistant.update_entity
|
||||
target:
|
||||
entity_id: sensor.blink1
|
||||
turn_off:
|
||||
- service: rest_command.blink1_turn_off
|
||||
- delay:
|
||||
milliseconds: 500
|
||||
- service: homeassistant.update_entity
|
||||
target:
|
||||
entity_id: sensor.blink1
|
||||
set_color:
|
||||
- service: rest_command.blink1_turn_off
|
||||
- service: rest_command.blink1_set_color
|
||||
data:
|
||||
# https://github.com/velijv/home-assistant-color-helpers#rgb-to-hex
|
||||
# https://community.home-assistant.io/t/advanced-light-template-help/175654
|
||||
# https://community.home-assistant.io/t/using-hsv-hsb-to-set-colored-lights/15472
|
||||
rgb: >-
|
||||
{%raw%}
|
||||
{%- set h2 = h / 360 -%}
|
||||
{%- set s2 = s / 100 -%}
|
||||
{%- set v = 100 -%}
|
||||
{%- set i = (h2 * 6 ) | round(2,'floor') | int-%}
|
||||
{%- set f = h2 * 6 - i -%}
|
||||
{%- set p = v * (1 - s2) -%}
|
||||
{%- set q = v * (1 - f * s2) -%}
|
||||
{%- set t = v * (1 - (1 - f) * s2) -%}
|
||||
{%- if i % 6 == 0 -%}
|
||||
{%- set r = v | int -%}
|
||||
{%- set g = t | int -%}
|
||||
{%- set b = p | int -%}
|
||||
{%- elif i % 6 == 1 -%}
|
||||
{%- set r = q | int -%}
|
||||
{%- set g = v | int -%}
|
||||
{%- set b = p | int -%}
|
||||
{%- elif i % 6 == 2 -%}
|
||||
{%- set r = p | int -%}
|
||||
{%- set g = v | int -%}
|
||||
{%- set b = t | int -%}
|
||||
{%- elif i % 6 == 3 -%}
|
||||
{%- set r = p | int -%}
|
||||
{%- set g = q | int -%}
|
||||
{%- set b = v | int -%}
|
||||
{%- elif i % 6 == 4 -%}
|
||||
{%- set r = t | int -%}
|
||||
{%- set g = p | int -%}
|
||||
{%- set b = v | int -%}
|
||||
{%- elif i % 6 == 5 -%}
|
||||
{%- set r = v | int -%}
|
||||
{%- set g = p | int -%}
|
||||
{%- set b = q | int -%}
|
||||
{%- endif -%}
|
||||
{{ '%02x%02x%02x' | format(r, g, b) }}
|
||||
{%endraw%}
|
||||
{% endif %}
|
|
@ -0,0 +1,52 @@
|
|||
{% raw -%}
|
||||
- platform: climate_template
|
||||
name: Radiators
|
||||
modes:
|
||||
- "auto"
|
||||
- "heat"
|
||||
- "cool"
|
||||
- "off"
|
||||
min_temp: 0
|
||||
max_temp: 30
|
||||
|
||||
current_temperature_template: "{{ states('input_number.heating_setpoint_test') }}"
|
||||
hvac_mode_template: "{{ states('input_select.heating_mode_test') }}"
|
||||
current_humidity_template: 0.0
|
||||
swing_mode_template: false
|
||||
availability_template: true
|
||||
|
||||
set_temperature:
|
||||
- service: input_number.set_value
|
||||
data:
|
||||
value: >-
|
||||
{% set set_point = float(state_attr('climate.radiators', 'temperature'), 14.0) %}
|
||||
{{ set_point }}
|
||||
target:
|
||||
entity_id: input_number.heating_setpoint_test
|
||||
|
||||
set_hvac_mode:
|
||||
- service: input_select.select_option
|
||||
data:
|
||||
option: >-
|
||||
{% set hvac_mode = state_attr('climate.radiators', 'hvac_mode') | default('off') %}
|
||||
{{ hvac_mode }}
|
||||
target:
|
||||
entity_id: input_select.heating_mode_test
|
||||
|
||||
{% endraw %}
|
||||
|
||||
{# use this in script?
|
||||
{{ state_attr('climate.radiators', 'temperature') }}
|
||||
|
||||
this should work, but doesnt
|
||||
docs: https://www.home-assistant.io/integrations/template/
|
||||
{{ this.attributes.temperature }}
|
||||
|
||||
https://github.com/jcwillox/hass-template-climate/issues/29
|
||||
|
||||
this syntax works:
|
||||
{% set set_point = float(state_attr('climate.radiators', 'temperature'), 14.0) %}
|
||||
{{ set_point }}
|
||||
|
||||
target_temperature_template: "{{ states('input_number.heating_setpoint_test') }}"
|
||||
#}
|
|
@ -57,48 +57,84 @@ default_config:
|
|||
# zeroconf:
|
||||
# zone:
|
||||
|
||||
automation ui: !include automations.yaml
|
||||
automation ansible: !include automations-ansible-managed.yaml
|
||||
script: !include scripts.yaml
|
||||
scene: !include scenes.yaml
|
||||
template: !include templates.yaml
|
||||
climate: !include climate.yaml
|
||||
|
||||
# Text to speech
|
||||
tts:
|
||||
- platform: voicerss
|
||||
api_key: !secret voicerss_api_key
|
||||
- platform: google_translate
|
||||
|
||||
automation: !include automations.yaml
|
||||
script: !include scripts.yaml
|
||||
scene: !include scenes.yaml
|
||||
template: !include templates.yaml
|
||||
|
||||
{# calendar:
|
||||
# {% for item in hass_caldav.urls %}
|
||||
#
|
||||
# - platform: caldav
|
||||
# days: 30
|
||||
# username: !secret caldav_user
|
||||
# password: !secret caldav_passwd
|
||||
# # {{ item.name }}
|
||||
# url: {{ item.url }}
|
||||
#
|
||||
# {% endfor %}
|
||||
#}
|
||||
- platform: picotts
|
||||
language: "en-GB"
|
||||
|
||||
calendar:
|
||||
{% for item in hass_caldav.calendars -%}
|
||||
- platform: caldav
|
||||
days: 30
|
||||
username: !secret caldav_user
|
||||
password: !secret caldav_passwd
|
||||
# {{ hass_caldav.urls[0].name }}
|
||||
url: {{ hass_caldav.urls[0].url }}
|
||||
# {{ item.name | trim }}
|
||||
url: {{ item.url | trim }}
|
||||
{% endfor %}
|
||||
|
||||
http:
|
||||
# container runs with network_mode=host, so no network isolation. the docs say to not
|
||||
# do this, and it doesnt work as expected either.
|
||||
# using ufw/iptables for now....
|
||||
#
|
||||
#server_host: 127.0.0.1
|
||||
server_host: 127.0.0.1
|
||||
server_port: 8123
|
||||
trusted_proxies:
|
||||
- 127.0.0.1
|
||||
use_x_forwarded_for: true
|
||||
|
||||
frontend:
|
||||
themes: !include_dir_merge_named themes
|
||||
|
||||
panel_custom:
|
||||
- name: zwave
|
||||
sidebar_title: Z-Wave
|
||||
sidebar_icon: mdi:z-wave
|
||||
js_url: /api/hassio/app/entrypoint.js
|
||||
url_path: 'config/devices/dashboard?historyBack=1&config_entry=d6e38621854098348266029e18f93048'
|
||||
embed_iframe: true
|
||||
require_admin: true
|
||||
config:
|
||||
ingress: core_configurator
|
||||
- name: automations
|
||||
sidebar_title: Automations
|
||||
sidebar_icon: mdi:robot
|
||||
js_url: /api/hassio/app/entrypoint.js
|
||||
url_path: 'config/automation/dashboard'
|
||||
embed_iframe: true
|
||||
require_admin: true
|
||||
config:
|
||||
ingress: core_configurator
|
||||
- name: scripts
|
||||
sidebar_title: Scripts
|
||||
sidebar_icon: mdi:script
|
||||
js_url: /api/hassio/app/entrypoint.js
|
||||
url_path: 'config/script/dashboard'
|
||||
embed_iframe: true
|
||||
require_admin: true
|
||||
config:
|
||||
ingress: core_configurator
|
||||
- name: integrations
|
||||
sidebar_title: Integrations
|
||||
sidebar_icon: mdi:integrated-circuit-chip
|
||||
js_url: /api/hassio/app/entrypoint.js
|
||||
url_path: 'config/integrations'
|
||||
embed_iframe: true
|
||||
require_admin: true
|
||||
config:
|
||||
ingress: core_configurator
|
||||
|
||||
|
||||
{% set zone = {'zone': hass_zones} %}
|
||||
{{ zone | to_nice_yaml }}
|
||||
|
||||
|
||||
homeassistant:
|
||||
auth_providers:
|
||||
- type: command_line
|
||||
|
@ -109,6 +145,7 @@ homeassistant:
|
|||
currency: EUR
|
||||
unit_system: metric
|
||||
time_zone: "Europe/Berlin"
|
||||
country: DE
|
||||
external_url: https://{{ hass_url }}
|
||||
internal_url: https://{{ hass_url }}
|
||||
allowlist_external_dirs:
|
||||
|
@ -118,6 +155,42 @@ homeassistant:
|
|||
- "https://{{ hass_notflix_url }}"
|
||||
media_dirs:
|
||||
media: "/usr/var/media"
|
||||
customize:
|
||||
zone.home:
|
||||
friendly_name: S21
|
||||
|
||||
lovelace:
|
||||
mode: storage
|
||||
dashboards:
|
||||
lovelace-yaml:
|
||||
mode: yaml
|
||||
title: Mini
|
||||
icon: mdi:view-dashboard
|
||||
show_in_sidebar: true
|
||||
require_admin: false
|
||||
filename: mini.yaml
|
||||
lovelace-yaml2:
|
||||
mode: yaml
|
||||
title: Test
|
||||
icon: mdi:view-dashboard
|
||||
show_in_sidebar: true
|
||||
require_admin: false
|
||||
filename: ui-test.yaml
|
||||
|
||||
{# resources:
|
||||
# - url: /config/custom_components/ui_lovelace_minimalist/cards/button-card/button-card.js
|
||||
# type: module
|
||||
# - url: /config/custom_components/ui_lovelace_minimalist/cards/button-card/button-card.js
|
||||
# type: module #}
|
||||
|
||||
recorder:
|
||||
purge_keep_days: 3
|
||||
exclude:
|
||||
entity_globs:
|
||||
- binary_sensor.1066d799*
|
||||
- sensor.1066d799*
|
||||
- light.1066d799*
|
||||
|
||||
|
||||
sensor:
|
||||
# https://www.home-assistant.io/integrations/dwd_weather_warnings/
|
||||
|
@ -144,28 +217,116 @@ sensor:
|
|||
# Stadt Berlin
|
||||
region_name: 811000000
|
||||
|
||||
{% for item in hass_bvg -%}
|
||||
- platform: bvg_berlin_public_transport
|
||||
name: {{ item.name }}
|
||||
stop_id: "{{ item.stop_id }}"
|
||||
direction: {{ item.direction | trim }}
|
||||
{% if item.walking_distance is defined -%}
|
||||
walking_distance: {{ item.walking_distance | trim }}
|
||||
{% endif -%}
|
||||
file_path: "/config/bvg/"
|
||||
{% endfor %}
|
||||
|
||||
- platform: waqi
|
||||
token: !secret waqi_token
|
||||
locations:
|
||||
{% for item in hass_waqi.locations -%}
|
||||
- "{{ item | trim }}"
|
||||
{%- endfor +%}
|
||||
{#stations:
|
||||
#{% for item in hass_waqi.stations -%}
|
||||
#- "{{ item | trim }}"
|
||||
#{% endfor %}
|
||||
#}
|
||||
|
||||
{% if blink1_enabled -%}
|
||||
- platform: rest
|
||||
resource: http://localhost:{{ blink1_server_port }}/blink1
|
||||
name: blink1
|
||||
json_attributes:
|
||||
- rgb
|
||||
- bright
|
||||
value_template: "{%raw%}{{ value_json.rgb }}{%endraw%}"
|
||||
{% endif %}
|
||||
|
||||
binary_sensor:
|
||||
- platform: workday
|
||||
country: DE
|
||||
workdays: [mon, tue, wed, thu, fri]
|
||||
excludes: [sat, sun, holiday]
|
||||
|
||||
{% for radiator in hass_radiators -%}
|
||||
{% if 'status' in radiator -%}
|
||||
- platform: threshold
|
||||
entity_id: sensor.radiator_{{ radiator.name }}_last_updated
|
||||
# defined in templates.yaml
|
||||
name: radiator_{{ radiator.name }}_reporting
|
||||
# minutes
|
||||
lower: 10
|
||||
{% endif -%}
|
||||
{% endfor -%}
|
||||
{% for target in hass_ping -%}
|
||||
- platform: ping
|
||||
name: ping_{{ target.name }}
|
||||
host: {{ target.host }}
|
||||
count: 1
|
||||
scan_interval: {{ target.interval_secs }}
|
||||
count: {{ target.count | default('1') }}
|
||||
scan_interval: {{ target.interval_secs | default('30') }}
|
||||
{% endfor %}
|
||||
|
||||
input_select:
|
||||
heating_mode_test:
|
||||
name: Heating Mode Test
|
||||
options:
|
||||
- "auto"
|
||||
- "heat"
|
||||
- "cool"
|
||||
- "off"
|
||||
initial: "off"
|
||||
icon: mdi:thermometer-lines
|
||||
|
||||
|
||||
input_number:
|
||||
heating_setpoint_test:
|
||||
name: Heating Setpoint Test
|
||||
icon: mdi:home-thermometer
|
||||
initial: 0
|
||||
min: 0
|
||||
max: 35
|
||||
step: 0.5
|
||||
|
||||
input_text:
|
||||
{% for linux_tracker in hass_linux_presence_trackers -%}
|
||||
webhook_{{ linux_tracker.name }}:
|
||||
name: webhook_{{ linux_tracker.name }}
|
||||
icon: "mdi:laptop"
|
||||
initial: "inactive"
|
||||
pattern: "^active|inactive$"
|
||||
{% endfor %}
|
||||
|
||||
device_tracker:
|
||||
- platform: bluetooth_le_tracker
|
||||
interval_seconds: 12
|
||||
track_new_devices: false
|
||||
track_battery: false
|
||||
consider_home: 150
|
||||
new_device_defaults:
|
||||
track_new_devices: false
|
||||
- platform: bluetooth_tracker
|
||||
request_rssi: false
|
||||
interval_seconds: 12
|
||||
track_new_devices: false
|
||||
consider_home: 150
|
||||
new_device_defaults:
|
||||
track_new_devices: false
|
||||
- platform: ping
|
||||
hosts:
|
||||
{% for target in hass_ping -%}
|
||||
{% if target.device_tracker|default(true) -%}
|
||||
{{ target.name }}: {{ target.host }}
|
||||
{% endif -%}
|
||||
{% endfor %}
|
||||
|
||||
# enabling bluetooth
|
||||
bluetooth:
|
||||
|
||||
influxdb:
|
||||
host: "{{ influxdb_url }}"
|
||||
|
@ -186,5 +347,79 @@ influxdb:
|
|||
source: hass
|
||||
home: S21
|
||||
|
||||
matrix:
|
||||
homeserver: https://{{ matrix_url }}
|
||||
username: !secret matrix_username
|
||||
password: !secret matrix_password
|
||||
rooms: !secret matrix_rooms
|
||||
commands:
|
||||
- word: hass
|
||||
name: hass
|
||||
|
||||
notify:
|
||||
- name: matrix
|
||||
platform: matrix
|
||||
default_room: !secret matrix_default_room
|
||||
- name: pagerduty
|
||||
platform: smtp
|
||||
sender: hass@{{ domain }}
|
||||
recipient:
|
||||
- !secret smtp_recipient_email
|
||||
server: !secret smtp_server
|
||||
port: {{ smtp_port_starttls }}
|
||||
username: !secret smtp_username
|
||||
password: !secret smtp_passwd
|
||||
encryption: starttls
|
||||
sender_name: "{{ hass_url }}"
|
||||
|
||||
shell_command:
|
||||
matrixmsg: /usr/local/bin/matrixmsg.py
|
||||
|
||||
rest_command:
|
||||
{% if blink1_enabled -%}
|
||||
blink1_turn_on:
|
||||
url: {{ hass_blink1_url }}/blink1/on?bright=250
|
||||
#url: http://localhost:{{ blink1_server_port }}/blink1/fadeToRGB?rgb=ff0ff
|
||||
method: GET
|
||||
content_type: "application/json"
|
||||
blink1_turn_off:
|
||||
url: {{ hass_blink1_url }}/blink1/off
|
||||
method: GET
|
||||
content_type: "application/json"
|
||||
blink1_turn_magenta:
|
||||
url: {{ hass_blink1_url }}/blink1/fadeToRGB?rgb=ff00ff
|
||||
method: GET
|
||||
content_type: "application/json"
|
||||
blink1_set_color:
|
||||
url: "{{ hass_blink1_url }}/blink1/fadeToRGB?rgb={%raw%}{{ rgb }}{%endraw%}"
|
||||
method: GET
|
||||
{% endif %}
|
||||
|
||||
light:
|
||||
{% if blink1_enabled -%}
|
||||
- platform: template
|
||||
lights:
|
||||
blink1: !include blink1.yaml
|
||||
{% endif %}
|
||||
|
||||
# enable 'wake_on_lan' for 'samsungtv'
|
||||
wake_on_lan:
|
||||
|
||||
samsungtv:
|
||||
- host: {{ hass_wifi_blackbox.tv_ip }}
|
||||
name: The TV
|
||||
turn_on_action:
|
||||
- service: wake_on_lan.send_magic_packet
|
||||
data:
|
||||
mac: "{{ hass_wifi_blackbox.tv_mac }}"
|
||||
|
||||
feedreader:
|
||||
urls:
|
||||
{% for item in hass_feedreader -%}
|
||||
- "{{ item.url | trim }}"
|
||||
{% endfor %}
|
||||
|
||||
{# logger:
|
||||
# logs:
|
||||
# pyatv: debug
|
||||
# homeassistant.components.apple_tv: debug #}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
# we can "safely" template in the actual secrets here and keep them out of
|
||||
# configuration.yaml, which does get synced to the repo.
|
||||
|
||||
openwrt_user: "{{ hass_openwrt_user }}"
|
||||
openwrt_pass: "{{ hass_openwrt_pass }}"
|
||||
|
||||
caldav_user: "{{ hass_caldav.user }}"
|
||||
caldav_passwd: "{{ hass_caldav.passwd }}"
|
||||
|
||||
|
@ -10,3 +13,17 @@ voicerss_api_key: {{ voicerss_api_key }}
|
|||
|
||||
# see group_vars/monitoring.yml
|
||||
influxdb_pass: {{ hass_influxdb_pass }}
|
||||
|
||||
matrix_username: "{{ hass_matrix.username }}"
|
||||
matrix_password: "{{ hass_matrix.password }}"
|
||||
{% set rooms = {'matrix_rooms': hass_matrix.rooms} -%}
|
||||
{{ rooms | to_nice_yaml }}
|
||||
matrix_default_room: "{{ hass_matrix.rooms[0] }}"
|
||||
|
||||
smtp_recipient_email: "{{ pagerduty_email }}"
|
||||
smtp_server: "{{ smtp_server }}"
|
||||
smtp_username: "{{ smtp_username }}"
|
||||
smtp_passwd: "{{ smtp_passwd }}"
|
||||
|
||||
|
||||
waqi_token: {{ hass_waqi.token }}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
- sensor:
|
||||
ben marked this conversation as resolved
ben
commented
this file needs serious work but thats not for this pr this file needs serious work but thats not for this pr
|
||||
- name: "chance_of_rain"
|
||||
unit_of_measurement: "%"
|
||||
icon: "mdi:weather-pouring"
|
||||
state: >-
|
||||
{% raw -%}
|
||||
{% set ipma_2h = state_attr('weather.ipma_hourly_home', 'forecast')[:2] | map(attribute='precipitation_probability') %}
|
||||
{% set ipma = state_attr('weather.ipma_hourly_home', 'forecast')[0]['precipitation_probability'] | int %}
|
||||
{% set owm = states('sensor.owm_home_forecast_precipitation_probability') | int %}
|
||||
{{ [owm, ipma, 0] | max | int }}
|
||||
{% endraw %}
|
||||
|
||||
{% for radiator in hass_radiators %}
|
||||
{% if 'status' in radiator %}
|
||||
|
||||
- name: "radiator_{{ radiator.name }}_last_updated"
|
||||
unit_of_measurement: "minutes"
|
||||
icon: "mdi:update"
|
||||
device_class: duration
|
||||
state: >-
|
||||
{% raw %} {% {% endraw -%}
|
||||
set since_last_update = now() - states.{{ radiator.status }}.last_updated
|
||||
{%- raw %} %} {% endraw %}
|
||||
|
||||
{% raw %} {{ {% endraw -%}
|
||||
since_last_update.seconds|int // 60
|
||||
{%- raw %} }} {% endraw -%}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for linux_tracker in hass_linux_presence_trackers -%}
|
||||
{% endfor %}
|
||||
|
||||
- binary_sensor:
|
||||
{% if blink1_enabled -%}
|
||||
- name: "blink1_on"
|
||||
device_class: light
|
||||
state: >-
|
||||
{% raw -%}
|
||||
{{ state_attr('sensor.blink1', 'rgb') != "#000000" }}
|
||||
{% endraw %}
|
||||
{% endif %}
|
||||
|
||||
- name: "heating_on"
|
||||
icon: "mdi:home-thermometer"
|
||||
device_class: heat
|
||||
state: >-
|
||||
{% raw -%}
|
||||
{% set all_radiators = states.climate | selectattr("attributes", "defined") | map(attribute="attributes") | selectattr("temperature", "defined") | map(attribute="temperature") | default([]) | list %}
|
||||
{% set max_radiator_temp = all_radiators | max | default(0.0) | float %}
|
||||
{% set target_temp = states('input_number.target_temp_heat') | default(0.0) | float %}
|
||||
{{ max_radiator_temp >= target_temp }}
|
||||
{% endraw %}
|
||||
|
||||
- name: s21_anyone_home
|
||||
ben marked this conversation as resolved
ben
commented
remove remove
ben
commented
fixed, not in this pr. fixed, not in this pr.
|
||||
icon: "mdi:home-account"
|
||||
attributes:
|
||||
friendly_name: "Anyone home"
|
||||
state: >-
|
||||
{% raw -%}
|
||||
{{ state_attr("zone.home", "persons") | default([]) | length > 0 }}
|
||||
{% endraw %}
|
||||
|
||||
- name: doorbell_buzzer
|
||||
state: >-
|
||||
{% raw %} {{ is_state("switch.doorbell_buzzer", "on") }} {% endraw +%}
|
||||
icon: >-
|
||||
{% raw -%}
|
||||
{% if is_state("switch.doorbell_buzzer", "on") %}
|
||||
mdi:electric-switch-closed
|
||||
{% else %}
|
||||
mdi:electric-switch
|
||||
{% endif %}
|
||||
{% endraw %}
|
||||
|
||||
- name: washing_machine_on
|
||||
icon: "mdi:washing-machine"
|
||||
device_class: running
|
||||
delay_on: "00:00:05"
|
||||
delay_off: "00:00:05"
|
||||
state: >-
|
||||
{% raw -%}
|
||||
{% set current = states('sensor.washing_machine_electric_a') %}
|
||||
{% set power = states('sensor.washing_machine_electric_w') %}
|
||||
{% if current == "unavailable" or power == "unavailable" %}
|
||||
{{ false }}
|
||||
{% else %}
|
||||
{{ current|default(0.0)|float > 0.14 or power|default(0.0)|float > 2.8 }}
|
||||
{% endif %}
|
||||
{% endraw %}
|
||||
|
||||
{% for linux_tracker in hass_linux_presence_trackers -%}
|
||||
- name: {{ linux_tracker.name }}_active
|
||||
icon: "mdi:laptop"
|
||||
state: >-
|
||||
{% raw -%} {% {% endraw %} set state_text = states('input_text.webhook_{{ linux_tracker.name }}') {%raw%} %} {%endraw%}
|
||||
{% raw %}
|
||||
{{ state_text == "active" }}
|
||||
{% endraw %}
|
||||
|
||||
- name: "{{ linux_tracker.name }}_webhook_triggering"
|
||||
state: >-
|
||||
{% raw %} {% {% endraw -%}
|
||||
set since_last_triggered = now() - state_attr('automation.webhook_presence_trackers_{{ linux_tracker.name }}', 'last_triggered')
|
||||
{%- raw %} %} {% endraw %}
|
||||
|
||||
{% raw %} {{ {% endraw -%}
|
||||
since_last_triggered.seconds|int < 666
|
||||
{%- raw %} }} {% endraw -%}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
- button:
|
||||
name: doorbell_buzzer
|
||||
icon: >-
|
||||
{% raw -%}
|
||||
{% if is_state("switch.doorbell_buzzer", "on") %}
|
||||
mdi:electric-switch-closed
|
||||
{% else %}
|
||||
mdi:electric-switch
|
||||
{% endif %}
|
||||
{% endraw +%}
|
||||
press:
|
||||
- service: script.toggle_switch_like_button
|
||||
data:
|
||||
target_switch: switch.doorbell_buzzer
|
||||
press_for_ms: 200
|
||||
ben marked this conversation as resolved
ben
commented
duplicate file? duplicate file?
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
|
||||
dependencies:
|
||||
- unifi
|
||||
- sudoisbot
|
||||
- hass
|
||||
- homeaudio
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
|
||||
dependencies:
|
||||
- podgrab
|
||||
- airconnect
|
||||
- shairplay
|
||||
- owntone
|
|
@ -0,0 +1,452 @@
|
|||
# A quick guide to configuring OwnTone:
|
||||
#
|
||||
# For regular use, the most important setting to configure is "directories",
|
||||
# which should be the location of your media. Whatever user you have set as
|
||||
# "uid" must have read access to this location. If the location is a network
|
||||
# mount, please see the README.
|
||||
#
|
||||
# In all likelihood, that's all you need to do!
|
||||
|
||||
general {
|
||||
# Username
|
||||
# Make sure the user has read access to the library directories you set
|
||||
# below, and full access to the databases, log and local audio
|
||||
uid = "abc"
|
||||
|
||||
# Database location
|
||||
db_path = "/config/dbase_and_logs/songs3.db"
|
||||
|
||||
# Database backup location
|
||||
# Uncomment and specify a full path to enable abilty to use REST endpoint
|
||||
# to initiate backup of songs3.db
|
||||
#db_backup_path = "/var/cache/owntone/songs3.bak"
|
||||
|
||||
# Log file and level
|
||||
# Available levels: fatal, log, warning, info, debug, spam
|
||||
logfile = "/config/dbase_and_logs/owntone.log"
|
||||
loglevel = log
|
||||
|
||||
# Admin password for the web interface
|
||||
# Note that access to the web interface from computers in
|
||||
# "trusted_network" (see below) does not require password
|
||||
#admin_password = ""
|
||||
|
||||
# Websocket port for the web interface.
|
||||
websocket_port = 3688
|
||||
|
||||
# Websocket interface to bind listener to (e.g. "eth0"). Default is
|
||||
# disabled, which means listen on all interfaces.
|
||||
#websocket_interface = ""
|
||||
|
||||
# Sets who is allowed to connect without authorisation. This applies to
|
||||
# client types like Remotes, DAAP clients (iTunes) and to the web
|
||||
# interface. Options are "any", "localhost" or the prefix to one or
|
||||
# more ipv4/6 networks. The default is { "localhost", "192.168", "fd" }
|
||||
trusted_networks = { "localhost", "192.168.21", "10.102.47", "fd" }
|
||||
|
||||
# Enable/disable IPv6
|
||||
ipv6 = no
|
||||
|
||||
# Set this if you want the server to bind to a specific IP address. Can
|
||||
# be ipv6 or ipv4. Default (commented out or "::") is to listen on all
|
||||
# IP addresses.
|
||||
#bind_address = "::"
|
||||
|
||||
# Location of cache database
|
||||
cache_path = "/config/dbase_and_logs/cache.db"
|
||||
|
||||
# DAAP requests that take longer than this threshold (in msec) get their
|
||||
# replies cached for next time. Set to 0 to disable caching.
|
||||
#cache_daap_threshold = 1000
|
||||
|
||||
# When starting playback, autoselect speaker (if none of the previously
|
||||
# selected speakers/outputs are available)
|
||||
#speaker_autoselect = no
|
||||
|
||||
# Most modern systems have a high-resolution clock, but if you are on an
|
||||
# unusual platform and experience audio drop-outs, you can try changing
|
||||
# this option
|
||||
#high_resolution_clock = yes
|
||||
}
|
||||
|
||||
# Library configuration
|
||||
library {
|
||||
# Name of the library as displayed by the clients (%h: hostname). If you
|
||||
# change the name after pairing with Remote you may have to re-pair.
|
||||
name = "audio.sudo.is"
|
||||
|
||||
# TCP port to listen on. Default port is 3689 (daap)
|
||||
port = 3689
|
||||
|
||||
# Password for the library. Optional.
|
||||
#password = ""
|
||||
|
||||
# Directories to index
|
||||
directories = { "/music" }
|
||||
|
||||
# Follow symlinks. Default: true.
|
||||
#follow_symlinks = true
|
||||
|
||||
# Directories containing podcasts
|
||||
# For each directory that is indexed the path is matched against these
|
||||
# names. If there is a match all items in the directory are marked as
|
||||
# podcasts. Eg. if you index /music, and your podcasts are in
|
||||
# /music/Podcasts, you can set this to "/Podcasts".
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
podcasts = { "/podcasts" }
|
||||
|
||||
# Directories containing audiobooks
|
||||
# For each directory that is indexed the path is matched against these
|
||||
# names. If there is a match all items in the directory are marked as
|
||||
# audiobooks.
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
audiobooks = { "/audiobooks" }
|
||||
|
||||
# Directories containing compilations (eg soundtracks)
|
||||
# For each directory that is indexed the path is matched against these
|
||||
# names. If there is a match all items in the directory are marked as
|
||||
# compilations.
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
compilations = { "/compilations" }
|
||||
|
||||
# Compilations usually have many artists, and sometimes no album artist.
|
||||
# If you dont want every artist to be listed in artist views, you can
|
||||
# set a single name which will be used for all compilation tracks
|
||||
# without an album artist, and for all tracks in the compilation
|
||||
# directories.
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
compilation_artist = "Various Artists"
|
||||
|
||||
# If your album and artist lists are cluttered, you can choose to hide
|
||||
# albums and artists with only one track. The tracks will still be
|
||||
# visible in other lists, e.g. songs and playlists. This setting
|
||||
# currently only works in some remotes.
|
||||
#hide_singles = false
|
||||
|
||||
# Internet streams in your playlists will by default be shown in the
|
||||
# "Radio" library, like iTunes does. However, some clients (like
|
||||
# TunesRemote+) wont show the "Radio" library. If you would also like
|
||||
# to have them shown like normal playlists, you can enable this option.
|
||||
radio_playlists = true
|
||||
|
||||
# These are the default playlists. If you want them to have other names,
|
||||
# you can set it here.
|
||||
#name_library = "Library"
|
||||
#name_music = "Music"
|
||||
#name_movies = "Movies"
|
||||
#name_tvshows = "TV Shows"
|
||||
#name_podcasts = "Podcasts"
|
||||
#name_audiobooks = "Audiobooks"
|
||||
#name_radio = "Radio"
|
||||
|
||||
# Artwork file names (without file type extension)
|
||||
# OwnTone will look for jpg and png files with these base names
|
||||
artwork_basenames = { "artwork", "cover", "Folder" }
|
||||
|
||||
# Enable searching for artwork corresponding to each individual media
|
||||
# file instead of only looking for album artwork. This is disabled by
|
||||
# default to reduce cache size.
|
||||
#artwork_individual = false
|
||||
|
||||
# File types the scanner should ignore
|
||||
# Non-audio files will never be added to the database, but here you
|
||||
# can prevent the scanner from even probing them. This might improve
|
||||
# scan time. By default .db, .ini, .db-journal, .pdf and .metadata are
|
||||
# ignored.
|
||||
#filetypes_ignore = { ".db", ".ini", ".db-journal", ".pdf", ".metadata" }
|
||||
|
||||
# File paths the scanner should ignore
|
||||
# If you want to exclude files on a more advanced basis you can enter
|
||||
# one or more POSIX regular expressions, and any file with a matching
|
||||
# path will be ignored.
|
||||
#filepath_ignore = { "myregex" }
|
||||
|
||||
# Disable startup file scanning
|
||||
# When OwnTone starts it will do an initial file scan of your
|
||||
# library (and then watch it for changes). If you are sure your library
|
||||
# never changes while OwnTone is not running, you can disable the
|
||||
# initial file scan and save some system ressources. Disabling this scan
|
||||
# may lead to OwnTones database coming out of sync with the
|
||||
# library. If that happens read the instructions in the README on how
|
||||
# to trigger a rescan.
|
||||
#filescan_disable = false
|
||||
|
||||
# Should metadata from m3u playlists, e.g. artist and title in EXTINF,
|
||||
# override the metadata we get from radio streams?
|
||||
#m3u_overrides = false
|
||||
|
||||
# Should iTunes metadata override ours?
|
||||
itunes_overrides = true
|
||||
|
||||
# Should we import the content of iTunes smart playlists?
|
||||
#itunes_smartpl = false
|
||||
|
||||
# Decoding options for DAAP clients
|
||||
# Since iTunes has native support for mpeg, mp4a, mp4v, alac and wav,
|
||||
# such files will be sent as they are. Any other formats will be decoded
|
||||
# to raw wav. If OwnTone detects a non-iTunes DAAP client, it is
|
||||
# assumed to only support mpeg and wav, other formats will be decoded.
|
||||
# Here you can change when to decode. Note that these settings have no
|
||||
# effect on AirPlay.
|
||||
# Formats: mp4a, mp4v, mpeg, alac, flac, mpc, ogg, wma, wmal, wmav, aif, wav
|
||||
# Formats that should never be decoded
|
||||
#no_decode = { "format", "format" }
|
||||
# Formats that should always be decoded
|
||||
#force_decode = { "format", "format" }
|
||||
|
||||
# Watch named pipes in the library for data and autostart playback when
|
||||
# there is data to be read. To exclude specific pipes from watching,
|
||||
# consider using the above _ignore options.
|
||||
#pipe_autostart = true
|
||||
|
||||
# Enable automatic rating updates
|
||||
# If enabled, rating is automatically updated after a song has either been
|
||||
# played or skipped (only skipping to the next song is taken into account).
|
||||
# The calculation is taken from the beets plugin "mpdstats" (see
|
||||
# https://beets.readthedocs.io/en/latest/plugins/mpdstats.html).
|
||||
# It consist of calculating a stable rating based only on the play- and
|
||||
# skipcount and a rolling rating based on the current rating and the action
|
||||
# (played or skipped). Both results are combined with a mix-factor of 0.75:
|
||||
# new rating = 0.75 * stable rating + 0.25 * rolling rating)
|
||||
#rating_updates = false
|
||||
|
||||
# Allows creating, deleting and modifying m3u playlists in the library directories.
|
||||
# Only supported by the player web interface and some mpd clients
|
||||
# Defaults to being disabled.
|
||||
allow_modifying_stored_playlists = true
|
||||
|
||||
# A directory in one of the library directories that will be used as the default
|
||||
# playlist directory. OwnTone creates new playlists in this directory if only
|
||||
# a playlist name is provided (requires "allow_modify_stored_playlists" set to true).
|
||||
default_playlist_directory = "/music/playlists"
|
||||
|
||||
# By default OwnTone will - like iTunes - clear the playqueue if
|
||||
# playback stops. Setting clear_queue_on_stop_disable to true will keep
|
||||
# the playlist like MPD does. Note that some dacp clients do not show
|
||||
# the playqueue if playback is stopped.
|
||||
#clear_queue_on_stop_disable = false
|
||||
}
|
||||
|
||||
# Local audio output
|
||||
audio {
|
||||
# Name - used in the speaker list in Remote
|
||||
nickname = "Computer"
|
||||
|
||||
# Type of the output (alsa, pulseaudio, dummy or disabled)
|
||||
#type = "alsa"
|
||||
|
||||
# For pulseaudio output, an optional server hostname or IP can be
|
||||
# specified (e.g. "localhost"). If not set, connection is made via local
|
||||
# socket.
|
||||
#server = ""
|
||||
|
||||
# Audio PCM device name for local audio output - ALSA only
|
||||
#card = "default"
|
||||
|
||||
# Mixer channel to use for volume control - ALSA only
|
||||
# If not set, PCM will be used if available, otherwise Master.
|
||||
#mixer = ""
|
||||
|
||||
# Mixer device to use for volume control - ALSA only
|
||||
# If not set, the value for "card" will be used.
|
||||
#mixer_device = ""
|
||||
|
||||
# Enable or disable audio resampling to keep local audio in sync with
|
||||
# e.g. Airplay. This feature relies on accurate ALSA measurements of
|
||||
# delay, and some devices dont provide that. If that is the case you
|
||||
# are better off disabling the feature.
|
||||
#sync_disable = false
|
||||
|
||||
# Here you can adjust when local audio is started relative to other
|
||||
# speakers, e.g. Airplay. Negative values correspond to moving local
|
||||
# audio ahead, positive correspond to delaying it. The unit is
|
||||
# milliseconds. The offset must be between -1000 and 1000 (+/- 1 sec).
|
||||
#offset_ms = 0
|
||||
|
||||
# To calculate what and if resampling is required, local audio delay is
|
||||
# measured each second. After a period the collected measurements are
|
||||
# used to estimate drift and latency, which determines if corrections
|
||||
# are required. This setting sets the length of that period in seconds.
|
||||
#adjust_period_seconds = 100
|
||||
}
|
||||
|
||||
# ALSA device settings
|
||||
# If you have multiple ALSA devices you can configure them individually via
|
||||
# sections like the below. Make sure to set the "card name" correctly. See the
|
||||
# README about ALSA for details. Note that these settings will override the ALSA
|
||||
# settings in the "audio" section above.
|
||||
#alsa "card name" {
|
||||
# Name used in the speaker list. If not set, the card name will be used.
|
||||
#nickname = "Computer"
|
||||
|
||||
# Mixer channel to use for volume control
|
||||
# If not set, PCM will be used if available, otherwise Master
|
||||
#mixer = ""
|
||||
|
||||
# Mixer device to use for volume control
|
||||
# If not set, the card name will be used
|
||||
#mixer_device = ""
|
||||
# }
|
||||
|
||||
# Pipe output
|
||||
# Allows OwnTone to output audio data to a named pipe
|
||||
#fifo {
|
||||
#nickname = "fifo"
|
||||
#path = "/path/to/fifo"
|
||||
# }
|
||||
|
||||
# AirPlay settings common to all devices
|
||||
#airplay_shared {
|
||||
# UDP ports used when airplay devices make connections back to
|
||||
# OwnTone (choosing specific ports may be helpful when running
|
||||
# OwnTone behind a firewall)
|
||||
# control_port = 0
|
||||
# timing_port = 0
|
||||
# }
|
||||
|
||||
# AirPlay per device settings
|
||||
# (make sure you get the capitalization of the device name right)
|
||||
#airplay "My AirPlay device" {
|
||||
# OwnTone's volume goes to 11! If that's more than you can handle
|
||||
# you can set a lower value here
|
||||
#max_volume = 11
|
||||
|
||||
# Enable this option to exclude a particular AirPlay device from the
|
||||
# speaker list
|
||||
#exclude = false
|
||||
|
||||
# Enable this option to keep a particular AirPlay device in the speaker
|
||||
# list and thus ignore mdns notifications about it no longer being
|
||||
# present. The speaker will remain until restart of OwnTone.
|
||||
#permanent = false
|
||||
|
||||
# Some devices spuriously disconnect during playback, and based on the
|
||||
# device type OwnTone may attempt to reconnect. Setting this option
|
||||
# overrides this so reconnecting is either always enabled or disabled.
|
||||
#reconnect = false
|
||||
|
||||
# AirPlay password
|
||||
#password = "s1kr3t"
|
||||
|
||||
# Disable AirPlay 1 (RAOP)
|
||||
#raop_disable = false
|
||||
|
||||
# Name used in the speaker list, overrides name from the device
|
||||
#nickname = "My speaker name"
|
||||
# }
|
||||
|
||||
# Chromecast settings
|
||||
# (make sure you get the capitalization of the device name right)
|
||||
#chromecast "My Chromecast device" {
|
||||
# OwnTone's volume goes to 11! If that's more than you can handle
|
||||
# you can set a lower value here
|
||||
#max_volume = 11
|
||||
|
||||
# Enable this option to exclude a particular device from the speaker
|
||||
# list
|
||||
#exclude = false
|
||||
|
||||
# Name used in the speaker list, overrides name from the device
|
||||
#nickname = "My speaker name"
|
||||
# }
|
||||
|
||||
# Spotify settings (only have effect if Spotify enabled - see README/INSTALL)
|
||||
spotify {
|
||||
# Set preferred bitrate for music streaming
|
||||
# 0: No preference (default), 1: 96kbps, 2: 160kbps, 3: 320kbps
|
||||
#bitrate = 0
|
||||
|
||||
# Your Spotify playlists will by default be put in a "Spotify" playlist
|
||||
# folder. If you would rather have them together with your other
|
||||
# playlists you can set this option to true.
|
||||
#base_playlist_disable = false
|
||||
|
||||
# Spotify playlists usually have many artist, and if you dont want
|
||||
# every artist to be listed when artist browsing in Remote, you can set
|
||||
# the artist_override flag to true. This will use the compilation_artist
|
||||
# as album artist for Spotify items.
|
||||
#artist_override = false
|
||||
|
||||
# Similar to the different artists in Spotify playlists, the playlist
|
||||
# items belong to different albums, and if you do not want every album
|
||||
# to be listed when browsing in Remote, you can set the album_override
|
||||
# flag to true. This will use the playlist name as album name for
|
||||
# Spotify items. Notice that if an item is in more than one playlist,
|
||||
# it will only appear in one album when browsing (in which album is
|
||||
# random).
|
||||
#album_override = false
|
||||
}
|
||||
|
||||
# RCP/Roku Soundbridge output settings
|
||||
# (make sure you get the capitalization of the device name right)
|
||||
#rcp "My SoundBridge device" {
|
||||
# Enable this option to exclude a particular device from the speaker
|
||||
# list
|
||||
#exclude = false
|
||||
|
||||
# A Roku/SoundBridge can power up in 2 modes: (default) reconnect to the
|
||||
# previously used library (ie OwnTone) or in a 'cleared library' mode.
|
||||
# The Roku power up behaviour is affected by how OwnTone disconnects
|
||||
# from the Roku device.
|
||||
#
|
||||
# Set to false to maintain default Roku power on behaviour
|
||||
#clear_on_close = false
|
||||
# }
|
||||
|
||||
|
||||
# MPD configuration (only have effect if MPD enabled - see README/INSTALL)
|
||||
mpd {
|
||||
# TCP port to listen on for MPD client requests.
|
||||
# Default port is 6600, set to 0 to disable MPD support.
|
||||
#port = 6600
|
||||
|
||||
# HTTP port to listen for artwork requests (only supported by some MPD
|
||||
# clients and will need additional configuration in the MPD client to
|
||||
# work). Set to 0 to disable serving artwork over http.
|
||||
#http_port = 0
|
||||
}
|
||||
|
||||
# SQLite configuration (allows to modify the operation of the SQLite databases)
|
||||
# Make sure to read the SQLite documentation for the corresponding PRAGMA
|
||||
# statements as changing them from the defaults may increase the possibility of
|
||||
# database corruptions! By default the SQLite default values are used.
|
||||
sqlite {
|
||||
# Cache size in number of db pages for the library database
|
||||
# (SQLite default page size is 1024 bytes and cache size is 2000 pages)
|
||||
#pragma_cache_size_library = 2000
|
||||
|
||||
# Cache size in number of db pages for the daap cache database
|
||||
# (SQLite default page size is 1024 bytes and cache size is 2000 pages)
|
||||
#pragma_cache_size_cache = 2000
|
||||
|
||||
# Sets the journal mode for the database
|
||||
# DELETE (default), TRUNCATE, PERSIST, MEMORY, WAL, OFF
|
||||
#pragma_journal_mode = DELETE
|
||||
|
||||
# Change the setting of the "synchronous" flag
|
||||
# 0: OFF, 1: NORMAL, 2: FULL (default)
|
||||
#pragma_synchronous = 2
|
||||
|
||||
# Number of bytes set aside for memory-mapped I/O for the library database
|
||||
# (requires sqlite 3.7.17 or later)
|
||||
# 0: disables mmap (default), any other value > 0: number of bytes for mmap
|
||||
#pragma_mmap_size_library = 0
|
||||
|
||||
# Number of bytes set aside for memory-mapped I/O for the cache database
|
||||
# (requires sqlite 3.7.17 or later)
|
||||
# 0: disables mmap (default), any other value > 0: number of bytes for mmap
|
||||
#pragma_mmap_size_cache = 0
|
||||
|
||||
# Should the database be vacuumed on startup? (increases startup time,
|
||||
# but may reduce database size). Default is yes.
|
||||
#vacuum = yes
|
||||
}
|
||||
|
||||
# Streaming audio settings for remote connections (ie stream.mp3)
|
||||
streaming {
|
||||
# Sample rate, typically 44100 or 48000
|
||||
#sample_rate = 44100
|
||||
|
||||
# Set the MP3 streaming bit rate (in kbps), valid options: 64 / 96 / 128 / 192 / 320
|
||||
bit_rate = 320
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
|
||||
- name: reload nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
|
||||
- name: restart owntone container
|
||||
docker_container:
|
||||
name: hass
|
||||
state: started
|
||||
restart: true
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
|
||||
- import_tasks: owntone.yml
|
||||
tags: owntone
|
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
ben marked this conversation as resolved
ben
commented
currently here currently here
ben
commented
owntone works reasonably well (and is building out of ben/builds/owntone), but its not done. not in this pr though. owntone works reasonably well (and is building out of ben/builds/owntone), but its not done. not in this pr though.
|
||||
|
||||
- name: create dir structure
|
||||
file:
|
||||
state: directory
|
||||
path: "{{ owntone_path }}/{{ item.name }}"
|
||||
mode: "{{ item.mode | default('0770') }}"
|
||||
owner: "{{ owntone_user.uid }}"
|
||||
group: "{{ owntone_group.gid }}"
|
||||
tags:
|
||||
- owntone-dirs
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
with_items:
|
||||
- name: ''
|
||||
- name: config
|
||||
- name: log
|
||||
- name: audio
|
||||
- name: audio/local_music
|
||||
- name: audio/playlists
|
||||
- name: audio/compilations
|
||||
- name: audio/pipes
|
||||
#- name: audio/lidarr
|
||||
#- name: audio/audiobooks
|
||||
#- name: audio/podcasts
|
||||
|
||||
- name: create input pipe
|
||||
command:
|
||||
cmd: mkfifo "{{ owntone_path }}/audio/pipes/{{ item }}"
|
||||
creates: "{{ owntone_path }}/audio/pipes/{{ item }}"
|
||||
become_user: "{{ owntone_user.username }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
with_items:
|
||||
- shairport-output.fifo
|
||||
- shairport-metadata.fifo
|
||||
tags:
|
||||
- input.fifo
|
||||
|
||||
- name: install certs
|
||||
copy:
|
||||
src: "/usr/local/etc/letsencrypt/live/{{ item }}"
|
||||
dest: "/usr/local/etc/certs/"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
tags:
|
||||
- letsencrypt-certs
|
||||
notify: reload nginx
|
||||
vars:
|
||||
prediff_cmd: echo
|
||||
with_items:
|
||||
- "{{ domain }}"
|
||||
|
||||
- name: template nginx vhost
|
||||
template:
|
||||
src: 01-owntone.conf.j2
|
||||
dest: /etc/nginx/sites-enabled/01-owntone.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
tags:
|
||||
- nginx
|
||||
- owntone-nginx
|
||||
notify: reload nginx
|
||||
|
||||
- name: template config file
|
||||
template:
|
||||
src: owntone.conf.j2
|
||||
dest: "{{ owntone_path }}/config/owntone.conf"
|
||||
owner: "{{ owntone_user.uid }}"
|
||||
group: "{{ owntone_group.gid }}"
|
||||
mode: 0644
|
||||
notify:
|
||||
- restart owntone container
|
||||
tags:
|
||||
- owntone.conf
|
||||
|
||||
- name: cron file
|
||||
template:
|
||||
src: owntone-cron.j2
|
||||
dest: /etc/cron.d/owntone
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0600
|
||||
tags:
|
||||
- cron
|
||||
- owntone-cron
|
||||
|
||||
- name: install utils for tagging
|
||||
apt:
|
||||
name:
|
||||
|
||||
- id3v2
|
||||
- ffmpeg
|
||||
state: present
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: install yt-dlp
|
||||
pip:
|
||||
name: yt-dlp
|
||||
state: latest
|
||||
tags:
|
||||
- packages
|
||||
- pip-packages
|
||||
- yt-dlp
|
||||
|
||||
- name: fuse allow other
|
||||
lineinfile:
|
||||
path: /etc/fuse.conf
|
||||
line: user_allow_other
|
||||
state: present
|
||||
|
||||
- name: start owntone container
|
||||
docker_container:
|
||||
name: owntone
|
||||
#image: lscr.io/linuxserver/daapd:latest
|
||||
image: git.sudo.is/ben/owntone:latest
|
||||
detach: true
|
||||
pull: true
|
||||
restart_policy: "unless-stopped"
|
||||
state: started
|
||||
container_default_behavior: compatibility
|
||||
networks_cli_compatible: false
|
||||
# user:
|
||||
network_mode: host
|
||||
env:
|
||||
VITE_OWNTONE_URL: "https://{{ owntone_url }}"
|
||||
mounts:
|
||||
- type: bind
|
||||
source: "{{ owntone_path }}/config/owntone.conf"
|
||||
target: "/etc/owntone.conf"
|
||||
- type: bind
|
||||
source: "{{ owntone_path }}/config"
|
||||
target: "/config"
|
||||
- type: bind
|
||||
source: "{{ owntone_path }}/log"
|
||||
target: "/log"
|
||||
- type: bind
|
||||
source: "{{ owntone_path }}/audio"
|
||||
target: "/audio"
|
||||
tags:
|
||||
- owntone-container
|
||||
- docker-containers
|
|
@ -0,0 +1,70 @@
|
|||
server {
|
||||
listen 443 ssl http2;
|
||||
# listen {{ owntone_port_tcp }};
|
||||
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
{% endif -%}
|
||||
|
||||
include /etc/nginx/authelia_internal.conf;
|
||||
include listen-proxy-protocol.conf;
|
||||
include /etc/nginx/sudo-known.conf;
|
||||
|
||||
server_name {{ owntone_url }};
|
||||
|
||||
access_log /var/log/nginx/access_{{ owntone_url }}.log main;
|
||||
error_log /var/log/nginx/error_{{ owntone_url }}.log warn;
|
||||
|
||||
ssl_certificate /usr/local/etc/certs/{{ domain }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ domain }}/privkey.pem;
|
||||
|
||||
# !
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
sub_filter 'owntone.local:3689' '{{ owntone_url }}';
|
||||
sub_filter 'http%3A%2F%2Fowntone.local%3A3689' 'https%3A%2F%2F{{ owntone_url }}';
|
||||
sub_filter 'http://owntone.local:3689' 'https://{{ owntone_url }}';
|
||||
sub_filter_types '*';
|
||||
sub_filter_once off;
|
||||
|
||||
proxy_pass http://127.0.0.1:{{ owntone_port_tcp }}/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
server {
|
||||
# only needs to be accessed by players that are being streamed to
|
||||
# maybe need to remove 'http2'
|
||||
listen {{ ansible_default_ipv4.address }}:{{ owntone_port_ws }} ssl http2;
|
||||
|
||||
server_name {{ owntone_url }};
|
||||
|
||||
access_log /var/log/nginx/access_{{ owntone_url }}_{{ owntone_port_ws }}.log main;
|
||||
error_log /var/log/nginx/error_{{ owntone_url }}_{{ owntone_port_ws }}.log warn;
|
||||
|
||||
ssl_certificate /usr/local/etc/certs/{{ domain }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ domain }}/privkey.pem;
|
||||
|
||||
# !
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:{{ owntone_port_ws }}/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# {{ ansible_managed }}
|
||||
|
||||
# m h dom mon dow
|
||||
|
||||
*/60 * * * * {{ owntone_user.username }} touch {{ owntone_path }}/audio/local_music/trigger.init-rescan
|
||||
|
||||
#
|
|
@ -0,0 +1,472 @@
|
|||
# A quick guide to configuring OwnTone:
|
||||
#
|
||||
# For regular use, the most important setting to configure is "directories",
|
||||
# which should be the location of your media. Whatever user you have set as
|
||||
# "uid" must have read access to this location. If the location is a network
|
||||
# mount, please see the README.
|
||||
#
|
||||
# In all likelihood, that's all you need to do!
|
||||
|
||||
general {
|
||||
# Username
|
||||
# Make sure the user has read access to the library directories you set
|
||||
# below, and full access to the databases, log and local audio
|
||||
uid = "owntone"
|
||||
|
||||
db_path = "/config/dbase_and_logs/songs3.db"
|
||||
|
||||
# Database backup location
|
||||
# Uncomment and specify a full path to enable abilty to use REST endpoint
|
||||
# to initiate backup of songs3.db
|
||||
#db_backup_path = "/var/cache/owntone/songs3.bak"
|
||||
|
||||
# Log file and level
|
||||
# Available levels: fatal, log, warning, info, debug, spam
|
||||
logfile = "/log/owntone.log"
|
||||
loglevel = log
|
||||
|
||||
# Admin password for the web interface
|
||||
# Note that access to the web interface from computers in
|
||||
# "trusted_network" (see below) does not require password
|
||||
admin_password = "{{ owntone_admin_pass }}"
|
||||
|
||||
# Websocket port for the web interface.
|
||||
websocket_port = {{ owntone_port_ws }}
|
||||
|
||||
# Websocket interface to bind listener to (e.g. "eth0"). Default is
|
||||
# disabled, which means listen on all interfaces.
|
||||
websocket_interface = "{{ owntone_interface }}"
|
||||
|
||||
# Sets who is allowed to connect without authorisation. This applies to
|
||||
# client types like Remotes, DAAP clients (iTunes) and to the web
|
||||
# interface. Options are "any", "localhost" or the prefix to one or
|
||||
# more ipv4/6 networks. The default is { "localhost", "192.168", "fd" }
|
||||
{% set s21 = s21_cidr.split(".")[:3] | join(".") -%}
|
||||
trusted_networks = { "localhost", "{{ s21 }}", "fd" }
|
||||
|
||||
# Enable/disable IPv6
|
||||
ipv6 = no
|
||||
|
||||
# Set this if you want the server to bind to a specific IP address. Can
|
||||
# be ipv6 or ipv4. Default (commented out or "::") is to listen on all
|
||||
# IP addresses.
|
||||
#bind_address = "{{ owntone_interface }}"
|
||||
|
||||
# Location of cache database
|
||||
cache_path = "/config/dbase_and_logs/cache.db"
|
||||
|
||||
# DAAP requests that take longer than this threshold (in msec) get their
|
||||
# replies cached for next time. Set to 0 to disable caching.
|
||||
#cache_daap_threshold = 1000
|
||||
|
||||
# When starting playback, autoselect speaker (if none of the previously
|
||||
# selected speakers/outputs are available)
|
||||
#speaker_autoselect = no
|
||||
|
||||
# Most modern systems have a high-resolution clock, but if you are on an
|
||||
# unusual platform and experience audio drop-outs, you can try changing
|
||||
# this option
|
||||
#high_resolution_clock = yes
|
||||
}
|
||||
|
||||
# Library configuration
|
||||
library {
|
||||
# Name of the library as displayed by the clients (%h: hostname). If you
|
||||
# change the name after pairing with Remote you may have to re-pair.
|
||||
name = "{{ owntone_url }}"
|
||||
|
||||
# TCP port to listen on. Default port is 3689 (daap)
|
||||
port = {{ owntone_port_tcp }}
|
||||
|
||||
# Password for the library. Optional.
|
||||
#password = "{{ owntone_library_pass }}"
|
||||
|
||||
# Directories to index
|
||||
directories = { "/audio" }
|
||||
|
||||
# Follow symlinks. Default: true.
|
||||
#follow_symlinks = true
|
||||
|
||||
# Directories containing podcasts
|
||||
# For each directory that is indexed the path is matched against these
|
||||
# names. If there is a match all items in the directory are marked as
|
||||
# podcasts. Eg. if you index /music, and your podcasts are in
|
||||
# /music/Podcasts, you can set this to "/Podcasts".
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
podcasts = { "/podcasts" }
|
||||
|
||||
# Directories containing audiobooks
|
||||
# For each directory that is indexed the path is matched against these
|
||||
# names. If there is a match all items in the directory are marked as
|
||||
# audiobooks.
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
audiobooks = { "/audiobooks" }
|
||||
|
||||
# Directories containing compilations (eg soundtracks)
|
||||
# For each directory that is indexed the path is matched against these
|
||||
# names. If there is a match all items in the directory are marked as
|
||||
# compilations.
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
compilations = { "/compilations" }
|
||||
|
||||
# Compilations usually have many artists, and sometimes no album artist.
|
||||
# If you dont want every artist to be listed in artist views, you can
|
||||
# set a single name which will be used for all compilation tracks
|
||||
# without an album artist, and for all tracks in the compilation
|
||||
# directories.
|
||||
# (changing this setting only takes effect after rescan, see the README)
|
||||
compilation_artist = "Various Artists"
|
||||
|
||||
# If your album and artist lists are cluttered, you can choose to hide
|
||||
# albums and artists with only one track. The tracks will still be
|
||||
# visible in other lists, e.g. songs and playlists. This setting
|
||||
# currently only works in some remotes.
|
||||
#hide_singles = false
|
||||
|
||||
# Internet streams in your playlists will by default be shown in the
|
||||
# "Radio" library, like iTunes does. However, some clients (like
|
||||
# TunesRemote+) wont show the "Radio" library. If you would also like
|
||||
# to have them shown like normal playlists, you can enable this option.
|
||||
radio_playlists = false
|
||||
|
||||
# These are the default playlists. If you want them to have other names,
|
||||
# you can set it here.
|
||||
#name_library = "Library"
|
||||
#name_music = "Music"
|
||||
#name_movies = "Movies"
|
||||
#name_tvshows = "TV Shows"
|
||||
#name_podcasts = "Podcasts"
|
||||
#name_audiobooks = "Audiobooks"
|
||||
#name_radio = "Radio"
|
||||
|
||||
# Artwork file names (without file type extension)
|
||||
# OwnTone will look for jpg and png files with these base names
|
||||
artwork_basenames = { "artwork", "cover", "Folder" }
|
||||
|
||||
# Enable searching for artwork corresponding to each individual media
|
||||
# file instead of only looking for album artwork. This is disabled by
|
||||
# default to reduce cache size.
|
||||
artwork_individual = true
|
||||
|
||||
# File types the scanner should ignore
|
||||
# Non-audio files will never be added to the database, but here you
|
||||
# can prevent the scanner from even probing them. This might improve
|
||||
# scan time. By default .db, .ini, .db-journal, .pdf and .metadata are
|
||||
# ignored.
|
||||
#filetypes_ignore = { ".db", ".ini", ".db-journal", ".pdf", ".metadata" }
|
||||
|
||||
# File paths the scanner should ignore
|
||||
# If you want to exclude files on a more advanced basis you can enter
|
||||
# one or more POSIX regular expressions, and any file with a matching
|
||||
# path will be ignored.
|
||||
#filepath_ignore = { "myregex" }
|
||||
|
||||
# Disable startup file scanning
|
||||
# When OwnTone starts it will do an initial file scan of your
|
||||
# library (and then watch it for changes). If you are sure your library
|
||||
# never changes while OwnTone is not running, you can disable the
|
||||
# initial file scan and save some system ressources. Disabling this scan
|
||||
# may lead to OwnTones database coming out of sync with the
|
||||
# library. If that happens read the instructions in the README on how
|
||||
# to trigger a rescan.
|
||||
#filescan_disable = false
|
||||
|
||||
# Should metadata from m3u playlists, e.g. artist and title in EXTINF,
|
||||
# override the metadata we get from radio streams?
|
||||
#m3u_overrides = false
|
||||
|
||||
# Should iTunes metadata override ours?
|
||||
itunes_overrides = {{ owntone_itunes_metadata_override | default(false) }}
|
||||
|
||||
# Should we import the content of iTunes smart playlists?
|
||||
#itunes_smartpl = false
|
||||
|
||||
# Decoding options for DAAP clients
|
||||
# Since iTunes has native support for mpeg, mp4a, mp4v, alac and wav,
|
||||
# such files will be sent as they are. Any other formats will be decoded
|
||||
# to raw wav. If OwnTone detects a non-iTunes DAAP client, it is
|
||||
# assumed to only support mpeg and wav, other formats will be decoded.
|
||||
# Here you can change when to decode. Note that these settings have no
|
||||
# effect on AirPlay.
|
||||
# Formats: mp4a, mp4v, mpeg, alac, flac, mpc, ogg, wma, wmal, wmav, aif, wav
|
||||
# Formats that should never be decoded
|
||||
#no_decode = { "format", "format" }
|
||||
# Formats that should always be decoded
|
||||
#force_decode = { "format", "format" }
|
||||
|
||||
# Watch named pipes in the library for data and autostart playback when
|
||||
# there is data to be read. To exclude specific pipes from watching,
|
||||
# consider using the above _ignore options.
|
||||
pipe_autostart = true
|
||||
|
||||
# Enable automatic rating updates
|
||||
# If enabled, rating is automatically updated after a song has either been
|
||||
# played or skipped (only skipping to the next song is taken into account).
|
||||
# The calculation is taken from the beets plugin "mpdstats" (see
|
||||
# https://beets.readthedocs.io/en/latest/plugins/mpdstats.html).
|
||||
# It consist of calculating a stable rating based only on the play- and
|
||||
# skipcount and a rolling rating based on the current rating and the action
|
||||
# (played or skipped). Both results are combined with a mix-factor of 0.75:
|
||||
# new rating = 0.75 * stable rating + 0.25 * rolling rating)
|
||||
#rating_updates = false
|
||||
|
||||
# Allows creating, deleting and modifying m3u playlists in the library directories.
|
||||
# Only supported by the player web interface and some mpd clients
|
||||
# Defaults to being disabled.
|
||||
allow_modifying_stored_playlists = true
|
||||
|
||||
# A directory in one of the library directories that will be used as the default
|
||||
# playlist directory. OwnTone creates new playlists in this directory if only
|
||||
# a playlist name is provided (requires "allow_modify_stored_playlists" set to true).
|
||||
default_playlist_directory = "/audio/playlists"
|
||||
|
||||
# By default OwnTone will - like iTunes - clear the playqueue if
|
||||
# playback stops. Setting clear_queue_on_stop_disable to true will keep
|
||||
# the playlist like MPD does. Note that some dacp clients do not show
|
||||
# the playqueue if playback is stopped.
|
||||
clear_queue_on_stop_disable = true
|
||||
}
|
||||
|
||||
# Local audio output
|
||||
audio {
|
||||
# Name - used in the speaker list in Remote
|
||||
nickname = "Computer"
|
||||
|
||||
# Type of the output (alsa, pulseaudio, dummy or disabled)
|
||||
type = "disabled"
|
||||
|
||||
# For pulseaudio output, an optional server hostname or IP can be
|
||||
# specified (e.g. "localhost"). If not set, connection is made via local
|
||||
# socket.
|
||||
#server = ""
|
||||
|
||||
# Audio PCM device name for local audio output - ALSA only
|
||||
#card = "default"
|
||||
|
||||
# Mixer channel to use for volume control - ALSA only
|
||||
# If not set, PCM will be used if available, otherwise Master.
|
||||
#mixer = ""
|
||||
|
||||
# Mixer device to use for volume control - ALSA only
|
||||
# If not set, the value for "card" will be used.
|
||||
#mixer_device = ""
|
||||
|
||||
# Enable or disable audio resampling to keep local audio in sync with
|
||||
# e.g. Airplay. This feature relies on accurate ALSA measurements of
|
||||
# delay, and some devices dont provide that. If that is the case you
|
||||
# are better off disabling the feature.
|
||||
#sync_disable = false
|
||||
|
||||
# Here you can adjust when local audio is started relative to other
|
||||
# speakers, e.g. Airplay. Negative values correspond to moving local
|
||||
# audio ahead, positive correspond to delaying it. The unit is
|
||||
# milliseconds. The offset must be between -1000 and 1000 (+/- 1 sec).
|
||||
#offset_ms = 0
|
||||
|
||||
# To calculate what and if resampling is required, local audio delay is
|
||||
# measured each second. After a period the collected measurements are
|
||||
# used to estimate drift and latency, which determines if corrections
|
||||
# are required. This setting sets the length of that period in seconds.
|
||||
#adjust_period_seconds = 100
|
||||
}
|
||||
|
||||
# ALSA device settings
|
||||
# If you have multiple ALSA devices you can configure them individually via
|
||||
# sections like the below. Make sure to set the "card name" correctly. See the
|
||||
# README about ALSA for details. Note that these settings will override the ALSA
|
||||
# settings in the "audio" section above.
|
||||
#alsa "card name" {
|
||||
# Name used in the speaker list. If not set, the card name will be used.
|
||||
#nickname = "Computer"
|
||||
|
||||
# Mixer channel to use for volume control
|
||||
# If not set, PCM will be used if available, otherwise Master
|
||||
#mixer = ""
|
||||
|
||||
# Mixer device to use for volume control
|
||||
# If not set, the card name will be used
|
||||
#mixer_device = ""
|
||||
# }
|
||||
|
||||
# Pipe output
|
||||
# Allows OwnTone to output audio data to a named pipe
|
||||
fifo {
|
||||
nickname = "fifo"
|
||||
path = "/audio/output.fifo"
|
||||
}
|
||||
|
||||
# AirPlay settings common to all devices
|
||||
#airplay_shared {
|
||||
# UDP ports used when airplay devices make connections back to
|
||||
# OwnTone (choosing specific ports may be helpful when running
|
||||
# OwnTone behind a firewall)
|
||||
# control_port = 0
|
||||
# timing_port = 0
|
||||
# }
|
||||
|
||||
# AirPlay per device settings
|
||||
# (make sure you get the capitalization of the device name right)
|
||||
#airplay "My AirPlay device" {
|
||||
# OwnTone's volume goes to 11! If that's more than you can handle
|
||||
# you can set a lower value here
|
||||
#max_volume = 11
|
||||
|
||||
# Enable this option to exclude a particular AirPlay device from the
|
||||
# speaker list
|
||||
#exclude = false
|
||||
|
||||
# Enable this option to keep a particular AirPlay device in the speaker
|
||||
# list and thus ignore mdns notifications about it no longer being
|
||||
# present. The speaker will remain until restart of OwnTone.
|
||||
#permanent = false
|
||||
|
||||
# Some devices spuriously disconnect during playback, and based on the
|
||||
# device type OwnTone may attempt to reconnect. Setting this option
|
||||
# overrides this so reconnecting is either always enabled or disabled.
|
||||
#reconnect = false
|
||||
|
||||
# AirPlay password
|
||||
#password = "s1kr3t"
|
||||
|
||||
# Disable AirPlay 1 (RAOP)
|
||||
#raop_disable = false
|
||||
|
||||
# Name used in the speaker list, overrides name from the device
|
||||
#nickname = "My speaker name"
|
||||
# }
|
||||
|
||||
{% for item in owntone_airplay -%}
|
||||
{% if item.exclude|default(false) -%}
|
||||
# Excluded AirPlay device: {{ item.name }}
|
||||
{% endif %}
|
||||
airplay "{{ item.name }}" {
|
||||
{% if 'nickname' in item -%}
|
||||
nickname = "{{ item.nickname }}"
|
||||
{% endif -%}
|
||||
{% if 'password' in item -%}
|
||||
password = "{{ item.password }}"
|
||||
{% endif -%}
|
||||
{% if 'max_volume' in item -%}
|
||||
max_volume = {{ item.max_volume }}
|
||||
{% endif -%}
|
||||
exclude = {{ item.exclude|default(false) | lower }}
|
||||
permanent = {{ item.permanent|default(false) | lower }}
|
||||
reconnect = {{ item.reconnect|default(false) | lower }}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
# Chromecast settings
|
||||
# (make sure you get the capitalization of the device name right)
|
||||
#chromecast "My Chromecast device" {
|
||||
# OwnTone's volume goes to 11! If that's more than you can handle
|
||||
# you can set a lower value here
|
||||
#max_volume = 11
|
||||
|
||||
# Enable this option to exclude a particular device from the speaker
|
||||
# list
|
||||
#exclude = false
|
||||
|
||||
# Name used in the speaker list, overrides name from the device
|
||||
#nickname = "My speaker name"
|
||||
# }
|
||||
|
||||
# Spotify settings (only have effect if Spotify enabled - see README/INSTALL)
|
||||
spotify {
|
||||
# Set preferred bitrate for music streaming
|
||||
# 0: No preference (default), 1: 96kbps, 2: 160kbps, 3: 320kbps
|
||||
bitrate = 3
|
||||
|
||||
# Your Spotify playlists will by default be put in a "Spotify" playlist
|
||||
# folder. If you would rather have them together with your other
|
||||
# playlists you can set this option to true.
|
||||
base_playlist_disable = true
|
||||
|
||||
# Spotify playlists usually have many artist, and if you dont want
|
||||
# every artist to be listed when artist browsing in Remote, you can set
|
||||
# the artist_override flag to true. This will use the compilation_artist
|
||||
# as album artist for Spotify items.
|
||||
artist_override = true
|
||||
|
||||
# Similar to the different artists in Spotify playlists, the playlist
|
||||
# items belong to different albums, and if you do not want every album
|
||||
# to be listed when browsing in Remote, you can set the album_override
|
||||
# flag to true. This will use the playlist name as album name for
|
||||
# Spotify items. Notice that if an item is in more than one playlist,
|
||||
# it will only appear in one album when browsing (in which album is
|
||||
# random).
|
||||
album_override = true
|
||||
}
|
||||
|
||||
# RCP/Roku Soundbridge output settings
|
||||
# (make sure you get the capitalization of the device name right)
|
||||
#rcp "My SoundBridge device" {
|
||||
# Enable this option to exclude a particular device from the speaker
|
||||
# list
|
||||
#exclude = false
|
||||
|
||||
# A Roku/SoundBridge can power up in 2 modes: (default) reconnect to the
|
||||
# previously used library (ie OwnTone) or in a 'cleared library' mode.
|
||||
# The Roku power up behaviour is affected by how OwnTone disconnects
|
||||
# from the Roku device.
|
||||
#
|
||||
# Set to false to maintain default Roku power on behaviour
|
||||
#clear_on_close = false
|
||||
# }
|
||||
|
||||
|
||||
# MPD configuration (only have effect if MPD enabled - see README/INSTALL)
|
||||
mpd {
|
||||
# TCP port to listen on for MPD client requests.
|
||||
# Default port is 6600, set to 0 to disable MPD support.
|
||||
port = {{ owntone_port_mpd|default('6600') }}
|
||||
|
||||
# HTTP port to listen for artwork requests (only supported by some MPD
|
||||
# clients and will need additional configuration in the MPD client to
|
||||
# work). Set to 0 to disable serving artwork over http.
|
||||
#http_port = 0
|
||||
}
|
||||
|
||||
# SQLite configuration (allows to modify the operation of the SQLite databases)
|
||||
# Make sure to read the SQLite documentation for the corresponding PRAGMA
|
||||
# statements as changing them from the defaults may increase the possibility of
|
||||
# database corruptions! By default the SQLite default values are used.
|
||||
sqlite {
|
||||
# Cache size in number of db pages for the library database
|
||||
# (SQLite default page size is 1024 bytes and cache size is 2000 pages)
|
||||
#pragma_cache_size_library = 2000
|
||||
|
||||
# Cache size in number of db pages for the daap cache database
|
||||
# (SQLite default page size is 1024 bytes and cache size is 2000 pages)
|
||||
#pragma_cache_size_cache = 2000
|
||||
|
||||
# Sets the journal mode for the database
|
||||
# DELETE (default), TRUNCATE, PERSIST, MEMORY, WAL, OFF
|
||||
#pragma_journal_mode = DELETE
|
||||
|
||||
# Change the setting of the "synchronous" flag
|
||||
# 0: OFF, 1: NORMAL, 2: FULL (default)
|
||||
#pragma_synchronous = 2
|
||||
|
||||
# Number of bytes set aside for memory-mapped I/O for the library database
|
||||
# (requires sqlite 3.7.17 or later)
|
||||
# 0: disables mmap (default), any other value > 0: number of bytes for mmap
|
||||
#pragma_mmap_size_library = 0
|
||||
|
||||
# Number of bytes set aside for memory-mapped I/O for the cache database
|
||||
# (requires sqlite 3.7.17 or later)
|
||||
# 0: disables mmap (default), any other value > 0: number of bytes for mmap
|
||||
#pragma_mmap_size_cache = 0
|
||||
|
||||
# Should the database be vacuumed on startup? (increases startup time,
|
||||
# but may reduce database size). Default is yes.
|
||||
#vacuum = yes
|
||||
}
|
||||
|
||||
# Streaming audio settings for remote connections (ie stream.mp3)
|
||||
streaming {
|
||||
# Sample rate, typically 44100 or 48000
|
||||
#sample_rate = 44100
|
||||
|
||||
# Set the MP3 streaming bit rate (in kbps), valid options: 64 / 96 / 128 / 192 / 320
|
||||
bit_rate = 320
|
||||
}
|
|
@ -1,7 +1 @@
|
|||
---
|
||||
|
||||
dependencies:
|
||||
- mariadb
|
||||
- zflux
|
||||
- sudoisbot
|
||||
- hass
|
||||
|
|
|
@ -56,6 +56,191 @@
|
|||
when: dht_builder|default(False)
|
||||
tags: dht
|
||||
|
||||
# https://bluedot.readthedocs.io/en/latest/pairpipi.html#using-the-command-line
|
||||
#
|
||||
# $ sudo bluetoothctl
|
||||
# [bluetooth]# discoverable on
|
||||
# Changing discoverable on succeeded
|
||||
# [bluetooth]# pairable on
|
||||
# Changing pairable on succeeded
|
||||
# [bluetooth]# agent on
|
||||
# Agent is already registered
|
||||
# [bluetooth]# default-agent
|
||||
# Default agent request successful
|
||||
# [bluetooth]# scan on
|
||||
# [bluetooth]# pair EA:26:7D:4A:ED:E4
|
||||
# 0a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char000d/desc000f
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char000d/desc0010
|
||||
# 00002902-0000-1000-8000-00805f9b34fb
|
||||
# Client Characteristic Configuration
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0011
|
||||
# e6807d23-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0011/desc0013
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0014
|
||||
# e6807d24-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0014/desc0016
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0014/desc0017
|
||||
# 00002902-0000-1000-8000-00805f9b34fb
|
||||
# Client Characteristic Configuration
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0018
|
||||
# e6807d25-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0018/desc001a
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char001b
|
||||
# e6807d26-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char001b/desc001d
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char001e
|
||||
# e6807d27-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char001e/desc0020
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0021
|
||||
# e6807e20-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0021/desc0023
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0021/desc0024
|
||||
# 00002902-0000-1000-8000-00805f9b34fb
|
||||
# Client Characteristic Configuration
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0025
|
||||
# e6807e21-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0025/desc0027
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0028
|
||||
# e6807e24-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0028/desc002a
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char0028/desc002b
|
||||
# 00002902-0000-1000-8000-00805f9b34fb
|
||||
# Client Characteristic Configuration
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char002c
|
||||
# e6807e25-b90a-11e5-a837-0800200c9a66
|
||||
# Vendor specific
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0009/char002c/desc002e
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Primary Service
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f
|
||||
# 0000181a-0000-1000-8000-00805f9b34fb
|
||||
# Environmental Sensing
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f/char0030
|
||||
# 00002a6e-0000-1000-8000-00805f9b34fb
|
||||
# Temperature
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f/char0030/desc0032
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f/char0030/desc0033
|
||||
# 00002902-0000-1000-8000-00805f9b34fb
|
||||
# Client Characteristic Configuration
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f/char0034
|
||||
# 00002a6f-0000-1000-8000-00805f9b34fb
|
||||
# Humidity
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f/char0034/desc0036
|
||||
# 00002901-0000-1000-8000-00805f9b34fb
|
||||
# Characteristic User Description
|
||||
# [NEW] Descriptor
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service002f/char0034/desc0037
|
||||
# 00002902-0000-1000-8000-00805f9b34fb
|
||||
# Client Characteristic Configuration
|
||||
# [NEW] Primary Service
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038
|
||||
# 0000180a-0000-1000-8000-00805f9b34fb
|
||||
# Device Information
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038/char0039
|
||||
# 00002a29-0000-1000-8000-00805f9b34fb
|
||||
# Manufacturer Name String
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038/char003b
|
||||
# 00002a24-0000-1000-8000-00805f9b34fb
|
||||
# Model Number String
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038/char003d
|
||||
# 00002a25-0000-1000-8000-00805f9b34fb
|
||||
# Serial Number String
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038/char003f
|
||||
# 00002a27-0000-1000-8000-00805f9b34fb
|
||||
# Hardware Revision String
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038/char0041
|
||||
# 00002a26-0000-1000-8000-00805f9b34fb
|
||||
# Firmware Revision String
|
||||
# [NEW] Characteristic
|
||||
# /org/bluez/hci0/dev_EA_26_7D_4A_ED_E4/service0038/char0043
|
||||
# 00002a28-0000-1000-8000-00805f9b34fb
|
||||
# Software Revision String
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 UUIDs: 00001800-0000-1000-8000-00805f9b34fb
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 UUIDs: 00001801-0000-1000-8000-00805f9b34fb
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 UUIDs: 0000180a-0000-1000-8000-00805f9b34fb
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 UUIDs: 0000181a-0000-1000-8000-00805f9b34fb
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 UUIDs: e6807d20-b90a-11e5-a837-0800200c9a66
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 ServicesResolved: yes
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 Appearance: 0x03c0
|
||||
# [CHG] Device EA:26:7D:4A:ED:E4 Paired: yes
|
||||
# Pairing successful
|
||||
# [Beddit 2564]# quit
|
||||
- name: set up bluetooth
|
||||
apt:
|
||||
name:
|
||||
- pi-bluetooth
|
||||
- bluez
|
||||
- libgirepository1.0-dev
|
||||
# - bluez-utils
|
||||
# - bluetooth
|
||||
# - blueman
|
||||
when: bluetooth_enabled | default(false)
|
||||
tags: bluetooth
|
||||
|
||||
- name: install fpm with gem
|
||||
gem:
|
||||
name: fpm
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
|
||||
dependencies:
|
||||
- mariadb
|
||||
- zflux
|
|
@ -14,7 +14,7 @@
|
|||
vars:
|
||||
prediff_cmd: echo
|
||||
with_items:
|
||||
- "{{ unifi_url }}"
|
||||
- "{{ domain }}"
|
||||
|
||||
- name: template nginx vhost
|
||||
template:
|
||||
|
@ -61,10 +61,13 @@
|
|||
# v6.5.55
|
||||
# v6.0.45
|
||||
# v5.14.23
|
||||
#
|
||||
# updated: v5.14.23 -> stable-5 -> stable-6 -> latest (v7)
|
||||
- name: start docker container
|
||||
docker_container:
|
||||
name: "unifi"
|
||||
image: "jacobalberty/unifi:v5.14.23"
|
||||
#image: "jacobalberty/unifi:v5.14.23"
|
||||
image: jacobalberty/unifi:latest
|
||||
ben
commented
v5 was better v5 was better
|
||||
auto_remove: false
|
||||
detach: true
|
||||
restart_policy: "unless-stopped"
|
||||
|
@ -86,8 +89,9 @@
|
|||
- "8080:8080/tcp" # Device/ controller comm.
|
||||
- "127.0.0.1:8443:8443/tcp" # Controller GUI/API as seen in a web browser
|
||||
- "10001:10001/udp" # AP discovery
|
||||
dns_servers:
|
||||
- "{{ ansible_docker0.ipv4.address }}"
|
||||
tags:
|
||||
- unifi-container
|
||||
- docker-containers
|
||||
|
||||
|
||||
- name: wait for controller to be responsive
|
||||
|
|
|
@ -15,6 +15,15 @@ server {
|
|||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /inform {
|
||||
proxy_pass http://localhost:8080;
|
||||
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
}
|
||||
|
||||
|
||||
location / {
|
||||
proxy_pass https://localhost:8443/;
|
||||
|
||||
|
@ -32,8 +41,8 @@ server {
|
|||
|
||||
ssl_session_timeout 5m;
|
||||
|
||||
ssl_certificate /usr/local/etc/certs/{{ unifi_url }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ unifi_url }}/privkey.pem;
|
||||
ssl_certificate /usr/local/etc/certs/{{ domain }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/{{ domain }}/privkey.pem;
|
||||
|
||||
add_header Referrer-Policy "no-referrer" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
|
|
|
@ -1,8 +1,26 @@
|
|||
server {
|
||||
server_name {%- for d in server_names %} {{ d }}{% endfor %};
|
||||
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
{% endif -%}
|
||||
listen 443 ssl http2;
|
||||
|
||||
include listen-proxy-protocol.conf;
|
||||
|
||||
ssl_certificate /usr/local/etc/certs/www.{{ domain }}/fullchain.pem;
|
||||
ssl_certificate_key /usr/local/etc/certs/www.{{ domain }}/privkey.pem;
|
||||
|
||||
location / {
|
||||
return 301 https://www.$http_host$request_uri;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/access_{{ domain }}.log main;
|
||||
error_log /var/log/nginx/error_{{ domain }}.log warn;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name {%- for d in server_names %} www.{{ d }} {{ d }}{% endfor %};
|
||||
server_name {%- for d in server_names %} www.{{ d }}{% endfor %};
|
||||
|
||||
{% if inventory_hostname in wg_clients -%}
|
||||
listen {{ wg_clients[inventory_hostname].ip }}:443 ssl http2;
|
||||
|
|
Loading…
Reference in New Issue
.