From cbb6f906ecc8b05bfb3b3f2df947e576c4295db1 Mon Sep 17 00:00:00 2001 From: oddlama Date: Fri, 24 Mar 2023 17:38:28 +0100 Subject: [PATCH] feat(zackbiene): deploy self signed TLS certs --- README.md | 10 +++++ hosts/zackbiene/esphome.nix | 27 ++++++++----- hosts/zackbiene/home-assistant.nix | 37 +++++++++++++++++- hosts/zackbiene/nginx.nix | 47 +++++++++++------------ hosts/zackbiene/secrets/dhparams.pem.age | Bin 0 -> 1210 bytes hosts/zackbiene/secrets/secrets.nix.age | Bin 551 -> 721 bytes hosts/zackbiene/secrets/selfcert.crt.age | Bin 0 -> 2385 bytes hosts/zackbiene/secrets/selfcert.key.age | Bin 0 -> 3690 bytes hosts/zackbiene/zigbee2mqtt.nix | 26 ++++++++++++- 9 files changed, 109 insertions(+), 38 deletions(-) create mode 100644 hosts/zackbiene/secrets/dhparams.pem.age create mode 100644 hosts/zackbiene/secrets/selfcert.crt.age create mode 100644 hosts/zackbiene/secrets/selfcert.key.age diff --git a/README.md b/README.md index 69e1e44..68f6a26 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,13 @@ all commands using these extra parameters, or permanently add the following the plugin-files = /lib/nix/plugins extra-builtins-file = /path/to/nix-config/nix/extra-builtins.nix ``` + +# Misc + +Generate self-signed cert: + +```bash +openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \ + -keyout zackbiene-selfcert.key -out zackbiene-selfcert.crt -subj \ + "/CN=example.com" -addext "subjectAltName=DNS:example.com,DNS:sub1.example.com,DNS:sub2.example.com,IP:10.0.0.1" +``` diff --git a/hosts/zackbiene/esphome.nix b/hosts/zackbiene/esphome.nix index 73a5a0f..6d1df01 100644 --- a/hosts/zackbiene/esphome.nix +++ b/hosts/zackbiene/esphome.nix @@ -16,26 +16,33 @@ ]; }; - systemd.services.nginx.serviceConfig.SupplementaryGroups = ["esphome"]; - systemd.services.nginx.requires = ["esphome.service"]; - services.nginx.upstreams = { - "esphome" = { + systemd.services.nginx = { + serviceConfig.SupplementaryGroups = ["esphome"]; + requires = ["esphome.service"]; + }; + + services.nginx = { + upstreams."esphome" = { servers = {"unix:/run/esphome/esphome.sock" = {};}; extraConfig = '' zone esphome 64k; keepalive 2; ''; }; - }; - services.nginx.virtualHosts = { - #"${nodeSecrets.esphome.domain}" = { - # forceSSL = true; - # enableACME = true; - "192.168.1.22" = { + virtualHosts."${nodeSecrets.esphome.domain}" = { + forceSSL = true; + #enableACME = true; + sslCertificate = config.rekey.secrets."selfcert.crt".path; + sslCertificateKey = config.rekey.secrets."selfcert.key".path; locations."/" = { proxyPass = "http://esphome"; proxyWebsockets = true; }; + # TODO dynamic definitions for the "local" network, IPv6 + extraConfig = '' + allow 192.168.0.0/22; + deny all; + ''; }; }; } diff --git a/hosts/zackbiene/home-assistant.nix b/hosts/zackbiene/home-assistant.nix index 88a5529..6f42e53 100644 --- a/hosts/zackbiene/home-assistant.nix +++ b/hosts/zackbiene/home-assistant.nix @@ -1,8 +1,11 @@ { lib, config, + nodeSecrets, ... -}: { +}: let + haPort = 8123; +in { services.home-assistant = { enable = true; extraComponents = [ @@ -15,8 +18,13 @@ "zha" "mqtt" ]; - openFirewall = true; config = { + http = { + server_host = ["127.0.0.1" "::1"]; + server_port = haPort; + use_x_forwarded_for = true; + trusted_proxies = ["127.0.0.1" "::1"]; + }; homeassistant = { name = "!secret ha_name"; latitude = "!secret ha_latitude"; @@ -60,4 +68,29 @@ # - auth for zigbee2mqtt frontend # - auth for esphome dashboard # - only allow connections from privileged LAN to HA or from vpn range + + services.nginx = { + upstreams."homeassistant" = { + servers = {"localhost:${toString haPort}" = {};}; + extraConfig = '' + zone homeassistant 64k; + keepalive 2; + ''; + }; + virtualHosts."${nodeSecrets.homeassistant.domain}" = { + forceSSL = true; + #enableACME = true; + sslCertificate = config.rekey.secrets."selfcert.crt".path; + sslCertificateKey = config.rekey.secrets."selfcert.key".path; + locations."/" = { + proxyPass = "http://homeassistant"; + proxyWebsockets = true; + }; + # TODO dynamic definitions for the "local" network, IPv6 + extraConfig = '' + allow 192.168.0.0/22; + deny all; + ''; + }; + }; } diff --git a/hosts/zackbiene/nginx.nix b/hosts/zackbiene/nginx.nix index b41df56..069529b 100644 --- a/hosts/zackbiene/nginx.nix +++ b/hosts/zackbiene/nginx.nix @@ -4,41 +4,38 @@ nodeSecrets, ... }: { + rekey.secrets."selfcert.crt" = { + file = ./secrets/selfcert.crt.age; + mode = "440"; + group = "nginx"; + }; + rekey.secrets."selfcert.key" = { + file = ./secrets/selfcert.key.age; + mode = "440"; + group = "nginx"; + }; + rekey.secrets."dhparams.pem" = { + file = ./secrets/dhparams.pem.age; + mode = "440"; + group = "nginx"; + }; + #security.acme.acceptTerms = true; #security.acme.defaults.email = "admin+acme@example.com"; services.nginx = { enable = true; - # Use recommended settings recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; - # Only allow PFS-enabled ciphers with AES256 - sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; - ## SSL config - #ssl_protocols TLSv1.2 TLSv1.3; - #ssl_dhparam /etc/nginx/dhparam.pem; - #ssl_ciphers EECDH+AESGCM:EDH+AESGCM; - #ssl_ecdh_curve secp384r1; - #ssl_session_timeout 10m; - #ssl_session_cache shared:SSL:10m; - #ssl_session_tickets off; - # - ## OCSP stapling - #ssl_stapling on; - #ssl_stapling_verify on; - - virtualHosts = { - "${nodeSecrets.zigbee2mqtt.domain}" = { - #forceSSL = true; - #enableACME = true; - locations."/" = { - root = "/var/www"; - }; - }; - }; + # SSL config + sslCiphers = "EECDH+AESGCM:EDH+AESGCM:!aNULL"; + sslDhparam = config.rekey.secrets."dhparams.pem".path; + commonHttpConfig = '' + ssl_ecdh_curve secp384r1; + ''; }; networking.firewall.allowedTCPPorts = [80 443]; diff --git a/hosts/zackbiene/secrets/dhparams.pem.age b/hosts/zackbiene/secrets/dhparams.pem.age new file mode 100644 index 0000000000000000000000000000000000000000..e49ceb2a626b465e620527c58dbed54de07d60fd GIT binary patch literal 1210 zcmV;r1V#H{XJsvAZewzJaCB*JZZ2ZINVt7zSRWV3QNO(n3LuoR3R5e9ecUcN=aYS7vohF-c}IcXnzsae4}DX)rWdMnp|^Q+ZHKa5rsZ zM{!koWOp-YM|UwzR#N2~_j~mA~X^4C>@Kd_P7<48<=t0ra{NS>9;D zCi&~lS^8{IyRvghVE1^fcjnVjN<&$QOyTVokI50w=SvoJ$z?M`>Sbu>rQAmxC;nOb zM*-KMuxB?-LIh-&-YoqMcjfW!^Ftgg6G3&&14a8#Gfr|!hm%YmM2#pxElYdfzeWXs zuWhIMQU#JicpO5ZF<>UnZAMDQ-}%i_}P zk}Mg``l#^l&?Z-EdDuCU)|HFyoj(Lr}P?^Tmw$f!GO^>H>N^A9-gT5UG`8|jRdF~qGHXw3HaTx% zD?@WfK?+PkL~>STH&;%2LNP-!Oie{rR#tgPL}6HFFEe^cW^H&`S!XMDIde5_Sqd#a zAaH4REpRe5HXwL$Q)M_&AVD~AXHGdVZEZJERc}ptaxX_jY=1&jXIf7+Qdm?lSwmrQ zWNu7OOm;zcIClzqV`)}qH*7*NdPG)IbZt&$H&QfVb3tfoXk#yNGc#pvWqgaH!Wv!Wnpt=AW~3lL~kiGX&_y3b5VO>OK%`)dOsuzD{*WyLP9rk zD@0gsc1n6?LVrecNmoolYDG~|Q)W4NSYudIa7s`$W;IqraCKr+LN9b^Y+7kSS4UMV zYBzZ>ZwhlqZb39NF-C4@bZ}^4S9NM*Q8H0xc{WvHV|aIOFG5O2SyOE^ZC6t;WHWbH zcx_ovRdh{iby;~?W^Yh=L^KLaZ!t*szHGg4qHZ)LJF=R_cT6arzWlCC6 zYfy1CZC7PYWo0l}S8;YjWo1i23PT?z7k4|_4)pkP*^Myr2Dll#6|rG&cHX>n*Y5d` zIQR79$;lSSs3e6N!DxT+PHB2045E{DjYg|GEbHyoC!sx|vJ}P+Z@Ik|0?gp>oxa{% z!!eN%U4O}9(?zZbB-giqG*H2Cf|$Q>ZMS)#CEV&+m?j}ksZoO>Wb@U$+zQ&FY2;aE zw?-RT`*aF&l9fGdGBF!S)GA7HYm$*RvSB5+PnLroMSAW4v48N;9C@q2z%A7L0&m#@Ubhuc delta 530 zcmV+t0`2|L1*Zg%Ab(6RIC?cRcraQqXhcP3O<_@2Sa>-}PGe9scxQ4sYh+?}G*(VC zHgt7SK?+k*GI%v_YD`pVGE!z&FH}-dL1js3S2I{NWjJ@Yj|pDdRJ30b2c(bD_BfXHc?qjcrr|EG*D+b zFGUJ1J|I|PEoX9NVRL05T3K*6AZ9;SF=as@eLD(gL1T4wHZw#oS7u9EOLj*{aCS~q zSa4`7Ge%KXFn@AUXKHmXlq1jL@QZ!Z*xXaWO73`VpU6LQ)6mT3Xhw6gV3_z-1nNzG%~h- zZIii;{0D{9>4&%`=ghHB9pej#_15&63=VwKTPw(IyMH&SBrd|C-ArnsFjS;EQ>GeEPKI%g3ThY7MIHss`WvMuZXDrN^vPwdnT5)kL8t!Q| zSvg!L`Y$b6I{};D5%_d}T(JX*{!j}8`+tIz#@RDDCb-@lcBx3_#|SxKT;u2k2<7n1 UBw*^GlMA80BY9i+e&ZPB;0wskk^lez diff --git a/hosts/zackbiene/secrets/selfcert.crt.age b/hosts/zackbiene/secrets/selfcert.crt.age new file mode 100644 index 0000000000000000000000000000000000000000..8b8e1d91cbdfd1428c956db6d916937f7c67439a GIT binary patch literal 2385 zcmV-X39j~GXJsvAZewzJaCB*JZZ2hId)-XVrOb( zNJ42vHDPyZQ&ezRM`$l>3YDFW23)_-@0QIbF@A`-f7j_$ zF(F9eIu(02Z!$Bim>Z|kmH@2@G7{XPRdSLw`o9hgj3shRXge&S(#4kvb^f_ z?ctkX{?3#ILkthHe2p*-W@hR(k$ZrR4ZN;J@OKrH?#DPX@P~)!HlG4oo_VesFm|qx zw054OD_Mo%BQ7}ajO4WVq2tskN}%{QiX!3A7!vci z?QOFx-AxwCQ-B_usmbSX+{rS8^lD5||K@e>V*4T;@$Dv zQ91S8jAu+9mY~+oNFE7Aie>{lB!OnwmwKgV9WR`3M?e{|#y(U7VJeCJq#=zr&$z32 zSi@&;T92Ko;-86Z!D!0qtUkGKPXKGC@|SoBg-=^rU{k|@t+D<0RsAu}mqd91kTQ$E zHY!jImn)!#{{*T2H<^_5;)}}UWpb!t`KWsb?KvsBbyyW(3sIFu9jFn<#0=pDvPnNR z>Jmgoqa)6)sPzvMf`di&n|1kZgh+Qy*6dtCAHX&w2KvKesQy%Mq%*wo-@{9H4IV!D zTIr^dW9+wb6Yf4VnHb2t1&~7`G3I+9dE&l+L~mx6mGLo1=8~sg3Y%yOlH?Ovoz3_QAkXz92*Dm_&o*M@D?~TiS zKvYA-7CR}vbgtwTYSeX*eu37f!HXC3A8VmihL5g%tf8a&?_%rb7l&{cOtSTBVWuhI z%{wztzR`10HxbQn6BIlM@dD;$x}M({9Pz@eRZFave(MHWDJ3eI^aH1^W3W+QD z*pMnnNHG(mKjdX88VWC;m^1dN7xA7-PzI|=`SSKFBaU=T#+>R0SkN($W?a2H*I$-J z{Z(Q#qht8j0>Q=l!y24Nep$v;gtyuly7BkS?u}=#y>_$)TwGQ;QjNAfZ*AUHMQyWt zE1>g?I8SROoCNGfqpSg;mIrnBnrK`>b*!>54h{)M_Ak*`Q9HIArE)Wt197c^*;7fM zxY|^;Kyjh5n8rBRKiC~PA6okDJ4xZc2aA!DT_fWgN`=7Md?UX^mjxbM^qnL?-e^z@ z7BGWSLyWLXILLe&JmicBop;-vm8MRNAL{e}iWu@yGE@Uxbex5%hK(kDjv;t<(rv0W z6vvq&jhgMY%YH@)O~Jx*bp$Mc*!*4*K$Wram9+z8q5=ON3FrK;(@bhYo;*t+u$N9Uw_c6#$V% z6)3vF{TWbthm4IBL0OWKA&60NMdJGcZUY~W>PlYxWfE4w&mfXo!XOhFB=J6s57VQK z;VpC2ded_9IIQ)td$Qw#&Rm3fztdw5>_3L^BlVzvp`LT!A7wI+vs+4Ys%Il0z6xA3 zO-tUHOoIL(b$k=S%=5ybk$l(ja}0*sq9PASm}{Q1nOP(Gw-Bx;xnVGVem@33V3sXV10ofS3MuKD$(F8U>6s|vH5{rX!pfFT)-+D&H6*;2 z^r{{ksa0O|{`r0u`sREJIP^|62UnVVJGZS0+<%`xA#Dd2ELdf4Os&jozux9%a(B~e zS(gmYi~@SB4K;UH0{WU;d{;hqW#-(Nz^=n$hDlB(MA8a8A=nKpB=A}PDz1gZKZsOB D;~q32 literal 0 HcmV?d00001 diff --git a/hosts/zackbiene/secrets/selfcert.key.age b/hosts/zackbiene/secrets/selfcert.key.age new file mode 100644 index 0000000000000000000000000000000000000000..4d54ae4162c04bfbc4ae59b9912c90d8ed16f96a GIT binary patch literal 3690 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 IF2FXeqoPgcoB#j- literal 0 HcmV?d00001 diff --git a/hosts/zackbiene/zigbee2mqtt.nix b/hosts/zackbiene/zigbee2mqtt.nix index 93e6e3b..df5e07e 100644 --- a/hosts/zackbiene/zigbee2mqtt.nix +++ b/hosts/zackbiene/zigbee2mqtt.nix @@ -1,6 +1,7 @@ { lib, config, + nodeSecrets, ... }: { rekey.secrets."mosquitto-pw-zigbee2mqtt.yaml" = { @@ -10,7 +11,6 @@ group = "mosquitto"; }; - networking.firewall.allowedTCPPorts = [8072]; services.zigbee2mqtt = { enable = true; settings = { @@ -25,7 +25,31 @@ user = "zigbee2mqtt"; password = "!${config.rekey.secrets."mosquitto-pw-zigbee2mqtt.yaml".path} password"; }; + # TODO once > 1.30.2 is out + # frontend.host = "/run/zigbee2mqtt/zigbee2mqtt.sock"; frontend.port = 8072; }; }; + + services.nginx = { + upstreams."zigbee2mqtt" = { + servers = {"localhost:8072" = {};}; + extraConfig = '' + zone zigbee2mqtt 64k; + keepalive 2; + ''; + }; + virtualHosts."${nodeSecrets.zigbee2mqtt.domain}" = { + forceSSL = true; + #enableACME = true; + sslCertificate = config.rekey.secrets."selfcert.crt".path; + sslCertificateKey = config.rekey.secrets."selfcert.key".path; + locations."/".proxyPass = "http://zigbee2mqtt"; + # TODO dynamic definitions for the "local" network, IPv6 + extraConfig = '' + allow 192.168.0.0/22; + deny all; + ''; + }; + }; }