feed.xml 282 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234
  1. <?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>GNUcode.me</title><id>https://gnucode.me/feed.xml</id><subtitle>Recent Posts</subtitle><updated>2023-05-12T11:47:30Z</updated><link href="gnucode.me/feed.xml" rel="self" /><link href="gnucode.me" /><entry><title>Afterboot OpenBSD</title><id>https://gnucode.me/afterboot-openbsd.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-04-28T23:00:00Z</updated><link href="https://gnucode.me/afterboot-openbsd.html" rel="alternate" /><summary type="html">&lt;h1&gt;set up doas&lt;/h1&gt;&lt;p&gt;Let’s make any user that is in the group “wheel” able to execute privledged
  2. commands.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# cat /etc/examples/doas.conf | sed 's/keepenv/persist keepevn/' &amp;gt; /etc/doas.conf&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;install packages&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;# pkg_add emacs dino netsurf dino git fish mpv firefox gpg \
  3. hack-fonts pkg_add isync evince libreoffice xfce4-terminal \
  4. xfce4-screenshooter xfce4-dict i3&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I installed isync, I got a message that said,
  5. the following rcscripts were installed: /etc/rc.d/saslauthd
  6. apparently openbsd’s packaged isync, lets you set up a daemon to periodically
  7. fetch your email. looking at the file, I’m not sure what it is.&lt;/p&gt;&lt;p&gt;Well I could list all of the packages that I minually installed, it is actually
  8. much easier to create a list of packages.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;pkg_info -mz | tee openbsd-pkg-list&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, when I want to re-install those packages I can just do this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# pkg_add -l list&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;clone my various repos&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;cd ~/
  9. git clone https://notabug.org/jbranso/prog
  10. cd prog
  11. mkdir -p gnu/guix/
  12. cd gnu/guix
  13. git clone https://notabug.org/jbranso/guix
  14. mv guix guix-src
  15. git clone https://notabug.org/jbranso/guix-config&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;update my OpenBSD install&lt;/h1&gt;&lt;p&gt;&lt;code&gt;# doas syspatch&lt;/code&gt;&lt;/p&gt;&lt;h1&gt;enable softupdates&lt;/h1&gt;&lt;p&gt;Unless you are using really old ancient hardware, you should enable softupdates.&lt;/p&gt;&lt;p&gt;change&lt;/p&gt;&lt;p&gt;&lt;code&gt;43434930490.a / ffs rw 1 1&lt;/code&gt;&lt;/p&gt;&lt;p&gt;to&lt;/p&gt;&lt;p&gt;&lt;code&gt;43434930490.a / ffs rw,softdep 1 1&lt;/code&gt;&lt;/p&gt;&lt;h1&gt;window manager stuff&lt;/h1&gt;&lt;h2&gt;modify my ~/.xsession&lt;/h2&gt;&lt;p&gt;auto start xfce, prefer utf-8, set up a background color, and lock X after some
  16. inactivity.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.xsession
  17. # prefer UTF-8 whenever possible
  18. export LC_CTYPE=&amp;quot;en_US.UTF-8&amp;quot;
  19. # use UTF-8 everywhere
  20. export LANG=en_US.UTF-8
  21. # specify location of kshrc
  22. export ENV=$HOME/.kshrc
  23. # set your background color
  24. xsetroot -solid dimgray
  25. xidle -delay 5 -sw -program &amp;quot;/usr/X11R6/bin/xlock -mode flag&amp;quot; \
  26. -timeout 300
  27. exec i3&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;set up polybar for i3&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://forum.endeavouros.com/t/tutorial-easy-setup-endeavour-xfce-i3-tiling-window-manager/13171&quot;&gt;https://forum.endeavouros.com/t/tutorial-easy-setup-endeavour-xfce-i3-tiling-window-manager/13171&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# doas pkg_add polybar
  28. $ mkdir ~/.config/polybar
  29. $ cp /usr/local/share/examples/polybar/config ~/.config/polybar&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This &lt;a href=&quot;https://github.com/polybar/polybar/wiki/Fonts&quot;&gt;wiki page&lt;/a&gt; has a lot of details about setting up fonts.&lt;/p&gt;&lt;p&gt;More information is in my &lt;a href=&quot;https://notabug.org/jbranso/openbsd-home/src/master/.config/polybar&quot;&gt;polybar config&lt;/a&gt;.&lt;/p&gt;&lt;h1&gt;If this is a laptop with a battery, then install this&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://dataswamp.org/~solene/2022-03-21-openbsd-cool-frequency.html&quot;&gt;https://dataswamp.org/~solene/2022-03-21-openbsd-cool-frequency.html&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# doas pkg_add obsdfreqd
  30. # rcctl enable obsdfreqd
  31. # rcctl stop apmd
  32. # rcctl disable apmd
  33. # rcctl start obsdfreqd&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;set up doom emacs&lt;/h1&gt;&lt;p&gt;(I also need to ensure that &lt;code&gt;~/prog/gnu/guix/&lt;/code&gt; exists because my emacs looks for
  34. some guix snippets).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone --depth 1 https://github.com/doomemacsdoomemacs ~/.config/emacs
  35. ~/.config/emacs/bin/doom install&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;add doom emacs to path&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.profile
  36. # $OpenBSD: dot.profile,v 1.8 2022/08/10 07:40:37 tb Exp $
  37. #
  38. # sh/ksh initialization
  39. #
  40. PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/home/joshua/.config/emacs/bin
  41. export PATH HOME TERM&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;copy my ~/ config files&lt;/h1&gt;&lt;p&gt;cp .authinfo.gpg, .ssh, .mbsyncrc, .gnupg/&lt;/p&gt;&lt;p&gt;cp documents to ~/&lt;/p&gt;&lt;h1&gt;import my gpg keys from my usb stick.&lt;/h1&gt;&lt;p&gt;&lt;code&gt;gpg --import ./dismail.de.gpg.key.asc&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;git config --global commit.gpgsign true&lt;/code&gt;&lt;/p&gt;&lt;h2&gt;set up pinentry&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;pkg_add pinentry-dmenu&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are two things that you need to do to set up pinentry-dmenu, so that when I
  42. need to sign commits or decrypt stuff, the pinentry-dmenu popup happens.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;set up gpg agent&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.gnupg/gpg-agent.conf
  43. pinentry-program /usr/local/bin/pinentry-dmenu
  44. default-cache-ttl 3600&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;man gpg-agent&lt;/code&gt; says to do this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;You should always add the following lines to your .bashrc or whatever
  45. initialization file is used for all shell invocations:
  46. cat ~/.profile | grep GPG_TTY
  47. GPG_TTY=$(tty)
  48. export GPG_TTY&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;start a dbus session&lt;/p&gt;&lt;p&gt;This is only needed if you want to use pinentry-gnome3&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.xsession | grep dbus
  49. # start a dbus session, which I believe gpg needs to for graphical pinentry
  50. # I found this command in /usr/local/share/doc/pkg-readmes/dbus
  51. if [ -x /usr/local/bin/dbus-launch -a -z &amp;quot;${DBUS_SESSION_BUS_ADDRESS}&amp;quot; ]; then
  52. eval `dbus-launch --sh-syntax --exit-with-x11`&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you have difficulty getting pinentry to work, here are some steps to
  53. manually get pinentry to work:&lt;/p&gt;&lt;p&gt;in a fish terminal a type in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpgconf --kill gpg-agent
  54. set GPG_TTY $(tty)
  55. export GPG_TTY
  56. git commit -m &amp;quot;my commit message&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;change &lt;code&gt;/etc/motd&lt;/code&gt;&lt;/h1&gt;&lt;p&gt;I once set an invalid option up in /etc/fstab that threw me in a root shell with
  57. only root mounted. All of a sudden vi would not work. That below command is
  58. how to fix it: &lt;code&gt;export TERM=vt200&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/motd
  59. OpenBSD 7.2 (GENERIC.MP) #7: Sat Feb 25 14:07:58 MST 2023
  60. Welcome to OpenBSD: The proactively secure Unix-like operating system.
  61. Please use the sendbug(1) utility to report bugs in the system.
  62. Before reporting a bug, please try to reproduce it with the latest
  63. version of the code. With bug reports, please try to ensure that
  64. enough information to reproduce the problem is enclosed, and if a
  65. known fix for it exists, include that as well.
  66. If you are having trouble using vi in the console try this:
  67. export TERM=vt200;&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;install haunt on OpenBSD&lt;/h1&gt;&lt;p&gt;&lt;code&gt;doas pkg_add guile info&lt;/code&gt;&lt;/p&gt;&lt;p&gt;First install guile-commonmark:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ cd ~/prog/guile
  68. $ git clone git clone https://github.com/OrangeShark/guile-commonmark
  69. $ cd guile-commonmark
  70. # export AUTOCONF_VERSION=2.71
  71. # export export AUTOMAKE_VERSION=1.16.5
  72. # doas pkg_add autoconf automake&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Why am I seeing 2 aclocal binaries? No idea.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ls /usr/local/bin/aclocal*
  73. ls /usr/local/bin/automake*
  74. /usr/local/bin/aclocal
  75. /usr/local/bin/aclocal-1.16
  76. /usr/local/bin/automake
  77. /usr/local/bin/automake-1.16&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Arsen on irc helped me figure out the next incantation.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;AUTOMAKE=automake-1.16 ACLOCAL=aclocal-1.16 ./bootstrap
  78. ./configure
  79. make
  80. make check
  81. # make install&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s install haunt&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone https://git.dthompson.us/haunt.git
  82. cd haunt
  83. AUTOMAKE=automake-1.16 ACLOCAL=aclocal-1.16 ./bootstrap
  84. ./configure
  85. make
  86. make check
  87. # make install&lt;/code&gt;&lt;/pre&gt;</summary></entry><entry><title>OpenBSD's hotplugd rocks!</title><id>https://gnucode.me/openbsds-hotplugd-rocks.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-04-13T11:41:00Z</updated><link href="https://gnucode.me/openbsds-hotplugd-rocks.html" rel="alternate" /><summary type="html">&lt;p&gt;My last post talked about how I broke my OpenBSD laptop by telling OpenBSD that
  88. my usbstick was essential to the boot process, and then, when I booted the
  89. laptop, I did not have that usb stick mounted. That caused some problems. I
  90. since learned that the preferred way of automounting a usb stick under OpenBSD
  91. is with &lt;code&gt;hotplugd&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://man.openbsd.org/hotplugd&quot;&gt;hotplugd&lt;/a&gt; is OpenBSD’s automounting functionality, and it’s actually super simple
  92. and easy. Just put your scripts at &lt;code&gt;/etc/hotplugd/attach&lt;/code&gt; and
  93. &lt;code&gt;/etc/hotplugd/detach&lt;/code&gt;. And the man page gives you an example shell script, but
  94. since I am not a big fan of &lt;code&gt;sh&lt;/code&gt; (its syntax is confusing), I decided to write
  95. my attach script in &lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;GNU Guile&lt;/a&gt;. Writing that script made me want to write more
  96. scripts in &lt;a href=&quot;https://scsh.net/&quot;&gt;scheme shell&lt;/a&gt;, but I the last time I tried to install the scheme shell
  97. on OpenBSD, it failed to compile.&lt;/p&gt;&lt;p&gt;Anyway, it is really easy to write your own script. &lt;code&gt;hotplugd&lt;/code&gt; will call your
  98. script like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;attach &amp;lt;number&amp;gt; &amp;lt;label&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where &lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt; is one of the numbers in the table below and &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; is a
  99. short descriptive string of the device.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;|---+------------------------------------|
  100. | 0 | generic, no special info |
  101. |---+------------------------------------|
  102. | 1 | CPU (carries resource utilization) |
  103. |---+------------------------------------|
  104. | 2 | disk drive |
  105. |---+------------------------------------|
  106. | 3 | network interface |
  107. |---+------------------------------------|
  108. | 4 | tape device |
  109. |---+------------------------------------|
  110. | 5 | serial line interface |
  111. |---+------------------------------------|&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I am only really interested in &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt;. Here is how I debbuged my attach
  112. script, and you can easily do the same.&lt;/p&gt;&lt;p&gt;First find out what &lt;code&gt;sd&lt;/code&gt; device your usb stick is. Before you put in your usb
  113. stick type in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sysctl hw.disknames
  114. hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now put in your usb stick and run the same command.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sysctl hw.disknames
  115. hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2,sd2:&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now I know that my usb stick is sd2. Let’s do a disklabel command on it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# disklabel sd2
  116. # /dev/rsd2c:
  117. type: SCSI
  118. disk: SCSI disk
  119. label: USB Flash Drive
  120. duid: 0000000000000000
  121. flags:
  122. bytes/sector: 512
  123. sectors/track: 63
  124. tracks/cylinder: 255
  125. sectors/cylinder: 16065
  126. cylinders: 1887
  127. total sectors: 30326784
  128. boundstart: 0
  129. boundend: 30326784
  130. 16 partitions:
  131. # size offset fstype [fsize bsize cpg]
  132. c: 14.5G 0 unused
  133. i: 14.5G 2048 MSDOS&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice from the output that this label is “USB Flash Drive”. That is the label
  134. that hotplugd will send to your attach script.&lt;/p&gt;&lt;p&gt;If you want a usb stick that is read-able/writeable accross all operating
  135. systems, currently you will want to use the &lt;a href=&quot;https://wiki.archlinux.org/title/FAT&quot;&gt;vfat&lt;/a&gt; filesystem. That is what the
  136. output above shows. The &lt;code&gt;fstype&lt;/code&gt; of &lt;code&gt;MSDOS&lt;/code&gt; is a vfat filesystem. This usb stick
  137. is what I will use when I want to copy data between different OS-es (I do want
  138. an &lt;a href=&quot;https://www.openbsd.org/faq/faq14.html#softraidCrypto&quot;&gt;encrypted OpenBSD-specific usb stick&lt;/a&gt; to store my gpg keys, but I have not yet
  139. set that up). According to some of the smart people on the &lt;code&gt;#openbsd&lt;/code&gt; irc
  140. channel, if you have such a usb stick, then the &lt;code&gt;i&lt;/code&gt; filesystem partition is the
  141. one that you want to mount to read the data. And we see that above as well (&lt;code&gt;c&lt;/code&gt;
  142. is code for the whole drive. &lt;code&gt;/dev/rsd2c&lt;/code&gt; is how you access the whole and raw
  143. disk).&lt;/p&gt;&lt;p&gt;Ok, so now that you know what arguments that &lt;code&gt;hotplugd&lt;/code&gt; will send your script,
  144. go ahead and write your basic script. It probably won’t be perfect, which is ok.
  145. To test it, type in &lt;code&gt;su&lt;/code&gt; in your terminal to get to root account, and then test
  146. your script in the exact same way that OpenBSD will use your script (&lt;code&gt;#&lt;/code&gt; means
  147. that you are currently the root user):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# ./attach 2 &amp;quot;USB Flash Drive&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will probably get some weird errors, and that’s ok. After you have run your
  148. attach script, and it seemed to have no errors, verify that it properly mounted
  149. with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mount
  150. /dev/sd1a on / type ffs (local, softdep)
  151. /dev/sd1k on /home type ffs (local, nodev, nosuid, softdep)
  152. /dev/sd1d on /tmp type ffs (local, nodev, nosuid, softdep)
  153. /dev/sd1f on /usr type ffs (local, nodev, softdep)
  154. /dev/sd1g on /usr/X11R6 type ffs (local, nodev, softdep)
  155. /dev/sd1h on /usr/local type ffs (local, nodev, wxallowed, softdep)
  156. /dev/sd1j on /usr/obj type ffs (local, nodev, nosuid, softdep)
  157. /dev/sd1i on /usr/src type ffs (local, nodev, nosuid, softdep)
  158. /dev/sd1e on /var type ffs (local, nodev, nosuid, softdep)
  159. /dev/sd2i on /mnt/usb type msdos (local, nodev, noexec)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And it look like I properly mounted my usb stick (the last line says it was).&lt;/p&gt;&lt;p&gt;One thing that users might find confusing is that OpenBSD passes in &lt;code&gt;2&lt;/code&gt;, but
  160. Guile accepted the &lt;code&gt;2&lt;/code&gt; as a string.&lt;/p&gt;&lt;p&gt;My simple &lt;a href=&quot;https://notabug.org/jbranso/prog/src/master/gnu/guile/scripts/attach&quot;&gt;attach script&lt;/a&gt; works for me. It will only auto mount vfat filesystems,
  161. and I am pretty sure that weird things will happen if I plug in two usb sticks
  162. at once, but it works.&lt;/p&gt;</summary></entry><entry><title>Accidentally Deleting fstab</title><id>https://gnucode.me/accidentally-deleting-fstab.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-04-05T20:00:00Z</updated><link href="https://gnucode.me/accidentally-deleting-fstab.html" rel="alternate" /><summary type="html">&lt;p&gt;The end of my previous blog post was a bit of a cliff hanger:&lt;/p&gt;&lt;p&gt;I did have a great time the next day. I was hoping to automount my usb
  163. stick on boot. So I added this beauty to my &lt;code&gt;/etc/fstab&lt;/code&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;sd1i /mnt/usb msdos rw 1 2&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The next time I booted it threw me into a rescue shell with only &lt;code&gt;/&lt;/code&gt; mounted.&lt;/p&gt;&lt;p&gt;This is the story of how I fixed a broken fstab on OpenBSD. The day began like
  164. any other. It was cold and dark as I arose to play with my new OpenBSD
  165. computer. It was time to reboot! That magical moment when OpenBSD &lt;a href=&quot;https://www.openbsd.org/innovations.html&quot;&gt;relinks the
  166. kernel at boot&lt;/a&gt;. How cool is that?&lt;/p&gt;&lt;p&gt;My admiration for this world class operating continues to rise as it boots, and
  167. OpenBSD proudly slaps me in the face (I did not write down the OpenBSD error
  168. message, but this is essentially what it said):&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;mount cannot find device sd1i. You are now in a resque shell.&lt;/p&gt;&lt;p&gt;root&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Hmmm. Well that’s a bummer. It looks like I had told OpenBSD that that usb stick
  169. was necesary for boot. I also did not have the usb stick plugged in, and OpenBSD
  170. needed me to write &lt;code&gt;/dev/sd1i&lt;/code&gt; not &lt;code&gt;sd1i&lt;/code&gt;. It might be a good project idea to
  171. add &lt;a href=&quot;https://man.openbsd.org/opendev&quot;&gt;opendev&lt;/a&gt; support to OpenBSD’s mount. Any takers?&lt;/p&gt;&lt;p&gt;Anyway, to fix this, I attempted to delete that last line from &lt;code&gt;/etc/fstab&lt;/code&gt;. I
  172. tried to type out &lt;code&gt;cd /etc/&lt;/code&gt;. Instead I got gibberish. Testing the keyboard a
  173. bit, I noticed that the keyboard was in the qwerty layout. I use dvorak. And my
  174. laptop keyboard physically shows a dvorak keyboard layout. It’s really hard to
  175. type correctly on a keyboard when pressing “‘,.pyf” is “qwerty”. Well let’s
  176. change my keyboard layout (notice that all commands below are run as the &lt;code&gt;root&lt;/code&gt;
  177. user. The &lt;code&gt;#&lt;/code&gt; means you are running as a root user).&lt;/p&gt;&lt;p&gt;I painstakingly typed out the following command.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# wsconctl keyboard.encoding=us.dvorak&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Awesome, that is an improvement. Let’s change &lt;code&gt;/etc/fstab&lt;/code&gt;. The following
  178. commands did not work, because the shell could not find the binary:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;nano /etc/fstab&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;vim /etc/fstab&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;vi /etc/fstab&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Well that’s weird. Is &lt;code&gt;/usr/bin&lt;/code&gt; not mounted?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount
  179. /dev/sd1a on / type ffs (ro)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oh great! I only have &lt;code&gt;/&lt;/code&gt; mounted! So my commands are limited, and &lt;code&gt;/&lt;/code&gt; is
  180. mounted read only. So even if I find a text editor that I can use, I cannot
  181. modify &lt;code&gt;/etc/fstab&lt;/code&gt;. How do I mount &lt;code&gt;/&lt;/code&gt; read-write? According to the irc people
  182. who helped me out, this is how: you update the mount information based on what
  183. &lt;code&gt;/etc/fstab&lt;/code&gt; says.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount -uvw /
  184. # mount
  185. /dev/sd1a on / type ffs (rw)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Awesome, &lt;code&gt;fstab&lt;/code&gt; is editable! I tried to edit &lt;code&gt;/etc/fstab&lt;/code&gt; but &lt;code&gt;vi&lt;/code&gt; was not
  186. available, probably because &lt;code&gt;vi&lt;/code&gt; is located in &lt;code&gt;/usr&lt;/code&gt;, which is not yet mounted.&lt;/p&gt;&lt;p&gt;What I should have done was &lt;code&gt;mount -U&lt;/code&gt;. This just mounts all mount points
  187. listed in &lt;code&gt;/etc/fstab&lt;/code&gt;. I did not read that option in the manpage yet. So I
  188. decided to manually try to guess which filesytem was which.&lt;/p&gt;&lt;p&gt;Well let’s print out human read-able file sizes of my filesystem partitions and
  189. that will give me some clue which filesystem is which. (please note that I am
  190. intentionally removing the offsets).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# disklabel -h sd1
  191. 16 partitions:
  192. # size offset fstype [fsize bsize cpg]
  193. a: 1.0G 4.2BSD 2048 16384 12960
  194. b: 8.0G swap
  195. c: 931.5G unused
  196. d: 4.0G 4.2BSD 2048 16384 12960
  197. e: 19.5G 4.2BSD 2048 16384 12960
  198. f: 30.0G 4.2BSD 2048 16384 12960
  199. g: 1.0G 4.2BSD 2048 16384 12960
  200. h: 20.0G 4.2BSD 2048 16384 12960
  201. i: 3.0G 4.2BSD 2048 16384 12960
  202. j: 6.0G 4.2BSD 2048 16384 12960
  203. k: 300.0G 4.2BSD 4096 32768 26062&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok. Clearly the 300G is my &lt;code&gt;/home&lt;/code&gt;. I can mount that now.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount /dev/sd1k /home&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok. How do I mount &lt;code&gt;/usr&lt;/code&gt; so that I have text editors? I don’t really know which
  204. partition is which. I guess I will just guess. Eventually I did correctly mount
  205. &lt;code&gt;/usr&lt;/code&gt;, so now I should have access to some text editors! So now I could edit
  206. &lt;code&gt;fstab&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# vim /etc/fstab
  207. vim: unknown command&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok. vim is not installed. Let’s try vi.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# vi /etc/fstab
  208. vi: unknown terminal type&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So vi doesn’t run on the console? That’s odd. Ok. Lets see what &lt;code&gt;head&lt;/code&gt;
  209. shows me:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# head /etc/fstab
  210. 5583d235b610c8a2.a / ffs rw,softdep 1 1
  211. 5583d235b610c8a2.k /home ffs rw,softdep,nodev,nosuid 1 2
  212. 5583d235b610c8a2.d /tmp ffs rw,softdep,nodev,nosuid 1 2
  213. 5583d235b610c8a2.f /usr ffs rw,softdep,nodev 1 2
  214. 5583d235b610c8a2.g /usr/X11R6 ffs rw,softdep,nodev 1 2
  215. 5583d235b610c8a2.h /usr/local ffs rw,wxallowed,softdep,nodev 1 2
  216. 5583d235b610c8a2.j /usr/obj ffs rw,softdep,nodev,nosuid 1 2
  217. 5583d235b610c8a2.i /usr/src ffs rw,softdep,nodev,nosuid 1 2
  218. 5583d235b610c8a2.e /var ffs rw,softdep,nodev,nosuid 1 2
  219. 5583d235b610c8a2.b none swap sw&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hey would you look at that! There is no line with &lt;code&gt;/mnt/usb&lt;/code&gt;. I should be able
  220. to just overwrite &lt;code&gt;fstab&lt;/code&gt; with the output of &lt;code&gt;head&lt;/code&gt;. Please do NOT copy or
  221. execute the following command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# head /etc/fstab &amp;gt; /etc/fstab&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I wish I had read the irc chat before I had executed the above command. In the
  222. words of a wise sage, “the redirection happens before head runs, so you’ll just
  223. get a blank file.” And that is exactly what happened. &lt;code&gt;/etc/fstab&lt;/code&gt; was empty.
  224. Now how do I mount filesystem partitions in the correct locations? “Out of the
  225. frying pan and into the fire.”&lt;/p&gt;&lt;p&gt;Some of the people on irc mentioned that &lt;code&gt;/var/backups&lt;/code&gt; should have a copy of my
  226. &lt;code&gt;fstab&lt;/code&gt;. Unfortunately, that backup command had not run yet. This was a fresh
  227. OpenBSD install afterall.&lt;/p&gt;&lt;p&gt;One of the people on the OpenBSD chat showed me this &lt;a href=&quot;https://github.com/openbsd/src/blob/master/sbin/disklabel/editor.c#L91&quot;&gt;link&lt;/a&gt;, which was super
  228. helpful, because it shows you the default size of the various partitions that
  229. the auto installer sets up. With that information, I was able to re-mount all my various
  230. partitions. Then someone on irc chat gave me this beauty of a command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount | awk '{ print $1 &amp;quot; &amp;quot; $3 &amp;quot; &amp;quot; $5 &amp;quot; rw 0 0&amp;quot;}' &amp;gt; /etc/fstab&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That created my &lt;code&gt;fstab&lt;/code&gt; for me! Let’s check it out!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# cat /etc/fstab
  231. sd1.a / ffs rw 1 1
  232. sd1.k /home ffs rw 1 2
  233. sd1.d /tmp ffs rw 1 2
  234. sd1.f /usr ffs rw 1 2
  235. sd1.g /usr/X11R6 ffs rw 1 2
  236. sd1.h /usr/local ffs rw 1 2
  237. sd1.j /usr/obj ffs rw 1 2
  238. sd1.i /usr/src ffs rw 1 2
  239. sd1.e /var ffs rw 1 2
  240. sd1.b none swap sw&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, well the mount options are absent, and it is NOT using UIDs…But this
  241. should be enough to boot into a complete system. So I rebooted. Upon reboot, I
  242. was able to change the mount points to UIDs and copy the proper mount options
  243. from my desktop OpenBSD. I then very quickly set up &lt;a href=&quot;https://man.openbsd.org/hotplugd&quot;&gt;hotplugd&lt;/a&gt;, which I will
  244. explain next time. Until then!&lt;/p&gt;</summary></entry><entry><title>Libreboot Full Disk encryption on OpenBSD</title><id>https://gnucode.me/libreboot-full-disk-encryption-on-openbsd.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-03-30T23:00:00Z</updated><link href="https://gnucode.me/libreboot-full-disk-encryption-on-openbsd.html" rel="alternate" /><summary type="html">&lt;p&gt;So I previously talked about my &lt;a href=&quot;http://gnucode.me/installing-openbsd-on-a-vm.html&quot;&gt;interest&lt;/a&gt; &lt;a href=&quot;http://gnucode.me/dual-booting-openbsd-guix-system.html&quot;&gt;in OpenBSD&lt;/a&gt;. Well last week, I
  245. have been more and more impressed with OpenBSD, especially after watching
  246. &lt;a href=&quot;https://undeadly.org/cgi?action=article;sid=20230325163416&quot;&gt;Theo’s recent talk&lt;/a&gt;. I recently installed OpenBSD on my desktop, and I was
  247. satisfied. There are some things that I knew how to do on GNU Guix that I do not
  248. yet know how to do on OpenBSD. For example, there is a minor issue with the
  249. sound being a bit wonky but that is not a deal breaker.&lt;/p&gt;&lt;p&gt;A few days ago I switched to OpenBSD on my laptop. So now, with the exception of
  250. my PinePhone, all of my computing devices are using OpenBSD. The OpenBSD
  251. installer is getting support for autoencrypting your hard drive, but I wanted to
  252. document the manual set up process if I ever decide to set up a RAID+ecryption.
  253. I do not believe the installer will support RAID+encryption anytime soon.&lt;/p&gt;&lt;p&gt;The real problem was trying to get libreboot to even recognize the OpenBSD usb
  254. installer stick. The best method to boot OpenBSD on libreboot is to use the
  255. seaBIOS payload. I could NOT get this to work. I must have booted and rebooted
  256. 10+ times trying to get this to work. I even opened up a grub command line
  257. prompt, and it could not SEE the usb stick. &lt;a href=&quot;https://misc.openbsd.narkive.com/auaZDqBe/bsd-rd-fails-to-boot-up-on-libreboot-x200-how-to-find-out-why&quot;&gt;Others have reported this problem.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In grub you can get a feel for what partitions are available via:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; ls
  258. (hd0) (hd0,msdos1)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This seems to only show my GNU/Linux Guix System partition. That’s not a good
  259. sign. There is another way to check. I can type out the following
  260. &lt;code&gt;set root=(hd0,msdos1)/&lt;/code&gt;&lt;/p&gt;&lt;p&gt;and then press TAB:&lt;/p&gt;&lt;p&gt;I was able to see &lt;code&gt;/bin&lt;/code&gt;, &lt;code&gt;/boot&lt;/code&gt;, &lt;code&gt;/etc&lt;/code&gt;, etc. Going into &lt;code&gt;/var&lt;/code&gt;, I saw
  261. &lt;code&gt;guix/&lt;/code&gt;. So clearly &lt;code&gt;hd0&lt;/code&gt; is my current SSD that has GNU/Linux Guix System. And
  262. grub and libreboot did NOT see the OpenBSD usb stick. I kept rebooting, tried
  263. searching for the OpenBSD stick, and finally the grub console showed me
  264. something other than &lt;code&gt;(hd0,msdos1)&lt;/code&gt;. I think I have to use the right-most usb
  265. port. I think that is the secret.&lt;/p&gt;&lt;p&gt;Technically, &lt;a href=&quot;https://notabug.org/swiftgeek/libreboot/src/master/docs/bsd/openbsd.md&quot;&gt;grub can boot
  266. OpenBSD&lt;/a&gt;,
  267. at least grub as packaged by Libreboot, but that is NOT advisable. And grub's
  268. ability to boot OpenBSD may disappear at any moment. Seeing no other option, I
  269. typed in this command to boot OpenBSD via grub:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; kopenbsd (usb0)/7.2/amd64/bsd.rd
  270. grub&amp;gt; boot&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And OpenBSD started booting! Woo hoo! At the OpenBSD installer I typed in “s”
  271. to exit to the shell so that I could set up full disc encryption.&lt;/p&gt;&lt;p&gt;Before we get to the disc encryption, let me give a quick overview of how
  272. OpenBSD sets up partitions. OpenBSD supports both MBR and GPT partitions, which
  273. divide the physical disc into sections (MBR is old; GPT is the modern way to do
  274. it, and most people will want GPT on newer machines so for the rest of this blog
  275. post I will just talk about GPT). All operating systems recognize and use GPT
  276. partitions. Linux will install its filesystem partitions into seperate GPT
  277. partitions, which means that a &amp;quot;partition&amp;quot; in Linux means the GPT
  278. partition and the filesystem partion. Here's a handy graphic:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;|--------------+------------+----------------|
  279. | | Linux | |
  280. |--------------+------------+----------------|
  281. | GPT partiton | filesystem | mount location |
  282. | | partition | |
  283. |--------------+------------+----------------|
  284. | /dev/sda1 | ext4 | / |
  285. | /dev/sda2 | btrfs | /etc |
  286. | /dev/sda3 | xfs | /boot |
  287. | ... | ... | ... |
  288. | /dev/sda128 | vfat | /boot/efi |
  289. | | | |
  290. | /dev/sdb1 | ext4 | /data |
  291. |--------------+------------+----------------|&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OpenBSD is a little different. It uses one big GPT partition, and then it
  292. further splits up that one big GPT partition into filesystem partitions, which
  293. can be examined via &lt;a href=&quot;https://man.openbsd.org/disklabel&quot;&gt;disklabel&lt;/a&gt;. So in
  294. OpenBSD &lt;code&gt;sd0&lt;/code&gt; and &lt;code&gt;sd1&lt;/code&gt; refer to the first and second hard drive. &lt;code&gt;/dev/sd0c&lt;/code&gt;
  295. refers to the one big GPT partition and &lt;code&gt;/dev/sd0a&lt;/code&gt; by convention is the &lt;code&gt;/&lt;/code&gt;
  296. partition. &lt;code&gt;/dev/sd0b&lt;/code&gt; is swap by convention and &lt;code&gt;d&lt;/code&gt; through &lt;code&gt;p&lt;/code&gt; could refor to
  297. any other arbitrary mount point. So &amp;quot;partition&amp;quot; in OpenBSD may refer to the GPT
  298. partion or the filesystem partitions.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;|--------------+-------------+----------------|
  299. | | OpenBSD | |
  300. |--------------+-------------+----------------|
  301. | GPT partiton | filesystem | mount location |
  302. | | partition | |
  303. | | (FFS) | |
  304. |--------------+-------------+----------------|
  305. | /dev/sd01 | /dev/sd0a | / |
  306. | /dev/sd01 | /dev/sd0b | swap |
  307. | /dev/sd01 | /dev/sd0c | not mounted |
  308. | /dev/sd01 | /dev/sd0d | /home |
  309. | | ... | |
  310. | /dev/sd01 | /dev/sd0e | /tmp |
  311. | | | |
  312. | /dev/sd11 | /dev/sd1i | /data |
  313. |--------------+-------------+----------------|&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I would highly recommend the OpenBSD
  314. &lt;a href=&quot;https://www.openbsd.org/faq/faq14.html#intro&quot;&gt;faq&lt;/a&gt; page about this (as well as
  315. the disklabel man page), which will also act as a more official version of this
  316. blog post. Now on with the blog post!&lt;/p&gt;&lt;p&gt;Let’s figure out which drive is my usb stick, and which drive is my SSD with
  317. Guix on it. Please note that I did not write the output of this command down.
  318. Your output might look different.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sysctl hw.disknames
  319. hw.disknames=sd0:ec557d42f5cbfa41,sd1:&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I typed in the next two commands to try to get a feel for which drive was my
  320. SSD.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;doas disklabel sd0
  321. doas disklabel sd1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I forget what the above commands output-ed, but looking at the output I was able
  322. to determine that &lt;code&gt;sd0&lt;/code&gt; was my GNU/Linux Guix System. Now it was time to set up a
  323. &lt;a href=&quot;https://www.openbsd.org/faq/faq14.html#softraidFDE&quot;&gt;full disc encryption&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /dev &amp;amp;&amp;amp; sh MAKEDEV sd0
  324. dd if=/dev/urandom of=/dev/rsd0c bs=1m&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That second command took 8+ hours to complete. It wrote random data on the
  325. whole SSD. That way, if an attacker ever stole my hard drive, when they
  326. examined my hard drive, they would not see:&lt;/p&gt;&lt;p&gt;00000000EncryptedData0000000EncryptedData000000&lt;/p&gt;&lt;p&gt;Instead they would see&lt;/p&gt;&lt;p&gt;RandomDataRandomDataRandomDataRandomDataRandomDataRandomData&lt;/p&gt;&lt;p&gt;where only the 2nd and 5th =RandomData= are actually my encrypted files. Trying
  327. to figure what is data and what is just random ones and zeros would be really
  328. hard. However, I should probably ask on &lt;code&gt;#openbsd&lt;/code&gt; irc to make sure that I
  329. wrote the right command. Is there a way to search your raw hard drive for a
  330. section of disc that is just 10,000 zeros?&lt;/p&gt;&lt;p&gt;Anway, let’s partition the &lt;code&gt;sd0&lt;/code&gt; drive and format it as a RAID. Random encrypted
  331. data will go to &lt;code&gt;sd0&lt;/code&gt;. OpenBSD will read files from the unencrypted &lt;code&gt;sd1&lt;/code&gt;,
  332. which will be encrypted and stored on &lt;code&gt;sd0&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;fdisk -iy sd0
  333. sd0&amp;gt; *a* *a*
  334. sd0&amp;gt;size: [ ... ] ***
  335. sd0&amp;gt; FS type: *RAID*
  336. sd0&amp;gt; *w*
  337. sd0&amp;gt; *q*&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This next command will ask you for a passphrase. If you use an alternative
  338. keyboard layout, then make your command use numbers and special characters on
  339. the 1-9 section. That way you can still type in the secret password on boot,
  340. because OpenBSD changes your keyboard layout after you unlock your encrypted
  341. volumes.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;bioctl -c C -l sd0a softraid0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s set up &lt;code&gt;sd1&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /dev &amp;amp;&amp;amp; sh MAKEDEV sd1
  342. dd if=/dev/zero of=/dev/rsd1c bs=1m count=1
  343. exit&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will return us to the main installer. When the installer asks you which
  344. hard drive to install OpenBSD on, I said &lt;code&gt;sd1&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;[...]
  345. Available disks are: sd0 sd1.
  346. Which disk is the root disk? ('?' for details) [sd0] *sd1*&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And that was that! I did a few things to set up &lt;code&gt;XFCE&lt;/code&gt;, which I quickly
  347. abandoned in favor of i3, and I was off to the races. Then I realized that my
  348. full-disk decryption passphrase was pretty weak. Basically, because I use a
  349. physical &lt;a href=&quot;https://en.wikipedia.org/wiki/Dvorak_keyboard_layout&quot;&gt;dvorak keyboard
  350. layout&lt;/a&gt;, and OpenBSD uses
  351. the standard &lt;a href=&quot;https://en.wikipedia.org/wiki/QWERTY&quot;&gt;qwerty&lt;/a&gt; layout when you type
  352. in the password to decrypt the disk, my initial full disk encryption password
  353. was just numbers. Now, I wanted to change it to my normal password.&lt;/p&gt;&lt;p&gt;Apparently you can do so while the encrypted volume &lt;a href=&quot;https://dev.to/nabbisen/openbsd-disk-encryption-change-passphrase-4i8l&quot;&gt;is
  354. mounted&lt;/a&gt;!
  355. I made sure that I changed the keyboard layout to the standard qwerty, when I typed in
  356. the new passphase.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; doas bioctl -P sd1 # I was using the dvorak layout here&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In another terminal I typed in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; setxkbmap -layout us&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then I moved to the terminal that was asking me to change the full disk
  357. encryption password.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; Old Passphrase: # I typed in the numbers
  358. New Passphrase: # I typed in an awesome password
  359. Confirm Passphrase: # I typed it in again.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's get back to dvorak:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; setxkbmap -layout dvorak&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That's better. I did have a great time the next day. I was hoping to
  360. automatically automount my usb stick on boot. So I added this beauty to my
  361. &lt;code&gt;/etc/fstab&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;sd2i /mnt/usb msdos rw 1 2&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The next time I booted it threw me into a rescue shell with only &lt;code&gt;/&lt;/code&gt; mounted.
  362. That was a wild ride to fix, bit I will explain how I fixed that next time!&lt;/p&gt;</summary></entry><entry><title>Installing Fedora on Power9</title><id>https://gnucode.me/installing-fedora-on-power9.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-03-06T13:30:00Z</updated><link href="https://gnucode.me/installing-fedora-on-power9.html" rel="alternate" /><summary type="html">&lt;p&gt;My friend has a &lt;a href=&quot;https://www.raptorcs.com/TALOSII/&quot;&gt;TalosII&lt;/a&gt; machine. He currently uses void linux, but void has
  363. dropped their &lt;a href=&quot;https://en.wikipedia.org/wiki/Power_ISA&quot;&gt;Power ISA&lt;/a&gt; support. So I convinced him to give Debian Gnu/Linux a
  364. try. First we downloaded the &lt;a href=&quot;https://www.debian.org/&quot;&gt;debian&lt;/a&gt; image:&lt;/p&gt;&lt;p&gt;We navigated our way around the website to download a &lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/&quot;&gt;complete debian DVD image&lt;/a&gt;,
  365. which was about 5 GB. We then tried to figure out how to &lt;a href=&quot;https://www.debian.org/CD/verify&quot;&gt;verify the installer
  366. image&lt;/a&gt;, which basically means, to check that the file we downloaded was not
  367. malware.&lt;/p&gt;&lt;p&gt;Well let’s first import the debian GPG keys:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
  368. &amp;quot;1046 0DAD 7616 5AD8 1FBC 0CE9 9880 21A9 64E6 EA7D&amp;quot;
  369. gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
  370. &amp;quot;DF9B 9C49 EAA9 2984 3258 9D76 DA87 E80D 6294 BE9B&amp;quot;
  371. gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
  372. &amp;quot;F41D 3034 2F35 4669 5F65 C669 4246 8F40 09EA 8AC3&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s double check that we have those signing keys:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --list-keys | grep debian
  373. uid [ unknown] Debian CD signing key &amp;lt;debian-cd@lists.debian.org&amp;gt;
  374. uid [ unknown] Debian CD signing key &amp;lt;debian-cd@lists.debian.org&amp;gt;
  375. uid [ unknown] Debian Testing CDs Automatic Signing Key &amp;lt;debian-cd@lists.debian.org&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sweet. Now what? How do we actually and practically, via what commands,
  376. verify the installer images? Well the debian page is not specific about
  377. what to do next. So I had to searching the internet for how to verify debian
  378. images. And I found this awesome &lt;a href=&quot;https://danilodellaquila.com/en/blog/how-to-verify-authenticity-of-downloaded-debian-iso-images&quot;&gt;blog post&lt;/a&gt;. Here’s how we do it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;wget https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/SHA512SUMS
  379. wget https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/SHA512SUMS.sign
  380. gpg --verify SHA512SUMS.sign
  381. gpg --verify SHA512SUMS.sign SHA512SUMS
  382. sha512sum -c SHA512SUMS 2&amp;gt;/dev/null | grep debian-11.6.0-ppc64el-netinst.iso
  383. debian-11.6.0-ppc64el-netinst.iso: OK&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We then tried to boot the usb debian power image. That failed to boot. Then we
  384. tried burning that image to a DVD. That did not work.&lt;/p&gt;&lt;p&gt;So I am guessing that Debian GNU/Linux will work on power, BUT the graphical
  385. installer does not currently work on Debian (I found out later that the Debian
  386. ncuruses installer does work on power).&lt;/p&gt;&lt;p&gt;My friend then installed Ubuntu server. Ubuntu server's installer actually
  387. worked! Then we just turned Ubuntu server into a Xubuntu like environment via
  388. command like: &lt;code&gt;sudo apt install xfce -y&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Then we rebooted and everything worked! Well, &lt;code&gt;Gnome&lt;/code&gt; did not. And &lt;code&gt;Xubuntu&lt;/code&gt; did
  389. not, but then we used &lt;code&gt;gdm&lt;/code&gt; to log into &lt;code&gt;xfce&lt;/code&gt; desktop. That worked flawlessly.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;netsurf&lt;/code&gt; web browser also worked really well! Which meant we could use any
  390. website that had virtually no javascript.&lt;/p&gt;&lt;p&gt;Then I thought, it would be great to have a modern web browser working on my
  391. friend’s desktop...&lt;/p&gt;&lt;p&gt;Well it looks like Firefox can run on Power9!&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.talospace.com/search/label/Firefox&quot;&gt;https://www.talospace.com/search/label/Firefox&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The latest blog post says that you can run Firefox version 110 on
  392. Power9. You can either add in a &lt;code&gt;--disable-webrtc&lt;/code&gt; in your
  393. &lt;code&gt;.mozconfig&lt;/code&gt; or you can compile Firefox with a tiny patch.&lt;/p&gt;&lt;p&gt;AND nonguix has a recipe for building Firefox. Let’s see if I can
  394. just install &lt;code&gt;guix&lt;/code&gt; set up the &lt;code&gt;nonguix channel&lt;/code&gt; and build Firefox that way!&lt;/p&gt;&lt;p&gt;If the nonguix packaged Firefox doesn’t work, then I can try to set
  395. build firefox from source via this video:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Hx42tyEWPxk&quot;&gt;https://www.youtube.com/watch?v=Hx42tyEWPxk&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Devaun was also a possiblity. That is a fork of debian that does not use
  396. &lt;code&gt;systemd&lt;/code&gt;. My friend is not a big fan of systemd.&lt;/p&gt;&lt;p&gt;I was also told that Fedora is probably the easiest linux distribution, in which
  397. to run GNU/Linux on Power9.&lt;/p&gt;&lt;p&gt;Well installing Fedora was actually easy. The installer just worked.
  398. (Apparently Debian GNU/Linux disables the ast driver by default, which means a
  399. VGA display will not work). And I have a working Firefox. Apparently I can run
  400. a slightly older version of firefox that has a &lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/sharkcz/talos/&quot;&gt;working javascript JIT.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;My friend now has a working Xfce desktop courtesy from &lt;a href=&quot;https://getfedora.org/&quot;&gt;Fedora GNU/Linux&lt;/a&gt;. My only
  401. concern is that this &lt;a href=&quot;https://www.talospace.com/2022/12/fedora-37-mini-review-on-blackbird-and.html&quot;&gt;blog post&lt;/a&gt; seems to suggest that updating Fedora on a Power9
  402. machine is going to be quite annoying. I would not want to have to re-install
  403. Fedora every time they upgrade. I personally no longer have any issues upgrading
  404. my laptop to my distro latest release, because I have found that GNU Guix System
  405. just works really well. And if an upgrade breaks, then I can always roll back
  406. to the previous known working system during the boot process.&lt;/p&gt;&lt;p&gt;It looks like Fedora can support something like this:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://sysguides.com/install-fedora-36-with-snapper-and-grub-btrfs/&quot;&gt;https://sysguides.com/install-fedora-36-with-snapper-and-grub-btrfs/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Maybe it is already enabled by default. Who knows.&lt;/p&gt;&lt;p&gt;I would personally love to recommend my friend to use GNU Guix System, but
  407. currently you cannot boot Guix System from Power9. The next step for me in this
  408. journey to help my friend set up his TalosII is to make sure his AMDGPU works.
  409. This &lt;a href=&quot;https://wiki.raptorcs.com/wiki/Troubleshooting/GPU,&quot;&gt;wiki article&lt;/a&gt; should help with that.&lt;/p&gt;&lt;p&gt;Also from the &lt;code&gt;#talos-workstation&lt;/code&gt; chat log on irc, I found out that the Linux
  410. kernel is having some issues with the graphics drivers on Power9. Currently the
  411. user is required to do some manual fiddling. However those workarounds should
  412. not be necessary by kernel 6.3ish. So until my friend runs Linux 6.3, he will
  413. probably have the best desktop experience in Xfce or KDE. Gnome has some minor
  414. issues apparently.&lt;/p&gt;</summary></entry><entry><title>Creating New Build Systems</title><id>https://gnucode.me/creating-new-build-systems.html</id><author><name>Mitchell Schmeisser &lt;mitchellschmeisser@librem.one&gt;</name><email>jbranso@dismail.de</email></author><updated>2023-02-24T12:00:00Z</updated><link href="https://gnucode.me/creating-new-build-systems.html" rel="alternate" /><summary type="html">&lt;p&gt;In Guix each package must specify a so-called &lt;code&gt;build-system&lt;/code&gt;, which
  415. knows how to bring a package from its inputs to deployment.
  416. Build systems are responsible for setting up the environment and performing
  417. build actions within that environment. The most ubiquitous of these is the
  418. &lt;a href=&quot;https://www.gnu.org/software/automake/manual/html_node/GNU-Build-System.html&quot;&gt;&lt;code&gt;gnu-build-system&lt;/code&gt;&lt;/a&gt;.
  419. Guix builds packages using this build system via the usual
  420. &lt;code&gt;./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make install&lt;/code&gt; process.&lt;/p&gt;&lt;p&gt;Any package can alter its build system by removing some steps or
  421. adding extra ones. This is extremely common and almost every package
  422. makes some adjustment to the build process. A &lt;code&gt;build-system&lt;/code&gt; in Guix
  423. hides away some of the common configuration choices. For example, there is
  424. no need to specify &lt;code&gt;make&lt;/code&gt; or &lt;code&gt;gcc&lt;/code&gt; as native inputs when using the &lt;code&gt;gnu-build-system&lt;/code&gt;,
  425. because they are added implicitly when a package is lowered into a &lt;em&gt;bag&lt;/em&gt;.&lt;/p&gt;&lt;h2&gt;Anatomy of a Guix Build System&lt;/h2&gt;&lt;p&gt;The job of a build system is to compile our &lt;em&gt;packages&lt;/em&gt; into &lt;em&gt;bags&lt;/em&gt;.
  426. Bags are a lower level representation of a package without all the bells and whistles
  427. (Makes sense since we are implementing them here),
  428. the bags are further refined to derivations which are used by the
  429. build daemon to create an isolated environment suitable for our
  430. &lt;em&gt;build phases&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Below is how guix defines a build system.
  431. It's surprisingly simple with just three items, two of which are for human consumption.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-record-type* &amp;lt;build-system&amp;gt; build-system make-build-system
  432. build-system?
  433. (name build-system-name) ; symbol
  434. (description build-system-description) ; short description
  435. (lower build-system-lower)) ; args ... -&amp;gt; bags&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The last field &lt;code&gt;lower&lt;/code&gt; is a function which takes the list of arguments
  436. given in the &lt;code&gt;(package ... (arguments ...))&lt;/code&gt; field.
  437. The keyword arguments that we are allowed to supply when writing the
  438. package are defined by the build-system.&lt;/p&gt;&lt;h1&gt;Code Strata&lt;/h1&gt;&lt;p&gt;Guix builds are implemented in two parts.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Code that compiles &lt;code&gt;packages-&amp;gt;derivations&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Derivations are the language the Guix Daemon speaks.
  439. They describe everything about how to &lt;em&gt;derive&lt;/em&gt; our package
  440. from the inputs to the environment and all the code on how to drive
  441. the build tools.
  442. This code is run in a poorly defined &amp;quot;user&amp;quot; environment.
  443. Guix produces derivations that actually can be influenced by
  444. undeclared aspects of the environment, like manually installed Guile
  445. packages or code added with the `-L` flag.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The guix daemon runs the builder code in as isolated and reproducible build environment to produce the package from its inputs.&lt;/p&gt;&lt;p&gt;This code is executed in an explicitly defined build environment
  446. with nothing being introduced from the host.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Code that runs in the host environment &lt;em&gt;stages&lt;/em&gt; code, which will run in isolation.
  447. This is where G-Expressions really shine.
  448. They provide the syntax to describe this relationship.&lt;/p&gt;&lt;h1&gt;Build Phases&lt;/h1&gt;&lt;p&gt;All programs are built more or less the same way.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Unpack the source code.&lt;/p&gt;&lt;p&gt;Whether it's tarball or a version controlled repository, the guix daemon must
  449. copy the software's source tree into our build environment.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Patch the shebangs.&lt;/p&gt;&lt;p&gt;Many projects contain scripts written to aid the build process.
  450. In Linux, executable scripts can contain a so-called &lt;em&gt;shebang&lt;/em&gt;,
  451. which contains an absolute path to the program, which is meant to
  452. interpret it: e.g. &lt;code&gt;#!/bin/sh&lt;/code&gt;. Most distributions provide a
  453. POSIX compliant shell interpreter at this location. Guix System does not do this.
  454. Instead, Guix System's &lt;code&gt;sh&lt;/code&gt; is yet another component in the store, so all of these files must
  455. be patched to point to the new location, which is only known at
  456. build time. We cannot rely on our &lt;code&gt;PATH&lt;/code&gt; to store this information,
  457. because the Linux kernel does not respect such things.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configure the build.&lt;/p&gt;&lt;p&gt;Whether it is autotools or CMake or ninja, etc., if you are relying
  458. on tools from the host system, then you have a step, which enables the
  459. host system to tell you where to find those tools.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Patch the generated shebangs.&lt;/p&gt;&lt;p&gt;Sometimes the configure phases creates scripts, which run during the build phase,
  460. these often contain references to &lt;code&gt;/bin/sh&lt;/code&gt;, and so guix must patch these scripts as well.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Build!&lt;/p&gt;&lt;p&gt;That's right folks we are off to the races, and the program is building.
  461. Usually this takes the form of a call to &lt;code&gt;make&lt;/code&gt;, with a handful of
  462. flags and last minute definitions, but there are other more &lt;em&gt;exotic&lt;/em&gt; methods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Test.&lt;/p&gt;&lt;p&gt;Now that guix built our software, we should test it before we sent software
  463. updates to users. This helps the guix project catch and eleminate software
  464. bugs before they impact guix users. Not all packages have tests, and guix
  465. developers occasionally disables some packages' testsuites, but the
  466. guix policy is to run the software's testsuite, if it is exists.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Install.&lt;/p&gt;&lt;p&gt;Now that we've verified everything works as expected, it is time to run
  467. &lt;code&gt;make install&lt;/code&gt; or the equivalent. This phase copies our build artifacts into
  468. their final resting place in the store.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Validate the Installation.&lt;/p&gt;&lt;p&gt;Here guix checks that our outputs do not contain any component paths, which
  469. are not specified by the package inputs. That would lead to incomplete
  470. deployment, harm &lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;reproducible builds&lt;/a&gt;,
  471. and would be &amp;quot;bad&amp;quot;.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;There are more steps, but they are not universally applicable.
  472. Of course no generic model, such as this, captures all the chaos of the
  473. world, and every package has exceptions to it.&lt;/p&gt;&lt;p&gt;Guix implements &lt;em&gt;build phases&lt;/em&gt; as a list of lambdas.
  474. As such our package can modify this list and add/delete/replace
  475. lambdas as they require. It is so common Guix provides a syntax
  476. for manipulating build phases: &lt;code&gt;modify-phases&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;A build system contains a default set of phases called &lt;code&gt;%standard-phases&lt;/code&gt;.
  477. Every build system starts with the &lt;code&gt;gnu-build-system&lt;/code&gt;, &lt;code&gt;%standard-phases&lt;/code&gt;,
  478. and modifies it to their needs.
  479. It is then provided to the packages using that build system.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;cmake-build-system&lt;/code&gt; is nearly identical to the &lt;code&gt;gnu-build-system&lt;/code&gt;
  480. except two phases.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;;
  481. ;; Excerpt from `guix/build/cmake-build-system.scm`
  482. ;;
  483. (define %standard-phases
  484. ;; Everything is the same as the GNU Build System, except for the `configure'
  485. ;; and 'check' phases.
  486. (modify-phases gnu:%standard-phases
  487. (delete 'bootstrap)
  488. (replace 'check check)
  489. (replace 'configure configure)))&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;The Zephyr Build System&lt;/h2&gt;&lt;p&gt;Zephyr uses &lt;code&gt;cmake&lt;/code&gt; to perform &lt;em&gt;physical component composition&lt;/em&gt;.
  490. It searches the filesystem and generates scripts, which the toolchain will
  491. use to successfully combine those components into a firmware image.&lt;/p&gt;&lt;p&gt;The fact that Zephyr provides this mechanism is one reason I chose to
  492. target zephyr in the first place.&lt;/p&gt;&lt;p&gt;This separation of projects in an embedded context is a really great thing.
  493. It brings many of the advantages to the Linux world such as
  494. code re-use, smaller binaries, more efficient cache/RAM usage, etc.
  495. It also allows us to work as independent groups and compose
  496. contributions from many teams.&lt;/p&gt;&lt;p&gt;It also brings all of the complexity. Suddenly all of the problems
  497. that plague traditional deployment now apply to our embedded
  498. system. The fact that the libraries are statically linked at compile
  499. time instead of dynamically at runtime is simply an implementation detail.&lt;/p&gt;&lt;p&gt;We now have dependencies which we must track and compose in the correct environments.
  500. The Zephyr Project offers a tool to help manage this new complexity: &lt;a href=&quot;https://docs.zephyrproject.org/latest/develop/west/index.html&quot;&gt;The West Meta-tool&lt;/a&gt;!
  501. To call it a &amp;quot;meta-tool&amp;quot; is an abuse of language. It is not even meta
  502. enough to bootstrap itself and relies on &lt;a href=&quot;https://docs.zephyrproject.org/latest/develop/getting_started/index.html&quot;&gt;other package managers&lt;/a&gt; to get
  503. started.
  504. In fact, it is not even suitable for managing multiple embedded projects as a composition!
  505. The project recommends &lt;a href=&quot;https://docs.zephyrproject.org/latest/build/sysbuild/index.html&quot;&gt;Yet Another Tool&lt;/a&gt; for this very common use case.&lt;/p&gt;&lt;p&gt;In fact, West does not really bring anything new to the table, and we can
  506. replace it in the same way we can replace every other language specific package
  507. manager, like node (js), Cabol (haskell), Dub (D), etc. &lt;strong&gt;PUTTING SOFTWARE ON
  508. THE SYSTEM IS THE JOB OF THE PACKAGE MANAGER!&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;West is the way it is for a reason. It is very practical to design the package
  509. manager in this way, because it enables Windows users to access the build
  510. environment. A more in-depth discussion on the material conditions, which lead
  511. to this or that design decision of the West tool is beyond the scope of this
  512. post. Let's instead explain how to provide a meta-tool and bootstrap complex
  513. embedded systems, from the ground up, in a flexible, composable, and
  514. &lt;em&gt;reproducible&lt;/em&gt; way.&lt;/p&gt;&lt;h1&gt;Why not use &lt;code&gt;cmake-build-system&lt;/code&gt;?&lt;/h1&gt;&lt;p&gt;A fair question! Zephyr's CMake scripts require additional information
  515. about the build to be provided at configure time. Most tedius for
  516. zephyr-packages is the &lt;code&gt;ZEPHYR_MODULES&lt;/code&gt; variable, which must be formatted and
  517. passed to CMake on the command line.&lt;/p&gt;&lt;h1&gt;Host Side&lt;/h1&gt;&lt;p&gt;Our job at this level is to take packages described using the &lt;code&gt;package&lt;/code&gt; syntax and
  518. lower it into a derivation that the guix-daemon can understand.&lt;/p&gt;&lt;p&gt;Here is the derivation for building hello world for the &lt;code&gt;frdm_k64f&lt;/code&gt; (hashes removed for brevity).
  519. The &lt;code&gt;package&lt;/code&gt; syntax provides a human friendly veneer over this garbage.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;Derive
  520. ([(&amp;quot;debug&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--debug&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)
  521. ,(&amp;quot;out&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr-&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)]
  522. ,[(&amp;quot;/gnu/store/...-newlib-nano-3.3.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  523. ,(&amp;quot;/gnu/store/...-hal-nxp-3.1.0-0.708c958.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  524. ,(&amp;quot;/gnu/store/...-make-4.3.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  525. ,(&amp;quot;/gnu/store/...-findutils-4.8.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  526. ,(&amp;quot;/gnu/store/...-grep-3.6.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  527. ,(&amp;quot;/gnu/store/...-sed-4.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  528. ,(&amp;quot;/gnu/store/...-ld-wrapper-0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  529. ,(&amp;quot;/gnu/store/...-bash-minimal-5.1.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  530. ,(&amp;quot;/gnu/store/...-hal-cmsis-5.8.0-0.093de61.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  531. ,(&amp;quot;/gnu/store/...-gawk-5.1.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  532. ,(&amp;quot;/gnu/store/...-gzip-1.10.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  533. ,(&amp;quot;/gnu/store/...-python-six-1.16.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  534. ,(&amp;quot;/gnu/store/...-zephyr-3.1.0-0.zephyr--checkout.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  535. ,(&amp;quot;/gnu/store/...-linux-libre-headers-5.10.35.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  536. ,(&amp;quot;/gnu/store/...-python-3.9.9.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  537. ,(&amp;quot;/gnu/store/...-diffutils-3.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  538. ,(&amp;quot;/gnu/store/...-arm-zephyr-eabi-nano-toolchain-12.1.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  539. ,(&amp;quot;/gnu/store/...-python-pyelftools-0.28.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  540. ,(&amp;quot;/gnu/store/...-guile-3.0.7.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  541. ,(&amp;quot;/gnu/store/...-python-dateutil-2.8.2.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  542. ,(&amp;quot;/gnu/store/...-patch-2.7.6.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  543. ,(&amp;quot;/gnu/store/...-gcc-10.3.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  544. ,(&amp;quot;/gnu/store/...-bzip2-1.0.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  545. ,(&amp;quot;/gnu/store/...-dtc-1.6.1.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  546. ,(&amp;quot;/gnu/store/...-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  547. ,(&amp;quot;/gnu/store/...-cmake-minimal-3.21.4.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  548. ,(&amp;quot;/gnu/store/...-python-pyyaml-6.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  549. ,(&amp;quot;/gnu/store/...-python-packaging-21.3.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  550. ,(&amp;quot;/gnu/store/...-arm-zephyr-eabi-binutils-2.38.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  551. ,(&amp;quot;/gnu/store/...-glibc-2.33.drv&amp;quot;,[&amp;quot;out&amp;quot;,&amp;quot;static&amp;quot;])
  552. ,(&amp;quot;/gnu/store/...-qemu-7.2.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  553. ,(&amp;quot;/gnu/store/...-ninja-1.10.2.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  554. ,(&amp;quot;/gnu/store/...-tar-1.34.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  555. ,(&amp;quot;/gnu/store/...-xz-5.2.5.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  556. ,(&amp;quot;/gnu/store/...-binutils-2.37.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  557. ,(&amp;quot;/gnu/store/...-python-pykwalify-1.7.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  558. ,(&amp;quot;/gnu/store/...-zephyr-3.1.0-0.zephyr-.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  559. ,(&amp;quot;/gnu/store/...-glibc-utf8-locales-2.33.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  560. ,(&amp;quot;/gnu/store/...-gdb-arm-zephyr-eabi-12.1.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  561. ,(&amp;quot;/gnu/store/...-module-import-compiled.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  562. ,(&amp;quot;/gnu/store/...-file-5.39.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  563. ,(&amp;quot;/gnu/store/...-python-pyparsing-3.0.6.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  564. ,(&amp;quot;/gnu/store/...-python-docopt-0.6.2.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  565. ,(&amp;quot;/gnu/store/...-arm-zephyr-eabi-sdk-0.15.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
  566. ,(&amp;quot;/gnu/store/...-coreutils-8.32.drv&amp;quot;,[&amp;quot;out&amp;quot;])]
  567. ,[&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--builder&amp;quot;,&amp;quot;/gnu/store/...-module-import&amp;quot;]
  568. ,&amp;quot;x86_64-linux&amp;quot;,&amp;quot;/gnu/store/...-guile-3.0.7/bin/guile&amp;quot;,[&amp;quot;--no-auto-compile&amp;quot;
  569. ,&amp;quot;-L&amp;quot;,&amp;quot;/gnu/store/...-module-import&amp;quot;
  570. ,&amp;quot;-C&amp;quot;,&amp;quot;/gnu/store/...-module-import-compiled&amp;quot;
  571. ,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--builder&amp;quot;]
  572. ,[(&amp;quot;debug&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--debug&amp;quot;)
  573. ,(&amp;quot;out&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr-&amp;quot;)])&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Lowering packages to bags&lt;/h3&gt;&lt;p&gt;We must provide the build system with a function which the following lambda form.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(lambda* (name #:key #:allow-other-keys) ...)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This means it takes one required argument &lt;code&gt;name&lt;/code&gt; and any amount of keys.
  574. Individual procedures can specify keys they are interested in such as
  575. &lt;code&gt;inputs&lt;/code&gt; or &lt;code&gt;outputs&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Which keys are ultimately supported is defined by our &lt;code&gt;lower&lt;/code&gt; function
  576. and our &lt;em&gt;build phases&lt;/em&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;; Use module-ref instead of referencing the variables directly
  577. ;; to avoid circular dependencies.
  578. (define %zephyr-build-system-modules
  579. `((mfs build zephyr-build-system)
  580. ,@%cmake-build-system-modules))
  581. (define default-zephyr-base
  582. (module-ref (resolve-interface '(mfs packages zephyr))
  583. 'zephyr))
  584. (define default-zephyr-sdk
  585. (module-ref (resolve-interface '(mfs packages zephyr))
  586. 'arm-zephyr-eabi-sdk))
  587. (define default-ninja
  588. (module-ref (resolve-interface '(gnu packages ninja))
  589. 'ninja))
  590. (define default-cmake
  591. (module-ref (resolve-interface '(gnu packages cmake))
  592. 'cmake-minimal))
  593. (define* (lower name
  594. #:key source inputs native-inputs outputs system target
  595. (zephyr default-zephyr-base)
  596. (sdk default-zephyr-sdk)
  597. (ninja default-ninja)
  598. (cmake default-cmake)
  599. #:allow-other-keys
  600. #:rest arguments)
  601. &amp;quot;Return a bag for NAME.&amp;quot;
  602. (define private-keywords `(#:zephyr #:inputs #:native-inputs #:target))
  603. (bag
  604. (name name)
  605. (system system)
  606. (target target)
  607. (build-inputs `(,@(if source `((&amp;quot;source&amp;quot; ,source)) '())
  608. ,@`((&amp;quot;cmake&amp;quot; ,cmake))
  609. ,@`((&amp;quot;zephyr-sdk&amp;quot; ,sdk))
  610. ,@`((&amp;quot;zephyr&amp;quot; ,zephyr))
  611. ,@`((&amp;quot;ninja&amp;quot; ,ninja))
  612. ,@native-inputs
  613. ,@(standard-packages)))
  614. ;; Inputs need to be available at build time
  615. ;; since everything is statically linked.
  616. (host-inputs inputs)
  617. (outputs outputs)
  618. (build zephyr-build)
  619. (arguments (strip-keyword-arguments private-keywords arguments))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here our &lt;code&gt;lower&lt;/code&gt; function provides default values for the packages
  620. every zephyr package needs, the SDK, CMake, and &lt;code&gt;ZEPHYR_BASE&lt;/code&gt; and adds
  621. them to the build-inputs.&lt;/p&gt;&lt;p&gt;Notice we also strip out some keywords, which do not get passed to the
  622. build function, because they get included as part of the broader
  623. abstractions the build system provides.&lt;/p&gt;&lt;p&gt;At this step it would be great to have a parser which could work out
  624. the required sdk from a &lt;code&gt;.config,&lt;/code&gt; but this requires compiling the kconfig,
  625. which requires at least the sdk cmake files.
  626. There might be a way to make it happen, but until then if a board needs a different
  627. sdk, then they can specify it in an argument keyword.&lt;/p&gt;&lt;h3&gt;Lowering Bags to Derivations&lt;/h3&gt;&lt;p&gt;Here is the definition for the actual build procedure. There is a lot
  628. of abstract trickery going on here, so do not worry if you don't understand it,
  629. I barely understand it!
  630. It's mostly copy and pasted from the CMake build system.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define* (zephyr-build name inputs
  631. #:key guile source
  632. board
  633. (outputs '(&amp;quot;out&amp;quot;)) (configure-flags ''())
  634. (search-paths '())
  635. (make-flags ''())
  636. (out-of-source? #t)
  637. (tests? #f)
  638. (test-target &amp;quot;test&amp;quot;)
  639. (parallel-build? #t) (parallel-tests? #t)
  640. (validate-runpath? #f)
  641. (patch-shebangs? #t)
  642. (phases '%standard-phases)
  643. (system (%current-system))
  644. (substitutable? #t)
  645. (imported-modules %zephyr-build-system-modules)
  646. ;; The modules referenced here contain code
  647. ;; which will be staged in the build environment with us.
  648. ;; Our build gexp down below will only be able to access this code
  649. ;; and we must be careful not to reference anything else.
  650. (modules '((zephyr build zephyr-build-system)
  651. (guix build utils))))
  652. &amp;quot;Build SOURCE using CMAKE, and with INPUTS. This assumes that SOURCE
  653. provides a 'CMakeLists.txt' file as its build system.&amp;quot;
  654. ;; This is the build gexp. It handles staging values from our host
  655. ;; system into code that our build system can run.
  656. (define build
  657. (with-imported-modules imported-modules
  658. #~(begin
  659. (use-modules #$@(sexp-&amp;gt;gexp modules))
  660. #$(with-build-variables inputs outputs
  661. #~(zephyr-build #:source #+source
  662. #:system #$system
  663. #:outputs %outputs
  664. #:inputs %build-inputs
  665. #:board #$board
  666. #:search-paths '#$(sexp-&amp;gt;gexp
  667. (map search-path-specification-&amp;gt;sexp
  668. search-paths))
  669. #:phases #$(if (pair? phases)
  670. (sexp-&amp;gt;gexp phases)
  671. phases)
  672. #:configure-flags #$(if (pair? configure-flags)
  673. (sexp-&amp;gt;gexp configure-flags)
  674. configure-flags)
  675. #:make-flags #$make-flags
  676. #:out-of-source? #$out-of-source?
  677. #:tests? #$tests?
  678. #:test-target #$test-target
  679. #:parallel-build? #$parallel-build?
  680. #:parallel-tests? #$parallel-tests?
  681. #:validate-runpath? #$validate-runpath?
  682. #:patch-shebangs? #$patch-shebangs?
  683. #:strip-binaries? #f)))))
  684. (mlet %store-monad ((guile (package-&amp;gt;derivation (or guile (default-guile))
  685. system #:graft? #f)))
  686. (gexp-&amp;gt;derivation name build
  687. #:system system
  688. #:target #f
  689. #:graft? #f
  690. #:substitutable? substitutable?
  691. #:guile-for-build guile)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally we define our build system which the package definitions can reference.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define zephyr-build-system
  692. (build-system
  693. (name 'zephyr)
  694. (description &amp;quot;The standard Zephyr build system&amp;quot;)
  695. (lower lower)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Easy right?&lt;/p&gt;&lt;h1&gt;Build Side&lt;/h1&gt;&lt;p&gt;The build side is not as complex as you might initially expect.
  696. Our build system is almost exactly the same as the CMake build system
  697. except our configure phase passes different values to CMake.
  698. Our job is much easier.&lt;/p&gt;&lt;h3&gt;Locating Modules&lt;/h3&gt;&lt;p&gt;Zephyr CMake requires the zephyr &lt;em&gt;modules&lt;/em&gt; which are needed for the
  699. build to be supplied on the command line.
  700. Unfortunately for us, the
  701. &lt;a href=&quot;https://docs.zephyrproject.org/3.1.0/develop/application/index.html#important-build-vars&quot;&gt;documentation&lt;/a&gt;
  702. is wrong, and the &lt;code&gt;ZEPHYR_MODULES&lt;/code&gt; environment variable is not honored.
  703. Thus we must implement some other solution for locating modules, until
  704. this that is fixed.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Input Scanning&lt;/strong&gt; - Lucky for us we are keeping detailed information
  705. about our dependencies. It is a simple matter to write a file tree
  706. walker which collects all the zephyr modules in our inputs.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define* (find-zephyr-modules directories)
  707. &amp;quot;Return the list of directories containing zephyr/module.yml found
  708. under DIRECTORY, recursively. Return the empty list if DIRECTORY is
  709. not accessible.&amp;quot;
  710. (define (module-directory file)
  711. (dirname (dirname file)))
  712. (define (enter? name stat result)
  713. ;; Skip version control directories.
  714. ;; Shouldn't be in the store but you never know.
  715. (not (member (basename name) '(&amp;quot;.git&amp;quot; &amp;quot;.svn&amp;quot; &amp;quot;CVS&amp;quot;))))
  716. (define (leaf name stat result)
  717. ;; Add module root directory to results
  718. (if (and (string= &amp;quot;module.yml&amp;quot; (basename name))
  719. (string= &amp;quot;zephyr&amp;quot; (basename (dirname name))))
  720. (cons (module-directory name) result)
  721. result))
  722. (define (down name stat result) result)
  723. (define (up name stat result) result)
  724. (define (skip name stat result) result)
  725. (define (find-modules directory)
  726. (file-system-fold enter? leaf down up skip error
  727. '() (canonicalize-path directory)))
  728. (append-map find-modules directories))
  729. (define (zephyr-modules-cmake-argument modules)
  730. &amp;quot;Return a proper CMake list from MODULES, a list of filepaths&amp;quot;
  731. (format #f &amp;quot;-DZEPHYR_MODULES='~{~a~^;~}'&amp;quot; modules))
  732. &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here are two functions. The first one &lt;code&gt;find-zephyr-modules&lt;/code&gt; walks a
  733. list of directories (package inputs) and returns a list of every module it finds.
  734. The second one is just for syntactic convenience when writing the CMake invokation.
  735. This is also slightly more robust than West's module discovery, because it allows for
  736. a single repository to provide multiple modules which are not &lt;em&gt;technically&lt;/em&gt; required
  737. to be at the top level.&lt;/p&gt;&lt;p&gt;From here we just need to provide alternate implementations of &lt;code&gt;configure&lt;/code&gt; and &lt;code&gt;install&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define* (configure #:key outputs (configure-flags '())
  738. inputs (out-of-source? #t)
  739. build-type
  740. #:allow-other-keys)
  741. &amp;quot;Configure the given package.&amp;quot;
  742. (let* ((out (assoc-ref outputs &amp;quot;out&amp;quot;))
  743. (abs-srcdir (getcwd))
  744. (srcdir (if out-of-source?
  745. (string-append &amp;quot;../&amp;quot; (basename abs-srcdir))
  746. &amp;quot;.&amp;quot;)))
  747. (format #t &amp;quot;source directory: ~s (relative from build: ~s)~%&amp;quot;
  748. abs-srcdir srcdir)
  749. (when out-of-source?
  750. (mkdir &amp;quot;../build&amp;quot;)
  751. (chdir &amp;quot;../build&amp;quot;))
  752. (format #t &amp;quot;build directory: ~s~%&amp;quot; (getcwd))
  753. ;; this is required because zephyr tries to optimize
  754. ;; future calls to the build scripts by keep a cache.
  755. (setenv &amp;quot;XDG_CACHE_HOME&amp;quot; (getcwd))
  756. (let ((args `(,srcdir
  757. ,@(if build-type
  758. (list (string-append &amp;quot;-DCMAKE_BUILD_TYPE=&amp;quot;
  759. build-type))
  760. '())
  761. ;; enable verbose output from builds
  762. &amp;quot;-DCMAKE_VERBOSE_MAKEFILE=ON&amp;quot;
  763. ,(zephyr-modules-cmake-argument
  764. (find-zephyr-modules (map cdr inputs)))
  765. ,@configure-flags)))
  766. (format #t &amp;quot;running 'cmake' with arguments ~s~%&amp;quot; args)
  767. (apply invoke &amp;quot;cmake&amp;quot; args))))
  768. (define* (install #:key outputs #:allow-other-keys)
  769. (let* ((out (string-append (assoc-ref outputs &amp;quot;out&amp;quot;) &amp;quot;/lib/firmware&amp;quot;))
  770. (dbg (string-append (assoc-ref outputs &amp;quot;debug&amp;quot;) &amp;quot;/share/zephyr&amp;quot;)))
  771. (mkdir-p out)
  772. (mkdir-p dbg)
  773. (copy-file &amp;quot;zephyr/.config&amp;quot; (string-append dbg &amp;quot;/config&amp;quot;))
  774. (copy-file &amp;quot;zephyr/zephyr.map&amp;quot; (string-append dbg &amp;quot;/zephyr.map&amp;quot;))
  775. (copy-file &amp;quot;zephyr/zephyr.elf&amp;quot; (string-append out &amp;quot;/zephyr.elf&amp;quot;))
  776. (copy-file &amp;quot;zephyr/zephyr.bin&amp;quot; (string-append out &amp;quot;/zephyr.bin&amp;quot;))))
  777. ;; Define new standard-phases
  778. (define %standard-phases
  779. (modify-phases cmake:%standard-phases
  780. (replace 'configure configure)
  781. (replace 'install install)))
  782. ;; Call cmake build with our new phases
  783. (define* (zephyr-build #:key inputs (phases %standard-phases)
  784. #:allow-other-keys #:rest args)
  785. (apply cmake:cmake-build #:inputs inputs #:phases phases args))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One thing to note is the &amp;quot;debug&amp;quot; output. This exists so we don't
  786. retain references to our build environment and make the file system
  787. closure huge. If you put all of the build outputs in the same store
  788. path, then the deployment closure will grow from 2MB to 833MB.&lt;/p&gt;&lt;h1&gt;Defining Zephyr Packages&lt;/h1&gt;&lt;p&gt;Now that we have a proper build system, it's time to define some packages!&lt;/p&gt;&lt;h3&gt;Zephyr Base&lt;/h3&gt;&lt;p&gt;Zephyr base contains the Zephyr source code. It is equivalent (in my mind
  789. anyway) to the linux kernel, in that packages' definitions' specifications,
  790. which target the linux kernel, can be minimal.&lt;/p&gt;&lt;p&gt;The selection of operating system actually comes from the toolchain. For
  791. example, we build linux packages with the &lt;a href=&quot;https://www.gnu.org/software/autoconf/manual/autoconf-2.65/html_node/Specifying-Target-Triplets.html&quot;&gt;gnu
  792. triplet&lt;/a&gt;.
  793. When we select the &lt;code&gt;arm-linux-gnueabihf,&lt;/code&gt; we are specifying our operating system.&lt;/p&gt;&lt;p&gt;It is the same for Zephyr. When we build for zephyr we use the &lt;code&gt;arm-zephyr-eabi&lt;/code&gt;
  794. toolchain. However, unlike linux applications, zephyr applications are
  795. embedded firmware images and are generally statically linked.
  796. Thus this package just consists of its source code and is not compiled directly.
  797. We cannot compile it now because applications/modules provide the required Kconfig
  798. options.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public zephyr
  799. (let ((version &amp;quot;3.1.0&amp;quot;)
  800. (commit &amp;quot;zephyr-v3.1.0&amp;quot;))
  801. (package
  802. (name &amp;quot;zephyr&amp;quot;)
  803. (version version)
  804. (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  805. (source (origin (method git-fetch)
  806. (uri (git-reference
  807. (url &amp;quot;https://github.com/zephyrproject-rtos/zephyr&amp;quot;)
  808. (commit commit)))
  809. (file-name (git-file-name name version))
  810. (sha256
  811. (base32 &amp;quot;1yl5y9757xc3l037k3g1dynispv6j5zqfnzrhsqh9cx4qzd485lx&amp;quot;))
  812. (patches
  813. ;; this patch makes this package work in a symlinked profile
  814. (search-patches &amp;quot;zephyr-3.1-linker-gen-abs-path.patch&amp;quot;))))
  815. (build-system copy-build-system)
  816. (arguments
  817. `(#:install-plan
  818. '((&amp;quot;.&amp;quot; &amp;quot;zephyr-workspace/zephyr&amp;quot;))
  819. #:phases
  820. (modify-phases %standard-phases
  821. (add-after 'unpack 'patch-cmake-scripts
  822. (lambda* _
  823. (format #t &amp;quot;~a~&amp;amp;&amp;quot; (getcwd))
  824. ;; Some cmake scripts assume the presence of a
  825. ;; git repository in the source directory.
  826. ;; We will just hard-code that information now
  827. (substitute* &amp;quot;CMakeLists.txt&amp;quot;
  828. ((&amp;quot;if\\(DEFINED BUILD_VERSION\\)&amp;quot; all)
  829. (format #f &amp;quot;set(BUILD_VERSION \&amp;quot;~a-~a\&amp;quot;)~&amp;amp;~a&amp;quot;
  830. ,version ,commit all))))))))
  831. (propagated-inputs
  832. (list python-3
  833. python-pyelftools
  834. python-pykwalify
  835. python-pyyaml
  836. python-packaging))
  837. (native-search-paths
  838. (list (search-path-specification
  839. (variable &amp;quot;ZEPHYR_BASE&amp;quot;)
  840. (files '(&amp;quot;zephyr-workspace/zephyr&amp;quot;)))))
  841. (synopsis &amp;quot;Source code for zephyr rtos&amp;quot;)
  842. (description &amp;quot;Zephyr rtos source code.&amp;quot;)
  843. (license license:apsl2))))
  844. (define-public zephyr-3.2.0-rc3
  845. (package (inherit zephyr)
  846. (version &amp;quot;3.2.0-rc3&amp;quot;)
  847. (source (origin (method git-fetch)
  848. (uri (git-reference
  849. (url &amp;quot;https://github.com/zephyrproject-rtos/zephyr&amp;quot;)
  850. (commit &amp;quot;v3.2.0-rc3&amp;quot;)))
  851. (file-name (git-file-name &amp;quot;zephyr&amp;quot; version))
  852. (sha256
  853. (base32 &amp;quot;06ksd9zj4j19jq0zg3lms13jx0gxzjc41433zgb91cnd2cqmn5cb&amp;quot;))
  854. (patches
  855. (search-patches &amp;quot;zephyr-3.1-linker-gen-abs-path.patch&amp;quot;))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here we use the &lt;code&gt;copy-build-system&lt;/code&gt; which takes a list of source destination
  856. pairs. In our case, we just copy everything to the output directory, but not
  857. before patching some files to accomodate our special environment.&lt;/p&gt;&lt;p&gt;While developing this I wanted to test some toolchain/board features
  858. on the latest release of Zephyr. I included an example of that package
  859. definition to show how we can easily accomodate side by side package
  860. variants and experiment without breaking anything.&lt;/p&gt;&lt;h3&gt;Modules&lt;/h3&gt;&lt;p&gt;It's finally time to define some firmware!
  861. Zephyr packages some examples in &lt;code&gt;$ZEPHYR_BASE/samples&lt;/code&gt; including a
  862. basic hello world. The k64 development board is already supported
  863. by Zephyr so building the example is trivial.&lt;/p&gt;&lt;p&gt;In order to actually target the k64 we need to two modules, the NXP
  864. hardware abstraction layer, and CMSIS.
  865. Looking at &lt;code&gt;$ZEPHYR_BASE/west.yml&lt;/code&gt; we can see the repositories
  866. and commits which contain these modules. This is how West does
  867. dependency management.&lt;/p&gt;&lt;p&gt;Defining these packages is not so bad (see footnote 1).&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public hal-cmsis
  868. (package
  869. (name &amp;quot;hal-cmsis&amp;quot;)
  870. (version &amp;quot;5.8.0&amp;quot;)
  871. (home-page &amp;quot;https://developer.arm.com/tools-and-software/embedded/cmsis&amp;quot;)
  872. (source (origin
  873. (method git-fetch)
  874. (uri (git-reference
  875. (url &amp;quot;https://github.com/zephyrproject-rtos/cmsis&amp;quot;)
  876. (commit &amp;quot;093de61c2a7d12dc9253daf8692f61f793a9254a&amp;quot;)))
  877. (file-name (git-file-name name version))
  878. (sha256
  879. (base32 &amp;quot;0f7cipnwllna7iknsnz273jkvrly16yr6wm4y2018i6njpqh67wi&amp;quot;))))
  880. (build-system zephyr-module-build-system)
  881. (arguments `(#:workspace-path &amp;quot;/modules/hal/cmsis&amp;quot;))
  882. (synopsis &amp;quot;Zephyr module providing the Common Microcontroller
  883. Software Interface Standard&amp;quot;)
  884. (description &amp;quot;Zephyr module providing the Common Microcontroller
  885. Software Interface Standard&amp;quot;)
  886. (license license:apsl2)))
  887. (define-public hal-nxp
  888. (package
  889. (name &amp;quot;hal-nxp&amp;quot;)
  890. (version &amp;quot;3.1.0&amp;quot;)
  891. (home-page &amp;quot;https://nxp.com&amp;quot;)
  892. (source (origin
  893. (method git-fetch)
  894. (uri (git-reference
  895. (url &amp;quot;https://github.com/zephyrproject-rtos/hal_nxp&amp;quot;)
  896. (commit &amp;quot;708c95825b0d5279620935a1356299fff5dfbc6e&amp;quot;)))
  897. (file-name (git-file-name name version))
  898. (sha256
  899. (base32 &amp;quot;1c0i26bpk6cyhr1q4af183jclfmxshv4d15i7k3cz7brzb12m8q1&amp;quot;))))
  900. (build-system zephyr-module-build-system)
  901. (arguments `(#:workspace-path &amp;quot;/modules/hal/nxp&amp;quot;))
  902. (native-search-paths
  903. (list (search-path-specification
  904. (variable &amp;quot;ZEPHYR_MODULES&amp;quot;)
  905. (files `(,(string-append %zephyr-workspace-name module-path)))
  906. (separator &amp;quot;;&amp;quot;))))
  907. (synopsis &amp;quot;Zephyr module for NXP Hardware Abstraction Layer&amp;quot;)
  908. (description &amp;quot;Provides sources for NXP HAL zephyr module&amp;quot;)
  909. (license license:bsd-3)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With these two modules defined we can write &lt;code&gt;zephyr-hello-world-frdm-k64f&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;Hello world&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public zephyr-hello-world-frdm-k64f
  910. (package
  911. (name &amp;quot;zephyr-hello-world-frdm-k64f&amp;quot;)
  912. (version (package-version zephyr))
  913. (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  914. (source (file-append (package-source zephyr)
  915. &amp;quot;/samples/hello_world&amp;quot;))
  916. (build-system zephyr-build-system)
  917. (arguments
  918. '(#:configure-flags '(&amp;quot;-DBOARD=frdm_k64f&amp;quot;)))
  919. (outputs '(&amp;quot;out&amp;quot; &amp;quot;debug&amp;quot;))
  920. (inputs
  921. (list hal-cmsis
  922. hal-nxp))
  923. (synopsis &amp;quot;Hello world example from Zephyr Project&amp;quot;)
  924. (description &amp;quot;Sample package for zephyr project&amp;quot;)
  925. (license license:apsl2)))&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Building&lt;/h3&gt;&lt;p&gt;Our above definition can be built using the following:
  926. When testing package definitions, I use the &lt;code&gt;-L&lt;/code&gt; flag to point to the local
  927. repository to load the new packages. I will be omitting that flag as
  928. if I had ~guix pull~ed successfully from &lt;a href=&quot;https://github.com/paperclip4465/guix-zephyr&quot;&gt;guix-zephyr&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;guix build zephyr-hello-world-frdm-k64f
  929. /gnu/store/...-zephyr-hello-world-frdm-k64f-3.1.0-debug
  930. /gnu/store/...-zephyr-hello-world-frdm-k64f-3.1.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This actually doesn't fully test our toolchain. The hello world
  931. example, by default, will use a zephyr provided
  932. minimal implementation of the C library and will not link against
  933. newlib.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public zephyr-hello-world-newlib-frdm-k64f
  934. (package
  935. (inherit zephyr-hello-world-frdm-k64f)
  936. (name &amp;quot;zephyr-hello-world-newlib-frdm-k64f&amp;quot;)
  937. (arguments
  938. (substitute-keyword-arguments (package-arguments zephyr-hello-world-frdm-k64f)
  939. ((#:configure-flags flags)
  940. `(append
  941. '(&amp;quot;-DCONFIG_MINIMAL_LIBC=n&amp;quot;
  942. &amp;quot;-DCONFIG_NEWLIB_LIBC=y&amp;quot;)
  943. ,flags))))))
  944. guix build zephyr-hello-world-newlib-frdm-k64f
  945. /gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-debug
  946. /gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Woohoo!&lt;/p&gt;&lt;h1&gt;Further Musings&lt;/h1&gt;&lt;p&gt;One thing I learned while going through the pains of getting this
  947. working is that even though the components are &amp;quot;modular&amp;quot; there is
  948. still a lot rigid interdependencies, especially on the zephyr base.
  949. Just having two versions of Zephyr in the code base made component
  950. composition fragile.
  951. Modules rely on specific features from the kernel.
  952. This is hidden from developers normally by west automagically walking
  953. the `west.yml` of all of the declared dependencies recursively to
  954. discover the graph.&lt;/p&gt;&lt;p&gt;While there are many benefits to a modularized build system, a monolithic build
  955. system, like Zephyr, does have many benefits too.&lt;/p&gt;&lt;p&gt;Part of the problem comes from the domain itself. If you really want to be able
  956. to target the most resource constrained systems and deal with the &amp;quot;industrial
  957. mess&amp;quot; that comes from every board being unique, you have to be as generic and
  958. flexible as possible, which is hard in a guix-like modular build system.&lt;/p&gt;&lt;p&gt;Superficially the problem is solved in the same way Linux solved it, using
  959. device trees and having a very stable userland interface. However, unlike Linux
  960. where the device tree is compiled to a binary blob and interpreted by drivers at
  961. runtime, Zephyr device trees are compiled to a &lt;code&gt;.h&lt;/code&gt; file and are mostly
  962. interpreted by the C pre-processor using an elaborate set of macros.&lt;/p&gt;&lt;p&gt;It goes beyond simply abstracting the hardware using clever hacks.
  963. Zephyr applications (and any zephyr module) can also introduce new
  964. &amp;quot;kernel&amp;quot; code, configuration options, and even linker script fragments
  965. at build time.
  966. Essentially the Zephyr CMake build system acts like a reverse ld.
  967. Instead of linking libraries after compilation, it discovers these
  968. things before gcc is ever invoked and provides additional code
  969. generation steps.&lt;/p&gt;&lt;p&gt;Zephyr does not have a stable &amp;quot;userland&amp;quot; interface for the same
  970. reason Linux does not have a stable &amp;quot;kernel module&amp;quot; interface.
  971. Because Zephyr applications are so tightly coupled to the hardware
  972. they run on it is not uncommon to bypass Zephyr utilities and directly
  973. touch hardware and memory.&lt;/p&gt;&lt;p&gt;In this way they are more related to kernel modules
  974. than userspace applications such as GNU Hello.&lt;/p&gt;&lt;p&gt;Perhaps there is a lispy way to track several zephyr releases without reducing
  975. the ability to freely modify components in the usual ways...I invite you dear
  976. reader to developer code to explore that possibility.&lt;/p&gt;&lt;p&gt;It is use-able for Guix anyway.&lt;/p&gt;&lt;h1&gt;Why a Special Build System? Why not &lt;code&gt;--target=frdm_k64f&lt;/code&gt;?&lt;/h1&gt;&lt;p&gt;That is a fair question!
  977. At first glance you might imagine the following incantation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;guix build --target=arm-zephyr-eabi hello&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The problem with calling the toolchain directly is that the architecture
  978. is specified by the board selection. It is not generally useful to
  979. compile a board to a different architecture.&lt;/p&gt;&lt;p&gt;Perhaps maybe something like this then.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;guix build --target=frdm_k64f hello&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above command tells GNU hello to link against arm-zephyr-newlib and run on
  980. a specific board. The problem is that while this &lt;em&gt;may&lt;/em&gt; work for GNU Hello, it
  981. will not work for anything, which requires inputs that are discovered by normal
  982. methods. Only packages which target zephyr explicitly could benefit from such an
  983. interface, and at that point, you may as well record which board is being targeted
  984. in the package definition.&lt;/p&gt;&lt;p&gt;In general not all zephyr applications can run on every board zephyr
  985. can run on, so the usefulness of the above command is dubious.&lt;/p&gt;&lt;p&gt;I think if you have firmware which targets multiple boards it is
  986. better to define a package for every board. It is likely every board
  987. will require special configuration flags anyway.&lt;/p&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;p&gt;Zephyr has a very complex build process which can be difficult to
  988. understand and frustrating to set up.&lt;/p&gt;&lt;p&gt;Using Guix to define firmware packages makes these problems disappear.
  989. It is trivial to create a channel which contains all of the quirks of
  990. your platform and share it with a team or student.&lt;/p&gt;&lt;p&gt;Packages defined this way serve as a reproducible starting point for
  991. future hardware revisions and variations.&lt;/p&gt;&lt;h1&gt;Footnotes&lt;/h1&gt;&lt;ol&gt;&lt;li&gt;I also made a &lt;code&gt;zephyr-module-build-system&lt;/code&gt; as well which is just the
  992. &lt;code&gt;copy-build-system&lt;/code&gt; that mimics the default zephyr workspace layout as provided
  993. by west. This way we do not need to provide the same install-plan for every
  994. module we package. However as I use the &lt;code&gt;copy-build-system&lt;/code&gt; more often, it
  995. doesn't really provide much over just using the copy-build system.&lt;/li&gt;&lt;/ol&gt;</summary></entry><entry><title>Building Toolchains with Guix</title><id>https://gnucode.me/building-toolchains-with-guix.html</id><author><name>Mitchell Schmeisser &lt;mitchellschmeisser@librem.one&gt;</name><email>jbranso@dismail.de</email></author><updated>2023-02-23T23:00:00Z</updated><link href="https://gnucode.me/building-toolchains-with-guix.html" rel="alternate" /><summary type="html">&lt;p&gt;Today's post is a guest post from my new internet friend Mitchell. We met on the
  996. #guix irc channel, and I offered to post a few of his blog posts on this blog. Without further ado,
  997. here is Michell's first blog post (it's pretty fantastic)!&lt;/p&gt;&lt;h1&gt;Overview&lt;/h1&gt;&lt;p&gt;In order to deploy embedded software using Guix we first need to teach Guix
  998. how to build it. Since Guix bootstraps everything this means we must teach Guix
  999. how to build our toolchain.&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://zephyrproject.org&quot;&gt;Zephyr Project&lt;/a&gt; uses its own fork of GCC with custom configs for
  1000. the architectures supported by the project.&lt;/p&gt;&lt;h1&gt;Anatomy of a toolchain&lt;/h1&gt;&lt;p&gt;Toolchains are responsible for taking high level descriptions of programs and
  1001. lowering them down to a series of equivalent machine instructions. This process
  1002. involves more than just a compiler. The compiler uses the &lt;code&gt;binutils&lt;/code&gt; to
  1003. manipulate it’s internal representation down to a given architecture. It
  1004. also needs the C standard library as well as a few other libraries needed for
  1005. some compiler optimizations.&lt;/p&gt;&lt;p&gt;The C library provides the interface to the underlying kernel. System calls like &lt;code&gt;write&lt;/code&gt;
  1006. and &lt;code&gt;read&lt;/code&gt; are provided by &lt;code&gt;Glibc&lt;/code&gt; on most Linux distributions.&lt;/p&gt;&lt;p&gt;In embedded systems smaller implementations like &lt;code&gt;newlib&lt;/code&gt; and &lt;code&gt;newlib-nano&lt;/code&gt; are used.&lt;/p&gt;&lt;h1&gt;Bootstrapping a Toolchain&lt;/h1&gt;&lt;p&gt;In order to compile GCC we need a C library that’s been compiled for
  1007. our target architecture. How can we cross compile our C library if we
  1008. need our C library to build a cross compiler? The solution is to build
  1009. a simpler compiler that doesn’t require the C library to function.
  1010. It will not be capable of as many optimizations and it will be very slow,
  1011. however it will be able to build the C libraries as well as the complete version
  1012. of GCC.&lt;/p&gt;&lt;p&gt;In order to build the simpler compiler we need to compile the &lt;code&gt;binutils&lt;/code&gt; to
  1013. work with our target architecture.
  1014. The &lt;code&gt;binutils&lt;/code&gt; can be bootstrapped with our host GCC and have no target dependencies.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://crosstool-ng.github.io/docs/toolchain-construction/&quot;&gt;For more information read this.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Doesn’t sound so bad right? It isn’t… in theory.
  1015. However internet forums since time immemorial have been
  1016. littered with the laments of those who came before.
  1017. From incorrect versions of &lt;code&gt;ISL&lt;/code&gt; to the wrong C library being linked
  1018. or the host linker being used, etc.
  1019. The one commonality between all of these issues is the environment.
  1020. Building GCC is difficult because isolating build environments is hard.&lt;/p&gt;&lt;p&gt;In fact as of &lt;code&gt;v0.14.2&lt;/code&gt; the zephyr SDK repository took down the build
  1021. instructions and posted a sign that read “Building this is too
  1022. complicated, don’t worry about it.” (I’m paraphrasing, but
  1023. &lt;a href=&quot;https://github.com/zephyrproject-rtos/sdk-ng/tree/v0.14.2#build-process&quot;&gt;not by
  1024. much&lt;/a&gt;.)&lt;/p&gt;&lt;p&gt;We will neatly side step all of these problems and not
  1025. risk destroying or polluting our host system with garbage
  1026. by using Guix to manage our environments for us.&lt;/p&gt;&lt;p&gt;Our toolchain only requires the first pass compiler because
  1027. newlib(-nano) is statically linked and introduced to the toolchain
  1028. by normal package composition.&lt;/p&gt;&lt;h1&gt;Defining the Packages&lt;/h1&gt;&lt;p&gt;All of the base packages are defined in &lt;code&gt;zephyr/packages/zephyr.scm&lt;/code&gt;.
  1029. Zephyr modules are defined in &lt;code&gt;zephyr/packages/zephyr-xyz.scm&lt;/code&gt;, following
  1030. the pattern of other module systems implemented by Guix.&lt;/p&gt;&lt;h2&gt;Binutils&lt;/h2&gt;&lt;p&gt;First thing we need to build is the &lt;code&gt;arm-zephyr-eabi&lt;/code&gt; binutils.
  1031. This is very easy in Guix.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-module (zephyr packages zephyr)
  1032. #:use-module (guix packages)
  1033. (define-public arm-zephyr-eabi-binutils
  1034. (let ((xbinutils (cross-binutils &amp;quot;arm-zephyr-eabi&amp;quot;)))
  1035. (package
  1036. (inherit xbinutils)
  1037. (name &amp;quot;arm-zephyr-eabi-binutils&amp;quot;)
  1038. (version &amp;quot;2.38&amp;quot;)
  1039. (source
  1040. (origin (method git-fetch)
  1041. (uri (git-reference
  1042. (url &amp;quot;https://github.com/zephyrproject-rtos/binutils-gdb&amp;quot;)
  1043. (commit &amp;quot;6a1be1a6a571957fea8b130e4ca2dcc65e753469&amp;quot;)))
  1044. (file-name (git-file-name name version))
  1045. (sha256 (base32 &amp;quot;0ylnl48jj5jk3jrmvfx5zf8byvwg7g7my7jwwyqw3a95qcyh0isr&amp;quot;))))
  1046. (arguments
  1047. `(#:tests? #f
  1048. ,@(substitute-keyword-arguments (package-arguments xbinutils)
  1049. ((#:configure-flags flags)
  1050. `(cons &amp;quot;--program-prefix=arm-zephyr-eabi-&amp;quot; ,flags)))))
  1051. (native-inputs
  1052. (append
  1053. (list texinfo
  1054. bison
  1055. flex
  1056. gmp
  1057. dejagnu)
  1058. (package-native-inputs xbinutils)))
  1059. (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  1060. (synopsis &amp;quot;binutils for zephyr RTOS&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The function &lt;code&gt;cross-binutils&lt;/code&gt; returns a package which has been
  1061. configured for the given gnu triplet. We simply inherit that package
  1062. and replace the source.
  1063. The zephyr build system expects the binutils to be prefixed with
  1064. &lt;code&gt;arm-zephyr-eabi-&lt;/code&gt; which is accomplished by adding another flag to the
  1065. &lt;code&gt;#:configure-flags&lt;/code&gt; argument.&lt;/p&gt;&lt;p&gt;We can test our package definition using the &lt;code&gt;-L&lt;/code&gt; flag with &lt;code&gt;guix build&lt;/code&gt;
  1066. to add our packages.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr zephyr-binutils
  1067. /gnu/store/a947nb4rb2vymz2gaqnafgm1bsq4ipqp-zephyr-binutils-2.38&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This directory contains the results of &lt;code&gt;make install&lt;/code&gt;.&lt;/p&gt;&lt;h2&gt;GCC sans libc&lt;/h2&gt;&lt;p&gt;This one is a bit more involved. Don’t be afraid!
  1068. This version of GCC wants ISL version 0.15. It’s easy enough
  1069. to make that happen. Inherit the current version of ISL and swap
  1070. out the source and update the version. For most packages the build process doesn’t
  1071. change that much between versions.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-public isl-0.15
  1072. (package
  1073. (inherit isl)
  1074. (version &amp;quot;0.15&amp;quot;)
  1075. (source (origin
  1076. (method url-fetch)
  1077. (uri (list (string-append &amp;quot;mirror://sourceforge/libisl/isl-&amp;quot;
  1078. version &amp;quot;.tar.gz&amp;quot;)))
  1079. (sha256
  1080. (base32
  1081. &amp;quot;11vrpznpdh7w8jp4wm4i8zqhzq2h7nix71xfdddp8xnzhz26gyq2&amp;quot;))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Like the binutils, there is a function for creating cross-gcc packages. This one
  1082. accepts keywords specifying which binutils and libc to use. If libc isn’t
  1083. given (like here), gcc is configured with many options disabled to facilitate
  1084. being built without libc. Therefore we need to add the extra options we want (I
  1085. got them from the SDK configuration scripts on the &lt;a href=&quot;https://github.com/zephyrproject-rtos/sdk-ng&quot;&gt;sdk
  1086. github&lt;/a&gt; as well as the commits to
  1087. use for each of the tools. ).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-public gcc-arm-zephyr-eabi-12
  1088. (let ((xgcc (cross-gcc &amp;quot;arm-zephyr-eabi&amp;quot;
  1089. #:xbinutils zephyr-binutils)))
  1090. (package
  1091. (inherit xgcc)
  1092. (version &amp;quot;12.1.0&amp;quot;)
  1093. (source (origin (method git-fetch)
  1094. (uri (git-reference
  1095. (url &amp;quot;https://github.com/zephyrproject-rtos/gcc&amp;quot;)
  1096. (commit &amp;quot;0218469df050c33479a1d5be3e5239ac0eb351bf&amp;quot;)))
  1097. (file-name (git-file-name (package-name xgcc) version))
  1098. (sha256
  1099. (base32 &amp;quot;1s409qmidlvzaw1ns6jaanigh3azcxisjplzwn7j2n3s33b76zjk&amp;quot;))
  1100. (patches
  1101. (search-patches &amp;quot;gcc-12-cross-environment-variables.patch&amp;quot;
  1102. &amp;quot;gcc-cross-gxx-include-dir.patch&amp;quot;))))
  1103. (native-inputs
  1104. (modify-inputs (package-native-inputs xgcc)
  1105. ;; Get rid of stock ISL
  1106. (delete &amp;quot;isl&amp;quot;)
  1107. ;; Add additional dependencies that xgcc doesn't have
  1108. ;; including our special ISL
  1109. (prepend flex
  1110. perl
  1111. python-3
  1112. gmp
  1113. isl-0.15
  1114. texinfo
  1115. python
  1116. mpc
  1117. mpfr
  1118. zlib)))
  1119. (arguments
  1120. (substitute-keyword-arguments (package-arguments xgcc)
  1121. ((#:phases phases)
  1122. `(modify-phases ,phases
  1123. (add-after 'unpack 'fix-genmultilib
  1124. (lambda _
  1125. (substitute* &amp;quot;gcc/genmultilib&amp;quot;
  1126. ((&amp;quot;#!/bin/sh&amp;quot;) (string-append &amp;quot;#!&amp;quot; (which &amp;quot;sh&amp;quot;))))
  1127. #t))
  1128. (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH
  1129. (lambda* (#:key inputs #:allow-other-keys)
  1130. (let ((gcc (assoc-ref inputs &amp;quot;gcc&amp;quot;)))
  1131. ;; Remove the default compiler from CPLUS_INCLUDE_PATH to
  1132. ;; prevent header conflict with the GCC from native-inputs.
  1133. (setenv &amp;quot;CPLUS_INCLUDE_PATH&amp;quot;
  1134. (string-join
  1135. (delete (string-append gcc &amp;quot;/include/c++&amp;quot;)
  1136. (string-split (getenv &amp;quot;CPLUS_INCLUDE_PATH&amp;quot;)
  1137. #\:))
  1138. &amp;quot;:&amp;quot;))
  1139. (format #t
  1140. &amp;quot;environment variable `CPLUS_INCLUDE_PATH' changed to ~a~%&amp;quot;
  1141. (getenv &amp;quot;CPLUS_INCLUDE_PATH&amp;quot;))
  1142. #t)))))
  1143. ((#:configure-flags flags)
  1144. ;; The configure flags are largely identical to the flags used by the
  1145. ;; &amp;quot;GCC ARM embedded&amp;quot; project.
  1146. `(append (list &amp;quot;--enable-multilib&amp;quot;
  1147. &amp;quot;--with-newlib&amp;quot;
  1148. &amp;quot;--with-multilib-list=rmprofile&amp;quot;
  1149. &amp;quot;--with-host-libstdcxx=-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm&amp;quot;
  1150. &amp;quot;--enable-plugins&amp;quot;
  1151. &amp;quot;--disable-decimal-float&amp;quot;
  1152. &amp;quot;--disable-libffi&amp;quot;
  1153. &amp;quot;--disable-libgomp&amp;quot;
  1154. &amp;quot;--disable-libmudflap&amp;quot;
  1155. &amp;quot;--disable-libquadmath&amp;quot;
  1156. &amp;quot;--disable-libssp&amp;quot;
  1157. &amp;quot;--disable-libstdcxx-pch&amp;quot;
  1158. &amp;quot;--disable-nls&amp;quot;
  1159. &amp;quot;--disable-shared&amp;quot;
  1160. &amp;quot;--disable-threads&amp;quot;
  1161. &amp;quot;--disable-tls&amp;quot;
  1162. &amp;quot;--with-gnu-ld&amp;quot;
  1163. &amp;quot;--with-gnu-as&amp;quot;
  1164. &amp;quot;--enable-initfini-array&amp;quot;)
  1165. (delete &amp;quot;--disable-multilib&amp;quot; ,flags)))))
  1166. (native-search-paths
  1167. (list (search-path-specification
  1168. (variable &amp;quot;CROSS_C_INCLUDE_PATH&amp;quot;)
  1169. (files '(&amp;quot;arm-zephyr-eabi/include&amp;quot;)))
  1170. (search-path-specification
  1171. (variable &amp;quot;CROSS_CPLUS_INCLUDE_PATH&amp;quot;)
  1172. (files '(&amp;quot;arm-zephyr-eabi/include&amp;quot;
  1173. &amp;quot;arm-zephyr-eabi/c++&amp;quot;
  1174. &amp;quot;arm-zephyr-eabi/c++/arm-zephyr-eabi&amp;quot;)))
  1175. (search-path-specification
  1176. (variable &amp;quot;CROSS_LIBRARY_PATH&amp;quot;)
  1177. (files '(&amp;quot;arm-zephyr-eabi/lib&amp;quot;)))))
  1178. (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  1179. (synopsis &amp;quot;GCC for zephyr RTOS&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This GCC can be built like so.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr gcc-cross-sans-libc-arm-zephyr-eabi
  1180. /gnu/store/qmp8bzmwwimw0r6fh165hgfhkxkxilpj-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0-lib
  1181. /gnu/store/38rli0rbn7ksmym3wq99cr4p2cjdz4a7-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Great! We now have our stage-1 compiler.&lt;/p&gt;&lt;h2&gt;Newlib(-nano)&lt;/h2&gt;&lt;p&gt;The newlib package is quite straight forward (relatively).
  1182. It is mostly adding in the relevent configuration flags and patching
  1183. the files the &lt;code&gt;patch-shebangs&lt;/code&gt; phase missed.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; (define-public zephyr-newlib
  1184. (package
  1185. (name &amp;quot;zephyr-newlib&amp;quot;)
  1186. (version &amp;quot;3.3&amp;quot;)
  1187. (source (origin
  1188. (method git-fetch)
  1189. (uri (git-reference
  1190. (url &amp;quot;https://github.com/zephyrproject-rtos/newlib-cygwin&amp;quot;)
  1191. (commit &amp;quot;4e150303bcc1e44f4d90f3489a4417433980d5ff&amp;quot;)))
  1192. (sha256
  1193. (base32 &amp;quot;08qwjpj5jhpc3p7a5mbl7n6z7rav5yqlydqanm6nny42qpa8kxij&amp;quot;))))
  1194. (build-system gnu-build-system)
  1195. (arguments
  1196. `(#:out-of-source? #t
  1197. #:configure-flags '(&amp;quot;--target=arm-zephyr-eabi&amp;quot;
  1198. &amp;quot;--enable-newlib-io-long-long&amp;quot;
  1199. &amp;quot;--enable-newlib-io-float&amp;quot;
  1200. &amp;quot;--enable-newlib-io-c99-formats&amp;quot;
  1201. &amp;quot;--enable-newlib-retargetable-locking&amp;quot;
  1202. &amp;quot;--enable-newlib-lite-exit&amp;quot;
  1203. &amp;quot;--enable-newlib-multithread&amp;quot;
  1204. &amp;quot;--enable-newlib-register-fini&amp;quot;
  1205. &amp;quot;--enable-newlib-extra-sections&amp;quot;
  1206. &amp;quot;--disable-newlib-wide-orient&amp;quot;
  1207. &amp;quot;--disable-newlib-fseek-optimization&amp;quot;
  1208. &amp;quot;--disable-newlib-supplied-syscalls&amp;quot;
  1209. &amp;quot;--disable-newlib-target-optspace&amp;quot;
  1210. &amp;quot;--disable-nls&amp;quot;)
  1211. #:phases
  1212. (modify-phases %standard-phases
  1213. (add-after 'unpack 'fix-references-to-/bin/sh
  1214. (lambda _
  1215. (substitute* '(&amp;quot;libgloss/arm/cpu-init/Makefile.in&amp;quot;
  1216. &amp;quot;libgloss/arm/Makefile.in&amp;quot;
  1217. &amp;quot;libgloss/libnosys/Makefile.in&amp;quot;
  1218. &amp;quot;libgloss/Makefile.in&amp;quot;)
  1219. ((&amp;quot;/bin/sh&amp;quot;) (which &amp;quot;sh&amp;quot;)))
  1220. #t)))))
  1221. (native-inputs
  1222. `((&amp;quot;xbinutils&amp;quot; ,zephyr-binutils)
  1223. (&amp;quot;xgcc&amp;quot; ,gcc-arm-zephyr-eabi-12)
  1224. (&amp;quot;texinfo&amp;quot; ,texinfo)))
  1225. (home-page &amp;quot;https://www.sourceware.org/newlib/&amp;quot;)
  1226. (synopsis &amp;quot;C library for use on embedded systems&amp;quot;)
  1227. (description &amp;quot;Newlib is a C library intended for use on embedded
  1228. systems. It is a conglomeration of several library parts that are easily
  1229. usable on embedded products.&amp;quot;)
  1230. (license (license:non-copyleft
  1231. &amp;quot;https://www.sourceware.org/newlib/COPYING.NEWLIB&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the build.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr zephyr-newlib
  1232. /gnu/store/4lx37gga1jv3ckykrxsfgwy9slaamln4-zephyr-newlib-3.3&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Complete toolchain&lt;/h2&gt;&lt;p&gt;Note that the toolchain is &lt;em&gt;Mostly&lt;/em&gt; complete. libstdc++ does not build because
  1233. `arm-zephyr-eabi` is not `arm-none-eabi` so a dynamic link check is
  1234. performed/failed. I cannot figure out how crosstool-ng handles this.&lt;/p&gt;&lt;p&gt;Anyway, now that we’ve got the individual tools it’s time to create
  1235. our complete toolchain. For this we need to do some package transformations.
  1236. Because these transformations are must be done for every combination of
  1237. binutils/gcc/newlib, it is best to create a function which we can reuse for
  1238. every version of the SDK.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define (arm-zephyr-eabi-toolchain xgcc newlib version)
  1239. &amp;quot;Produce a cross-compiler zephyr toolchain package with the compiler XGCC and the C
  1240. library variant NEWLIB.&amp;quot;
  1241. (let ((newlib-with-xgcc (package (inherit newlib)
  1242. (native-inputs
  1243. (alist-replace &amp;quot;xgcc&amp;quot; (list xgcc)
  1244. (package-native-inputs newlib))))))
  1245. (package
  1246. (name (string-append &amp;quot;arm-zephyr-eabi&amp;quot;
  1247. (if (string=? (package-name newlib-with-xgcc)
  1248. &amp;quot;newlib-nano&amp;quot;)
  1249. &amp;quot;-nano&amp;quot; &amp;quot;&amp;quot;)
  1250. &amp;quot;-toolchain&amp;quot;))
  1251. (version version)
  1252. (source #f)
  1253. (build-system trivial-build-system)
  1254. (arguments
  1255. '(#:modules ((guix build union)
  1256. (guix build utils))
  1257. #:builder
  1258. (begin
  1259. (use-modules (ice-9 match)
  1260. (guix build union)
  1261. (guix build utils))
  1262. (let ((out (assoc-ref %outputs &amp;quot;out&amp;quot;)))
  1263. (mkdir-p out)
  1264. (match %build-inputs
  1265. (((names . directories) ...)
  1266. (union-build (string-append out &amp;quot;/arm-zephyr-eabi&amp;quot;)
  1267. directories)
  1268. #t))))))
  1269. (inputs
  1270. `((&amp;quot;binutils&amp;quot; ,zephyr-binutils)
  1271. (&amp;quot;gcc&amp;quot; ,xgcc)
  1272. (&amp;quot;newlib&amp;quot; ,newlib-with-xgcc)))
  1273. (synopsis &amp;quot;Complete GCC tool chain for ARM zephyrRTOS development&amp;quot;)
  1274. (description &amp;quot;This package provides a complete GCC tool chain for ARM
  1275. bare metal development with zephyr rtos. This includes the GCC arm-zephyr-eabi cross compiler
  1276. and newlib (or newlib-nano) as the C library. The supported programming
  1277. language is C.&amp;quot;)
  1278. (home-page (package-home-page xgcc))
  1279. (license (package-license xgcc)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function creates a special package which consists of the toolchain in a special directory hierarchy, i.e &lt;code&gt;arm-zephyr-eabi/&lt;/code&gt;.
  1280. Our complete toolchain definition looks like this.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-public arm-zephyr-eabi-toolchain-0.15.0
  1281. (arm-zephyr-eabi-toolchain
  1282. gcc-arm-zephyr-eabi-12
  1283. zephyr-newlib
  1284. &amp;quot;0.15.0&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To build:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr arm-zephyr-eabi-toolchain
  1285. /gnu/store/9jnanr27v6na5qq3dlgljraysn8r1sad-arm-zephyr-eabi-toolchain-0.15.0&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;Integrating with Zephyr Build System&lt;/h1&gt;&lt;p&gt;Zephyr uses CMake as it’s build system. It contains numerous CMake files in both the so-called &lt;code&gt;ZEPHYR_BASE&lt;/code&gt;,
  1286. the zephyr source code repository, as well as a handful in the SDK which help select the correct toolchain
  1287. for a given board.&lt;/p&gt;&lt;p&gt;There are standard locations the build system will look for the SDK. We are not
  1288. using any of them. Our SDK lives in the store, immutable forever. According to
  1289. &lt;a href=&quot;https://docs.zephyrproject.org/latest/develop/west/without-west.html&quot;&gt;this
  1290. webpage&lt;/a&gt;,
  1291. the variable &lt;code&gt;ZEPHYR_SDK_INSTALL_DIR&lt;/code&gt; needs to point to our custom spot.&lt;/p&gt;&lt;p&gt;We also need to grab the cmake files from the &lt;a href=&quot;https://github.com/zephyrproject-rtos/sdk-ng&quot;&gt;repository&lt;/a&gt; and create a file &lt;code&gt;sdk_version&lt;/code&gt; which
  1292. contains the version string &lt;code&gt;ZEPHYR_BASE&lt;/code&gt; uses to find a compatible SDK.&lt;/p&gt;&lt;p&gt;Along with the SDK proper we need to include a number of python packages required by the build system.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; (define-public zephyr-sdk
  1293. (package
  1294. (name &amp;quot;zephyr-sdk&amp;quot;)
  1295. (version &amp;quot;0.15.0&amp;quot;)
  1296. (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  1297. (source (origin (method git-fetch)
  1298. (uri (git-reference
  1299. (url &amp;quot;https://github.com/zephyrproject-rtos/sdk-ng&amp;quot;)
  1300. (commit &amp;quot;v0.15.0&amp;quot;)))
  1301. (file-name (git-file-name name version))
  1302. (sha256 (base32 &amp;quot;04gsvh20y820dkv5lrwppbj7w3wdqvd8hcanm8hl4wi907lwlmwi&amp;quot;))))
  1303. (build-system trivial-build-system)
  1304. (arguments
  1305. `(#:modules ((guix build union)
  1306. (guix build utils))
  1307. #:builder
  1308. (begin
  1309. (use-modules (guix build union)
  1310. (ice-9 match)
  1311. (guix build utils))
  1312. (let* ((out (assoc-ref %outputs &amp;quot;out&amp;quot;))
  1313. (cmake-scripts (string-append (assoc-ref %build-inputs &amp;quot;source&amp;quot;)
  1314. &amp;quot;/cmake&amp;quot;))
  1315. (sdk-out (string-append out &amp;quot;/zephyr-sdk-0.15.0&amp;quot;)))
  1316. (mkdir-p out)
  1317. (match (assoc-remove! %build-inputs &amp;quot;source&amp;quot;)
  1318. (((names . directories) ...)
  1319. (union-build sdk-out directories)))
  1320. (copy-recursively cmake-scripts
  1321. (string-append sdk-out &amp;quot;/cmake&amp;quot;))
  1322. (with-directory-excursion sdk-out
  1323. (call-with-output-file &amp;quot;sdk_version&amp;quot;
  1324. (lambda (p)
  1325. (format p &amp;quot;0.15.0&amp;quot;)))
  1326. #t)))))
  1327. (propagated-inputs
  1328. (list
  1329. arm-zephyr-eabi-toolchain-0.15.0
  1330. zephyr-binutils
  1331. dtc))
  1332. (native-search-paths
  1333. (list (search-path-specification
  1334. (variable &amp;quot;ZEPHYR_SDK_INSTALL_DIR&amp;quot;)
  1335. (files '(&amp;quot;&amp;quot;)))))
  1336. (synopsis &amp;quot;SDK for zephyrRTOS&amp;quot;)
  1337. (description &amp;quot;zephyr-sdk contains bundles a complete gcc toolchain as well
  1338. as host tools like dtc, openocd, qemu, and required python packages.&amp;quot;)
  1339. (license license:apsl2)))&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Testing&lt;/h2&gt;&lt;p&gt;In order to test we will need an environment with the SDK installed.
  1340. We can take advantage of &lt;code&gt;guix shell&lt;/code&gt; to avoid installing test packages into
  1341. our home environment. This way, if it causes problems, we can just exit the shell
  1342. and try again.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix shell -L guix-zephyr zephyr-sdk cmake ninja git&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;ZEPHYR_BASE&lt;/code&gt; can be cloned into a temporary workspace to test our toolchain
  1343. functionality (For now. Eventually we will need to create a package for
  1344. &lt;code&gt;zephyr-base&lt;/code&gt; that our guix zephyr-build-system can use).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mkdir /tmp/zephyr-project
  1345. cd /tmp/zephyr-project
  1346. git clone https://github.com/zephyrproject-rtos/zephyr
  1347. export ZEPHYR_BASE=/tmp/zephyr-project/zephyr&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In order to build for the test board (k64f in this case) we need to get a hold
  1348. of the vendor Hardware Abstraction Layers and CMSIS (These will also need to
  1349. become guix packages to allow the build system to compose modules).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone https://github.com/zephyrproject-rtos/hal_nxp &amp;amp;&amp;amp;
  1350. git clone https://github.com/zephyrproject-rtos/cmsis&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To inform the build system about this module we pass it in with &lt;code&gt;-DZEPHYR_MODULES=&lt;/code&gt; which is
  1351. a semicolon separated list of paths containing a module.yml file.&lt;/p&gt;&lt;p&gt;To build the hello world sample we use the following incantation.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cmake -Bbuild $ZEPHYR_BASE/samples/hello_world \
  1352. -GNinja \
  1353. -DBOARD=frdm_k64f \
  1354. -DBUILD_VERSION=3.1.0 \
  1355. -DZEPHYR_MODULES=&amp;quot;/tmp/zephyr-project/hal_nxp;/tmp/zephyr-project/cmsis&amp;quot; \
  1356. &amp;amp;&amp;amp; ninja -Cbuild&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything is set up correctly we will end up with a &lt;code&gt;./build&lt;/code&gt;
  1357. directory with all our build artifacts. The SDK is installed correctly!&lt;/p&gt;</summary></entry><entry><title>Nextcloud and Guix System Server</title><id>https://gnucode.me/nextcloud-and-guix-system-server.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-02-22T17:00:00Z</updated><link href="https://gnucode.me/nextcloud-and-guix-system-server.html" rel="alternate" /><summary type="html">&lt;p&gt;So I have wanted to run &lt;a href=&quot;https://nextcloud.com/&quot;&gt;nextcloud&lt;/a&gt; for a while now. In my humble opinion, guix
  1358. system makes maintaining websites super easy, so I would prefer to run nextcloud
  1359. on guix system. Unfortunately, nextcloud will NOT be packaged in guix anytime
  1360. soon for two reasons:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Guix does not currently have a php build system or any php packages, though
  1361. there is a 80% completed &lt;a href=&quot;https://issues.guix.gnu.org/42338&quot;&gt;work-in-progress issue.&lt;/a&gt; So the php bits of nextcloud
  1362. cannot be packaged properly.&lt;/li&gt;&lt;li&gt;Nextcloud has a lot of javascript dependencies, and javascript is &lt;a href=&quot;https://dustycloud.org/blog/javascript-packaging-dystopia/&quot;&gt;notoriously
  1363. hard to package for guix.&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;It seems like the easiest way to currently run nextcloud on guix system is by
  1364. using the &lt;a href=&quot;https://github.com/nextcloud/all-in-one&quot;&gt;all in one docker image.&lt;/a&gt; Please consider this a guide to set up
  1365. running nextcloud on guix system via a linode, which currently costs me about $5
  1366. per month.&lt;/p&gt;&lt;p&gt;Note, that while this is the easiest method to run nextcloud, apparently this
  1367. all in one docker image has some security issues:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;The AIO image mounts the Docker socket, which is a security risk since it allows
  1368. full access to other container as well as running any new container. It’s a bad
  1369. idea and should be avoided.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;tl;dr Here are the 6 simple steps that you need to do:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Set up a &lt;a href=&quot;https://guix.gnu.org/en/cookbook/en/html_node/Running-Guix-on-a-Linode-Server.html#Running-Guix-on-a-Linode-Server&quot;&gt;linode guix system server.&lt;/a&gt; &lt;code&gt;info &amp;quot;Guix Cookbook&amp;quot; RET i linode RET&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Buy a domain name. I use &lt;a href=&quot;https://hover.com&quot;&gt;hover.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Point your domain name at your linode IP address.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Set up a basic nginx static website without encryption. This means that you
  1370. don’t want to define &lt;code&gt;(service certbot-service-type)&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo mkdir -p /srv/www/html/yourdomainname.com
  1371. # the command I did was this:
  1372. sudo mkdir -p /srv/www/html/the-nx.com
  1373. sudo chgrp -R users /srv
  1374. sudo chmod -R g+rwx /srv&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Inside your newly created directory (&lt;em&gt;srv/www/html/yourdomainname.com&lt;/em&gt;), put
  1375. a simple HTML file and call it “index.html”. You could use this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
  1376. &amp;lt;html class=&amp;quot;no-js&amp;quot; lang=&amp;quot;&amp;quot;&amp;gt;
  1377. &amp;lt;head&amp;gt;
  1378. &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
  1379. &amp;lt;meta http-equiv=&amp;quot;x-ua-compatible&amp;quot; content=&amp;quot;ie=edge&amp;quot;&amp;gt;
  1380. &amp;lt;title&amp;gt;the nx&amp;lt;/title&amp;gt;
  1381. &amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;&amp;quot;&amp;gt;
  1382. &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1&amp;quot;&amp;gt;
  1383. &amp;lt;link rel=&amp;quot;apple-touch-icon&amp;quot; href=&amp;quot;/apple-touch-icon.png&amp;quot;&amp;gt;
  1384. &amp;lt;/head&amp;gt;
  1385. &amp;lt;body&amp;gt;
  1386. &amp;lt;!--[if lt IE 8]&amp;gt;
  1387. &amp;lt;p class=&amp;quot;browserupgrade&amp;quot;&amp;gt;
  1388. You are using an &amp;lt;strong&amp;gt;outdated&amp;lt;/strong&amp;gt; browser. Please
  1389. &amp;lt;a href=&amp;quot;http://browsehappy.com/&amp;quot;&amp;gt;upgrade your browser&amp;lt;/a&amp;gt; to improve
  1390. your experience.
  1391. &amp;lt;/p&amp;gt;
  1392. &amp;lt;![endif]--&amp;gt;
  1393. &amp;lt;p&amp;gt;Hello!&amp;lt;/p&amp;gt;
  1394. &amp;lt;/body&amp;gt;
  1395. &amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now set up a basic nginx configuration for a static website without
  1396. encryption. It will end up looking something like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service nginx-service-type
  1397. (nginx-configuration
  1398. (server-blocks
  1399. (list
  1400. (nginx-server-configuration
  1401. (server-name '(&amp;quot;the-nx.com&amp;quot;))
  1402. (listen (list &amp;quot;80&amp;quot; &amp;quot;[::]:80&amp;quot;))
  1403. (root &amp;quot;/srv/www/html/the-nx.com&amp;quot;))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you need to reconfigure so that the &lt;code&gt;nginx&lt;/code&gt; user is created:&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo guix system reconfigure config.scm&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Now, nginx is running, but you will probably need to give nginx access to
  1404. read the files in your /srv directory.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo chown -R nginx /srv
  1405. sudo chmod -R u-rwx /srv&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Open up a web browser and go to &lt;a href=&quot;http://yourdomainname.com&quot;&gt;http://yourdomainname.com&lt;/a&gt; and check to see
  1406. that you see a basic website.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Now you need to turn your basic static website, into a site that has https
  1407. support. Now you need to edit your nginx config and add in a certbot config:&lt;/p&gt;&lt;p&gt;Before your &lt;code&gt;(operating-system ...)&lt;/code&gt; declartion, define this bit of code:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define %nginx-deploy-hook
  1408. (program-file
  1409. &amp;quot;nginx-deploy-hook&amp;quot;
  1410. #~(let ((pid (call-with-input-file &amp;quot;/var/run/nginx/pid&amp;quot; read)))
  1411. (kill pid SIGHUP))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Also make sure that you add in a &lt;code&gt;certbot&lt;/code&gt; service and a modified &lt;code&gt;nginx&lt;/code&gt;
  1412. service that look like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service certbot-service-type
  1413. (certbot-configuration
  1414. (email &amp;quot;mysubscriptions@member.fsf.org&amp;quot;)
  1415. (webroot &amp;quot;/srv/www/&amp;quot;)
  1416. (certificates
  1417. (list
  1418. (certificate-configuration
  1419. (name &amp;quot;the-nx.com&amp;quot;)
  1420. (domains '(&amp;quot;the-nx.com&amp;quot; &amp;quot;www.the-nx.com&amp;quot;))
  1421. (deploy-hook %nginx-deploy-hook))))))
  1422. (service nginx-service-type
  1423. (nginx-configuration
  1424. (server-blocks
  1425. (list
  1426. (nginx-server-configuration
  1427. (server-name '(&amp;quot;the-nx.com&amp;quot;))
  1428. (listen (list &amp;quot;80&amp;quot;
  1429. &amp;quot;443 ssl http2&amp;quot;
  1430. &amp;quot;[::]:80&amp;quot;
  1431. &amp;quot;[::80]:443 ssl http2&amp;quot;))
  1432. (root &amp;quot;/srv/www/html/the-nx.com&amp;quot;)
  1433. (ssl-certificate &amp;quot;/etc/letsencrypt/live/the-nx.com/fullchain.pem&amp;quot;)
  1434. (ssl-certificate-key &amp;quot;/etc/letsencrypt/live/the-nx.com/privkey.pem&amp;quot;)
  1435. (locations
  1436. (list
  1437. (nginx-location-configuration ;; for certbot
  1438. (uri &amp;quot;/.well-known&amp;quot;)
  1439. (body (list &amp;quot;root /srv/www;&amp;quot;))))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we will have to reconfigure again to set up certbot:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure config.scm
  1440. # tell certbot to set up our certificates
  1441. sudo /var/lib/certbot/renew-certificates&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you should be able to go to &lt;a href=&quot;https://yourdomainname.com&quot;&gt;https://yourdomainname.com&lt;/a&gt; and see your site
  1442. in glorious encrypted mode!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Modify your guix config based on my &lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/the-nx.com-current-config.scm&quot;&gt;the-nx.com-current-config.scm&lt;/a&gt;.
  1443. You will need to enable these services &lt;code&gt;(dbus-service)&lt;/code&gt;, &lt;code&gt;(service docker-service-type)&lt;/code&gt;, &lt;code&gt;(elogind service)&lt;/code&gt;, &lt;code&gt;(service certbot-service-type)&lt;/code&gt;,
  1444. and &lt;code&gt;(service nginx-service-type)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I just ran this command, and my local nextcloud just started working.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo docker run \
  1445. --sig-proxy=false \
  1446. --name nextcloud-aio-mastercontainer \
  1447. --restart always \
  1448. --publish 80:80 \
  1449. --publish 8080:8080 \
  1450. --publish 8443:8443 \
  1451. --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
  1452. --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  1453. nextcloud/all-in-one:latest&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following is the same quick guide as above, but has more details:&lt;/p&gt;&lt;p&gt;I decided to create a new linode image following the linode cookbook guide, and
  1454. I noticed a tiny error in the guide:&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo apt-get install gpg&lt;/code&gt; failed. It worked after I ran &lt;code&gt;sudo apt-get update&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Also the basic config example needs to migrate to the new &amp;lt;swap-space&amp;gt; record.
  1455. It gave me this warning message:&lt;/p&gt;&lt;p&gt;/root/config.scm:11:0: warning: List elements of the field ’swap-devices’ should
  1456. now use the &amp;lt;swap-space&amp;gt; record, as the old method is deprecated. See “(guix)
  1457. operating-system Reference” for more details.&lt;/p&gt;&lt;p&gt;The cookbook guide also should probably mention that you may need to login to
  1458. the server for the first time using linode’s weblish, and set up the root passwd
  1459. with &lt;code&gt;passwd&lt;/code&gt;. Then set up your user password with &lt;code&gt;passwd &amp;lt;username&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Now that we have a basic site set up, let’s set up certbot and the nginx services:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service certbot-service-type
  1460. (certbot-configuration
  1461. (email &amp;quot;mysubscriptions@member.fsf.org&amp;quot;)
  1462. (webroot &amp;quot;/srv/www/&amp;quot;)
  1463. (certificates
  1464. (list
  1465. (certificate-configuration
  1466. (name &amp;quot;the-nx.com&amp;quot;)
  1467. (domains '(&amp;quot;the-nx.com&amp;quot; &amp;quot;www.the-nx.com&amp;quot;))
  1468. (deploy-hook %nginx-deploy-hook))))))
  1469. (nginx-configuration
  1470. (server-blocks
  1471. (list
  1472. (nginx-server-configuration
  1473. (server-name '(&amp;quot;the-nx.com&amp;quot;))
  1474. (listen (list &amp;quot;80&amp;quot;
  1475. &amp;quot;443 ssl http2&amp;quot;
  1476. ;;&amp;quot;[::]:80&amp;quot;
  1477. ;;&amp;quot;[::80]:443 ssl http2&amp;quot;
  1478. ))
  1479. (root &amp;quot;/srv/www/html/the-nx.com&amp;quot;)
  1480. (ssl-certificate &amp;quot;/etc/letsencrypt/live/the-nx.com/fullchain.pem&amp;quot;)
  1481. (ssl-certificate-key &amp;quot;/etc/letsencrypt/live/the-nx.com/privkey.pem&amp;quot;)
  1482. (locations
  1483. (list
  1484. (nginx-location-configuration ;; for certbot
  1485. (uri &amp;quot;/.well-known&amp;quot;)
  1486. (body (list &amp;quot;root /srv/www;&amp;quot;)))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s reconfigure and get a certbot certificate. &lt;code&gt;ssh&lt;/code&gt; into the-nx.com and
  1487. run these commands:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure the-nx.com-current-config.scm
  1488. # tell certbot to set up our certificates
  1489. sudo /var/lib/certbot/renew-certificates&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now my server has a valid certificate. It is time change the nginx
  1490. configuration to proxy incoming requests to the docker all in one image.&lt;/p&gt;&lt;p&gt;Ok, maybe I can use sexpressions to tell nginx to redirect all incoming traffic
  1491. to &lt;code&gt;the-nx.com&lt;/code&gt; to the docker nextcloud image:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(nginx-location-configuration
  1492. (uri &amp;quot;/&amp;quot;)
  1493. (body
  1494. (list
  1495. &amp;quot;proxy_pass http://127.0.0.1:9000;\n&amp;quot;
  1496. &amp;quot;proxy_set_header X-Real-IP $remote_addr;\n&amp;quot;
  1497. &amp;quot;proxy_set_header Host $host;\n&amp;quot;
  1498. &amp;quot;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n&amp;quot;
  1499. &amp;quot;client_max_body_size 0;\n&amp;quot;
  1500. &amp;quot;# Websocket\n&amp;quot;
  1501. &amp;quot;proxy_http_version 1.1;\n&amp;quot;
  1502. &amp;quot;proxy_set_header Upgrade $http_upgrade;\n&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I am going to deploy this image, and take a look at the generated nginx
  1503. configuration file. I ran this command on my T400 laptop:&lt;/p&gt;&lt;p&gt;&lt;code&gt;guix deploy the-nx.com-current-config.scm&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Well, that’s super annoying. I do not know which nginx.conf file is the right
  1504. one:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find /gnu/store -name '*nginx.conf'
  1505. /gnu/store/7m1ygzqk6njn5mywqmhwbydbb2z4b9li-nginx.conf
  1506. /gnu/store/0gcfj61q4943h94jdqq7i9y0a0v9jr9q-nginx.conf
  1507. /gnu/store/4mzrp39w5i4v94kxf98gxc13ws79l88n-nginx.conf
  1508. /gnu/store/0nia2iqfw63ziasibbgq321wr9b3152n-nginx.conf
  1509. /gnu/store/pf8d0sj1yf9b2ndsbc61yj3h6rp4pck2-nginx.conf
  1510. /gnu/store/9nra62v41wsk08xf3msw5a1z35gji2gx-nginx-1.23.2/share/nginx/conf/nginx.conf
  1511. /gnu/store/4b1szfyn0snwzf3lm1snvaapk6diz3yq-nginx.conf
  1512. /gnu/store/fv5rg3nf5999vyg6qvp4sbgjysnkn1fc-nginx.conf
  1513. /gnu/store/vmjwj2zwblcz4wx2whsmxdfc7zxcgjh5-nginx.conf
  1514. /gnu/store/n3m2lihq9cjm6mxdln57q5nrbjgz53s6-nginx.conf
  1515. /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/nginx.conf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I guess I will reboot, run &lt;code&gt;guix system delete-generations&lt;/code&gt; and &lt;code&gt;guix gc&lt;/code&gt;, and
  1516. run the above command again:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find /gnu/store -name '*nginx.conf'
  1517. /gnu/store/7m1ygzqk6njn5mywqmhwbydbb2z4b9li-nginx.conf
  1518. /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/nginx.conf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that looks promising. Let's check out my nginx.conf file.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/i2mzdhg8wlbxv7iza8y4qk5v0vmvp27q-nginx.conf
  1519. user nginx nginx;
  1520. pid /var/run/nginx/pid;
  1521. error_log /var/log/nginx/error.log info;
  1522. events { }
  1523. http {
  1524. client_body_temp_path /var/run/nginx/client_body_temp;
  1525. proxy_temp_path /var/run/nginx/proxy_temp;
  1526. fastcgi_temp_path /var/run/nginx/fastcgi_temp;
  1527. uwsgi_temp_path /var/run/nginx/uwsgi_temp;
  1528. scgi_temp_path /var/run/nginx/scgi_temp;
  1529. access_log /var/log/nginx/access.log;
  1530. include /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/mime.types;
  1531. server {
  1532. listen 443 ssl http2;
  1533. server_name the-nx.com ;
  1534. ssl_certificate /etc/letsencrypt/live/the-nx.com/fullchain.pem;
  1535. ssl_certificate_key /etc/letsencrypt/live/the-nx.com/privkey.pem;
  1536. root /srv/www/html/the-nx.com;
  1537. index index.html ;
  1538. server_tokens off;
  1539. location /.well-known {
  1540. root /srv/www;
  1541. }
  1542. location / {
  1543. proxy_pass http://127.0.0.1:9000;
  1544. proxy_set_header X-Real-IP $remote_addr;
  1545. proxy_set_header Host $host;
  1546. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  1547. client_max_body_size 0;
  1548. # Websocket
  1549. proxy_http_version 1.1;
  1550. proxy_set_header Upgrade $http_upgrade;
  1551. }
  1552. }
  1553. server {
  1554. listen 80;
  1555. listen [::]:80;
  1556. server_name the-nx.com www.the-nx.com ;
  1557. root /srv/http;
  1558. index index.html ;
  1559. server_tokens off;
  1560. location /.well-known {
  1561. root /srv/www/;
  1562. }
  1563. location / {
  1564. return 301 https://$host$request_uri;
  1565. }
  1566. }
  1567. }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The generated configuration seems pretty wonky, and I am suprised that nginx is
  1568. still running, but it is still running. And I suppose that it should work.&lt;/p&gt;&lt;p&gt;I was able to get nextcloud to start with this command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo docker run --sig-proxy=false --name nextcloud-aio-mastercontainer \
  1569. --restart always \
  1570. --publish 8080:8080 \
  1571. -e APACHE_PORT=9000 \
  1572. --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
  1573. --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  1574. nextcloud/all-in-one:latest&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now I can login at the-nx.com:8080 and configure various stuff. Also I really
  1575. need to set up a firewall. That’s probably a really good idea. Also what’s nice
  1576. about this docker image is that it will start itself if you update the guix
  1577. system server and reboot.&lt;/p&gt;&lt;p&gt;MORE BONUS CONTENT:&lt;/p&gt;&lt;p&gt;If you see this blog post, and you decide to set up your nextcloud on a guix
  1578. system server, and if your nginx config doesn’t seem to be proxying requests to
  1579. your docker container, then you may follow these steps to delete the docker
  1580. image and start over:&lt;/p&gt;&lt;p&gt;This &lt;a href=&quot;https://help.nextcloud.com/t/aio-this-site-can-t-provide-a-secure-connection/128478/5&quot;&gt;page&lt;/a&gt; has some good commands for deleting the docker image and starting
  1581. over:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo docker stop nextcloud-aio-mastercontainer &amp;amp;&amp;amp; \\
  1582. sudo docker rm nextcloud-aio-mastercontainer &amp;amp;&amp;amp; \\
  1583. sudo docker container prune -f &amp;amp;&amp;amp; \\
  1584. sudo docker volume prune -f &amp;amp;&amp;amp; \\
  1585. sudo docker pull nextcloud/all-in-one:latest&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so it looks like the nextcloud all in one documentation has a &lt;a href=&quot;https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md&quot;&gt;page&lt;/a&gt; for
  1586. understanding the reverse proxy.&lt;/p&gt;&lt;p&gt;It would also be nice to get my nextcloud image to sync my contacts. I probably just need to add in another nginx
  1587. location line for that. That will be a project for another day.&lt;/p&gt;</summary></entry><entry><title>Upgrading the PinePhone</title><id>https://gnucode.me/upgrading-the-pinephone.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-02-04T18:00:00Z</updated><link href="https://gnucode.me/upgrading-the-pinephone.html" rel="alternate" /><summary type="html">&lt;p&gt;So I have been running this to upgrade the pinephone for a while now:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apk upgrade
  1588. # apk update
  1589. # apk upgrade
  1590. # apk update&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Today, when I rebooted I got a message that said that my pinephone’s version was
  1591. no longer supported. I should &lt;a href=&quot;https://postmarketos.org/upgrade&quot;&gt;upgrade&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;I figured that I will probably do this again, so I might as well write down the
  1592. steps for how to do the upgrade.&lt;/p&gt;&lt;p&gt;Before I really get started in this, I want to get set up in the &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Matrix_and_IRC&quot;&gt;matrix chat
  1593. room.&lt;/a&gt; I used the web based interface for the matrix chat. It had me create an
  1594. online account, and verify my email address, then I could talk in the matrix
  1595. channel. That was easy, moving onto the next step.&lt;/p&gt;&lt;p&gt;First install &lt;code&gt;postmarketos-release-upgrade&lt;/code&gt; package:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apk add postmarketos-release-upgrade&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next I want to create a &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Backup_and_restore_your_data&quot;&gt;backup&lt;/a&gt;, of the pinephone incase the upgrade fails or
  1596. breaks the phone and I have to install postmarketOS.&lt;/p&gt;&lt;p&gt;Ok, in the pinephone’s terminal, start the sshd daemon:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo service sshd start&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So possibly the best way to upgrade your pinephone is to connect the phone to
  1597. your laptop/desktop via a usb cord and enable &lt;a href=&quot;https://wiki.postmarketos.org/wiki/USB_Internet#Linux&quot;&gt;usb internet.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Apparently after you connect the phone to your host machine, you should be able
  1598. to run:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ssh user@172.16.42.1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That didn’t work. And it is quickly looking to me like the usb internet upgrade
  1599. option is NOT going to work. Or rather, it will work, but it will take me a lot
  1600. of time to get it to work.&lt;/p&gt;&lt;p&gt;So instead of using the usb internet upgrade option, I will try connecting the
  1601. pinephone to the internet via an ethernet cord (I personally disabled the wifi
  1602. on the phone to try to save power). Then I will make a backup of the pinephone.&lt;/p&gt;&lt;p&gt;Ok, now that I have my phinephone connected to an ethernet port, I used my
  1603. laptop to ssh into the pinephone.&lt;/p&gt;&lt;p&gt;I found my pinephone’s ip address via running this on the pinephone’s terminal:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ip a&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so the looking at eth0: the pinephone’s ip address is:&lt;/p&gt;&lt;p&gt;SOME.IP.Address.04&lt;/p&gt;&lt;p&gt;So, I can now ssh into the phone via:&lt;/p&gt;&lt;p&gt;&lt;code&gt;ssh user@SOME.IP.Address.04&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Since I have ssh-agent set up, lets set up ssh key login:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ssh-copy-id user@SOME.IP.ADDRESS.04&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s create a backup on my host comptuter (laptop):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mkdir ~/postmarket-os-backup
  1604. rsync -avz --exclude=.cache user@SOME.IP.ADDRESS.04:/home/user/ .
  1605. fish: Unknown command: rsync
  1606. fish:
  1607. rsync --server --sender -vlogDtprze.iLsfxCIvu . /home/user/
  1608. ^
  1609. rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
  1610. rsync error: error in rsync protocol data stream (code 12) at io.c(231) [Receiver=3.2.7]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that seems like a weird problem. Let’s go join the fish irc channel.&lt;/p&gt;&lt;p&gt;Well the channel is here:&lt;/p&gt;&lt;p&gt;&lt;code&gt;#fish&lt;/code&gt; at irc.oftc.net&lt;/p&gt;&lt;p&gt;I can find out how to connect via going to oftc.net. They ever have a &lt;a href=&quot;https://webchat.oftc.net/&quot;&gt;webchat&lt;/a&gt;.
  1611. That makes it easy. Just put in a goofy nickname and you are in the chat room!&lt;/p&gt;&lt;p&gt;It took the fish people a while to respond, so I also asked in the &lt;code&gt;#guix&lt;/code&gt;
  1612. channel, while I was waiting. A guix user said that I should try this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix shell --network -C coreutils rsync openssh-sans-x&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then run my rsync command.&lt;/p&gt;&lt;p&gt;That didn’t work, but then the &lt;code&gt;#fish&lt;/code&gt; people just asked me if I have rsync
  1613. installed on my pinephone…I didn’t realize I needed it installed on both
  1614. devices.&lt;/p&gt;&lt;p&gt;So let’s do that on the pinephone: &lt;code&gt;sudo apk add rsync&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Let’s try this again. On my laptop I ran this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;rsync -avz --exclude=.cache user@SOME.IP.ADDRESS.04:/home/user/ ~/postmarket-os-backup&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok that worked!&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Upgrade_to_a_newer_postmarketOS_release&quot;&gt;postmarketOS wiki&lt;/a&gt; recommends that I use tmux or screen to update the
  1615. pinephone, in case the ssh connection breaks. Well I believe that I have tried
  1616. updating the pinephone before using just an ssh connection, and the ssh
  1617. connection dropped. I did not know if they phone was done updating or if it had
  1618. just died. So I forcefully shut off the device, and it failed to boot. Fun
  1619. times.&lt;/p&gt;&lt;p&gt;Well let’s go ask in the postmarketOS irc channel or &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Category:Community&quot;&gt;matrix&lt;/a&gt; and ask about using
  1620. tmux or screen. How does it make sure that the ssh connection does not break? I
  1621. can also check out the archlinux wiki. Also it seems as if tmux is more user
  1622. friendly, so I will check out the &lt;a href=&quot;https://wiki.archlinux.org/title/Tmux&quot;&gt;tmux&lt;/a&gt; page to learn more about it.&lt;/p&gt;&lt;p&gt;Well let’s go ahead and install tmux on my laptop: &lt;code&gt;guix install tmux&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Let’s try to run an ssh connection on the pinephone via tmux. I think this
  1623. is how you do it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;tmux
  1624. ssh user@&amp;lt;IP address of the pinephone&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well I asked in the postmarketOS irc channel why they reccommend using tmux in
  1625. case the ssh connection drops, and this is the answer that I got:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;if you use tmux, you can just restore your tmux session if the ssh connection drops
  1626. and the command will still be running in there&lt;/p&gt;&lt;p&gt;run tmux
  1627. then if the connection drops
  1628. tmux list-sessions
  1629. and then
  1630. tmux attach-session
  1631. I think&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Then if the ssh connection gets dropped, I can open up a new terminal and do
  1632. this &lt;code&gt;tmux attach&lt;/code&gt;, and I will be right back where I was. This &lt;a href=&quot;https://www.youtube.com/watch?v=JQ0yDCVu44E&quot;&gt;video&lt;/a&gt; explains
  1633. that. That is pretty awesome!&lt;/p&gt;&lt;p&gt;Here &lt;a href=&quot;https://mutelight.org/practical-tmux&quot;&gt;are&lt;/a&gt; &lt;a href=&quot;https://blog.hawkhost.com/2010/06/28/tmux-the-terminal-multiplexer/&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;https://blog.hawkhost.com/2010/07/02/tmux-%E2%80%93-the-terminal-multiplexer-part-2&quot;&gt;tmux&lt;/a&gt; &lt;a href=&quot;https://man.archlinux.org/man/tmux.1&quot;&gt;resources.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Next, I ran the following to update the pinephone:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;tmux
  1634. ssh user@&amp;lt;my Pinephone IP address&amp;gt;
  1635. postmarketos-release-upgrade&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since, my phinephone had an ethernet connection, the upgrade process was over
  1636. inside 5 minutes, and the phone rebooted itself. Nice work postmarketos
  1637. developers!&lt;/p&gt;</summary></entry><entry><title>Setting up a Firewall</title><id>https://gnucode.me/setting-up-a-firewall.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-01-23T13:00:00Z</updated><link href="https://gnucode.me/setting-up-a-firewall.html" rel="alternate" /><summary type="html">&lt;p&gt;Edit: Feb 12: The below firewall does NOT work. I currently do NOT use a
  1638. firewall on my servers.&lt;/p&gt;&lt;p&gt;So my guix system servers have been running without a firewall. I have decided
  1639. to actually fix that. Unfortunately, OpenBSD’s pf does not work on linux. It
  1640. seems like the best packaged firewall for GNU Guix System is currently provided
  1641. by the netfilter service. Luckily Guix’s default server provides a good basic
  1642. configuration for enabling ssh access to the machine. That configuration looks
  1643. like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;table inet filter {
  1644. chain input {
  1645. type filter hook input priority 0; policy drop;
  1646. # early drop of invalid connections
  1647. ct state invalid drop
  1648. # allow established/related connections
  1649. ct state { established, related } accept
  1650. # allow from loopback
  1651. iifname lo accept
  1652. # allow icmp
  1653. ip protocol icmp accept
  1654. ip6 nexthdr icmpv6 accept
  1655. # allow ssh
  1656. tcp dport ssh accept
  1657. # reject everything else
  1658. reject with icmpx type port-unreachable
  1659. }
  1660. chain forward {
  1661. type filter hook forward priority 0; policy drop;
  1662. }
  1663. chain output {
  1664. type filter hook output priority 0; policy accept;
  1665. }
  1666. }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So it looks like I just need to add in policies just after the &lt;code&gt;#allow ssh&lt;/code&gt;
  1667. line.&lt;/p&gt;&lt;p&gt;It seems like the easiest way to test this service out, is to first, &lt;code&gt;guix install nft&lt;/code&gt;, then put your configuration into a file. Then load in those
  1668. firewall rules via &lt;code&gt;sudo nft -f nftables.conf&lt;/code&gt;. If those rules end up breaking
  1669. things, you can revert the firewall to allow everything via &lt;code&gt;sudo nft flush ruleset&lt;/code&gt;. You can also list the current ruleset via &lt;code&gt;sudo nft list ruleset&lt;/code&gt;.
  1670. You can also check the syntax in &lt;code&gt;nftables.conf&lt;/code&gt; via &lt;code&gt;sudo nft -cf nftable.conf&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Well I had a firewall working fairly well. I tested the firewall rules via
  1671. &lt;code&gt;sudo nft -f nftables-lamora.conf&lt;/code&gt;, and it worked really well. But this scheme
  1672. code seemed to break everything on the server. Now, I can’t login to lamora and
  1673. the websites it hosts are not working.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service nftables-service-type
  1674. (nftables-configuration
  1675. (ruleset
  1676. (mixed-text-file &amp;quot;nftables.conf&amp;quot;
  1677. &amp;quot;./nftables-lamora.conf&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I reached out to linode support, and I am able to boot the machine in a rescue
  1678. image, which is pretty awesome. From there I might be able to mount the
  1679. &lt;code&gt;/dev/sda&lt;/code&gt; drive such that &lt;code&gt;/gnu/store&lt;/code&gt; is set up properly. But I think that is
  1680. pretty much beyond me. Too much work to get correct. So instead, I shall start
  1681. from scratch I suppose. :(&lt;/p&gt;&lt;p&gt;What if I had just run,&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mount /dev/sda /mnt
  1682. chroot /mnt
  1683. sudo guix system roll-back&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That might have worked. But it also might not have and it might have just taken me
  1684. longer too.&lt;/p&gt;&lt;p&gt;Looks like I have a small basic guix image lying around that I can tell linode
  1685. to use. Let’s try that.&lt;/p&gt;&lt;p&gt;Well that caused a kernel panic. That didn’t work. Probably because I told
  1686. linode to set the root password, and linode doesn’t know how to mess with guix
  1687. system?&lt;/p&gt;&lt;p&gt;So I whiped my linode server, and started over. And it looks like
  1688. I need to modify the current cookbook entry about running guix system on linode via
  1689. adding in&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo apt-get update&lt;/code&gt;, then &lt;code&gt;sudo apt-get install gpg&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Here are some of the commands that I used to set up my new linode server. It's on the
  1690. same IP address. It's currently hosting gnucode.me.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;wget https://notabug.org/jbranso/linode-guix-system-configuration/raw/master/gnucode.me-initial-config.scm
  1691. mount /dev/sdc /mnt
  1692. sudo guix system reconfigure locke-lamora-initial-config.scm
  1693. guix install git
  1694. mkdir -p ~/prog/gnu/guix/guix-config/
  1695. cd ~/prog/gnu/guix/guix-config/
  1696. git clone https://notabug.org/jbranso/linode-guix-system-configuration
  1697. cd ../
  1698. git clone https://git.sr.ht/~whereiseveryone/guixrus
  1699. sudo mkdir -p /srv/www/html&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I need to git clone my various static websites on the server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /srv/www/html
  1700. sudo git clone https://notabug.org/jbranso/gnucode.me.git
  1701. sudo git clone https://notabug.org/jbranso/propernaming.git
  1702. sudo git clone https://notabug.org/jbranso/gnu-hurd.com.git
  1703. sudo mv propernaming propernaming.org&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So I believe that I need to chmod the files in /srv/www/html, so that nginx can
  1704. actually serve them. Unfortunately, I cannot do a &lt;code&gt;sudo chown -R nginx /srv&lt;/code&gt;,
  1705. because my current guix system does not have an nginx user yet. But I believe
  1706. that I can still reconfigure the system, even if nginx will not be able to serve
  1707. the html files. After I have reconfigured, then I should be able chown the owner
  1708. of /srv to nginx. In the end I actually just did a &lt;code&gt;cd /srv; sudo chmod -R o+r *&lt;/code&gt; and just made every file readable by everyone. That sort of violates the
  1709. principle of least privledge, oh well.&lt;/p&gt;&lt;p&gt;Now that I have made some modifications to my gnucode.me-current-config.scm that
  1710. comments out various certificate files that are not there yet, I can attempt to
  1711. reconfigure on the server:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd prog/gnu/guix/guix-config/linode-guix-system-configuration/
  1712. sudo guix system reconfigure gnucode.me-current-config.scm
  1713. guix system: error: aborting reconfiguration because commit
  1714. 9fe5b490df83ff32e2e0a604bf636eca48b9e240 of channel 'guix' is not a descendant
  1715. of 900d33527c9286a811f064d4bb8f4a9b18d1db0b&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well let’s try this updating everything. And I believe that you need to do a
  1716. guix pull as root at least once.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;su
  1717. guix pull;
  1718. exit;
  1719. guix pull;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oh yeah, I also need to power down my linode, delete the debian partition, and
  1720. resize the guix partition to full size.&lt;/p&gt;&lt;p&gt;Now I believe that I cannot reconfigure my server with the current
  1721. &lt;code&gt;gnucode.me-current-config.scm&lt;/code&gt;, because nginx will fail to start because the
  1722. letsencrypt scripts are not there yet. So I need to modify the nginx bits before
  1723. I can start the service. I also decided to set up &lt;code&gt;guix deploy&lt;/code&gt; on my gnucode.me
  1724. machine, so that reconfiguring the remote server is faster.&lt;/p&gt;&lt;p&gt;Ok, so I have my current-config for gnucode.me deployed. Geez, guix deploy is
  1725. sooo super fast! And all you need to do is to set up ssh-agent and customize a
  1726. deployment list. I set up ssh-agent via my &lt;code&gt;.bash_profile&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat .bash_profile | grep eval -A 1
  1727. if [[ -z $DISPLAY ]] &amp;amp;&amp;amp; [[ $(tty) = /dev/tty6 ]]; then
  1728. eval `ssh-agent -s`
  1729. ssh-add
  1730. exec dbus-run-session sway
  1731. fi&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now all you need to do is customize this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(list (machine
  1732. (operating-system %system)
  1733. (environment managed-host-environment-type)
  1734. (configuration (machine-ssh-configuration
  1735. (host-name &amp;quot;45.56.66.20&amp;quot;)
  1736. (system &amp;quot;x86_64-linux&amp;quot;)
  1737. (user &amp;quot;joshua&amp;quot;)
  1738. (identity &amp;quot;~/.ssh/id_rsa&amp;quot;)
  1739. (host-key &amp;quot;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJgL0hBTWmCVGGvNJYa+YS+fEXs89v0GbdkQ+M+LdZlf root@(none)&amp;quot;)
  1740. (port 63355)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The port is the ssh port. And the ssh-ed25519 is found on your remote server’s
  1741. &lt;code&gt;etc/ssh/ssh_host_ed25519_key.pub&lt;/code&gt; file.&lt;/p&gt;&lt;p&gt;Now nginx serves my websites via http. Let’s get https working.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo /var/lib/certbot/renew-certificates&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alright, now I can set up my config.scm to allow nginx to serve web traffic via https.&lt;/p&gt;&lt;p&gt;Well, can I get a nftables service running now?&lt;/p&gt;&lt;p&gt;At first it seemed that &lt;code&gt;(service nftables-service-type)&lt;/code&gt; is apparently good
  1742. enough to be a decent firewall for my server. Then very quickly I realized that
  1743. it was a terrible firewall for a server, because it blocked all http and https
  1744. traffic.&lt;/p&gt;&lt;p&gt;It looks like the arch linux wiki has a decent configuration example for a server:&lt;/p&gt;&lt;p&gt;https://wiki.archlinux.org/title/Nftables#Examples&lt;/p&gt;&lt;p&gt;So I just took the example nftables configuration for a server and used that.
  1745. The configuration file is here:&lt;/p&gt;&lt;p&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/nftables.scm&lt;/p&gt;&lt;p&gt;Let me know if you see that I did something silly in it, because I probably did.&lt;/p&gt;&lt;p&gt;Bonus paragraph! It took me about 2-4 hours to re-set up my server just the way
  1746. it was before, except I haven't set up email yet. If you crashed your server
  1747. lost your backups, how long would it take you to set up you server, just as it
  1748. was? 2-4 hours is longer than I expected, but I think guix's declarative
  1749. approach certainly is pretty awesome!&lt;/p&gt;</summary></entry><entry><title>Submitting Opensmtpd Service to Guixrus</title><id>https://gnucode.me/submitting-opensmtpd-service-to-guixrus.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-12-22T15:00:00Z</updated><link href="https://gnucode.me/submitting-opensmtpd-service-to-guixrus.html" rel="alternate" /><summary type="html">&lt;p&gt;EDIT 02-24-2023: Through this whole process, I have used this guide to set up email.
  1750. If you are going to try to set up your own email service, do check it out:
  1751. &lt;a href=&quot;https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/&quot;&gt;https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I was recently encouraged by the delightfully friendly raghavgururajan to try to
  1752. merge my opensmtpd service project into guixrus, which is a small community
  1753. actively working to upstream packages and services into guix proper. I figured,
  1754. why not? Sounds like fun. The following post will describe my developmental
  1755. workflow, which is probably pretty poor…&lt;/p&gt;&lt;p&gt;tl;dr&lt;/p&gt;&lt;p&gt;Soonish, I will clean up the code for a proper ~opensmtpd-service-type~ with
  1756. ~opensmtpd-records~ for guix system. It may take 6 months to get it in a clean
  1757. state. Until it is merged, you may find it here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://git.sr.ht/~whereiseveryone/guixrus/commit/255875f7d86e92bb64006a59be26c64430c0c046&quot;&gt;https://git.sr.ht/~whereiseveryone/guixrus/commit/255875f7d86e92bb64006a59be26c64430c0c046&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The current documentation is here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records-documentation.txt&quot;&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records-documentation.txt&lt;/a&gt;&lt;/p&gt;&lt;p&gt;My server's config is here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/linode-locke-lamora-current-config.scm&quot;&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/linode-locke-lamora-current-config.scm&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The current task list is here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org&quot;&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Added, the guixrus channel to my ~/.config/guix/channels.scm&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.config/guix/channels.scm
  1758. (cons* (channel ;; for firefox-wayland
  1759. (name 'nonguix)
  1760. (url &amp;quot;https://gitlab.com/nonguix/nonguix&amp;quot;)
  1761. ;; Enable signature verification:
  1762. (introduction
  1763. (make-channel-introduction
  1764. &amp;quot;897c1a470da759236cc11798f4e0a5f7d4d59fbc&amp;quot;
  1765. (openpgp-fingerprint
  1766. &amp;quot;2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5&amp;quot;))))
  1767. (channel ;; for sway-latest
  1768. (name 'guixrus)
  1769. (url &amp;quot;https://git.sr.ht/~whereiseveryone/guixrus&amp;quot;)
  1770. (introduction
  1771. (make-channel-introduction
  1772. &amp;quot;7c67c3a9f299517bfc4ce8235628657898dd26b2&amp;quot;
  1773. (openpgp-fingerprint
  1774. &amp;quot;CD2D 5EAA A98C CB37 DA91 D6B0 5F58 1664 7F8B E551&amp;quot;))))
  1775. %default-channels)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Before I submit the patch, I should make sure that the code actually works. To
  1776. do that, I logged into my gnucode.me server tried to set up the opensmtpd
  1777. server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix pull --url=https://notabug.org/jbranso/guix/src/newOpensmtpdBranch \
  1778. --branch=newOpensmtpdBranch
  1779. Updating channel 'guix' from Git repository at 'https://notabug.org/jbranso/guix'...
  1780. guix pull: error: Git error: cannot locate remote-tracking branch 'origin/keyring'
  1781. guix pull --url=https://notabug.org/jbranso/guix \
  1782. --commit=8abbb6c442d135ae8e7c1cb0e17525478fafe8f0
  1783. Updating channel 'guix' from Git repository at 'https://notabug.org/jbranso/guix'...
  1784. guix pull: error: Git error: cannot locate remote-tracking branch 'origin/keyring'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, well my opensmtpd service is NOT using signed commits. That’s probably the
  1785. problem. Hmmm… Well I guess I need to start signing my commits. Generate an
  1786. gpg key. grrr….&lt;/p&gt;&lt;p&gt;These three pages are seem promising:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://moser-isi.ethz.ch/gpg.html&quot;&gt;https://moser-isi.ethz.ch/gpg.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://wiki.debian.org/Keysigning&quot;&gt;https://wiki.debian.org/Keysigning&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://risanb.com/code/backup-restore-gpg-key/&quot;&gt;https://risanb.com/code/backup-restore-gpg-key/&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --full-generate-key
  1787. gpg: directory '/home/joshua/.gnupg/openpgp-revocs.d' created
  1788. h.lgpg: revocation certificate stored as '/home/joshua/.gnupg/openpgp-revocs.d/LOTSOFNUMBERS.rev'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I copied my Revocation-Certificate into my spare usb:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo cp .gnupg/openpgp-revocs.d/LOTSOFNUMBERS.rev /mnt/gnucode.gpg.rev&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s export my gpg key to the server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --auto-key-locate keyserver -a --send-keys 67A42A3CC23F979886F9686C750BCFEF3A579572
  1789. gpg -a --export gnucode
  1790. -----BEGIN PGP PUBLIC KEY BLOCK-----
  1791. mQINBGOSU7sBEAC/8renj2OgTHKJfbqz7CRplPQ0su8aasJXTkunx70IhVpTFBS+
  1792. 9Bwvjbo7HM2aBYD/NYa6n24J3OXla17uDxFt2i63ojhbl5AVntac3ZOeyn661Y2U
  1793. r9szIRM+edTieWZZvY5G49ZFTH5VJ+jZS2leRLpIqsYCst+Ru61MdUUggBNvPgBm
  1794. q97HAylBqQs0kf7XfctyqKbkChLsvkuD5cR1X8BQL8KAn/KDXrDSwj4hIO+tSdv5
  1795. VmaTC+6/xbdqfq6gpywJMEPkLNUjCArlF+Oz5UqQvLh1lRXWPejzFa0LmXsviqb3
  1796. RmQh+9cNvDVge+kYIRWHhCXY5dTau7ABnYsgxnW3zlBkFNbc+I5Sqiz6LDcuInlA
  1797. QznFw90GL3l0+1WGzeAD5DhNx6hgpOYvFZV7S3OgbOGeOHvF7bFBixB6Pa3oByMn
  1798. euKqol+rOZiUkjcaxo5XUKsglFLgOaxfmZujO7lwoipYXxiyD7jf1+ou1WZ5C3l+
  1799. YCOnia2qWE5DRpR/WDBRLQl3ZrCUtDQW7dKNAuweEgDT5T53k2m3Gqu1Z28SrzIS
  1800. is+SHZcZhv4dx9Cs6sX6me3WzQ3wgoI9DNW5v8XGitaGQFjIRI33Y8MeGjEBMip3
  1801. ZnT6Cl8WJgd0JBXsPQnKw1EO1sh2S5cU5drvHkuCPMA/PaBb8XrNpobSlwARAQAB
  1802. tDNKb3NodWEgQWxsZW4gQnJhbnNvbiAoZ251Y29kZSkgPGpicmFuc29AZGlzbWFp
  1803. bC5kZT6JAk4EEwEIADgWIQRnpCo8wj+XmIb5aGx1C8/vOleVcgUCY5JTuwIbAwUL
  1804. CQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRB1C8/vOleVcgwwEACp4ZwBIM/4Udc9
  1805. ndZvUJeegSP0W7o86v+9ELXfXdX99ZO0iErr6/XTWxov0mw7AaoDJRdETBTkYeU0
  1806. /CDrLcjklW8b7RZe98+Cr0+IB9XSozpqNVhiP7/TogL80lkbu2+Khtk29E/UYupt
  1807. 8rihR+2tkDKPaWOufGgi+6ftw8A9P9jlFsV1N1Oxo4rA+gbcXHtxbDiZ1dR2UOAS
  1808. Ge7TJPpIjgSiG+nm6b9BIoAxLpjf5JrwpNm5wvDXic1YP27GC2Il9Ny7TdGyKpn9
  1809. RCZXR1yEMQTVNn4iEiMK6XIcoAFUS1oWAP2JKQ4bCfcxM/VGx31rsGgNL36iW6yj
  1810. zLD9yJYhbvm536CiRb2cTco+lAmwS9/iM4Bdpp/H9fZFPp2CxeB02mOd/P0HkC+2
  1811. Po2KXpEj6Ettjp0xJcAQye75vRvjDMkHvTvugfY4FQg6V6a6N3jxSbfwuFUp426F
  1812. fgfki4Y7OWm47mYa7goI4oDOG2qUdN5YkbhpVA+j2tGGHbbXmUtvj4MES4fnaSkF
  1813. vc6+xMZpFTWcFRt8rVTqS1Vu1w8zfT/VUV+FC/J6hdSxIQJ4dg4WsaD2kzGflZzO
  1814. miTyxMYPvdQ6I7Nshp/bEyfd9F40sXm/kzL6r+qm9+ly2uR5V+bIo9gu6CfkM0ZJ
  1815. DDiIf9wkk+xSb/AGj1YVazQKpKS0wLkCDQRjklO7ARAAzrtyGaOFTtCHlItxxb51
  1816. s0Qt5LZwG3sNUjI9P7n3oZrzI35sbPrWxWCX2MMW0gUIx79dlMzQBt1RXQEKiipr
  1817. RdSrtuclTytxaMtLRP+VtmcRQkGgKb20ipCvFHX4oA7L+3Y8s2RQBsz+wo9h55Dt
  1818. iQRxoONm9biHXBUZ4EJnR4B8z0dp9j+fctTR4ds6OI3jIeKHcd4AALYIpyBnh5ue
  1819. 5Iictiv0evBjcogfCttHlg/NK3TVZpq8YYOG8x+8XVrvvJ5WKtmXduZuFIL3+Wmv
  1820. jBv807a4zGLPLpB6OcD7fj/12Eo9n7d9gHZOV200rPguzt9YMIoRGgtSEEpMsvrJ
  1821. 5upiFLPULj/14arXePdqZshlU01U0uE6glGJRUt7IVyU+1LbziQ8JqBlVTnRRYrb
  1822. uKDFqzmtd3zhLDPAPLkv7xLtEjYUPcFDmrf33dz22FHUGeOB0G5Ur+e9qTedfmj0
  1823. r5sHaoCspZzDcVR8sKyuUdAnRAGxJs9eIFUq2GkyxZGgfJoU2A9RMxg+YTfFfdQV
  1824. guvvPj6udOF4ugmIW1EnDXza08UyDqOITLIadNu4GqZL407JRIRtYfw48qQgL3Zo
  1825. 6lqxC/3n7orkuRU/cKvHArqQt1sP7ZYzAy5N/yoY0/m3o2RV9Li7SkF2m5By8EjH
  1826. RNvQMPsipdvjWf4I+jLaAM0AEQEAAYkCNgQYAQgAIBYhBGekKjzCP5eYhvlobHUL
  1827. z+86V5VyBQJjklO7AhsMAAoJEHULz+86V5Vy6U0QAJtjybCfDAqE5DIcKkiBDbIN
  1828. erk+MTU+uOROuVigDCyvqJUuxtGaJPIRWdBQuHcQxnf6Bv1xoAeDk/7hyL7i5+rz
  1829. 9vWZnSZRr4DB6pY8G5jz/HGdML4luEtuOrE5UMN8Bf5PM/9sj/c1QSuMhpAMw5TL
  1830. GoAu+MY/uDCHLb2nzwLIaCPFDTX0q5HgFQA7Do78fdxxPLqPlbg9xeTsAP5P6Egb
  1831. /8NUUa1SM4mfygriyL82nLH9SvwtnEbItovAWE+GH4XkE8xSjvWl6MpCk0+H0Xtr
  1832. WdbxtKqE7BPzs0lN3NOi+mOJABDt5ozPGfVcUsB/nqz00YiF33CQWu0ote1Q1TKn
  1833. NPOCLqFM3F1rG2z7Bf/LP9p6CpmfQGr54XmKpGinYNr8dqRtLEMVERCxGI+BuNhZ
  1834. ppQLuqOlHinKPaBO58LCwLA0uMScbmjgTQrJiXolCGHYXorCx3rcqitvMzbAcswr
  1835. wMeAXMREYKGM84Pf8fGxv+GZZwfQJHQNbOFrOTpnRITDAZvzKBD97yWkXcLGt6B7
  1836. A5iRXOI8sv9CGM3kI78b+MCcgbz8HNGF2RQipGNQZhEgL4ixbhpMaMVUuTo7BrKr
  1837. M3IeyVwUMpUBFbk5OqLsMqPbL2VvL6x1zgg4P0LmGQYoikKiwmPl/OyRQW6btWCG
  1838. 1f7+w1RrcKjUANLQNjXm
  1839. =Vl9S
  1840. -----END PGP PUBLIC KEY BLOCK-----
  1841. gpg -a --export gnucode &amp;gt; gnucode.pub
  1842. sudo cp gnucode.pub /mnt/&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s backup the gpg key.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; gpg --export-secret-keys --armor gnucode &amp;gt; secret-key-backup.asc
  1843. sudo mv secret-key-backup.asc /mnt/&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I ever need to move that gpg key to another computer, all I have to do is:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --import /path/to/secret-key-backup.asc&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s try testing a signed commit.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git config --global commit.gpgsign true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key&quot;&gt;https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --list-secret-keys --keyid-format=long
  1844. # git config --global user.signingkey MYSIGNINGKEY
  1845. git config --global alias.logs &amp;quot;log --show-signature&amp;quot;
  1846. git commit -m &amp;quot;mail.scm: minor sanitization improvements.&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok well let’s try this to see what the error was:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;GIT_TRACE=1 git commit -m &amp;quot;blah&amp;quot; -S
  1847. 23:07:37.656401 git.c:460 trace: built-in: git commit -m blah -S
  1848. 23:07:37.678825 run-command.c:655 trace: run_command: gpg --status-fd=2 -bsau 750BCFEF3A579572
  1849. error: gpg failed to sign the data
  1850. fatal: failed to write commit object
  1851. gpg --status-fd=2 -bsau 750BCFEF3A579572&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As I was running through the above command, I realized that, it is possible that
  1852. I did not have pinentry installed:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix install pinentry
  1853. git logs&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I think I will try rebooting and check to see if I can still sign git
  1854. commits.&lt;/p&gt;&lt;p&gt;And after I rebooted, I cannot sign commits with emacs…&lt;/p&gt;&lt;p&gt;Emacs says “hint: Waiting for your editor to close the file…”
  1855. “Waiting for Emacs”&lt;/p&gt;&lt;p&gt;Well online, I see this as a possible solution&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git config --global core.editor emacs&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that didn’t quite work. I was able to squash two commits, via emacs, but
  1856. only after I had the gpg agent had cached my private key password. That makes
  1857. me think that magit is having a hard time querying my for my password.&lt;/p&gt;&lt;p&gt;Well let me try updating doom emacs. I doubt that will work, but I’ll try it.
  1858. That didn’t work. :(&lt;/p&gt;&lt;p&gt;Well I found a possible error here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/magit/with-editor/issues/69&quot;&gt;https://github.com/magit/with-editor/issues/69&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://emacs.stackexchange.com/questions/74097/magit-cannot-commit-emacsclient-on-path-pop-os&quot;&gt;https://emacs.stackexchange.com/questions/74097/magit-cannot-commit-emacsclient-on-path-pop-os&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://magit.vc/manual/with-editor/Configuring-With_002dEditor.html&quot;&gt;https://magit.vc/manual/with-editor/Configuring-With_002dEditor.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Then I thought, how about I disable the with-editor elisp package that doom
  1859. emacs ships and instead &lt;code&gt;guix install emacs-with-editor&lt;/code&gt;. Let’s try that.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat .doom.d/packages.el | grep with-editor
  1860. (package! with-editor :disable t)
  1861. doom upgrade
  1862. doom sync
  1863. guix install emacs-with-editor&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nope. That didn’t work either. Hmmm. I can get emacs to commit the message,
  1864. after the gpg agent caches my key’s password.&lt;/p&gt;&lt;p&gt;Well let’s try running emacs without any configuration: &lt;code&gt;emacs -q&lt;/code&gt;. Nope. That
  1865. also didn’t work. :(&lt;/p&gt;&lt;p&gt;My current theory is that my wayland only session is prohibiting the pinentry
  1866. from displaying, which is NOT allowing me to enter in my gpg password. I shall
  1867. try temporarily enabling Xwayland and see if that fixed it.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat config | grep xwayland
  1868. # disable xwayland. Just trying it out
  1869. xwayland enable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Yup! That fixed it. With the above, I can now sign my commits with emacs! But
  1870. I would rather keep my wayland only session. Let’s try pinetry-bemenu:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -i pinentry-bemenu -r pinentry
  1871. cat config | grep xwayland
  1872. # disable xwayland.
  1873. xwayland disable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that didn’t work. Let’s try pinetry-gnome3.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -r pinentry-bemenu -i pinentry-gnome3&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nope. It’s X only. Let’s try qt:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -r pinentry-gnome3 -i pinentry-qt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nope. That also seems to be X only. grr. Maybe this bemenu thing works, but I
  1874. need to configure it properly.&lt;/p&gt;&lt;p&gt;Well let’s install pinentry, and temporarily enable xwayland.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -r pinentry-tty -i pinentry
  1875. cat config | grep xwayland
  1876. # enable xwayland.
  1877. xwayland enable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well I should probably try eventually to edit &lt;code&gt;.config/gpg.conf&lt;/code&gt; and tell it to
  1878. use pinentry-bemu as the pinentry program.&lt;/p&gt;&lt;p&gt;I think that spending all that time working on getting gpg key signing to work
  1879. was probably a big waste of time. :( I think instead of keeping my opensmtpd
  1880. code in guix-src/gnu/services/mail.scm, I will move it to
  1881. guixrus/services/opensmtpd.scm. Then I can just copy opensmtpd.scm file to my
  1882. linode server, and manually load in that code to start my opensmtpd service.&lt;/p&gt;&lt;p&gt;First I will delete the opensmtpd record stuff in gnu/services/mail.scm. I
  1883. don’t want myself getting confused where I am storing my developmental code.&lt;/p&gt;&lt;p&gt;Now I will cp my opensmtpd.scm code into my linode service git repo.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cp opensmtpd.scm ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/
  1884. ls ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm
  1885. cat ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm | tail
  1886. /home/joshua/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm
  1887. (service-extension pam-root-service-type
  1888. (const %opensmtpd-pam-services))
  1889. (service-extension profile-service-type
  1890. (compose list opensmtpd-configuration-package))
  1891. (service-extension shepherd-root-service-type
  1892. opensmtpd-shepherd-service)
  1893. (service-extension setuid-program-service-type
  1894. opensmtpd-set-gids)))
  1895. (description &amp;quot;Run the OpenSMTPD, a lightweight @acronym{SMTP, Simple Mail
  1896. Transfer Protocol} server.&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I will commit the changes to my linode git repo and push them.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git add opensmtpd.scm
  1897. git commit -m &amp;quot;copying opensmtpd.scm from guixrus.&amp;quot;
  1898. [master 7399550] copying opensmtpd.scm from guixrus.
  1899. 1 file changed, 7 insertions(+)
  1900. rename opensmtpd.scm =&amp;gt; guixrus/services/opensmtpd.scm (99%)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmmm, was that commit signed? No idea.&lt;/p&gt;&lt;p&gt;Now let’s push that commit.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's log into the gnucode service and pull that commit.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git pull
  1901. cat opensmtpd.scm | tail
  1902. Updating a8d88b9..7399550
  1903. Fast-forward
  1904. opensmtpd.scm =&amp;gt; guixrus/services/opensmtpd.scm | 7 +++++++
  1905. 1 file changed, 7 insertions(+)
  1906. rename opensmtpd.scm =&amp;gt; guixrus/services/opensmtpd.scm (99%)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I am realizing that it will probably be easiest to reconfigure my server with my
  1907. opensmtpd records, if my server has the same directory structure as my local
  1908. machine. Namely my git repos are in the same directories. So I did some changes
  1909. on my server to make sure that my server's directory structure matches my local
  1910. one. Now my server’s &lt;code&gt;config.scm&lt;/code&gt; is no longer at
  1911. ~/linode-guix-system-configuration/linode-locke-lamora-current-config.scm. Now
  1912. it is at:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find . -name '*current-config.scm'
  1913. ./prog/gnu/guix/guix-config/linode-guix-system-configuration/linode-locke-lamora-current-config.scm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I want to make sure that my remote server has a copy of the guixrus source code
  1914. with my newest commit committing &lt;code&gt;services/opensmtpd.scm&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So, I made a guixrus repo on &lt;a href=&quot;https://notabug.org/jbranso/guixrus&quot;&gt;notabug.org&lt;/a&gt;, then I pulled that repo on my server:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone https://notabug.org/jbranso/guixrus
  1915. git show HEAD | head
  1916. commit 147a9ce316be2f9f7c9ed25b3e097fd84b8b01eb
  1917. Author: Joshua Branson &amp;lt;jbranso@dismail.de&amp;gt;
  1918. Date: Thu Dec 22 09:21:19 2022 -0500
  1919. services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.
  1920. Openmstpd-configuration may only be configured by a config-file that
  1921. uses the smtpd.conf syntax. This patch, enables one to configure
  1922. opensmtpd by using record types.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It would be nice to test the configuration locally, to see if it will work
  1923. before I push it to the server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix system vm linode-locke-lamora-current-config.scm
  1924. guix system: error: (cert &amp;quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&amp;quot;) is invalid.
  1925. hint: Try a file.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above is actually a good sign. I do not have that certificate locally, but
  1926. it is available on the server. If that is the only error, then let’s go ahead
  1927. and try to reconfigure the server.&lt;/p&gt;&lt;p&gt;The relevant opensmtpd-service looks like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service opensmtpd-service-type
  1928. (let ([action-receive (opensmtpd-local-delivery
  1929. (name &amp;quot;receive&amp;quot;)
  1930. (method (opensmtpd-maildir
  1931. (pathname &amp;quot;/home/%{rcpt.user}/Maildir&amp;quot;)
  1932. (junk #t)))
  1933. (virtual (opensmtpd-table
  1934. (name &amp;quot;vusers&amp;quot;)
  1935. (data '((&amp;quot;joshua@gnucode.me&amp;quot; . &amp;quot;joshua&amp;quot;)
  1936. (&amp;quot;jbranso@gnucode.me&amp;quot; . &amp;quot;joshua&amp;quot;)
  1937. (&amp;quot;postmaster@gnucode.me&amp;quot; . &amp;quot;joshua&amp;quot;))))))]
  1938. [pki-gnucode (opensmtpd-pki
  1939. (domain &amp;quot;smtp.gnucode.me&amp;quot;)
  1940. (cert &amp;quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&amp;quot;)
  1941. (key &amp;quot;/etc/letsencrypt/live/gnucode.me/privkey.pem&amp;quot;))]
  1942. [filter-dkimsign (opensmtpd-filter
  1943. (name &amp;quot;dkimsign&amp;quot;)
  1944. (exec #t)
  1945. (proc (list (file-append opensmtpd-filter-dkimsign &amp;quot;/libexec/opensmtpd/filter-dkimsign&amp;quot;)
  1946. &amp;quot; -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k &amp;quot;
  1947. &amp;quot;/etc/dkim/private.key &amp;quot;
  1948. &amp;quot;user nobody group nogroup&amp;quot;)))]
  1949. [table-creds (opensmtpd-table
  1950. (name &amp;quot;creds&amp;quot;)
  1951. (data
  1952. (list
  1953. (cons &amp;quot;joshua&amp;quot;
  1954. &amp;quot;$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.&amp;quot;))))])
  1955. (opensmtpd-configuration
  1956. (interfaces
  1957. (list
  1958. ;; this forum help suggests that I listen on 0.0.0.0 and NOT eth0
  1959. ;; https://serverfault.com/questions/726795/opensmtpd-wont-work-at-reboot
  1960. ;; this listens for email from the outside world
  1961. (opensmtpd-interface
  1962. (interface &amp;quot;eth0&amp;quot;)
  1963. (port 25)
  1964. (secure-connection &amp;quot;tls&amp;quot;)
  1965. (pki pki-gnucode))
  1966. ;; this lets local users logged into the system via ssh send email
  1967. (opensmtpd-interface
  1968. (interface &amp;quot;lo&amp;quot;)
  1969. (port 25)
  1970. (secure-connection &amp;quot;tls&amp;quot;)
  1971. (pki pki-gnucode))
  1972. (opensmtpd-interface
  1973. (interface &amp;quot;eth0&amp;quot;)
  1974. (port 465)
  1975. (secure-connection &amp;quot;smtps&amp;quot;)
  1976. (pki pki-gnucode)
  1977. (auth table-creds)
  1978. (filters (list filter-dkimsign)))
  1979. (opensmtpd-interface
  1980. (interface &amp;quot;eth0&amp;quot;)
  1981. (port 587)
  1982. (secure-connection &amp;quot;tls-require&amp;quot;)
  1983. (pki pki-gnucode)
  1984. (auth table-creds)
  1985. (filters (list filter-dkimsign)))))
  1986. (matches (list
  1987. (opensmtpd-match
  1988. (action (opensmtpd-relay
  1989. (name &amp;quot;relay&amp;quot;)))
  1990. (options
  1991. (list
  1992. (opensmtpd-option
  1993. (option &amp;quot;for any&amp;quot;))
  1994. (opensmtpd-option
  1995. (option &amp;quot;from any&amp;quot;))
  1996. (opensmtpd-option
  1997. (option &amp;quot;auth&amp;quot;)))))
  1998. (opensmtpd-match
  1999. (action action-receive)
  2000. (options
  2001. (list
  2002. (opensmtpd-option
  2003. (option &amp;quot;from any&amp;quot;))
  2004. (opensmtpd-option
  2005. (option &amp;quot;for domain&amp;quot;)
  2006. (data (opensmtpd-table
  2007. (name &amp;quot;vdoms&amp;quot;)
  2008. (data (list &amp;quot;gnucode.me&amp;quot;
  2009. &amp;quot;gnu-hurd.com&amp;quot;))))))))
  2010. (opensmtpd-match
  2011. (action action-receive)
  2012. (options
  2013. (list
  2014. (opensmtpd-option
  2015. (option &amp;quot;for local&amp;quot;))))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I was curious to see how outdated my server is. It’s dated apparently.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix system describe
  2016. Generation 118 Aug 14 2022 02:45:18 (current)
  2017. file name: /var/guix/profiles/system-118-link
  2018. canonical file name: /gnu/store/7jkrafkf61bw3fdxlrlzvkrl98ys1icj-system
  2019. label: GNU with Linux-Libre 5.18.16
  2020. bootloader: grub
  2021. root device: /dev/sda
  2022. kernel: /gnu/store/iz6xn1b1dyk6pwaf6dym3jm3vwnh4gz9-linux-libre-5.18.16/bzImage
  2023. channels:
  2024. guix:
  2025. repository URL: https://git.savannah.gnu.org/git/guix.git
  2026. branch: master
  2027. commit: 43decd1f7ea4ebd911199ad10c0ca555d0dffbd6
  2028. configuration file: /gnu/store/rv7rhwn5kd9yxv8kayqlsgxwyhcz55ca-configuration.scm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let's try reconfiguring my server with the opensmtpd configuration.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix pull
  2029. sudo guix system reconfigure linode-locke-lamora-current-config.scm
  2030. In srfi/srfi-1.scm:
  2031. 586:29 19 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
  2032. 586:29 18 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
  2033. 586:29 17 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
  2034. 586:29 16 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
  2035. 586:29 15 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
  2036. 586:29 14 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type agetty 7f8c1…&amp;gt; …))
  2037. 586:29 13 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type syslog 7f8c1…&amp;gt; …))
  2038. 586:29 12 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type console-font…&amp;gt; …))
  2039. 586:29 11 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type virtual-term…&amp;gt; …))
  2040. 586:17 10 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type opensmtpd 7f…&amp;gt; …))
  2041. In guixrus/services/opensmtpd.scm:
  2042. 2567:27 9 (opensmtpd-shepherd-service #&amp;lt;&amp;lt;opensmtpd-configuration&amp;gt;…&amp;gt;)
  2043. 2541:19 8 (opensmtpd-configuration-&amp;gt;mixed-text-file #&amp;lt;&amp;lt;opensmtpd-…&amp;gt;)
  2044. 2496:3 7 (opensmtpd-configuration-&amp;gt;string #&amp;lt;&amp;lt;opensmtpd-configura…&amp;gt;)
  2045. 2421:9 6 (opensmtpd-configuration-fieldname-&amp;gt;string #&amp;lt;&amp;lt;opensmtp…&amp;gt; …)
  2046. 2430:10 5 (list-of-records-&amp;gt;string (#&amp;lt;&amp;lt;opensmtpd-interface&amp;gt; i…&amp;gt; …) …)
  2047. 2434:17 4 (loop (#&amp;lt;&amp;lt;opensmtpd-interface&amp;gt; interface: &amp;quot;eth0&amp;quot; fam…&amp;gt; …))
  2048. 1848:5 3 (opensmtpd-interface-&amp;gt;string #&amp;lt;&amp;lt;opensmtpd-interface&amp;gt; in…&amp;gt;)
  2049. In unknown file:
  2050. 2 (string-append &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;tls &amp;quot; #&amp;lt;unspecified&amp;gt; &amp;quot;p…&amp;quot; …)
  2051. In ice-9/boot-9.scm:
  2052. 1685:16 1 (raise-exception _ #:continuable? _)
  2053. 1685:16 0 (raise-exception _ #:continuable? _)
  2054. ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  2055. In procedure string-append: Wrong type (expecting string): #&amp;lt;unspecified&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ahh, I know what that problem is! Let’s fix that. So now I have make a local
  2056. commit. Push it to my notabug.org/guixrus, ssh into lamora, run &lt;code&gt;git pull&lt;/code&gt; on
  2057. the guixrus repo, then try to reconfigure. This seems like a very odd/poor way
  2058. to test changes. By making a commit locally, pushing it, pulling it, and then
  2059. wondering if the reconfigure will work. I should really set up guix deploy.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure linode-locke-lamora-current-config.scm
  2060. module-import-compiled 1.0MiB 1.6MiB/s 00:01 [##################] 100.0%
  2061. building /gnu/store/mw8x4pbl11a5pdgxqcw2vvczdccpmicf-switch-to-system.scm.drv...
  2062. making '/gnu/store/0v5sbvlx9r151gjlc906lxyhps7xx1h8-system' the current system...
  2063. setting up setuid programs in '/run/setuid-programs'...
  2064. populating /etc from /gnu/store/1n0l349b03h7dclwai9l0kxglb8kwyv0-etc...
  2065. checking syntax of /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf
  2066. /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf:14: syntax error
  2067. /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf:21: no such dispatcher: relay&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so I have a configuration error. Let’s take a look at the generated
  2068. configuration file:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The first error is this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf | grep '&amp;lt;&amp;quot;&amp;lt;&amp;quot;'
  2069. listen on eth0 filter &amp;quot;dkimsign&amp;quot; smtps port 465 pki smtp.gnucode.me auth &amp;lt;&amp;quot;&amp;lt;&amp;quot;creds&amp;quot;&amp;gt;&amp;quot;&amp;gt;
  2070. listen on eth0 filter &amp;quot;dkimsign&amp;quot; tls-require port 587 pki smtp.gnucode.me auth &amp;lt;&amp;quot;&amp;lt;&amp;quot;creds&amp;quot;&amp;gt;&amp;quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It should be &amp;lt;“creds”&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Another error is this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf | grep match
  2071. match !for any !from any !auth action &amp;quot;relay&amp;quot;
  2072. match !from any !for domain &amp;lt;&amp;quot;vdoms&amp;quot;&amp;gt; action &amp;quot;receive&amp;quot;
  2073. match !for local action &amp;quot;receive&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These match options should NOT be false. Let's quickly fix those issues
  2074. reconfigure again:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure linode-locke-lamora-current-config.scm
  2075. checking syntax of /gnu/store/a69a5vn2r94glh58wlfq41ygfl38ikgn-smtpd.conf
  2076. configuration OK&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That’s a good sign!&lt;/p&gt;&lt;p&gt;Let’s reboot and see what happens!&lt;/p&gt;&lt;p&gt;Well when I reboot, smtpd refused to start. Let’s look at the config file.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/a69a5vn2r94glh58wlfq41ygfl38ikgn-smtpd.conf
  2077. filter &amp;quot;dkimsign&amp;quot; proc-exec &amp;quot;/gnu/store/n2f5waxzdzcsdvh0xydhnc174n3kingw-opensmtpd-filter-dkimsign-0.6/libexec/opensmtpd/filter-dkimsign -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k /etc/dkim/private.key user nobody group nogroup&amp;quot;
  2078. mta max-deferred 100
  2079. table &amp;quot;creds&amp;quot; { &amp;quot;joshua&amp;quot; = &amp;quot;$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.&amp;quot; }
  2080. table &amp;quot;vusers&amp;quot; { &amp;quot;joshua@gnucode.me&amp;quot; = &amp;quot;joshua&amp;quot;, &amp;quot;jbranso@gnucode.me&amp;quot; = &amp;quot;joshua&amp;quot;, &amp;quot;postmaster@gnucode.me&amp;quot; = &amp;quot;joshua&amp;quot; }
  2081. table &amp;quot;vdoms&amp;quot; { &amp;quot;gnucode.me&amp;quot;, &amp;quot;gnu-hurd.com&amp;quot; }
  2082. pki smtp.gnucode.me cert &amp;quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&amp;quot;
  2083. pki smtp.gnucode.me key &amp;quot;/etc/letsencrypt/live/gnucode.me/privkey.pem&amp;quot;
  2084. listen on eth0 tls port 25 pki smtp.gnucode.me
  2085. listen on lo tls port 25 pki smtp.gnucode.me
  2086. listen on eth0 filter &amp;quot;dkimsign&amp;quot; smtps port 465 pki smtp.gnucode.me auth &amp;lt;&amp;quot;creds&amp;quot;&amp;gt;
  2087. listen on eth0 filter &amp;quot;dkimsign&amp;quot; tls-require port 587 pki smtp.gnucode.me auth &amp;lt;&amp;quot;creds&amp;quot;&amp;gt;
  2088. action &amp;quot;relay&amp;quot; relay
  2089. action &amp;quot;receive&amp;quot; maildir &amp;quot;/home/%{rcpt.user}/Maildir&amp;quot; junk virtual &amp;lt;&amp;quot;vusers&amp;quot;&amp;gt;
  2090. match for any from any auth action &amp;quot;relay&amp;quot;
  2091. match from any for domain &amp;lt;&amp;quot;vdoms&amp;quot;&amp;gt; action &amp;quot;receive&amp;quot;
  2092. match for local action &amp;quot;receive&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It seems to be just fine...hmmm. What does the error log say?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /var/log/maillog | tail
  2093. Dec 22 10:05:41 localhost smtpd[19325]: warn: lost processor: dkimsign exited abnormally
  2094. Dec 22 10:05:41 localhost smtpd[19328]: dkimsign: Can't open key file (/etc/dkim/private.key): No such file or directory
  2095. Dec 22 10:05:41 localhost smtpd[19330]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
  2096. Dec 22 10:05:41 localhost smtpd[19325]: Exiting
  2097. Dec 22 11:22:18 localhost smtpd[268]: info: OpenSMTPD 6.8.0p2 starting
  2098. Dec 22 11:22:18 localhost smtpd[269]: warn: lost processor: dkimsign exited abnormally
  2099. Dec 22 11:22:18 localhost smtpd[272]: dkimsign: Can't open key file (/etc/dkim/private.key): No such file or directory
  2100. Dec 22 11:22:18 localhost smtpd[274]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
  2101. Dec 22 11:22:18 localhost smtpd[269]: Exiting&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, well I think I found the problem. haha. Let’s see, ah, looks like that key
  2102. is here:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find . -name '*key'
  2103. /etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s commit my current-config locally, push it upstream, pull it from my server
  2104. and reconfigure.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure linode-locke-lamora-current-config.scm
  2105. checking syntax of /gnu/store/42q90z8n03zi9rx29gwdnms4sdr2g2p9-smtpd.conf
  2106. configuration OK&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After I rebooted, smtpd still was not starting. Let’s try to find out why:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /var/log/maillog | tail
  2107. Dec 22 11:38:03 localhost smtpd[498]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
  2108. Dec 22 11:38:03 localhost smtpd[493]: warn: lost processor: dkimsign exited abnormally
  2109. Dec 22 11:38:03 localhost smtpd[496]: dkimsign: Can't open key file (/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key): Permission denied
  2110. Dec 22 11:38:03 localhost smtpd[493]: Exiting
  2111. Dec 22 11:40:02 localhost dovecot: master: Dovecot v2.3.19.1 (9b53102964) starting up for imap (core dumps disabled)
  2112. Dec 22 11:42:41 localhost smtpd[258]: info: OpenSMTPD 6.8.0p2 starting
  2113. Dec 22 11:42:41 localhost smtpd[259]: warn: lost processor: dkimsign exited abnormally
  2114. Dec 22 11:42:41 localhost smtpd[262]: dkimsign: Can't open key file (/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key): Permission denied
  2115. Dec 22 11:42:41 localhost smtpd[264]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
  2116. Dec 22 11:42:41 localhost smtpd[259]: Exiting&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, this is just a permissions error. That’s an easy fix! I changed a
  2117. &lt;code&gt;sudo chown -R smtpd /etc/opensmtpd&lt;/code&gt;. Then I got this beauty:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo herd start smtpd
  2118. Service smtpd has been started.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Woo hoo! Now let’s try to send an email and see if it works!&lt;/p&gt;&lt;p&gt;I sent an email to gmail, and if you select an email in gmail, you can click on
  2119. view original. It showed me that I did pass dkimsigning! That’s awesome! And
  2120. my email was in my gmail inbox. That’s a really good sign! Now I am off to
  2121. submit a patch to guixrus!&lt;/p&gt;&lt;p&gt;I did get a tip from someone on irc that mentioned that I should verify my
  2122. dkimsigning and SPF via https://dkimvalidator.com/ And when I used that tool, I
  2123. discovered that my SPF was failing, so I will need to fix that.&lt;/p&gt;</summary></entry><entry><title>Simple Mispelling Problem</title><id>https://gnucode.me/simple-mispelling-problem.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-11-22T11:00:00Z</updated><link href="https://gnucode.me/simple-mispelling-problem.html" rel="alternate" /><summary type="html">&lt;p&gt;Edit: Yes I am aware that I misspelled &amp;quot;mispelling&amp;quot;. I figure it's funny if I
  2124. leave it as it is. :)&lt;/p&gt;&lt;p&gt;I had this simple coding problem that I wanted to solve. Here's the problem:&lt;/p&gt;&lt;p&gt;Suppose you are writing an guix service &lt;a href=&quot;https://notabug.org/jbranso/guix/src/newOpensmtpdBranch/gnu/services/mail.scm&quot;&gt;(like I happen to be)&lt;/a&gt;, and you are
  2125. sanitizing user input for various records. Suppose your user mispells an
  2126. option. Wouldn't it be nice to include a nice helpful hint on what he probably
  2127. did wrong?&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(opensmtpd-option (option &amp;quot;forany&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;error: (option &amp;quot;forany&amp;quot;) is invalid.
  2128. hint: Try &amp;quot;for rcpt-to&amp;quot;, &amp;quot;for domain&amp;quot;, &amp;quot;for local&amp;quot;, &amp;quot;for any&amp;quot;, or &amp;quot;for&amp;quot;.&lt;/p&gt;&lt;p&gt;Using &lt;code&gt;string-prefix-length-ci&lt;/code&gt;, I was able to construct a fairly naive
  2129. prococedure that tries to guess what the user meant to type. Here's what I came
  2130. up with:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;; if strings is (list &amp;quot;auth&amp;quot; &amp;quot;for any&amp;quot; &amp;quot;from local&amp;quot;)
  2131. ;; Then this will return &amp;quot;Try \&amp;quot;auth\&amp;quot;, \&amp;quot;for any\&amp;quot;, or \&amp;quot;from local\&amp;quot;.&amp;quot;
  2132. (define (try-string strings)
  2133. (string-append &amp;quot;Try &amp;quot;
  2134. (let loop ((strings strings))
  2135. (cond ((= 1 (length strings))
  2136. (string-append
  2137. &amp;quot;or \&amp;quot;&amp;quot; (car strings) &amp;quot;\&amp;quot;.\n&amp;quot;))
  2138. (else
  2139. (string-append
  2140. &amp;quot;\&amp;quot;&amp;quot; (car strings) &amp;quot;\&amp;quot;, &amp;quot;
  2141. (loop (cdr strings))))))))
  2142. ;; suppose string is &amp;quot;for anys&amp;quot;
  2143. ;; and strings is (list &amp;quot;for any&amp;quot; &amp;quot;for local&amp;quot; &amp;quot;for domain&amp;quot;)
  2144. ;; then hint-string will return &amp;quot;Did you mean &amp;quot;for any&amp;quot;?&amp;quot;
  2145. (define* (hint-string string strings
  2146. #:key (fieldname #f))
  2147. (if (not (string? string))
  2148. (try-string strings)
  2149. (let loop ((current-max 1)
  2150. (loop-strings strings)
  2151. (hint-strings '()))
  2152. (if (null? loop-strings)
  2153. (cond ((= 1 (length hint-strings)) ;; only one worthwhile match
  2154. (if fieldname
  2155. (string-append &amp;quot;Did you mean (&amp;quot; fieldname &amp;quot; \&amp;quot;&amp;quot;
  2156. (car hint-strings) &amp;quot;\&amp;quot;) ?\n&amp;quot;)
  2157. (string-append &amp;quot;Did you mean \&amp;quot;&amp;quot; (car hint-strings)
  2158. &amp;quot;\&amp;quot;?\n&amp;quot;)))
  2159. (else (if (null? hint-strings)
  2160. (try-string strings)
  2161. (try-string hint-strings))))
  2162. (let* ((element-string (car loop-strings))
  2163. (element-max
  2164. (string-prefix-length-ci element-string string)))
  2165. (cond ((&amp;gt; element-max current-max)
  2166. (loop element-max (cdr loop-strings)
  2167. (list element-string)))
  2168. ((= element-max current-max)
  2169. (loop current-max (cdr loop-strings)
  2170. (cons element-string hint-strings)))
  2171. (else (loop current-max
  2172. (cdr loop-strings) hint-strings))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It won't recognize that &amp;quot;or any&amp;quot; or &amp;quot;bor any&amp;quot; should match &amp;quot;for any&amp;quot;, but for
  2173. most mispellings, it should be half decent, provided the user got the first
  2174. character right.&lt;/p&gt;&lt;p&gt;What do you all think? How would you write such a procedure?&lt;/p&gt;&lt;p&gt;EDIT: Well it turns out that the guix developers actually have a
  2175. (string-closest) procedure. The relevant code can be found in
  2176. (guix utils) and (guix combinators):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define fold2
  2177. (case-lambda
  2178. ((proc seed1 seed2 lst)
  2179. &amp;quot;Like `fold', but with a single list and two seeds.&amp;quot;
  2180. (let loop ((result1 seed1)
  2181. (result2 seed2)
  2182. (lst lst))
  2183. (if (null? lst)
  2184. (values result1 result2)
  2185. (call-with-values
  2186. (lambda () (proc (car lst) result1 result2))
  2187. (lambda (result1 result2)
  2188. (loop result1 result2 (cdr lst)))))))
  2189. ((proc seed1 seed2 lst1 lst2)
  2190. &amp;quot;Like `fold', but with two lists and two seeds.&amp;quot;
  2191. (let loop ((result1 seed1)
  2192. (result2 seed2)
  2193. (lst1 lst1)
  2194. (lst2 lst2))
  2195. (if (or (null? lst1) (null? lst2))
  2196. (values result1 result2)
  2197. (call-with-values
  2198. (lambda () (proc (car lst1) (car lst2) result1 result2))
  2199. (lambda (result1 result2)
  2200. (loop result1 result2 (cdr lst1) (cdr lst2)))))))))
  2201. (define (string-distance s1 s2)
  2202. &amp;quot;Compute the Levenshtein distance between two strings.&amp;quot;
  2203. ;; Naive implemenation
  2204. (define loop
  2205. (mlambda (as bt)
  2206. (match as
  2207. (() (length bt))
  2208. ((a s ...)
  2209. (match bt
  2210. (() (length as))
  2211. ((b t ...)
  2212. (if (char=? a b)
  2213. (loop s t)
  2214. (1+ (min
  2215. (loop as t)
  2216. (loop s bt)
  2217. (loop s t))))))))))
  2218. (let ((c1 (string-&amp;gt;list s1))
  2219. (c2 (string-&amp;gt;list s2)))
  2220. (loop c1 c2)))
  2221. (define* (string-closest trial tests #:key (threshold 3))
  2222. &amp;quot;Return the string from TESTS that is the closest from the TRIAL,
  2223. according to 'string-distance'. If the TESTS are too far from TRIAL,
  2224. according to THRESHOLD, then #f is returned.&amp;quot;
  2225. (identity ;discard second return value
  2226. (fold2 (lambda (test closest minimal)
  2227. (let ((dist (string-distance trial test)))
  2228. (if (and (&amp;lt; dist minimal) (&amp;lt; dist threshold))
  2229. (values test dist)
  2230. (values closest minimal))))
  2231. #f +inf.0
  2232. tests)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A lot of the above code is a little bit above my head, but it sure looks cool.&lt;/p&gt;&lt;p&gt;And it actually works better than mine.:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;; old scheme code
  2233. (display (hint-string &amp;quot;bor any&amp;quot; (list &amp;quot;for any&amp;quot; &amp;quot;auth&amp;quot; &amp;quot;rdns&amp;quot;)))
  2234. Try &amp;quot;for any&amp;quot;, &amp;quot;auth&amp;quot;, or &amp;quot;rdns&amp;quot;.
  2235. ;; It didn't match any string. :(
  2236. ;; Let's try guix's (string-closest _) ...
  2237. (string-closest &amp;quot;bor any&amp;quot; (list &amp;quot;for any&amp;quot; &amp;quot;auth&amp;quot; &amp;quot;rdns&amp;quot;))
  2238. $1 = &amp;quot;for any&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Awesome!&lt;/p&gt;</summary></entry><entry><title>Doom Emacs rocks!</title><id>https://gnucode.me/doom-emacs-rocks.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-11-15T13:00:00Z</updated><link href="https://gnucode.me/doom-emacs-rocks.html" rel="alternate" /><summary type="html">&lt;p&gt;I have been using Doom emacs for about 6 months now, and I must say the
  2239. experience is truly wonderful! It is hands down the best Emacs distribution
  2240. that I have ever used. And it is &lt;em&gt;sooo fast&lt;/em&gt;!&lt;/p&gt;&lt;p&gt;I used to own my own emacs config, which is something that everyone should do at
  2241. some point to help you learn more about emacs, but maintaining your own emacs
  2242. config is really hard. You have to:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Fix any bugs that you have. &lt;a href=&quot;https://elpa.gnu.org/packages/bug-hunter.html&quot;&gt;bug hunter is really helpful for this&lt;/a&gt;&lt;/li&gt;&lt;li&gt;examine any cool packages that you may want to add.&lt;/li&gt;&lt;li&gt;Keep up to date with new packages that are probably better than the packages
  2243. that you are using.&lt;/li&gt;&lt;li&gt;Update packages and deal with any new bugs they introduce.&lt;/li&gt;&lt;li&gt;Stay sane with all the complexity.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I did the above for some time, and it is doable. I maintained my own Emacs for
  2244. so long, because it was one of the few coding projects that I actively used and
  2245. worked on. The problem was that my config’s stability varied week to week, and
  2246. it made it harder to focus on actually helping &lt;a href=&quot;https://guix.gnu.org&quot;&gt;GNU Guix&lt;/a&gt;. At a certain point I
  2247. decided that I would rather let someone else maintain a config, so that I could
  2248. spend more time helping a free software project.&lt;/p&gt;&lt;p&gt;I also realized that since I use Doom emacs so often, and it is in need of
  2249. &lt;a href=&quot;https://liberapay.com/hlissner&quot;&gt;funding,&lt;/a&gt; that I should probably go ahead and chip in. I highly reccommend you
  2250. to check out Doom Emacs, and consider donating. Currently the maintainer of
  2251. Doom can only allocate 12 hours per week on the project, but hopefully the
  2252. community will be able to support his work full time.&lt;/p&gt;</summary></entry><entry><title>PinePhone Update</title><id>https://gnucode.me/pinephone-update.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-11-02T12:40:00Z</updated><link href="https://gnucode.me/pinephone-update.html" rel="alternate" /><summary type="html">&lt;p&gt;When I was using Mobian GNU/Linux, I had some issues with the PinePhone. Namely,
  2253. my phone no longer received SMS text messages. I switched to &lt;a href=&quot;https://postmarketos.org/&quot;&gt;PostMarketOS&lt;/a&gt;, and
  2254. my issues seemed to have gone away, at least if I keep using the phone as a dumb
  2255. phone. I have disabled wifi on the phone, because I really don’t use it.&lt;/p&gt;&lt;p&gt;It would be nice if I could get the PinePhone to work well with &lt;a href=&quot;https://jmp.chat&quot;&gt;JMP.chat&lt;/a&gt;, but
  2256. currently the texts from my desktop machine do NOT sync well with the phone. So
  2257. if I use two devices, I end up in a weird situation with out of sync text
  2258. messages, which is really confusing. Plus using the internet on the phone
  2259. drains the battery. So I have just disabled the internet on the phone via the
  2260. hardware kill switches.&lt;/p&gt;&lt;p&gt;Texting works flawlessly, but I cannot get SMS images. Also the phone volume
  2261. for calls is pretty poor. And sometimes when I make phone calls, I cannot hear
  2262. what the other person is saying. So that is a little odd.&lt;/p&gt;&lt;p&gt;I highly recommend installing the reversed engineered and nearly &lt;a href=&quot;https://github.com/the-modem-distro/pinephone_modem_sdk&quot;&gt;libre custom
  2263. firmware&lt;/a&gt; for the PinePhone’s modem. It was actually &lt;a href=&quot;https://www.youtube.com/watch?v=aokclNgnIbE&quot;&gt;super easy to do&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;It might also not be a bad idea to edit the official PinePhone wiki and mention
  2264. that &lt;a href=&quot;https://tello.com/&quot;&gt;Tello&lt;/a&gt; is a fairly cheap provider. I pay them $8 per month and I have no
  2265. data and unlimited calling and texting texts. That’s pretty good.&lt;/p&gt;&lt;p&gt;That’s the main update for today!&lt;/p&gt;</summary></entry><entry><title>Installing OpenBSD on a VM</title><id>https://gnucode.me/installing-openbsd-on-a-vm.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-08-05T07:00:00Z</updated><link href="https://gnucode.me/installing-openbsd-on-a-vm.html" rel="alternate" /><summary type="html">&lt;p&gt;I am of the opinion, that in order to learn how to use an operating system, you
  2266. have to use it often. Since I am madly in love with Guix System, but have an
  2267. interest in the GNU/Hurd and OpenBSD, I might as well install those OSs on a
  2268. virtual machine! I have already done that with the GNU/Hurd, and today I also
  2269. did it for OpenBSD.&lt;/p&gt;&lt;p&gt;I was not that hard to do. I used this guide to &lt;a href=&quot;https://wiki.qemu.org/index.php/Hosts/BSD#OpenBSD&quot;&gt;install OpenBSD on a vm.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;First let’s create a qemu img for OpenBSD.&lt;/p&gt;&lt;p&gt;&lt;code&gt;qemu-img create -f qcow2 hd0.qcow2.img 100G&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Now, let's create an install script.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat install-bsd.sh
  2270. #!/bin/sh
  2271. qemu-system-x86_64 -m 2048 \
  2272. -no-reboot \
  2273. -cdrom cd71.iso \
  2274. -drive if=virtio,file=hd0.qcow2.img,format=qcow2 \
  2275. -enable-kvm \
  2276. -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
  2277. -device virtio-net,netdev=mynet0 \
  2278. -smp 2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As always installing OpenBSD is an absolute breeze. I do not know how to
  2279. manually partition things, so I just chose the auto install. Also OpenBSD
  2280. supports a &lt;code&gt;us.swapcaps.dvorak&lt;/code&gt; keyboard layout. That’s my layout! How cool is
  2281. that!? And it sets up that layout for the console and X by default. Guix
  2282. System does that, but not so well for wayland.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat run-bsd.sh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's create a run script.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;#!/bin/sh
  2283. qemu-system-x86_64 -m 4G \
  2284. -no-reboot \
  2285. -drive if=virtio,file=hd0.qcow2.img,format=qcow2 \
  2286. -enable-kvm \
  2287. -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
  2288. -device virtio-net,netdev=mynet0 \
  2289. -smp 2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I find the &lt;code&gt;-no-reboot&lt;/code&gt; option helpful, because OpenBSD likes to try to autoreboot
  2290. itself, even when you give it the command: &lt;code&gt;halt&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;I have ran OpenBSD before for about a week before, and it is always a pleasure
  2291. to read man afterboot. With OpenBSD the man pages are absolutely excelent.&lt;/p&gt;&lt;p&gt;One of the first things I did was:&lt;/p&gt;&lt;p&gt;&lt;code&gt;# cp /etc/examples/doas.conf /etc/&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Now my user &lt;code&gt;berno&lt;/code&gt; can use &lt;code&gt;doas&lt;/code&gt; to install packages! Let’s install Emacs!&lt;/p&gt;&lt;p&gt;&lt;code&gt;doas pkg_add emacs&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Also OpenBSD has a habit of printing clues to the console after you type in a
  2292. command. For examle, after you install a package, OpenBSD tells you that it has
  2293. installed README files in &lt;code&gt;/usr/local/bsah/blah/README/emacs/&lt;/code&gt;. I find it really
  2294. cool that it reminds you of this. Also, when you run &lt;code&gt;doas syspatch&lt;/code&gt; it will
  2295. tell you that it updated syspatch. It will also say something like:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Please run syspatch again to apply the patches.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;That’s a handy tip! And indeed, &lt;code&gt;doas syspatch -c&lt;/code&gt; showed that the patches had
  2296. not yet been applied.&lt;/p&gt;&lt;p&gt;Also whilst searching for the internet for how to install OpenBSD on a vm image,
  2297. I came accross &lt;a href=&quot;https://www.skreutz.com/posts/autoinstall-openbsd-on-qemu/&quot;&gt;blog post&lt;/a&gt; that describes that you can automate OpenBSD installs.
  2298. That might be something to play with later!&lt;/p&gt;&lt;p&gt;I would like to also set up my local OpenBSD to set up ssh. That way I could do
  2299. something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;#+BEGIN_SRC shell :dir /ssh:berno@localhost:/home/berno :exports both
  2300. ls | wc -l
  2301. #+END_SRC
  2302. #+RESULTS:
  2303. : 9&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I also think it would be fabulous if the OpenBSD team started to make a
  2304. guix-like package manager/distro. I imagine that they could use perl to do it,
  2305. since it seems like OpenBSD has embraced perl as their scripting language, and I
  2306. think it their man pages show that perl can use some rather low lever operating
  2307. system interfaces.&lt;/p&gt;</summary></entry><entry><title>Status Update July 2022</title><id>https://gnucode.me/status-update-july-2022.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-08-02T13:00:00Z</updated><link href="https://gnucode.me/status-update-july-2022.html" rel="alternate" /><summary type="html">&lt;p&gt;So I recently bought a guix system server! It cost me about $250. It’s got 16GB
  2308. of RAM (I can upgrade to 32GB) with a 4TB harddrive. I may play with RAID at
  2309. some point, but that’s a little down the line. If you want some help getting
  2310. something like this for yourself, please contact me. This blog post is my first
  2311. attempt at trying to figure out how to connect to &lt;code&gt;copertino&lt;/code&gt;, to the
  2312. internet. Now on with the blog post!&lt;/p&gt;&lt;p&gt;So when you are like me, and you start to wonder how the internets work, a good
  2313. thing to learn first is difference between &lt;strong&gt;WAN&lt;/strong&gt; and &lt;strong&gt;LAN&lt;/strong&gt;. LAN is your local area
  2314. network. When you are at home, on your computer, you are on your LAN. If your
  2315. computer talks to another computer in your house, then those machines are using
  2316. the LAN. When your computer talks to &lt;code&gt;www.gnu.org&lt;/code&gt;, your computer is accessing
  2317. the WAN, which is the wide area network, usually called the internet.&lt;/p&gt;&lt;p&gt;Computers talk to each other via IP addresses. An IP address is a numerical ID
  2318. that is unique to each computer. Computers use IP address as essentially phone
  2319. numbers to reach out and say, “Hey what time are we having this binary number
  2320. crunching date?” What’s interesting, is computers have more than just a phone
  2321. number, they have a phone number, plus several extensions.&lt;/p&gt;&lt;p&gt;When you call a business, and they say, “Thanks for calling Bank of Scotland.
  2322. Please press 5 to talk to a manager, 4 to talk to a sales person, and 3 to open
  2323. an account. Thanks!” 5, 4, and 3 are extensions. Computers have the same
  2324. thing, on steroids. They calls extensions ports, and there are like 50,000+
  2325. ports. Ports are usually set up to be used by specific applications. For
  2326. example, your web browser uses port 80 and 443 to visit websites.&lt;/p&gt;&lt;p&gt;Here’s a crazy example.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ping -c 1 gnu.org&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;PING gnu.org (209.51.188.116): 56 data bytes
  2327. 64 bytes from 209.51.188.116: icmp&amp;lt;sub&amp;gt;seq&amp;lt;/sub&amp;gt;=0 ttl=55 time=39.078 ms
  2328. — gnu.org ping statistics —
  2329. 1 packets transmitted, 1 packets received, 0% packet loss
  2330. round-trip min/avg/max/stddev = 39.078/39.078/39.078/0.000 ms&lt;/p&gt;&lt;p&gt;So, we now know that gnu.org is serving it’s website on 209.51.188.116. Try
  2331. posting this in a web browser url: 209.51.188.116. You’ll end up at
  2332. savannah.nongnu.org, which is a website that the fabulous people at GNU run.&lt;/p&gt;&lt;p&gt;Anyway, let’s take a look at your IP address:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ip address show&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;1: lo: &amp;lt;LOOPBACK,MULTICAST,UP,LOWER&amp;lt;sub&amp;gt;UP&amp;lt;/sub&amp;gt;&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  2333. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  2334. inet 127.0.0.1/8 scope global lo
  2335. valid&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever preferred&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever
  2336. 2: enp0s25: &amp;lt;BROADCAST,MULTICAST,UP,LOWER&amp;lt;sub&amp;gt;UP&amp;lt;/sub&amp;gt;&amp;gt; mtu 1500 qdisc pfifo&amp;lt;sub&amp;gt;fast&amp;lt;/sub&amp;gt; state UP group default qlen 1000
  2337. link/ether 00:1c:25:9a:37:ba brd ff:ff:ff:ff:ff:ff
  2338. inet 192.168.1.122/24 brd 192.168.1.255 scope global dynamic noprefixroute enp0s25
  2339. valid&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; 22986sec preferred&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; 22986sec
  2340. inet6 fe80::36a7:f91e:a1e0:16fe/64 scope link noprefixroute
  2341. valid&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever preferred&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever
  2342. 3: wlp2s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
  2343. link/ether b6:cf:27:17:7c:fc brd ff:ff:ff:ff:ff:ff permaddr e4:ce:8f:59:d6:bf&lt;/p&gt;&lt;p&gt;Let’s take the above output line by line:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;1: lo: &amp;lt;LOOPBACK,MULTICAST,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  2344. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  2345. inet *127.0.0.1/8* scope global lo
  2346. valid_lft forever preferred_lft forever
  2347. lo is your loopback device, which is fancy talk for &amp;quot;ME&amp;quot;. The embolded
  2348. *127.0.0.1* is a universal alias for &amp;quot;ME&amp;quot;. If you have a web site running on
  2349. your computer, typing in 127.0.0.1:80 lets you access that website. 127.0.0.1:80
  2350. means, talk to the computer at address 127.0.0.1 (which is me), and request the
  2351. content on port 80.
  2352. 2: *enp0s25*: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  2353. link/ether 00:1c:25:9a:37:ba brd ff:ff:ff:ff:ff:ff
  2354. *inet* *192.168.1.122/24* brd 192.168.1.255 scope global dynamic noprefixroute enp0s25
  2355. valid_lft 22986sec preferred_lft 22986sec
  2356. *inet6* *fe80::36a7:f91e:a1e0:16fe/64* scope link noprefixroute
  2357. valid_lft forever preferred_lft forever
  2358. *enp0s25* is your ethernet device. Anything that begins with an 'e' is usually
  2359. an ethernet device. Ethernet is usually the blue cable that you
  2360. plug into your laptop or server. Laptops increasingly do not have ethernet,
  2361. which is sad 'cause ethernet is faster than wifi.
  2362. *init* means IPv4. Remember when I said that computers have IP address? Well
  2363. than have one that looks like *192.168.1.122*. That is the IPv4 address. People
  2364. now adays have phones, tablets, gaming consoles, smart watches, etc. and each
  2365. need an IP address. As a result, the IPv4 address space is getting a little
  2366. crowded. So some smart people introduced IPv6, which has much more unique IDs.
  2367. (Keep reading to see an example IPv6 address).
  2368. Unfortunately for me, an IP address of 192.168.number.number is a LAN IP. That
  2369. means I have to be in my house to talk to view my personal website. I cannot
  2370. view that website at work. :(
  2371. *init6* is IPv6. And *fe80::36a7:f91e:a1e0:16fe* is this computer's IPv6
  2372. address. fe80 is also a LAN IPv6 address. The outside world cannot use that
  2373. address to talk to this local computer.
  2374. 3: *wlp2s0*: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
  2375. link/ether b6:cf:27:17:7c:fc brd ff:ff:ff:ff:ff:ff permaddr e4:ce:8f:59:d6:bf
  2376. This is my wifi device. Anything that begins with an 'w' is usually a wifi device.
  2377. ip route&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;default via 192.168.1.1 dev enp0s25 proto dhcp metric 100
  2378. 192.168.1.0/24 dev enp0s25 proto kernel scope link src 192.168.1.122 metric 100&lt;/p&gt;&lt;p&gt;The number after &lt;strong&gt;default&lt;/strong&gt; is the default gateway. That is my router’s LAN IP
  2379. address. If I type that into a web browser, when I am at home, then I can log
  2380. into my router. Usually your router’s username and password is on a stick on the
  2381. back of your router.&lt;/p&gt;&lt;p&gt;Also, it should be possible for me to log into the router and tell it to open up
  2382. ports 80 and 443 (http and https), so that anyone connecting to say
  2383. &lt;code&gt;www.copertino.me&lt;/code&gt; would be connecting to my computer only, AND NOT my
  2384. roommates’ laptop. However, an attacker could still potentially break into my
  2385. guix system computer, and attack my roommate’s computer.&lt;/p&gt;&lt;p&gt;Also, if you decide to play around with customizing your router, I would
  2386. recommend OpenBSD. OpenBSD potentially has some binary blobs for wifi, which is
  2387. why the &lt;a href=&quot;https://www.gnu.org/distros/free-distros.en.html&quot;&gt;FSF&lt;/a&gt; will not endorse it as a free distro. but if you don’t use wifi,
  2388. then there is no software freedom issues. Anyway, I have recently developed
  2389. quite the crush on OpenBSD, and I found this &lt;a href=&quot;https://openbsdrouterguide.net/&quot;&gt;guide&lt;/a&gt;, that helps you use OpenBSD
  2390. for your router. It’s actually quite comprehensive:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;In this guide we’re going to take a look at how we can use cheap and “low end”
  2391. hardware to build an amazing OpenBSD router with firewalling capabilities,
  2392. segmented local area networks, DNS with domain blocking, DHCP and more.&lt;/p&gt;&lt;p&gt;We will use a setup in which the router segments the local area network (LAN)
  2393. into three separate networks, one for the grown-ups in the house, one for the
  2394. children, and one for public facing servers (a DMZ), such as a private web
  2395. server or mail server. We will also look at how we can use DNS to block out ads,
  2396. porn, and other websites on the Internet. The OpenBSD router can also be used on
  2397. small to mid-size offices.&lt;/p&gt;&lt;/blockquote&gt;</summary></entry><entry><title>Reading my email on the Hurd</title><id>https://gnucode.me/reading-my-email-on-the-hurd.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-07-11T14:30:00Z</updated><link href="https://gnucode.me/reading-my-email-on-the-hurd.html" rel="alternate" /><summary type="html">&lt;p&gt;;tldr The video of all of this blog post is available here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://video.hardlimit.com/w/18NHmZA5sNEgVrZhoq7xna&quot;&gt;https://video.hardlimit.com/w/18NHmZA5sNEgVrZhoq7xna&lt;/a&gt;&lt;/p&gt;&lt;p&gt;So recently I re-set up my Emacs to send email. I usually use Emacs’ Gnus
  2398. mode for reading mailing lists. I have yet to find a better tool to process the
  2399. sheer amount of email that mailing lists through at you. Gnus is cool, but
  2400. it’s also a Turing tarpit (that’s another blog post).&lt;/p&gt;&lt;p&gt;So, if you dear reader want to check your mailing lists via Emacs’ Gnus in a
  2401. Hurd vm, here’s what you want to do:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ wget https://cdimage.debian.org/cdimage/ports/latest/hurd-i386/debian-hurd.img.tar.gz
  2402. $ tar -xz &amp;lt; debian-hurd.img.tar.gz&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Modify my command to start your Hurd vm to your liking:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;qemu-system-i386 -m 4G \
  2403. -drive format=raw,cache=writeback,file=./debian-hurd-20220331.img \
  2404. -net user,hostfwd=tcp:127.0.0.1:2222-:22 -net nic,model=e1000 \
  2405. -no-reboot --enable-kvm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now that you have the Hurd running in a vm, install emacs and msmtp!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo apt-get install emacs msmtp&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Configure msmtp: &lt;a href=&quot;https://wiki.archlinux.org/title/Msmtp&quot;&gt;https://wiki.archlinux.org/title/Msmtp&lt;/a&gt;&lt;/p&gt;&lt;p&gt;That means put in this inside your ~/.msmtprc. Change the values to what you
  2406. need. Check the wiki link above. The arch wiki is awesome!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# Example for a user configuration file ~/.msmtprc
  2407. #
  2408. # Set default values for all following accounts.
  2409. defaults
  2410. # Use the mail submission port 587 instead of the SMTP port 25.
  2411. port 587
  2412. # Always use TLS.
  2413. tls on
  2414. # Set a list of trusted CAs for TLS. The default is to use system settings, but
  2415. # you can select your own file.
  2416. tls_trust_file /etc/ssl/certs/ca-certificates.crt
  2417. logfile ~/.msmtp.log
  2418. # A dismail account
  2419. account dismail.de
  2420. # Host name of the SMTP server
  2421. host smtp.dismail.de
  2422. # Envelope-from address
  2423. from jbranso@dismail.de
  2424. # Authentication. The password is given using one of five methods, see below.
  2425. auth on
  2426. user jbranso@dismail.de
  2427. # Password method 3: Store the password directly in this file. Usually it is not
  2428. # a good idea to store passwords in plain text files. If you do it anyway, at
  2429. # least make sure that this file can only be read by yourself.
  2430. password ReallyAwesomePassword!
  2431. # Set a default account
  2432. account default : dismail.de
  2433. sudo chmod og-rwx ~/.msmtprc&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can test make sure that you can send email via msmtp. Check the
  2434. archlinux wiki page for how to test to see if msmtp works.&lt;/p&gt;&lt;p&gt;Now decide where you want your emacs init file: “~/.emacs” or
  2435. “~/.emacs.d/init.el”.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mkdir ~/.emacs.d
  2436. emacs ~/.emacs.d/init.el&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And you will put this into your emacs:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;;; Some functionality uses this to identify you, e.g. GPG configuration, email
  2437. ;; clients, file templates and snippets.
  2438. (setq user-full-name &amp;quot;Joshua Branson&amp;quot;
  2439. user-mail-address &amp;quot;jbranso@dismail.de&amp;quot;)
  2440. ;; gmail is &amp;quot;imap.dismail.de&amp;quot;
  2441. ;; fastmail.com is a great paid email solution!
  2442. (setq gnus-select-method '(nnimap &amp;quot;imap.dismail.de&amp;quot;))
  2443. ;; use msmtp
  2444. ;; from the emacs wiki: https://www.emacswiki.org/emacs/GnusMSMTP
  2445. (setq message-send-mail-function 'message-send-mail-with-sendmail)
  2446. ;; we substitute sendmail with msmtp
  2447. (setq sendmail-program &amp;quot;/usr/bin/msmtp&amp;quot;)
  2448. ;; This is needed to allow msmtp to do its magic:
  2449. (setq message-sendmail-f-is-evil 't)
  2450. ;;need to tell msmtp which account we're using
  2451. (setq message-sendmail-extra-arguments '(&amp;quot;--read-envelope-from&amp;quot;))
  2452. ;; This is optional, but highly reccommended.
  2453. ;; save email replies to my Sent folder
  2454. (setq gnus-posting-styles
  2455. `((&amp;quot;.*&amp;quot;
  2456. ;; between the &amp;quot;+&amp;quot; and the &amp;quot;:&amp;quot; put the string for
  2457. ;; gnus-select-method
  2458. (gcc &amp;quot;\&amp;quot;nnimap+imap.dismail.de:Sent\&amp;quot;&amp;quot;)
  2459. ;; I use this next line for my dismail filter to mark as read archived messages
  2460. ;; that gnus sends to my Sent folder.
  2461. ;; this next line is optional. You may delete it.
  2462. (&amp;quot;X-Gnus-Sucks&amp;quot; &amp;quot;I know man&amp;quot;)
  2463. )))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Restart Emacs, and &lt;code&gt;M-x m&lt;/code&gt; your first email!&lt;/p&gt;&lt;p&gt;&lt;code&gt;M-x Gnus&lt;/code&gt; starts Gnus for the first time. You might need to read the manual or
  2464. check out a youtube video online to help you set up Gnus for the first time.&lt;/p&gt;</summary></entry><entry><title>Status Update June 2022</title><id>https://gnucode.me/status-update-june-2022.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-07-07T18:00:00Z</updated><link href="https://gnucode.me/status-update-june-2022.html" rel="alternate" /><summary type="html">&lt;p&gt;Sorry for the belated status update.&lt;/p&gt;&lt;p&gt;For June I finally submitted my opensmtpd-records code to be reviewed by guix
  2465. properly. I am fairly happy about that. Here is the url:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://issues.guix.gnu.org/56046&quot;&gt;https://issues.guix.gnu.org/56046&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I also created a short video showing people how you could play with the current
  2466. code base.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://video.hardlimit.com/w/p/bmbYAkQ84BBfF4aAZNAPcR?playlistPosition=8&amp;amp;resume=true&quot;&gt;https://video.hardlimit.com/w/p/bmbYAkQ84BBfF4aAZNAPcR?playlistPosition=8&amp;amp;resume=true&lt;/a&gt;&lt;/p&gt;&lt;h1&gt;I also fixed Emacs again. Somehow I lost the ability to send email via Emacs,&lt;/h1&gt;&lt;p&gt;which is super annoying. I committed everything to git, so hopefully I won’t do
  2467. that again anytime soon. Here is the gist of how I set up email again:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;;; I need to use imap to read my dismail inbox...for some reason, my local gnus
  2468. ;; cannot read my local dovecot Inbox...No idea why.
  2469. (setq gnus-select-method '(nnimap &amp;quot;imap.dismail.de&amp;quot;))
  2470. (setq gnus-secondary-select-methods
  2471. '(
  2472. ;; I would like to use gnus as my maildir, but imap works just fine for now.
  2473. ;; (nnmaildir &amp;quot;dismail.de&amp;quot;
  2474. ;; (nnir-search-engine notmuch)
  2475. ;; (nnir-notmuch-additional-switches &amp;quot;search&amp;quot;)
  2476. ;; (directory &amp;quot;~/.mail/dismail/&amp;quot;))
  2477. ;; (nnmaildir &amp;quot;fastmail&amp;quot; (directory &amp;quot;~/.mail/&amp;quot;))
  2478. ;; (nntp &amp;quot;news.gwene.org&amp;quot;)
  2479. (nntp &amp;quot;news.gmane.io&amp;quot;)
  2480. ;; this makes gnus startup super slow!!! (nnmaildir
  2481. ;; &amp;quot;dismail.de&amp;quot; (directory &amp;quot;~/.mail/dismail.de/&amp;quot;))
  2482. (nnimap &amp;quot;gnucode.me&amp;quot;
  2483. (nnimap-stream ssl)
  2484. (nnimap-address &amp;quot;imap.gnucode.me&amp;quot;)
  2485. (nnimap-user &amp;quot;joshua&amp;quot;))
  2486. ;; this is the right config, but I'm not certain how to set up a dovecot username and password
  2487. (nnimap &amp;quot;localDismail&amp;quot;
  2488. (nnimap-address &amp;quot;localhost&amp;quot;)
  2489. (nnimap-stream network)
  2490. (nnimap-server-port 143)
  2491. )))
  2492. ;; use msmtp
  2493. ;; from the emacs wiki: https://www.emacswiki.org/emacs/GnusMSMTP
  2494. (setq message-send-mail-function 'message-send-mail-with-sendmail)
  2495. ;; we substitute sendmail with msmtp
  2496. (setq sendmail-program &amp;quot;/home/joshua/.guix-profile/bin/msmtp&amp;quot;)
  2497. ;; This is needed to allow msmtp to do its magic:
  2498. (setq message-sendmail-f-is-evil 't)
  2499. ;;need to tell msmtp which account we're using
  2500. (setq message-sendmail-extra-arguments '(&amp;quot;--read-envelope-from&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;I created a simple debbugs function to help me search for guix packages:&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;;; setting up debbugs
  2501. (require 'debbugs-autoloads)
  2502. ;; send mail function so &amp;quot;C&amp;quot; in the debbugs-gnu-mode works
  2503. (setq send-mail-function 'message-send-mail-with-sendmail)
  2504. ;; the below doesn't seem to work
  2505. (setq debbugs-gnu-default-packages '(&amp;quot;guix&amp;quot; &amp;quot;guix-patches&amp;quot;))
  2506. ;; my defun for searching for a package my bug #
  2507. ;; TODO make this seach by default NOT search for closed bugs
  2508. ;; press x for now.
  2509. (defun my-debbugs-search ()
  2510. (interactive)
  2511. (let (string)
  2512. (setq debbugs-gnu-suppress-closed t)
  2513. (setq string (read-string &amp;quot;Search String: &amp;quot;))
  2514. (debbugs-gnu-search string nil nil &amp;quot;guix&amp;quot; nil)))
  2515. (defalias 'my-open-bugs 'debbugs-gnu-tagged)
  2516. my-open-bugs&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;M-x my-dubbugs-search RET 56046 RET&lt;/code&gt; is a pretty cool way to search for open
  2517. guix bug reports. Also &lt;code&gt;M-x debbugs-gnu-search&lt;/code&gt; is broken on doom emacs. It
  2518. keeps prompting you for more input. It never lets you search. Weird.&lt;/p&gt;&lt;p&gt;I also found out that in the debbugs-gnu-mode (the buffer that appears after you
  2519. search for bugs), you can type in “t” to tag yourself to open bugs. This is an
  2520. easy way to remind yourself, which buys you want. Then &lt;code&gt;M-x my-open-bugs&lt;/code&gt; or
  2521. &lt;code&gt;M-x debbugs-gnu-tagged&lt;/code&gt; shows you a buffer of bugs that you are currently
  2522. interested in.&lt;/p&gt;&lt;p&gt;I also learned that I can unarchive, tag, close, and do various other things to bugs by
  2523. pressing the &amp;quot;C&amp;quot; key inside a debbugs-gnu-mode buffer. I actually closed one of my
  2524. old bug reports from inside emacs the other day: &lt;code&gt;M-x my-debbugs-search RET 39271&lt;/code&gt;&lt;/p&gt;&lt;h1&gt;I also played with a proposed patch from Ludo yesterday:&lt;/h1&gt;&lt;p&gt;&lt;code&gt;M-x my-debbugs-search 56114&lt;/code&gt;. Basically, it lets you build a gexp and show the
  2525. output file from the repl. It’s a really nifty patch, and I hope it gets merged
  2526. soon.&lt;/p&gt;&lt;p&gt;In order to play with the proposed patch, I had to learn how to apply patches
  2527. from debbugs to my local guix-src branch:&lt;/p&gt;&lt;p&gt;First find the patch via issues.guix.gnu.org or debbugs.&lt;/p&gt;&lt;p&gt;guix install emacs-debbugs&lt;/p&gt;&lt;p&gt;M-x my-debbugs-search BugNumber RET&lt;/p&gt;&lt;p&gt;Find the email via debbugs, and type in O m to save the file.&lt;/p&gt;&lt;p&gt;Then open up M-x magit-status RET w m to apply the patch.&lt;/p&gt;&lt;p&gt;magit may give you an odd error. But you can always check the log. Sometimes it
  2528. applies the patch, and still gives you an error. In my case, it applied the
  2529. patch that I wanted to play with, but then magit thought there were other
  2530. patches that I may want to apply. Magit was stuck in &amp;quot;applying patches mode&amp;quot;,
  2531. and would not let me re-order commits. My fixed this error by typing &amp;quot;w s&amp;quot;. &amp;quot;w&amp;quot;
  2532. is appylying patches mode. &amp;quot;s&amp;quot; is skip. This fixed the error, and applied the
  2533. patch successfully.&lt;/p&gt;&lt;p&gt;This method works fairly well, if you are applying one patch. But to apply a patch
  2534. series, it may be a be a tedious process.&lt;/p&gt;&lt;p&gt;That’s where this irc conversation comes in handy:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; gnucode │ is there an easy way to apply a patch from debbugs-gnu to my local guix repository?
  2535. unmatched-paren │ gnucode: download the mbox and `git am` away :)
  2536. gnucode │ unmatched-paren that seems very tedious...
  2537. unmatched-paren │ curl might be able to make it easier
  2538. gnucode │ It would be nice if I could apply the patch from emacs and debbugs...just my 2 cents.
  2539. morganw │ I think there is an Emacs package which can apply git patches that are in a mail message.
  2540. unmatched-paren │ I use aerc which allows me to download and apply the mbox automatically, not sure whether $EMACS_MAIL_CLIENT can do that
  2541. unmatched-paren │ aerc command is :pipe -mb git am -3&amp;lt;Enter&amp;gt;
  2542. unmatched-paren │ &amp;quot;pipe the mbox into git am three-way&amp;quot;
  2543. gnucode │ unmatched-paren are you using mbox to read the guix email achives?
  2544. unmatched-paren │ gnucode: what do you mean?
  2545. unmatched-paren │ i think aerc uses maildir by default
  2546. gnucode │ ok. Maybe I should give aerc a try. I keep wanting to use emacs for most of my email and everything needs. But I have a really hard time figuring out how to use it.
  2547. gnucode │ I used to be able to send email via emacs...now I can't.
  2548. morganw │ gnucode: I think this is one some people use: https://git.kyleam.com/piem
  2549. unmatched-paren │ aerc uses vi commands, fyi
  2550. gnucode │ I am using evil-mode
  2551. unmatched-paren │ ah
  2552. unmatched-paren │ gnucode: I'm afraid my patch adding aerc hasn't been merged yet though
  2553. unmatched-paren │ because of the general lack of vi users around here :)
  2554. morganw │ It believe that if you use Gnus there is also a built in command to send the message buffer to a pipe and so something with it.
  2555. morganw │ *do something
  2556. morganw │ Or possibly it was built into message mode, I think I tried it once but I don't remember the exact process.
  2557. unmatched-paren │ maybe there's a way to pipe the mbox too
  2558. gnucode │ I just found this: https://emacs.stackexchange.com/questions/36885/how-do-i-apply-a-patch-from-gnus-to-a-git-repo
  2559. gnucode │ seems promising
  2560. unmatched-paren │ nice!
  2561. ulfvonbelow │ M-&amp;gt; C-&amp;lt;space&amp;gt; M-&amp;lt; M-| &amp;lt;your command here&amp;gt;
  2562. ulfvonbelow │ that works with any buffer btw
  2563. rekado_ │ gnucode: I use mu4e (which uses gnus message mode to display emails) and wired up the mu4e-action-git-apply-mbox action.
  2564. gnucode │ rekado_: do you ever use debbugs?
  2565. rekado_ │ I dog-food mumi / issues.guix.gnu.org
  2566. gnucode │ rekado_: hahah.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See you next time!&lt;/p&gt;</summary></entry><entry><title>Status Update May 2022</title><id>https://gnucode.me/status-update-may-2022.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-05-03T18:00:00Z</updated><link href="https://gnucode.me/status-update-may-2022.html" rel="alternate" /><summary type="html">&lt;p&gt;I have worked more this month on polishing/cleaning up my currect records for
  2567. opensmtpd. I am still finding more things to do, but I am satisified with
  2568. current code base. It is starting to feel like I have less and less things to do.&lt;/p&gt;&lt;p&gt;I have also written some preleminary documentation. The OpenBSD folks’ &lt;code&gt;man smtpd.conf&lt;/code&gt;’ is a work of art. Seriously go read it. I have shamelessly copied
  2569. numerous portions of that documentation to create my own monstrosity.&lt;/p&gt;&lt;p&gt;Whoever ends up committing my code for OpenBSD’s configuration for guix, will
  2570. probably have to revise my rough draft of a document. But at least there is
  2571. visible forward movement in the project. Here is that documentation that I was
  2572. telling you about:&lt;/p&gt;&lt;p&gt;Apologies for the weird exported documentation...&lt;/p&gt;&lt;h1&gt;OpenSMTPD Service documentation&lt;/h1&gt;&lt;p&gt;OpenSMTPD is an easy-to-use mail transfer agent (MTA). Its configuration file is
  2573. throughly documented in man 5 &lt;code&gt;smtpd.conf&lt;/code&gt;. OpenSMTPD &lt;strong&gt;listens&lt;/strong&gt; for incoming
  2574. mail and &lt;strong&gt;matches&lt;/strong&gt; the mail to &lt;strong&gt;actions&lt;/strong&gt;. The following records represent those
  2575. stages: &lt;code&gt;&amp;lt;opensmtpd-listen-on-configuration&amp;gt;&lt;/code&gt;,
  2576. &lt;code&gt;&amp;lt;opensmtpd-listen-on-socket-configuration&amp;gt;=, =&amp;lt;opensmtpd-match-configuration&amp;gt;&lt;/code&gt;,
  2577. &lt;code&gt;&amp;lt;opensmtpd-action-local-delivery-configuration&amp;gt;&lt;/code&gt;, and
  2578. &lt;code&gt;&amp;lt;opensmtpd-action-relay-configuration&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Additionally, each &lt;code&gt;&amp;lt;opensmtpd-listen-on-configuration&amp;gt;&lt;/code&gt; and
  2579. &lt;code&gt;&amp;lt;opensmtpd-listen-on-socket-configuration&amp;gt;&lt;/code&gt; may use a list of
  2580. &lt;code&gt;&amp;lt;opensmtpd-filter-configuration&amp;gt;&lt;/code&gt;, and/or
  2581. &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt; records to filter email/spam. Also
  2582. numerous records’ fieldnames use &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; to hold lists
  2583. or key value pairs of data.&lt;/p&gt;&lt;p&gt;A simple example configuration is below:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(let ((smtp.gnu.org (opensmtpd-pki-configuration
  2584. (domain &amp;quot;smtp.gnu.org&amp;quot;)
  2585. (cert &amp;quot;file.cert&amp;quot;)
  2586. (key &amp;quot;file.key&amp;quot;))))
  2587. (service opensmtpd-service-type
  2588. (opensmtpd-configuration
  2589. (listen-ons (list
  2590. (opensmtpd-listen-on-configuration
  2591. (pki smtp.gnu.org))
  2592. (opensmtpd-listen-on-configuration
  2593. (pki smtp.gnu.org)
  2594. (secure-connection &amp;quot;smtps&amp;quot;))))
  2595. (matches (list
  2596. (opensmtpd-match-configuration
  2597. (action
  2598. (opensmtpd-action-local-delivery-configuration
  2599. (name &amp;quot;local-delivery&amp;quot;))))
  2600. (opensmtpd-match-configuration
  2601. (action
  2602. (opensmtpd-action-relay-configuration
  2603. (name &amp;quot;relay&amp;quot;)))))))))&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Scheme Variable: opensmtpd-service-type&lt;/p&gt;&lt;p&gt;Service type for the OpenSMTPD (&lt;a href=&quot;https://www.opensmtpd.org&quot;&gt;https://www.opensmtpd.org&lt;/a&gt;) email server. The
  2604. value for this service type is a &lt;code&gt;&amp;lt;opensmtpd-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-configuration&lt;/p&gt;&lt;p&gt;Data type representing the configuration of OpenSMTPD.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;package&lt;/code&gt; (default: &lt;code&gt;opensmtpd&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The OpenSMTPD package to use.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;config-file&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;File-like object of the OpenSMTPD configuration file to use. By default it
  2605. listens on the loopback network interface, and allows for mail from users
  2606. and daemons on the local machine, as well as permitting email to remote
  2607. servers. Run &lt;code&gt;man smtpd.conf&lt;/code&gt; for more information.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;bounce&lt;/code&gt; (default: &lt;code&gt;(list &amp;quot;4h&amp;quot;)&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;bounce&lt;/code&gt; is a list of strings, which send warning messages to the envelope
  2608. sender when temporary delivery failures cause a message to remain in the
  2609. queue for longer than string &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;delay&amp;lt;/span&amp;gt;. Each string &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;delay&amp;lt;/span&amp;gt; parameter consists
  2610. of a string beginning with a positive decimal integer and a unit s, m, h,
  2611. or d. At most four delay parameters can be specified.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;listen-ons&lt;/code&gt; (default: &lt;code&gt;(list (opensmtpd-listen-on-configuration))&lt;/code&gt; )&lt;/p&gt;&lt;p&gt;&lt;code&gt;listen-ons&lt;/code&gt; is a list of &lt;code&gt;&amp;lt;opensmtpd-listen-on-configuration&amp;gt;&lt;/code&gt; records.
  2612. This list details what interfaces and ports OpenSMTPD listens on as well as
  2613. other information.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;listen-on-socket&lt;/code&gt; (default: &lt;code&gt;(opensmtpd-listen-on-socket-configuration-configuration)&lt;/code&gt; )&lt;/p&gt;&lt;p&gt;Listens for incoming connections on the Unix domain socket.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;includes&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;includes&lt;/code&gt; is a list of string &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;filenames&amp;lt;/span&amp;gt;. Each filename’s contents is
  2614. additional configuration that is inserted into the top of the configuration
  2615. file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;matches&lt;/code&gt; default:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(list (opensmtpd-match-configuration
  2616. (action (opensmtpd-action-local-delivery-configuration
  2617. (name &amp;quot;local&amp;quot;)
  2618. (method &amp;quot;mbox&amp;quot;)))
  2619. (for (opensmtpd-option-configuration
  2620. (option &amp;quot;for local&amp;quot;))))
  2621. (opensmtpd-match-configuration
  2622. (action (opensmtpd-action-relay-configuration
  2623. (name &amp;quot;outbound&amp;quot;)))
  2624. (from (opensmtpd-option-configuration
  2625. (option &amp;quot;from local&amp;quot;)))
  2626. (for (opensmtpd-option-configuration
  2627. (option &amp;quot;for any&amp;quot;)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;matches&lt;/code&gt; is a list of &lt;code&gt;&amp;lt;opensmtpd-match-configuration&amp;gt;&lt;/code&gt; records, which
  2628. matches incoming mail and sends it to a correspending action. The match
  2629. records are evaluated sequentially, with the first match winning. If an
  2630. incoming mail does not match any match records, then it is rejected.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mta-max-deferred&lt;/code&gt; (default: &lt;code&gt;100&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;When delivery to a given host is suspended due to temporary failures, cache
  2631. at most &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;number&amp;lt;/span&amp;gt; envelopes for that host such that they can be delivered as
  2632. soon as another delivery succeeds to that host. The default is 100.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;queue&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;queue&lt;/code&gt; expects an &lt;code&gt;&amp;lt;opensmtpd-queue-configuration&amp;gt;&lt;/code&gt; record. With it, one may
  2633. compress and encrypt queue-ed emails as well as set the default expiration
  2634. time for temporarily undeliverable messages.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;smtp&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;smtp&lt;/code&gt; expects an &lt;code&gt;&amp;lt;opensmtpd-smtp-configuration&amp;gt;&lt;/code&gt; record, which lets one
  2635. specifiy how large email may be along with other settings.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;srs&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;srs&lt;/code&gt; expects an &lt;code&gt;&amp;lt;opensmtpd-srs-configuration&amp;gt;&lt;/code&gt; record, which lets one set
  2636. up SRS, the Sender Rewritting Scheme.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-listen-on-configuration&lt;/p&gt;&lt;p&gt;Data type representing the configuration of an
  2637. &lt;code&gt;&amp;lt;opensmtpd-listen-on-configuration&amp;gt;&lt;/code&gt;. Listen on the fieldname &lt;code&gt;interface&lt;/code&gt; for
  2638. incoming connections, using the same syntax as for ifconfig(8). The interface
  2639. parameter may also be an string interface group, an string IP address, or a
  2640. string domain name. Listening can optionally be restricted to a specific
  2641. address fieldname &lt;code&gt;family&lt;/code&gt;, which can be either “inet4” or “inet6”.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;interface&lt;/code&gt; (default: “lo”)&lt;/p&gt;&lt;p&gt;The string interface to listen for incoming connections. These interface can
  2642. usually be found by the command &lt;code&gt;ip link&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;family&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The string IP family to use. Valid strings are “inet4” or “inet6”.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;auth&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Support SMTPAUTH: clients may only start SMTP transactions after successful
  2643. authentication. If &lt;code&gt;auth&lt;/code&gt; is &lt;code&gt;#t&lt;/code&gt;, then users are authenticated against
  2644. their own normal login credentials. Alternatively &lt;code&gt;auth&lt;/code&gt; may be an
  2645. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; whose users are authenticated against
  2646. their passwords.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;auth-optional&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Support SMTPAUTH optionally: clients need not authenticate, but may do so.
  2647. This allows the &lt;code&gt;&amp;lt;opensmtpd-listen-on-configuration&amp;gt;&lt;/code&gt; to both accept
  2648. incoming mail from untrusted senders and permit outgoing mail from
  2649. authenticated users (using &lt;code&gt;&amp;lt;opensmtpd-match-configuration&amp;gt;&lt;/code&gt; fieldname
  2650. &lt;code&gt;auth&lt;/code&gt;). It can be used in situations where it is not possible to listen on
  2651. a separate port (usually the submission port, 587) for users to
  2652. authenticate.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;filters&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;A list of one or many &lt;code&gt;&amp;lt;opensmtpd-filter-configuration&amp;gt;&lt;/code&gt; or
  2653. &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt; records. The filters are applied
  2654. sequentially. These records listen and filter on connections handled by this
  2655. listener.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;hostname&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Use string “hostname” in the greeting banner instead of the default server
  2656. name.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;hostnames&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Override the server name for specific addresses. Use a
  2657. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; containing a mapping of string IP
  2658. addresses to hostnames. If the address on which the connection arrives
  2659. appears in the mapping, the associated hostname is used.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mask-src&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If &lt;code&gt;#t&lt;/code&gt;, then omit the from part when prepending “Received” headers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;disable-dsn&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;When &lt;code&gt;#t&lt;/code&gt;, then disable the DSN (Delivery Status Notification) extension.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;pki&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;For secure connections, use an &lt;code&gt;&amp;lt;opensmtpd-pki-configuration&amp;gt;&lt;/code&gt;
  2660. to prove a mail server’s identity.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;port&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Listen on the &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;integer&amp;lt;/span&amp;gt; port instead of the default port of 25.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy-v2&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If &lt;code&gt;#t&lt;/code&gt;, then support the PROXYv2 protocol, rewriting appropriately source
  2661. address received from proxy.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;received-auth&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If &lt;code&gt;#t&lt;/code&gt;, then in “Received” headers, report whether the session was
  2662. authenticated and by which local user.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;senders&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Look up the authenticated user in the supplied
  2663. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; to find the email addresses that user is
  2664. allowed to submit mail as.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;secure-connection&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;This is a string of one of these options:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt; |----------------------+---------------------------------------------|
  2665. | &amp;quot;smtps&amp;quot; | Support SMTPS, by default on port 465. |
  2666. |----------------------+---------------------------------------------|
  2667. | &amp;quot;tls&amp;quot; | Support STARTTLS, by default on port 25. |
  2668. |----------------------+---------------------------------------------|
  2669. | &amp;quot;tls-require-verify&amp;quot; | Like tls, but force clients to establish |
  2670. | | a secure connection before being allowed to |
  2671. | | start an SMTP transaction. With the verify |
  2672. | | option, clients must also provide a valid |
  2673. | | certificate to establish an SMTP session. |
  2674. |----------------------+---------------------------------------------|&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;code&gt;- `tag` (default: `#f`)
  2675. Clients connecting to the listener are tagged with the given string tag.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-listen-on-socket-configuration&lt;/p&gt;&lt;p&gt;Data type representing the configuration of an
  2676. &lt;code&gt;&amp;lt;opensmtpd-listen-on-socket-configuration&amp;gt;&lt;/code&gt;. Listen for incoming SMTP
  2677. connections on the Unix domain socket &lt;code&gt;/var/run/smtpd.sock&lt;/code&gt;. This is done by
  2678. default, even if the directive is absent.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;filters&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;A list of one or many &lt;code&gt;&amp;lt;opensmtpd-filter-configuration&amp;gt;&lt;/code&gt; or
  2679. &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt; records. These filter incoming
  2680. connections handled by this listener.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mask-src&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If &lt;code&gt;#t&lt;/code&gt;, then omit the from part when prepending “Received” headers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;tag&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Clients connecting to the listener are tagged with the given string tag.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-match-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2681. &lt;code&gt;&amp;lt;opensmtpd-match-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;p&gt;If at least one mail envelope matches the options of one match record, receive
  2682. the incoming message, put a copy into each matching envelope, and atomically
  2683. save the envelopes to the mail spool for later processing by the respective
  2684. &lt;code&gt;&amp;lt;opensmtpd-action-configuration&amp;gt;&lt;/code&gt; found in fieldname &lt;code&gt;action&lt;/code&gt;.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;action&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If mail matches this match configuration, then do this action. Valid values
  2685. include &lt;code&gt;&amp;lt;opensmtpd-action-local-delivery-configuration&amp;gt;&lt;/code&gt; or
  2686. &lt;code&gt;&amp;lt;opensmtpd-action-relay-configuration&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;options&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;
  2687. The fieldname ’option’ is a list of unique
  2688. &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt; records.&lt;/p&gt;&lt;p&gt;Each &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt; record’s fieldname ’option’ has some
  2689. mutually exclusive options: there can be one “for” and one “from” option.&lt;/p&gt;&lt;p&gt;The following matching options are supported and can all be negated via (not
  2690. #t). The options that support a table (anything surrounded with ’&amp;lt;’ and ’&amp;gt;’
  2691. eg: &amp;lt;table&amp;gt;), also support specifying regex via (regex #t).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;for any&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may address any destination.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;for local&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may address any local domain. This is the default,
  2692. and may be omitted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;for domain _domain_ | &amp;lt;domain&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may address the string or list table &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;domain&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;for rcpt-to _recipient_ | &amp;lt;recipient&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may address the string or list table &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;recipient&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from any&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may originate from any source.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from auth&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may originate from any authenticated user, no matter
  2693. the source IP address.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from auth _user_ | &amp;lt;user&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may originate from authenticated &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;user&amp;lt;/span&amp;gt; or user list
  2694. user, no matter the source IP address.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from local&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may only originate from a local IP address, or from
  2695. the local enqueuer. This is the default, and may be omitted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from mail-from _sender_ | &amp;lt;sender&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may originate from &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;sender&amp;lt;/span&amp;gt; or table &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;sender&amp;lt;/span&amp;gt;, no
  2696. matter the source IP address.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from rdns&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may only originate from an IP address that resolves
  2697. to a reverse DNS.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from rdns _hostname_ | &amp;lt;hostname&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may only originate from an IP address that resolves
  2698. to a reverse DNS matching string or list string &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;hostname&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from socket&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may only originate from the local enqueuer.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;from src _address_ | &amp;lt;address&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session may only originate from string or list table address
  2699. which can be a specific &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;address&amp;lt;/span&amp;gt; or a subnet expressed in CIDR-notation.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;auth&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Matches transactions which have been authenticated.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;auth _username_ | &amp;lt;username&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Matches transactions which have been authenticated for user or user list
  2700. &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;username&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;helo _helo-name_ | &amp;lt;helo-name&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that session’s HELO / EHLO should match the string or list table
  2701. &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;helo-name&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mail-from _sender_ | &amp;lt;sender&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that transactions’s MAIL FROM should match the string or list
  2702. table &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;sender&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;rcpt-to _recipient_ | &amp;lt;recipient&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Specify that transaction’s RCPT TO should match the string or list table
  2703. &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;recipient&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;tag tag&lt;/code&gt;
  2704. Matches transactions tagged with the given &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;tag&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;tls&lt;/code&gt;
  2705. Specify that transaction should take place in a TLS channel.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here is a simple example:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-option-configuration
  2706. (not #t)
  2707. (regex #f)
  2708. (option &amp;quot;for domain&amp;quot;)
  2709. (data (opensmtpd-table-configuration
  2710. (name &amp;quot;domain-table&amp;quot;)
  2711. (data (list &amp;quot;gnu.org&amp;quot; &amp;quot;dismail.de&amp;quot;)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The mail must NOT come from the domains &lt;code&gt;gnu.org&lt;/code&gt; or &lt;code&gt;dismail.de&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-option-configuration&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-action-local-delivery-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2712. &lt;code&gt;&amp;lt;opensmtpd-action-local-delivery-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; is the string name of the relay action.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;method&lt;/code&gt; (default: &lt;code&gt;&amp;quot;mbox&amp;quot;&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The email delivery option. Valid options are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;quot;mbox&amp;quot;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Deliver the message to the user’s mbox with mail.local(8).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;quot;expand-only&amp;quot;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Only accept the message if a delivery method was specified in an aliases
  2713. or &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;.forward file&amp;lt;/span&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;quot;forward-only&amp;quot;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Only accept the message if the recipient results in a remote address after
  2714. the processing of aliases or forward file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;lt;opensmtpd-lmtp-configuration&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Deliver the message to an LMTP server at
  2715. &lt;code&gt;&amp;lt;opensmtpd-lmtp-configuration&amp;gt;&lt;/code&gt;’s fieldname &lt;code&gt;destination&lt;/code&gt;. The location
  2716. may be expressed as string host:port or as a UNIX socket. Optionally,
  2717. &lt;code&gt;&amp;lt;opensmtpd-lmtp-configuration&amp;gt;&lt;/code&gt;’s fieldname &lt;code&gt;rcpt-to&lt;/code&gt; might be specified
  2718. to use the recipient email address (after expansion) instead of the local
  2719. user in the LMTP session as RCPT TO.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;lt;opensmtpd-maildir-configuration&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Deliver the message to the maildir in
  2720. &lt;code&gt;&amp;lt;opensmtpd-maildir-configuration&amp;gt;&lt;/code&gt;’s fieldname &lt;code&gt;pathname&lt;/code&gt; if specified,
  2721. or by default to &lt;code&gt;~/Maildir&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The pathname may contain format specifiers that are expanded before use
  2722. (see the below section about Format Specifiers).&lt;/p&gt;&lt;p&gt;If &lt;code&gt;&amp;lt;opensmtpd-maildir-configuration&amp;gt;&lt;/code&gt;’s record fieldname &lt;code&gt;junk&lt;/code&gt; is &lt;code&gt;#t&lt;/code&gt;,
  2723. then message will be moved to the ‘Junk’ folder if it contains a positive
  2724. ‘X-Spam’ header. This folder will be created under fieldname &lt;code&gt;pathname&lt;/code&gt; if
  2725. it does not yet exist.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;lt;opensmtpd-mda-configuration&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Delegate the delivery to the &lt;code&gt;&amp;lt;opensmtpd-mda-configuration&amp;gt;&lt;/code&gt;’s fieldname
  2726. &lt;code&gt;command&lt;/code&gt; (type string) that receives the message on its standard input.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;command&lt;/code&gt; may contain format specifiers that are expanded before use
  2727. (see Format Specifiers).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;alias&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Use the mapping table for aliases expansion. &lt;code&gt;alias&lt;/code&gt; is an
  2728. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;ttl&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;ttl&lt;/code&gt; is a string specify how long a message may remain in the queue. It’s
  2729. format is &lt;code&gt;n{s|m|h|d}&lt;/code&gt;. eg: “4m” is four minutes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;user&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt; )&lt;/p&gt;&lt;p&gt;&lt;code&gt;user&lt;/code&gt; is the string username for performing the delivery, to be looked up
  2730. with getpwnam(3).&lt;/p&gt;&lt;p&gt;This is used for virtual hosting where a single username is in charge of
  2731. handling delivery for all virtual users.&lt;/p&gt;&lt;p&gt;This option is not usable with the mbox delivery method.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;userbase&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;userbase&lt;/code&gt; is an &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; record for mapping user
  2732. lookups instead of the getpwnam(3) function.&lt;/p&gt;&lt;p&gt;The fieldnames &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;userbase&lt;/code&gt; are mutually exclusive.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;virtual&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;virtual&lt;/code&gt; is an &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; record is used for virtual
  2733. expansion.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-action-relay-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2734. &lt;code&gt;&amp;lt;opensmtpd-action-relay-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; is the string name of the relay action.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;backup&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;When &lt;code&gt;#t&lt;/code&gt;, operate as a backup mail exchanger delivering messages to any
  2735. mail exchanger with higher priority.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;backup-mx&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Operate as a backup mail exchanger delivering messages to any mail exchanger
  2736. with higher priority than mail exchanger identified as string name.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;helo&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Advertise string heloname as the hostname to other mail exchangers during
  2737. the HELO phase.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;helo-src&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt; )&lt;/p&gt;&lt;p&gt;Use the mapping &lt;code&gt;&amp;lt;openmstpd-table-configuration&amp;gt;&lt;/code&gt; to look up a hostname
  2738. matching the source address, to advertise during the HELO phase.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;domain&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Do not perform MX lookups but look up destination domain in an
  2739. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; and use matching relay url as relay host.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;host&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Do not perform MX lookups but relay messages to the relay host described by
  2740. the string relay-url. The format for relay-url is
  2741. &lt;code&gt;[proto://[label@]]host[:port]&lt;/code&gt;. The following protocols are available:&lt;/p&gt;&lt;p&gt;Unless noted, port defaults to 25.&lt;/p&gt;&lt;p&gt;The label corresponds to an entry in a credentials table, as documented in
  2742. &lt;code&gt;table(5)&lt;/code&gt;. It is used with the &lt;code&gt;&amp;quot;smtp+tls&amp;quot;&lt;/code&gt; and &lt;code&gt;&amp;quot;smtps&amp;quot;&lt;/code&gt; protocols for
  2743. authentication. Server certificates for those protocols are verified by
  2744. default.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;pki&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;For secure connections, use the certificate associated with
  2745. &lt;code&gt;&amp;lt;opensmtpd-pki-configuration&amp;gt;&lt;/code&gt; (declared in a pki directive) to prove the
  2746. client’s identity to the remote mail server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;srs&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If &lt;code&gt;#t&lt;/code&gt;, then when relaying a mail resulting from a forward, use the Sender
  2747. Rewriting Scheme to rewrite sender address.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;tls&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) boolean or string “no-verify”&lt;/p&gt;&lt;p&gt;When &lt;code&gt;#t&lt;/code&gt;, Require TLS to be used when relaying, using mandatory STARTTLS by
  2748. default. When used with a smarthost, the protocol must not be
  2749. &lt;code&gt;&amp;quot;smtp+notls://&amp;quot;&lt;/code&gt;. When string &lt;code&gt;&amp;quot;no-verify&amp;quot;&lt;/code&gt;, then do not require a valid
  2750. certificate.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;auth&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Use the alist &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; for connecting to relay-url
  2751. using credentials. This option is usable only with fieldname &lt;code&gt;host&lt;/code&gt; option.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mail-from&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) string&lt;/p&gt;&lt;p&gt;Use the string &amp;lt;span class=&amp;quot;underline&amp;quot;&amp;gt;mailaddress&amp;lt;/span&amp;gt; as MAIL FROM address within the SMTP transaction.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;src&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) string | &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Use the string or &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; sourceaddr for the
  2752. source IP address, which is useful on machines with multiple interfaces. If
  2753. the list contains more than one address, all of them are used in such a way
  2754. that traffic is routed as efficiently as possible.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-filter-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2755. &lt;code&gt;&amp;lt;opensmtpd-filter-configuration&amp;gt;&lt;/code&gt;. This is the filter record one should use
  2756. if they want to use an external package to filter email eg: rspamd or
  2757. spamassassin.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The string name of the filter.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;proc&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The string command or process name. If &lt;code&gt;proc-exec&lt;/code&gt; is &lt;code&gt;#t&lt;/code&gt;, &lt;code&gt;proc&lt;/code&gt; is
  2758. treated as a command to execute. Otherwise, it is a process name.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;proc-exec&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-filter-phase-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2759. &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;In a regular workflow, smtpd(8) may accept or reject a message based only on
  2760. the content of envelopes. Its decisions are about the handling of the message,
  2761. not about the handling of an active session.&lt;/p&gt;&lt;p&gt;Filtering extends the decision making process by allowing smtpd(8) to stop at
  2762. each phase of an SMTP session, check that options are met, then decide if a
  2763. session is allowed to move forward.&lt;/p&gt;&lt;p&gt;With filtering via an &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt; record, a
  2764. session may be interrupted at any phase before an envelope is complete. A
  2765. message may also be rejected after being submitted, regardless of whether the
  2766. envelope was accepted or not.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The string name of the filter phase.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;phase-name&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;The string name of the phase. Valid values are:&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;options&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;A list of unique &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt; records.&lt;/p&gt;&lt;p&gt;At each phase, various options, specified by a list of
  2767. &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;, may be checked. The
  2768. &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;’s fieldname ’option’ values of: “fcrdns”,
  2769. “rdns”, and “src” data are available in all phases, but other data must have
  2770. been already submitted before they are available. Options with a &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;
  2771. next to them require the &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;’s fieldname
  2772. &lt;code&gt;data&lt;/code&gt; to be an &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt;. There are the available
  2773. options:&lt;/p&gt;&lt;p&gt;These conditions may all be negated by setting
  2774. &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;’s fieldname &lt;code&gt;not&lt;/code&gt; to &lt;code&gt;#t&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Any conditions that require a table may indicate that tables include regexs
  2775. setting &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;’s fieldname &lt;code&gt;regex&lt;/code&gt; to &lt;code&gt;#t&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;decision&lt;/code&gt;&lt;/p&gt;&lt;p&gt;A string decision to be taken. Some decisions require an &lt;code&gt;message&lt;/code&gt; or
  2776. &lt;code&gt;value&lt;/code&gt;. Valid strings are:&lt;/p&gt;&lt;p&gt;Decisions that involve a message require that the message be RFC valid,
  2777. meaning that they should either start with a 4xx or 5xx status code.
  2778. Descisions can be taken at any phase, though junking can only happen before
  2779. a message is committed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;message&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;A string message beginning with a 4xx or 5xx status code.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;value&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;A number value. &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt; are mutually exclusive.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-option-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2780. &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt;, which is used by
  2781. &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;opensmtpd-match-configuration&amp;gt;&lt;/code&gt;
  2782. to match various options for email.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;conditition&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;A string option to be taken. Some options require a string or an
  2783. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; via the fieldname data. When the option
  2784. record is used inside of an &lt;code&gt;&amp;lt;opensmtpd-filter-phase-configuration&amp;gt;&lt;/code&gt;, then
  2785. valid strings are:&lt;/p&gt;&lt;p&gt;At each phase, various options may be matched. The fcrdns, rdns, and src
  2786. data are available in all phases, but other data must have been already
  2787. submitted before they are available.&lt;/p&gt;&lt;p&gt;When &lt;code&gt;&amp;lt;opensmtpd-option-configuration&amp;gt;&lt;/code&gt; is used inside of an
  2788. &lt;code&gt;&amp;lt;opensmtpd-match-configuration&amp;gt;&lt;/code&gt;, then valid strigs for fieldname &lt;code&gt;option&lt;/code&gt;
  2789. are: “for”, “for any”, “for local”, “for domain”, “for rcpt-to”, “from any”
  2790. “from auth”, “from local”, “from mail-from”, “from rdns”, “from socket”,
  2791. “from src”, “auth”, “helo”, “mail-from”, “rcpt-to”, “tag”, or “tls”.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;data&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;) &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Some options require a table to be present. One would specify that table
  2792. here.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;regex&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) boolean&lt;/p&gt;&lt;p&gt;Any options using a table may indicate that tables hold regex by
  2793. prefixing the table name with the keyword regex.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;not&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;) boolean&lt;/p&gt;&lt;p&gt;When &lt;code&gt;#t&lt;/code&gt;, this option record is negated.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-table-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2794. &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt; is the name of the &lt;code&gt;&amp;lt;opensmtpd-table-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;data&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;data&lt;/code&gt; expects a list of strings or an alist, which is a list of
  2795. cons cells. eg: &lt;code&gt;(data (list (&amp;quot;james&amp;quot; . &amp;quot;password&amp;quot;)))&lt;/code&gt; OR
  2796. &lt;code&gt;(data (list (&amp;quot;gnu.org&amp;quot; &amp;quot;fsf.org&amp;quot;)))&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-pki-configuration&lt;/p&gt;&lt;p&gt;This data type represents the configuration of an
  2797. &lt;code&gt;&amp;lt;opensmtpd-pki-configuration&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;domain&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;domain&lt;/code&gt; is the string name of the &lt;code&gt;&amp;lt;opensmtpd-pki-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;cert&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;cert&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;cert&lt;/code&gt; is the string certificate filename to use for this pki.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;key&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;key&lt;/code&gt; is the string certificate falename to use for this pki.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dhe&lt;/code&gt; (default: &lt;code&gt;&amp;quot;none&amp;quot;&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Specify the DHE string parameter to use for DHE cipher suites with host
  2798. pkiname. Valid parameter values are “none”, “legacy”, or “auto”. For “legacy”, a
  2799. fixed key length of 1024 bits is used, whereas for “auto”, the key length is
  2800. determined automatically. The default is “none”, which disables DHE cipher
  2801. suites.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-maildir-configuration&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;pathname&lt;/code&gt; (default: &lt;code&gt;&amp;quot;~/Maildir&amp;quot;&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Deliver the message to the maildir if pathname if specified, or by default
  2802. to &lt;code&gt;~/Maildir&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The pathname may contain format specifiers that are expanded before use
  2803. (see FORMAT SPECIFIERS).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;junk&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;If the junk argument is &lt;code&gt;#t&lt;/code&gt;, then the message will be moved to the &lt;code&gt;‘Junk’&lt;/code&gt;
  2804. folder if it contains a positive &lt;code&gt;‘X-Spam’&lt;/code&gt; header. This folder will be
  2805. created under pathname if it does not yet exist.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-mda-configuration&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The string name for this MDA command.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Delegate the delivery to a command that receives the message on its standard
  2806. input.&lt;/p&gt;&lt;p&gt;The command may contain format specifiers that are expanded before use (see
  2807. FORMAT SPECIFIERS).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-queue-configuration&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;compression&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Store queue files in a compressed format. This may be useful to save disk
  2808. space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;encryption&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Encrypt queue files with EVP&amp;lt;sub&amp;gt;aes&amp;lt;/sub&amp;gt;&amp;lt;sub&amp;gt;256&amp;lt;/sub&amp;gt;&amp;lt;sub&amp;gt;gcm&amp;lt;/sub&amp;gt;(3). If no key is specified, it is
  2809. read with getpass(3). If the string stdin or a single dash (‘-’) is given
  2810. instead of a key, the key is read from the standard input.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;ttl-delay&lt;/code&gt; (default &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Set the default expiration time for temporarily undeliverable messages,
  2811. given as a positive decimal integer followed by a unit s, m, h, or d. The
  2812. default is four days (“4d”).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-smtp-configuration&lt;/p&gt;&lt;p&gt;Data type representing an &lt;code&gt;&amp;lt;opensmtpd-smtp-configuration&amp;gt;&lt;/code&gt; record.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;ciphers&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Set the control string for SSL&amp;lt;sub&amp;gt;CTX&amp;lt;/sub&amp;gt;&amp;lt;sub&amp;gt;set&amp;lt;/sub&amp;gt;&amp;lt;sub&amp;gt;cipher&amp;lt;/sub&amp;gt;&amp;lt;sub&amp;gt;list&amp;lt;/sub&amp;gt;(3). The default is
  2813. “HIGH:!aNULL:!MD5”.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;limit-max-mails&lt;/code&gt; (default: &lt;code&gt;100&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Limit the number of messages to count for each sessio&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;limit-max-rcpt&lt;/code&gt; (default: &lt;code&gt;1000&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Limit the number of recipients to count for each transaction.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;max-message-size&lt;/code&gt; (default: &lt;code&gt;35M&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Reject messages larger than size, given as a positive number of bytes or as
  2814. a string to be parsed with scan&amp;lt;sub&amp;gt;scaled&amp;lt;/sub&amp;gt;(3).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;sub-addr-delim character&lt;/code&gt; (default: &lt;code&gt;+&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;When resolving the local part of a local email address, ignore the ASCII
  2815. character and all characters following it. This is helpful for email
  2816. filters. &lt;code&gt;&amp;quot;admin+bills@gnu.org&amp;quot;&lt;/code&gt; is the same email address as
  2817. &lt;code&gt;&amp;quot;admin@gnu.org&amp;quot;&lt;/code&gt;. BUT an email filter can filter emails addressed to first
  2818. email address into a ’Bills’ email folder.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Data Type: opensmtpd-srs-configuration&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;key&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Set the secret key to use for SRS, the Sender Rewriting Scheme.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;backup-key&lt;/code&gt; (default: &lt;code&gt;#f&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Set a backup secret key to use as a fallback for SRS. This can be used to
  2819. implement SRS key rotation.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;ttl-delay&lt;/code&gt; (default: &lt;code&gt;&amp;quot;4d&amp;quot;&lt;/code&gt;)&lt;/p&gt;&lt;p&gt;Set the time-to-live delay for SRS envelopes. After this delay, a bounce
  2820. reply to the SRS address will be discarded to limit risks of forged
  2821. addresses.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Format Specifiers&lt;/p&gt;&lt;p&gt;Some configuration records support expansion of their parameters at
  2822. runtime. Such records (for example
  2823. &lt;code&gt;&amp;lt;opensmtpd-maildir-configuration&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;opensmtpd-mda-configuration&amp;gt;&lt;/code&gt;) may use
  2824. format specifiers which are expanded before delivery or relaying. The
  2825. following formats are currently supported:&lt;/p&gt;&lt;p&gt;Expansion formats also support partial expansion using the optional bracket notations
  2826. with substring offset. For example, with recipient domain &lt;code&gt;“example.org”&lt;/code&gt;:&lt;/p&gt;&lt;p&gt;In addition, modifiers may be applied to the token. For example, with recipient
  2827. &lt;code&gt;“User+Tag@Example.org”&lt;/code&gt;:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary></entry><entry><title>Status Update April 2022</title><id>https://gnucode.me/status-update-april-2022.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-04-01T18:00:00Z</updated><link href="https://gnucode.me/status-update-april-2022.html" rel="alternate" /><summary type="html">&lt;p&gt;I am back to working on various records to support &lt;code&gt;&amp;lt;opensmtpd-configuration&amp;gt;&lt;/code&gt;
  2828. for the &lt;code&gt;opensmtpd-service-type&lt;/code&gt;. I decided about a week ago, to just do some
  2829. of the changes in the records that I want to do. Once I am satisfied with the
  2830. updates, then I will work on making the code output the &lt;code&gt;smtpd.conf&lt;/code&gt; file. I am
  2831. fairly please with some of the changes to the records that I have made.&lt;/p&gt;&lt;p&gt;Feel free to play with the examples below from my repo!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;https://notabug.org/jbranso/linode-guix-system-configuration.git
  2832. guile -L .
  2833. scheme@(guile-user)&amp;gt; ,use (opensmtpd-records)
  2834. scheme@(guile-user)&amp;gt; ,m (opensmtpd-records)
  2835. (opensmtpd-table (name &amp;quot;table&amp;quot;) (values (list &amp;quot;hello&amp;quot; &amp;quot;world&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Please note, that I am still working on changing the record names, so various
  2836. things that work as described in the blog post may not work in a week or two.&lt;/p&gt;&lt;h2&gt;a pretty useful &lt;code&gt;&amp;lt;opensmtpd-configuration&amp;gt;&lt;/code&gt; gives no errors&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;(define example-opensmtpd-configuration
  2837. (let ([interface &amp;quot;lo&amp;quot;]
  2838. [creds-table (opensmtpd-table
  2839. (name &amp;quot;creds&amp;quot;)
  2840. (values
  2841. (list
  2842. (cons &amp;quot;joshua&amp;quot;
  2843. &amp;quot;$some$encrypted$password&amp;quot;))))]
  2844. [receive-action (opensmtpd-action-local-delivery-configuration
  2845. (name &amp;quot;receive&amp;quot;)
  2846. (method (opensmtpd-maildir-configuration
  2847. (pathname &amp;quot;/home/%{rcpt.user}/Maildir&amp;quot;)
  2848. (junk #t)))
  2849. (virtual (opensmtpd-table
  2850. (name &amp;quot;virtual&amp;quot;)
  2851. (values (list &amp;quot;josh&amp;quot; &amp;quot;jbranso@dismail.de&amp;quot;)))))]
  2852. [filter-dkimsign (opensmtpd-filter
  2853. (name &amp;quot;dkimsign&amp;quot;)
  2854. (exec #t)
  2855. (proc (string-append &amp;quot;/path/to/dkimsign -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k &amp;quot;
  2856. &amp;quot;/path/to/dkimsign-key user nobody group nobody&amp;quot;)))]
  2857. [smtp.gnucode.me (opensmtpd-pki
  2858. (domain &amp;quot;smtp.gnucode.me&amp;quot;)
  2859. (cert &amp;quot;opensmtpd.scm&amp;quot;)
  2860. (key &amp;quot;opensmtpd.scm&amp;quot;))])
  2861. (opensmtpd-configuration
  2862. (mta-max-deferred 50)
  2863. (queue
  2864. (opensmtpd-queue-configuration
  2865. (compression #t)))
  2866. (smtp
  2867. (opensmtpd-smtp-configuration
  2868. (max-message-size &amp;quot;10M&amp;quot;)))
  2869. (srs
  2870. (opensmtpd-srs-configuration
  2871. (ttl-delay &amp;quot;5d&amp;quot;)))
  2872. (listen-ons
  2873. (list
  2874. (opensmtpd-listen-on
  2875. (interface interface)
  2876. (port 25)
  2877. (secure-connection &amp;quot;tls&amp;quot;)
  2878. (filters (list (opensmtpd-filter-phase
  2879. (name &amp;quot;noFRDNS&amp;quot;)
  2880. (phase &amp;quot;commit&amp;quot;)
  2881. (conditions (list (opensmtpd-conditions-configuration
  2882. (condition &amp;quot;fcrdns&amp;quot;)
  2883. (not #t))))
  2884. (decision &amp;quot;disconnect&amp;quot;)
  2885. (message &amp;quot;No FCRDNS&amp;quot;))))
  2886. (pki smtp.gnucode.me))
  2887. ;; this lets local users logged into the system via ssh send email
  2888. (opensmtpd-listen-on
  2889. (interface interface)
  2890. (port 465)
  2891. (secure-connection &amp;quot;smtps&amp;quot;)
  2892. (pki smtp.gnucode.me)
  2893. (auth creds-table)
  2894. (filters (list filter-dkimsign)))
  2895. (opensmtpd-listen-on
  2896. (interface interface)
  2897. (port 587)
  2898. (secure-connection &amp;quot;tls-require&amp;quot;)
  2899. (pki smtp.gnucode.me)
  2900. (auth creds-table)
  2901. (filters (list filter-dkimsign)))))
  2902. (matches (list
  2903. (opensmtpd-match
  2904. (action (opensmtpd-action-relay-configuration
  2905. (name &amp;quot;relay&amp;quot;)))
  2906. (for (opensmtpd-match-configuration
  2907. (option &amp;quot;for any&amp;quot;)))
  2908. (from (opensmtpd-match-configuration
  2909. (option &amp;quot;from any&amp;quot;)))
  2910. (auth (opensmtpd-match-configuration
  2911. (option &amp;quot;auth&amp;quot;))))
  2912. (opensmtpd-match
  2913. (action receive-action)
  2914. (from (opensmtpd-match-configuration
  2915. (option &amp;quot;from any&amp;quot;)))
  2916. (for (opensmtpd-match-configuration
  2917. (option &amp;quot;for domain&amp;quot;)
  2918. (value (opensmtpd-table
  2919. (name &amp;quot;domain-table&amp;quot;)
  2920. (values (list &amp;quot;gnucode.me&amp;quot; &amp;quot;gnu-hurd.com&amp;quot;)))))))
  2921. (opensmtpd-match
  2922. (action receive-action)
  2923. (for (opensmtpd-match-configuration
  2924. (option &amp;quot;for local&amp;quot;)))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However there’s still some work to do because this doesn’t work:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-configuration-&amp;gt;mixed-text-file example-opensmtpd-configuration)
  2925. ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  2926. error: value: unbound variable
  2927. Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
  2928. scheme@(opensmtpd-records) [12]&amp;gt; ,bt
  2929. In /home/joshua/prog/gnu/guix/guix-config/linode-guix-system-configuration/opensmtpd-records.scm:
  2930. 1667:3 4 (opensmtpd-configuration-&amp;gt;mixed-text-file #&amp;lt;&amp;lt;opensmtpd-configuration&amp;gt; package: #&amp;lt;package opensmtpd@6.8.0p2 gnu/packages/mail.scm:2979 7f1e1a3…&amp;gt;)
  2931. 1628:9 3 (opensmtpd-configuration-fieldname-&amp;gt;string _ _ _)
  2932. 1634:10 2 (list-of-records-&amp;gt;string _ _)
  2933. 1669:99 1 (_ _)
  2934. In ice-9/boot-9.scm:
  2935. 1685:16 0 (raise-exception _ #:continuable? _)&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;I have also sanitized the &lt;code&gt;&amp;lt;opensmtpd-conditions-configuration&amp;gt;&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;If you type in various incorrectly written
  2936. &lt;code&gt;&amp;lt;opensmtpd-conditions-configuration&amp;gt;&lt;/code&gt; records, then you will get some helpful
  2937. error messages:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;if condition is rdns, src, helo, mail-from, rcpt-to, then they must also provide a table&lt;/p&gt;&lt;p&gt;What is interesting, is that I do not know how to sanitize a whole record when
  2938. the record is initiated. I can only have a parent record sanitize it. For
  2939. example the following record is invalid, because if the ’condition’ is “src”,
  2940. then you need to provide a table. However, the following works in a REPL.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-conditions-configuration
  2941. (condition &amp;quot;src&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;$11 = #&amp;lt;&amp;lt;opensmtpd-conditions-configuration&amp;gt; condition: &amp;quot;src&amp;quot; not: #f regex: #f table: #f&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;But when you put the same incorrect &lt;code&gt;&amp;lt;opensmtpd-conditions-configuration&amp;gt;&lt;/code&gt;
  2942. into an &lt;code&gt;&amp;lt;opensmtpd-filter-phase&amp;gt;&lt;/code&gt;, then you get the right error message.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-filter-phase
  2943. (name &amp;quot;filter&amp;quot;)
  2944. (phase &amp;quot;helo&amp;quot;)
  2945. (decision &amp;quot;bypass&amp;quot;)
  2946. (conditions
  2947. (list
  2948. (opensmtpd-conditions-configuration
  2949. (condition &amp;quot;src&amp;quot;)))))
  2950. &amp;lt;opensmtpd-conditions-configuration&amp;gt;'s fieldname 'condition' values of
  2951. 'src', 'helo', 'mail-from', or 'rcpt-to' need a corresponding 'table'
  2952. of type &amp;lt;opensmtpd-table&amp;gt;. eg:
  2953. (opensmtpd-conditions-configuration
  2954. (condition &amp;quot;src&amp;quot;)
  2955. (table (opensmtpd-table
  2956. (name &amp;quot;src-table&amp;quot;)
  2957. (values (list &amp;quot;hello&amp;quot; &amp;quot;cat&amp;quot;)))))
  2958. ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  2959. Throw to key `bad!' with args `((#&amp;lt;&amp;lt;opensmtpd-conditions-configuration&amp;gt; condition: &amp;quot;mail-from&amp;quot; not: #f regex: #f table: #f&amp;gt;))'.
  2960. Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;make sure that there are no duplicate conditions&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-filter-phase
  2961. (name &amp;quot;noFRDNS&amp;quot;)
  2962. (phase &amp;quot;commit&amp;quot;)
  2963. (conditions (list (opensmtpd-conditions-configuration
  2964. (condition &amp;quot;fcrdns&amp;quot;)
  2965. (not #t))
  2966. (opensmtpd-conditions-configuration
  2967. (condition &amp;quot;fcrdns&amp;quot;)
  2968. (not #t))))
  2969. (decision &amp;quot;disconnect&amp;quot;)
  2970. (message &amp;quot;No FCRDNS&amp;quot;))
  2971. &amp;lt;opensmtpd-filter-phase&amp;gt; fieldname: 'conditions' is a list of unique
  2972. &amp;lt;opensmtpd-conditions-configuration&amp;gt; records.
  2973. ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  2974. Throw to key `bad!' with args `((#&amp;lt;&amp;lt;opensmtpd-conditions-configuration&amp;gt; condition: &amp;quot;fcrdns&amp;quot; not: #t regex: #f table: #f&amp;gt; #&amp;lt;&amp;lt;opensmtpd-conditions-configuration&amp;gt; condition: &amp;quot;fcrdns&amp;quot; not: #t regex: #f table: #f&amp;gt;))'.
  2975. Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;sanitize the phase-name&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-filter-phase
  2976. (name &amp;quot;filter&amp;quot;)
  2977. (phase &amp;quot;hello&amp;quot;)
  2978. (decision &amp;quot;bypass&amp;quot;)
  2979. (conditions
  2980. (list
  2981. (opensmtpd-conditions-configuration
  2982. (condition &amp;quot;auth&amp;quot;)))))
  2983. &amp;lt;opensmtpd-filter-phase&amp;gt; fieldname: 'phase' is of type string. The string can be either 'connect', 'helo', 'mail-from', 'rcpt-to', 'data', or 'commit.'
  2984. ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  2985. Throw to key `bad!' with args `(&amp;quot;hello&amp;quot;)'.
  2986. Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Changes to the records eleminate potential errors like&lt;/h2&gt;&lt;p&gt;misspelling a table name, or calling an action that is not defined.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;&amp;lt;opensmtpd-configuration&amp;gt;&lt;/code&gt; used to be defined this way:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service opensmtpd-service
  2987. (opensmtpd-configuration
  2988. (includes ...)
  2989. (tables ...)
  2990. (pkis ...)
  2991. (filters ...)
  2992. (listen-on ...)
  2993. (actions ...)
  2994. (matches ...)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It would be possible to give a table a name of “password-table”, but then later
  2995. to refer to it as “passwords-table”, which would NOT have worked. Like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service opensmtpd-service
  2996. (opensmtpd-configuration
  2997. (tables (list (opensmtpd-table
  2998. (name &amp;quot;&amp;lt;passwords-table&amp;gt;&amp;quot;)
  2999. (values
  3000. (list
  3001. (cons &amp;quot;joshua&amp;quot;
  3002. &amp;quot;$encrypted$password&amp;quot;))))))
  3003. (listen-on
  3004. (list (opensmtpd-listen-on
  3005. (auth &amp;quot;&amp;lt;password-table&amp;gt;&amp;quot; ))))
  3006. (actions ...)
  3007. (matches ...)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now instead, you define the table where it is used!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(opensmtpd-listen-on
  3008. (interface interface)
  3009. (port 587)
  3010. (secure-connection &amp;quot;tls-require&amp;quot;)
  3011. (pki smtp.gnucode.me)
  3012. (auth (opensmtpd-table
  3013. (name &amp;quot;creds&amp;quot;)
  3014. (values
  3015. (list
  3016. (cons &amp;quot;joshua&amp;quot;
  3017. &amp;quot;$encrypted$password&amp;quot;)))))
  3018. (filters (list filter-dkimsign)))&lt;/code&gt;&lt;/pre&gt;</summary></entry></feed>