[ansible][attitude-adjuster]

pull/28/head
Alpha Chen 5 years ago
parent 1b3dbcc09a
commit 5a0cd902df

@ -0,0 +1,44 @@
# vim: ft=dockerfile
FROM armhf/alpine
# https://wiki.alpinelinux.org/wiki/Ddclient
RUN apk update && apk upgrade && \
apk add \
curl \
make \
perl \
# perl-utils \
# perl-test-taint \
# perl-netaddr-ip \
# perl-net-ip \
# perl-yaml \
# perl-log-log4perl \
perl-io-socket-ssl
RUN cpan install Test::Requires && cpan Data::Validate::IP
RUN cd tmp && \
curl --location https://github.com/ddclient/ddclient/archive/v3.9.0.tar.gz > ddclient-3.9.0.tar.gz && \
tar xvz < ddclient-3.9.0.tar.gz && \
cp ddclient-3.9.0/ddclient /usr/sbin && \
mkdir /etc/ddclient && \
mkdir -p /var/cache/ddclient
# RUN apk del --purge \
# build-dependencies && \
# rm -rf /tmp/*
# RUN apt-get update -y && \
# apt-get install -yq curl libdata-validate-ip-perl libio-socket-ip-perl libio-socket-ssl-perl libjson-any-perl perl && \
# cd tmp && \
# curl --location https://github.com/ddclient/ddclient/archive/v3.9.0.tar.gz > ddclient-3.9.0.tar.gz && \
# tar xvz < ddclient-3.9.0.tar.gz && \
# rm ddclient-3.9.0.tar.gz && \
# cp ddclient-3.9.0/ddclient /usr/sbin && \
# rm -rf ddclient-3.9.0 && \
# mkdir /etc/ddclient && \
# mkdir -p /var/cache/ddclient
VOLUME /etc/ddclient
ENTRYPOINT [ "ddclient", "-daemon", "300", "-foreground", "-verbose" ]

@ -12,9 +12,6 @@
- `ansible-playbook --extra-vars "ansible_user=pi" --ask-pass attitude-adjuster/bootstrap.yml` - `ansible-playbook --extra-vars "ansible_user=pi" --ask-pass attitude-adjuster/bootstrap.yml`
- `ansible-playbook attitude-adjuster/main.yml` - `ansible-playbook attitude-adjuster/main.yml`
1. Install Pi-hole
- `curl -sSL https://install.pi-hole.net | bash`
## Optional ## Optional
1. Use `raspi-config` to set up the WiFi 1. Use `raspi-config` to set up the WiFi

@ -1,17 +0,0 @@
{
"bridge": {
"name": "Homebridge",
"username": "67:9E:AC:02:F4:51",
"port": 59377,
"pin": "617-05-928"
},
"platforms": [
{
"platform": "SmartThings",
"name": "SmartThings",
"app_url": "https://graph-na04-useast2.api.smartthings.com:443/api/smartapps/installations/",
"access_token": "d03f2c6e-36e4-4069-8b7a-a2fcb30c1d68",
"app_id": "d0549bc7-23cc-4355-b261-6bfe9e5e48b6"
}
]
}

@ -1,6 +0,0 @@
use=web
ssl=yes
protocol=googledomains
login={{ ddclient_login }}
password={{ ddclient_password }}
{{ ddclient_host }}

@ -0,0 +1,66 @@
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
become: yes
tasks:
- name: configure ddclient
copy:
content: |
use=web
ssl=yes
protocol=googledomains
login={{ home.ddclient.login }}
password={{ home.ddclient.password }}
{{ home.host }}
use=web
ssl=yes
protocol=googledomains
login={{ home_assistant.ddclient.login }}
password={{ home_assistant.ddclient.password }}
{{ home_assistant.host }}
use=web
ssl=yes
protocol=googledomains
login={{ homebridge.ddclient.login }}
password={{ homebridge.ddclient.password }}
{{ homebridge.host }}
use=web
ssl=yes
protocol=googledomains
login={{ pihole.ddclient.login }}
password={{ pihole.ddclient.password }}
{{ pihole.host }}
use=web
ssl=yes
protocol=googledomains
login={{ traefik.ddclient.login }}
password={{ traefik.ddclient.password }}
{{ traefik.host }}
dest: /etc/ddclient/ddclient.conf
mode: 0600
notify: restart ddclient
- name: build docker image
docker_image:
build:
path: .
dockerfile: Dockerfile.ddclient
pull: yes
name: kejadlen/ddclient
repository: kejadlen/ddclient
push: yes
source: build
handlers:
- name: restart ddclient
docker_container:
name: ddclient
restart: yes
ignore_errors: yes

@ -0,0 +1,142 @@
# https://docs.docker.com/install/linux/docker-ce/debian/#install-using-the-repository
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
become: yes
tasks:
- name: install dependencies
package:
name: "{{ item }}"
state: present
with_items:
- apt-transport-https
- ca-certificates
- gnupg2
- name: add docker apt key
apt_key:
url: https://download.docker.com/linux/debian/gpg
# https://github.com/moby/moby/issues/31405#issuecomment-501494874
- name: add docker apt repository
apt_repository:
repo: deb [arch=armhf] https://download.docker.com/linux/raspbian stretch stable
state: present
filename: docker
- name: install docker
package:
name: "{{ item }}"
state: present
with_items:
- docker-ce
- docker-ce-cli
- containerd.io
- name: add myself to docker group
user:
name: alpha
groups: docker
append: yes
- name: install dependencies
package:
name: "{{ item }}"
state: present
with_items:
- docker-compose
- python-docker
- name: docker compose
docker_compose:
project_name: attitude-adjuster
definition:
version: '2'
services:
ddclient:
image: kejadlen/ddclient
container_name: ddclient
environment:
TZ: America/Los_Angeles
volumes:
- /etc/ddclient:/etc/ddclient
networks:
- bridge
restart: always
home_assistant:
container_name: home-assistant
image: homeassistant/raspberrypi3-homeassistant
ports:
- 5353:5353/udp
- 51827:51827/tcp
environment:
TZ: America/Los_Angeles
volumes:
- /etc/homeassistant:/config
networks:
- bridge
restart: always
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:{{ home_assistant.host }}
- traefik.basic.port=8123
- traefik.basic.protocol=http
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- 53:53/tcp
- 53:53/udp
environment:
ServerIP: 192.168.1.101
TZ: America/Los_Angeles
VIRTUAL_HOST: "{{ pihole.host }}"
WEBPASSWORD: "{{ pihole.password }}"
volumes:
- /etc/pihole:/etc/pihole
- /etc/dnsmasq.d:/etc/dnsmasq.d
dns:
- 127.0.0.1
- 1.1.1.1
cap_add:
- NET_ADMIN
networks:
- bridge
restart: always
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:{{ pihole.host }}
- traefik.basic.port=80
- traefik.basic.protocol=http
traefik:
container_name: traefik
image: traefik
command: --api --docker
ports:
- 80:80
- 8080:8080
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.toml:/traefik.toml
- /opt/traefik/acme.json:/acme.json
networks:
- bridge
restart: always
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:{{ traefik.host }}
- traefik.frontend.auth.basic.users=alpha:{{ traefik.password | password_hash('md5') | replace('$', '$$') }}
- traefik.basic.port=8080
- traefik.basic.protocol=http
networks:
bridge:
state: present
pull: yes

@ -1,22 +0,0 @@
$HTTP["host"] == "{{ fqdn }}" {
# Ensure the Pi-hole Block Page knows that this is not a blocked domain
setenv.add-environment = ("fqdn" => "true")
# Enable the SSL engine with a LE cert, only for this specific host
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/letsencrypt/live/{{ fqdn }}/combined.pem"
ssl.ca-file = "/etc/letsencrypt/live/{{ fqdn }}/fullchain.pem"
ssl.honor-cipher-order = "enable"
ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
ssl.use-sslv2 = "disable"
ssl.use-sslv3 = "disable"
}
# Redirect HTTP to HTTPS
$HTTP["scheme"] == "http" {
$HTTP["host"] =~ ".*" {
url.redirect = (".*" => "https://%0$0")
}
}
}

@ -0,0 +1,39 @@
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
become: yes
tasks:
- name: configure home assistant
copy:
content: |
default_config:
http:
base_url: https://{{ home_assistant.host }}
tts: # Text to speech
- platform: google_translate
homekit:
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
dest: /etc/homeassistant/configuration.yaml
notify: restart home assistant
- name: allow access to homekit
ufw:
rule: allow
proto: "{{ item.proto }}"
port: "{{ item.port }}"
state: reloaded
with_items:
- { proto: tcp, port: 51827 }
- { proto: udp, port: 5353 }
handlers:
- name: restart home assistant
docker_container:
name: home-assistant
restart: yes
ignore_errors: yes

@ -0,0 +1,16 @@
{
"bridge": {
"name": "Homebridge",
"username": "{{ homebridge.username }}",
"port": 51826,
"pin": "{{ homebridge.pin }}"
},
"platforms": [
{
"platform": "SmartThings Cloud",
"name": "SmartThings Cloud",
"port": 3000,
"publicKey": "{{ homebridge.smartthings_public_key | b64encode }}"
}
]
}

@ -0,0 +1,7 @@
# Defaults / Configuration options for homebridge
# The following settings tells homebridge where to find the config.json file and where to persist the data (i.e. pairing and others)
HOMEBRIDGE_OPTS=-U /var/lib/homebridge
# If you uncomment the following line, homebridge will log more
# You can display this via systemd's journalctl: journalctl -f -u homebridge
# DEBUG=*

@ -0,0 +1,17 @@
[Unit]
Description=Node.js HomeKit Server
After=syslog.target network-online.target
[Service]
Type=simple
User=homebridge
EnvironmentFile=/etc/default/homebridge
# Adapt this to your specific setup (could be /usr/bin/homebridge)
# See comments below for more information
ExecStart=/usr/local/bin/homebridge $HOMEBRIDGE_OPTS
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target

@ -0,0 +1,83 @@
# https://github.com/nfarina/homebridge/wiki/Running-HomeBridge-on-a-Raspberry-Pi#install-avahi-and-other-dependencies
- hosts: pi
vars_files:
- vars.yml.private
become: yes
tasks:
- name: update apt to get a modern version of node
block:
- apt_key:
url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key
- copy:
src: nodesource.list
dest: /etc/apt/sources.list.d/nodesource.list
- name: update apt
apt:
update_cache: yes
- name: install dependencies
package:
name: "{{ item }}"
state: present
with_items:
- libavahi-compat-libdnssd-dev
- nodejs
- name: install homebridge
npm:
name: "{{ item }}"
global: yes
with_items:
- homebridge
- homebridge-smartthings-cloud
- name: copy systemd config
copy:
src: homebridge/{{ item.key }}
dest: "{{ item.value }}"
with_dict:
homebridge: /etc/default
homebridge.service: /etc/systemd/system
notify:
- reload systemd daemon
- enable and restart homebridge service
- name: create homebridge user
user:
name: homebridge
password: !
- name: create homebridge dir
file:
path: /var/lib/homebridge
state: directory
owner: homebridge
- name: copy homebridge config
template:
src: homebridge/config.json
dest: /var/lib/homebridge
owner: homebridge
notify: enable and restart homebridge service
- name: allow access to homebridge
ufw:
rule: allow
proto: tcp
port: 51826
state: reloaded
handlers:
- name: reload systemd daemon
systemd:
daemon_reload: yes
- name: enable and restart homebridge service
service:
name: homebridge
enabled: yes
state: restarted

@ -0,0 +1,2 @@
deb https://deb.nodesource.com/node_12.x stretch main
deb-src https://deb.nodesource.com/node_12.x stretch main

@ -1,2 +0,0 @@
[sshd]
enabled = true

@ -0,0 +1,69 @@
# https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface/5771
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
become: yes
tasks:
- name: install certbot
package:
name: certbot
state: present
- name: obtain ssl certificates
command: >-
certbot certonly
--webroot --webroot-path /var/www/html
-d {{ item.fqdn }}
-m alpha+lets.encrypt@kejadlen.dev
--agree-tos
--non-interactive
args:
creates: /etc/letsencrypt/live/{{ item.fqdn }}
with_items:
- "{{ home }}"
- "{{ home_assistant }}"
- "{{ homebridge }}"
- "{{ pihole }}"
- name: create combined pemfile
shell: >-
cat /etc/letsencrypt/live/{{ item.fqdn }}/privkey.pem
/etc/letsencrypt/live/{{ item.fqdn }}/cert.pem >
/etc/letsencrypt/live/{{ item.fqdn }}/combined.pem
args:
creates: /etc/letsencrypt/live/{{ item.fqdn }}/combined.pem
with_items:
- "{{ home }}"
- "{{ home_assistant }}"
- "{{ homebridge }}"
- "{{ pihole }}"
- name: let lighttpd read the pemfile
file:
path: /etc/letsencrypt/live/{{ item.fqdn }}
state: directory
recurse: yes
owner: www-data
with_items:
- "{{ home }}"
- "{{ home_assistant }}"
- "{{ homebridge }}"
- "{{ pihole }}"
- name: enable mod_proxy
command: lighttpd-enable-mod proxy
ignore_errors: yes
- name: update lighttpd configuration
template:
src: external.conf.private
dest: /etc/lighttpd/external.conf
notify: restart lighttpd
handlers:
- name: restart lighttpd
service:
name: lighttpd
state: restarted

@ -1,4 +1,5 @@
- hosts: attitude-adjuster - hosts: attitude-adjuster
become: yes
tasks: tasks:
- name: install dependencies - name: install dependencies
@ -8,148 +9,9 @@
with_items: with_items:
- git - git
- vim - vim
become: yes
# Security - import_playbook: security.yml
#
# https://www.raspberrypi.org/documentation/configuration/security.md
- hosts: attitude-adjuster - import_playbook: ddclient.yml
tasks: - import_playbook: home-assistant.yml
- import_playbook: docker.yml
- name: disable ssh password logins
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^(#\s*)?{{ item }} '
line: "{{ item }} no"
notify: reload ssh
with_items:
- ChallengeResponseAuthentication
- PasswordAuthentication
- UsePAM
become: yes
- name: disable pi user
user:
name: pi
password: !
become: yes
- name: install ufw and fail2ban
package:
name: "{{ item }}"
state: present
become: yes
with_items:
- ufw
- fail2ban
- name: allow access to dns, http, and https
ufw:
rule: allow
name: "{{ item }}"
with_items:
- DNS
- WWW Full
become: yes
- name: allow access to dhcp
ufw:
rule: allow
proto: udp
port: 67
become: yes
- name: limit ssh access
ufw:
rule: limit
name: OpenSSH
become: yes
- name: enable ufw
ufw:
state: enabled
become: yes
- name: create jail.local
copy:
src: jail.local
dest: /etc/fail2ban/
become: yes
notify: reload fail2ban
handlers:
- name: reload ssh
service:
name: ssh
state: reloaded
- name: reload fail2ban
service:
name: fail2ban
state: reloaded
- import_playbook: pihole.yml
# ddclient
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
tasks:
- name: install ddclient
package:
name: ddclient
state: present
become: yes
- name: configure ddclient
template:
src: ddclient.conf
dest: /etc/ddclient.conf
mode: go-r
become: yes
notify: restart ddclient
- name: enable ddclient
service:
name: ddclient
enabled: yes
become: yes
handlers:
- name: restart ddclient
service:
name: ddclient
state: restarted
become: yes
# Homebridge
- hosts: attitude-adjuster
tasks:
- name: install npm
package:
name: npm
state: present
become: yes
- name: install homebridge
npm:
name: "{{ item }}"
global: yes
with_items:
- homebridge
- homebridge-smartthings-tonesto7
become: yes
- name: create ~/.homebridge
file:
path: ~/.homebridge
state: directory
- name: copy homebridge config
copy:
src: config.json
dest: ~/.homebridge/config.json

@ -0,0 +1,72 @@
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
become: yes
tasks:
- name: install dependencies
package:
name: "{{ item }}"
state: present
with_items:
- certbot
- nginx
- python3-certbot-nginx
- name: allow for long domain names
lineinfile:
path: /etc/nginx/nginx.conf
regexp: '^(\s*)# server_names_hash_bucket_size 64;$'
line: '\1server_names_hash_bucket_size 64;'
backrefs: yes
- name: obtain ssl certs
command: >-
certbot certonly --nginx
-d {{ item }}
-m alpha+lets.encrypt@kejadlen.dev
--agree-tos
--non-interactive
args:
creates: /etc/letsencrypt/live/{{ item }}
with_items:
- "{{ home.fqdn }}"
- "{{ home_assistant.fqdn }}"
- "{{ pihole.fqdn }}"
- name: configure nginx
copy:
content: |
server {
server_name {{ fqdn }};
# Redirect non-https traffic to https
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
location / {
proxy_pass http://{{ proxy }}/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For nginx;
}
listen 80;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/{{ fqdn }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ fqdn }}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
dest: /etc/nginx/conf.d/{{ fqdn }}.conf
vars:
fqdn: "{{ item.fqdn }}"
proxy: "{{ item.nginx.proxy }}"
with_items:
- "{{ home }}"
- "{{ home_assistant }}"
- "{{ pihole }}"

@ -1,64 +0,0 @@
# https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface/5771
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
tasks:
- name: install certbot
package:
name: certbot
state: present
become: yes
- name: clone the pi-hole repo
git:
repo: https://github.com/pi-hole/pi-hole.git
dest: ~/src/pi-hole
depth: 1
- name: obtain ssl certificates
command: >-
certbot certonly
--webroot --webroot-path /var/www/html
-d {{ fqdn }}
-m alpha+lets.encrypt@kejadlen.dev
--agree-tos
--non-interactive
args:
creates: /etc/letsencrypt/live/{{ fqdn }}
become: yes
- name: create combined pemfile
shell: >-
cat /etc/letsencrypt/live/{{ fqdn }}/privkey.pem
/etc/letsencrypt/live/{{ fqdn }}/cert.pem >
/etc/letsencrypt/live/{{ fqdn }}/combined.pem
args:
creates: /etc/letsencrypt/live/{{ fqdn }}/combined.pem
become: yes
- name: let lighttpd read the pemfile
file:
path: /etc/letsencrypt/live/{{ fqdn }}
state: directory
recurse: yes
owner: www-data
become: yes
- name: update lighttpd configuration
template:
src: external.conf
dest: /etc/lighttpd/external.conf
become: yes
notify: restart lighttpd
handlers:
- name: restart lighttpd
service:
name: lighttpd
state: restarted
become: yes

@ -0,0 +1,66 @@
# https://www.raspberrypi.org/documentation/configuration/security.md
- hosts: attitude-adjuster
become: yes
tasks:
- name: disable ssh password logins
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^(#\s*)?{{ item }} '
line: "{{ item }} no"
notify: reload ssh
with_items:
- ChallengeResponseAuthentication
- PasswordAuthentication
- UsePAM
- name: disable pi user
user:
name: pi
password: !
- name: install ufw and fail2ban
package:
name: "{{ item }}"
state: present
with_items:
- ufw
- fail2ban
- name: allow access to dns, http, and https
ufw:
rule: allow
name: "{{ item }}"
with_items:
- DNS
- WWW Full
- name: limit ssh access
ufw:
rule: limit
name: OpenSSH
- name: enable ufw
ufw:
state: enabled
- name: create jail.local
copy:
content: |
[sshd]
enabled = true
dest: /etc/fail2ban/jail.local
notify: reload fail2ban
handlers:
- name: reload ssh
service:
name: ssh
state: reloaded
- name: reload fail2ban
service:
name: fail2ban
state: reloaded

@ -0,0 +1,49 @@
# https://docs.traefik.io/user-guide/docker-and-lets-encrypt/
- hosts: attitude-adjuster
vars_files:
- vars.yml.private
become: yes
tasks:
- name: traefik.toml
copy:
content: |
debug = false
insecureSkipVerify = true
logLevel = "ERROR"
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[retry]
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "{{ traefik.domain }}"
watch = true
exposedByDefault = false
network = "attitudeadjuster_bridge"
[acme]
email = "{{ traefik.email }}"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
dest: /opt/traefik/traefik.toml
- name: acme.json
file:
name: /opt/traefik/acme.json
mode: 0600
state: touch
Loading…
Cancel
Save