├── .github └── workflows │ ├── codeql.yml │ └── devskim.yml ├── ASUS Router ├── README.MD └── wgclient-start ├── GL.iNet └── README.md ├── Pictures ├── home_net.jpg ├── npm.jpg ├── smart_home.pptx ├── start_page.jpg └── travel_net.jpg ├── README.md ├── SECURITY.md ├── SynologyNAS ├── README.md └── cp210x.ko ├── docker ├── README.MD ├── acme.sh │ └── README.md ├── adguard │ └── README.md ├── caddy │ ├── Dockerfile │ └── README.md ├── esphome │ └── README.md ├── home assistant │ └── README.md ├── homer │ ├── README.md │ └── tools.zip ├── nginx proxy manager │ └── README.md ├── pi-hole │ └── README.md ├── plex │ └── README.md ├── radarr │ └── README.MD ├── transmission │ └── README.md ├── vaultwarden │ └── README.md └── zigbee2mqtt │ └── README.md ├── secrets.py ├── telegrambot ├── mytelegrambot.py └── torrent_watcher.py └── yeelight ├── Yeelight_Inter-Operation_Spec.pdf └── yeelight.py /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '22 16 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | with: 74 | category: "/language:${{matrix.language}}" 75 | -------------------------------------------------------------------------------- /.github/workflows/devskim.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: DevSkim 7 | 8 | on: 9 | push: 10 | branches: [ "master" ] 11 | pull_request: 12 | branches: [ "master" ] 13 | schedule: 14 | - cron: '28 14 * * 6' 15 | 16 | jobs: 17 | lint: 18 | name: DevSkim 19 | runs-on: ubuntu-20.04 20 | permissions: 21 | actions: read 22 | contents: read 23 | security-events: write 24 | steps: 25 | - name: Checkout code 26 | uses: actions/checkout@v3 27 | 28 | - name: Run DevSkim scanner 29 | uses: microsoft/DevSkim-Action@v1 30 | 31 | - name: Upload DevSkim scan results to GitHub Security tab 32 | uses: github/codeql-action/upload-sarif@v2 33 | with: 34 | sarif_file: devskim-results.sarif 35 | -------------------------------------------------------------------------------- /ASUS Router/README.MD: -------------------------------------------------------------------------------- 1 | # ASUS router hacks (Merlin FW) 2 | ASUS builds nice routers. Best hardware and worst software.. If you really want a good router - check gl.inet. 3 | # DPI bypass 4 | copy wgclient-start file to /jffs/scripts directory. 5 | Everytime Wireguard client connection is established a chunks of random data are sent to fool the DPI. This helps to mask the WireGuard signature, but this approach will not work if DPI is set to block "unknown" traffic. 6 | 7 | # Get interface speed 8 | ``` 9 | ethctl eth0 media-type 10 | ``` 11 | 12 | # Free NVRAM space 13 | Some old ASUS routers with a new firmware may have a "no free space" NVRAM problem. Best way to clean NVRAM is to factory reset the device. If that's not possible - use this. 14 | Script below will remove empty NVRAM parameters (e.g., "var="). Will clear some memory, looks harmless, but *MAY ACTUALLY BREAK THINGS*! 15 | So backup NVRAM first with ```nvram dump > backup.txt``` 16 | ```bash 17 | for line in `nvram show | grep ^[^=]*=$ `; do var=${line%*=}; nvram unset $var; done; nvram commit 18 | ``` 19 | # Super Power! 20 | Change router's country to unlock full power and all wifi channels. 21 | Be carefull. In this mode with auto wifi channel selection router may jump to the wifi channel, not available in your country. Clients will not be able to see or use it. Use manual channel assigment if needed. 22 | 23 | How to pick a good wifi channel. 24 | 1. run Inssider (PC) or Wifiman (Android). 25 | 2. find the least used channel 26 | 3. check [wiki page](https://en.wikipedia.org/wiki/List_of_WLAN_channels) to make sure that this channel has 160Mhz band 27 | 28 | ```bash 29 | # IMPORTANT! BACKUP NVRAM FIRST! 30 | # nvram dump > dump.txt 31 | 32 | # Use those commands to get the current TX power. 33 | # wl txpwr 34 | # wl txpwr_target_max 35 | 36 | # Per interface (depends on your router. This one is for GT-AXE16000) 37 | # wl -i eth7 txpwr_adj_est 38 | # wl -i eth8 txpwr_adj_est 39 | # wl -i eth9 txpwr_adj_est 40 | # wl -i eth10 txpwr_adj_est 41 | 42 | # I have 4 bands (AXE16000) -> I need to set country 4 times. You may have 2 or 3 bands -> wl3, wl2 may not needed. Check existing NVRAM dump and adjust accordingly 43 | nvram set 0:ccode=#a 44 | nvram set 0:regrev=0 45 | nvram set 1:ccode=#a 46 | nvram set 1:regrev=0 47 | nvram set 2:ccode=#a 48 | nvram set 2:regrev=0 49 | nvram set 3:ccode=#a 50 | nvram set 3:regrev=0 51 | nvram set 4:ccode=#a 52 | nvram set 4:regrev=0 53 | nvram set location_code=#a 54 | nvram set wl_country_code=#a 55 | nvram set wl_country_rev=0 56 | nvram set wl0_country_abbrev_override=US 57 | nvram set wl0_country_code=#a 58 | nvram set wl0_country_rev=0 59 | nvram set wl1_country_abbrev_override=US 60 | nvram set wl1_country_code=#a 61 | nvram set wl1_country_rev=0 62 | nvram set wl2_country_abbrev_override=US 63 | nvram set wl2_country_code=#a 64 | nvram set wl2_country_rev=0 65 | nvram set wl3_country_abbrev_override=US 66 | nvram set wl3_country_code=#a 67 | nvram set wl3_country_rev=0 68 | nvram commit 69 | ``` 70 | 71 | # Get client specific connection details 72 | Run this to get the list of clients per interface ```wl -i eth7 assoclist```. Pick one and run this ```wl -i eth7 sta_info MAC ADDRESS OF CLIENT``` 73 | 74 | # Site-to-site VPN between 2 Asus routers. 75 | On "Master router" start OpenVPN server. "Master router" must have VPN port available from Internet. "Slave router" may have local-only IP. 76 | Same VPN connection will be used for both site-to-site and regular VPN. 77 | 78 | Master router local IP: A.A.A.0/24 (pls change to your own range) 79 | 80 | Slave router local IP: B.B.B.0/24 81 | 82 | Master router VPN IP: VPN.VPN.VPN.0/24 83 | 84 | 1. Generate proper certs for different users - https://github.com/RMerl/asuswrt-merlin.ng/wiki/Generating-OpenVPN-keys-using-Easy-RSA 85 | 86 | Or see the video here: 87 | 88 | https://www.youtube.com/watch?v=cHaD-Bofj9A 89 | 90 | .. and create few certs for multiple users. User1 will be used solely for Slave router connection. It will have a dedicated routing rule attached to it so all hosts from Master router's LAN can access all systems in Slave router's LAN and vise versa. User2 and User3 will be just normal users. 91 | 92 | 2. In OpenVPN server general settings set "Both" to access both LAN and Internet. 93 | 3. In OpenVPN advanced settings: 94 | 95 | Manage Client-Specific Options - Yes 96 | 97 | Allow Client <-> Client - No 98 | 99 | Allow only specified clients - No 100 | 101 | Add new entry into "Allowed clients" list: 102 | 103 | User1 B.B.B.0 255.255.255.0 Push=Yes 104 | 105 | 4. Go to Slave router. Add new OpenVPN client and upload the .ovpn file generated for User1. 106 | 107 | - Create NAT on tunnel - Yes 108 | - Inbound Firewall - Allow 109 | - Redirect Internet traffic through tunnel - "VPN Director" 110 | 111 | 5. Slave router, go to "VPN Director" tab. 112 | 113 | Add new rule: 114 | 115 | Some_name, Local IP = B.B.B.0/24, Remote IP = A.A.A.0/24, iface=OVPN1 116 | 117 | For mass adding VPN director rule see "Mass adding VPN Director rules" section below 118 | 119 | 6. done! Check Satus page on Master router. 120 | 121 | # Mass adding VPN Director rules 122 | If you need to redirect traffic to YouTube, for example, via your VPN, do the following. 123 | 124 | Step 1. Get the list of YouTube IPs from here https://rockblack.su/vpn/dopolnitelno/diapazon-ip-adresov 125 | 126 | Step 2. Create a script and run it. 127 | ```bash 128 | #!/bin/sh 129 | 130 | #Add existing rules here. Use your LAN IP instead of 192.168.7.0/24! 131 | rulelist='<1>OFFICE_LAN>192.168.7.0/24>10.0.1.0/24>OVPN1' 132 | n=1 133 | 134 | # add ip ranges here. Max 199 rules! 135 | list="188.114.0.0/16, 172.64.0.0/16, 104.18.0.0/16, 64.233.0.0/16, 8.8.4.0/24, 8.8.8.0/24, 8.34.0.0/16, 8.35.0.0/16, 23.236.0.0/16, 23.251.0.0/16, 34.0.0.0/10, 35.184.0.0/13, 35.192.0.0/14, 35.196.0.0/15" 136 | 137 | # Set IFS to handle both commas and spaces 138 | IFS=', ' 139 | 140 | # Loop through the list and construct the rulelist. Replace 192.168.7.0/24 with your LAN IP! 141 | for line in $list; do 142 | rulelist="${rulelist}<1>YouTube$((n++))>192.168.7.0/24>$line>OVPN1" 143 | done 144 | 145 | # Output the result 146 | echo "$rulelist" 147 | echo "Number of elements: $n" 148 | 149 | # apply the list 150 | echo "$rulelist" > /jffs/openvpn/vpndirector_rulelist 151 | ``` 152 | 153 | # YazFi + Yeelight + Home Assisstant 154 | !UPDATE I re-programmed all my Yeelights to use ESPHOME (soldering required!) 155 | 156 | So yeeligh smart lights only work using the LAN Mode if both sorce and destination IPs belong to the same subnet. 157 | I pushed all lights to YazFi guest wifi network. 158 | 159 | NAT is needed to keep the LAN control option. 160 | * login to your ASUS router 161 | * ```nano /jffs/addons/YazFi.d/userscripts.d/nat_to_guest.sh``` 162 | ```bash 163 | #!/bin/sh 164 | #iptables -I YazFiFORWARD -i wl0.1 -o br0 -d 10.0.1.5 -j ACCEPT 165 | iptables -t nat -A POSTROUTING -o wl0.1 -s 10.0.1.5 -j MASQUERADE 166 | ``` 167 | where ```10.0.1.5``` is Home Assistant IP 168 | 169 | # Asus Router Home assistant addon 170 | Install "ASUS Router" custom integration via HACS to your Home Assistant. 171 | You can add a parental contol switch to your HA now. 172 | Block internet access to entertaiment devices via "Parental Controls" tab on the router. Switch on parental controls through the Home Assistant when you need to disable internet for those devices. 173 | 174 | # Wifi Jail 175 | put your smart devices who need access to WiFi but not to Internet (e.g., soundbar) into the isolated part of the network. 176 | Add this to ```/jffs/scripts/firewall-start```: 177 | ``` 178 | iptables -I FORWARD -m iprange --src-range 10.0.1.231-10.0.1.254 -j REJECT 179 | ``` 180 | Now go to the management portal and assign a static IP from that IP range (do not forget to exclude it from the DHCP scope!). 181 | 182 | ## Remove the rule 183 | Remove the rule. Get the rule number. 184 | ```bash 185 | iptables -L FORWARD --line-numbers 186 | ``` 187 | Remove the specific rule (e.g., first one) 188 | ```bash 189 | iptables -D FORWARD 1 190 | ``` 191 | ```bash 192 | route del -net 192.168.7.0 netmask 255.255.255.0 dev tun21 193 | ``` 194 | 195 | # DynDNS for ASUS with Gandi and Cloudflare 196 | [Merlin Wiki](https://github.com/RMerl/asuswrt-merlin/wiki/Custom-DDNS/a5d71302d2e976c38d72d23a8ccdc13c1c3b6449) 197 | 198 | ```bash 199 | #!/bin/bash 200 | 201 | APIKEY_GANDI="123123123123" 202 | APIKEY_CLOUDFLARE="12312312312312312" 203 | 204 | #IP=$(ip route get 1 | awk '{print $NF;exit}') 205 | # if external IP is not known to router. More here https://openwrt.org/docs/guide-user/services/ddns/client#detecting_public_ip 206 | IP="$(curl -fs4 http://checkip.amazonaws.com)" 207 | 208 | # CloudFlare 209 | ZONE_ID="aaaaaa" # get it from your Cloudflare dashboard 210 | RECORD_ID="bbbbbbb" # curl ... "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" | json_pp 211 | DOMAIN="1.com" 212 | status=$(curl -s -X PUT -H "Content-Type: application/json" \ 213 | -H "Authorization: Bearer ${APIKEY_CLOUDFLARE}" \ 214 | --data "{\"type\":\"A\",\"name\":\"${DOMAIN}\",\"content\":\"${IP}\",\"ttl\":1,\"proxied\":false}" \ 215 | "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}") 216 | logger -s -t ddns "Domain $domain reports $status" 217 | 218 | # Gandi 219 | gandi_dns_update() { 220 | for sub in $subdomains 221 | do 222 | status=$(curl -s -X PUT -H "Content-Type: application/json" \ 223 | -H "X-Api-Key: ${APIKEY_GANDI}" \ 224 | -d "{\"rrset_ttl\": 10800, \"rrset_values\": [\"${IP}\"]}" \ 225 | "https://dns.api.gandi.net/api/v5/domains/${domain}/records/${sub}/A") 226 | logger -s -t ddns "Domain $sub.$domain reports $status" 227 | done 228 | } 229 | 230 | domain="2.com" 231 | subdomains="www mail post web" 232 | gandi_dns_update 233 | 234 | 235 | if [ $? -eq 0 ]; then 236 | /sbin/ddns_custom_updated 1 237 | else 238 | /sbin/ddns_custom_updated 0 239 | fi 240 | 241 | # Update NEXT DNS and AdGuard DNS 242 | curl -fs -o /dev/null "https://link-ip.nextdns.io/aaa/bbbb" 243 | curl -fs -o /dev/null "https://linkip.adguard-dns.com/linkip/asdasd/asdasd" 244 | ``` 245 | DDNS with Gandi and wget instead of curl (may be usefull for old ASUS routers) 246 | ```bash 247 | #!/bin/sh 248 | 249 | IP=$(ip route get 1 | awk '{print $NF;exit}') 250 | DOMAIN="example.com" 251 | SUBDOMAIN="vpn" 252 | 253 | wget --method=PUT --header="Content-Type: application/json" --header="X-Api-Key: " --body-data='{"rrset_ttl": 10800, "rrset_values": ["'${IP}'"]}' https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records/${SUBDOMAIN}/A 254 | 255 | # for Burp proxy add this to the end 256 | # -e use_proxy=yes -e http_proxy=127.0.0.1:8080 -e https_proxy=127.0.0.1:8080 --no-check-certificate 257 | ``` 258 | 259 | # clear DNS leases 260 | ```killall dnsmasq; rm /var/lib/misc/dnsmasq.leases; service restart_dnsmasq``` 261 | -------------------------------------------------------------------------------- /ASUS Router/wgclient-start: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Set the number of times a random message would be sent 4 | NUM_MESSAGES_SENT=3 5 | 6 | # Random message generation params 7 | block_size=512 8 | block_count=5 9 | 10 | # Enable exit on error 11 | set -e 12 | 13 | # Function to generate a random number between 49152 and 65535 14 | generate_random_port() { 15 | awk -v min=49152 -v max=65535 'BEGIN { srand(); print int(min + rand() * (max - min + 1)) }' 16 | } 17 | 18 | # Function to generate a random message and send it 19 | send_random_message() { 20 | message=$(dd if=/dev/urandom bs=$block_size count=$block_count 2>/dev/null | tr -dc 'A-Za-z0-9') 21 | echo "$message" | socat - UDP-SENDTO:"$wg_server:$wg_port",sourceport="$l_port" 22 | logger -t WireGuardClient -p user.notice "Message sent to WG server $wg_server:$wg_port from client's port $l_port" 23 | sleep 1 24 | } 25 | 26 | interface="wgc$1" 27 | sleep 3 28 | # Log the start of the script 29 | logger -t WireGuardClient -p user.notice "Starting junk-udp-hack script" 30 | logger -t WireGuardClient -p user.notice "Processing WG interface - $interface" 31 | 32 | # Retrieve the server and port 33 | wg_endpoint=$(wg show "$interface" endpoints 2>/dev/null || echo "") 34 | if [ -z "$wg_endpoint" ]; then 35 | logger -s -t WireGuardClient -p user.err "Unable to retrieve endpoint for interface $interface" >&2 36 | exit 1 37 | fi 38 | 39 | wg_server=$(echo "$wg_endpoint" | awk '{print $2}' | cut -d':' -f1 2>/dev/null || echo "") 40 | wg_port=$(echo "$wg_endpoint" | awk '{print $2}' | cut -d':' -f2 2>/dev/null || echo "") 41 | 42 | if [ -z "$wg_server" ] || [ -z "$wg_port" ]; then 43 | logger -s -t WireGuardClient -p user.err "Unable to extract server or port for interface $interface" >&2 44 | exit 1 45 | fi 46 | 47 | l_port=$(generate_random_port) 48 | while netstat -an | grep -qE '(^|[^0-9])'"$l_port"'([^0-9]|$)'; do 49 | logger -t WireGuardClient -p user.warn "Port $l_port is already in use. Generating new one" 50 | sleep 1 51 | l_port=$(generate_random_port) 52 | done 53 | 54 | # Send random messages specified number of times 55 | i=1 56 | while [ "$i" -le "$NUM_MESSAGES_SENT" ]; do 57 | send_random_message 58 | i=$((i + 1)) 59 | done 60 | 61 | # Update the WireGuard interface with the new listen port 62 | wg set "$interface" listen-port "$l_port" 63 | 64 | logger -t WireGuardClient -p user.notice "Done" 65 | -------------------------------------------------------------------------------- /GL.iNet/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | GL.iNet [GL-AXT1800](https://www.gl-inet.com/products/gl-axt1800/) router tunning 3 | 4 | ## VLAN configuration (for T-Mobile internet) 5 | - SSH to GL-AXT1800 6 | - edit ```vi /etc/config/network```: 7 | 1. replace ```option device 'eth0'``` with ```option device 'eth0.300'``` for WAN interface (optionally for WAN6 too) 8 | 2. add switch to the end 9 | ```bash 10 | config switch_vlan 11 | option device 'switch0' 12 | option vlan '1' 13 | option description 'WAN_t-mobile' 14 | option ports '1t 5t' 15 | ``` 16 | 3. (optional) google how to exit VIM... google again how to save and exit... 17 | 4. restart network: ```/etc/init.d/network restart``` 18 | -------------------------------------------------------------------------------- /Pictures/home_net.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/Pictures/home_net.jpg -------------------------------------------------------------------------------- /Pictures/npm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/Pictures/npm.jpg -------------------------------------------------------------------------------- /Pictures/smart_home.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/Pictures/smart_home.pptx -------------------------------------------------------------------------------- /Pictures/start_page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/Pictures/start_page.jpg -------------------------------------------------------------------------------- /Pictures/travel_net.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/Pictures/travel_net.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # "Живи с умом!" (c) Смешарики 2 | ## Железо 3 | ![Схема сети](Pictures/home_net.jpg) 4 | 5 | Основа моего умного дома - NAS Synology DS218+, в который я вставил 2 планки старой ноутбучной памяти, тем самым, нарастив её до 16 Гб. В НАСе стоят два Enterpise жестких диска (WD RED, Seagate IronWolf Pro) в режиме зеркала (RAID 0). 6 | 7 | НАС - это полноценный домашний сервер. Хранение файлов - только одна из многих его функций. В будущем я (наверное) заменю жесткие диски на SSD чтобы уменьшить шум. Чем НАС лучше одноплатника или NUCа? Софтом для телефона, удобной вебмордой, энергопотреблением. Чем хуже? Нет места для карт расширения. 8 | 9 | На роутеры АСУС существует кастомная прошивка от merlin. Туда же через утилиту amtm можно установить аддон YazFi, который немного расширяет управление гостевыми сетями и устройствами. Подробней смотри в папке [ASUS Router](ASUS%20Router/README.MD) 10 | 11 | Когда мы надолго куда-нибудь уезжаем, я беру с собой "умный дом лайт" 12 | ![Схема сети для путешествий](Pictures/travel_net.jpg) 13 | 14 | Воткнуть свой роутер в сеть отеля - это удобно. Не нужно подключать планшеты/телефоны/ноутбуки к новому вайфаю, т.к. на роутере настроена домашняя сеть. Быстрый вайфай + встроенный ВПН до дома чтобы, например, скачать кино. Мини Алиса (с USB-c!) и умная розетка позволяют выключать свет не вставая с дивана (супер опция для тех, кто проходил весь день). 15 | Модем Huawei, даже прошитый хакнутой прошивкой - опция так себе. Как-нибудь проапгрейжу до внешнего кейса + miniPCI WAN карты (на 4pda отличная тема про [это](https://4pda.to/forum/index.php?showtopic=994474)). 16 | Роутеры gl.inet - прям отличные устройства, если нужна мобильность! Удобный интерфейс с резалкой рекламы (хотя я всё равно использую [NextDNS](https://nextdns.io)) + OpenWRT внутри. 17 | Amazon Fire TV 4k Pro - лучший стик, на распродаже оч дёшев. Можно убрать всё гавно от Амазона (см @amazonfiretvrus в телеге), поставить [FLauncher](https://gitlab.com/flauncher/flauncher), [SmartTubeNext](https://github.com/yuliskov/SmartTubeNext), [AerialView](https://github.com/theothernt/AerialViews), NUM - No UI Movies и Kodi 18 | 19 | ## Софт 20 | ![Стартовая страница Homer](Pictures/start_page.jpg) 21 | 22 | Вот так выглядит домашний веб сервер Homer (ниже про него подробней) 23 | На НАСе крутятся: 24 | - Софт Synology 25 | - Synology Photos - отличный каталогизатор семейных фотографий. Я немного причесываю семейный архив [скриптами](https://github.com/ageev/others) время от времени 26 | - HyperBackup - универсальный бэкапер. Работает практически со всеми облаками и имеет очень гибкие политики бэкапа. Я бэкаплю много и часто, в основном, в Azure, предварительно всё хорошенько зашифровав 27 | - CloudSync - синхронизирует локальную папку на НАСе с каким-нибудь облаком 28 | - Virtual Machine Manager - тут у меня крутится VitrualDSM (виртуальный НАС). Раньше была ещё Убунту, но сейчас всё в докере 29 | - Surveillance Station - отличный менеджер камер наблюдения 30 | - НАС шарит папку Media со всей домашней сетью, где лежат скачанные фильмы 31 | - Python скрипты, которые я запускаю через планировщик Synology 32 | - docker - тут всё самое основное 33 | - [adguard](https://github.com/ageev/SmartHouse/tree/master/adguard) - продвинутая резалка рекламы. Лучше чем [pihole](https://github.com/ageev/SmartHouse/tree/master/pi-hole) 34 | - [caddy](https://github.com/ageev/SmartHouse/tree/master/docker/caddy) - вебсервер с поддержкой ACME (автоматическая выдача HTTPS сертификатов) - *заменил на Nginx Proxy Manager + acme.sh* 35 | - [esphome](https://github.com/ageev/SmartHouse/tree/master/docker/esphome) - генератор прошивок и дэшборд для ESP32 (дешевый чип с поддержкой Wi-Fi и BLE). Позволяет перепрошивать всякие Tuya Smart и прочии девайсы для интеграции с Home Assistant 36 | - *home-assistant* (HA, homeass, хомяк)- универсальный интеграционный сервис умного дома. За счёт огромного количества аддонов позволяет связывать в единую систему очень разные компоненты. Например, Яндекс Станцию и Телеграм, датчики IKEA и вентилятор Xiaomi. Примеры автоматизаций внутри 37 | - [homer](https://github.com/ageev/SmartHome/tree/master/docker/homer) - простой вебсервер, на котором удобно сделать стартовую страницу умного дома. Скриншот из Гомера вы видите выше. Когда мне нужно что-то открыть в домашней сети - я использую стартовую страницу Гомера 38 | - [transmission](https://github.com/ageev/SmartHome/tree/master/docker/transmission) - качалка торрентов. Выбрал её потому что у нее самая удобная интеграция с HA. Использую с плагином для браузера Torrent Control - позволяет скачивать всё сразу на НАС 39 | - [acme.sh](https://github.com/ageev/SmartHouse/tree/master/acme.sh) - позволяет автоматизировать получение HTTPS сертификатов, посылает уведомоления в телегу, может закидывать обновленный сертификат прямо в DSM 40 | - [vaultwarden](https://github.com/ageev/SmartHouse/tree/master/vaultwarden) - форк BitWarden - очень хороший менеджер паролей с клиентами под все платформы 41 | - [nginx proxy manager](https://github.com/ageev/SmartHouse/tree/master/Nginx%20Proxy%20Manager) - единое окно (ну почти) для всех внутренних веб-порталов. Позволяет сделать "зеленый замочек" (HTTP -> HTTPS) там, где его отродясь не было. Один минус NGM - нужно искать уникальный кастомный прокси конфиг под каждое приложение. С Traefik такой проблемы нет. Надо сравнить 42 | - mariadb - база данных. Нужна для Nginx Proxy Manager 43 | - [mosquitto](https://github.com/ageev/SmartHome/tree/master/docker/zigbee2mqtt) - MQTT брокер. Нужен для zigbee2mqtt. Работает с очередью запросов к ZigBee устройствам для умного дома 44 | - [zigbee2mqtt](https://github.com/ageev/SmartHome/tree/master/docker/zigbee2mqtt) - позволяет интегрировать Zigbee устройства умного дома с home-assistant. Работает с USB стиком Sonoff Zigbee 3.0, воткнутым в USB порт НАСа. В целом, можно было использовать и встроенный в Home Assistant zigbee модуль 45 | - [plex](https://github.com/ageev/SmartHome/tree/master/docker/plex) - каталогизатор видео. Позволяет на лету транскодировать видеопотоки (если железо позволяет. DS218+ позволяет) под различные разрешения и устройства. Ну то есть можно стримить мультики на детские планшеты, и они сами могут выбирать, что смотреть. Пользуюсь редко. В основном, фильмы смотрим через NFS шары и Kodi 46 | - prowlarr - интегратор торрент треккеров. Даешь ему команду найти торрент - он ищет сразу по всем твоим любимым треккерам. Используется в связке с radarr 47 | - radarr - менеджер домашней видеобиблиотеки (тут писал про него подробнее https://habr.com/ru/post/505814/). Работает как-то так: 48 | - Добавляешь фильм в Watchlist на IMDB.com 49 | - лист синхронизируется с Radarr 50 | - Radarr даёт команду Prowlarr найти все раздачи с этим фильмом 51 | - Radarr фильтрует все раздачи в соответствии с задаными фильтрами (например, качество не хуже HD, английская или русская дорожка. Не менее 3х сидеров) 52 | - Если после фильтрации осталась нужная раздача, Radarr дает команду Transmission скачать нужный торрент 53 | - Кладёт раздачу в папочку Movies на НАСе, посылает уведомление через телегу 54 | - Если вдруг вышла раздача лучшего качества - скачивает её пока максимальное качество не достигнуто 55 | - torrserver - сервер для NUM. В путешествиях я вожу с собой Amazon Fire TV стик. Воткнул в телевизор в отеле и можно смотреть свой Netflix. NUM в связке с домашним torrserver позволяет смотреть еще и торренты в странах, где за это наказывают 56 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Detected the vulnerability? Open an issue! 6 | -------------------------------------------------------------------------------- /SynologyNAS/README.md: -------------------------------------------------------------------------------- 1 | # Send Synology NAS notifications to Telegram group using webhooks in DSM7 2 | ## Prerequisites 3 | 1. Telegram bot token 4 | 2. Group ChatID 5 | 3. DSM7 6 | 7 | ## Web hook push notifications in DSM7 8 | Those are broken. I created one manually and then just edited the file directly 9 | ```bash 10 | sudo vi /usr/syno/etc/synowebhook.conf 11 | ``` 12 | 13 | Here is the config, you probably need to transform it to oneliner 14 | ```json 15 | {"Telegram Bot": 16 | {"needssl":true, 17 | "port":443, 18 | "prefix":"_A new system event occurred on your %HOSTNAME% on_ *%DATE%* _at_ *%TIME%*.", 19 | "req_method":"get", 20 | "req_header":"{}", 21 | "req_param":"{}", 22 | "sepchar":" ", 23 | "template":"https://api.telegram.org/bot/sendMessage?chat_id=&parse_mode=Markdown&text=@@PREFIX@@%0A@@TEXT@@", 24 | "type":"custom", 25 | "url":"" 26 | } 27 | } 28 | ``` 29 | save it, test it via GUI. 30 | 31 | @@FULLTEXT@@ == @@PREFIX@@%0A@@TEXT@@ 32 | 33 | 34 | to fully enjoy the benefits you need to instal the Synology Log center. In "Notification" menu you can set the fillter using words "signed in" (for web) and "logged in" (for SSH). This will generate telegram messages when someone is logged in on your NAS 35 | 36 | 37 | # USB ZigBee donlge on DSM 7 (Synology) 38 | ## Sonoff Zigbee 3.0 Dongle Plus 39 | 1. get your CPU architecture. Run ```uname -a``` and note the CPU codename. Example: ```Linux DS218 4.4.180+ #42218 SMP Mon Oct 18 19:17:56 CST 2021 x86_64 GNU/Linux synology_apollolake_218+``` -> apollolake 40 | 41 | 2. add a task to the Scheduler. Adjust the URL to match the CPU architecture. Run at boot-up as a root 42 | ```bash 43 | if [ ! -f /lib/modules/cp210x.ko ]; then 44 | cd /lib/modules 45 | wget https://github.com/robertklep/dsm7-usb-serial-drivers/raw/main/modules/apollolake/dsm-7.2/cp210x.ko 46 | fi 47 | 48 | modprobe usbserial 49 | modprobe ftdi_sio 50 | modprobe cdc-acm 51 | insmod /lib/modules/cp210x.ko 52 | chmod 666 /dev/ttyUSB0 53 | ``` 54 | Some comments here. After DSM upgrade the ```cp210x.io``` file will disappear. The boot-up script will catch this and redownload it. 55 | 56 | If your ZigBee works slow, just re-plug the Sonoff stick! 57 | 58 | ## Route to docker 59 | ```bash 60 | ip link add macvlan0 link ovs_eth0 type macvlan mode bridge 61 | ip addr add 10.0.1.8/29 dev macvlan0 62 | ip link set macvlan0 up 63 | ``` 64 | ## Sync Radarr every 5 min 65 | Radarr can be nicely integrated with IMDB list. So every time you add anything to your IMDB watchlist - Radarr will catch it and lanch the download. 66 | BUT because Radarr uses it's own servers for that they've set up a throttling mechanism - you can check all lists minimum every 7 hours... 67 | To bypass this check you can trigger a "list update" task manually in Radarr GUI. I use Burp Suite to catch such requests and export them to curl & set a synology task scheduler to run those every 5 min. 68 | ```bash 69 | curl -i -s -k -X $'POST' \ 70 | -H $'Host: ds.local:7878' -H $'Content-Type: application/json' -H $'X-Api-Key: ' -H $'Referer: http://ds.local:7878/system/tasks' \ 71 | --data-binary $'{\"name\":\"ImportListSync\"}' \ 72 | $'http://:7878/api/v3/command' 73 | ``` 74 | -------------------------------------------------------------------------------- /SynologyNAS/cp210x.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/SynologyNAS/cp210x.ko -------------------------------------------------------------------------------- /docker/README.MD: -------------------------------------------------------------------------------- 1 | ## Blocking internet access FROM docker containers 2 | Containers should not go to Internet unless absolutely must 3 | 1. Create two separate Docker networks in your ```docker-compose.yml``` file 4 | ```bash 5 | networks: 6 | internet_allowed: 7 | driver: bridge 8 | ipam: 9 | config: 10 | - subnet: 172.18.0.0/16 11 | internet_blocked: 12 | driver: bridge 13 | ipam: 14 | config: 15 | - subnet: 172.19.0.0/16 16 | ``` 17 | 2. For those containers who doesnt need access to internet add this: 18 | ```bash 19 | services: 20 | container_name 21 | ... 22 | networks: 23 | - internet_blocked 24 | ``` 25 | 3. Go to Synology task scheduler and create a root task triggered after boot: 26 | ```bash 27 | iptables -F DOCKER-USER 28 | iptables -A DOCKER-USER -s 172.19.0.0/16 -d 192.168.0.0/16 -j RETURN 29 | iptables -A DOCKER-USER -s 172.19.0.0/16 -d 172.16.0.0/12 -j RETURN 30 | iptables -A DOCKER-USER -s 172.19.0.0/16 -d 10.0.0.0/8 -j RETURN 31 | iptables -A DOCKER-USER -s 172.19.0.0/16 -j DROP 32 | iptables -A DOCKER-USER -j RETURN 33 | ``` 34 | 35 | View routes 36 | 37 | ```bash 38 | sudo iptables -L DOCKER-USER --line-numbers 39 | ``` 40 | 41 | Note: Synology's iptables doesnt support REJECT -> so I used DROP instead. REJECT is almost instant, while DROP cancels connection attempt after few seconds delay. 42 | -------------------------------------------------------------------------------- /docker/acme.sh/README.md: -------------------------------------------------------------------------------- 1 | # Acme.sh 2 | Это утилита для коммандной строки, позволяющая получать и обновлять HTTPS сертификаты. Её можно использовать и без докера, но с докером безопасней. 3 | 4 | Основные плюсы: 5 | - поддерживает DNS челленджи для ACME, то есть может работать без публикации ваших веб ресурсов наружу. DNS челенджи работают только через DNS API вашего регистратора. То есть можно получить сертификат, который будет использоваться исключительно в локальной сети 6 | - может пушить свежие сертификаты в Synology DSM. Таким образом решается проблема получения доверенного сертификата на DSM без публикации НАСа наружу 7 | - работает с телеграммом. Приятный бонус 8 | 9 | ## Пререквизиты 10 | 1. домен. Я использую домен, купленный Gandi.net. *acme.sh поддерживает не всех регистраторов!* 11 | 2. API токен. Нужно сгенерировать его в настройках вашего регистратора 12 | 3. Нужно создать несколько доменных имён в консоли регистратора, которые вы затем будете использовать уже внутри сети. Ну например ```dsm 10800 IN A 192.168.1.5```. Теперь URL ```dsm.mydomain.com``` указывает на ваш НАС. Естественно работать такой URL будет только внутри локальной сети 13 | 4. нужно вручную создать несколько папок на НАСе: ```/volume1/docker/acme/config``` и ```/volume1/docker/acme/key``` 14 | 5. заведите нового пользователя на НАСе: имя ```acme```, добавьте в группу админов (к сожалению, без этого никак). Можно и нужно лишить этого пользователя всех прав, кроме доступа к DSM 15 | 6. когда в этих папках acme.sh создаст ключи - приватный ключ будет лежать с урезанными правами доступа (ну понятно то почему). Однако чтобы работать с этим ключом из других контейнеров вам нужно будет модифицировать эти разрешения (зайти через SSH на НАС. Выполнить ```sudo chmod 777 /path/to/key/file```. ВНИМАНИЕ! эта команда разрешает доступ к ключу любому локальному юзеру на НАСе) 16 | 7. я везде получаю и использую wildcard сертификат (т.е. со свездочкой. *.domain.com). Это удобно, так как не раскрывает внутренние имена в certificate transparency feed'е 17 | 18 | ## docker-compose.yml 19 | ```yml 20 | ## install new versions 21 | # cd /volume1/docker 22 | # sudo docker-compose pull 23 | # sudo docker-compose up -d 24 | ## clean docker 25 | # sudo docker system prune -a 26 | ## rebuild containers 27 | # sudo docker-compose up -d --build 28 | 29 | --- 30 | version: "3.9" 31 | services: 32 | acme.sh: 33 | image: neilpang/acme.sh 34 | container_name: acme.sh 35 | environment: 36 | - PUID=1029 # CHANGE ME! 37 | - PGID=100 # CHANGE ME! 38 | - TZ=Europe/Zurich 39 | - GANDI_LIVEDNS_KEY= 40 | - TELEGRAM_BOT_APITOKEN= 41 | - TELEGRAM_BOT_CHATID= 42 | #SYNO Deploy hook 43 | - SYNO_Scheme=https 44 | - SYNO_Hostname=dsm.domain.com #NAS's address. CHANGE ME! 45 | - SYNO_Port="5001" 46 | - SYNO_Username=acme 47 | - SYNO_Password= # CHANGE ME! 48 | # - SYNO_DID= #copy did cookie parameter from browser's DSM admin session 49 | - SYNO_Certificate=*.domain.com # CHANGE ME! 50 | - SYNO_Create=1 51 | network_mode: host 52 | volumes: 53 | - /volume1/docker/acme/config:/acme.sh 54 | - /volume1/docker/acme/key:/key 55 | command: daemon 56 | restart: unless-stopped 57 | network_mode: "bridge" 58 | ``` 59 | 60 | после установки контейнера нужно выполнить ряд команд в консоли НАСа (замени domain.com на свой домен!): 61 | ``` 62 | sudo docker exec acme.sh acme.sh --register-account -m 63 | sudo docker exec acme.sh acme.sh --set-notify --notify-hook telegram 64 | sudo docker exec acme.sh acme.sh --issue -d *.domain.com -k 4096 -ak 4096 --dns dns_gandi_livedns --dnssleep 300 65 | sudo docker exec acme.sh acme.sh --deploy -d *.domain.com --deploy-hook synology_dsm --insecure 66 | ``` 67 | внутри контейнера есть cron job, который пробегается периодически по папкам в конфиге. Посмотреть его можно так: 68 | ``` 69 | sudo docker exec acme.sh crontab -l 70 | ``` 71 | 72 | # Ссылки 73 | 1. https://github.com/acmesh-official/acme.sh/wiki/deployhooks#20-deploy-the-certificate-to-synology-dsm 74 | -------------------------------------------------------------------------------- /docker/adguard/README.md: -------------------------------------------------------------------------------- 1 | # How to install ADGUARD HOME docker container on Synology NAS 2 | ## Adguard vs Pi-hole vs NextDNS 3 | I switched fully to Adguard now and here is why: 4 | 5 | Pros of Adguard 6 | - fast search 7 | - nice GUI 8 | - supports all the fancy stuff: DoH, DoT, QUIC (certificate is required) 9 | 10 | Pros of Pi-hole: 11 | - opensource & community driven 12 | 13 | Pros of NextDNS: 14 | - no CPU consumption (because it's a cloud) 15 | - very advanced solution 16 | 17 | # Step 1. Installation 18 | - adjust and copy the docker compose content to your docker compose file (e.g. to /volume1/docker/docker-compose.yml) 19 | - SSH to NAS 20 | - "cd /volume1/docker" 21 | - "sudo docker-compose up -d" 22 | 23 | docker-compose.yml 24 | ```yaml 25 | ## install new versions 26 | # cd /volume1/docker 27 | # sudo docker-compose pull 28 | # sudo docker-compose up -d 29 | ## clean docker 30 | # sudo docker system prune -a 31 | ## rebuild containers 32 | # sudo docker-compose up -d --build 33 | 34 | --- 35 | version: "3.9" 36 | services: 37 | 38 | adguard: 39 | image: adguard/adguardhome:latest 40 | container_name: adguard 41 | hostname: adguard 42 | user: 1029:100 #put your docker used ID (UID) and group ID (GID) here! 43 | domainname: local 44 | mac_address: 00:fa:c0:fa:c0:aa 45 | cap_add: 46 | - NET_ADMIN 47 | networks: 48 | macvlan_network: 49 | ipv4_address: 192.168.1.9 #ip of your adguard container. I choose 192.168.1.8/29 subnet for my macvlans 50 | dns: 51 | - 192.168.1.1 52 | - 1.1.1.1 53 | environment: 54 | - TZ=Europe/Amsterdam # your TZ 55 | volumes: 56 | - /volume1/docker/adguard/work:/opt/adguardhome/work 57 | - /volume1/docker/adguard/conf:/opt/adguardhome/conf 58 | - /volume1/docker/acme/config/:/opt/adguardhome/cert #this string is needed if you want to use ACME issued HTTPS cert 59 | restart: unless-stopped 60 | 61 | networks: 62 | macvlan_network: 63 | driver: macvlan 64 | enable_ipv6: false 65 | driver_opts: 66 | parent: ovs_eth0 67 | ipam: 68 | config: 69 | - subnet: 192.168.1.0/24 70 | gateway: 192.168.1.1 71 | ip_range: 192.168.1.8/29 72 | ``` 73 | 74 | 75 | # Step 2. Configuration 76 | I use all the default lists and this one: 77 | - https://abp.oisd.nl/ 78 | 79 | Custom blocking rules: 80 | ```bash 81 | ||graph.facebook.com^$important 82 | ||notifier-configs.airbrake.io^$important 83 | ||www.googleadservices.com^$important 84 | ||v10.events.data.microsoft.com^$important 85 | ||arcus-uswest.amazon.com^$important 86 | ||cdn.meta.ndmdhs.com^$important 87 | ||redirector.googlevideo.com^$important 88 | ||clck.yandex.net^$important 89 | ||in.appcenter.ms^$important 90 | ||mtalk.google.com^ 91 | ||pushserver.mfms.ru^$important 92 | ||xboxlive.com^$important 93 | ||dls.di.atlas.samsung.com^$important 94 | ||i.67yo.net^$important 95 | ||us.urcatwalkstar.com^$important 96 | ||client-telemetry.roblox.com^$important 97 | ||ephemeralcounters.api.roblox.com^$important 98 | ||alt2-mtalk.google.com^$important 99 | ``` 100 | # Step 3. Additional configurations 101 | You need to figure out this by your own, but here are few things I did: 102 | - Adjusted router's DHCP scope to serve Adguard IP as a primary DNS 103 | - NAS still uses static DNS. I don't want things to get broken if Adguard container is restarted 104 | - I still have Pi-hole on Raspberry Pi Zero W. That's my secondary DNS 105 | - My router redirects all DNS requests to Adguard, except requests from NAS, Adguard itself and Pi-hole (this is called DNSFilter in Asus routers with Merlin's firmware) 106 | - I've added all family devices to Adguard (Settings > Client Settings). For kid's tablets I've switched off all unneeded services (e.g. Amazon, ebay, OK.ru ....) 107 | - I've added some internal network devices to custom blocking rules (filters > custom rules). This is needed for the internal DNS resolution to work 108 | - I also have [ACME.SH](https://github.com/ageev/SmartHouse/tree/master/docker/acme.sh) container which handles HTTPS certificates. I have mounted the cert folder from ACME.SH to AdGuard (see docker-compose config above) and now use this cert to protect AdGuard also 109 | - I've added A record to my domain name, pointed to the local AdGuard IP (e.g. dns 10800 IN A 192.168.1.9). Now I can use dns.example.com url to access AdGuard locally 110 | 111 | ```bash 112 | #internal hosts 113 | 192.168.1.1 router.local 114 | 192.168.1.2 nas.local 115 | ``` 116 | ## Autoupdating docker 117 | I've switched off my autoupdate after few bugs, but here is how you can do it: 118 | - go to Task Scheduler 119 | - add a task to be run as root 120 | - paste this to "user-defined script" window: 121 | ```bash 122 | cd /volume1/docker/ 123 | docker-compose pull #get new versions 124 | docker-compose up -d #recreate containers 125 | docker system prune -a -f #clean docker 126 | ``` 127 | 128 | # Step 4. Adding proper route to docker's macvlan network adapter 129 | Docker's macvlan adapters are available for LAN users, but are not available for DSM/Docker users. Generaly speaking that's not an issue, but if you want, for example, to add adguard to your home-assistant container running on the same docker (like I did) you need this. 130 | 131 | Create a bootup task for root user (aka "user-defined scrip") in Synology tasks with this content: 132 | ```bash 133 | ip link add macvlan0 link ovs_eth0 type macvlan mode bridge 134 | ip addr add 192.168.1.8/29 dev macvlan0 135 | ip link set macvlan0 up 136 | ``` 137 | 138 | * 192.168.1.8/29 - IP range in my network dedicated to docker's macvlan. Make sure this range is excluded from the DHCP scope! 139 | * macvlan0 - new virtual network interface name 140 | * ovs_eth0 - Synology DSM network interface name 141 | -------------------------------------------------------------------------------- /docker/caddy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM caddy:builder AS builder 2 | RUN xcaddy build --with github.com/caddy-dns/gandi 3 | 4 | FROM caddy:latest 5 | COPY --from=builder /usr/bin/caddy /usr/bin/caddy -------------------------------------------------------------------------------- /docker/caddy/README.md: -------------------------------------------------------------------------------- 1 | # Caddy 2 | 3 | Caddy is a proxy server, which works with ACME. 4 | | :exclamation: Currently I replaced Caddy with [NGINX Proxy Manager](https://github.com/ageev/SmartHouse/tree/master/docker/nginx%20proxy%20manager) | 5 | |-----------------------------------------| 6 | 7 | # Installation 8 | 9 | Caddy's docker doesnt support Gandi DNS API out-of-the-box, so I need to compile it 10 | 11 | 1. Create the file ```/volume1/docker/Dockerfile``` 12 | ``` 13 | FROM caddy:builder AS builder 14 | RUN xcaddy build --with github.com/caddy-dns/gandi 15 | 16 | FROM caddy:latest 17 | COPY --from=builder /usr/bin/caddy /usr/bin/caddy 18 | ``` 19 | 2. Create directories 20 | ``` 21 | /volume1/docker/caddy 22 | /volume1/docker/caddy/data 23 | /volume1/docker/caddy/config 24 | /volume1/docker/caddy/log 25 | ``` 26 | 27 | 3. create a file ```/volume1/docker/caddy/caddyfile```. This file has some variables like DOMAIN or EMAIL, which are defined later in the docker-compose file 28 | 29 | | :exclamation: Config below is relevan for [VaultWarden](https://github.com/ageev/SmartHouse/tree/master/docker/vaultwarden) | 30 | |-----------| 31 | ``` 32 | { 33 | #default http port needs to be changed or Caddy will not start if it's already in use. Even if you don't use HTTP 34 | http_port 4080 35 | acme_dns gandi {$GANDI_API_TOKEN} 36 | #try to uncomment this if caddy goes to ZeroSSL or another servers for the cert and you get errors. DNS challenge is not supported for every endpoint 37 | #acme_ca https://acme-v02.api.letsencrypt.org/directory 38 | email {$EMAIL} 39 | } 40 | 41 | # start HTTPS on 4443 42 | {$DOMAIN}:4443 { 43 | tls { 44 | dns gandi {$GANDI_API_TOKEN} 45 | } 46 | 47 | log { 48 | output file {$LOG_FILE} 49 | level debug 50 | } 51 | 52 | encode zstd gzip 53 | 54 | #connect to vaultwarden on 8088 55 | reverse_proxy /notifications/hub/negotiate localhost:8088 56 | reverse_proxy localhost:8088 57 | 58 | #websocket port (default==3012) 59 | reverse_proxy /notifications/hub localhost:3012 60 | header / { 61 | # Enable HTTP Strict Transport Security (HSTS) 62 | Strict-Transport-Security "max-age=31536000;" 63 | # Enable cross-site filter (XSS) and tell browser to block detected attacks 64 | X-XSS-Protection "1; mode=block" 65 | # Disallow the site to be rendered within a frame (clickjacking protection) 66 | X-Frame-Options "DENY" 67 | # Prevent search engines from indexing (optional) 68 | X-Robots-Tag "none" 69 | # Server name remove 70 | -Server 71 | } 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /docker/esphome/README.md: -------------------------------------------------------------------------------- 1 | esphome.io <- тут много интересного 2 | 3 | Я использую [ATOM M5 stack](https://m5stack.com/) (M5 lite сгорели быстро, но Matrix работает уже много лет) и Sonoff с Tuya Smart. 4 | Sonoff и Tuya нужно перешивать с бубном, но результат часто того стоит. 5 | Обновлять этот контейнер следует осторожно. Один раз он всё мне поломал. Ну и обновлять прошивки у ESP32 каждый месяц так же дурное занятие. Работает твой ИоТ? Не трож! 6 | 7 | ## docker-compose.yml 8 | 9 | ```yml 10 | --- 11 | version: "3.9" 12 | services: 13 | esphome: 14 | image: esphome/esphome 15 | container_name: esphome 16 | hostname: esphome 17 | user: 1029:100 # !! CHANGE ME!!! Or disable to build the FW !! otherwise you will see permission denied messages 18 | environment: 19 | - TZ=Europe/Zurich 20 | volumes: 21 | - /volume1/docker/esphome/config:/config 22 | - /volume1/docker/esphome/cache:/cache 23 | ports: 24 | - 6052:6052 25 | - 6123:6123 26 | restart: unless-stopped 27 | network_mode: "bridge" 28 | ``` 29 | -------------------------------------------------------------------------------- /docker/home assistant/README.md: -------------------------------------------------------------------------------- 1 | # HomAss, хомяк - центр умного дома 2 | 3 | # Железо 4 | ## Docker 5 | Мне удобней использовать докер и единственный домашний сервер - Synology NAS. Но есть определенная логика в том, чтобы использовать отдельное устройство для home-assistant: через платы расширения можно добиться большего функционала (вставить, например, плату-акселератор работы с ИИ), такое устройство можно запихнуть сразу в сеть умных устройств, и не держать его в "человеческой" сети. 6 | 7 | ## Sonoff Zigbee 3.0 dongle 8 | У хомяка есть родная интеграция Zigbee. Она была раньше плохая, и я спрыгнул на [zigbee2mqtt](https://github.com/ageev/SmartHome/tree/master/docker/zigbee2mqtt). Сейчас бы уже, наверное, остался на родной. 9 | Про настройку донгла почитайте в разделе [zigbee2mqtt](../zigbee2mqtt) 10 | ## APC UPS 11 | 12 | 13 | # Установка 14 | ## docker-compose.yml 15 | ```yml 16 | --- 17 | version: "3.9" 18 | services: 19 | home-assistant: 20 | image: homeassistant/home-assistant 21 | container_name: home-assistant 22 | hostname: home-assistant 23 | environment: 24 | - PUID=1029 25 | - PGID=100 26 | - TZ=Europe/Zurich 27 | volumes: 28 | - /volume1/docker/home-assistant:/config 29 | restart: unless-stopped 30 | network_mode: "host" 31 | ## will be handled by zigbee2mqtt 32 | # devices: 33 | # - /dev/ttyACM0:/dev/ttyACM0 # old SONOFF stick 34 | # - /dev/ttyUSB0:/dev/ttyUSB0 # sonoff zigbee 3.0 dongle plus 35 | ``` 36 | ## HACS 37 | HACS - это *неофициальный* магазин аддонов к хомяку. Это то место, где Хомяк становится понастоящему мощной штукой. 38 | HACS подтягивает интеграции с GitHab. 39 | 40 | ## Полезные автоматизации 41 | 42 | ## "Алиса, найди пульт от телевизора" 43 | Яндекс станция, услышав эту команду, начнёт поиск пульта от телевизора (пульты от Nvidia Shield TV умеют писчать по запросу приставки). 44 | 45 | Что нужно: 46 | 1. колонка с Алисой 47 | 2. home assistant с интеграцией YandexStation (https://github.com/AlexxIT/YandexStation) установленной через HACS 48 | 3. Nvidia Shield TV, подключенный к Home Assisstant через интеграцию AndroidTV с включенным ADB Debug (через Wifi и режим разработчика на ShieldTV) 49 | 50 | ### Шаг 1 - добавить сценарий в Яндексе 51 | Добавляем сценарий: Если я скажу "Алиса, найди пульт от телевизора", Алиса скажет "Пультик-пультик, ты где?" 52 | 53 | ### Шаг 2 - добавляем автоматизацию в Home Assistant 54 | ``` 55 | alias: 'ALISA find REMOTE 📺 ' 56 | description: '' 57 | trigger: 58 | - platform: event 59 | event_type: yandex_speaker 60 | event_data: 61 | value: Пультик-пультик, ты где? 62 | condition: [] 63 | action: 64 | - service: script.remote_finder 65 | data: {} 66 | mode: single 67 | ``` 68 | 69 | ### Шаг 3 - создаем скрипт script.remote_finder 70 | Открываем вкладку scripts в Home Assisstant и создаем новый скрипт: 71 | ``` 72 | alias: TV Remote Finder 73 | icon: mdi:target 74 | mode: single 75 | sequence: 76 | - service: androidtv.adb_command 77 | data: 78 | command: >- 79 | am start -a android.intent.action.VIEW -d -n 80 | com.nvidia.remotelocator/.ShieldRemoteLocatorActivity 81 | entity_id: media_player.ShieldADB 82 | ``` 83 | 84 | -------------------------------------------------------------------------------- /docker/homer/README.md: -------------------------------------------------------------------------------- 1 | # Homer 2 | Гомер - это простой вебсервер, который берёт содержимое ```config.yml``` и преобразует его в вебстраницу. 3 | Гомер очень удобен в виде стартовой страницы для всех сервисов вашего умного дома. 4 | Вот такой: 5 | 6 | ![Стартовая страница Homer](https://github.com/ageev/SmartHome/raw/master/Pictures/start_page.jpg) 7 | 8 | Я создал DNS А запись для собственного домена, указывающую на Гомера, и добавил сайт в [NPM.](https://github.com/ageev/SmartHome/tree/master/docker/nginx%20proxy%20manager) 9 | Теперь мне не нужно запоминать адреса внутренней сети. Я просто вбиваю в браузер и вижу все ссылки. 10 | Еще я установил [тему на Гомера](https://github.com/walkxcode/homer-theme). Мои иконки разных приложений в файле [tools.zip](https://github.com/ageev/SmartHome/raw/master/docker/homer/tools.zip) 11 | 12 | # docker-compose.yml 13 | ```yml 14 | --- 15 | version: "3.9" 16 | networks: 17 | homer: 18 | image: b4bz/homer 19 | container_name: homer 20 | environment: 21 | - PUID=1029 #change me! 22 | - PGID=100 #change me! 23 | - TZ=Europe/Zurich 24 | - PORT=8080 25 | volumes: 26 | - /volume1/docker/homer:/www/assets 27 | ports: 28 | - 8080:8080 29 | restart: unless-stopped 30 | network_mode: "bridge" 31 | ``` 32 | 33 | ## config.yml 34 | ```yml 35 | --- 36 | # Homepage configuration 37 | # See https://fontawesome.com/icons for icons options 38 | 39 | title: "Стартовая страница" 40 | subtitle: "Наш дом" 41 | logo: "logo.png" 42 | 43 | header: false 44 | footer: false 45 | 46 | # theme 47 | 48 | stylesheet: 49 | - "assets/custom.css" 50 | 51 | columns: "3" # You can change this to any number that is a factor of 12: (1, 2, 3, 4, 6, 12) 52 | theme: default 53 | colors: 54 | light: 55 | highlight-primary: "#fff5f2" 56 | highlight-secondary: "#fff5f2" 57 | highlight-hover: "#bebebe" 58 | background: "#12152B" 59 | card-background: "rgba(255, 245, 242, 0.8)" 60 | text: "#ffffff" 61 | text-header: "#fafafa" 62 | text-title: "#000000" 63 | text-subtitle: "#111111" 64 | card-shadow: rgba(0, 0, 0, 0.5) 65 | link: "#3273dc" 66 | link-hover: "#2e4053" 67 | background-image: "../assets/wallpaper-light.jpeg" # Change wallpaper.jpeg to the name of your own custom wallpaper! 68 | dark: 69 | highlight-primary: "#181C3A" 70 | highlight-secondary: "#181C3A" 71 | highlight-hover: "#1F2347" 72 | background: "#12152B" 73 | card-background: "rgba(24, 28, 58, 0.8)" 74 | text: "#eaeaea" 75 | text-header: "#7C71DD" 76 | text-title: "#fafafa" 77 | text-subtitle: "#8B8D9C" 78 | card-shadow: rgba(0, 0, 0, 0.5) 79 | link: "#c1c1c1" 80 | link-hover: "#fafafa" 81 | background-image: "../assets/wallpaper.jpeg" 82 | 83 | # Optional navbar 84 | # links: [] # Allows for navbar (dark mode, layout, and search) without any links 85 | links: 86 | - name: "DSM" 87 | icon: "far fa-edit" 88 | url: "https://dsm" 89 | target: "_blank" # optional html a tag target attribute 90 | - name: "VirtualDSM" 91 | icon: "far fa-edit" 92 | url: "http://dsm" 93 | target: "_blank" # optional html a tag target attribute 94 | 95 | # Services 96 | # First level array represent a group. 97 | # Leave only a "items" key if not using group (group name, icon & tagstyle are optional, section separation will not be displayed). 98 | # Place the icons in "assets/tools/" 99 | services: 100 | - name: "Видео" 101 | icon: "fas fa-download" 102 | items: 103 | - name: "Plex Media Server" 104 | logo: "assets/tools/plex.png" 105 | subtitle: "Медиа сервер с фильмами и сериалами" 106 | tag: "movies" 107 | url: "https:///plex" 108 | target: "_blank" 109 | - name: "Radarr" 110 | logo: "assets/tools/radarr.png" 111 | subtitle: "Управление медиатекой фильмов" 112 | tag: "torrents" 113 | url: "https:///radarr" 114 | target: "_blank" 115 | # ...and others 116 | 117 | - name: "Утилиты" 118 | icon: "fas fa-tools" 119 | items: 120 | - name: "Bitwarden" 121 | logo: "assets/tools/bitwarden.png" 122 | subtitle: "Менеджер паролей" 123 | tag: "passwords" 124 | tagstyle: "is-primary" # This will display the is-primary color! Try changing it to; is-link, is-info, is-success, is-warning or is-danger! 125 | url: "https://" 126 | target: "_blank" 127 | ``` 128 | -------------------------------------------------------------------------------- /docker/homer/tools.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/docker/homer/tools.zip -------------------------------------------------------------------------------- /docker/nginx proxy manager/README.md: -------------------------------------------------------------------------------- 1 | #Nginx Proxy Manager 2 | Nginx Proxy Manager (aka, NPM) is a tool which allows you: 3 | 1. deploy HTTPS inside your network 4 | 2. publish something in a secure way to internet 5 | 3. auto manages your HTTPS certs (via let's encrypt ACME bot) 6 | 7 | Disadvantages: you need a custom config for most of the apps you publish. Sometimes it's a serious pain in the *** . Google "nginx proxy %appname%" and be ready to try a lot of configs. Traefik can forward traffic directly from the docker. So I may move to Traefik one day... 8 | 9 | ## Setting up NPM with Synology 10 | I want NPM to directly handle HTTP/HTTPS traffic on the standard ports (80/443, TCP). Unfortunately those are not available for docker for Synology NAS. DSM uses those ports for itself (just to redirect the traffic to 5001..). Also docker container can't see macvlan docker containers (no local route), so you need 2 dockers. 11 | Best solution I've found so far - Install Synology VM Manager, setup Virtual DSM (you have 1 free license), setup another Docker instance in the Virtual DSM. Setup your NPM docker there. 12 | ![NPM network scheme](https://github.com/ageev/SmartHome/raw/master/Pictures/npm.jpg) 13 | 14 | Disadvantages: 15 | - you now have 2 dockers, 2 DSMs to manage 16 | 17 | ## docker-compose.yml for NGM (for VirtualDSM) 18 | ```yml 19 | ## install new versions 20 | # cd /volume1/docker 21 | # sudo docker-compose pull 22 | # sudo docker-compose up -d 23 | ## clean docker 24 | # sudo docker system prune -a 25 | ## rebuild containers 26 | # sudo docker-compose up -d --build 27 | 28 | --- 29 | version: "3.9" 30 | networks: 31 | macvlan_network: 32 | driver: macvlan 33 | enable_ipv6: false 34 | driver_opts: 35 | parent: eth0 36 | ipam: 37 | config: 38 | - subnet: 192.168.1.0/24 39 | gateway: 192.168.1.1 40 | ip_range: 192.168.1.16/29 41 | 42 | services: 43 | nginx-proxy-manager: 44 | image: 'jc21/nginx-proxy-manager' 45 | container_name: nginx_proxy_manager 46 | hostname: nginx_proxy_manager 47 | #user: 1027:100 #CHANGE ME! 48 | domainname: local 49 | mac_address: 00:fa:c0:fa:c0:af 50 | cap_add: 51 | - NET_ADMIN 52 | dns: 53 | - 192.168.1.9 # CHANGE ME! 54 | environment: 55 | - PUID=1027 # CHANGE ME! 56 | - PGID=100 # CHANGE ME! 57 | - TZ=Europe/Amsterdam 58 | - DB_MYSQL_HOST=192.168.1.5 #CHANGE ME! 59 | - DB_MYSQL_PORT=3306 60 | - DB_MYSQL_USER=npm 61 | - DB_MYSQL_PASSWORD=p@55w0rd #CHANGE ME! 62 | - DB_MYSQL_NAME=npm 63 | # Uncomment this if IPv6 is not enabled on your host 64 | - DISABLE_IPV6=true 65 | volumes: 66 | - /volume1/docker/nginx_proxy_manager/config.json:/app/config/production.json 67 | - /volume1/docker/nginx_proxy_manager/data:/data 68 | - /volume1/docker/nginx_proxy_manager/letsencrypt:/etc/letsencrypt 69 | restart: unless-stopped 70 | networks: 71 | macvlan_network: 72 | ipv4_address: 192.168.1.17 73 | ``` 74 | 75 | ## docker-compose.yml for MariaDB (main docker on a normal DSM) 76 | 77 | ```yml 78 | --- 79 | version: "3.9" 80 | services: 81 | mariadb: 82 | image: linuxserver/mariadb 83 | container_name: mariadb 84 | hostname: mariadb 85 | environment: 86 | - PUID=1029 #change me! 87 | - PGID=100 #change me! 88 | - TZ=Europe/Zurich 89 | - MYSQL_ROOT_PASSWORD= #change me! 90 | - MYSQL_DATABASE=npm 91 | - MYSQL_USER=npm 92 | - MYSQL_PASSWORD= #change me! 93 | volumes: 94 | - /volume1/docker/mariadb:/config 95 | ports: 96 | - "3306:3306" 97 | restart: unless-stopped 98 | network_mode: "bridge" 99 | 100 | ``` 101 | 102 | # Configs for NGINX proxy manager 103 | add a URL in NPM. Enable everything in SSL tab, enable Web Sockets. Paste those configs to the "Advanced" tab 104 | replace with the real IP 105 | 106 | ## Radarr 107 | ``` 108 | # Radarr. Go to settings in Radarr and set "URL base" to "/radarr" 109 | location /radarr { 110 | proxy_pass http://:7878; 111 | proxy_set_header Host $host; 112 | proxy_set_header X-Real-IP $remote_addr; 113 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 114 | } 115 | ``` 116 | ## Prowlarr 117 | ``` 118 | # Prowlarr. Go to settings in Prowlarr and set "URL base" to "/radarr" 119 | location /prowlarr { 120 | proxy_pass http://:9696; 121 | proxy_set_header Host $host; 122 | proxy_set_header X-Real-IP $remote_addr; 123 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 124 | } 125 | ``` 126 | 127 | ## Plex 128 | ``` 129 | # Plex. Go to settings, network, custom server access - set 4a.pm/plex 130 | location /web { 131 | proxy_pass http://:32400; 132 | proxy_set_header Host $host; 133 | proxy_set_header X-Real-IP $remote_addr; 134 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 135 | } 136 | 137 | location /plex { 138 | proxy_pass http://:32400/web; 139 | } 140 | ``` 141 | ## Transmission 142 | ``` 143 | location /trans { 144 | proxy_pass http://:9091; 145 | proxy_set_header Host $host; 146 | proxy_set_header X-Real-IP $remote_addr; 147 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 148 | } 149 | ``` 150 | 151 | ## Zigbee2mqqt 152 | ``` 153 | location /zigbee { 154 | proxy_pass http://:8081; 155 | proxy_set_header Host $host; 156 | proxy_set_header X-Real-IP $remote_addr; 157 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 158 | } 159 | ``` 160 | 161 | ## Code server 162 | add a subdomain (e.g., code-server.domain.com) 163 | ``` 164 | location / { 165 | proxy_pass http://:8443; 166 | proxy_set_header Host $host; 167 | proxy_set_header X-Real-IP $remote_addr; 168 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 169 | proxy_set_header Referer “”; 170 | proxy_http_version 1.1; 171 | proxy_set_header Upgrade $http_upgrade; 172 | proxy_set_header Connection “upgrade”; 173 | } 174 | 175 | location = /robots.txt { 176 | add_header Content-Type text/plain; 177 | return 200 "User-agent: *\nDisallow: /\n"; 178 | } 179 | 180 | location ~ ^/(.*) 181 | { 182 | # Connect to local port 183 | proxy_pass http://:8443; 184 | } 185 | ``` 186 | 187 | ## home assistant 188 | add a subdomain (e.g., ha.domain.com)\ 189 | ``` 190 | location / { 191 | proxy_pass http://:8123; 192 | proxy_set_header Host $host; 193 | proxy_set_header X-Real-IP $remote_addr; 194 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 195 | } 196 | 197 | location /api/websocket { 198 | proxy_pass http://:8123/api/websocket; 199 | proxy_set_header Host $host; 200 | proxy_set_header X-Real-IP $remote_addr; 201 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 202 | proxy_http_version 1.1; 203 | proxy_set_header Upgrade $http_upgrade; 204 | proxy_set_header Connection "upgrade"; 205 | } 206 | ``` 207 | add this to ```configuration.yaml``` of your HA 208 | ```bash 209 | http: 210 | use_x_forwarded_for: true 211 | trusted_proxies: 212 | - 192.168.1.17/32 #nginx proxy manager ip 213 | #ip_ban_enabled: true # use this to enable auto IP ban 214 | #login_attempts_threshold: 3 215 | ``` 216 | 217 | ## Vaultwarden 218 | add subdomain (e.g., vw.domain.com) 219 | ``` 220 | location /admin { 221 | return 404; 222 | } 223 | 224 | location / { 225 | proxy_pass http://:8088; 226 | proxy_set_header Host $host; 227 | proxy_set_header X-Real-IP $remote_addr; 228 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 229 | proxy_set_header X-Forwarded-Proto $scheme; 230 | } 231 | 232 | location /notifications/hub { 233 | proxy_pass http://:3012; 234 | proxy_set_header Upgrade $http_upgrade; 235 | proxy_set_header Connection "upgrade"; 236 | } 237 | 238 | location /notifications/hub/negotiate { 239 | proxy_set_header Host $host; 240 | proxy_set_header X-Real-IP $remote_addr; 241 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 242 | proxy_set_header X-Forwarded-Proto $scheme; 243 | proxy_pass http://:8088; 244 | } 245 | ``` 246 | -------------------------------------------------------------------------------- /docker/pi-hole/README.md: -------------------------------------------------------------------------------- 1 | ### I moved to Adguard Home https://github.com/ageev/SmartHouse/tree/master/adguard 2 | 3 | # Setting up pi-hole on Synology with docker using macvlan 4 | There are multiple ways to have pi-hole installed: native app, Virtual Machine, docker host, docker macvlan. I tried them all, docker macvlan is the best one (macvlan == separate virtual network adapter). Only last option gives you opportunety to run pi-hole on 80/443 opened ports. 5 | 6 | # Step 0. Preparing the environment 7 | 1. create a "docker" folder on NAS. In will be used to store container's configs 8 | 2. install docker in DSM 9 | 3. create a docker user. Set user's persmissions accordingly (write access to docker folder, remove everything else) 10 | 4. get user ID and group ID using "id *docker_username*" console command. Note the UID and GID numbers 11 | 5. create *pihole* folder inside *docker* folder. Create *dnsmasq* folder inside *pihole* folder 12 | 13 | # Step 1. Docker-compose 14 | 1. copy the "docker-compose.yml" file from this repo to your docker folder (probably /Volume1/docker) 15 | ```yml 16 | version: "2" 17 | services: 18 | pihole: 19 | image: pihole/pihole:latest 20 | container_name: pihole 21 | hostname: pihole 22 | domainname: local 23 | mac_address: 00:fa:c0:fa:c0:aa 24 | cap_add: 25 | - NET_ADMIN 26 | networks: 27 | pihole_network: 28 | ipv4_address: 192.168.7.8 29 | dns: 30 | - 192.168.7.1 31 | - 1.1.1.1 32 | environment: 33 | - PUID=1029 #put your PUID here 34 | - PGID=100 35 | - TZ=Europe/Amsterdam 36 | - WEBPASSWORD=p@ssw0rd #your p@ssw0rd 37 | - DNSSEC=true 38 | - DNS_BOGUS_PRIV=true 39 | - DNS_FQDN_REQUIRED=true 40 | - REV_SERVER=true 41 | - REV_SERVER_DOMAIN=local 42 | - REV_SERVER_TARGET=192.168.7.1 #router's IP 43 | - REV_SERVER_CIDR=192.168.0.0/16 #your LAN subnet 44 | - ServerIP=192.168.7.8 #pi-hole IP (again) 45 | - DNS1=208.67.222.222 # OpenDNS 46 | - DNS2=1.1.1.1 # CloudFlare 47 | volumes: 48 | - /volume1/docker/pihole:/etc/pihole/ 49 | - /volume1/docker/pihole/dnsmasq:/etc/dnsmasq.d/ 50 | restart: unless-stopped 51 | 52 | networks: 53 | pihole_network: 54 | driver: macvlan 55 | driver_opts: 56 | parent: ovs_eth0 57 | ipam: 58 | config: 59 | - subnet: 192.168.7.0/24 60 | gateway: 192.168.7.1 61 | #ip_range: 192.168.0.0/16 62 | 63 | ``` 64 | 2. customize the docker-compose file (see below) 65 | 3. SSH to NAS 66 | ```bash 67 | cd /volume1/docker 68 | sudo docker-compose up -d 69 | ``` 70 | 4. all done! 71 | 72 | if you need to upgrade the container, stop it 1st. Run ```sudo docker system prune -a```. This will remove everything except the pi-hole config/logs folder and do the (3) again. 73 | 74 | # Step 2. Importing lists 75 | Default pi-hole lists are too unrestrictive. My average ad blocking rate for average home network is 20% with default list, 40-80% with additional ones. 76 | Download the pi-hole....tar.gz file. Go to pi-hole admin -> Settings -> Teleporter -> Restore and import the file content. 77 | It may block smthng important -> goto pihole dashboard, go through your logs and build your own whitelist. 78 | 79 | # Step 3. Adding proper route to docker's macvlan network adapter 80 | Docker's macvlan adapters are available for LAN users, but are not available for DSM/Docker users. Generaly speaking that's not an issue, but if you want, for example, to add pi-hole to your home-assistant container running on the same docker (like I did) you need this. 81 | 1. create a file in /usr/local/etc/rc.d folder with .sh extention (this is a DSM script autostart directory[1]) 82 | 2. chmod 755 83 | 3. andjust & copy this into the file 84 | 85 | ```bash 86 | #!/bin/bash 87 | 88 | if [ "$1" = "start" ]; 89 | then 90 | sleep 60 91 | ip link add dlink0 link ovs_eth0 type macvlan mode bridge 92 | ip addr add 192.168.7.127/32 dev dlink0 93 | ip link set dlink0 up 94 | ip route add 192.168.7.8/32 dev dlink0 95 | fi 96 | ``` 97 | * 192.168.7.127/32 - just a random IP to use as a virtual adapter's IP 98 | * dlink0 - new virtual network interface name 99 | * ovs_eth0 - Synology DSM network interface name 100 | * 192.168.7.8/32 - pi-hole container's IP 101 | 102 | "sleep 60" is needed for script to work properly, otherwise it fails. 103 | 104 | # Step 4. Customising docker-compose.yml 105 | Here is the official documentation on all parameters [2]. I found out that my DNS settings were not preserved during container restart. That's why I put them inside the container configuration. 106 | 107 | # Links 108 | * [1] Synology DSM developer guide https://www.synology.com/en-us/support/developer#tool 109 | * [2] https://github.com/pi-hole/docker-pi-hole 110 | -------------------------------------------------------------------------------- /docker/plex/README.md: -------------------------------------------------------------------------------- 1 | # Plex 2 | 3 | Плекс позволяет каталогизировать и стримить видео с транскодингом. Есть профили под каждого пользователя. Это, в целом, удобная штука, когда у вас в семье много устройств. Лично я понял, что пользуюсь, в основном, Kodi. 4 | Пожизненная лицензия на Плекс стоит в районе 50-60 евро на Черную Пятницу. Чтобы нормально работать, Плексу нужна папка с фильмами. 5 | 6 | ## Докер или Plex for Synology 7 | Докер, т.к. это удобней, чаще выходят апдейты. Аппаратная поддержка транскодинга в докере работает (если ваш NAS её поддерживает). 8 | 9 | ## Установка 10 | Вначале установите Plex из магазина Synology. При этом система создаст нужного служебного пользователя (PlexMediaServer) и даст нужные разрешения. 11 | Теперь удалите Plex и ставьте версию для докера. 12 | 13 | ## docker-compose.yml 14 | ```yml 15 | --- 16 | version: "3.9" 17 | services: 18 | plex: 19 | image: plexinc/pms-docker 20 | container_name: plex 21 | environment: 22 | - PLEX_UID=297536 # find your PlexMediaServer user ID with "id -u PlexMediaServer" 23 | - PLEX_GID=297536 24 | # - PLEX_CLAIM=claim-xxxx #get yours here https://www.plex.tv/claim/ (4min lifetime!) 25 | - TZ=Europe/Zurich 26 | - VERSION=latest 27 | - ADVERTISE_IP=http://192.168.1.5:32400/ 28 | - ALLOWED_NETWORKS=192.168.1.0/24,10.0.0.0/8 # add your VPN network here too 29 | volumes: 30 | - /volume1/docker/plex:/config 31 | - /volume1/media:/media 32 | devices: 33 | - /dev/dri:/dev/dri 34 | restart: unless-stopped 35 | network_mode: host 36 | ``` 37 | -------------------------------------------------------------------------------- /docker/radarr/README.MD: -------------------------------------------------------------------------------- 1 | # синхронизация с IMDB раз в 5 минут 2 | 3 | Вот такой скрипт, добавленный в планировщик Synology, позволяет запускать синхронизацию с IMDB 4 | 5 | ```bash 6 | curl -i -s -k -X $'POST' \ 7 | -H $'Host: nas.local:7878' -H $'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0' -H $'Accept: application/json, text/javascript, */*; q=0.01' -H $'Accept-Language: en-US,en;q=0.5' -H $'Accept-Encoding: gzip, deflate' -H $'Content-Type: application/json' -H $'X-Api-Key: ```. Docker user should have sufficient rights to read/write to /volume1/docker/ dir 30 | 31 | ## Setting up Caddy 32 | I need to build a custom Caddy docker image with Gandi support 33 | 34 | 1. create a file ```/volume1/docker/Dockerfile``` 35 | ``` 36 | FROM caddy:builder AS builder 37 | RUN xcaddy build --with github.com/caddy-dns/gandi 38 | 39 | FROM caddy:latest 40 | COPY --from=builder /usr/bin/caddy /usr/bin/caddy 41 | ``` 42 | 43 | 2. create directories 44 | ``` 45 | /volume1/docker/caddy 46 | /volume1/docker/caddy/data 47 | /volume1/docker/caddy/config 48 | /volume1/docker/caddy/log 49 | /volume1/docker/vaultwarden 50 | ``` 51 | 6. create a file ```/volume1/docker/caddy/caddyfile```. This file has some variables like DOMAIN or EMAIL, which are defined later in the docker-compose file 52 | 53 | caddyfile 54 | ``` 55 | { 56 | #default http port needs to be changed or Caddy will not start if it's already in use. Even if you don't use HTTP 57 | http_port 4080 58 | acme_dns gandi {$GANDI_API_TOKEN} 59 | #try to uncomment this if caddy goes to ZeroSSL or another servers for the cert and you get errors. DNS challenge is not supported for every endpoint 60 | #acme_ca https://acme-v02.api.letsencrypt.org/directory 61 | email {$EMAIL} 62 | } 63 | 64 | # start HTTPS on 4443 65 | {$DOMAIN}:4443 { 66 | tls { 67 | dns gandi {$GANDI_API_TOKEN} 68 | } 69 | 70 | log { 71 | output file {$LOG_FILE} 72 | level debug 73 | } 74 | 75 | encode zstd gzip 76 | 77 | #connect to vaultwarden on 8088 78 | reverse_proxy /notifications/hub/negotiate localhost:8088 79 | reverse_proxy localhost:8088 80 | 81 | #websocket port (default==3012) 82 | reverse_proxy /notifications/hub localhost:3012 83 | header / { 84 | # Enable HTTP Strict Transport Security (HSTS) 85 | Strict-Transport-Security "max-age=31536000;" 86 | # Enable cross-site filter (XSS) and tell browser to block detected attacks 87 | X-XSS-Protection "1; mode=block" 88 | # Disallow the site to be rendered within a frame (clickjacking protection) 89 | X-Frame-Options "DENY" 90 | # Prevent search engines from indexing (optional) 91 | X-Robots-Tag "none" 92 | # Server name remove 93 | -Server 94 | } 95 | } 96 | ``` 97 | 98 | 4. create/edit ```/volume1/docker/docker-compose.yml``` file 99 | 100 | docker-compose.yml 101 | ```yaml 102 | --- 103 | version: "3.9" 104 | services: 105 | caddy: 106 | container_name: caddy 107 | build: . #builds caddy + gandi version. see Dockerfile for details 108 | environment: 109 | - PUID= 110 | - PGID= 111 | - TZ=Europe/Amsterdam 112 | - ACME_AGREE=true 113 | - DOMAIN=*.example.com # i suggest to get the wildcard cert - you can reuse them in other containers! 114 | - EMAIL= 115 | - GANDI_API_TOKEN= 116 | - LOG_FILE=/var/log/caddy/caddy.log 117 | volumes: 118 | - /volume1/docker/caddy/caddyfile:/etc/caddy/Caddyfile 119 | - /volume1/docker/caddy/data:/data 120 | - /volume1/docker/caddy/config:/config 121 | - /volume1/docker/caddy/log:/var/log/caddy 122 | restart: unless-stopped 123 | network_mode: "host" 124 | 125 | vaultwarden: 126 | container_name: vaultwarden 127 | image: vaultwarden/server:latest 128 | environment: 129 | - PUID= 130 | - PGID= 131 | - TZ=Europe/Amsterdam 132 | - WEBSOCKET_ENABLED=true # Required to use websockets 133 | # - SIGNUPS_ALLOWED=false # set to false to disable signups 134 | - DOMAIN=https://vw.example.com # change this to the actual domain you use. It should be real & match the certificate issued by Caddy 135 | # - SMTP_HOST=[MAIL-SERVER] 136 | # - SMTP_FROM=[E-MAIL] 137 | # - SMTP_PORT=587 138 | # - SMTP_SSL=true 139 | # - SMTP_USERNAME=[E-MAIL] 140 | # - SMTP_PASSWORD=[SMTP-PASS] 141 | - ADMIN_TOKEN= # run to get random token 142 | - ROCKET_PORT=8088 143 | # - YUBICO_CLIENT_ID=[OPTIONAL] 144 | # - YUBICO_SECRET_KEY=[OPTIONAL] 145 | - LOG_FILE=/data/bitwarden.log 146 | - EXTENDED_LOGGING=true 147 | - LOG_LEVEL=warn 148 | - ROCKET_WORKERS=10 149 | - SHOW_PASSWORD_HINT=false 150 | # - DISABLE_ICON_DOWNLOAD=true 151 | volumes: 152 | - /volume1/docker/vaultwarden:/data 153 | restart: unless-stopped 154 | ports: 155 | - 8088:8088 156 | - 3012:3012 157 | network_mode: "bridge" 158 | ``` 159 | 160 | 5. SSH to NAS & run docker-compose 161 | 162 | ```bash 163 | cd /volume1/docker 164 | sudo docker-compose up -d --build 165 | ``` 166 | 167 | 6. give Caddy few minutes to get the cert. Go to "https://:4443". You should see the BitWarden login page 168 | 7. You can set some admin settings here "https://:4443/admin" using the token specified in the docker-compose file. Don't forget to change "Domain URL" in General settings to https://:**4443**. Otherwise attachment download will not work. 169 | If you want to disable the admin panel - remove/comment "ADMIN_TOKEN" string from your docker-compose file AND from ```/volume1/docker/vaultwarden/config.json``` 170 | 8. I use Caddy's certificate also to secure my Adblock container. That's convinient because let's encrypt certs are issued only for 3 month and caddy manages all the updates. To do this you just need to mount the certificate folder. 171 | E.g. 172 | ``` 173 | /volume1/docker/caddy/data/caddy/certificates:/opt/adguardhome/cert 174 | ``` 175 | -------------------------------------------------------------------------------- /docker/zigbee2mqtt/README.md: -------------------------------------------------------------------------------- 1 | # Zigbee2Mqtt 2 | zigbee2mqtt - это одна из трех популярных zigbee интеграций. Наверное даже самая популярная. У них [отличный сайт](https://www.zigbee2mqtt.io/), где можно проверить, работает ли ваша лампочка с z2m или нет. 3 | Я использую zigbee2mqtt для управления всеми моими ZB устройствами в Home Assistant (но можно, в принципе, использовать и встроенную в HA интеграцию Zigbee). 4 | Для работы контейнера нужен еще контейнер mosquitto 5 | 6 | ## Пререквизиты 7 | 1. Zigbee донгл. Самым удобным мне показался стик Sonoff Zigbee 3.0 с али. К стику нужен небольшой USB удлинитель 8 | 2. Нужно загрузить драйвера для стика на НАС 9 | Т.к. после апгрейда Synology DSM НАС может драйвера потерять, у меня в Task Manager стоит вот такой таск (запускать под рутом при загрузке девайса) 10 | 11 | Не забудьте вставить правильный URL под вашу конркетную модель НАСа (CPU)! У меня DS218+ c CPU из семейства apollolake. 12 | 13 | ```bash 14 | if [ ! -f /lib/modules/cp210x.ko ]; then 15 | cd /lib/modules 16 | wget https://github.com/robertklep/dsm7-usb-serial-drivers/raw/main/modules/apollolake/cp210x.ko # CHANGE ME!!! 17 | fi 18 | 19 | modprobe usbserial 20 | modprobe ftdi_sio 21 | modprobe cdc-acm 22 | insmod /lib/modules/cp210x.ko 23 | chmod 666 /dev/ttyUSB0 # you need this to have user-level access to the stick from docker 24 | ``` 25 | 26 | ## docker-compose.yml zigbee2mqtt 27 | ```yml 28 | --- 29 | version: "3.9" 30 | services: 31 | zigbee2mqtt: 32 | container_name: zigbee2mqtt 33 | image: koenkk/zigbee2mqtt 34 | group_add: 35 | - dialout # needed so user has access to USB device, but no such group exists in DSM7.0, so you need to do "sudo chmod 0666 /dev/ttyUSB0"! 36 | user: 1029:100 # CHANGE ME! 37 | volumes: 38 | - /volume1/docker/zigbee2mqtt:/app/data 39 | - /run/udev:/run/udev:ro 40 | ports: 41 | - 8081:8081 42 | environment: 43 | - TZ=Europe/Zurich 44 | devices: 45 | # - /dev/ttyACM0:/dev/ttyACM0 # old SONOFF stick 46 | - /dev/ttyUSB0:/dev/ttyUSB0 # sonoff zigbee 3.0 dongle plus 47 | restart: unless-stopped 48 | network_mode: "bridge" 49 | ``` 50 | 51 | ## docker-compose.yml для mosquitto 52 | ```yml 53 | --- 54 | version: "3.9" 55 | services: 56 | mosquitto: 57 | image: eclipse-mosquitto 58 | container_name: mosquitto 59 | hostname: mosquitto 60 | environment: 61 | - PUID=1029 #CHANGE ME! 62 | - PGID=100 #CHANGE ME! 63 | - TZ=Europe/Zurich 64 | volumes: 65 | - /volume1/docker/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro 66 | - /volume1/docker/mosquitto/mosquitto.passwd:/mosquitto/config/mosquitto.passwd # do chmod 0666 on that file! 67 | - /volume1/docker/mosquitto/log/mosquitto.log:/mosquitto/log/mosquitto.log # do chmod 0666! 68 | - /volume1/docker/mosquitto/data:/mosquitto/data 69 | ports: 70 | - "1883:1883" 71 | restart: unless-stopped 72 | network_mode: "bridge" 73 | ``` 74 | 75 | Как обычно все папки указанные в конфигах надо вначале вручную создать на НАСе, а то получите ошибку доступа в логах 76 | -------------------------------------------------------------------------------- /secrets.py: -------------------------------------------------------------------------------- 1 | """ 2 | SANITIZED VERSION. FILL WITH YOUR OWN DATA!!! 3 | 4 | File used to set environment variables including tokens and passwords. 5 | 6 | """ 7 | ENVIRONMENT = "Production" 8 | #ENVIRONMENT = "Test" 9 | 10 | if ENVIRONMENT == "Production": 11 | # General 12 | NAS_IP = "192.168.1.1" 13 | ADDRESS_BOOK = { 14 | '192.168.1.101' : '', 15 | } 16 | 17 | # Telegram 18 | Telegram = { 19 | "token" : ":", 20 | "chat_id" : "", 21 | } 22 | 23 | # Meteoserver 24 | Meteoserver = { 25 | "url" : "", 26 | "token" : "", 27 | "town" : "", 28 | } 29 | 30 | # qBittorrent 31 | qBittorrent = { 32 | "ip" : NAS_IP, 33 | "port" : "", 34 | } 35 | 36 | # Synology surveillance station 37 | SurvStation = { 38 | "login" : "", 39 | "password" : "", 40 | "ip" : NAS_IP, 41 | "port" : "5001", 42 | 43 | } 44 | 45 | # Gandi 46 | Gandi = { 47 | "token" : "", 48 | } 49 | 50 | def main(): 51 | pass 52 | 53 | if __name__ == "__main__": 54 | main() 55 | -------------------------------------------------------------------------------- /telegrambot/mytelegrambot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # """Python telegram bot. POST API only""" 3 | 4 | # Usefull links 5 | # https://stackoverflow.com/questions/32423837/telegram-bot-how-to-get-a-group-chat-id#32572159 6 | # allow bot to join groups - @botfather send /setjoingroups then Enable 7 | # https://sourceforge.net/p/telegram/wiki/markdown_syntax/ 8 | 9 | import requests, json 10 | 11 | # Locate the directory containing this file and the repository root. 12 | # Temporarily add these directories to the system path so that we can import 13 | # local files. 14 | import sys 15 | from pathlib import Path 16 | here = Path(__file__).parent.absolute() 17 | repository_root = (here / ".." ).resolve() 18 | sys.path.insert(0, str(repository_root)) 19 | 20 | # supress SSL errors 21 | #from requests.packages.urllib3.exceptions import InsecureRequestWarning 22 | 23 | # use your own secrets! 24 | from secrets import Telegram 25 | 26 | def main(): 27 | pass 28 | 29 | # send text to telegram bot 30 | def sendtext(bot_message, token=Telegram["token"], chat_id=Telegram["chat_id"]): 31 | 32 | url = f"https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&parse_mode=Markdown&text={bot_message}" 33 | #response = requests.get(url, verify=False) 34 | response = requests.get(url) 35 | 36 | return response.json() 37 | 38 | if __name__ == "__main__": 39 | main() 40 | -------------------------------------------------------------------------------- /telegrambot/torrent_watcher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # """script monitors qBittorent torrents and sends Telegram messages""" 3 | 4 | # qbittorrent webAPI https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-Documentation 5 | 6 | import requests, json, os, time 7 | 8 | # Locate the directory containing this file and the repository root. 9 | # Temporarily add these directories to the system path so that we can import 10 | # local files. 11 | import sys 12 | from pathlib import Path 13 | here = Path(__file__).parent.absolute() 14 | repository_root = (here / ".." ).resolve() 15 | sys.path.insert(0, str(repository_root)) 16 | 17 | # use your own secrets! 18 | from secrets import qBittorrent 19 | from mytelegrambot import sendtext 20 | 21 | # in seconds, should match scheduler time (e.g. if script runs every minute ==> AGE = 60). i've added +1 second "just in case". 22 | # you can also save torrent state to disk, but time-based approach was chosen in favor to reduce disk IO operations 23 | AGE = 61 24 | 25 | def main(): 26 | # Step 1: get torrents from qBT and saved torrents 27 | torrents = get_torrents(qBittorrent['ip'], qBittorrent['port']) 28 | # print(json.dumps(torrents, indent=4, sort_keys=True)) 29 | 30 | # check for fresh torrents 31 | current_time = int(time.time()) #get current epoch time in seconds 32 | for _ in torrents: 33 | if (_['completion_on'] != 4294967295) and ((current_time - _['completion_on']) <= AGE): 34 | size = human_readable_size(_['size']) 35 | message = f"*Завершен* торрент [{_['name']}](http://{qBittorrent['ip']}:{qBittorrent['port']}) Размер: *{size}*." 36 | sendtext(message) 37 | elif (current_time - _['added_on']) <= AGE: 38 | size = human_readable_size(_['size']) 39 | message = f"*Добавлен* торрент [{_['name']}](http://{qBittorrent['ip']}:{qBittorrent['port']}) Размер: *{size}*." 40 | sendtext(message) 41 | 42 | # get list of torrents from qbittorent 43 | def get_torrents(ip, port): 44 | r = requests.get(f'http://{ip}:{port}/api/v2/torrents/info') 45 | return json.loads(r.text) 46 | 47 | def human_readable_size(size, decimal_places=1): 48 | for unit in ['Б','КБ','МБ','ГБ','ТБ']: 49 | if size < 1024.0: 50 | break 51 | size /= 1024.0 52 | return f"{size:.{decimal_places}f} {unit}" 53 | 54 | if __name__ == "__main__": 55 | main() 56 | -------------------------------------------------------------------------------- /yeelight/Yeelight_Inter-Operation_Spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ageev/SmartHome/8f57f53a07add23aacc31415fd88b7305a65a876/yeelight/Yeelight_Inter-Operation_Spec.pdf -------------------------------------------------------------------------------- /yeelight/yeelight.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # """Working with Yeelight""" 3 | # 4 | 5 | # Imports 6 | import os 7 | import sys 8 | import socket 9 | import json 10 | 11 | 12 | # Module Constants 13 | START_MESSAGE = "Yeelight WakeUp script" 14 | PORT = 55443 15 | 16 | HOST = "192.168." 17 | 18 | 19 | 20 | # power = '{"id": 1, "method": "set_power", "params": ["on", "smooth", 350]}' 21 | # off = '{"id": 1, "method": "set_power", "params": ["off", "smooth", 350]}' 22 | # bright = '{"id": 1, "method": "set_bright", "params": [1, "smooth", 350]}' 23 | # tempr = '{"id": 1, "method": "set_ct_abx", "params": [2700, "smooth", 350]}' #2700-6500 24 | # bg_power = '{"id": 1, "method": "bg_set_power", "params": ["on", "smooth", 350]}' 25 | # bg_bright = '{"id": 1, "method": "bg_set_bright", "params": [1, "smooth", 350]}' 26 | # bg_colour = '{"id": 1, "method": "bg_set_rgb", "params": [14423100, "smooth", 350]}' #RGB color green - 65280, blue - 255, red 16711680. Gray RGB code = 128*65536+128*256+128 27 | # {"id":1,"method":"adjust_bright","params":[-20, 500]} 28 | 29 | # Module "Global" Variables 30 | location = os.path.abspath(__file__) 31 | 32 | def send_command_to_device(cmd, HOST, PORT): 33 | # Create a socket (SOCK_STREAM means a TCP socket) 34 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 35 | # Connect to server and send data 36 | sock.connect((HOST, PORT)) 37 | sock.sendall(bytes(cmd, "utf-8")+b'\x0d\x0a') 38 | 39 | # Receive data from the server and shut down 40 | received = str(sock.recv(1024), "utf-8") 41 | 42 | print("Sent: {}".format(cmd)) 43 | print("Received: {}".format(received)) 44 | 45 | def get_cmd_json(param1, param2): 46 | command = {} 47 | command['id'] = 1 48 | command['method'] = param1 49 | command['params'] = param2 50 | return json.dumps(command) 51 | 52 | # Module Functions and Classes 53 | def main(*args): 54 | """My main script function. 55 | Displays the full patch to this script, and a list of the arguments passed 56 | to the script. 57 | """ 58 | 59 | print(START_MESSAGE) 60 | print("Script Location:", location) 61 | print("Arguments Passed:", args) 62 | 63 | duration = 3000 64 | 65 | send_command_to_device(get_cmd_json("set_power", ["on", "sudden", 1]), HOST, PORT) 66 | send_command_to_device(get_cmd_json("set_bright", [1, "sudden", 1]), HOST, PORT) 67 | send_command_to_device(get_cmd_json("set_ct_abx", [2700, "sudden", 1]), HOST, PORT) 68 | send_command_to_device(get_cmd_json("bg_set_bright", [1, "sudden", 1]), HOST, PORT) 69 | send_command_to_device(get_cmd_json("adjust_bright", [100, duration]), HOST, PORT) 70 | send_command_to_device(get_cmd_json("bg_adjust_bright", [100, duration]), HOST, PORT) 71 | # send_command_to_device(get_cmd_json("set_ct_abx", [6500, "smooth", duration]), HOST, PORT) 72 | 73 | 74 | 75 | 76 | cmd_json = get_cmd_json 77 | 78 | {"id":1,"method":"adjust_bright","params":[-20, 500]} 79 | 80 | 81 | # Check to see if this file is the "__main__" script being executed 82 | if __name__ == '__main__': 83 | _, *script_args = sys.argv 84 | main(*script_args) 85 | --------------------------------------------------------------------------------