From 9d494b06b1306e471fe3484048204ad392058335 Mon Sep 17 00:00:00 2001 From: J the Code Monkey Date: Wed, 9 Oct 2024 22:07:55 -0400 Subject: [PATCH] docs: update home, server, relay, and donate pages, add relay implementation pages, and remove metatdata from images (#1) --- .github/FUNDING.yml | 1 - README.md | 4 +- docs/assets/logo_cropped_purple.png | Bin 34044 -> 27540 bytes docs/assets/logo_square_purple.png | Bin 48829 -> 42325 bytes docs/bitcoin.pdf | Bin 184292 -> 184590 bytes docs/contact.md | 39 ++++ docs/donate/index.md | 11 +- docs/faq.md | 8 +- docs/images/additional-features.png | Bin 274041 -> 270237 bytes docs/images/choose-image.png | Bin 321062 -> 317258 bytes docs/images/choose-location.png | Bin 344296 -> 340492 bytes docs/images/choose-plan-personal.png | Bin 309715 -> 305911 bytes docs/images/choose-plan-public.png | Bin 384044 -> 380240 bytes docs/images/namecheap-checkout.png | Bin 201958 -> 198155 bytes ...search.png => namecheap-domain-search.png} | Bin 61611 -> 57808 bytes docs/images/namecheap-records.png | Bin 143103 -> 139300 bytes docs/images/namecheap-remove-records.png | Bin 86755 -> 82683 bytes docs/images/server-info.png | Bin 101264 -> 97192 bytes docs/images/server-password.png | Bin 93853 -> 90184 bytes docs/images/server-type.png | Bin 212561 -> 208758 bytes docs/images/ssh-copy-id.png | Bin 173266 -> 169866 bytes docs/images/ssh-into-server.png | Bin 219240 -> 215840 bytes docs/images/ufw-status.png | Bin 68142 -> 64339 bytes docs/implementations.md | 18 +- docs/index.md | 34 ++- docs/relay/free-up-space.md | 0 docs/relay/khatru-pyramid.md | 1 + docs/relay/khatru-pyramid/configuration.md | 1 + docs/relay/khatru-pyramid/install.md | 1 + docs/relay/khatru-pyramid/service.md | 1 + docs/relay/khatru-pyramid/test.md | 1 + docs/relay/nostr-rs-relay.md | 1 + .../configuration.md} | 4 +- docs/relay/{ => nostr-rs-relay}/install.md | 4 +- docs/relay/{ => nostr-rs-relay}/service.md | 6 +- docs/relay/{ => nostr-rs-relay}/test.md | 0 .../nostr-rs-relay/websocket-connection.md | 111 +++++++++ docs/relay/nostream.md | 1 + docs/relay/nostream/configuration.md | 1 + docs/relay/nostream/install.md | 1 + docs/relay/nostream/service.md | 1 + docs/relay/nostream/test.md | 1 + docs/relay/relay29-khatru29.md | 1 + docs/relay/relay29-khatru29/configuration.md | 1 + docs/relay/relay29-khatru29/install.md | 1 + docs/relay/relay29-khatru29/service.md | 1 + docs/relay/relay29-khatru29/test.md | 1 + docs/relay/relay29-strfry29.md | 1 + docs/relay/relay29-strfry29/configuration.md | 1 + docs/relay/relay29-strfry29/install.md | 1 + docs/relay/relay29-strfry29/service.md | 1 + docs/relay/relay29-strfry29/test.md | 1 + docs/relay/strfry.md | 1 + docs/relay/strfry/configuration.md | 1 + docs/relay/strfry/install.md | 1 + docs/relay/strfry/service.md | 1 + docs/relay/strfry/test.md | 1 + docs/relay/wot-relay.md | 1 + docs/relay/wot-relay/configuration.md | 1 + docs/relay/wot-relay/install.md | 1 + docs/relay/wot-relay/service.md | 1 + docs/relay/wot-relay/test.md | 1 + docs/resources.md | 33 ++- docs/server/domain-name.md | 40 ---- docs/server/firewall.md | 119 +++++++++- docs/server/get-a-domain-name.md | 39 ++++ docs/server/get-a-server.md | 66 +++--- docs/server/remote-access.md | 125 ++++++++-- docs/server/reverse-proxy.md | 130 ++++++++--- docs/server/ssl-tls-certificate.md | 214 ++++++++++++++++++ docs/server/ssl.md | 93 -------- mkdocs.yml | 61 ++++- nginx.conf | 1 - 73 files changed, 931 insertions(+), 261 deletions(-) create mode 100644 docs/contact.md rename docs/images/{namecheap-search.png => namecheap-domain-search.png} (90%) delete mode 100644 docs/relay/free-up-space.md create mode 100644 docs/relay/khatru-pyramid.md create mode 100644 docs/relay/khatru-pyramid/configuration.md create mode 100644 docs/relay/khatru-pyramid/install.md create mode 100644 docs/relay/khatru-pyramid/service.md create mode 100644 docs/relay/khatru-pyramid/test.md create mode 100644 docs/relay/nostr-rs-relay.md rename docs/relay/{config.md => nostr-rs-relay/configuration.md} (86%) rename docs/relay/{ => nostr-rs-relay}/install.md (96%) rename docs/relay/{ => nostr-rs-relay}/service.md (85%) rename docs/relay/{ => nostr-rs-relay}/test.md (100%) create mode 100644 docs/relay/nostr-rs-relay/websocket-connection.md create mode 100644 docs/relay/nostream.md create mode 100644 docs/relay/nostream/configuration.md create mode 100644 docs/relay/nostream/install.md create mode 100644 docs/relay/nostream/service.md create mode 100644 docs/relay/nostream/test.md create mode 100644 docs/relay/relay29-khatru29.md create mode 100644 docs/relay/relay29-khatru29/configuration.md create mode 100644 docs/relay/relay29-khatru29/install.md create mode 100644 docs/relay/relay29-khatru29/service.md create mode 100644 docs/relay/relay29-khatru29/test.md create mode 100644 docs/relay/relay29-strfry29.md create mode 100644 docs/relay/relay29-strfry29/configuration.md create mode 100644 docs/relay/relay29-strfry29/install.md create mode 100644 docs/relay/relay29-strfry29/service.md create mode 100644 docs/relay/relay29-strfry29/test.md create mode 100644 docs/relay/strfry.md create mode 100644 docs/relay/strfry/configuration.md create mode 100644 docs/relay/strfry/install.md create mode 100644 docs/relay/strfry/service.md create mode 100644 docs/relay/strfry/test.md create mode 100644 docs/relay/wot-relay.md create mode 100644 docs/relay/wot-relay/configuration.md create mode 100644 docs/relay/wot-relay/install.md create mode 100644 docs/relay/wot-relay/service.md create mode 100644 docs/relay/wot-relay/test.md delete mode 100644 docs/server/domain-name.md create mode 100644 docs/server/get-a-domain-name.md create mode 100644 docs/server/ssl-tls-certificate.md delete mode 100644 docs/server/ssl.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index c6a57ab..8bc25f6 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,3 @@ # These are supported funding model platforms - github: [christianchiarulli, jchiarulli] patreon: chrisatmachine diff --git a/README.md b/README.md index 3889a29..fd6ed03 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ You'll learn how to: - Set up remote access using SSH -- Configure nginx - - Set up a firewall +- Configure Nginx + - Obtain and set up an SSL/TLS certificate - Build the relay software diff --git a/docs/assets/logo_cropped_purple.png b/docs/assets/logo_cropped_purple.png index 2013409f4f7a957df70899f4995ea64bfa4028fa..8730f2bb724a07d44cbe936526f9d3905001a0f1 100644 GIT binary patch delta 13 Ucmey<$u#9U;{@f+-I9gb04%=++5i9m delta 6566 zcmcIoy{_am7|pJP1g4|_xu{iF5^sEA~q4R;lSIs1PqfM@dJG zD7N8IC^(-TXY5=%lNl}G4RrU5e^nF(S z{L6b)_3W>Qk3M_&wEO;W|J}Fa-Pgn6;nn?c7+&6u6{9;l(8U|hq%u~wTGzN_D_h>7 zVd)7Mwd=a6rMtTad#aUdG_HT5VRtdb=Mj!Bfj;`;vJM;bLjN2P0-Fvk!VEx2;jZSG z4zxrA7q{pqa0DPft~rw+P8`oO0Bh%lpwt*>=84@bP`B2^;*Rrt2TC`ZhcBa>Fb=zJ zW*Y99@`ny-U|_E>OK?62B*R?@DY!rnTAiqwQ261Z#U%Q4=%xVyirxX(5yYX#_qm3@ zvEP2LKdGwf3%|nCYKiaeA5ImcyId{Dig=-N*0d7DPR&rtu7iL*=nm_)$ z`@5>%eV#3(m*3o13^#U|sEn*NOq|4M;HGZ0&_}I|QP20*^65CSOtN(s6-~M=?nsuFr6Hf)c6IU5D4O2jAE!eaWYnPDBONR#-6filoxgA zlO7BlHI`8d(1C6uB04{?Om|cQj;R50bfm0bLl7E?2gjO8m_^^3_kO<^jV0!wGIj9s zgn3eH(J3ya)GH!>jJQ~4P$LGb&PP5Pck#i1E+1Sn!$*`&OCPkTj7HQ7=e; zkxVzn@?H;P`mMCd18!O2dxsP6`wPAS@WV56T&?)9T!3m7 zGI?-qu~D&QM#`K*sZF4({NF^%r7rcIfxP}}l1p4TU%Q|e#3;lCI2y8mE2r~d7g}a(# zI?xggT->6cz!8A_xaLfPIB`7B0IZ!Gf>L9knJ0F$K;2psi#yKq9Vp#s9=?oj!Z_@@ znQ6FZ${#wUfq}ikEW!C8kPLSrq~HQQXmz4yLg9yt7L(}Hp_>K-D0&BAM-Yb|-{%_s z#(w^_{-~;|&-@Bct0lgFcsx~%?tY06Tr*W`t4Aa86|O}L1-JoGSjmYsT$p9eX@2|T z{_m=K`z~8ZFTZ@K7;fw^Q5jilm^g{iz)js~p^sV_$!pEE(gxKvh#roN$K!G29R019 z)T4}0vKO`Nu?hlnQHe}i(-{ORVLCY|sqqUyArQp57{yR`;$*DoP`Lesj6G%3C@<>J zCp{QAYAmA^pab1RM09>&neM0r98&}0=tx<=h9EQ&4~{jHFpIu5@BMx;8cWPUW$NJN z3G<}ZqElQ-saHh&7;&-8phgTE#zrw&x zBbjcD<-Hyz<0goguP$Jb>6$d~dsf`+o}rzYEQ8MlY)JX{ArMFciTrgaJ%XGZ(_*=RhAIUF zR&+Tp%EtwBh|o{Gf|H$WQQr+Vol>;%z(!k#+4yrP(1>H0q(W~Y2$kh%xLWaHxd7EF z$VYXJdO8`}d~*OefiM*vEenaLv+*H13RcLDN_E93gcrBcrtFe-37q`dQqGF{o~tbK zMxIElHjz65w4+@R%7E6ImR64p>x?7coo{}b8mOJ-jpw%BITLLHqUlTB%;RM*2%r zQZ>&_X;XiRQrdqNrBn^Cll)g9r6kg){XpgY?-4H`t>vUN;->;oqCcKrZWoZs0i_WF zO7-uTlVaXZDb0WR|MI+ZF0?>tkD49+-!5)NF$c8PpZXd<#cFa$t7LI#xy^RyFGt5C zS5gXUGWoAWibor1%-2bVBAS z@Bb}G+4^@tTWWUu|GbnIC-VB2;f$!Wnky;MJBKIlxZlMa9*tL@?!A>Ucq4=t)a>)u MU%mFzd-BJB0Vr%xJOBUy diff --git a/docs/bitcoin.pdf b/docs/bitcoin.pdf index 1e19b739f6e296dd1b38f71f20bf9152e6d9f6d1..21f8812fcb01091ee9354c070a58cddc1b7500f3 100644 GIT binary patch delta 222 zcmaDdpSy1ncS8%~7N#fX>s6gn(=+p2D>BnU^7C^-3sMqGQn@OMQq#B$6b!ixpuo&r z!OYau*i<1+feXk+NEjF>fRq@5Bua`BGjmdlxNK~=^n)|2QWeZBxb%ba^Gg)W%oGe1 zg1GcOT@<1fY@8hpoeUgJOq^UyO{OQDXA)&mut`puUU{A=&{032D78$%(89>v$ehd0 mj!V@wF9p?cKuHrLOCzr0lEk7CutR|Y#)igRs;aL3Zd?HGP(9!P delta 13 UcmeBM#QkJGcS8%~7N#fX0V*{HH~;_u diff --git a/docs/contact.md b/docs/contact.md new file mode 100644 index 0000000..68b44b8 --- /dev/null +++ b/docs/contact.md @@ -0,0 +1,39 @@ +# Contact + +## NODE-TEC + +đŸŠ© npub: + +```bash +npub1809mpa7748df7kext899m2yatetky9w78zz72x7jgaxarvxyfvtqwvfpz8 +``` + +📧 Email: + +[devs@node-tec.com](mailto:devs@node-tec.com "devs@node-tec.com") + +🔐 PGP Fingerprint: + +```bash +04BD 8C20 598F A5FD DE19 BECD 8F24 69F7 1314 FAD7 +``` + +## Developers + +đŸŠ© Chris' npub: + +```bash +npub1ygzj9skr9val9yqxkf67yf9jshtyhvvl0x76jp5er09nsc0p3j6qr260k2 +``` + +đŸŠ© J's npub: + +```bash +npub1zn559gr2vwyex2s2mt2s7x5r5ryjeyy0zwy2zx3ckp6ktwpe4p4spgt84e +``` + +đŸŠ© Nick's npub: + +```bash +npub1te6nugpy7utp9ls620awmj5zw0nedwhh3rjj2gx6vnzms2rvz5jq9kkh4n +``` diff --git a/docs/donate/index.md b/docs/donate/index.md index 0931867..55234d1 100644 --- a/docs/donate/index.md +++ b/docs/donate/index.md @@ -1,20 +1,19 @@ # Donate Bitcoin -If you find this guide helpful, please consider donating some sats. Your support is greatly appreciated. +If you find these guides helpful, please consider donating some sats. Your support is greatly appreciated. -- **Zap me on nostr:** +- **Zap me on Nostr:** -``` +```bash npub1ygzj9skr9val9yqxkf67yf9jshtyhvvl0x76jp5er09nsc0p3j6qr260k2 ``` - **Bitcoin:** -``` +```bash bc1q6hqtxr5hnhu9asze30a8w02g65nztlw8y27p7q ``` - **Lightning:** -[Tip with lightning](https://getalby.com/p/chrisatmachine) - +[Tip with Lightning](https://getalby.com/p/chrisatmachine) diff --git a/docs/faq.md b/docs/faq.md index 1eab840..72e6a68 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,7 +1,3 @@ -Ask me questions on nostr and maybe I'll answer them here. +# FAQ -pubkey: - -``` -npub1ygzj9skr9val9yqxkf67yf9jshtyhvvl0x76jp5er09nsc0p3j6qr260k2 -``` +If your question wasn't answered here, reach out to us on [Nostr](https://nostr.com "Nostr"). We'll update this page with the answers. diff --git a/docs/images/additional-features.png b/docs/images/additional-features.png index a3bb889b3e8e3e4754aaad0b8f41641e612613e6..2bb889d6fc290d1ef152579e4dbb640ee85c455e 100644 GIT binary patch delta 29 icmex)M_}%LfeFgZ|M}Yg^DzQ36A&|R|If!#B@Y18pA5JF delta 3864 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 diff --git a/docs/images/choose-image.png b/docs/images/choose-image.png index e13bfacce6cf67134860753440f2f3ce91658075..3a2608b6db19b1110b1fdc5e91add5ab855cac78 100644 GIT binary patch delta 29 icmZ2>M)=e^;R(vk|M}Yg^DzQ36A&|R|If#wejNbJ3=G@= delta 3864 zcmZWm2{@GP_kNKr*<~Ng*w?W|7$n&;vTIPb42^9tGnuiyC`<_{Dp@MBFJ+7D3fV#t zS<041w)iaB;x{eda{d3$b)D;+=bUrj_jAtEUB;Q$%Xv!-Jf@E}Ft9W=Fc7f}!g!*6 zQ2=0aJ@q_2(x!_$%jx#5TWlhcktqY|B2bCQ6gEfTtKl>D+rZ;CUIy7KIIGs`c!m!H zcI@peBuIIs^i~tn(sH;x`XccTb=`{GWcs&s?ZY4BUa&7i8~Y6c%u5kCOj(K;PnDf? z;TPa&5xfItycEY%K_5}8@UqOqBeJeRAP_27zRQQspFRSlhQvzgI3n!b%>X;T0S ztcY+l9l(E2v|oP8>lAZ>Gbyv3I++*H;&h*!04GeTNj9R-W7IiFbGs!~!Z?+KyfpQK zu36ME_qhvPh64oshA$+<1<2mjvicX zV{9NBBi9yNP71=|a`Zc)6EoyM*S<)hwmxcS*OP5VZ1nM1sF-b-W1aMUCglsF^R`yH zpoWlpIEm-zdi0E~xaVT*g8jbF>nwlP%_+}?H*R#76< z0jESE(nw(rJnt4ky=X zmV#rM(-@A639NQLVMTIWB}KJax+}e9(P#?~#K5VYf4JdW9csxf@TPIjERHe8B!&@2 z$hC1!L&J9uvjv&89z{HptRm$Q7sEsF%@4C%K3{(nuXcpDZ zIk+7>`BB5Szp7??#luVGtkCH#sqq82^(*IBewKz=i^A(UH&6H}O=h%aJ^X=<=xhR> zPwP3kGnN1N;IJfqMMyjP1R!}u(5KC@JSPZVTbCtmKN4AkG=z^@8gHS%%9Ci`!S>PiqjeK)GGXJ0YJ+x}$li`3vGb|W zq{XE``;l!RMTS&)RTS10+tBt_89Ql-l*qpU_f*MWc zP44XVw-T2%9TQg0EWW)nZ@8f~7S(iWPbsqSQpkP2FQjrM7Vel_*RS`v(qmFxQOFba zaVJ{IVaFF+LY^g^WcQjvOt6h@QWr(>w{;5&i_?l;6wnsu7F>USW2k%RN&&>CK6?wX ztm<&b*KiAJoJ{)}{Wq{RA>ktMiMP#iq2R*FqMLQs>JmbtL(+F+jdC0Y_t7#{VPhPQ%*$NM zRLfWC3|^UDEfyWPUusoo^)%3MRw5HolU@0hb3SH6WjA71A|y%DVbJkTPS;>Yu0tWw zWIfOGA-91Kc+Eb=zHHdN6yiv(uB$Q~8y?diqh8(_ORu&->v_5!W1@>|_3FLk>z3h( zTVTWc;%c=Vv~soTabvg;d^P?eo)e$HV80;retF>4M#*Mvh-Qe{=GNDb1AA(11cp#j zKxein-k|Il@u{Beq>D>|OLnu^W~uT;0x_DHyyL&V$IZob*RZZ# zHr_KHbT+f;d3#q?-bdjZGPx9KpJwk<(&yM%^Su0Ag|q8N*N>13QUS^e> zm6^UyexYv?FTbwndG6#DJStQjT-jgsw5s`Yq*kpqNpM)RidF2`x}csod%(0`=4D}LVe8kqfSzfYSNB-;wD;31(?M+FIybpqtjhRWf;9hIwVCSpMyAQ! zcXMMVW1UmUmB#9cVRH*pvbc-iLV6OW)yMpzoGQo92eSqjhGvG=#N`?n8K=HBzsn-` zp!z<(@6Ht8l;-$4iEIoDej4^P+!-Wlhj@j4TV3Htsh&OQ-Ba*d_lqw4p}8)k2{CCq znE*CHB0MAD&ECz%2iynLhouMoAFeFPZ=Kuf0muNlr8V-qAgmA3cm0&SlK3<6X9_0T z(xL^>dHrX^0HXlE01U~gbK@50<7)$}19OixUUXd0t%)5M_`pdZJgVf7GI9U(SyRO5gLfM0 zmzNgGGiN6{jwjVCfAZWPS|dyGp6g5tz(K>In3)6H)85t#i9@gkY3CD9VF~H>so-!A zd39vfg<+qz_{hi8!qZ2mD{&7uj(@$#r^_d&TBrI$rAH<7jG$G_yq*2!;n!XjVHI(-O|+@B!g=E7M)mA`iU{7|qS_uhK2JyPnBu;lmTsnABQbXL<_lG!K9Bwh zHKw#w^G1uJn|50b&P^vqc>Yf-bHUVGN&;^61ozW<6g3y&>(6+;7d5d zID4g7sxdxEQO8JA{SbM$_Hs5{N?a=BoM%SZ1iXA_rBFG)th%kLDw9Po99%)HrrCIn zdL=zv*9`vLFtTI7gXG~?taB;B;C*zq>&L&*k57y*z=#*T8HVQeXM;kd1M?TK2eLuPP|EUigvnKgY|E&vk4%tf7JZW@crzH&nH-@>&By9)_T1w z!L`AH;k?_=HmxRd>XUYoTtIkN=wG?m1DmnI3a`9=@45?hi8%UTmk8Z0BAKZxzF(&u z^#0+n`EF}2s(Js=dl@n~zH@fB=x}pJgAVh&5g$H2!SnI^)Wwzh{%>ZwykQ>>k~i0u z@}F4r>ssub-nBk>zv44kvx@n?i{0CkfXi5{$wju_$jhf$4G{pUJV1bVHOz>w7=9>o zG#g$i%eHNSBpTUr1p^CHhoK18{rVS-Em;by+q9csX8}?k727w)fn+iI#TEziz_Jt` zD4gE+=8p$=)9DV(t+F&h(jJ++)9zwx|8g_1FB0a}uy3UR0Kg3t($v%39FV2N48Rd8 zet?z|Q2_u5=u!#%eF2Q9qyd^=1!@3@Ljy;CHv#7;{^z+xF$(C9r@0*q&{J+46eB#M z{=1vu-6NX6W7?OL8lZ1uU}{S7HkX1>D1Yo_49>~yq%tMJ7yz0$U;%(z;-^uWT8pnz z1U{f`kvOC|LhBO7PtnZ-5a{8l1HFvH1!%!w!NI|b z!K#XwATOA*rluxLNd=~&qCf#CV2S=XH-dscR_r&+-$Z9n*h@j^02~_QFY=Sv%^ics z=|G`BmHs)uABrNN|5ftG{+a6%i1CB{EWwl&m0ROW-fs|BJQ5qJj)CeiT)l?!TY*2mRmTA0Qm| zbNc^mk delta 3867 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 DWK7;} diff --git a/docs/images/choose-plan-personal.png b/docs/images/choose-plan-personal.png index 46c079eac9cd49d047cb5ee9a22aa8c4ba7a6e70..7548a45a55468ddbd8263da4cd9f43dd8f220231 100644 GIT binary patch delta 29 icmccoS?K#!p$W>(|M}Yg^DzQ36A&|R|If#AWfcJ4#0~-g delta 3864 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 B-+2H4 diff --git a/docs/images/choose-plan-public.png b/docs/images/choose-plan-public.png index 544deee2959ae4827c07faf2e807ca5ce0086b5b..eab3fa9a193b2a0d0ef3a796aabaa67723144695 100644 GIT binary patch delta 33 kcmZ3pL;S)l@d?V!|M}Yg^DzQ36A&{4G0XP0RZC;T>t<8 delta 3867 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 E50x$7)c^nh diff --git a/docs/images/namecheap-checkout.png b/docs/images/namecheap-checkout.png index 2c97134ca92d0c0da0581558f85cf48d316c9f6a..c4ca2ec8134e7b9576e61099a4bcd2a90aef657e 100644 GIT binary patch delta 25 fcmaF1lBc_eXM%F`Kfd;Ve2hTMwEZ6+^9xo0m1hdw delta 3861 zcmZWm2{@GP_kNK*OUOQ!v1S`vgfWtA86iu9vSny&gPF;U?L}G2UR1JFME0`Fu7-%v z@{y%%F|x&HU*b3Q^)1)`|6JF(p7We@-{*eLIq?ZcXN!)eNPtK6F$M;frUnLLmVsCg zj1L+BOm3!MWJFna^X53-PD$Yui-<@Y$P|N0MWk^$0N)IsAG-}aCi64NUBg?o*Tge@ z8n8Xq!5#;xsFK}mL0MW3c0^q!-Jxw*mLJdjo~d*AgVGE3W$EC)Lx4FMB9|$9G4tv2 zQ_g}yTy4U4z^s>&1RCfgT2+4bIe2)^4G086<05eN(CN!(Ag-x-UUq2L^AJ>Ypmh}y z1tbNh)b&O5_@?N93ER+{>Y_kyR^9#Eu+%H4$Rr*HrqwfAeU?*lTIa2&bXhXDQS4+z zpwNm0$1nhb_r&`ZCOl8GB|61rchIKt1KQkf<742MDQ%p!cx|)>SKQ2QX|*U`^`Ia_ zqp*7#ebjB{5|5#xWtvR)r1_rSht*ayza*cw*psCnk(jHcp?%8Ox=NYo9+l%$A^{HW zJme8hkdv8blQS<3X@529y~xQaN`OmWgb2Bh*2(1**@%-d9tV}M33X_Yz0az0Nqo-6 z3IS@0xP`^>v8+W+*=Pvm-*K~T8Q8_2h%KAyUwy*T8tBa7KFsWsez1TPznGtl;qmB{ z(MLvpsyv;>&s@PkK2I7Bn3T)3iq6RDq7f=muoG#OB3GOVFp0PzDsOU+;dSw%S>PJO zY`kwTPk@9i(K*~Bv`|$K#rp7RoM<0?qXNiN#m#`fLAnBEn1ymOFr1(y5tuue1LU$f zZtq8+W>8ts?wfYQ)3YzLIJL0s72ZzzSzZb`_c{2UToARm_tp5d{4|-his<_84RHl6 zM(clC%!O8<6yw6xMVnij6C*-=y2#7`7o!(A%_MBw+ZHEjn9T1qeOi2*8!Fxj?*n>v~)y+0sq<9lItuEC36qb^75-Xt%GYw82|OxpTNin3I`? zm?1YtxeX29Kg<MH#7ML0eWb7a{_MuD}msG|v{2w}oJB|Z8TZTKk!Q6SFe>aAy2q1!EDwE+tID*8RGRBR9I$oAbwud+P=WCZ>5 z=(PZvtdV?xu@YKAOp9{dWL_tSv!w1T`zsdBOV315`FqlfX4MD7rsx7f^EnA zxw2^Z+R^@yvFMVg+)Y691Y|owjEVWN_)#*TVpz(_NTzocZ!zKIiX=n3P2_Gz#vKz- zrOSv-gUY9{xN~2)zG%oUE|a=uq7x`Yio;7hOSO=VxnKqP$X{aw#^x!cCC22f&Joq= zvJ-f7*WO88)pAH&KD+Sl&Ya=8_DE#Q={@C$qAS7o1!m(al-YTs^Ig8(=gEvtcR{00 z+Qpu1r-U9~XbXOxeCn9z1ajT_&|836Z%hPPmOIEGo$;eo;tYl3#f9k6Rz#e7sf&v2M)W zL@ue>-|;crgc_&Pf5m*w|El;^`cJ7qnH@F5csGO9$7JhDSsZv`CQbVd=8f(fAp(Jb zBUo(k6H<4DHv%_w=P4gWi@_&e)=Ndg^QVdv8g4Ws21f;F?#3A9*?-u_oTv^R;c{SG z;#s0uy3Szm%Jh1P_`v-#t0Jps0fy63*~q%ws&CwL(d(+a;k#17$

89PZ?Gf5^(W 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 diff --git a/docs/images/namecheap-search.png b/docs/images/namecheap-domain-search.png similarity index 90% rename from docs/images/namecheap-search.png rename to docs/images/namecheap-domain-search.png index 8310d2256edaa2b732176cd0adf5b3cf681f8f90..49c536870ba767be23451142d3193d9a9b694348 100644 GIT binary patch delta 13 VcmZ4ekom%4<_XH1|M9JT2mmn}2POaj delta 3852 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 diff --git a/docs/images/namecheap-records.png b/docs/images/namecheap-records.png index d391d14f6593ed328c2e49d381ff54755dc93e16..ce45d9aab03487771b5e356366325c4ec8ba6f52 100644 GIT binary patch delta 21 dcmex=mt)BRjtR=m|M=Sf@iA`y$H&B|004Dz2@L=M delta 3858 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 delta 4118 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 diff --git a/docs/images/server-info.png b/docs/images/server-info.png index 851750711608d6b352fe176343ba52f3be7a6871..7fb711cdfb07512d2ca26781060a72dee726f51a 100644 GIT binary patch delta 17 YcmbO*oo&T;)(OhZ+ydLV1sGea0X&=q_5c6? delta 4118 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%0D@ zSw#-67?@qLE(Qxf0w``*8hvO!lC_iuwE2Vyym}u_FMSB#os^#{Al?9 vEaR_L|H@K!t$7>)|L5N{kI#Kr&!v1NALgQoB@iYVAxRY>38|2zM#BFG8!FxM diff --git a/docs/images/ssh-copy-id.png b/docs/images/ssh-copy-id.png index 7786b6e6c0ddbe3add0cb9b98e647584154e1853..234305d451aa7457c753e86c1eaaee933f2410f7 100644 GIT binary patch delta 21 ccmca~lB;Vy*97I}Y~J>4UdHX&yiDoS0bjre#sB~S delta 3443 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 diff --git a/docs/images/ssh-into-server.png b/docs/images/ssh-into-server.png index efcfaf60f8cba30539e386cb0d522d220574b54b..426e47fbf409bd517e6bc3350c1722e9ac2098b8 100644 GIT binary patch delta 25 fcmaE{fp@_)-U-Uh*}U!9yo^B1v^|@b`L7oMfTIZ! delta 3446 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 diff --git a/docs/implementations.md b/docs/implementations.md index b852330..cd85030 100644 --- a/docs/implementations.md +++ b/docs/implementations.md @@ -1,13 +1,21 @@ # Relay Implementations -There are many different relay implementations available. For this guide we'll be using [nostr-rs-relay](https://github.com/scsibug/nostr-rs-relay). +There are many different relay implementations available. This guide will demonstrate how to set up multiple implementations. The implementation you choose depends on your use case. -Here are some other implementations: +Implementations: -- [nostream](https://github.com/Cameri/nostream) +- [Khatru Pyramid](https://github.com/github-tijlxyz/khatru-pyramid/tree/main "Khatru Pyramid") -- [strfry](https://github.com/hoytech/strfry) +- [Nostream](https://github.com/Cameri/nostream "Nostream") -After following this guide you should have enough knowledge to setup any of these implementations. +- [nostr-rs-relay](https://github.com/scsibug/nostr-rs-relay/tree/master "nostr-rs-relay") +- [strfry](https://github.com/hoytech/strfry/tree/master "strfry") +- [WoT Relay](https://github.com/bitvora/wot-relay/tree/master "WoT Relay") + +- [relay29 Khatru29](https://github.com/fiatjaf/relay29/tree/v0.4.0/examples/groups.fiatjaf.com "relay29 Khatru29") + +- [relay29 strfry29](https://github.com/fiatjaf/relay29/tree/v0.4.0/strfry29 "relay29 strfry29") + +After following this guide, you should have enough knowledge to setup any of these implementations. diff --git a/docs/index.md b/docs/index.md index 20be477..92aa3f3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,11 +1,37 @@ # Relay Runner -This site will help you setup a relay for personal or public use. Relays are servers that transmit notes and other stuff to clients on the [nostr](https://nostr.com/) network and may (or may not) store them as well. +This site will help you setup a relay for personal or public use. Relays are servers that transmit notes and other stuff to clients on the [Nostr](https://nostr.com/ "Nostr") network and may (or may not) store them as well. -## Why run a personal relay? +## Why Run a Personal Relay? Running a personal relay is a great way to keep your notes and other data under your control. You can use it as an archive for all of your data or maybe as a dedicated relay for a personal website. -## Why run a public relay? +## Why Run a Public Relay? -Running a public relay is a great way to decentralize and help the nostr network grow. You also have the option to monetize your relay by charging clients for access. +Running a public relay is a great way to decentralize and help the Nostr network grow. You also have the option to monetize your relay by charging clients for access. + +## What You'll Learn + +The guides will walk you through the process of setting up various relay implementations from scratch. + +You'll learn how to: + +- Get a server + +- Get a domain name + +- Set up remote access using SSH + +- Set up a firewall + +- Configure Nginx + +- Obtain and set up an SSL/TLS certificate + +- Build the relay software + +- Install the relay software + +- Configure your relay + +- Set up a systemd service for your relay diff --git a/docs/relay/free-up-space.md b/docs/relay/free-up-space.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/relay/khatru-pyramid.md b/docs/relay/khatru-pyramid.md new file mode 100644 index 0000000..2bc348f --- /dev/null +++ b/docs/relay/khatru-pyramid.md @@ -0,0 +1 @@ +# Khatru Pyramid diff --git a/docs/relay/khatru-pyramid/configuration.md b/docs/relay/khatru-pyramid/configuration.md new file mode 100644 index 0000000..a025a48 --- /dev/null +++ b/docs/relay/khatru-pyramid/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/relay/khatru-pyramid/install.md b/docs/relay/khatru-pyramid/install.md new file mode 100644 index 0000000..55af1c5 --- /dev/null +++ b/docs/relay/khatru-pyramid/install.md @@ -0,0 +1 @@ +# Install diff --git a/docs/relay/khatru-pyramid/service.md b/docs/relay/khatru-pyramid/service.md new file mode 100644 index 0000000..42321b7 --- /dev/null +++ b/docs/relay/khatru-pyramid/service.md @@ -0,0 +1 @@ +# Service diff --git a/docs/relay/khatru-pyramid/test.md b/docs/relay/khatru-pyramid/test.md new file mode 100644 index 0000000..ceb1228 --- /dev/null +++ b/docs/relay/khatru-pyramid/test.md @@ -0,0 +1 @@ +# Test your Relay diff --git a/docs/relay/nostr-rs-relay.md b/docs/relay/nostr-rs-relay.md new file mode 100644 index 0000000..64ea8ce --- /dev/null +++ b/docs/relay/nostr-rs-relay.md @@ -0,0 +1 @@ +# nostr-rs-relay diff --git a/docs/relay/config.md b/docs/relay/nostr-rs-relay/configuration.md similarity index 86% rename from docs/relay/config.md rename to docs/relay/nostr-rs-relay/configuration.md index b69ddec..d747377 100644 --- a/docs/relay/config.md +++ b/docs/relay/nostr-rs-relay/configuration.md @@ -1,7 +1,5 @@ # Configuration -Update the `nostr-rs-relay` config file with your information and preferences: - ```bash mkdir /etc/nostr-rs-relay cd /etc/nostr-rs-relay @@ -26,7 +24,7 @@ Here are some important settings: - `data_directory` - The directory where your relay will store data. We'll set this to `/var/lib/nostr-rs-relay/data`. -- `max_conn` - Maximum number of SQLite reader connections. Recommend setting this to approx the number of CPU cores. +- `max_conn` - Maximum number of SQLite reader connections. Recommend setting this to approx the number of CPU cores. - `address` - The address your relay will listen on. We'll set this to `127.0.0.1`. diff --git a/docs/relay/install.md b/docs/relay/nostr-rs-relay/install.md similarity index 96% rename from docs/relay/install.md rename to docs/relay/nostr-rs-relay/install.md index 7675db7..7362b73 100644 --- a/docs/relay/install.md +++ b/docs/relay/nostr-rs-relay/install.md @@ -12,13 +12,13 @@ apt install build-essential cmake protobuf-compiler pkg-config libssl-dev We'll also need to install `git` and `rust` to clone and compile the repository. -git: +Install git by running: ```bash apt install git ``` -rust: +Install rust by running: ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh diff --git a/docs/relay/service.md b/docs/relay/nostr-rs-relay/service.md similarity index 85% rename from docs/relay/service.md rename to docs/relay/nostr-rs-relay/service.md index a2b5951..541d3ec 100644 --- a/docs/relay/service.md +++ b/docs/relay/nostr-rs-relay/service.md @@ -4,14 +4,18 @@ A service is a long-running process that can be started and stopped. It can be u ## Create User -Create a new user called `nostr` to run the relay service. Creating a new user is a good practice to isolate the service from the rest of the system. +Create a new user called `nostr` to run the relay service: ```bash sudo adduser --disabled-login nostr ``` +Creating a new user is a good practice to isolate the service from the rest of the system. + ## Change ownership for data directory +Change ownership of the relay data directory: + ```bash chown -R nostr:nostr /var/lib/nostr-rs-relay ``` diff --git a/docs/relay/test.md b/docs/relay/nostr-rs-relay/test.md similarity index 100% rename from docs/relay/test.md rename to docs/relay/nostr-rs-relay/test.md diff --git a/docs/relay/nostr-rs-relay/websocket-connection.md b/docs/relay/nostr-rs-relay/websocket-connection.md new file mode 100644 index 0000000..d02d45f --- /dev/null +++ b/docs/relay/nostr-rs-relay/websocket-connection.md @@ -0,0 +1,111 @@ +# WebSocket Connection + +Replace the contents of `/etc/nginx/conf.d/relay_relayrunner_xyz.conf` with the following configuration where `relay_relayrunner_xyz.conf` should be replaced by whatever name you used for your Nginx config file: + +```nginx title="relay_relayrunner_xyz.conf" +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +upstream nostr_rs_relay_websocket { # can replace with a unique upstream WebSocket name that you choose + server 127.0.0.1:8080; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name relay.relayrunner.xyz; # replace with your domain + + location / { + proxy_pass http://nostr_rs_relay_websocket; # can replace with your unique upstream WebSocket name + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + try_files $uri $uri/ =404; + } + + # Only return Nginx in server header + server_tokens off; + + #### SSL Configuration #### + # Test configuration: + # https://www.ssllabs.com/ssltest/analyze.html + # https://cryptcheck.fr/ + ssl_certificate /etc/letsencrypt/live/relay.relayrunner.xyz/fullchain.pem; # replace with your domain + ssl_certificate_key /etc/letsencrypt/live/relay.relayrunner.xyz/privkey.pem; # replace with your domain + # Verify chain of trust of OCSP response using Root CA and Intermediate certs + ssl_trusted_certificate /etc/letsencrypt/live/relay.relayrunner.xyz/chain.pem; # replace with your domain + + ssl_protocols TLSv1.3 TLSv1.2; + + # For more information on the security of different cipher suites, you can refer to the following link: + # https://ciphersuite.info/ + # Compilation of the top cipher suites 2024: + # https://ssl-config.mozilla.org/#server=nginx + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305"; + + # Perfect Forward Secrecy (PFS) is frequently compromised without this + ssl_prefer_server_ciphers on; + + ssl_session_tickets off; + + # Enable SSL session caching for improved performance + # Try setting ssl_session_timeout to 1d if performance is bad + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + + # By default, the buffer size is 16k, which corresponds to minimal overhead when sending big responses. + # To minimize Time To First Byte it may be beneficial to use smaller values + ssl_buffer_size 8k; + + # OCSP stapling + ssl_stapling on; + ssl_stapling_verify on; + + #### Security Headers #### + # Test configuration: + # https://securityheaders.com/ + # https://observatory.mozilla.org/ + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; + + add_header X-Frame-Options DENY; + + # Avoid MIME type sniffing + add_header X-Content-Type-Options "nosniff" always; + + add_header Referrer-Policy "no-referrer" always; + + add_header X-XSS-Protection "1; mode=block" always; + + add_header Permissions-Policy "geolocation=(), midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=()" always; + + #### Content-Security-Policy (CSP) #### + add_header Content-Security-Policy "base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests;" always; +} + +server { + listen 80; + listen [::]:80; + server_name relay.relayrunner.xyz; # replace with your domain + + location /.well-known/acme-challenge/ { + root /var/www/relay.relayrunner.xyz; # replace with the directory you used to store the challenge files in + allow all; + } + + location / { + return 301 https://relay.relayrunner.xyz$request_uri; # replace with your domain + } +} +``` + +Be sure to replace `relay.relayrunner.xyz` with your domain name and `/var/www/relay.relayrunner.xyz` with the directory you used to store the challenge files in. + +You can also replace `nostr_rs_relay_websocket` with a unique upstream WebSocket name that you choose. + +The proxy headers specified in the `location` block above, the SSL/TLS directives, and the security headers specified above can be changed to meet the specific needs of your relay. There are even more strict values that can be set especially for the `Permissions-Policy` and `Content-Security-Policy` headers depending on your requirements. Be sure to test any changes you make are compatible with the nostr-rs-relay implementation. diff --git a/docs/relay/nostream.md b/docs/relay/nostream.md new file mode 100644 index 0000000..08a0887 --- /dev/null +++ b/docs/relay/nostream.md @@ -0,0 +1 @@ +# Nostream diff --git a/docs/relay/nostream/configuration.md b/docs/relay/nostream/configuration.md new file mode 100644 index 0000000..a025a48 --- /dev/null +++ b/docs/relay/nostream/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/relay/nostream/install.md b/docs/relay/nostream/install.md new file mode 100644 index 0000000..55af1c5 --- /dev/null +++ b/docs/relay/nostream/install.md @@ -0,0 +1 @@ +# Install diff --git a/docs/relay/nostream/service.md b/docs/relay/nostream/service.md new file mode 100644 index 0000000..42321b7 --- /dev/null +++ b/docs/relay/nostream/service.md @@ -0,0 +1 @@ +# Service diff --git a/docs/relay/nostream/test.md b/docs/relay/nostream/test.md new file mode 100644 index 0000000..ceb1228 --- /dev/null +++ b/docs/relay/nostream/test.md @@ -0,0 +1 @@ +# Test your Relay diff --git a/docs/relay/relay29-khatru29.md b/docs/relay/relay29-khatru29.md new file mode 100644 index 0000000..a087ed8 --- /dev/null +++ b/docs/relay/relay29-khatru29.md @@ -0,0 +1 @@ +# relay29 Khatru29 diff --git a/docs/relay/relay29-khatru29/configuration.md b/docs/relay/relay29-khatru29/configuration.md new file mode 100644 index 0000000..a025a48 --- /dev/null +++ b/docs/relay/relay29-khatru29/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/relay/relay29-khatru29/install.md b/docs/relay/relay29-khatru29/install.md new file mode 100644 index 0000000..55af1c5 --- /dev/null +++ b/docs/relay/relay29-khatru29/install.md @@ -0,0 +1 @@ +# Install diff --git a/docs/relay/relay29-khatru29/service.md b/docs/relay/relay29-khatru29/service.md new file mode 100644 index 0000000..42321b7 --- /dev/null +++ b/docs/relay/relay29-khatru29/service.md @@ -0,0 +1 @@ +# Service diff --git a/docs/relay/relay29-khatru29/test.md b/docs/relay/relay29-khatru29/test.md new file mode 100644 index 0000000..ceb1228 --- /dev/null +++ b/docs/relay/relay29-khatru29/test.md @@ -0,0 +1 @@ +# Test your Relay diff --git a/docs/relay/relay29-strfry29.md b/docs/relay/relay29-strfry29.md new file mode 100644 index 0000000..683a86c --- /dev/null +++ b/docs/relay/relay29-strfry29.md @@ -0,0 +1 @@ +# relay29 strfry29 diff --git a/docs/relay/relay29-strfry29/configuration.md b/docs/relay/relay29-strfry29/configuration.md new file mode 100644 index 0000000..a025a48 --- /dev/null +++ b/docs/relay/relay29-strfry29/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/relay/relay29-strfry29/install.md b/docs/relay/relay29-strfry29/install.md new file mode 100644 index 0000000..55af1c5 --- /dev/null +++ b/docs/relay/relay29-strfry29/install.md @@ -0,0 +1 @@ +# Install diff --git a/docs/relay/relay29-strfry29/service.md b/docs/relay/relay29-strfry29/service.md new file mode 100644 index 0000000..42321b7 --- /dev/null +++ b/docs/relay/relay29-strfry29/service.md @@ -0,0 +1 @@ +# Service diff --git a/docs/relay/relay29-strfry29/test.md b/docs/relay/relay29-strfry29/test.md new file mode 100644 index 0000000..ceb1228 --- /dev/null +++ b/docs/relay/relay29-strfry29/test.md @@ -0,0 +1 @@ +# Test your Relay diff --git a/docs/relay/strfry.md b/docs/relay/strfry.md new file mode 100644 index 0000000..8da0ce0 --- /dev/null +++ b/docs/relay/strfry.md @@ -0,0 +1 @@ +# strfry diff --git a/docs/relay/strfry/configuration.md b/docs/relay/strfry/configuration.md new file mode 100644 index 0000000..a025a48 --- /dev/null +++ b/docs/relay/strfry/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/relay/strfry/install.md b/docs/relay/strfry/install.md new file mode 100644 index 0000000..55af1c5 --- /dev/null +++ b/docs/relay/strfry/install.md @@ -0,0 +1 @@ +# Install diff --git a/docs/relay/strfry/service.md b/docs/relay/strfry/service.md new file mode 100644 index 0000000..42321b7 --- /dev/null +++ b/docs/relay/strfry/service.md @@ -0,0 +1 @@ +# Service diff --git a/docs/relay/strfry/test.md b/docs/relay/strfry/test.md new file mode 100644 index 0000000..ceb1228 --- /dev/null +++ b/docs/relay/strfry/test.md @@ -0,0 +1 @@ +# Test your Relay diff --git a/docs/relay/wot-relay.md b/docs/relay/wot-relay.md new file mode 100644 index 0000000..8ccd3aa --- /dev/null +++ b/docs/relay/wot-relay.md @@ -0,0 +1 @@ +# WoT Relay diff --git a/docs/relay/wot-relay/configuration.md b/docs/relay/wot-relay/configuration.md new file mode 100644 index 0000000..a025a48 --- /dev/null +++ b/docs/relay/wot-relay/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/relay/wot-relay/install.md b/docs/relay/wot-relay/install.md new file mode 100644 index 0000000..55af1c5 --- /dev/null +++ b/docs/relay/wot-relay/install.md @@ -0,0 +1 @@ +# Install diff --git a/docs/relay/wot-relay/service.md b/docs/relay/wot-relay/service.md new file mode 100644 index 0000000..42321b7 --- /dev/null +++ b/docs/relay/wot-relay/service.md @@ -0,0 +1 @@ +# Service diff --git a/docs/relay/wot-relay/test.md b/docs/relay/wot-relay/test.md new file mode 100644 index 0000000..ceb1228 --- /dev/null +++ b/docs/relay/wot-relay/test.md @@ -0,0 +1 @@ +# Test your Relay diff --git a/docs/resources.md b/docs/resources.md index 0d24906..9099bff 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -1,16 +1,31 @@ # Resources -Learn about nostr: +## Learn about Nostr -- [nostr.com](https://nostr.how/en/relays) -- [nostr.how](https://nostr.how) +- [nostr.com](https://nostr.com "nostr.com") -Other Guides: +- [nostr.how](https://nostr.how "nostr.how") -- [Nostr Relay Setup Guide](https://github.com/BlockChainCaffe/Nostr-Relay-Setup-Guide) -- [How to Setup a Paid Nostr Relay](https://andreneves.xyz/p/how-to-setup-a-paid-nostr-relay) -- [Nostr Relay Quick Start](https://zbd.dev/knowledge-base/guides/nostr-relay) +- [Nostr GitHub](https://github.com/nostr-protocol/nostr "Nostr GitHub") -Relay Quickstart: +- [NIPs](https://github.com/nostr-protocol/nips "NIPs") -- [relay.tools](https://relay.tools/) +## Other Guides + +- [Nostr Relay Setup Guide](https://github.com/BlockChainCaffe/Nostr-Relay-Setup-Guide "Nostr Relay Setup Guide") + +- [How to Setup a Paid Nostr Relay](https://andreneves.xyz/p/how-to-setup-a-paid-nostr-relay "How to Setup a Paid Nostr Relay") + +- [Nostr Relay Quick Start](https://zbd.dev/knowledge-base/guides/nostr-relay "Nostr Relay Quick Start") + +## Relay Quick Start + +- [relay.tools](https://relay.tools "relay.tools") + +- [Relay Wizard](https://relaywizard.com "Relay Wizard") + +## Clients + +- [Damus](https://damus.io "Damus") + +- [NoteStack](https://notestack.com "NoteStack") diff --git a/docs/server/domain-name.md b/docs/server/domain-name.md deleted file mode 100644 index 85cc8c8..0000000 --- a/docs/server/domain-name.md +++ /dev/null @@ -1,40 +0,0 @@ -# Get a Domain Name - -For this guide we'll be using [Namecheap](https://www.namecheap.com/). You can use any domain registrar you like, but the images in this guide will be specific to Namecheap. - -## Register - -First, go to [Namecheap](https://www.namecheap.com/) and search for a domain name. Once you find one you like, add it to your cart and proceed to checkout. You can get a `.xyz` for about $1 for the first year so if you don't want to commit to a domain just yet get one of these to get started. - -![Namecheap Domain Search](../images/namecheap-search.png) - -## Checkout - -Once you're at the checkout screen, you'll see a few options. You can toggle on the switch for `Domain Privacy` which is free and leave the rest toggled off. If you like your domain and plan to keep it I recommend turning on `AUTO-RENEW` as well. - -![Namecheap Checkout](../images/namecheap-checkout.png) - -## DNS - -After your order is processed you can go to your Domain List and see your new domain. You can click on the `Manage` button, and then choose `Advanced DNS` to get started hooking up your domain to the server you created in the last section. We'll be adding a few records so make sure you have the IP addresses from the server from the last section. - -First, remove the default records that name cheap added for you. You should have a `CNAME` record for `www` and an `A` record for `@`. - -![Namecheap Remove Records](../images/namecheap-remove-records.png) - -Now we'll add a few records for `@` which is the root domain (relayrunner.xyz), `www` (www.relayrunner.xyz), and `relay` (relay.relayrunner.xyz). You will need to create an `A` record for each IPv4 address and a `AAAA` record for each Ipv6 address. When you're done it should look like the image below: - -![Namecheap Records](../images/namecheap-records.png) - -## DNS Propagation - -It can take up to 24 hours for your DNS changes to propagate. You can check the status of your DNS changes by going to [WhatsMyDNS.net](https://www.whatsmydns.net/) - -When you enter your domain name you should see the IP addresses you added in the previous step. If you don't see them yet, wait a few hours and check again. - -## Some other places to get a domain - -- [porkbun](https://porkbun.com/) * Pay with Bitcoin -- [hostinger](https://www.hostinger.com/) * Pay with Bitcoin - - diff --git a/docs/server/firewall.md b/docs/server/firewall.md index 4050a60..9cdee82 100644 --- a/docs/server/firewall.md +++ b/docs/server/firewall.md @@ -1,18 +1,129 @@ # Firewall -You should allow traffic on port 80 and 443. +By setting up a firewall we’ll be able to monitor, allow, and block incoming and outgoing network traffic based on security rules that we define. Multiple network ports may be open and listening for incoming connections by default which leaves the relay open to various network based attacks. By monitoring and gaining control over which ports are open and closed we’ll be able to mitigate many of the network based attacks. -Check the status of the firewall: +We’ll be using the [Uncomplicated Firewall (UFW)](https://launchpad.net/ufw "Uncomplicated Firewall (UFW)") which is a firewall configuration tool that allows us to easily manage a [netfilter](https://www.netfilter.org/ "netfilter") firewall by using the provided `ufw` command. + +## Install UFW + +To install UFW run the following command: + +```bash +apt install ufw +``` + +## Status + +To check the status of UFW run the following command: ```bash ufw status ``` -If only SSH is allowed you can allow HTTP and HTTPS traffic by running the following commands: +The output indicates if the firewall is `active` or `inactive`. + +## Default Policy + +Before enabling UFW and activating the firewall, we’re going to first discuss the default policies for incoming and outgoing network traffic. The default policies determine how traffic that doesn’t match a specific rule is controlled. + +By default, UFW is configured to deny all incoming connections and to allow all outgoing connections. This means no one can establish a connection with the server while an application running on the server can establish a connection outside of the server. + +The following commands can be run to reset the default behavior of UFW for incoming and outgoing connections. + +### Deny Incoming + +To deny all incoming connections run the following command: + +```bash +ufw default deny incoming +``` + +### Allow Outgoing + +To allow all outgoing connections run the following command: + +```bash +ufw default allow outgoing +``` + +## Allow Incoming SSH Connections + +When UFW is enabled by default it will block all incoming connections to the relay. With the current configuration of UFW we’ll be disconnected once we enable it since we’re using SSH to access the relay. Therefore, we need to first allow incoming SSH connections before we enable UFW. + +To allow incoming SSH connections we need to open the port the relay is using for SSH. + +If you’re using the default port for the SSH server, i.e., port `22`, you can run the following command to allow incoming SSH connections: + +```bash +ufw allow ssh +``` + +If you changed the default port for the SSH server, then run the following command to allow incoming SSH connections on the custom port: + +```bash +ufw allow +``` + +Here `` should be replaced with the custom listening port number you set for the SSH server. + +## Allow Incoming Nginx Connections + +We're going to set up an Nginx reverse proxy in the next section, so we're going to allow incoming HTTP and HTTPS connections on ports `80` and `443`, respectively. + +To allow incoming HTTP and HTTPS connections you can run the following command: ```bash ufw allow 'Nginx Full' ``` -![ufw status](../images/ufw-status.png) +## Logging + +By default, UFW will keep logs using low mode which means it logs all the packets that are blocked or allowed by the rules we set. + +### Disable Logging + +If you don’t have a valid reason to keep UFW’s logging active, you should disable the logging because it can take up GBs of the relay's storage. + +```bash +ufw logging off +``` +## Enable + +After setting the incoming connections rules and setting the logging preference, we’re now ready to enable UFW which will activate it and apply the rules we set. + +To enable UFW run the following command: + +```bash +ufw enable +``` + +After running the above command, you may receive a warning message that looks similar to: + +```bash +Command may disrupt existing ssh connections. Proceed with operation (y|n)? +``` + +If you successfully configured the rules for the incoming SSH connections, then enter `y` and press enter. + +## Check Status + +After enabling UFW, you can check the status by running the following command: + +```bash +ufw status +``` + +The output indicates if the firewall is `active` or `inactive` as well as all of the rules you set for your firewall. + +The status of your firewall should look similar to the following: + +![UFW Status](../images/ufw-status.png) + +## Enable on Boot + +UFW should already be enabled to start automatically on boot, but if it isn’t then run the following command: + +```bash +systemctl enable ufw +``` diff --git a/docs/server/get-a-domain-name.md b/docs/server/get-a-domain-name.md new file mode 100644 index 0000000..c15550a --- /dev/null +++ b/docs/server/get-a-domain-name.md @@ -0,0 +1,39 @@ +# Get a Domain Name + +For this guide we'll be using [Namecheap](https://www.namecheap.com "Namecheap"). You can use any domain registrar you like, but the images in this guide will be specific to Namecheap. + +## Register + +First, go to Namecheap and search for a domain name. Once you find one you like, add it to your cart and proceed to checkout. You can get a `.xyz` for about $1 for the first year, so if you don't want to commit to a domain just yet get one of these to get started. + +![Namecheap Domain Search](../images/namecheap-domain-search.png) + +## Checkout + +Once you're at the checkout screen, you'll see a few options. You can toggle on the switch for `Domain Privacy` which is free and leave the rest toggled off. If you like your domain and plan to keep it, it's recommended to turn on `AUTO-RENEW` as well. + +![Namecheap Checkout](../images/namecheap-checkout.png) + +## DNS + +After your order is processed, you can go to your Domain List and see your new domain. You can click on the `Manage` button, and then choose `Advanced DNS` to get started hooking up your domain to the server you created in the last section. We'll be adding a few records so make sure you have the IP addresses from the server from the last section. + +First, remove the default records that Namecheap added for you. You should have a `CNAME` record for `www` and an `A` record for `@`. + +![Namecheap Remove Records](../images/namecheap-remove-records.png) + +Now we'll add a few records for `@` which is the root domain (relayrunner.xyz), `www` (www.relayrunner.xyz), and `relay` (relay.relayrunner.xyz). You will need to create an `A` record for each IPv4 address and a `AAAA` record for each Ipv6 address. When you're done it should look like the image below: + +![Namecheap Records](../images/namecheap-records.png) + +## DNS Propagation + +It can take up to 24 hours for your DNS changes to propagate. You can check the status of your DNS changes by going to [whatsmydns.net](https://www.whatsmydns.net "whatsmydns.net") + +When you enter your domain name you should see the IP addresses you added in the previous step. If you don't see them yet, wait a few hours and check again. + +## Domain Name Registrars + +- [Hostinger](https://www.hostinger.com "Hostinger") \* Pay with Bitcoin + +- [Porkbun](https://porkbun.com "Porkbun") \* Pay with Bitcoin diff --git a/docs/server/get-a-server.md b/docs/server/get-a-server.md index ee7919a..7e99e0e 100644 --- a/docs/server/get-a-server.md +++ b/docs/server/get-a-server.md @@ -1,54 +1,60 @@ # Get a Server -For this guide we'll be using a Virtual Private Server (VPS) from [vultr](https://www.vultr.com/?ref=9247696). You can use any VPS provider you like, but I recommend vultr because they have a wide range of locations and their pricing is pretty good. +For this guide we'll be using a Virtual Private Server (VPS) from [Vultr](https://www.vultr.com/?ref=9247696 "Vultr"). You can use any VPS provider you like, but Vultr is recommended because they have a wide range of locations and their pricing is reasonable. ## Create an Account -First, you'll need to create an account on vultr. You can do that [here](https://www.vultr.com/?ref=9247696). +First, you'll need to create an account on Vultr. You can do that on the [Vultr](https://www.vultr.com/?ref=9247696 "Vultr") website. ## Deploy a Server -Once you've created an account, you can deploy a server by clicking on the `Deploy` button. +Once you've created an account, you can deploy a server by clicking on the `Deploy +` button in the top right corner. ## Choose a Server Type -If you're just starting out or just plan to use this as a personal relay, I recommend using the `Cloud Compute - Shared CPU` server type. It will only cost you about $6 per month and will be more than enough to store your own notes and test things out. +If you're just starting out or just plan to use this as a personal relay, it's recommended to use the `Cloud Compute - Shared CPU` server type. It will only cost you about $6 per month and will be more than enough to store your own notes and test things out. -If you plan to run a public relay, you may want to choose a more powerful server type. I recommend their `Optimized Cloud Compute - Dedicated CPU` option. +If you plan to run a public relay, you may want to choose a more powerful server type. In that case it's recommended to use their `Optimized Cloud Compute - Dedicated CPU` option. -![server type](../images/server-type.png) +![Server Type](../images/server-type.png) ## Choose a Server Location -You can choose a server location that is closest to you or your target audience. I'll be choosing `New York (NJ)` since it's closest to my location and I only plan to use this as a personal relay. +You can choose a server location that is closest to you or your target audience. We'll be choosing `New York (NJ)` for our server location. -![choose location](../images/choose-location.png) +![Choose Location](../images/choose-location.png) ## Choose an Operating System -You can choose any operating system you like, but I for this guide I'll be using `Debian 12 x64`. +You can choose any operating system (OS) you like, but we'll be using `Debian 12 x64` for this guide. If you want to follow along exactly, be sure to choose the same OS. -![choose image](../images/choose-image.png) +![Choose Image](../images/choose-image.png) ## Choose a Plan +You'll now need to choose a server type for your relay. + +### Cloud Compute - Shared CPU + If you chose the `Cloud Compute - Shared CPU` server type, you can choose the $6 per month plan since it will likely be more than enough for your needs and you can always upgrade later. -![choose plan personal](../images/choose-plan-personal.png) +![Choose Plan Personal](../images/choose-plan-personal.png) + +### Optimized Cloud Compute - Dedicated CPU -If you chose the `Optimized Cloud Compute - Dedicated CPU` server type, I recommend choosing one of the `Storage Optimized` plans since you'll likely need more storage for a public relay. +If you chose the `Optimized Cloud Compute - Dedicated CPU` server type, it's recommended to choose one of the `Storage Optimized` plans since you'll likely need more storage for a public relay. -![choose plan public](../images/choose-plan-public.png) +![Choose Plan Public](../images/choose-plan-public.png) ## Additional Features -You can add additional features like backups, DDoS protection, and more if you like. I recommend adding backups for peace of mind and you might as well enable IPv6 since it's free and could maybe one day matter. If you're running a public server you might also consider enabling DDoS Protection. +You can add additional features like `Auto Backups`, `IPv6`, `DDoS Protection`, etc. It's recommended to add auto backups for peace of mind, and you might as well enable IPv6 since it's free. If you're running a public server, you might also consider enabling DDoS protection. -![additional features](../images/additional-features.png) +![Additional Features](../images/additional-features.png) ## Server Settings -You have the option to choose an ssh key that will automatically be added to your server. If you don't have one don't worry we'll be settings one up later. +You have the option to choose an SSH key that will automatically be added to your server. If you don't have one, don't worry we'll be setting one up later. ## Server Hostname & Label @@ -56,16 +62,24 @@ You can choose a hostname and label for your server. I recommend choosing someth ## Server Info -After your server is provisioned take note of the IP and IPv6 address since we'll need those in the next section. +After your server is provisioned, take note of the IP address and the IPv6 address since we'll need those in the next section. + +![Server Info](../images/server-info.png) + +## Web Hosting/VPS Services + +Here are some other places to get a server: + +- [Njalla](https://njal.la "Njalla") \* Pay with Bitcoin + +- [OrangeWebsite](https://orangewebsite.com "OrangeWebsite") \* Pay with Bitcoin + +- [1984 Hosting Company](https://1984.hosting "1984 Hosting Company") \* Pay with Bitcoin + +- [AWS](https://aws.amazon.com "AWS") -![server info](../images/server-info.png) +- [DigitalOcean](https://www.digitalocean.com "DigitalOcean") -## Some Other places to get a server +- [Hetzner](https://www.hetzner.com "Hetzner") -- [OrangeWebsite](https://orangewebsite.com/) * Pay with Bitcoin -- [Njalla](https://njal.la/) * Pay with Bitcoin -- [1984 Hosting](https://1984.hosting/) * Pay with Bitcoin -- [Hetzner](https://www.hetzner.com/) -- [AWS](https://aws.amazon.com/) -- [Linode](https://www.linode.com/) -- [Digital Ocean](https://www.digitalocean.com/) +- [Linode](https://www.linode.com "Linode") diff --git a/docs/server/remote-access.md b/docs/server/remote-access.md index ab406ec..30513ab 100644 --- a/docs/server/remote-access.md +++ b/docs/server/remote-access.md @@ -1,45 +1,140 @@ # Remote Access -You will need to access your server remotely to install software, update the server, and manage the relay. This guide will show you how to access your server using SSH. +You'll need to access your server remotely to install software, update the server, and manage the relay. This guide will show you how to access your server using SSH. -## Login to your server +## Login to your Server -You will need to login to your server using SSH. You can do this by running the following command: +You'll need to login to your server using SSH. + +You can do this by running the following command: ```bash -ssh root@relayrunner.xyz # replace with your domain name +ssh root@relayrunner.xyz ``` -![SSH into server](../images/ssh-into-server.png) +Be sure to replace `relayrunner.xyz` with the domain name you're using with your relay. + +### Confirm Fingerprint + +When you first attempt to SSH into the relay from your client you’ll be prompted with the SSH server fingerprint and asked to confirm the connection. + +To confirm the connection answer the prompt by typing `yes` and pressing enter. + +After answering `yes` and establishing the connection the SSH server fingerprint will be stored in the client’s `known_hosts` file which is located in the `.ssh` hidden directory. + +### Enter Password + +You'll then be prompted to enter the password for the user you're using with SSH, i.e., `root` in our case. -You will be prompted to enter your password. You can find the password in your server details. +You can find the password in your server details. ![Server Password](../images/server-password.png) -### [Optional] Login with ssh key +### SSH Login Output + +If the SSH login was successful, the output should look similar to the following: + +![SSH into Server](../images/ssh-into-server.png) + +After successfully logging into your server, it's recommended to set up public key authentication and to disable password authentication or at the very least to change the password provided by your VPS to be something unique and secure. + +## Exit SSH Server + +To exit the SSH server session run the following command: + +```bash +exit +``` + +You should now be returned to the terminal of your client. + +## Public Key Authentication + +Since the relay is visible from the internet and not just present on a Local Area Network (LAN), it needs to be secured against various attacks, e.g., brute forcing your SSH login password. + +To improve the security of the SSH login, we’re going to set up public key authentication and disable password authentication. This improves the security of the SSH login by reducing the possibility of unauthorized access since an SSH key pair will be used to login to the server. Therefore, only someone with physical possession of the private key can easily login to the server. + +Since anyone with the private key will be able to login to the server, it’s important to properly secure the private key by using secure key management practices and to use a passphrase which is used to encrypt the private key. + +### Copy Public Key + +You can copy your SSH public key to your relay by running the following command from your client: + +```bash +ssh-copy-id -i root@relayrunner.xyz +``` + +Be sure to replace `` with the path to the SSH public key you're using with your relay which is located in the `/root/.ssh` directory if you used the default location when generating your SSH key pair. -If you have a ssh key you can use that instead of a password. You can add your ssh key to your server by running the following command: +Also, be sure to replace `relayrunner.xyz` with the domain name you're using with your relay. + +After running the `ssh-copy-id` command you’ll initially be prompted to enter the SSH login password. + +Once you successfully authenticate the user you’ll see output similar to: + +![SSH Copy ID](../images/ssh-copy-id.png) + +The public key will be appended to the `authorized_keys` +file on the relay which will be created if it doesn’t exist, and the connection will be closed. + +The `authorized_keys` file contains all of the public keys that have been copied to the relay and is located in the `/root/.ssh` directory. + +If you ever want to remove a public key, then open the `authorized_keys` file, delete the line containing the public key you want to remove, and save the file. + +### Login + +Now you can login to your relay and you shouldn't be prompted to enter a password since you're using public key authentication: ```bash -ssh-copy-id root@relayrunner.xyz # replace with your domain name +ssh root@relayrunner.xyz ``` -![SSH copy id](../images/ssh-copy-id.png) +## Disable Password Authentication + +To add another layer of security to the relay, we’re going to disable the password authentication for SSH which means only public key authentication will be used to login to the relay. Preventing password authentication protects the relay from various attacks like attempting to brute force or guess the SSH login password. + +Before disabling password authentication, make sure you’re able to login with public key authentication and the user you’re logging in with has `sudo` privileges which should be the case if you’ve been following along. -Now you can login to your server without a password. +To start SSH into the relay using public key authentication if you’re not already logged in. -If you'd like to disable password login you can do so by editing the sshd config file: +Next, we need to open the `sshd_config` file on the relay by running the following command: ```bash nano /etc/ssh/sshd_config ``` -Find the line that says `#PasswordAuthentication yes` uncomment it and change it to `PasswordAuthentication no`. +To disable tunneled clear text passwords locate the `PasswordAuthentication` keyword, uncomment it, and set it to `no`. + +The line should look like the following: + +```bash +PasswordAuthentication no +``` + +To disable challenge-response passwords locate the `KbdInteractiveAuthentication` keyword and set it to `no`. -Find the line that says `UsePAM yes` and change it to `UsePAM no`. +The line should look like the following: -Then reload the ssh service: +```bash +KbdInteractiveAuthentication no +``` + +To disable PAM authentication, account processing, and session processing locate the `UsePAM` keyword and set it to `no`. + +The line should look like the following: + +```bash +UsePAM no +``` + +After editing the file, save and exit. + +For the changes to take effect we need to reload the SSH server which we can do by running the following command: ```bash systemctl reload sshd ``` + +Now, if you attempt to SSH into the relay from a client that doesn’t have access to the private key from your SSH key pair, then the login attempt will be refused without giving the option of entering the SSH login password. + +If you lose access to your SSH keys, then you'll be unable to access the relay remotely using SSH. Be sure to securely backup the passphrase for the private key if you used one as well as the SSH keys using, e.g., a USB. diff --git a/docs/server/reverse-proxy.md b/docs/server/reverse-proxy.md index 32dac89..2824335 100644 --- a/docs/server/reverse-proxy.md +++ b/docs/server/reverse-proxy.md @@ -1,10 +1,16 @@ # Reverse Proxy -A reverse proxy is a server that sits between clients and the backend server(s) that they’re trying to access. It receives requests from clients and forwards them to the backend server(s). The response from the backend server(s) is then sent back to the client. +A reverse proxy is a server that sits between clients and the backend server(s) that the clients are trying to access. It receives requests from clients and forwards them to the backend server(s). The response from the backend server(s) is then sent back to the client. -## Update your server +We'll be setting up an HTTP server with an upstream backend WebSocket server. -You should update your server to make sure you have the latest software. You can do this by running the following command: +Since the server only uses HTTP, the communication between the client and the server isn't encrypted. We'll be going over how to set up an SSL/TLS certificate in the next section to enable HTTPS which will encrypt the communication between the client and the server. + +## Update your Server + +You should update your server to make sure you have the latest software. + +You can do this by running the following command: ```bash apt update && apt upgrade -y @@ -12,66 +18,128 @@ apt update && apt upgrade -y ## Install Nginx +Install Nginx by running the following command: + ```bash apt install nginx ``` ## Configure Nginx -Add a configuration file for your site in the `/etc/nginx/conf.d/` directory. +You now need to add an Nginx config file for your site in the `/etc/nginx/conf.d` directory. + +First, navigate to the `/etc/nginx/conf.d` directory by running: ```bash -cd /etc/nginx/conf.d/ +cd /etc/nginx/conf.d ``` -You can name the file whatever you'd like, but it should end with `.conf`. Here is an example configuration file for a relay: +You can name the file whatever you'd like, but it should end with `.conf`. -```nginx title="relay.conf" -map $http_upgrade $connection_upgrade { - default upgrade; - '' close; -} +We'll be naming the file using the `relay` subdomain we previously set up in [Namecheap](https://www.namecheap.com "Namecheap"), i.e., `relay.relayrunner.xyz`. -upstream websocket { - server 127.0.0.1:8080; -} +To create the file run the following command: + +```bash +touch relay_relayrunner_xyz.conf +``` + +Be sure to replace `relay_relayrunner_xyz.conf` with your Nginx config file name. +Here's an example config file for `relay_relayrunner_xyz.conf`: + +```nginx title="relay_relayrunner_xyz.conf" server { listen 80; listen [::]:80; server_name relay.relayrunner.xyz; # replace with your domain location /.well-known/acme-challenge/ { - root /var/www/relayrunner; # replace with your domain + root /var/www/relay.relayrunner.xyz; # replace with your domain allow all; } location / { - proxy_pass http://websocket; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; + try_files $uri $uri/ =404; } + + # Only return Nginx in server header + server_tokens off; + + #### Security Headers #### + # Test configuration: + # https://securityheaders.com/ + # https://observatory.mozilla.org/ + add_header X-Frame-Options DENY; + + # Avoid MIME type sniffing + add_header X-Content-Type-Options "nosniff" always; + + add_header Referrer-Policy "no-referrer" always; + + add_header X-XSS-Protection "1; mode=block" always; + + add_header Permissions-Policy "geolocation=(), midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=()" always; + + #### Content-Security-Policy (CSP) #### + add_header Content-Security-Policy "base-uri 'self'; object-src 'none'; frame-ancestors 'none';" always; } ``` -Make sure to replace `relayrunner` with your domain name. +Be sure to replace `relay.relayrunner.xyz` with your domain name. -## Reload Nginx +The security headers specified above can be changed to meet the specific needs of your relay. The values chosen here place an emphasis on security and privacy, but there are even more strict values that can be set depending on your use case. + +If you want to properly secure your server, be sure to set up an SSL/TLS certificate in the next section. + +## Test Nginx -now test your config and restart Nginx to apply the changes: +Now you can test your Nginx configuration: ```bash -nginx -t # if this command fails, you have a syntax error in your config +nginx -t +``` + +If this command fails, you most likely have a syntax error in your Nginx config file. + +## Reload Nginx + +After successfully testing your Nginx config file, you can reload Nginx to apply the changes: -systemctl restart nginx +```bash +systemctl reload nginx ``` -## Nginx Resources +## Resources + +If you want to learn more about Nginx, security headers, and the Content Security Policy (CSP), be sure to check out the resources below. + +### Nginx + +- [Nginx Product Documentation](https://docs.nginx.com "Nginx Product Documentation") + +- [Beginner's Guide](https://nginx.org/en/docs/beginners_guide.html "Beginner's Guide") + +- [Nginx Directory Structure](https://wiki.debian.org/Nginx/DirectoryStructure "Nginx Directory Structure") + +- [Nginx Configuration Generator](https://www.digitalocean.com/community/tools/nginx "Nginx Configuration Generator") + +### Content Security Policy (CSP) + +- [Content Security Policy - An Introduction](https://scotthelme.co.uk/content-security-policy-an-introduction "Content Security Policy - An Introduction") + +- [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP "Content Security Policy (CSP)") + +- [Content security policy](https://web.dev/articles/csp "Content security policy") + +- [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy "Content-Security-Policy") + +### Security Headers + +- [Hardening your HTTP response headers](https://scotthelme.co.uk/hardening-your-http-response-headers "Hardening your HTTP response headers") + +- [A new security header: Referrer Policy](https://scotthelme.co.uk/a-new-security-header-referrer-policy "A new security header: Referrer Policy") + +- [A new security header: Feature Policy](https://scotthelme.co.uk/a-new-security-header-feature-policy "A new security header: Feature Policy") -- [Nginx Documentation](https://docs.nginx.com/) -- [Nginx Configuration](https://nginx.org/en/docs/beginners_guide.html) -- [Nginx Directory Structure](https://wiki.debian.org/Nginx/DirectoryStructure) -- [Nginx Configuration Generator](https://www.digitalocean.com/community/tools/nginx) +- [Goodbye Feature Policy and hello Permissions Policy!](https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy "Goodbye Feature Policy and hello Permissions Policy!") diff --git a/docs/server/ssl-tls-certificate.md b/docs/server/ssl-tls-certificate.md new file mode 100644 index 0000000..9558d21 --- /dev/null +++ b/docs/server/ssl-tls-certificate.md @@ -0,0 +1,214 @@ +# SSL/TLS Certificate + +SSL/TLS certificates are used to secure the connection between the client and the server. This is important for protecting sensitive information such as passwords and personal information. The certificates are used to encrypt the data that is sent between the client and the server. This ensures that the data cannot be intercepted by a third party. + +By generating SSL/TLS certificates for our server, we'll be enabling the ability to use HTTPS on the server which we'll then configure for Nginx. + +## Install Certbot + +Certbot is a tool that can be used to automatically generate and renew SSL/TLS certificates. + +To install Certbot on your server run: + +```bash +apt install certbot python3-certbot-nginx +``` + +## Add acme-challenge Directory + +To generate the SSL/TLS certificate, we need to create a directory to store the challenge files: + +```bash +mkdir -p /var/www/relay.relayrunner.xyz/.well-known/acme-challenge +``` + +The `acme-challenge` directory will be used by Certbot to verify that you own the domain. + +Be sure to replace the `relay.relayrunner.xyz` directory with your domain name that you're using for your relay. + +## Generate SSL/TLS Certificate + +Generate the SSL/TLS certificate using Certbot: + +```bash +certbot certonly --webroot -w /var/www/relay.relayrunner.xyz -d relay.relayrunner.xyz +``` + +Be sure to replace `relay.relayrunner.xyz` with your domain name that you're using for your relay. + +### Certbot Email + +If this is your first time running Certbot on your server, you'll be prompted to provide an email address which is used to send warnings about upcoming certificate expirations as well as warnings about using a deprecated and possibly insecure setup. + +If you don't want to provide an email, leave the input empty. It's possible to add an email to your Certbot account later if you decide you do want to receive the notifications. + +If you do provide an email, you'll be asked if you want to share your email with the Electronic Frontier Foundation (EFF) to receive news, campaigns, ways to support digital freedom, etc. If you don't want to receive EFF emails, type `n` and press enter. + +To add an email to your Certbot account and to update the email associated with your Certbot account run the following command: + +```bash +certbot update_account --email your-email@example.com +``` + +Be sure to replace `your-email@example.com` with the email address you want to use with your Certbot account. + +## Configure Nginx + +Replace the contents of `/etc/nginx/conf.d/relay_relayrunner_xyz.conf` with the following configuration where `relay_relayrunner_xyz.conf` should be replaced by whatever name you used for your Nginx config file: + +```nginx title="relay_relayrunner_xyz.conf" +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name relay.relayrunner.xyz; # replace with your domain + + location / { + try_files $uri $uri/ =404; + } + + # Only return Nginx in server header + server_tokens off; + + #### SSL Configuration #### + # Test configuration: + # https://www.ssllabs.com/ssltest/analyze.html + # https://cryptcheck.fr/ + ssl_certificate /etc/letsencrypt/live/relay.relayrunner.xyz/fullchain.pem; # replace with your domain + ssl_certificate_key /etc/letsencrypt/live/relay.relayrunner.xyz/privkey.pem; # replace with your domain + # Verify chain of trust of OCSP response using Root CA and Intermediate certs + ssl_trusted_certificate /etc/letsencrypt/live/relay.relayrunner.xyz/chain.pem; # replace with your domain + + ssl_protocols TLSv1.3 TLSv1.2; + + # For more information on the security of different cipher suites, you can refer to the following link: + # https://ciphersuite.info/ + # Compilation of the top cipher suites 2024: + # https://ssl-config.mozilla.org/#server=nginx + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305"; + + # Perfect Forward Secrecy (PFS) is frequently compromised without this + ssl_prefer_server_ciphers on; + + ssl_session_tickets off; + + # Enable SSL session caching for improved performance + # Try setting ssl_session_timeout to 1d if performance is bad + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + + # By default, the buffer size is 16k, which corresponds to minimal overhead when sending big responses. + # To minimize Time To First Byte it may be beneficial to use smaller values + ssl_buffer_size 8k; + + # OCSP stapling + ssl_stapling on; + ssl_stapling_verify on; + + #### Security Headers #### + # Test configuration: + # https://securityheaders.com/ + # https://observatory.mozilla.org/ + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; + + add_header X-Frame-Options DENY; + + # Avoid MIME type sniffing + add_header X-Content-Type-Options "nosniff" always; + + add_header Referrer-Policy "no-referrer" always; + + add_header X-XSS-Protection "1; mode=block" always; + + add_header Permissions-Policy "geolocation=(), midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=()" always; + + #### Content-Security-Policy (CSP) #### + add_header Content-Security-Policy "base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests;" always; +} + +server { + listen 80; + listen [::]:80; + server_name relay.relayrunner.xyz; # replace with your domain + + location /.well-known/acme-challenge/ { + root /var/www/relay.relayrunner.xyz; # replace with the directory you used to store the challenge files in + allow all; + } + + location / { + return 301 https://relay.relayrunner.xyz$request_uri; # replace with your domain + } +} +``` + +Be sure to replace `relay.relayrunner.xyz` with your domain name and `/var/www/relay.relayrunner.xyz` with the directory you used to store the challenge files in. + +The SSL/TLS directives and the security headers specified above can be changed to meet the specific needs of your relay. The values chosen here place an emphasis on security and privacy. There are even more strict values that can be set especially for the `Permissions-Policy` and `Content-Security-Policy` headers depending on your requirements. + +## Test Nginx + +Now you can test your Nginx configuration: + +```bash +nginx -t +``` + +If this command fails, you most likely have a syntax error in your Nginx config file. + +## Reload Nginx + +After successfully testing your Nginx config file, you can reload Nginx to apply the changes: + +```bash +systemctl reload nginx +``` + +## Resources + +If you want to learn more about Nginx, security headers, the Content Security Policy (CSP), and how to test your configuration, be sure to check out the resources below. + +### Nginx + +- [Nginx Product Documentation](https://docs.nginx.com "Nginx Product Documentation") + +- [Beginner's Guide](https://nginx.org/en/docs/beginners_guide.html "Beginner's Guide") + +- [Nginx Directory Structure](https://wiki.debian.org/Nginx/DirectoryStructure "Nginx Directory Structure") + +- [How I configure my sites in NGINX](https://blog.jeanbruenn.info/2021/08/12/how-i-configure-my-sites-in-nginx "How I configure my sites in NGINX") + +- [Nginx Configuration Generator](https://www.digitalocean.com/community/tools/nginx "Nginx Configuration Generator") + +- [moz://a SSL Configuration Generator](https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=modern&openssl=1.1.1d&guideline=5.7 "moz://a SSL Configuration Generator") + +### Content Security Policy (CSP) + +- [Content Security Policy - An Introduction](https://scotthelme.co.uk/content-security-policy-an-introduction "Content Security Policy - An Introduction") + +- [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP "Content Security Policy (CSP)") + +- [Content security policy](https://web.dev/articles/csp "Content security policy") + +- [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy "Content-Security-Policy") + +### Security Headers + +- [Hardening your HTTP response headers](https://scotthelme.co.uk/hardening-your-http-response-headers "Hardening your HTTP response headers") + +- [A new security header: Referrer Policy](https://scotthelme.co.uk/a-new-security-header-referrer-policy "A new security header: Referrer Policy") + +- [A new security header: Feature Policy](https://scotthelme.co.uk/a-new-security-header-feature-policy "A new security header: Feature Policy") + +- [Goodbye Feature Policy and hello Permissions Policy!](https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy "Goodbye Feature Policy and hello Permissions Policy!") + +### Tests + +- [Qualys SSL Labs](https://www.ssllabs.com "Qualys SSL Labs") + +- [CryptCheck](https://cryptcheck.fr "CryptCheck") + +- [Security Headers](https://securityheaders.com "Security Headers") + +- [Observatory](https://observatory.mozilla.org "Observatory") + +- [webbkoll](https://webbkoll.dataskydd.net/en "webbkoll") diff --git a/docs/server/ssl.md b/docs/server/ssl.md deleted file mode 100644 index fc0d69e..0000000 --- a/docs/server/ssl.md +++ /dev/null @@ -1,93 +0,0 @@ -# SSL/TLS Certificate - -SSL/TLS certificates are used to secure the connection between the client and the server. This is important for protecting sensitive information such as passwords and personal information. The certificates are used to encrypt the data that is sent between the client and the server. This ensures that the data cannot be intercepted by a third party. - -## Install Certbot - -Certbot is a tool that can be used to automatically generate and renew SSL/TLS certificates. - -```bash -apt install certbot python3-certbot-nginx -``` - -## Add acme-challenge directory - -To generate the SSL/TLS certificate, we need to create a directory to store the challenge files. This directory will be used by Certbot to verify that you own the domain. Replace this directory name with your domain name. - -```bash -mkdir -p /var/www/relayrunner # replace with your domain - -mkdir -p /var/www/relayrunner/.well-known/acme-challenge/ # replace with your domain -``` - -## Generate SSL/TLS Certificate - -Generate the SSL/TLS certificate using Certbot. Replace `relayrunner.xyz` with your domain name. - -```bash -certbot certonly --webroot -w /var/www/relayrunner -d relay.relayrunner.xyz # replace with your domain -``` - -## Configure Nginx - -Replace the contents of `/etc/nginx/conf.d/relay.conf` with the following configuration: - -```nginx title="relay.conf" -map $http_upgrade $connection_upgrade { - default upgrade; - '' close; -} - -upstream websocket { - server 127.0.0.1:8080; -} - -server { - listen 443 ssl; - listen [::]:443 ssl; - server_name relay.relayrunner.xyz; # replace with your domain - - location / { - proxy_pass http://websocket; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; - } - - #### SSL Configuration #### - ssl_certificate /etc/letsencrypt/live/relayrunner.xyz/fullchain.pem; # replace with your domain - ssl_certificate_key /etc/letsencrypt/live/relayrunner.xyz/privkey.pem; # replace with your domain - - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 10m; - ssl_protocols TLSv1.2 TLSv1.1 TLSv1; - ssl_prefer_server_ciphers on; - ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"; - ssl_stapling on; - ssl_stapling_verify on; - ssl_ecdh_curve secp384r1; - - add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; - add_header X-Frame-Options DENY; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header Referrer-Policy same-origin; - add_header Feature-Policy "geolocation none;midi none;notifications none;push none;sync-xhr none;microphone none;camera none;magnetometer none;gyroscope none;speaker self;vibrate none;fullscreen self;payment none;"; -} -``` - -## Reload Nginx - -First, test the configuration to make sure there are no syntax errors: - -```bash -nginx -t -``` - -If that went well, reload Nginx to apply the changes: - -```bash -systemctl reload nginx -``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6542b9f..6cec1fa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,23 +3,60 @@ nav: - Home: - Introduction: index.md - Implementations: implementations.md + - Contact: contact.md - Resources: resources.md - FAQ: faq.md - Server: - Get a Server: server/get-a-server.md - - Get a Domain Name: server/domain-name.md + - Get a Domain Name: server/get-a-domain-name.md - Remote Access: server/remote-access.md - - Reverse Proxy: server/reverse-proxy.md - Firewall: server/firewall.md - - SSL/TLS Certificate: server/ssl.md + - Reverse Proxy: server/reverse-proxy.md + - SSL/TLS Certificate: server/ssl-tls-certificate.md - Relay: - - Install: relay/install.md - - Configure: relay/config.md - - Service: relay/service.md - # - Free up Space: relay/free-up-space.md - - Test Your Relay: relay/test.md + - Khatru Pyramid: relay/khatru-pyramid.md + - Install: relay/khatru-pyramid/install.md + - Configuration: relay/khatru-pyramid/configuration.md + - Service: relay/khatru-pyramid/service.md + - Test Your Relay: relay/khatru-pyramid/test.md + + - Nostream: relay/nostream.md + - Install: relay/nostream/install.md + - Configuration: relay/nostream/configuration.md + - Service: relay/nostream/service.md + - Test Your Relay: relay/nostream/test.md + + - nostr-rs-relay: relay/nostr-rs-relay.md + - Install: relay/nostr-rs-relay/install.md + - Configuration: relay/nostr-rs-relay/configuration.md + - Service: relay/nostr-rs-relay/service.md + - Test Your Relay: relay/nostr-rs-relay/test.md + + - strfry: relay/strfry.md + - Install: relay/strfry/install.md + - Configuration: relay/strfry/configuration.md + - Service: relay/strfry/service.md + - Test Your Relay: relay/strfry/test.md + + - WoT Relay: relay/wot-relay.md + - Install: relay/wot-relay/install.md + - Configuration: relay/wot-relay/configuration.md + - Service: relay/wot-relay/service.md + - Test Your Relay: relay/wot-relay/test.md + + - relay29 Khatru29: relay/relay29-khatru29.md + - Install: relay/relay29-khatru29/install.md + - Configuration: relay/relay29-khatru29/configuration.md + - Service: relay/relay29-khatru29/service.md + - Test Your Relay: relay/relay29-khatru29/test.md + + - relay29 strfry29: relay/relay29-strfry29.md + - Install: relay/relay29-strfry29/install.md + - Configuration: relay/relay29-strfry29/configuration.md + - Service: relay/relay29-strfry29/service.md + - Test Your Relay: relay/relay29-strfry29/test.md - Donate: - bitcoin: donate/index.md @@ -97,11 +134,11 @@ extra: generator: false social: - icon: fontawesome/brands/twitter - link: https://twitter.com/@chrisatmachine - name: chrisatmachine on Twitter + link: https://x.com/node_tec + name: NODE-TEC on Twitter - icon: fontawesome/brands/youtube - link: https://youtube.com/@chrisatmachine - name: chrisatmachine on YouTube + link: https://www.youtube.com/@nodetec + name: NODE-TEC on YouTube - icon: fontawesome/brands/github link: https://github.com/nodetec name: NODE-TEC on GitHub diff --git a/nginx.conf b/nginx.conf index 25b8ed9..d0b208a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,5 +1,4 @@ server { - listen 80; listen [::]:80;