From f48b25dfbee52614aa082645bf82a918085df6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Gro=C3=9Fmann?= Date: Fri, 19 Jan 2024 22:33:03 +0100 Subject: [PATCH] feat: paperless backups --- .../generated/paperlessHetznerSsh.age | Bin 0 -> 1108 bytes .../paperless/generated/resticpasswd.age | 15 +++++ modules/services/paperless.nix | 55 ++++++++++++++++++ modules/services/samba.nix | 36 ++++++++++++ modules/services/vaultwarden.nix | 3 +- secrets/secrets.nix.age | Bin 5013 -> 5093 bytes 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 hosts/elisabeth/secrets/paperless/generated/paperlessHetznerSsh.age create mode 100644 hosts/elisabeth/secrets/paperless/generated/resticpasswd.age diff --git a/hosts/elisabeth/secrets/paperless/generated/paperlessHetznerSsh.age b/hosts/elisabeth/secrets/paperless/generated/paperlessHetznerSsh.age new file mode 100644 index 0000000000000000000000000000000000000000..4ada6591726d8e16c3cdf1e8652c68b80fe28c3a GIT binary patch literal 1108 zcmY+>`)?Bk0KoAH#LWUiLKKYzJ4kS&E7vR6mm}!W_S#-=eXO@zS0K=K*SqWWde>|3 z(UV7v@{}-iF)VJfO+^u1V3`8~)9IKX!EIqE8eNzez-@p!H3;$pJ`#W6FZkq}Z=52H zWHu=lg#yE8SMVYQ$e_-+S|2rAETBW*$lB{nX-}B&&@3MKcu1s5YlXLk(2U+9(v=p-@zLz=|Oh<5To7Poy=BU^$pI@gW<)`|P0_ zIY1()$fXED5kN&EBWit|2xN89dJ3wAhytCCx)Vqyi)B$-6$vs2Bq0|bTN%J5z(U5o zn4fyUvdCPh5Z1#EB@qm;m`%*kkUq&Nage?TtpB@!OxVYyHPC|+q`lSO#EIHykYXXXVzz2gpOn;jV24HXrf~~L7b92<<(OKLr=y%`E5sZPTn@HDa*k1J z6!U+-Hi||{B;$Ef7fhHeT0LZqBYA}KHpH=ix{XHtN{1b7ba@N{pFnJcSAyvXmX>`{ zdrplpx zY1^0mfxd6%!BI|TjY*XQiic0Dif zFMEFfv14*bn}AN`#(tRxo*(|B0y(ka%y`d8Qy0?sdERt5yzccf{doJKrnCAhcYf_j zX%o*$B`>~vH}%ZI|2jHv>G&t@=kE6o1=_kgzB~BBlfB)xsfU+e+IhNi0@$lIgFp38Zr(KZ zL%+1?ql(4o?dhtrbE;H&CeW8^!%vnCM@ohty$NV7-c$FQW=PwEYa&|p2cxm=$JTT0 z<+1YZx+=a=d=Lci`O4;|w=^GQnK6JKa-^JGV*H=F6oYB7I mwW}{B688qs17^@UIQmq>z?Ng%M;DLVT3foyr}s&xJO2jZ_`1&k literal 0 HcmV?d00001 diff --git a/hosts/elisabeth/secrets/paperless/generated/resticpasswd.age b/hosts/elisabeth/secrets/paperless/generated/resticpasswd.age new file mode 100644 index 0000000..ef4aee0 --- /dev/null +++ b/hosts/elisabeth/secrets/paperless/generated/resticpasswd.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> X25519 k9S1TqxAKH41Lq6xpAYBaMd9f90qCAQmyxrq0chU+Tc +irgvzLHOIREuCUA2k1+FnxZCXNTIpChKE3uNN5l48OA +-> piv-p256 XTQkUA A/Jy50UrN5mbigxkQI5K1Q0FQTor4ocPQh1YJXYnWMvl +z73ZTKho/qeVH2XyneDKUxw+eg2FrHDfrllHVaj3s5U +-> piv-p256 ZFgiIw AlVTQpjtIYs7vQ/M0jDmRzRebsIQ+Kj39qyeQk1OIwZ+ +jAPOyDEuginirLTSUFJ2oW1VsdpWN1ASdfR7ybU+G0M +-> piv-p256 5vmPtQ AhiueRGQs93xrLgEwnhC/G3GZfB8WnU/U6fP4Zoj6CAm +Zrx69DLkn13YXMPzyVgzKCakPwMuuqhc9ev1JZ6O19o +-> piv-p256 ZFgiIw ApvxXQDq40lC1AHIi/Goo7zdxBNMzdyaICbc99l+7AKV +HaqccPBNp4O5HG5HXqkV4ks6/egCx83KTHFNHek8/VI +-> "[q9C-grease &e7[}5WO @C'4x = +3OGP2dJt6w +--- 0GHa/cHUag5xe+LPDSEgHvSWTi9tNDdaq1FQZIsK2uc +Ǩ`pc' ,ݜ8EBG%FtŹKVN~ TJ2IVa<I+F띰oO> ە \ No newline at end of file diff --git a/modules/services/paperless.nix b/modules/services/paperless.nix index 100fd34..41fd77b 100644 --- a/modules/services/paperless.nix +++ b/modules/services/paperless.nix @@ -4,7 +4,62 @@ ... }: let paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}"; + paperlessBackupDir = "/var/cache/backups/paperless"; in { + systemd.tmpfiles.settings = { + "10-paperless".${paperlessBackupDir}.d = { + inherit (config.services.paperless) user; + mode = "0770"; + }; + }; + age.secrets.resticpasswd = { + generator.script = "alnum"; + }; + age.secrets.paperlessHetznerSsh = { + generator.script = "ssh-ed25519"; + }; + services.restic.backups = { + main = { + inherit (config.services.paperless) user; + timerConfig = { + OnCalendar = "06:00"; + Persistent = true; + RandomizedDelaySec = "3h"; + }; + initialize = true; + passwordFile = config.age.secrets.resticpasswd.path; + hetznerStorageBox = { + enable = true; + inherit (config.secrets.secrets.global.hetzner) mainUser; + inherit (config.secrets.secrets.global.hetzner.users.paperless) subUid path; + sshAgeSecret = "paperlessHetznerSsh"; + }; + paths = [paperlessBackupDir]; + pruneOpts = [ + "--keep-daily 10" + "--keep-weekly 7" + "--keep-monthly 12" + "--keep-yearly 75" + ]; + }; + }; + systemd.services.paperless-backup = let + cfg = config.systemd.services.paperless-consumer; + in { + description = "Paperless document backup"; + serviceConfig = + lib.recursiveUpdate + cfg.serviceConfig + { + ExecStart = "${config.services.paperless.package}/bin/paperless-ngx document_exporter -na -nt -f -d ${paperlessBackupDir}"; + ReadWritePaths = cfg.serviceConfig.ReadWritePaths ++ [paperlessBackupDir]; + Restart = "no"; + Type = "oneshot"; + }; + inherit (cfg) environment; + requiredBy = ["restic-backups-main.service"]; + }; + networking.firewall.allowedTCPPorts = [3000]; age.secrets.paperless-admin-passwd = { generator.script = "alnum"; diff --git a/modules/services/samba.nix b/modules/services/samba.nix index 1728daa..4ecc29d 100644 --- a/modules/services/samba.nix +++ b/modules/services/samba.nix @@ -234,21 +234,57 @@ systemd.tmpfiles.settings = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { + "10-smb-paperless"."/paperless/consume/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; "10-smb-paperless"."/paperless/consume/${v."#user"}".d = { user = "paperless"; group = "paperless"; mode = "0770"; }; + "10-smb-paperless"."/paperless/media/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/documents/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + + "10-smb-paperless"."/paperless/media/documents/archive/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; "10-smb-paperless"."/paperless/media/documents/archive/${v."#user"}".d = { user = "paperless"; group = "paperless"; mode = "0770"; }; + "10-smb-paperless"."/paperless/media/documents/archive/${v."#user"}/.keep".f = { + user = "paperless"; + group = "paperless"; + mode = "0660"; + }; + "10-smb-paperless"."/paperless/media/documents/originals/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; "10-smb-paperless"."/paperless/media/documents/originals/${v."#user"}".d = { user = "paperless"; group = "paperless"; mode = "0770"; }; + "10-smb-paperless"."/paperless/media/documents/originals/${v."#user"}/.keep".f = { + user = "paperless"; + group = "paperless"; + mode = "0660"; + }; })); environment.persistence = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: lib.optionalAttrs ((v ? "#persistRoot") && (v."#persistRoot" != "")) { diff --git a/modules/services/vaultwarden.nix b/modules/services/vaultwarden.nix index 914f64e..dd8c3e9 100644 --- a/modules/services/vaultwarden.nix +++ b/modules/services/vaultwarden.nix @@ -28,7 +28,7 @@ in { }; services.restic.backups = { main = { - user = "root"; + user = "vaultwarden"; timerConfig = { OnCalendar = "06:00"; Persistent = true; @@ -75,7 +75,6 @@ in { smtpSecurity = "force_tls"; smtpPort = 465; }; - #backupDir = "/data/backup"; environmentFile = config.age.secrets.vaultwarden-env.path; }; diff --git a/secrets/secrets.nix.age b/secrets/secrets.nix.age index bf36d7468788d9aa6461db5a2553f30ba4cc070c..93dd8b3d00371e604c262ff3c9fc7b6112352969 100644 GIT binary patch delta 5091 zcmV<96CCW7C*>!QAb(CwT3T9BQ7bo8Ge&DKWLi&EG&N#5FKSY5F)?j$Hco3ua%6RM zOmKBmX9_Y&cyvQEF?niub3}MiLu`0hVRc9=P;hZYMRHL=X--i|bag~VcS2@%cM2^& zAaH4REpRe5HXvA3QEOE}AVGL|SwvY_Y;Q+TIeBz!Ycw}vN`Fj2aCUEOIBIHlSV>bw zb2u_FL2@)=S$7I!bt`67PdP7QFE~+4FlKslXj(8bIchXmNKQy~Ia*|MFhxvaQB6=} zVo3@uJ|J*ub}eu+H8vnxMrUbBcOXG)Sw(YkQ*>%gVNQ5BWp-mudQ3K1a7#FLW@|w= zbuU&^Ycf?wIWbmcZD>mhD>!jtL}gKDFfwImLv>9~G*NU5PhXisV@MnrHhS#MfQWM+DIRWw(6ayM@ZEj}P{ zX?87eGBq|JT1IDSNp~PYXJkP#Ib$?>P+?dzQZZz6Ohz<+b5&wtae6gqK~ZZ-c2sO< zN@PxAH+4*M3OFz_dO~n{cUMbOOgU*uaBOX3W;i!gY-vPFOH49VNJ&9&M{+i1OH)O2 z3N1b$Vor8gMK>`yEoX9NVRL05Vqs%U3Uf|Pad~NNGgm@0RZ>iCY-(n5Qe$*uH*HjI zQFB3MRckbVVP89;GgxIcM^FkYXf=0XIAKb6D_1K+ zXGAY>ZbLzJP&jTgHELoCEiEk|NKbQRX>N8gXKPhZX)#b@OiofqPDOf9X;Do$YHmYV zM`L^yml6zwKNgbEic_ zZ*dWSZTg3n7<&`vE=$kl|Mz_lLK@D$I=dOcOGUoFiHFB1s zukDnCOnmd%-sg?C9?qkpj^j<=Q8p#OQ90x7|A1g&!|M$cbMf7~YOd7M{o6^f9U3fO zX;TioHh=5?a!6J^=fSnjpCaO_;4jLftVySv$YCZ(fI&^^FN2>Jw+IX6jhVyFmF5;CEDi;xJTH43APH7BRrPluJ%Wym+ko z_cY;tKK3T!-R210z|6}vMf!B7n$2U$@9{#3zHS+HgUC>veRi z_fBwY<=xw*C3@Y-8a$K8p8UqU5y-;(yl7JbJl-P>CT$rgg#UpJ4t}wpfdNCwzA>0k z`JAjUU!W=`t<8L5WEhg2R$I{fzXw6r5}`9pRo=+&UN`{9T$Fpe8e56LhO6L5E&_?N zVPrvpu)MAa%S{x>Z)(AcuG(OK8BItt$d+mWjCkmGx!f(o%&K&bupewVG`CJ)I|mx9 z!=K#-xv)M@tL*M%Or!=o(OBAtcoYDV1uOHJ9r{B+(_| zK!gYV-i+8oDsW|F6Aexb!oAmjx02oEUSq23W-5aQ#u!NsW!=D(TGlXs+6oCeyzA%B z#9?16qvn3xh5>I5vUs2MVBMZ=vpt+4dv`c6KRdo0V2u?a{XgnP_TkDcOUK5-JYB$4 zRYSeJ-vLDpi7OAaQ6?Z~R2Fg!N^~YZ7Gs77&66uI`d`(jp3tEtn0>#MI9@wNC3EJd zsWL=&N%-*d3^%%s7F%Nk{JbJk?Txhv)D=(mbe`Vqiwa~3Sp*mDh87&qGq<2x_m{vxDh3aEAWd zAZhdc7-p8!5yLG^i>XTKNuZWR&{d^rU+!$*w$q9rM>(l~F@^G&KE-nFXnfH?>K|nw zZ0zMf*(fS!boxjGaNK(UG%_nyCwoU$gN}AIPSx#ed`DUuF3rQs;cQ|5l6+_D+iQx_CQ6K2}ieH%9&F(+3E6BA0r<@shm;0?eF;7;YNHThjgeIA1`bN%#eQXHn z*3?u(S$}|ikUdGHHFom=`_@rXfbe)MEHHrd@HfQq6D2JS z_^Yg$d}utU1Yzlzac-1;3uaZT>7VY@^%fc^*o@tOx}wR-UqnK$hxr7$eE^8+zfS&8 z83!Z#;}sc?MOO^zJM4k*WxDaD&>m0s7#6kY*l8VORhUjl03eq<3zkw=pWOzI@n^qU z^NATl`UC|;7W&AJ5o#scBr?5(7W(qpLimims(|;nb@x-isq|+3vk&gwoih*GdP+EUcb3p8o>6F1MU3&S&`iURl(DJE# zy5T;oSLbIp)ZKzA&3e3tbW(QtvfI89z$JTs$@KdzWjo~?vdRHr5tP~8v@&aMm%ETb1%zoH=fcjt1U(`=jg z6>3|^m7Vb0L@GDU$)U;N)X(3X<DbhaN>#rP~R@3CuBo@zZ00>myYe(p`ymeiA1Yr}D$SgduxptBhbbx-oH)YB z?Zh~k2H@-eyXzpQs;?_gxk>hXz^yQUpt)0i6Uf#0i=}akIN&`ZT*>O98EzgzBP8v^ z{f~)H-f zVAObKwFBNFzKXT#xQh!rz6s2V5UmVG)?8`6*@D?maO}_80^=N7@AohQ)sv$hZ*G+D zQ(|2+UNpdyLXgZ!+XlsJkznqB#Zk=v2w*tx8Y(EraE6Ka6695>@Nwj{B$}tk2Bg{c z{kg&H<&t=?(l?ij(!e`GXt?&Bdr5vYp^eP%U4P7RCt?w;1Ah;#iOY*4VDYowQMlzI zjn%B$A$rfDzR!TWWq+pqd9sImyF|lTp&m1g{EyekQ>=kY+EVK-IiP=k3^ovj$OmaF zuA=~lh9=EAc$veu@UEs}jea7w_Nx(3vy*PQ4kWg#xQJZe{T*_1zRj*08QWu@)BHUmnkyOz0p)r|pJB%3o-HThU1EqB+-`Dz;;nEcEf-6-S)Yy8 zBHJ)EhGK4lJgexbuRdX$20i;}%gq$fU{E zd!`g<1eDt8W1r26V5GW=#j_XmO%th*pzy|Q0tWdPSWdN753Tt#GSptKt>HtasqO!J zA(+>mlORIk3|69l96ecr8gH8*Iymx^Tm&HTl@=q-FBZD0H- zlhUhjW;EEx($z`KUQ0!#(DT?Yv$V$-ip&YAuin(6C-W)Kpt?In5;XyjL$rDX1TL(G zr7@(paJnt+vk}r970;5`=Q!U7`&F3*>;$86`Fm4wj=27Rak>^wxC51MIYCkv@5{^$ z=-~P3M5W@%P{VpRm0q`+)wi3C`;K=iQ<*6=D$WXAJ6U>CWGH3``VzRHRpx(&Pzt(J zGWJ>=zg6AoJPaJd5-rH%<`#Lj2Qvj^Lu?$QjkHz&-RTP4^r3)@)W2VHh33(P2z5ga zg#k@S``7D#wOvZh8DJzF?Oan+BRuRD9BcE&@w;cR=ucIkuY!wO2q1xpFwzN_l3JrX z%fgWrwa_;hPmx4IcRy6Ct?EYFdKv!wi6%g_VyAZS7IB&YYBL=oMchHUWygxz> zzgCHR@n*xO8Jr*ut1|uu7st)0^>>thOyaX+fLXnN4r=Y7fXsZ3B!`{d%fty(QGz>` zaJiDu3*>8W(R7(Q)Rp$&Px_{zJNy<*?x^l6%}2Y%Wh-NKgXvG5%dHz8UGE5#$tRENV70z{09LKg@rG(qe{_11fyhR>fRzy@y7)>PAWp~g~V{}C&6{T+7v4A=$gS1$b@dBVZS9&q!y z*rrAL*g0731T+(WOt!qq_pZfBGypRum!&fIt=4+ZWzycNh`?eQ(At%lXpRtEf(eAF zuYSOJMH0E`Nll`du1lIyt4x0STn9!F(kMteTxRs7??^ee<>LWH<+%=%#HiGlPin|4wXkDr*HE(P>qU0 zY;5a2P>5kv+I*1TjA17othw+*Uo!Pc6>jP1MYzLPcJz6O<6(|7wO7UOAPy1NwClTn zJ;_V5j~SLgiKA4`R`SB~P)!ilmxZ|}1?Z`0JTXLWjOQoiTKtpp66&FS_xsN@x<63d zbdVV|clFfnd&507m`%K7MiFMui+&QynVJD2+EgXy2Nk}G9q9{ZQ-{X@?-+HE4g3H^ zJ({yp_$Kz$J14Ie*Y!M)=HKZO9SePb;HSHx@&$A1O1+dWJi6AS()b2b?ZVk6v@HHw zLAJZ(PnBGaZpL-9S~)gR4#uU3NZHOW6^hqJ|N7DfG;KE#p3_G5x~P>&yo9!gumc3o z8tJ`!pSl?6;hZD^Ww10%ZObnX5k3UC&*N34BhnlfEb=pC`5BDP&Z|Tdj-vCF4 zAZI0n`~ZeCyyY8lspoHG2)6it6V_EsS7f7x2$spKL;unk%CPD58L5iw8;9S(Ivp^1ZT_^7nZVdwRyjdWRB26QOhImAYBN<-V`o=ddNoHYc12i8 zIClyyJ|J*ub}eu+H8vnxMrUbBcOXG}OIdkNRc=T)G-p(JcTQqgcs6l2X=P?jFfmwl zLvna?b3svLQ!#T@MnO{wL{U~NGgnthZE!bJbY?_$b67`nX+lhIXKQd!K}Ak(K}S|t zXi0D}S!i#QPXQHwZ*opXW^7n#HgHujb4qznGdX8(R5o){X;(%yQ+ZNjPH;&~aCJdw zH*!Y`Y&1_Rd31U>b4O8iIc#ioa5QUWcPnmMcu{X?Pcu|ybYxRWQ%g%TRds6$Ej}P{ zX?87eGBq|JT1IDSNp~PYdPs0pctt^FHDhT?aY-^&cQI~%Mp8LVMKXFF+xyPWi&8oVM%Xq z3N1b$G)hQ3E8^R9UWB!ZQV6GTRmSuqR$Z|D2 zaIuVZXUXap246ODx$<%B&X1OQ2f2=txSzy-$e4oq=^$sCbx`L7)SXYzhT58ABi$-d zk3@5`!#v{>v^dO#5&Xo0g6D z@^#MEFT@M``euzf{lI(G?5d-3V3!BW2Wk`jQeYc{2;$&!?I0mYwJ8><^hoj0vDp0y1d zaF16!A~Lnyo;xUH&8bI7I-F#dMO8eUwhnhPi4l$K`o*}(Rc9(1n_X^eq)DWNbL&t# zQ03ZSwAoC3F;-u*YLy5wdzJ>TTsDt?LIP@^*DrQJUr9zF01-u1#4CeR+Fz^j>p=9; ztD?f;GFh_{(u@-j0!6cv)luCq@@w6uo(BfUpeUd`5~|YA!cc|Zv@+LO@Ebhfb~adJ zFU%C)xV}GN8lzB_)hsZE$MTS6mRg)19#G0s)EZOhES^Cvf}mty>Q*82#2g5JgYh9O z9Bn{OI0a_LjWdJE0`ag4^&AQJHm|`>vu}T@x^}RUFDi>)ym&`c2wOj#40*!iKx1!0 z=O!neRyg-}=e&KotZ@8vHvtch>RSpY#Sv&`C3B(S3}NF@w`l1%)uAcUX@ORXl~>Q> zAx76|AdYcd&95vP-xWc#Z*&QNt(z6qhe~~o$86W>`t2#X>N&ipmMtrC**y~_V@xM6 zRvtXpT*Nuw6k=2dW%o-S5&^0|?^6#|XQRa%8KCGp7?M+Oim576KJlBZA5mksoCTyc z6?`R|5BsOC!ZzXwDx-dyN2#T8SR?Cf0}Snr_X(e;+Ay__ot&Fv;arShoYr}NLz@x51 z0Fp6#WG}b`IYM~M#4Nii$GnLImC);TBWf$lr|OiJh&a%mW!-EJi0fc|7#o{CpXjLkN{?=lb(1r zG&`N1K~!_`t5jSkGi2%yypH0uuhid`$?n|2(MS?{zwbsO0ZBpb#kZms4JN)l`Z3_0 zqxS7=7y7Fja7zv90+4~iPMd09Xl!Kxq1F0b;2uO>*R7fBAofLJr4bk>)uY1d6jYgl_lb_=!@sjEVG$^$3 z!CXmniGuw^{f;(&k|Yy0xI;q!am#pBOVQ!Fi>NmY=wtlr?o{FKCWWwU4oFKUUnmi` zOJP0WtPDY)9&uxem^G_sT`QLUShEAy{FX?mX!(KEm18gHBx5AAB6J@JJ3&^vO346zXL>F4sFZlyZcfwzvKKR8f zsDWEy132!WS(H%}Pzu0w)AeSMk&&Dy`HxV(ee(A1XG>+M3ojDQ=no|0srvw{OnfBMt|I=+gK=J-9n%=8&%j5 z(=DSD?f@JHVBMsj#;Y)Wn&$1+ zn|*74@yGa$yfwKC`hbl9MS?}#@#<)PxdiUNj1ZPh%r~7j61!@Zrt|@O{^jR2cps>` zRo=?x*bbPu=~x&pl_yH-3vm|>;ee!r*KLVBUx5ew+jPUjI3_O2fhs92i^0k$R|#0& zgY2aV9u|C`z5h`ws2#ocwO=qcHt3kC)jITlzkFCgm^G{R5>3{=qhRp{-F)#*gyhXF z>QwI_xr*BnEf>KIweN-Ui>Mxp9rIGAyHt;sc5*68u91P+Qgk^l`4De`Cs1ugtWPWbBE* z``2KXGKx?#o1z44-fwWOr-NVDyjRenyMh#?;CQ}DK!`7+b4pxG4{%+4@iR44Y$b{y zFFX4&O%k$p8|ipZA|w0nhqsDO`S*80RGjF= zxk?>230uFApWXGA3Jbw(EpKIH1h)Fb_1i(-miFX6$C_9~|M?A=6-Z})PtPI!=dH!e z78&WnQsbN97vmusgt$e-L|bX0!m|`+MGh&C6iss$E6h{FPQE zKf#X6u-0#z3hHip%*etJm}C30k>Z9LBGw9v$$~nrDT3GOFhz3y@h&I_p?*wt?bLf= zf6^8Zs*D9j(u7$;o>82C7jXi;;u->!*cJBDm)Nu!*-eU)UUbuli+xPAM2k6JB z23BLHJ=(AiWJ>I#%4t`#z^wB)1!&P4oU8rNQjtQF`a5a|`X0vQc`7pH-S1xNO1?e| zQxp8m8in;V&1-5OY<61KhXl76z4laEau7Xnq~gz=Kuox6&LeZydJYZK?!}0iSjNoo z_5zpYq$#ldar{PqpaRDivTGAqZxcs05`~i)8)a|Nr%cl(@WkQ0Rk~t{xpM0LS+dYG z&<6b=p1?TY-d)jzP}?~dPLVnUv?J|>=j^IIuxwR<$@Mig&3?L=7B3CTQ4_nW1-39a z2WTr5N0F?~zGpFD?`k1aSqAtjRrsuC=jDA(hz}>h|8p{bD28uPwWX7^b^)u=36^ zvDp7j_twdOR?kdNJikItvap_y=(Q|4+46})L@1sP z;HB@~RMkOVG1^^Ob*TcYJl@r6&_W-$I(qhImvo{_EGw zHl(pkiqh&B1$T-<#?}s`q)H7Ji@@YsG1w?&&ojm)3UTRVw~~xal}@XbGZ<)6o{Wr2 zz?tlSls&k}p$rR|haq(~hoJ@B2MBb$G5|PA!vw!2WAV)$kY~4T$*+Ffyhae(AVY1& zAbGyxw1FN9kgp6{VO%s*GvUNu!t=WO!gY}~Yo6HKQP~Nkpr1N854%ptBm7Ol-mH|d zTEqLFY83t!a^h`R-t7@3f|yqpnIUhTFkN-D!ckr4ulBXMc^gS)~wep=v+ zHN3$jdHf`76Ok{_S)`6(t|Rwjx?}TyCSlsX#vkCPf{~bc@j^RT@g8WMr2iwVwyHgE z3!_(&2Q0P*(pm??>i4{_=+$>sSmJ0LcGxzSWeXp8WVNx2jV#l`nN9}X+A()ebrh>7 zm4Y9+y!2l+M^b$!mBo?pzrf~O4gOJ48}7urkGv)m4$i3vk?qWXmzhXMgmL+Qre04q zy2z7gw3zCJjpe$WNm333wPu<_k36?QD?sK+8LK0GGrp&}6Vbtm9l&=0