From 6424e702203f7e937888e27d5e6137374e8223ff Mon Sep 17 00:00:00 2001 From: funkypenguin Date: Sun, 16 Jul 2017 00:06:02 +1200 Subject: [PATCH] Initial commit --- .gitexclude | 1 + .gitlab-ci.yml | 38 +++ docs/README.md | 9 + docs/advanced/about.md | 3 + docs/advanced/docker.md | 289 ++++++++++++++++++ docs/advanced/gitlab.md | 0 docs/advanced/home-assistant/basic.md | 0 docs/advanced/home-assistant/grafana.md | 0 docs/advanced/home-assistant/limitless-led.md | 0 docs/advanced/home-assistant/xiaomi.md | 0 docs/advanced/huginn.md | 0 docs/advanced/keepalived.md | 226 ++++++++++++++ docs/advanced/nextcloud.md | 0 docs/advanced/owntracks.md | 0 docs/advanced/shaarli.md | 0 docs/advanced/tiny-tiny-rss.md | 113 +++++++ docs/advanced/traefik.md | 1 + docs/advanced/wallabag.md | 0 docs/beginner/2-factor-auth.md | 5 + docs/beginner/beginner.md | 5 + docs/images/site-logo.png | Bin 0 -> 13796 bytes docs/index.md | 3 + docs/intermediate/plex.md | 0 docs/intermediate/welcome.md | 0 docs/whoami.md | 38 +++ mkdocs-material | 1 + mkdocs.yml | 110 +++++++ 27 files changed, 842 insertions(+) create mode 100644 .gitexclude create mode 100644 .gitlab-ci.yml create mode 100644 docs/README.md create mode 100644 docs/advanced/about.md create mode 100644 docs/advanced/docker.md create mode 100644 docs/advanced/gitlab.md create mode 100644 docs/advanced/home-assistant/basic.md create mode 100644 docs/advanced/home-assistant/grafana.md create mode 100644 docs/advanced/home-assistant/limitless-led.md create mode 100644 docs/advanced/home-assistant/xiaomi.md create mode 100644 docs/advanced/huginn.md create mode 100644 docs/advanced/keepalived.md create mode 100644 docs/advanced/nextcloud.md create mode 100644 docs/advanced/owntracks.md create mode 100644 docs/advanced/shaarli.md create mode 100644 docs/advanced/tiny-tiny-rss.md create mode 100644 docs/advanced/traefik.md create mode 100644 docs/advanced/wallabag.md create mode 100644 docs/beginner/2-factor-auth.md create mode 100644 docs/beginner/beginner.md create mode 100644 docs/images/site-logo.png create mode 100644 docs/index.md create mode 100644 docs/intermediate/plex.md create mode 100644 docs/intermediate/welcome.md create mode 100644 docs/whoami.md create mode 160000 mkdocs-material create mode 100644 mkdocs.yml diff --git a/.gitexclude b/.gitexclude new file mode 100644 index 0000000..4c8f017 --- /dev/null +++ b/.gitexclude @@ -0,0 +1 @@ +mkdocs-material diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..6a81f21 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,38 @@ +stages: + - build + - test + - deploy + +image: python:alpine + +#before_script: +# - pip install mkdocs +# # add your custom theme (https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes) if not inside a theme_dir +# # - pip install mkdocs-material + +build site: + stage: build + script: + - pip install mkdocs + - mkdocs build + - mv site public + artifacts: + expire_in: 1 day + paths: + - public + only: + - master + +test site: + stage: test + script: + - echo fake result as a placeholder + +deploy site: + image: garland/docker-s3cmd + stage: deploy + environment: production + script: + - export LC_ALL=C.UTF-8 + - export LANG=C.UTF-8 + - s3cmd --no-mime-magic --access_key=$ACCESS_KEY --secret_key=$SECRET_KEY --acl-public --delete-removed --delete-after --no-ssl --host=$S3HOST --host-bucket='$S3HOSTBUCKET' sync public s3://geeks-cookbook diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..38370ed --- /dev/null +++ b/docs/README.md @@ -0,0 +1,9 @@ +# How to read this book + +## Structure + +1. "Recipies" are sorted by degree of geekiness required to complete them. Relatively straightforward projects are "beginner", more complex projects are "intermediate", and the really fun ones are "advanced". +2. Each recipe contains enough detail in a single page to take a project to completion. +3. When there are optional add-ons/integrations possible to a project (i.e., the addition of "smart LED bulbs" to Home Assistant), this will be reflected as a sub-page of the main project. + +## Requirements diff --git a/docs/advanced/about.md b/docs/advanced/about.md new file mode 100644 index 0000000..9512b5c --- /dev/null +++ b/docs/advanced/about.md @@ -0,0 +1,3 @@ +# About + +This is the advanced section. It's for geeks who are proficient working in the command line, understanding networking, and who enjoy a challenge! diff --git a/docs/advanced/docker.md b/docs/advanced/docker.md new file mode 100644 index 0000000..59ab05e --- /dev/null +++ b/docs/advanced/docker.md @@ -0,0 +1,289 @@ +# Docker Swarm + +For truly highly-available services with Docker containers, we need an orchestration system. Docker Swarm (as defined at 1.13) is the simplest way to achieve redundancy, such that a single docker host could be turned off, and none of our services will be interrupted. + +## Ingredients + +* 2 x CentOS Atomic hosts (bare-metal or VMs). A reasonable minimum would be: +* 1 x vCPU +* 1GB repo_name +* 10GB HDD +* Hosts must be within the same subnet, and connected on a low-latency link (i.e., no WAN links) + +## Preparation + +### Install CentOS Atomic hosts + +I decided to use CentOS Atomic rather than full-blown CentOS7, for the following reasons: + +1. I want less responsibility for maintaining the system, including ensuring regular software updates and reboots. Atomic's idempotent nature means the OS is largely real-only, and updates/rollbacks are "atomic" (haha) procedures, which can be easily rolled back if required. +2. For someone used to administrating servers individually, Atomic is a PITA. You have to employ [tricky](http://blog.oddbit.com/2015/03/10/booting-cloud-images-with-libvirt/) [tricks](https://spinningmatt.wordpress.com/2014/01/08/a-recipe-for-starting-cloud-images-with-virt-install/) to get it to install in a non-cloud environment. It's not designed for tweaking or customizing beyond what cloud-config is capable of. For my purposes, this is good, because it forces me to change my thinking - to consider every daemon as a container, and every config as code, to be checked in and version-controlled. Atomic forces this thinking on you. +3. I want the design to be as "portable" as possible. While I run it on VPSs now, I may want to migrate it to a "cloud" provider in the future, and I'll want the most portable, reproducible design. + +``` +systemctl disable docker --now +systemctl enable docker-latest --now +sed -i '/DOCKERBINARY/s/^#//g' /etc/sysconfig/docker + +atomic host upgrade +``` + +## Setup Swarm + +Setting up swarm really is straightforward. You need to ensure that the nodes can talk to each other. + +In my case, my nodes are on a shared subnet with other VPSs, so I wanted to ensure that they were not exposed more than necessary. If I were doing this within a cloud infrastructure which provided separation of instances, I wouldn't need to be so specific: + +``` +# Permit Docker Swarm from other nodes/managers +-A INPUT -s 202.170.164.47 -p tcp --dport 2376 -j ACCEPT +-A INPUT -s 202.170.164.47 -p tcp --dport 2377 -j ACCEPT +-A INPUT -s 202.170.164.47 -p tcp --dport 7946 -j ACCEPT +-A INPUT -s 202.170.164.47 -p udp --dport 7946 -j ACCEPT +-A INPUT -s 202.170.164.47 -p udp --dport 4789 -j ACCEPT +``` + +```` + +Now, to launch my swarm: + +```docker swarm init``` + +Yeah, that was it. Now I have a 1-node swarm. + +``` +[root@ds1 ~]# docker swarm init +Swarm initialized: current node (b54vls3wf8xztwfz79nlkivt8) is now a manager. + +To add a worker to this swarm, run the following command: + + docker swarm join \ + --token SWMTKN-1-2orjbzjzjvm1bbo736xxmxzwaf4rffxwi0tu3zopal4xk4mja0-bsud7xnvhv4cicwi7l6c9s6l0 \ + 202.170.164.47:2377 + +To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. + +[root@ds1 ~]# +``` + +Right, so I a 1-node swarm: + +``` +[root@ds1 ~]# docker node ls +ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS +b54vls3wf8xztwfz79nlkivt8 * ds1.funkypenguin.co.nz Ready Active Leader +[root@ds1 ~]# +``` + +If I followed the "join" command above, I'd end up with a worker node. In my case, I actually want another manager, so that I have full HA, so I followed the instruction and ran ```docker swarm join-token manager``` instead.: + +``` +[root@ds1 ~]# docker swarm join-token manager +To add a manager to this swarm, run the following command: + + docker swarm join \ + --token SWMTKN-1-2orjbzjzjvm1bbo736xxmxzwaf4rffxwi0tu3zopal4xk4mja0-cfm24bq2zvfkcwujwlp5zqxta \ + 202.170.164.47:2377 + +[root@ds1 ~]# +``` + +I run the command: + +```` +[root@ds2 davidy]# docker node ls +ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS +b54vls3wf8xztwfz79nlkivt8 ds1.funkypenguin.co.nz Ready Active Leader +xmw49jt5a1j87a6ihul76gbgy * ds2.funkypenguin.co.nz Ready Active Reachable +[root@ds2 davidy]# +```` + + +Swarm initialized: current node (25fw5695wkqxm8mtwqnktwykr) is now a manager. + +To add a worker to this swarm, run the following command: + + docker swarm join \ + --token SWMTKN-1-54al7nosz9jzj41a8d6kjhz2yez7zxgbdw362f821j81svqofo-e9rw3a8pi53jhlghuyscm52bn \ + 202.170.161.87:2377 + +To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. + +[root@ds1 ~]# docker swarm join-token manager +To add a manager to this swarm, run the following command: + + docker swarm join \ + --token SWMTKN-1-54al7nosz9jzj41a8d6kjhz2yez7zxgbdw362f821j81svqofo-1sjspmbyxqvica5gdb5p4n7mh \ + 202.170.161.87:2377 + +[root@ds1 ~]# +```` + +Added the second host to the swarm, then promoted it. + +```` +[root@ds2 ~]# docker swarm join \ +> --token SWMTKN-1-54al7nosz9jzj41a8d6kjhz2yez7zxgbdw362f821j81svqofo-1sjspmbyxqvica5gdb5p4n7mh \ +> 202.170.161.87:2377 +This node joined a swarm as a manager. +[root@ds2 ~]# +```` + +lvcreate -l 100%FREE -n gfs /dev/atomicos +mkfs.xfs -i size=512 /dev/atomicos/gfs +mkdir -p /srv/glusterfs +echo '//dev/atomicos/gfs /srv/glusterfs/ xfs defaults 1 2' >> /etc/fstab +mount -a && mount + +```` +docker run \ + -h glusterfs-server \ + -v /etc/glusterfs:/etc/glusterfs:z \ + -v /var/lib/glusterd:/var/lib/glusterd:z \ + -v /var/log/glusterfs:/var/log/glusterfs:z \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + -v /var/srv/glusterfs:/var/srv/glusterfs \ + -d --privileged=true --net=host \ + --restart=always \ + --name="glusterfs-server" \ + gluster/gluster-centos +```` + + + +now exec into the container, and "probe" its peer, to establish the gluster cluster + +``` +[root@ds1 ~]# docker exec -it glusterfs-server bash +[root@glusterfs-server /]# +``` + +``` +[root@glusterfs-server /]# gluster peer probe ds2 +peer probe: success. +[root@glusterfs-server /]# gluster peer status +Number of Peers: 1 + +Hostname: ds2 +Uuid: 9fbc1985-4e8d-4380-9c10-3c699ebcb10c +State: Peer in Cluster (Connected) +[root@glusterfs-server /]# exit +exit +[root@ds1 ~]# +``` + +Run ```gluster volume create gv0 replica 2 ds1:/var/srv/glusterfs/gv0 ds2:/var/srv/glusterfs/gv0``` as below to create the cluster: +``` +[root@glusterfs-server /]# gluster volume create gv0 replica 2 ds1:/var/srv/glusterfs/gv0 ds2:/var/srv/glusterfs/gv0 +volume create: gv0: success: please start the volume to access data +[root@glusterfs-server /]# +``` + +Run ```gluster volume start gv0``` to start it: + +``` +[root@glusterfs-server /]# gluster volume start gv0 +volume start: gv0: success +[root@glusterfs-server /]# +``` + +Exit out of the container: +``` +[root@glusterfs-server /]# exit +exit +[root@ds1 ~]# +``` + +Create your mountpoint on the host, and mount the gluster volume: + +``` +mkdir /srv/data +HOSTNAME=`hostname -s` +echo "$HOSTNAME:/gv0 /srv/data glusterfs defaults,_netdev 0 0" >> /etc/fstab +mount -a && mount +``` + +mount -t glusterfs ds1:/gv0 /srv/data/ + + +on secondary +mkdir /srv/data +mount -t glusterfs ds2:/gv0 /srv/data/ + + +/dev/VG-vda3/gv0 /srv/glusterfs xfs defaults 1 2 +ds2:/gv0 /srv/data glusterfs defaults,_netdev 0 0 + + +install docker-compose: + +```` +curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose +chmod +x /usr/local/bin/docker-compose +```` + + +### Atomic hosts + + + + +docker stack deploy traefik -c traefik.yml + +need to deal with selinux though :(, had to set to permissive to get it working + +this seemed to work: + +https://github.com/dpw/selinux-dockersock + +```` +mkdir ~/dockersock +cd ~/dockersock +curl -O https://github.com/dpw/selinux-dockersock/raw/master/dockersock.te +curl -O https://github.com/dpw/selinux-dockersock/raw/master/Makefile +make && semodule -i dockersock.pp +```` + +however... glusterfs still doesn't support selinux, so until that's sorted, you have te disable selinux anyway with "setenforce 0", in order for _ANY_ containers to write to the glusterfs fuse partition. + +need to add something to rc.local to make glustetr fs mount + +__ maybe __this works: +setsebool -P virt_sandbox_use_fusefs on + +https://docs.openshift.org/latest/install_config/persistent_storage/persistent_storage_glusterfs.html#selinux + + +Stupid cloud-init makes the system slow to boot: + +[root@ds1 ~]# systemctl mask cloud-final.service +Created symlink from /etc/systemd/system/cloud-final.service to /dev/null. +[root@ds1 ~]# systemctl mask cloud-config.service +Created symlink from /etc/systemd/system/cloud-config.service to /dev/null. +[root@ds1 ~]# + + + + +added {"experimental":true} to /etc/docker-latest/daemon.json to enable logs of deployed services + +I.e changed this: + +``` +Usage: docker stack COMMAND +{ + "log-driver": "journald", + "signature-verification": false +} +``` + +To this: + +``` +{ + "log-driver": "journald", + "signature-verification": false, + "experimental": true +}``` + +!!! note the comma after "false" above diff --git a/docs/advanced/gitlab.md b/docs/advanced/gitlab.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/home-assistant/basic.md b/docs/advanced/home-assistant/basic.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/home-assistant/grafana.md b/docs/advanced/home-assistant/grafana.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/home-assistant/limitless-led.md b/docs/advanced/home-assistant/limitless-led.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/home-assistant/xiaomi.md b/docs/advanced/home-assistant/xiaomi.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/huginn.md b/docs/advanced/huginn.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/keepalived.md b/docs/advanced/keepalived.md new file mode 100644 index 0000000..d70425e --- /dev/null +++ b/docs/advanced/keepalived.md @@ -0,0 +1,226 @@ +# keepalived + + +## On both hosts + +The design for redundant Docker hosts requires a virtual IP for high availability. To enable this, we install the "keepalived" daemon on both hosts: + +````yum -y install keepalived```` + +Below, we'll configure a very basic primary/secondary configuration. + +!!! note + Note that if you have a firewall on your hosts, you need to permit the VRRP traffic, as follows (note that for both INPUT and OUTPUT rule, the destination is 224.0.0.18, a multicast address) + + ```` + # permit keepalived in + -A INPUT -i eth0 -d 224.0.0.18 -j ACCEPT + + # permit keepalived out + -A OUTPUT -o eth0 -d 224.0.0.18 -j ACCEPT + ```` + +## On the primary + +Configure keepalived (note the priority) +```` +VIP= +PASS= +cat << EOF > /etc/keepalived/keepalived.conf +vrrp_instance DS { + state MASTER + interface eth0 + virtual_router_id 42 + priority 200 + advert_int 1 + authentication { + auth_type PASS + auth_pass $PASS + } + virtual_ipaddress { + $VIP + } +} +EOF +systemctl enable keepalived +systemctl start keepalived +```` + +## On the secondary + +Repeat the same on the secondary (all that changes is the priority - the priority of the secondary must be lower than that of the primary): + +```` +VIP= +PASS= +cat << EOF > /etc/keepalived/keepalived.conf +vrrp_instance DS { + state MASTER + interface eth0 + virtual_router_id 42 + priority 100 + advert_int 1 + authentication { + auth_type PASS + auth_pass $PASS + } + virtual_ipaddress { + $VIP + } +} +EOF +systemctl enable keepalived +systemctl start keepalived +```` + +Check the state of keepalived on both nodes by running +````systemctl status keepalived```` + + +## Confirm HA function + +You should now be able to ping your HA IP address, and you can test the HA function by running ````tail -f /var/log/messages | grep Keepalived```` the secondary node, and turning keepalived off/on on the primary node, by running ````systemctl stop keepalived && sleep 10s && systemctl start keepalived````. + +## Docker + +On both hosts, run: + +sudo yum install -y yum-utils device-mapper-persistent-data lvm2 +sudo yum-config-manager \ + --add-repo \ + https://download.docker.com/linux/centos/docker-ce.repo + +sudo yum makecache fast +sudo yum install docker-ce + +sudo systemctl start docker + sudo docker run hello-world + + + + +## Setup Swarm + +```` +[[root@ds1 ~]# docker swarm init +Swarm initialized: current node (25fw5695wkqxm8mtwqnktwykr) is now a manager. + +To add a worker to this swarm, run the following command: + + docker swarm join \ + --token SWMTKN-1-54al7nosz9jzj41a8d6kjhz2yez7zxgbdw362f821j81svqofo-e9rw3a8pi53jhlghuyscm52bn \ + 202.170.161.87:2377 + +To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. + +[root@ds1 ~]# docker swarm join-token manager +To add a manager to this swarm, run the following command: + + docker swarm join \ + --token SWMTKN-1-54al7nosz9jzj41a8d6kjhz2yez7zxgbdw362f821j81svqofo-1sjspmbyxqvica5gdb5p4n7mh \ + 202.170.161.87:2377 + +[root@ds1 ~]# +```` + +Added the second host to the swarm, then promoted it. + +```` +[root@ds2 ~]# docker swarm join \ +> --token SWMTKN-1-54al7nosz9jzj41a8d6kjhz2yez7zxgbdw362f821j81svqofo-1sjspmbyxqvica5gdb5p4n7mh \ +> 202.170.161.87:2377 +This node joined a swarm as a manager. +[root@ds2 ~]# +```` + +mkfs.xfs -i size=512 /dev/vdb1 +mkdir -p /srv/glusterfs +echo '/dev/vdb1 /srv/glusterfs/ xfs defaults 1 2' >> /etc/fstab +mount -a && mount + +```` +docker run \ + -h glusterfs-server \ + -v /etc/glusterfs:/etc/glusterfs:z \ + -v /var/lib/glusterd:/var/lib/glusterd:z \ + -v /var/log/glusterfs:/var/log/glusterfs:z \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + -v /var/srv/glusterfs:/var/srv/glusterfs \ + -d --privileged=true --net=host \ + --restart=always \ + --name="glusterfs-server" \ + gluster/gluster-centos +```` + + + +gluster volume create gv0 replica 2 server1:/data/brick1/gv0 server2:/data/brick1/gv0 + gluster volume start gv0 + +[root@ds2 ~]# gluster peer probe ds1 + + +gluster volume create gv0 replica 2 ds1:/srv/glusterfs/gv0 ds2:/srv/glusterfs/gv0 +gluster volume start gv0 + +[root@ds1 ~]# mkdir /srv/data +[root@ds1 ~]# mount -t glusterfs ds1:/gv0 /srv/data/ + + +on secondary +mkdir /srv/data +mount -t glusterfs ds2:/gv0 /srv/data/ + + +/dev/VG-vda3/gv0 /srv/glusterfs xfs defaults 1 2 +ds2:/gv0 /srv/data glusterfs defaults,_netdev 0 0 + + +install docker-compose: + +```` +curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose +chmod +x /usr/local/bin/docker-compose +```` + + +### Atomic hosts + +systemctl disable docker --now +systemctl enable docker-latest --now +sed -i '/DOCKERBINARY/s/^#//g' /etc/sysconfig/docker + +atomic host upgrade + + +docker stack deploy traefik -c traefik.yml + +need to deal with selinux though :(, had to set to permissive to get it working + +this seemed to work: + +https://github.com/dpw/selinux-dockersock + + +need to add something to rc.local to make glustetr fs mount + + + +added {"experimental":true} to /etc/docker/dameon.json to enable logs of deployed services + + + + + + +echo "modprobe ip_vs" >> /etc/rc.local + +for primary / secondary keepalived + + +docker run -d --name keepalived --restart=always \ + --cap-add=NET_ADMIN --net=host \ + -e KEEPALIVED_UNICAST_PEERS="#PYTHON2BASH:['202.170.164.47', '202.170.164.48']" \ + -e KEEPALIVED_VIRTUAL_IPS=202.170.164.49 \ + -e KEEPALIVED_PRIORITY=100 \ + osixia/keepalived:1.3.5 diff --git a/docs/advanced/nextcloud.md b/docs/advanced/nextcloud.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/owntracks.md b/docs/advanced/owntracks.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/shaarli.md b/docs/advanced/shaarli.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/advanced/tiny-tiny-rss.md b/docs/advanced/tiny-tiny-rss.md new file mode 100644 index 0000000..0cbd6b9 --- /dev/null +++ b/docs/advanced/tiny-tiny-rss.md @@ -0,0 +1,113 @@ + +# Introduction + +[Tiny Tiny RSS][ttrss] is a self-hosted, AJAX-based RSS reader, which rose to popularity as a replacement for Google Reader. It supports advanced features, such as: + +* Plugins and themeing in a drop-in fashion +* Filtering (discard all articles with title matching "trump") +* Sharing articles via a unique public URL/feed + +Tiny Tiny RSS requires a database and a webserver - this recipe provides both using docker, exposed to the world via LetsEncrypt. + +# Ingredients + +**Required** + +1. Webserver (nginx container) +2. Database (postgresql container) +3. TTRSS (ttrss container) +3. Nginx reverse proxy with LetsEncrypt + + +**Optional** + +1. Email server (if you want to email articles from TTRSS) + +# Preparation + +**Setup filesystem location** + +I setup a directory for the ttrss data, at /data/ttrss. + +I created docker-compose.yml, as follows: + +```` +rproxy: + image: nginx:1.13-alpine + ports: + - "34804:80" + environment: + - DOMAIN_NAME=ttrss.funkypenguin.co.nz + - VIRTUAL_HOST=ttrss.funkypenguin.co.nz + - LETSENCRYPT_HOST=ttrss.funkypenguin.co.nz + - LETSENCRYPT_EMAIL=davidy@funkypenguin.co.nz + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + volumes_from: + - ttrss + links: + - ttrss:ttrss + +ttrss: + image: tkaefer/docker-ttrss + restart: always + links: + - postgres:database + environment: + - DB_USER=ttrss + - DB_PASS=uVL53xfmJxW + - SELF_URL_PATH=https://ttrss.funkypenguin.co.nz + volumes: + - ./plugins.local:/var/www/plugins.local + - ./themes.local:/var/www/themes.local + - ./reader:/var/www/reader + +postgres: + image: postgres:latest + volumes: + - /srv/ssd-data/ttrss/db:/var/lib/postgresql/data + restart: always + environment: + - POSTGRES_USER=ttrss + - POSTGRES_PASSWORD=uVL53xfmJxW + +gmailsmtp: + image: softinnov/gmailsmtp + restart: always + environment: + - user=davidy@funkypenguin.co.nz + - pass=eqknehqflfbufzbh + - DOMAIN_NAME=gmailsmtp.funkypenguin.co.nz +```` + +Run ````docker-compose up```` in the same directory, and watch the output. PostgreSQL container will create the "ttrss" database, and ttrss will start using it. + + +# Login to UI + +Log into https://\. Default user is "admin" and password is "password" + +# Optional - Enable af_psql_trgm plugin for similar post detection + +One of the native plugins enables the detection of "similar" articles. This requires the pg_trgm extension enabled in your database. + +From the working directory, use ````docker exec```` to get a shell within your postgres container, and run "postgres" as the postgres user: +```` +[root@kvm nginx]# docker exec -it ttrss_postgres_1 /bin/sh +# su - postgres +No directory, logging in with HOME=/ +$ psql +psql (9.6.3) +Type "help" for help. +```` + +Add the trgm extension to your ttrss database: +```` +postgres=# \c ttrss +You are now connected to database "ttrss" as user "postgres". +ttrss=# CREATE EXTENSION pg_trgm; +CREATE EXTENSION +ttrss=# \q +```` + +[ttrss]:https://tt-rss.org/ diff --git a/docs/advanced/traefik.md b/docs/advanced/traefik.md new file mode 100644 index 0000000..9ffc590 --- /dev/null +++ b/docs/advanced/traefik.md @@ -0,0 +1 @@ +docker stack deploy traefik -c docker-compose.yml diff --git a/docs/advanced/wallabag.md b/docs/advanced/wallabag.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/beginner/2-factor-auth.md b/docs/beginner/2-factor-auth.md new file mode 100644 index 0000000..50c7880 --- /dev/null +++ b/docs/beginner/2-factor-auth.md @@ -0,0 +1,5 @@ +# 2-Factor authentication + +## What is it? + +## Why do we need it? diff --git a/docs/beginner/beginner.md b/docs/beginner/beginner.md new file mode 100644 index 0000000..1c3d694 --- /dev/null +++ b/docs/beginner/beginner.md @@ -0,0 +1,5 @@ +# Beginner + +The recipies in the beginner section meet the following criteria: + +1. They do not require command-line skills diff --git a/docs/images/site-logo.png b/docs/images/site-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7edb223fda65cece2fcd7b938db756b62ec8c76f GIT binary patch literal 13796 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 z%0A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 P0RIehOtfEXIo|$X1sNbQ literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..cccf287 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,3 @@ +# Index + +This book is a collection of recipies diff --git a/docs/intermediate/plex.md b/docs/intermediate/plex.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/intermediate/welcome.md b/docs/intermediate/welcome.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/whoami.md b/docs/whoami.md new file mode 100644 index 0000000..fbf3678 --- /dev/null +++ b/docs/whoami.md @@ -0,0 +1,38 @@ +# Welcome to Funky Penguin's Geek Cookbook + +## Hello world, + +I'm [David](https://www.funkypenguin.co.nz/contact/). + +I've spent 20+ years working with technology. My current role is **Senior Infrastructure Architect** at [Prophecy Networks Ltd](http://www.prophecy.net.nz) in New Zealand, with a specific interest in networking, systems, open-source, and business management. + +I've had a [book published](https://www.funkypenguin.co.nz/book/phplist-2-email-campaign-manager/), and I [blog](https://www.funkypenguin.co.nz/blog/) on topics that interest me. + +## Why Funky Penguin? + +My first "real" job, out of high-school, was working the IT helpdesk in a typical pre-2000 organization in South Africa. I enjoyed experimenting with Linux, and cut my teeth by replacing the organization's Exchange 5.5 mail platform with a 15-site [qmail-ldap](http://www.nrg4u.com/) cluster, with [amavis](https://en.wikipedia.org/wiki/Amavis) virus-scanning. + +One of our suppliers asked me to quote to do the same for their organization. With nothing to loose, and half-expecting to be turned down, I quoted a generous fee, and chose a cheeky company name. The supplier immediately accepted my quote, and the name ("_Funky Penguin_") stuck. + +## Technical Documentation + +During the same "real" job above, I wanted to deploy [jabberd](https://en.wikipedia.org/wiki/Jabberd14), for internal instant messaging within the organization, and as a means to control the sprawl of ad-hoc instant-messaging among staff, using ICQ, MSN, and Yahoo Messenger. + +To get management approval to deploy, I wrote a logger (with web UI) for jabber conversations ([Bandersnatch](https://www.funkypenguin.co.nz/project/bandersnatch/)), and a [75-page user manual](https://www.funkypenguin.co.nz/book/jajc-manual/) (in [Docbook XML](http://www.docbook.org/) for a spunky Russian WinXP jabber client, [JAJC](http://jajc.jrudevels.org/). + +Due to my contributions to [phpList](http://www.phplist.com), I was approached in 2011 by [Packt Publishing](http://www.packtpub.com), to [write a book](https://www.funkypenguin.co.nz/book/phplist-2-email-campaign-manager) about using PHPList. + +## Contact Me + +Contact me by: + +* Email ([davidy@funkypenguin.co.nz](mailto:davidy@funkypenguin.co.nz)) +* Twitter ([@funkypenguin](https://twitter.com/funkypenguin)) +* Mastodon ([@davidy@funkypenguin.co.nz](https://mastodon.funkypenguin.co.nz/@davidy)) + + +Or by using the form below: + +
+ +
diff --git a/mkdocs-material b/mkdocs-material new file mode 160000 index 0000000..ea3909d --- /dev/null +++ b/mkdocs-material @@ -0,0 +1 @@ +Subproject commit ea3909dcc1e3e8f184ac9f8fb283a81a806f7dbd diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..34325dd --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,110 @@ +site_name: Funky Penguin's Self-Hosted Geek's Cookbook +site_description: 'A short description of my project' +site_author: 'David Young' +site_url: 'http://localhost:8000' + +# Repository +# repo_name: 'funkypenguin/geek-cookbook' +# repo_url: 'https://github.com/john-doe/my-project' + +# Copyright +copyright: 'Copyright © 2016 - 2017 David Young' + + +theme: null +theme_dir: 'mkdocs-material/material' +pages: + - Home : index.md + - Introduction: + - README: README.md + - whoami: whoami.md + + - Docker (Standalone): + - Getting Started: + - Basic Setup: beginner/beginner.md + - LVM-Backed storage: beginner/beginner.md + - LetsEncrypt Proxy: advanced/about.md + + - Tiny Tiny RSS: + - Basic: advanced/tiny-tiny-rss.md + - Plugins: advanced/tiny-tiny-rss.md + - Themes: advanced/tiny-tiny-rss.md + +# - Home Assistant: +# - About: advanced/home-assistant/basic.md +# - Basic: advanced/home-assistant/basic.md +# - Grafana: advanced/home-assistant/grafana.md +# - Limitless LED: advanced/home-assistant/limitless-led.md +# - OwnTracks: advanced/home-assistant/limitless-led.md + + - Docker (HA Swarm): + + - Getting Started: + - Basic Setup: beginner/beginner.md + - Persistent Storage: beginner/beginner.md + - Keepalived: advanced/keepalived.md + + - Tiny Tiny RSS: + - Basic: advanced/tiny-tiny-rss.md + - Plugins: advanced/tiny-tiny-rss.md + - Themes: advanced/tiny-tiny-rss.md + +# - Home Assistant: + +# - About: advanced/home-assistant/basic.md +# - Basic: advanced/home-assistant/basic.md +# - Grafana: advanced/home-assistant/grafana.md +# - Limitless LED: advanced/home-assistant/limitless-led.md +# - OwnTracks: advanced/home-assistant/limitless-led.md + +# - Huginn: advanced/huginn.md +# - Nextcloud: advanced/nextcloud.md +# - OwnTracks: advanced/owntracks.md +# - Shaarli: advanced/shaarli.md +# - Wallabag: advanced/wallabag.md + + + + +extra: + logo: 'images/site-logo.png' + feature: + tabs: false + palette: + primary: 'indigo' + accent: 'indigo' + font: + text: 'Roboto' + code: 'Roboto Mono' + social: + - type: 'github' + link: 'https://github.com/john-doe' + - type: 'twitter' + link: 'https://twitter.com/john-doe' + - type: 'linkedin' + link: 'https://de.linkedin.com/in/john-doe' + +# Google Analytics +google_analytics: + - 'UA-XXXXXXXX-X' + - 'auto' + +# Extensions +markdown_extensions: + - admonition + - codehilite(linenums=true) + - toc(permalink=true) + - footnotes + - pymdownx.arithmatex + - pymdownx.betterem(smart_enable=all) + - pymdownx.caret + - pymdownx.critic + - pymdownx.emoji: + emoji_generator: !!python/name:pymdownx.emoji.to_svg + - pymdownx.inlinehilite + - pymdownx.magiclink + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.tasklist(custom_checkbox=true) + - pymdownx.tilde