├── .gitignore ├── LICENSE ├── README.md ├── clair ├── config.yaml ├── docker-compose.yaml ├── dockerfile └── readme.md ├── crontab-ui ├── arm32v7-node.dockerfile ├── docker-compose.yaml └── readme.md ├── hashi-vault ├── default.hcl ├── docker-compose.yaml └── readme.md ├── monitoring ├── docker-compose.yaml └── prometheus.yaml ├── pihole ├── dhcp-relay.dockerfile ├── docker-compose.yaml ├── isc-dhcp-relay ├── pihole-exporter.dockerfile └── readme.md ├── traefik ├── docker-compose.yaml ├── dynamic-conf.yaml └── readme.md └── unifi-controller ├── docker-compose.yaml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | #Extras 2 | .DS_Store 3 | .key 4 | .crt 5 | .pem 6 | .private 7 | data/ 8 | .env 9 | 10 | # Logs 11 | logs 12 | *.log 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | 18 | # Diagnostic reports (https://nodejs.org/api/report.html) 19 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 20 | 21 | # Runtime data 22 | pids 23 | *.pid 24 | *.seed 25 | *.pid.lock 26 | 27 | # Directory for instrumented libs generated by jscoverage/JSCover 28 | lib-cov 29 | 30 | # Coverage directory used by tools like istanbul 31 | coverage 32 | *.lcov 33 | 34 | # nyc test coverage 35 | .nyc_output 36 | 37 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 38 | .grunt 39 | 40 | # Bower dependency directory (https://bower.io/) 41 | bower_components 42 | 43 | # node-waf configuration 44 | .lock-wscript 45 | 46 | # Compiled binary addons (https://nodejs.org/api/addons.html) 47 | build/Release 48 | 49 | # Dependency directories 50 | node_modules/ 51 | jspm_packages/ 52 | 53 | # TypeScript v1 declaration files 54 | typings/ 55 | 56 | # TypeScript cache 57 | *.tsbuildinfo 58 | 59 | # Optional npm cache directory 60 | .npm 61 | 62 | # Optional eslint cache 63 | .eslintcache 64 | 65 | # Microbundle cache 66 | .rpt2_cache/ 67 | .rts2_cache_cjs/ 68 | .rts2_cache_es/ 69 | .rts2_cache_umd/ 70 | 71 | # Optional REPL history 72 | .node_repl_history 73 | 74 | # Output of 'npm pack' 75 | *.tgz 76 | 77 | # Yarn Integrity file 78 | .yarn-integrity 79 | 80 | # dotenv environment variables file 81 | .env 82 | .env.test 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | 87 | # next.js build output 88 | .next 89 | 90 | # nuxt.js build output 91 | .nuxt 92 | 93 | # gatsby files 94 | .cache/ 95 | public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rapsberry Pi Setup 2 | 3 | ## 1. Install OS 4 | 5 | This guide does an excellent job of summarizing the steps: 6 | https://desertbot.io/blog/headless-raspberry-pi-4-ssh-wifi-setup 7 | 8 | The gist... 9 | 10 | You'll download the Raspbian Lite OS Image here: 11 | https://www.raspberrypi.org/downloads/raspbian/ 12 | 13 | On Mac use balenaEtcher to write the os img file to the SD card. 14 | https://www.balena.io/etcher/ 15 | 16 | Simply insert the SD card, boot up Etcher, and select the img downloaded. Then Etcher will take care of the rest. 17 | 18 | Create a blank file on the root (the SD card will be labeled "boot", use the root of that drive) of the SD card titled "ssh". This tells Raspbian to start the ssh server on boot. 19 | 20 | Insert the SD card into the Raspberry Pi, plug in ethernet and power. 21 | 22 | View your DHCP logs/clients to get the IP of the device. You can also continually ping "raspberrypi.local" for the IP. 23 | 24 | ## 2. Connect and Configure 25 | 26 | Once you have an IP of the fresh Pi, go ahead and connect to it. 27 | 28 | Need to know: 29 | ``` 30 | default hostname: raspberrypi 31 | default username: pi 32 | default password: raspberry 33 | ``` 34 | ssh into the raspberry pi 35 | ``` 36 | ssh pi@raspberrypi.local 37 | ``` 38 | 39 | Once in you have a plethora of options. To edit and change a slew of basic items related to the rapsberry pi use the following command. You'll be able to change the hostname, local, timezone, and other raspberry specific files. 40 | ``` 41 | sudo raspi-config 42 | ``` 43 | 44 | ### Static IP 45 | 46 | To set a static IP we'll need to edit the ``` vi /etc/dhcpcd.conf ``` file. 47 | 48 | Default files: 49 | 50 | ``` 51 | # A sample configuration for dhcpcd. 52 | # See dhcpcd.conf(5) for details. 53 | 54 | # Allow users of this group to interact with dhcpcd via the control socket. 55 | #controlgroup wheel 56 | 57 | # Inform the DHCP server of our hostname for DDNS. 58 | hostname 59 | 60 | # Use the hardware address of the interface for the Client ID. 61 | clientid 62 | # or 63 | # Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361. 64 | # Some non-RFC compliant DHCP servers do not reply with this set. 65 | # In this case, comment out duid and enable clientid above. 66 | #duid 67 | 68 | # Persist interface configuration when dhcpcd exits. 69 | persistent 70 | 71 | # Rapid commit support. 72 | # Safe to enable by default because it requires the equivalent option set 73 | # on the server to actually work. 74 | option rapid_commit 75 | 76 | # A list of options to request from the DHCP server. 77 | option domain_name_servers, domain_name, domain_search, host_name 78 | option classless_static_routes 79 | # Respect the network MTU. This is applied to DHCP routes. 80 | option interface_mtu 81 | 82 | # Most distributions have NTP support. 83 | #option ntp_servers 84 | 85 | # A ServerID is required by RFC2131. 86 | require dhcp_server_identifier 87 | 88 | # Generate SLAAC address using the Hardware Address of the interface 89 | #slaac hwaddr 90 | # OR generate Stable Private IPv6 Addresses based from the DUID 91 | slaac private 92 | 93 | # Example static IP configuration: 94 | #interface eth0 95 | #static ip_address=192.168.0.10/24 96 | #static ip6_address=fd51:42f8:caae:d92e::ff/64 97 | #static routers=192.168.0.1 98 | #static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1 99 | 100 | # It is possible to fall back to a static IP if DHCP fails: 101 | # define static profile 102 | #profile static_eth0 103 | #static ip_address=192.168.1.23/24 104 | #static routers=192.168.1.1 105 | #static domain_name_servers=192.168.1.1 106 | 107 | # fallback to static profile on eth0 108 | #interface eth0 109 | #fallback static_eth0 110 | ``` 111 | 112 | We'll edit the above file to set a static IP. 113 | 114 | Add the following at the bottom of the file. I downloaded Vim: ```sudo apt install vim -y``` 115 | ``` 116 | interface eth0 117 | static ip_address=192.168.1.12/24 118 | static routers=192.168.1.1 119 | static domain_name_servers=192.168.1.1 1.1.1.1 120 | ``` 121 | Save the file using "esc" key then ":qw" to quit and write the file to disk. 122 | ```sudo reboot``` to reboot the raspberry pi. I tried to restart networking and the dhcpd service however those did not reload the configuration file. 123 | 124 | Side note: this version of debian uses this config file for setting networking IP scheme. Previously ```/etc/networking/interfaces``` was used. 125 | 126 | ### Configure the Raspberry Pi 127 | 128 | The world is your oyster now. You can do with your Pi as you please but you know have a headless Pi configured to be used over SSH. 129 | 130 | I'll continue with setting up Docker and other changes I will make with every install. 131 | 132 | #### Setup SSH Keys 133 | 134 | ```ssh-keygen ``` used defaults to place new ssh keys into the home folder of Pi. I'll be adding this public key to my Github account to pull in new items for development. 135 | 136 | #### Git 137 | ```sudo apt install git -y``` 138 | 139 | #### Docker 140 | Using this as a guide: https://docs.docker.com/v17.12/install/linux/docker-ce/debian/#install-using-the-repository 141 | 142 | ``` 143 | sudo apt-get update -y 144 | 145 | sudo apt-get install -y \ 146 | apt-transport-https \ 147 | ca-certificates \ 148 | curl \ 149 | gnupg2 \ 150 | software-properties-common 151 | 152 | curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - 153 | 154 | #verify release version 155 | lsb_release -cs 156 | 157 | echo "deb [arch=armhf] https://download.docker.com/linux/debian \ 158 | $(lsb_release -cs) stable" | \ 159 | sudo tee /etc/apt/sources.list.d/docker.list 160 | 161 | sudo apt-get update -y 162 | 163 | sudo apt-get install docker-ce -y --no-install-recommends 164 | ``` 165 | 166 | The official Docker CE will try to install aufs-dkms as a dependency however it will fail. The default is to now use overlayfs2. This requires no changes on your part though. 167 | Reference: https://github.com/raspberrypi/linux/issues/3021#issuecomment-508704040 168 | 169 | ``` 170 | sudo apt remove aufs-dkms -y 171 | 172 | sudo usermod -aG docker $USER 173 | 174 | sudo docker run armhf/hello-world 175 | 176 | sudo systemctl enable docker 177 | 178 | sudo apt install python3-pip -y 179 | 180 | sudo pip3 install docker-compose 181 | ``` 182 | 183 | #### Setup Files 184 | 185 | ``` 186 | sudo mkdir /srv/containers 187 | sudo chown $USER:docker /srv/containers 188 | 189 | git clone git@github.com:hbwheat/Raspberry-Pi-Setup.git /srv/containers 190 | 191 | ``` 192 | 193 | #### Setup Network for Traefik 194 | ``` 195 | sudo docker network create traefiknet 196 | ``` 197 | 198 | ## Overall File Structure 199 | You'll need to create the data folder, .env, and any user made folders in data. 200 | You'll need to create items with * next to them. 201 | ``` 202 | --| containers 203 | ----| traefik 204 | ------|docker-compose.yaml 205 | ------| dynamic-config.yaml 206 | ------| readme.md 207 | ------| .env * 208 | ------| data * 209 | --------| acme.json (this file must be locked down to 600 using chmod) * 210 | --------| traefik.log * 211 | ----| pihole 212 | ------| docker-compose.yaml 213 | ------| dhcp-relay.dockerfile 214 | ------| .env * 215 | ------| data * 216 | ---------| etc-dnsmasq.d 217 | -----------| (pihole will create more files here) 218 | -----------| 02-pihole.conf * 219 | --------| etc-pihole 220 | -----------| (pihole will create more files here) 221 | -----------| 01.locallan.list * 222 | ----| unifi-controller 223 | ------| docker-compose.yaml 224 | ------| .env * 225 | ------| data * 226 | ``` 227 | 228 | 229 | -------------------------------------------------------------------------------- /clair/config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2015 clair authors 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # 16 | # From https://raw.githubusercontent.com/coreos/clair/master/config.yaml.sample 17 | # 18 | 19 | # The values specified here are the default values that Clair uses if no configuration file is specified or if the keys are not defined. 20 | clair: 21 | database: 22 | # Database driver 23 | type: pgsql 24 | options: 25 | # PostgreSQL Connection string 26 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING 27 | #source: host=postgres port=5432 user=clair sslmode=disable statement_timeout=60000 28 | source: postgresql://clair:password@postgres:5432/clair?sslmode=disable&statement_timeout=60000 29 | 30 | # Number of elements kept in the cache 31 | # Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database. 32 | cachesize: 16384 33 | 34 | # 32-bit URL-safe base64 key used to encrypt pagination tokens 35 | # If one is not provided, it will be generated. 36 | # Multiple clair instances in the same cluster need the same value. 37 | paginationkey: 38 | 39 | # Maximum number of open connections allowed to database 40 | # If unspecified or <= 0 then no limit is enforced in Clair 41 | maxopenconnections: 10 42 | 43 | api: 44 | # v3 grpc/RESTful API server address 45 | addr: "0.0.0.0:6060" 46 | 47 | # Health server address 48 | # This is an unencrypted endpoint useful for load balancers to check to healthiness of the clair server. 49 | healthaddr: "0.0.0.0:6061" 50 | 51 | # Deadline before an API request will respond with a 503 52 | timeout: 900s 53 | 54 | # Optional PKI configuration 55 | # If you want to easily generate client certificates and CAs, try the following projects: 56 | # https://github.com/coreos/etcd-ca 57 | # https://github.com/cloudflare/cfssl 58 | servername: 59 | cafile: 60 | keyfile: 61 | certfile: 62 | 63 | updater: 64 | # Frequency the database will be updated with vulnerabilities from the default data sources 65 | # The value 0 disables the updater entirely. 66 | interval: 2h 67 | enabledupdaters: 68 | - debian 69 | - ubuntu 70 | - rhel 71 | - oracle 72 | - alpine 73 | - suse 74 | 75 | notifier: 76 | # Number of attempts before the notification is marked as failed to be sent 77 | attempts: 3 78 | 79 | # Duration before a failed notification is retried 80 | renotifyinterval: 2h 81 | 82 | http: 83 | # Optional endpoint that will receive notifications via POST requests 84 | endpoint: 85 | 86 | # Optional PKI configuration 87 | # If you want to easily generate client certificates and CAs, try the following projects: 88 | # https://github.com/cloudflare/cfssl 89 | # https://github.com/coreos/etcd-ca 90 | servername: 91 | cafile: 92 | keyfile: 93 | certfile: 94 | 95 | # Optional HTTP Proxy: must be a valid URL (including the scheme). 96 | proxy: -------------------------------------------------------------------------------- /clair/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | clair: 5 | container_name: clair 6 | build: 7 | context: . 8 | image: local/arm32v6-clair:v2.1.2 9 | volumes: 10 | - ./config.yaml:/etc/clair/config.yaml 11 | networks: 12 | - traefiknet 13 | - cn 14 | labels: 15 | - "traefik.enable=true" 16 | - "traefik.http.routers.clair.rule=Host(`${URL0_SAN}`)" 17 | - "traefik.http.routers.clair.entrypoints=websecure" 18 | - "traefik.http.routers.clair.tls=true" 19 | - "traefik.http.routers.clair.tls.certresolver=mydnschallenge" 20 | 21 | postgres: 22 | image: arm32v7/postgres 23 | container_name: clairdb 24 | networks: 25 | - cn 26 | #volumes: 27 | # - cldb:/var/lib/postgresql/data 28 | environment: 29 | POSTGRES_USER: ${DB_USER} 30 | POSTGRES_PASSWORD: ${DB_PASS} 31 | POSTGRES_DB: clair 32 | 33 | networks: 34 | traefiknet: 35 | external: true 36 | cn: 37 | internal: true 38 | 39 | volumes: 40 | cldb: -------------------------------------------------------------------------------- /clair/dockerfile: -------------------------------------------------------------------------------- 1 | #source https://github.com/quay/clair/blob/master/Dockerfile 2 | 3 | FROM arm32v6/golang:1.13-alpine AS build 4 | RUN apk add --no-cache git build-base 5 | RUN mkdir -p go/clair/ 6 | WORKDIR /go/clair/ 7 | RUN git clone https://github.com/quay/clair.git . && \ 8 | git checkout tags/v2.1.2 9 | RUN export CLAIR_VERSION=$(git describe --tag --always --dirty) && \ 10 | env GOOS=linux GOARCH=arm go build -ldflags "-X github.com/quay/clair/v3/pkg/version.Version=$CLAIR_VERSION" ./cmd/clair 11 | 12 | FROM arm32v6/alpine:3.10 13 | COPY --from=build /go/clair/clair /clair 14 | RUN apk add --no-cache git rpm xz ca-certificates dumb-init 15 | 16 | # change ownership of ssl directory to allow custom cert in OpenShift 17 | #RUN chgrp -R 0 /etc/ssl/certs && \ 18 | # chmod -R g=u /etc/ssl/certs 19 | 20 | ENTRYPOINT ["/usr/bin/dumb-init", "--", "/clair"] 21 | VOLUME /config 22 | EXPOSE 6060 6061 23 | 24 | -------------------------------------------------------------------------------- /clair/readme.md: -------------------------------------------------------------------------------- 1 | # Work in Progress instructions 2 | 3 | mkdir $PWD/clair_config 4 | curl -L https://raw.githubusercontent.com/coreos/clair/master/config.yaml.sample -o $PWD/clair_config/config.yaml 5 | docker run -d -e POSTGRES_PASSWORD="" -p 5432:5432 postgres:9.6 6 | 7 | docker run --net=host -d -p 6060-6061:6060-6061 -v $PWD/clair_config:/config quay.io/coreos/clair-git:latest -config=/config/config.yaml -------------------------------------------------------------------------------- /crontab-ui/arm32v7-node.dockerfile: -------------------------------------------------------------------------------- 1 | # arm dockerfile for crontab-ui 2 | FROM arm32v7/node:8-slim 3 | 4 | RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get upgrade -y && \ 5 | DEBIAN_FRONTEND=noninteractive apt-get install -y wget curl cron && \ 6 | apt-get clean && rm -rf /var/lib/apt/lists/* 7 | 8 | WORKDIR /home/node 9 | 10 | USER node 11 | 12 | ENV NPM_CONFIG_PREFIX=/home/node/.npm-global 13 | ENV PATH=$PATH:/home/node/.npm-global/bin 14 | ENV NODE_ENV=production 15 | 16 | RUN npm install -g crontab-ui && \ 17 | npm install -g pm2 18 | 19 | ENV PORT 8000 20 | ENV HOST 0.0.0.0 21 | 22 | EXPOSE $PORT 23 | 24 | CMD [ "pm2-runtime", "crontab-ui", "--raw", "start" ] 25 | # --raw or --json format -------------------------------------------------------------------------------- /crontab-ui/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | 3 | services: 4 | crontab-ui: 5 | container_name: crontab-ui 6 | build: 7 | context: . 8 | dockerfile: arm32v7-node.dockerfile 9 | image: local/arm32v7-crontab-ui:latest 10 | networks: 11 | - traefiknet 12 | volumes: 13 | - ./data/scripts:/home/node/scripts:ro 14 | labels: 15 | - "traefik.enable=true" 16 | - "traefik.http.routers.cron.rule=Host(`${URL0_SAN}`)" 17 | - "traefik.http.routers.cron.entrypoints=websecure" 18 | - "traefik.http.routers.cron.tls=true" 19 | - "traefik.http.routers.cron.tls.certresolver=mydnschallenge" 20 | - "traefik.http.middlewares.cronauth.basicauth.users=${CRON_LOGIN}" 21 | - "traefik.http.routers.cron.middlewares=cronauth" 22 | 23 | networks: 24 | traefiknet: 25 | external: true 26 | -------------------------------------------------------------------------------- /crontab-ui/readme.md: -------------------------------------------------------------------------------- 1 | # Crontab-UI 2 | Crontab-UI is being installed via npm package rather than their git repo. 3 | 4 | Needs an active internet connection to pull the packages. -------------------------------------------------------------------------------- /hashi-vault/default.hcl: -------------------------------------------------------------------------------- 1 | storage "file" { 2 | path = "/vault/file" 3 | } 4 | 5 | ui = true 6 | 7 | listener "tcp" { 8 | address = "0.0.0.0:8200" 9 | tls_disable = 1 10 | } 11 | 12 | telemetry { 13 | prometheus_retention_time = "30s", 14 | disable_hostname = true 15 | } -------------------------------------------------------------------------------- /hashi-vault/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | vault: 5 | image: arm32v6/vault 6 | container_name: vault 7 | restart: always 8 | hostname: vault 9 | command: 10 | - "server" 11 | networks: 12 | - traefiknet 13 | - monitor 14 | expose: 15 | - 8200 16 | volumes: 17 | - ./default.hcl:/vault/config/default.hcl:ro 18 | - ./data/logs:/vault/logs:rw 19 | - ./data/file:/vault/file:rw 20 | environment: 21 | VAULT_API_ADDR: https://${URL0_SAN} 22 | #VAULT_LOG_LEVEL: INFO 23 | cap_add: 24 | - IPC_LOCK 25 | labels: 26 | - "traefik.enable=true" 27 | - "traefik.http.routers.vault.rule=Host(`${URL0_SAN}`)" 28 | - "traefik.http.routers.vault.entrypoints=websecure" 29 | - "traefik.http.routers.vault.tls=true" 30 | - "traefik.http.routers.vault.tls.certresolver=mydnschallenge" 31 | 32 | networks: 33 | traefiknet: 34 | external: true 35 | monitor: 36 | external: true -------------------------------------------------------------------------------- /hashi-vault/readme.md: -------------------------------------------------------------------------------- 1 | # Hashicorp Vault 2 | 3 | ## Overview 4 | 5 | I'm using the arm32v6 image from docker hub. The storage provider is local file storage and i'm setting it to run in "production" mode via the command in the compose file. Everything is else is per usual on setup. Refer to the docker hub page on configuration options. 6 | 7 | Initial setup i'm doing through the UI, but something like ```docker exec -it vault bash``` plus cli commands will do the same. Vault's documents have setup done through the cli. 8 | 9 | Recommend to run with "server" command option from github link I found. So doing that. 10 | ======= 11 | The intial setup for Vault want something like: 12 | Root login -> admin and provisioner acls from docs -> admin token -> admin login 13 | 14 | ### TL;DR 15 | Some things to keep in mind: 16 | Vault is least privilege out of the box. The "default" acl is used for self management. The doc's admin profile is used to make overarching items, but not the same root access as root. 17 | 18 | When you create a new "engine" or place to store items they are at the "/whatever" path. So if you make a new key-vaule (kv) engine and name it "kv" as the default it'll be available at the "/kv" path in the configs. 19 | 20 | You will need to make a new acls policy for the "engine" you make or use a wildcard. Then create tokens or as 21 | 22 | #### Example 1, Wildcard: 23 | 24 | ``` 25 | # Access and Mange all Engines 26 | path "/*" 27 | { 28 | capabilities = ["create", "read", "update", "delete", "list", "sudo"] 29 | } 30 | ``` 31 | 32 | #### Example 2, Specific: 33 | 34 | Key-value for cloudfare items. 35 | 36 | ``` 37 | path "kv-cloudflare/" { 38 | capabilities = ["read"] 39 | } 40 | 41 | path "kv-cloudflare/" { 42 | capabilities = ["list"] 43 | } 44 | ``` 45 | ## Setup 46 | 47 | >Reference: https://learn.hashicorp.com/vault/identity-access-management/iam-policies 48 | 49 | After running ```docker-compose up -d; docker-compose logs -f``` navigate to the URL via the browswer. Traefik already setup a https cert for us. We'll need to initialize the Vault. Once again this can be done through the cli. 50 | 51 | ### Policies 52 | 53 | Use the pre-made policies from the docs to assign an admin and provisioner acl. 54 | 55 | Create new client token via the new admin policy. ```vault write auth/token/create policies=admin``` and copy the contents to a safe place. This creates a token to be used as an admin. 56 | 57 | Reference: https://www.vaultproject.io/docs/concepts/policies.html 58 | 59 | ### Tokens 60 | 61 | Tokens are the initial and most basic form of authentication. Use the cli to create a token and use it during your api call to retrieve the secret. 62 | 63 | ```vault write auth/token/create policies=kv-it``` 64 | 65 | ``` 66 | vault secrets enable -path=kv cloudflare 67 | ``` 68 | 69 | For userpass authentication add the name of the policy inside of the policy "Generated Token's Policies 70 | " section. This will all the logged in user to have access to that acl. -------------------------------------------------------------------------------- /monitoring/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | prometheus: 5 | container_name: prometheus 6 | hostname: prometheus 7 | image: prom/prometheus:v2.13.1 8 | restart: always 9 | command: 10 | - "--config.file=/etc/prometheus/prometheus.yaml" #set config file on startup 11 | - "--storage.tsdb.path=/prometheus" #set below via container volume 12 | - "--storage.tsdb.retention=30d" 13 | - '--web.enable-lifecycle' # curl -kX POST http://localhost:9090/-/reload to reload config file 14 | # curl -kX POST https://${URL0_SAN}/-/reload 15 | volumes: 16 | - ./prometheus.yaml:/etc/prometheus/prometheus.yaml 17 | #- prometheus-data:/etc/prometheus/ #configs dir 18 | - prometheus-data:/prometheus #data dir 19 | networks: 20 | - traefiknet 21 | - monitor 22 | dns: 23 | - pihole # resolution works in container via nslookup however prom is not resolving the hostname/connecting 24 | # use pihole to server dns resolution for outside services that will be polled by prometheus 25 | expose: 26 | - 9090 27 | labels: 28 | - "traefik.enable=true" 29 | - "traefik.http.routers.prom.rule=Host(`${URL0_SAN}`)" 30 | - "traefik.http.routers.prom.entrypoints=websecure" 31 | - "traefik.http.routers.prom.tls=true" 32 | - "traefik.http.routers.prom.tls.certresolver=mydnschallenge" 33 | 34 | nodeexporter: 35 | image: prom/node-exporter 36 | container_name: nodeexporter 37 | hostname: nodeexporter 38 | networks: 39 | - monitor 40 | volumes: 41 | - /proc:/host/proc:ro 42 | - /sys:/host/sys:ro 43 | - /:/rootfs:ro 44 | - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket:ro #logind 45 | command: 46 | - '--path.procfs=/host/proc' 47 | - '--path.rootfs=/rootfs' 48 | - '--path.sysfs=/host/sys' 49 | - '--collector.logind' 50 | - '--collector.processes' 51 | - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc|srv|media)($$|/)' 52 | restart: unless-stopped 53 | 54 | grafana: 55 | image: grafana/grafana:6.7.1 56 | networks: 57 | - traefiknet 58 | - monitor 59 | restart: always 60 | container_name: grafana 61 | environment: 62 | - GF_INSTALL_PLUGINS=grafana-azure-monitor-datasource 63 | - GF_SERVER_ROOT_URL=${GF_ROOT} 64 | - GF_SECURITY_ADMIN_PASSWORD=${GF_ADMIN_PASSWORD} 65 | - GF_PLUGINS_APP_TLS_SKIP_VERIFY_INSECURE=true 66 | - GF_SMTP_ENABLED=true 67 | - GF_SMTP_HOST=${SMTP_HOST} 68 | - GF_SMTP_FROM_ADDRESS=${SMTP_USER} 69 | - GF_SMTP_USER=${SMTP_USER} 70 | - GF_SMTP_PASSWORD=${SMTP_PASSWORD} 71 | #- GF_LOG_LEVEL=debug 72 | user: "1000" 73 | volumes: 74 | #- ./data/grafana.db:/var/lib/grafana/grafana.db:rw 75 | - ./data/grafana:/var/lib/grafana:rw 76 | labels: 77 | - "traefik.enable=true" 78 | - "traefik.http.routers.grafana.rule=Host(`${URL2_SAN}`)" 79 | - "traefik.http.routers.grafana.entrypoints=websecure" 80 | - "traefik.http.routers.grafana.tls=true" 81 | - "traefik.http.routers.grafana.tls.certresolver=mydnschallenge" 82 | - "traefik.http.routers.grafanahttp.rule=Host(`${URL2_SAN}`)" 83 | - "traefik.http.routers.grafanahttp.entrypoints=web" 84 | - "traefik.http.routers.grafanahttp.middlewares=enforce-https@file" 85 | 86 | networks: 87 | traefiknet: 88 | external: true 89 | monitor: 90 | external: true 91 | 92 | volumes: 93 | prometheus-data: -------------------------------------------------------------------------------- /monitoring/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 45s # Set the scrape interval to every 15 seconds. Default is every 1 minute. 3 | evaluation_interval: 25s # Evaluate rules every 15 seconds. The default is every 1 minute. 4 | # scrape_timeout is set to the global default (10s). 5 | 6 | scrape_configs: 7 | # The job name is added as a label `job=` to any timeseries scraped from this config. 8 | - job_name: 'prometheus' 9 | scrape_interval: 5s 10 | # metrics_path defaults to '/metrics' 11 | # scheme defaults to 'http'. 12 | static_configs: 13 | - targets: 14 | - localhost:9090 15 | 16 | - job_name: 'nodeexporter' 17 | scrape_interval: 5s 18 | # metrics_path defaults to '/metrics' 19 | # scheme defaults to 'http'. 20 | static_configs: 21 | - targets: 22 | - nodeexporter:9100 23 | 24 | - job_name: 'traefik' 25 | scrape_interval: 5s 26 | # metrics_path defaults to '/metrics' 27 | # scheme defaults to 'http'. 28 | static_configs: 29 | - targets: 30 | - traefik:8082 31 | 32 | - job_name: 'vault' 33 | scrape_interval: 5s 34 | static_configs: 35 | - targets: 36 | - vault:8082 37 | 38 | - job_name: 'helium-general' 39 | scrape_interval: 15s 40 | static_configs: 41 | - targets: 42 | - 192.168.1.163:9182 43 | 44 | - job_name: 'helium-hardware' 45 | scrape_interval: 15s 46 | static_configs: 47 | - targets: 48 | - 192.168.1.163:9183 49 | -------------------------------------------------------------------------------- /pihole/dhcp-relay.dockerfile: -------------------------------------------------------------------------------- 1 | FROM arm32v7/debian 2 | RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get upgrade -y && \ 3 | DEBIAN_FRONTEND=noninteractive apt-get install -y isc-dhcp-relay && \ 4 | apt-get clean && rm -rf /var/lib/apt/lists/* 5 | 6 | ARG INTERFACE_UPSTREAM 7 | ENV INTERFACE_UPSTREAM=${INTERFACE_UPSTREAM} 8 | ARG INTERFACE_DOWNSTREAM 9 | ENV INTERFACE_DOWNSTREAM=${INTERFACE_DOWNSTREAM} 10 | 11 | ARG SERVER 12 | ENV SERVER=${SERVER} 13 | 14 | RUN export INTERFACE_UPSTREAM=${INTERFACE_UPSTREAM} && \ 15 | export INTERFACE_DOWNSTREAM=${INTERFACE_DOWNSTREAM} && \ 16 | export SERVER=${SERVER} 17 | 18 | EXPOSE 67/udp 19 | 20 | CMD dhcrelay -4 -d -id $INTERFACE_DOWNSTREAM -iu $INTERFACE_UPSTREAM $SERVER 21 | -------------------------------------------------------------------------------- /pihole/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | # More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/ 4 | services: 5 | dhcp-relay: 6 | container_name: dhcp-relay 7 | build: 8 | context: . 9 | dockerfile: dhcp-relay.dockerfile 10 | args: 11 | INTERFACE_UPSTREAM: "br-976c9dfa3dbb" 12 | INTERFACE_DOWNSTREAM: "eth0" 13 | SERVER: "pihole.local" 14 | image: local/dhcp-relay-arm32v7:latest 15 | restart: always 16 | network_mode: host 17 | depends_on: 18 | - pihole 19 | cap_add: 20 | - NET_ADMIN 21 | dns: 22 | - pihole.local #tell container to look at pihole container for dns 23 | dns_search: 24 | - .local #search locally for .local domains not the internet 25 | 26 | pihole: 27 | container_name: pihole 28 | image: pihole/pihole:latest 29 | env_file: ./.env 30 | hostname: pihole.local 31 | networks: 32 | - traefiknet 33 | - piholedhcp 34 | ports: 35 | - "53:53/tcp" #dns 36 | - "53:53/udp" #dns 37 | #- "67:67/udp" #dhcp server 38 | #- "80:80/tcp" 39 | #- "443:443/tcp" 40 | expose: 41 | - 80 42 | - 443 43 | environment: 44 | TZ: 'America/New_York' 45 | WEBPASSWORD: ${WEBPASSWORD} 46 | DNS1: 1.1.1.1 47 | DNS2: 9.9.9.9 48 | ServerIP: ${HOST_IP} 49 | VIRTUAL_HOST: ${URL0_SAN} 50 | DNSMASQ_LISTENING: all 51 | # Volumes store your data between container upgrades 52 | volumes: 53 | - ./data/etc-pihole/:/etc/pihole/ 54 | - ./data/etc-dnsmasq.d/:/etc/dnsmasq.d/ 55 | dns: 56 | - 127.0.0.1 57 | - 1.1.1.1 58 | # Recommended but not required (DHCP needs NET_ADMIN) 59 | # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities 60 | cap_add: 61 | - NET_ADMIN 62 | restart: always 63 | labels: 64 | - "traefik.enable=true" 65 | 66 | #sinkhole for port 80 67 | - "traefik.http.routers.pihole80.rule=Host(`${URL0_SAN}`) || Host(`${HOST_IP}`)" 68 | - "traefik.http.routers.pihole80.service=pihole80@docker" 69 | - "traefik.http.routers.pihole80.entrypoints=web" 70 | - "traefik.http.services.pihole80.loadbalancer.server.port=80" 71 | - "traefik.http.routers.pihole80.middlewares=piholeadmin80-redirect,piholeadmin80ip-redirect" 72 | 73 | - "traefik.http.middlewares.piholeadmin80-redirect.redirectregex.regex=^http://${URL0_SAN}/admin*" 74 | - "traefik.http.middlewares.piholeadmin80-redirect.redirectregex.replacement=https://${URL0_SAN}/admin" 75 | - "traefik.http.middlewares.piholeadmin80ip-redirect.redirectregex.regex=^http://${HOST_IP}/admin*" 76 | - "traefik.http.middlewares.piholeadmin80ip-redirect.redirectregex.replacement=https://${URL0_SAN}/admin" 77 | 78 | #---------------------------------------------------------------------------------- 79 | #sinkhole for port 443 by IP 80 | - "traefik.http.routers.pihole443.rule=Host(`${HOST_IP}`)" 81 | - "traefik.http.routers.pihole443.service=pihole443@docker" 82 | - "traefik.http.routers.pihole443.entrypoints=websecure" 83 | - "traefik.http.routers.pihole443.tls=true" 84 | - "traefik.http.services.pihole443.loadbalancer.server.scheme=https" 85 | - "traefik.http.services.pihole443.loadbalancer.server.port=443" 86 | 87 | #---------------------------------------------------------------------------------- 88 | #admin for port 443 89 | - "traefik.http.routers.pihole443admin.rule=Host(`${URL0_SAN}`)" 90 | - "traefik.http.routers.pihole443admin.service=pihole443admin@docker" 91 | - "traefik.http.routers.pihole443admin.entrypoints=websecure" 92 | - "traefik.http.routers.pihole443admin.tls=true" 93 | - "traefik.http.routers.pihole443admin.tls.certresolver=mydnschallenge" 94 | - "traefik.http.services.pihole443admin.loadbalancer.server.scheme=http" 95 | - "traefik.http.services.pihole443admin.loadbalancer.server.port=80" 96 | #---------------------------------------------------------------------------------- 97 | #admin access 98 | - "traefik.http.routers.piholeadmin.rule=Host(`${URL1_SAN}`)" 99 | - "traefik.http.routers.piholeadmin.entrypoints=websecure" 100 | - "traefik.http.routers.piholeadmin.service=piholeadmin@docker" 101 | - "traefik.http.routers.piholeadmin.tls=true" 102 | - "traefik.http.routers.piholeadmin.tls.certresolver=mydnschallenge" 103 | - "traefik.http.middlewares.piholeadmin-redirect.redirectregex.regex=^https://${URL1_SAN}*" 104 | - "traefik.http.middlewares.piholeadmin-redirect.redirectregex.replacement=https://${URL0_SAN}/admin" 105 | - "traefik.http.routers.piholeadmin.middlewares=piholeadmin-redirect" 106 | - "traefik.http.services.piholeadmin.loadbalancer.server.scheme=http" 107 | - "traefik.http.services.piholeadmin.loadbalancer.server.port=80" 108 | 109 | networks: 110 | traefiknet: 111 | external: true 112 | piholedhcp: 113 | external: true -------------------------------------------------------------------------------- /pihole/isc-dhcp-relay: -------------------------------------------------------------------------------- 1 | # Defaults for isc-dhcp-relay initscript 2 | # sourced by /etc/init.d/isc-dhcp-relay 3 | # installed at /etc/default/isc-dhcp-relay by the maintainer scripts 4 | 5 | # 6 | # This is a POSIX shell fragment 7 | # 8 | 9 | # What servers should the DHCP relay forward requests to? 10 | SERVERS="pihole" 11 | 12 | # On what interfaces should the DHCP relay (dhrelay) serve DHCP requests? 13 | INTERFACES="" 14 | 15 | # Additional options that are passed to the DHCP relay daemon? 16 | OPTIONS="-4 -id eth0 -iu br-976c9dfa3dbb" -------------------------------------------------------------------------------- /pihole/pihole-exporter.dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine -------------------------------------------------------------------------------- /pihole/readme.md: -------------------------------------------------------------------------------- 1 | # Pihole Setup on Raspberry Pi 4 2 | 3 | ## Files 4 | Setup .env and data directories on the server. From point of docker-compose.yaml: 5 | 6 | ``` 7 | mkdir -p data/etc-pihole 8 | mkdir data/dnsmasq.d 9 | ``` 10 | 11 | The etc-pihole folder will hold persistent data. We'll add a new config to the dnsmasq.d direcotry to act like split-brain dns for a domain. In my case hbwheat.dev. 12 | 13 | Create a single text file with a line telling the pihole dns to send all dns traffic based on the wild card *.hbwheat.dev towards the ip of the server. I'll also add a .list file for reference in the persistent data folder for future use. This will allow me to define IPs as necessary and be served by the pihole dns server. 14 | 15 | DNSMASQ will look to this directory for any configuration files. 16 | 17 | file name: 02-pihole.conf added the following in srv/containers/pihole/data/dnsmasq.d/02-pihole.conf: 18 | 19 | ``` 20 | addn-hosts=/etc/pihole/01.locallan.list 21 | address=/hbwheat.dev/192.168.1.12 22 | ``` 23 | This creates our wildcard scenario and directs traffic towards our destination via DNS. 24 | 25 | ## Local DNS Settings 26 | You can define custom dns entries using a .list files and configuring DNSMASQ to look at this list for DNS requests. 27 | Make sure you put the .list file in "/srv/containers/pihole/data/etc-pihole/*.list". 28 | 29 | Add any local dns records to the "01.locallan.list". 30 | 31 | Reference to add dns entries: 32 | https://qiita.com/bmj0114/items/9c24d863bcab1a634503 33 | 34 | ## DHCP-Relay and DHCP 35 | ### Important part here: The pihole DHCP server will hand out the IP of the container. Override it with the IP of the raspberry pi. 36 | 37 | Add the following line to your DHCP config in the "etc-dnsmaq.d" data folder: 38 | ```dhcp-option=option:dns-server,x.x.x.x```` 39 | 40 | You'll need to turn DHCP on in the pihole first for this file to exist. Either open the file and add the line or use a one liner. 41 | 42 | ```echo "dhcp-option=option:dns-server,192.168.1.2" | sudo tee ./etc-dnsmasq.d/02-pihole-dhcp.conf``` 43 | 44 | Next set a hostname for your container in the docker-compose file. We'll need this for the relay to have a server to search for. 45 | 46 | Also, we'll comment out the dhcp port in the compose file. The DHCP-relay will forward our traffic back and forth out of the container. 47 | 48 | Setting up a DHCP server within a container has a simple challenge. DHCP packets don't traverse over subnets. The way docker handles bridging of networks, if you wish to have a container not be on the host network you'll need to configure your server with a dhcp relay. 49 | 50 | The relay will sit on both the docker network bridge for the dhcp server and the client request side. 51 | 52 | We'll need to define a network outside of the compose file for Pihole to use. Before we do that, let's check out the route table on the server to determine what the interfaces are and then we can figure out the name of the new network interface. 53 | 54 | ``` 55 | ip route 56 | ``` 57 | 58 | Then create a new network for docker: 59 | ``` 60 | docker network create piholedhcp 61 | ``` 62 | 63 | Bring up ip routes again and lets see the new networking scheme. The new network interface will be towards the bottom of the list and look something like ```br-976c9dfa3dbb``` 64 | 65 | ``` 66 | ip route 67 | ``` 68 | I'm using Method 2 .....after going with Method 1 first, but I like it everything being containerized. Minimal server setup is my preference. 69 | 70 | ### Methood 1 71 | #### Use a dhcp-relay on the raspberry pi to listen on an interface and forward requets to the container network. 72 | 73 | We'll add the interface we found above to the dhcp-relay configuration file. 74 | 75 | Install the dhcp relay via apt. 76 | ``sudo apt install isc-dhcp-relay -y``` 77 | 78 | I've added my isc-dhcp-relay file for reference. The options used here will be set in the "options" on in the file. 79 | 80 | ```sudo service isc-dhcp-relay restart``` 81 | To monitor the logs tail ```tail -f /var/log/syslog``` to verify the deamon is starting properly. 82 | 83 | You can also use the debugging switch to verify your switches work as intended.Then write these swtiches to the OPTIONS section in the configuration files at ```/etc/default/isc-dhcp-relay```. 84 | 85 | ```sudo dhcrelay -4 -d -id eth0 -iu br-976c9dfa3dbb pihole``` 86 | 87 | Remember to start the service once you've tested with the above command. 88 | ```sudo service isc-dhcp-relay restart``` 89 | 90 | Man page for the DHCP relay: https://manpages.debian.org/testing/isc-dhcp-relay/dhcrelay.8.en.html 91 | 92 | ## Method 2 93 | ### Use a seperate container and make it the relay. 94 | The second method is to define a second container, give this one network mode host, and stradle the necessary interfaces. 95 | 96 | This is a good reference used https://discourse.pi-hole.net/t/dhcp-with-docker-compose-and-bridge-networking/17038 97 | I like the idea of everything being in containers. 98 | 99 | Need to use ```sudo docker-compose build``` for some reason. This needed to be run as sudo. It'll use the tag in the compose file to label the image. 100 | 101 | The docker-compose file lists the build image tag and necessary information for the container. Most importantly this container will have the network mode host option. Network mode host gives this container access to the host networking stack. It'll be able to forward UDP packets on the interfaces we specify. 102 | 103 | Give the dockerfile some build arguments: 104 | ``` 105 | args: 106 | INTERFACE_UPSTREAM: "br-976c9dfa3dbb" 107 | INTERFACE_DOWNSTREAM: "eth0" 108 | SERVER: "pihole" 109 | ``` 110 | The upstream interface is the one where the DHCP server will be, and the downstream is where requests will originate. Last, the server is the hostname we defined in the compose file. This dockerfile could be refactored to manually add more interfaces if needed. 111 | 112 | -------------------------------------------------------------------------------- /traefik/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | traefik: 5 | image: arm32v6/traefik:latest 6 | container_name: traefik 7 | restart: always 8 | networks: 9 | - traefiknet 10 | ports: 11 | - 80:80 12 | - 443:443 13 | volumes: 14 | - ./dynamic-conf.yaml:/etc/traefik/dynamic-conf.yaml:ro 15 | - ./data/traefik.log:/etc/traefik/traefik.log 16 | - ./data/certs/CAs.crt:/etc/traefik/certs/CAs.crt:ro 17 | - /var/run/docker.sock:/var/run/docker.sock:ro 18 | - ./data/acme.json:/letsencrypt/acme.json:rw #used by LetsEncrypt for HTTPs 19 | #- ./certs:/srv/certs:ro #for self signed certs and CA 20 | environment: 21 | #- CF_API_EMAIL=${CF_API_EMAIL} 22 | #- CF_API_KEY=${CF_API_KEY} 23 | - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} 24 | - CF_ZONE_API_TOKEN=${CF_ZONE_API_TOKEN} 25 | #- "TRAEFIK_SERVERSTRANSPORT_INSECURESKIPVERIFY=true" 26 | command: #these commands replace a separate traefik.yaml config file 27 | - "--log.level=INFO" #logLevel DEBUG, INFO, WARN, ERROR, FATAL, PANIC 28 | - "--log.filepath=/etc/traefik/traefik.log" 29 | - "--log.format=json" 30 | #- "--api.insecure=true" 31 | - "--api.dashboard=true" 32 | #- "--serverstransport.insecureskipverify=true" 33 | - "--metrics.prometheus.entryPoint=metrics" 34 | - "--metrics.prometheus.addentrypointslabels" 35 | - "--metrics.prometheus.addserviceslabels=true" 36 | - "--providers.docker=true" 37 | - "--providers.docker.exposedbydefault=false" 38 | - "--providers.docker.network=traefiknet" 39 | - "--entrypoints.web.address=:80" 40 | - "--entrypoints.websecure.address=:443" 41 | - "--entrypoints.metrics.address=:8082" 42 | #- "--hostresolver.cnameflattening=true" 43 | - "--providers.file.filename=/etc/traefik/dynamic-conf.yaml" 44 | - "--providers.file.watch=true" 45 | - "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true" 46 | - "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=cloudflare" 47 | #- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" #for testing the challenge and API keys 48 | - "--certificatesresolvers.mydnschallenge.acme.email=${MYDNSCHALLENGE_ACME_EMAIL}" 49 | - "--certificatesResolvers.mydnschallenge.acme.dnsChallenge.delayBeforeCheck=5" 50 | - "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json" 51 | - "--serverstransport.rootcas=/etc/traefik/certs/CAs.crt" 52 | labels: 53 | - "traefik.enable=true" 54 | - "traefik.http.routers.api.rule=Host(`${URL0_SAN}`)" 55 | - "traefik.http.routers.api.entrypoints=websecure" 56 | - "traefik.http.routers.api.service=api@internal" 57 | - "traefik.http.routers.api.tls=true" 58 | - "traefik.http.routers.api.tls.certresolver=mydnschallenge" 59 | - "traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_LOGIN}" 60 | - "traefik.http.routers.api.middlewares=auth" 61 | 62 | 63 | networks: 64 | traefiknet: 65 | external: true 66 | -------------------------------------------------------------------------------- /traefik/dynamic-conf.yaml: -------------------------------------------------------------------------------- 1 | # ./dyanamic-conf.yaml 2 | 3 | http: 4 | middlewares: 5 | enforce-https: 6 | redirectScheme: 7 | scheme: https 8 | permanent: true -------------------------------------------------------------------------------- /traefik/readme.md: -------------------------------------------------------------------------------- 1 | # Traefik Setup 2 | 3 | Using docker-compose to organize all of the information required to setup treafik. The workflow I have now is to push changes to Github then pull them down on the docker server. 4 | 5 | ## HTTPS + AMCEv2 + LetsEncrypt 6 | I'm using traefik's built in cert ability and DNS-01 challenage with Cloudflare. 7 | 8 | Reference: https://docs.traefik.io/user-guides/docker-compose/acme-dns/ 9 | 10 | ## Files 11 | 12 | The compose file works in tune with a .env file and dynamic-conf.yaml file. 13 | 14 | You'll see that the commands section of the compose.yaml sets quite a few default parameters. ie entrypoints, dnschallenge, providers (docker, file), and misc other items. 15 | 16 | In the future for testing or changes, rather than taking down the proxy server we can adjust configurations in the dynamic-config.yaml file as traefik is configured to watch this for any updates. 17 | 18 | The directory structure is as follows: * are items you'll need to create. 19 | ``` 20 | --| traefik 21 | ----|docker-compose.yaml 22 | ----| dynamic-config.yaml 23 | ----| readme.md 24 | ----| .env * 25 | ----| data * 26 | ------| acme.json (this file must be locked down to 600 using chmod) * 27 | ------| traefik.log * 28 | ``` 29 | 30 | ## .env file 31 | 32 | My .env file. This is a file I excluded from github so you'll have to create manually. 33 | 34 | ``` 35 | CF_API_EMAIL= 36 | CF_API_KEY= 37 | CF_DNS_API_TOKEN= 38 | CF_ZONE_API_TOKEN= 39 | CF_API_EMAIL= 40 | MYDNSCHALLENGE_ACME_EMAIL= 41 | URL0_SAN= 42 | URL_IP= 43 | ``` 44 | 45 | ```URL0_SAN``` defines a designation for Traefik to route based on a http request for an address. ```URL0``` is simply the first URL to route ie ```traefik.site.local``` , and ```URL_IP``` is the IP address for routing as well ie ```192.168.1.12```. 46 | 47 | When a request hits traefik at ```traefik.site.local``` traefik will route to the service identified in the docker-compose file label. 48 | 49 | Refer to the docker-compose.yaml file labels section: ```- "traefik.http.routers.api.rule=Host(`${URL0_SAN}`)"``` 50 | 51 | Remember .env files use a simple key-value pair and docker-compose will pull the value from the key associated with ```$``` or ```${key}```. 52 | 53 | ## Providers 54 | 55 | ### Docker 56 | 57 | Of course we're using docker as a provider here. This means Traefik is assigned read-only access to the docker socket on the server. Here it'll watch for new containers and using labels we can define parameters for proxying. 58 | 59 | Some things to note: 60 | - We Set Docker to the "traefiknet" network created outside of the compose file 61 | - ``` docker create network traefiknet ``` 62 | - Traefik is set to not automatically route to containers. 63 | - We have to enable this by by using ``` traefik.enable=true ``` label . 64 | 65 | ### File 66 | We are setting this up for the future. The docker provider looks for things "dynamically" or at runtime of the container. The file provider gives us the option to set configurations that are not able to be set dynamically. 67 | 68 | These do not always work however, I've found. 69 | 70 | Once again though we've told Traefik to watch the yaml file we define. 71 | -------------------------------------------------------------------------------- /unifi-controller/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | unifi: 5 | image: linuxserver/unifi-controller:arm32v7-latest 6 | container_name: unifi-controller 7 | hostname: unifi 8 | networks: 9 | - traefiknet 10 | environment: 11 | - PUID=1000 12 | - PGID=1000 13 | - MEM_LIMIT=1024M #optional 14 | volumes: 15 | - ./data:/config 16 | ports: 17 | - 3478:3478/udp # STUN 18 | - 10001:10001/udp # port for device discovery 19 | - 8080:8080 # device communication 20 | - 8081:8081 21 | - 8443:8443 # gui in browser for testing 22 | - 8843:8843 23 | - 8880:8880 24 | - 6789:6789 # speed test 25 | restart: always 26 | labels: 27 | - "traefik.enable=true" 28 | - "traefik.http.routers.unifi.rule=Host(`${URL0_SAN}`)" 29 | - "traefik.http.routers.unifi.entrypoints=websecure" 30 | #- "traefik.http.routers.unifi.service=unifi@docker" 31 | - "traefik.http.routers.unifi.tls=true" 32 | - "traefik.http.routers.unifi.tls.certresolver=mydnschallenge" 33 | #- "traefik.http.routers.unifi.middlewares=unifiproxy" 34 | - "traefik.http.services.unifi.loadbalancer.server.scheme=https" 35 | - "traefik.http.services.unifi.loadbalancer.server.port=8443" 36 | #- "traefik.http.services.unifi.loadbalancer.passhostheader=true" 37 | 38 | #- "traefik.http.middlewares.unifiproxy.headers.accesscontrolallowcredentials=true" 39 | #- "traefik.http.middlewares.unifiproxy.headers.accesscontrolexposeheaders=Access-Control-Allow-Origin,Access-Control-Allow-Credentials" 40 | #- "traefik.http.middlewares.unifiproxy.headers.addvaryheader=true" 41 | #- "traefik.http.middlewares.unifiproxy.headers.framedeny=true" 42 | #- "traefik.http.middlewares.unifiproxy.headers.sslredirect=true" 43 | #- "traefik.http.middlewares.unifiproxy.headers.browserxssfilter=true" 44 | #- "traefik.http.middlewares.unifiproxy.headers.sslhost=${URL0_SAN}" 45 | #- "traefik.http.middlewares.unifiproxy.headers.stsseconds=315360000" 46 | #- "traefik.http.middlewares.unifiproxy.headers.stsincludesubdomains=true" 47 | #- "traefik.http.middlewares.unifiproxy.headers.stspreload=true" 48 | #- "traefik.http.middlewares.unifiproxy.headers.contenttypenosniff=true" 49 | #- "traefik.http.middlewares.unifiproxy.headers.sslforcehost=true" 50 | 51 | networks: 52 | traefiknet: 53 | external: true -------------------------------------------------------------------------------- /unifi-controller/readme.md: -------------------------------------------------------------------------------- 1 | # Unifi-Controller 2 | 3 | Create data folder 4 | Create .env with URL for controller --------------------------------------------------------------------------------