From 3da60c72cca15e18dc588c391cb7279d48f423df Mon Sep 17 00:00:00 2001 From: Tobias Brenner <19689801+brenner-tobias@users.noreply.github.com> Date: Sun, 28 Nov 2021 14:16:00 +0100 Subject: [PATCH] Added Cloudflared Add-On --- README.md | 4 +- cloudflared/CHANGELOG.md | 0 cloudflared/DOCS.md | 129 +++++++++++++++++++++++++++++++++++++++ cloudflared/README.md | 82 +++++++++++++++++++++++++ cloudflared/config.yaml | 26 ++++++++ cloudflared/icon.png | Bin 0 -> 2837 bytes cloudflared/logo.png | Bin 0 -> 4515 bytes 7 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 cloudflared/CHANGELOG.md create mode 100644 cloudflared/DOCS.md create mode 100644 cloudflared/README.md create mode 100644 cloudflared/config.yaml create mode 100644 cloudflared/icon.png create mode 100644 cloudflared/logo.png diff --git a/README.md b/README.md index 364be1b..fee06b7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ https://github.com/brenner-tobias/ha-addons ### ✓ [Cloudflared][addon-cloudflared] -![Latest Version][cloudflared-version-shield] +![Latest Version][cloudflared-release-shield] ![Supports armhf Architecture][cloudflared-armhf-shield] ![Supports armv7 Architecture][cloudflared-armv7-shield] ![Supports aarch64 Architecture][cloudflared-aarch64-shield] @@ -67,7 +67,7 @@ SOFTWARE. [cloudflared-armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg [cloudflared-armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg [cloudflared-i386-shield]: https://img.shields.io/badge/i386-yes-green.svg -[cloudflared-version-shield]: https://img.shields.io/badge/version-v0.1.0-blue.svg +[cloudflared-release-shield]: https://img.shields.io/github/release/brenner-tobias/addon-cloudflared [license-shield]: https://img.shields.io/github/license/brenner-tobias/ha-addons [maintenance-shield]: https://img.shields.io/maintenance/yes/2021.svg [project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg diff --git a/cloudflared/CHANGELOG.md b/cloudflared/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/cloudflared/DOCS.md b/cloudflared/DOCS.md new file mode 100644 index 0000000..438aabf --- /dev/null +++ b/cloudflared/DOCS.md @@ -0,0 +1,129 @@ +# Home Assistant Add-on: Cloudflared + +Cloudflared connects your Home Assistant Instance via a secure tunnel to a domain +or subdomain at Cloudflare. Doing that, you can expose your Home Assitant to the +Internet without opening ports in your router. Additionally, you can utilize +Cloudflare Teams, their Zero Trust platform to further secure your Home Assistant +connection. + +**To use this add-on you have to own a domain name (e.g. example.com) and use the +DNS servers of cloudflare.** + +## Installation + +The installation of this add-on is pretty straightforward but requires some prerequisites +and a manual step at the first set-up: + +1. (Optional if you don't yet have a working Cloudflare set-up): + Get a domain name and set-up Cloudflare. See section + [Domain Name and Cloudlfare Set-Up](#domain-name-and-cloudlfare-set-up) for details. +1. Set the "external_hostname" add-on option with your domain name or a subdomain + that you want to use to access Home Assistant. +1. (Optional) Change the "internal_ha_port" add-on option with the internal Port + to reach Home Assistant in your network (default: 8123). +1. (Optional) Change the "tunnel_name" add-on option (default: homeassistant). +1. **Make sure that there is no DNS entry with your desired external hostname and + no existing tunnel with your desired tunnel name at Cloudflare**. +1. Start the "Cloudflare" add-on. +1. Check the logs of the "Cloudflare" add-on and **follow the instruction to authenticate + at cloudflare**. + You need to copy a URL from the logs and visit it to authenticate. +1. A tunnel and a DNS entry will be created and show up in your cloudflare DNS / + Teams dashboard. + +## Configuration + +**Note**: _Remember to restart the add-on when the configuration is changed._ + +Example add-on configuration: + +```yaml +internal_ha_port: "8123" +external_hostname: "ha.example.com" +tunnel_name: homeassistant +``` + +**Note**: _This is just an example, don't copy and paste it! Create your own!_ + +### Configuration.yaml + +Since HomeAssistant blocks requests via proxies or reverse proxies, you have to tell +your instance to allow requests from the Cloudflared Add-On. The add-on runs locally, +so HA hasto trust the docker network. In order to do so, add the following lines +to your /config/configuration.yaml (if you need assistance changing the config, +please follow the [Advanced Configuration Tutorial][advancedconfiguration]): + +```yaml +http: + use_x_forwarded_for: true + trusted_proxies: + - 172.30.33.0/24 +``` + +### Option: `log_level` + +The `log_level` option controls the level of log output by the addon and can +be changed to be more or less verbose, which might be useful when you are +dealing with an unknown issue. Possible values are: + +- `trace`: Show every detail, like all called internal functions. +- `debug`: Shows detailed debug information. +- `info`: Normal (usually) interesting events. +- `warning`: Exceptional occurrences that are not errors. +- `error`: Runtime errors that do not require immediate action. +- `fatal`: Something went terribly wrong. Add-on becomes unusable. + +Please note that each level automatically includes log messages from a +more severe level, e.g., `debug` also shows `info` messages. By default, +the `log_level` is set to `info`, which is the recommended setting unless +you are troubleshooting. + +## Domain Name and Cloudlfare Set-Up + +To use this plugin, you need a domain name that is using Cloudflare for its +DNS entries. + +### Domain Name + +If you do not already have a domain name, get one. In case you dont want +to pay for a domain name, you can look for a free domain name at +[freenom][freenom]. + +### Cloudflare + +Create a free Cloudflare Account at [cloudflare.com][cloudflare] and follow +the tutorial [Getting started with Cloudflare][cloudflaretutorial]. + +## Authors & contributors + +The original setup of this repository is by [Tobias Brenner][tobias]. + +## License + +MIT License + +Copyright (c) 2021 Tobias Brenner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +[advancedconfiguration]: https://www.home-assistant.io/getting-started/configuration/ +[cloudflare]: https://www.cloudflare.com/ +[cloudflaretutorial]: https://support.cloudflare.com/hc/en-us/articles/360027989951-Getting-Started-with-Cloudflare +[freenom]: https://freenom.com +[tobias]: https://github.com/brenner-tobias diff --git a/cloudflared/README.md b/cloudflared/README.md new file mode 100644 index 0000000..340e87d --- /dev/null +++ b/cloudflared/README.md @@ -0,0 +1,82 @@ +# Home Assistant Add-on: Cloudflared + +[![GitHub Release][releases-shield]][releases] +![Project Stage][project-stage-shield] +[![License][license-shield]](LICENSE.md) + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] +![Supports armhf Architecture][armhf-shield] +![Supports armv7 Architecture][armv7-shield] +![Supports i386 Architecture][i386-shield] + +[![Github Actions][github-actions-shield]][github-actions] +![Project Maintenance][maintenance-shield] + +Connect remotely to your Home Assistant instance without opening any ports using +Cloudflared. + +## About + +Cloudflared connects your Home Assistant Instance via a secure tunnel to a domain +or subdomain at Cloudflare. Doing that, you can expose your Home Assitant to the +Internet without opening ports in your router. Additionally, you can utilize +Cloudflare Teams, their Zero Trust platform to further secure your Home Assistant +connection. + +**To use this add-on you have to own a domain name (e.g. example.com) and use the +DNS servers of cloudflare. If you do not have a domain name, you can register a +free one at [freenom][freenom]** + +[:books: Read the full add-on documentation][docs] + +## Support + +Got questions? + +Feel free to [open an issue here][issue] on GitHub. + +## Author + +[Tobias Brenner][tobias] + +## License + +MIT License + +Copyright (c) 2021 Tobias Brenner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[docs]: cloudflared/DOCS.md +[freenom]: https://freenom.com +[github-actions-shield]: https://github.com/brenner-tobias/addon-cloudflared/workflows/CI/badge.svg +[github-actions]: https://github.com/brenner-tobias/addon-cloudflared//actions +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg +[issue]: https://github.com/brenner-tobias/addon-cloudflared/issues +[license-shield]: https://img.shields.io/github/license/brenner-tobias/addon-cloudflared +[maintenance-shield]: https://img.shields.io/maintenance/yes/2021.svg +[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg +[releases-shield]: https://img.shields.io/github/release/brenner-tobias/addon-cloudflared +[releases]: https://github.com/brenner-tobias/addon-cloudflared/releases +[tobias]: https://github.com/brenner-tobias diff --git a/cloudflared/config.yaml b/cloudflared/config.yaml new file mode 100644 index 0000000..82a4f6c --- /dev/null +++ b/cloudflared/config.yaml @@ -0,0 +1,26 @@ +--- +name: Cloudflared +version: dev +slug: cloudflared +description: > + Add-On to use a Cloudflared tunnel (formerly Argo Tunnel) + to remotely connect to your Home Assistant without opening any ports +url: "https://github.com/brenner-tobias/addon-cloudflared/" +image: ghcr.io/brenner-tobias/cloudflared/{arch} +startup: services +init: false +arch: + - aarch64 + - amd64 + - armhf + - armv7 + - i386 +options: + external_hostname: "" + internal_ha_port: "8123" + tunnel_name: homeassistant +schema: + external_hostname: str + internal_ha_port: port + tunnel_name: str + log_level: list(trace|debug|info|notice|warning|error|fatal)? diff --git a/cloudflared/icon.png b/cloudflared/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f5b0f7e85b88e704c1610ea6ad0b43b8ee5e9744 GIT binary patch literal 2837 zcmds3S6fqw0z8L=-aDZf6cCUqLZtU1O;`k}5d=j#2vQW0fOMqTsM3o{3@n`(At=&B zLorAVRcct+T_S-5$o2k+`*I&<=4Iw_zL`wNt5)0`;v4_~a9dw7clxcU|ALL>H}@Id z9QiF^l#`Vy&`6Nn0sxLtYjYFlxEp`H;*Joy0~=(FE|3=1B1NTNq~U&*OCE;i7rUU#zDPT2oAV6Z{ha#S`$#ZBJF6) zNs&oeu1Wf-D!VY)L)b;;%F5mk$CBuAR8sNJNbH>o>ItJ_(V!F8iGyObXTiv}2a0C| zfOIoyFdxvK2h&FirHq-DB3LC=y<-4&RG(Bt*TWf57T}5PUH;J&y0|3fQ%v`nHL|Zycofm~3VmdF@SI{;}^*N!fA}!W0khe`Cy9TGTD0F`;| zi&*Q_!u$!yR_9PP)Vu%A!tmU%IdeyRebPej;6;GGZ5lrhs{Bg8d&^qUssVxYukt#x z8@3DTH%Zv8BNtnInj`Sp({%3RX2--_+)>7pX=Jp7!^wMrb&Xlc6kut`%#}GIVH*bw zTrXHAiia5Lpj*~8;}9;q#<8_`FYwdV9Gg3FIub=^y*FBaz;6Aaj8D{>#)o^Amu z6Yb|<7+zX&xbi;gS3UjxcB$T~Oj*+NjI;{>Ud;9Erj&=!62SmNEZQqd5eDo$4erj| z7oCC}s-o`7uo?2EeFNW=((+2y4C&w3G~Pg0%Xtv7cFG^M`*?2Z0oaoRc|iH1%rlf! z`#Zmz$)A(}eP4f4Q1)bz#v{Ah?pDeD4q;SW?Q)Iu6h2#<*%nd>H=-8yy%Na9>P*i! zzfW0ROK;&u#od}P%|9rN%xL&@QH`ZkFKFaqxF?Wdb$%3j+hgSH8;?OQsIU{X%fUi=r3)Z@d1<_0R}ay&Awi$fvT@C(FTLq( zHPz;AzY`F7XXC>kHlXQ~x-S01alJI5m|b8Zes7$iQO-03SXvp_RKC_I{`!0&HU6qw z^yITT;B(C~0{EV)V8d<^7xsa30n6|AnX>ERQ^r`%A@oL|*ka>LeCcr?Yr4Z=05)5l zLPB7R?p4N|{E=TmV!vWwAmLLVV#nXdOR{gSKw7*0$py@u+Fv&iy&8R%*mz%y{%%jw zY4p+27XdKP(ru>qHT;(P zw#U;ioTr_n3DBr?5-~2DbM}OblKDp%X62_qUIQtSYN)VksIGAS`+;=Z!Nv|n`7dk4 zVZeCI$&l|OMKR!nW4^@j7jJcW$?ezskf^D7EO#UC!o8V@*C{Kb$2hCvY?lU*@V9%I!uiTb{FX-5BJd;59D*qGyU8=Gcx%vMj0G z=!v?N-^6q35^wV8#Q&CzTJaRZBz_Nu%h`4+^*y31JYh5bPHz($XMi2mYFW0qbJpdrLU+rv4M@5IDcJqltb76*g<$5LAw zRvo7C`*|@X_dG(gV0X@WvlyQfFBviJpq?d9uGNb1($tvVFcKl<&zUA-@oDt&?7A)! ztW{0i5d#bML%LdwYP^V7@u!QZeyY-g-$y}E@ZLfyi@&BWLp ziD3M_r*PJZBLpKj&4aP;74NE#jiy(S;q2IpPX?>tg0xrjGaXI%u(fJ@>!pMNUfY4B zTdoH+m3xwId&N6`-tzhSytM)|c>DRq+2sY8$+XcoFs zjZT@KX+-<7L?mvC9E#*T>~#APC9s9`Rtk!3)NUqPW(I7cxoW+;l|)CR#vG1<;0Sc{ zh=^y{QO3GJi=R+9yAf-e&ieHiacNI2w+RHR{Qwm7%?pu*^OLw_1ggu>9GlS{L!Jmd9Sz=7^ zozX|4Ec$3jrFYsV1GUQI?-&9Mx~uopK)MbdzGaw8$+lIpWP{L~p}mC2&5ctM^`I`6 zVH5@-8w77;)JF_s( zAXN)=9rwRUMc9A2p3y=Iyu_oh$4^HA`9vZ_c=W8(A$v+lHa*P_U`LbRCJ~yhlmO)X$Pp3fvpqV`4 zA`dQk$i|?c#yhmgNo$}>BvVQn|M!&x0Beh@=8dL4 G$^QY4^+PlO literal 0 HcmV?d00001 diff --git a/cloudflared/logo.png b/cloudflared/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8d5fa7b3d197f811f87408bb3cb941d1845488bd GIT binary patch literal 4515 zcmZ`-cQD*txc;rOR_{U7=uy_{E&2+gB|b!nUN)jF(d!arMJLMYEiBQyRli7r=mZHN zN|X>~qbxykefPin$9>M6^UOKVJoC;w=Y40+oP>u)I@A=mDF6VV*3*TX-0<+t)P{g> zR@#8-+#4c6Xc%e$KvOE^l>_O`p2tbo#1H^N1OWgQ0|38oj!-)Q;12_UU3&mfy790e z3viF_-3VYueH}RP_rFonTa^g_bT~b@hH22^zKwg3>0DPte=mXoqK8s{`bdTx-Nq4m z?=;$srzL=4p#7zMnR%_wBhjI<(|cB_TpD03VO>$YtuDml&HTnJBfXfauOy~d2&Car z+b$Bc#v2XMOXxyCLnF6`_?;&w45Y|0PvTBhC$DnbB-|t2!w-K$-S^u-Di!P(GEgvL5c?1b%@qPstd~^lH`xTu&#&4iEVLQ-+?wur4ltOkBl?OZdBR5}06(Y=U$# zKlF={&VF z&H_K8zO$^rYShvvyVZB?KNGD>74o%|PEGn9cp`I-M@7U&EI~u(pYqEHaG~6%qC|Dd zd~>D(0dii+r`X^Vc1x1JaI|XCNBcv2)1MhN>5C7Fr*HMd{reh-><*{D1N`J$@3%0J zK&1HBl`E@KCp~rV<|_GFDnco_HP=vZ&;MjbrFfXfX8nBm_2z{da72P?ATW^-pWj8j z2Kp2$ocO0+SdN}S(@D~Ix)~&~!NDs|JUHb!XFhuZ*5wi`b3a2;ch{1}TO@&WOe51uMKX`vpxJHw<|a68ki%oBrkqcCN4>(;8JIj@8|QQ;e`6R zmsbQJOw=XT)YSRwg`mA0@6T>h`!^eCQhPPY6$i~&_IWE@^KP176Tgzp8|Gl%*CQbH z!kQ>4Ar!4=TV}ad>M;gMiW1U#NE0)k4{RFFEBg3r8jF8uEI|}~x{50#w?oW@KT(&RQzmk!XviW_ zEY%Qt-RxH%*~jtlNh8f668AWPin|@zf4F>idW5A$K>H`1zm%{m;I7y|*hR$zE8Q7lp`a zT?>LP#_kCUWYRJk=~zwMTrUL-OlrC;(gar9PV*I3)KE)=wf%Z^7pi|PiMrUS>aC9R zFwIh-=VPe{xftIwckLrkT68a*4ehH1=F244OXXE0W)WeJw^H4HZK)hIf1(9lh1O(h zVUDPidhnaVz5vPudAH;wapU=eDVJplab1d%fAb^b9t0&v-MuSOTlQAv8eHKP2s%iY zG;X3fw>MWK${p(M_0G(Ha^a`_Ud@?G>d8n`nSJ)#D-mL+e-;Zrj>YaJC9dLD1%;iC zaobZByi+@O8&yN-=Sw}+u}uwgu5seWw}4b#N~y4oWKO{M_vOm76~8Gg9<>ghk-~|@ ziE<)ScdQO3fKRM!n z@K?#&WMxj|>%cnUI>Z}IHmA}eCC=SfmI>BrNXlBRr2*Nw)yfy@ja-n9`?b1Qa)1E+ z>7Wgyk+4Cr1f!22%Cq`99;ypK%mHsgf*#)qdaBCI53uK7k&C; zbRWJWpMN`$C&O*!4kYUnJ19vp-MRgls>ags!ds;tQMvRzHSNxIR}1C8Q$Cl-lyzgX*_Kl?`G_4}UUX@E4VUNn^<;n{}-k^U}kWjY!^k;Cai zNPim>q(iX9Du;g<7G>>YsD0Rfk)ugPt{v?OKx7BMt|dFa&Twmp8qDAsd_TU*MQD0} z2gax$j3yyn7M`zW4~}?0U%e@D2gZo01tVvC7C8bg$g4Hpc=jh4wOF8blewJWJ1OI* z#3o3M(4Y8-8Jjmo(b%O>&H`O38nH6t1Y`T??>0z?x~P13I_cxBPE|1Tv~+Q4HhADA zp~x#)+3)+|O>7d(d|%D2kKLc6Gko3#=NS0!n$|@_#AG!z{||U61_Si8+}zx(jEs!V z{#;YOK;3EKV$jq0Do=qJ&&zsKb3lrcjmP{#!!p?X;U_fo4YU4};DM!mt~AZ3?DqNs z(xQKV5FYm|FT{(Bh~#OecR-=^5Y3 zhcTa`$4{Pw;oPi@7e|Sr+Jl$cJ>8S>Po9ej)?2u*>Gp( zvK>+sqisN$aO>FiaqkZ?LQv}_ytDBitC07HgzK#!W}VqqwlNED38zZ#%j>=zhTiz0 zauw~E5g*f*Wb|I{1u<`k;le2`uKzJU7(TDnn|?<{Wq;Q&UygGhJGF5amoog|G1I2E zYOyyN-E*#YZ=UA;wRQbUh7?pU3AjyP3aqwZd|K%K5CESS4y=bCLIGDM`aAo%!_M`) z`iL=%G{O|d8uGC@2;?8$YYBo;uexQ&D#r-phG1d+FWsfgWaHTc+KrO+d}n1^Kq3j| zZ$Dp-TV(rZ96zyU=lNAbf32gXHT&q!OY`lmlu&GKZEd``Vh|V=(_iUqIqlruHfgC| z)dQcuyq0X1nsr1C-CuaG21!h^gaHXLHL_;2u~4EE2fdV)P*!F0S_=JT38;#qSNQW9bBRd7)k3Gm_MKz7sd{ zM9u0D^;kigJaqHiHE9M$pFMllF;S>2Pd3QZf|yh#Uln!YQ2MrUS5<<|a43mePDZAV zv}eSMYZDBMLo;iy0jmN7O}7#;<{-ad38j0)B~o|b5zR{FO-&biyas_uA2k4W(7n+l z`RPs1hgR7h>s&$;p6--_EiIWZ9}Zv9uX|;CiW{v1(nA~7Ju;G%WR&Xufof)ETAbT^ zID`s{cq}Xi9pE2B3(Y@0XK_`Cbtl^CJMkm@6?r+s0U?=?G_=)=;ayU60yZ50wVgxo zw9LNP==xsyvdCg}P3ODqY)~RjIxIC+t-t?jUs8{G^i35vsli zgnj$4FtfhCt}H4d^4lM;Ds893)HWCEX1PWh_o!>H@Y6^5ZarGW+6(TcgB{qw+EtP%rLSakNn97#AsN13o!RI=#u0>$+d(#OF90oFaoA{^Q z8;EOUe*IoP1Fx=|Tea0c|0s{F4SFUAraQ2b0bi8?jeWR|)Bevb%v-M1cFKV-g~k?13(-^XIG~9i zUk0w}OY}K}JSNA-ZIsibx`7fLPKiGz;N5{Wk%HQawkBE}EKz*u zdU7y_B7|&_>x3gz1ScZR^PfkGAA5! z6>&WuK{>-r+V6D0520roUH8{SFZn)yzL1@jg^7)gC58VfChq)P>i6abj6Ne$h=~HW z=j?xzl9E=p#`E*bndMIk$~v&FU zvh7i2m2`|Tv$eH76!T7f#By3%zZXMC_^=zVpfPwIw|04W_F9=;c`31KetsSbI#Tz( zzYydbP}0`cRxQ-4lC3%C-%GT5nzGRaWX*m0G*4L?UM;-K#rtH<{yN^$vb;$52s8Qw zN|?6jw}*XlsfP3C80kBH-3jB3xLqQj+aw8Aq`|lbxyhH~4>`3NK{K&ayZ5;264=~- zerX(*EkG*CHJ>G{@T@Oj@Xq`L0W?iluj==#$%?pJg>AWG2DfyY>J@yya~}iW6^CtD zwpo}V(zD6o!{?sh9n1KlWucgz_dVd5jgc?-(TRzo!iQ;IgQvhsDkFYqF=Y#&x69ih z>ggLeB-DYi@_e4+ExvAMW^<)MLf9G{g}Rsv>jwY*P(qIb>xVbjxrL#ifqhmvdjzs? z8g^1(p$05*Hm}U*FcU*_eC2^l+j6LDh!I56QJqs?r{?5MI-kxMa8yN7FWw<`tT_l% zH9XV09d~HtYK7+7w%n1;(O0ReVjkSw+&qQmC=GqV_%zZFnC%pgkAF)w=-XW&Omb-a zDs@{_qt|%esoB39XE5PZ<(BuiY-Qg1=Ef!sI+TXxlF{Z=LAORzsM+OYfX@4~t$!W2 z*nyc`p9i5p7#d;*6eV^#tE@-nGA=2`qB~CQ^&%uzoj#YI3aO8*_TO^b>Q+bY6iyLAWm8L}gJn4X_+9q?UuKXw|& z9D3HRB70?yu*QGm4DZu`_{d8adSwc=R8%;(N}KaGt0F3^LfzO1TL1gP3R?2 zHArUk-zSNHpSFdcvxA?Dl9R8?4FOUxDVR7+N?c0bR7z4w7N#U6B?^Nn!C)ij4XOXf d;OXt`<{JF}8#-UJNZ%L$J#8a+y{3Ki{{XBZNe}=4 literal 0 HcmV?d00001