123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015 |
- <?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>2024-04-18T01:18:57Z</updated><link href="https://gnucode.me/feed.xml" rel="self" /><link href="https://gnucode.me" /><entry><title>OpenBSD's Philosophy</title><id>https://gnucode.me/openbsds-philosophy.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2024-04-17T18:00:00Z</updated><link href="https://gnucode.me/openbsds-philosophy.html" rel="alternate" /><content type="html"><p>I have talked about OpenBSD before in this blog, and I recently
- watched a talk by OpenBSD's leader Theo de Raadt about <code>pledge ()</code> and
- <code>arc4random()</code>. He described OpenBSD's design philosophy so well, that
- I wanted to write it down. You should definitely take some time to
- hear Theo speak. He's entertaining, and his talks are super awesome!</p><p>So a long time ago (early 90s ?), a cracker (1) broke into Theo's
- OpenBSD's syslog. This got Theo to examine OpenBSD's source code to
- fix any lingering bugs, and he found a lot. He realized that trying
- to constantly examine source code to prevent bugs is a never ending
- process. He wanted to ensure code quality got better over time. He
- envision an operating system that that enforced code correctness like
- the below ASCII art shows.</p><pre><code>__________________________
- | Poorly written programs |
- | crash on OpenBSD. |
- | ---------------------- |
- | | Correctly written | |
- | | programs run well | |
- | | on OpenBSD. | |
- | ---------------------- |
- ---------------------------</code></pre><p>He wondered if he could create features to slightly narrow the things
- that applications could do. When poorly written programs run on
- OpenBSD, they crash in deterministic ways, but correct programs work
- just fine. Theo also made sure that &quot;mitigations&quot;, or checks to ensure
- a program's correctness, <em>cannot</em> be turned off on OpenBSD. If a user
- or a project manager has a problem with an application not working on
- OpenBSD due to a toggleable security feature, then the user or project
- manager will just turn off the feature. So to ensure that programs
- abide by the mitigations, OpenBSD enforces their security policies.</p><p>OpenBSD also makes it easy to use their security features. If they
- introduce a policy that is manatory, they try to make the API easy to
- use. If you create a security policy that is hard for the programmer
- to use, then the security policy won't be used.</p><p>When OpenBSD creates a new mitigation, their application porters port
- 3rd party software packages to OpenBSD. Typically these changes find
- their way into the upstream packages. What's awesome is that usually
- other operating systems start to use OpenBSD mitigations on their
- systems 5 years after OpenBSD introduced them. Windows, Mac, and
- Linux applications all benefit from the strict standards that OpenBSD
- creates. Theo's talks gave two examples for this: <code>pledge ()</code> and
- <code>arc4random ()</code>.</p><p>Here's a question for you. How do you get random data? Well you read
- <code>/dev/random</code> of course. Simple. Easy. Done. That used to be how
- things were handled. Apparently reading from <code>/dev/random</code> has some
- limitations that Theo mentioned. Can you read from <code>/dev/random</code>
- inside the kernel? Inside a library? In your libc? Reading from
- <code>/dev/random</code> is not perfect. Theo wanted to make something better.</p><p>OpenBSD created <code>arc4random ()</code> as a better source of entropy. It is
- a C function that almost any application can call (even the kernel),
- most of the time. This lets many applications, libraries, etc. easily
- use random numbers. What's surprizing to me is that many operating
- systems use <code>arc4random ()</code> or a function like it, so that more
- applictions can easily request random data. This function (or one
- like it) exists on your Android phone, iPhone, iMac, and sort of on
- Linux thanks to OpenBSD.</p><p>What's <code>pledge ()</code> ? Oh ho, let me tell you! Let's take a look at a
- typical program.</p><pre><code class="language-C">int main () {
- initialize_stuff();
-
- for (;;) {
- ;; let's run the program
- }
- }</code></pre><p>Most programs have an initialization phase followed by a loop, in
- which the application runs. The OpenBSD team realized that the
- initialize phase uses most of the system calls. After the initialize
- phase, the program typically needs less system calls. OpenBSD's
- <code>pledge ()</code> was created in response to this pattern present in most
- programs.</p><p><code>pledge ()</code> is a security call, by which an application tells the
- kernel, &quot;I pledge to only do these things and no other.&quot; For example,
- &quot;I pledge to only output text&quot;. Or &quot;I pledge to only access the
- internet and output text.&quot; If the application tries to do something
- that it has pledged not to do, then OpenBSD kills the application.</p><p>A really interesting blog post that talks about this is at
- <a href="https://justine.lol/pledge/">justine's blog</a>.</p><p>After watching two of Theo's talks, I am fairly convinced that his
- design goals are slowly working to make all POSIX operating systems
- more correct and secure. I used to dual boot Guix System and OpenBSD,
- but unfortunately my spare SSD busted. So for now I am only using
- Guix System. I personally prefer to use Guix System for my linode
- server (that powers this blog), because Guix makes it easy to manage
- servers.</p><p>I wish that the Guix developers could one day create Guix OpenBSD
- System, but I have been told that Guix System assumes your libc is
- <code>glibc</code> and that OpenBSD cannot currently make isolated build
- environments as well as Linux can. Also fun fact OpenBSD is not
- currently working on reproducible builds. :)</p><p>My two only minor complaints with OpenBSD currently are:</p><ul><li>I wish OpenBSD supported Wayland. This may happen in 6 months to a
- year. Fingers crossed.</li><li>A better filesystem: OpenBSD's FFS (fast file system) works, but it
- is possible to lose data in a crash. Filesystems are <em>really</em> hard
- to get right. Kent Overstreet has been working on bcachefs for
- almost a decade now, and it might soon become one of Linux's best
- filesystems (my opinion), so I don't blame OpenBSD for not trying to
- create a new next generational filesystem. Anybody want to spend 10
- years of their life creating an awesome filesystem that will
- probably only work well on OpenBSD? One might be able to port
- HammerFS to OpenBSD, and a basic read-only port does exist.</li></ul><p>If you want to try OpenBSD, give it a shot! It works really well on
- most lenovo laptops and most desktop machines.</p><ol><li>Nerdy computer people like me use the word &quot;hacker&quot; to mean someone
- who builds computer programs, and a &quot;cracker&quot; is someone who breaks
- into computer systems.</li></ol></content></entry><entry><title>The Hurd on Bare Metal Update</title><id>https://gnucode.me/the-hurd-on-bare-metal-update.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2024-01-07T19:00:00Z</updated><link href="https://gnucode.me/the-hurd-on-bare-metal-update.html" rel="alternate" /><content type="html"><h1>Running the Hurd on Bare Metal</h1><p>So apparently, you can run X on the Hurd, and I am currently daily
- driving the Hurd. It's not perfect. Once a month or so the Hurd will
- lock up completely, and I will have to hard shutoff the machine and
- deal with filesystem corruption. But it does work! You will need to
- read the whole <a href="https://www.debian.org/ports/hurd/hurd-install">Debian wiki</a> page. There are sections that mention how
- to upgrade to the unstable distribution, setting up X, and the correct
- upgrade procedure:</p><pre><code># apt update
- # apt upgrade --without-new-pkgs
- # apt full-upgrade</code></pre><p>Let's install some packages and set up X.</p><pre><code># apt install i3 xinit pinentry-gnome3
- # Tell X to let any user startx (it is better to let only console
- # users to start X, but that is not working for me.
- # apt dpkg-reconfigure x11-common xserver-xorg-legacy</code></pre><p>Create a keyboard shortcut to kill X, because X may get stuck.</p><pre><code>cat /etc/X11/xorg.conf.d/xorg-ctrl-backspace.conf
- Section &quot;InputDevice&quot;
- Identifier &quot;Generic KeyBoard&quot;
- Driver &quot;kbd&quot;
- Option &quot;XkbOptions&quot; &quot;terminate:ctrl_alt_bksp&quot;
- EndSection</code></pre><p>If, I am running X, then the best way to shutdown the computer, is to
- first kill X, then from the console execute <code>sudo halt</code>. I tried to
- issue <code>sudo halt</code> from an <code>xterm</code>, and that caused some filesystem
- corruption on my <code>/home</code> partition.</p><p>So what works?</p><ul><li><p>Emacs 29.1</p><ul><li>Gnus</li><li>magit</li><li>erc</li><li>org-mode</li></ul></li><li><p>git send-email</p></li><li><p>netsurf web browser</p><p>I &quot;ported&quot; it via hard-coding <code>PATHMAX</code>, which is not an ideal
- solution, but at least I have a web browser that can render simple
- websites like Wikipedia.</p></li><li><p>ffmpeg</p><p>I actually use <code>recordmydesktop --no-sound --fps 2</code> on the Hurd
- machine. This does actually work. I tried
- using ffmpeg on my Guix System to add audio to the file, but the
- audio is out of sync with the video. I'm not sure why.</p></li><li><p><a href="https://mail.gnu.org/archive/html/bug-hurd/2023-03/msg00021.html">terrible-mdns-responder</a></p><p>Sergey created this as a way to easily ssh into his hurd box from a
- GNU/Linux machine. I use it like so: <code>ssh joshua@pippin.local</code>,
- and I can ssh into my Hurd machine without having to know its IP
- address. It's pretty cool!</p></li><li><p>i3</p><p>i3 is probably the slickest window manager out there! Since the
- Hurd is currently X only, I might as well use something light-weight
- that I like.</p></li><li><p>pastebinit</p><p>It would be nice if netsurf would work with a pastebin, but it's
- not. So the <code>pastebinit</code> command works.</p></li><li><p>ikiwiki</p><p>I can update the GNU Hurd wiki entirely using the Hurd. That's
- awesome!</p></li></ul><h2><strong>Gotchas</strong></h2><p>There are some gotchas when running the Hurd.</p><p>If, <code>/home</code> or <code>/</code> are readonly, then X will refuse to start and will
- not tell you why. So, my <code>.bashrc</code> has this in it:</p><pre><code>cat .profile | grep -A 15 'tell me'
- # tell me if / or /home are writeable or not.
- echo -n '/ is '
- myroot=$(fsysopts / | awk '{ print $2 }')
- myroot=${myroot:2}
- echo $myroot
- echo -n '/home is '
- myhome=$(fsysopts /home | awk '{ print $2 }')
- myhome=${myhome:2}
- echo $myhome
- if [ $myhome == &quot;writable&quot; ]; then
- echo &quot;starting X&quot;;
- else
- echo &quot;NOT starting X&quot;;
- fi</code></pre><p>When I have filesystem corruption, I need to umount <code>/</code> and <code>/home</code>
- and run fsck on them. Then reboot. Most of the time the Hurd can
- auto run fsck for you, but sometimes it is so bad that you must do it
- yourself.</p><p>When you have to fsck the filesystem, here is how to do it. You have
- to login via <code>root</code>, then <code>umount /home &amp;&amp; umount /</code>. Then run
- <code>fsck.ext2 /dev/hd0s1 &amp;&amp; fsck.ext2 /dev/hd0s6</code>. Now reboot.</p><p>I also cannot shutoff the machine from a terminal inside X. I first
- have to kill X, and then shutoff the machine from the console.</p><p>Also, <code>apt</code> is apparently not the best tool to install various
- packages. It is actually better to use <code>aptitude</code>. <code># apt install elpa-magit</code> fails, but <code>#aptitude install elpa-magit</code> somehow works.
- I do not know why.</p><p>This is kind of new, but <code>sudo</code> is failing:</p><pre><code>$ sudo ls
- malloc(): invalid size (unsorted)
- Aborted</code></pre><p>I would love to get haunt running on the Hurd, and it does run! But
- it fails to build this blog. At first it was that <code>guile-commonmark</code>
- was not installed. Then it was that haunt could not find
- <code>guile-commonmark</code>. The fix was pretty easy. In the haunt source
- code directory:</p><pre><code>$ export GUILE_LOAD_PATH=/usr/local/share/guile/site/3.0&quot;
- $ ./configure</code></pre><p>So that helped me build haunt correctly and it could find
- guile-commonmark. But then it needed guile-reader installed as well.
- Now I can't build guile-reader.</p><pre><code>$ autoreconf -vif
- autoreconf: error: automake failed with exit status: 1</code></pre><p>And of course the <code>./configure</code> in the guile-reader directory failed
- too.</p></content></entry><entry><title>The Hurd on Bare Metal</title><id>https://gnucode.me/the-hurd-on-bare-metal.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-08-13T14:00:00Z</updated><link href="https://gnucode.me/the-hurd-on-bare-metal.html" rel="alternate" /><content type="html"><p>This blog post was written on a Debian GNU/Hurd system on a IBM ThinkPad T43
- with 1.5 GB of RAM. (It was edited on Guix System (running linux)). Apparently
- running Emacs on the hurd in the console is actually quite stable. This post
- will describe my attempt to make this T43 be my daily laptop. Let’s see
- how far I can get with that eh?</p><p>tl;dr Debian GNU/Hurd is shockingly stable. If you are an emacs wiz,
- then you will feel right at home.</p><p>The first thing to notice after you login to the Hurd is that you can
- easily switch virtual consoles via <code>Alt-&lt;right-arrow&gt;</code>. It is
- actually pretty awesome that you can do this. I know literally every
- other OS has this, but it is cool to have Emacs open in one console,
- and have another program running on another console; switching
- between them feels beautiful.</p><p>Another thing to notice is that <code>mount</code> does not work. Let's explore that shall
- we?</p><pre><code>cat /etc/mtab | awk '{ print $1 &quot; &quot; $2 &quot; &quot; $3 }'
- /dev/hd0s1 / ext2fs
- none /run /hurd/tmpfs
- none /run/lock /hurd/tmpfs
- /dev/hd0s6 /home /hurd/ext2fs
- proc /proc /hurd/procfs</code></pre><p>Actually <code>/etc/mtab</code> is a symlink to <code>/proc/mounts</code>.</p><pre><code>ls -lha /etc/mtab
- lrwxr-xr-x 1 root root 12 Apr 10 12:14 /etc/mtab -&gt; /proc/mounts</code></pre><p>It looks like the Hurd labels MBR partitions slightly differently from Linux. It
- appears that the Hurd uses <code>/dev/hd0s1</code>, <code>dev/hd0s2</code>, and so on.</p><pre><code>echo $pw | sudo -S fdisk -l /dev/hd0
- Disk /dev/hd0: 37.26 GiB, 40007761920 bytes, 78140160 sectors
- Units: sectors of 1 * 512 = 512 bytes
- Sector size (logical/physical): 512 bytes / 512 bytes
- I/O size (minimum/optimal): 512 bytes / 512 bytes
- Disklabel type: dos
- Disk identifier: 0x1ab32a1b
- Device Boot Start End Sectors Size Id Type
- /dev/hd0s1 2048 26681343 26679296 12.7G 83 Linux
- /dev/hd0s2 26683390 78139391 51456002 24.5G 5 Extended
- /dev/hd0s5 26683392 28682239 1998848 976M 82 Linux swap / Solaris
- /dev/hd0s6 28684288 78139391 49455104 23.6G 83 Linux</code></pre><p>It looks like a good place to start learning how to use the Hurd is
- via <code>https://www.debian.org/ports/hurd/hurd-install</code>.</p><p>So the file that describes my network interfaces is here:</p><pre><code>cat /etc/network/interfaces
- # This file describes the network interfaces available on your system
- # and how to activate them. For more information, see interfaces(5).
- source /etc/network/interfaces.d/*
- # The loopback network interface
- auto lo
- iface lo inet loopback
- # The primary network interface
- auto /dev/eth0
- iface /dev/eth0 inet dhcp</code></pre><p>So it looks like i should definitely read <code>man 5 interfaces</code> at some
- point. And the Debian Hurd guide mentions that I should add name
- servers to my /etc/resolv.conf file. I am not certain why it says
- that I should do that though, but I went ahead and added OpenDNS’ name
- servers.</p><pre><code>cat /etc/resolv.conf
- nameserver 172.16.112.1
- cat /etc/resolv.conf
- nameserver 172.16.112.1
- nameserver 208.67.222.222
- nameserver 208.67.220.220</code></pre><p>Ok, so it seems like <code>pfinit</code> is still the default GNU Hurd <code>TPC/IP</code>
- translator, which is based on an old Linux TCP/IP driver (<code>lwip</code> or
- <code>rumpkernel</code> may one day replace it). Apparently my internet
- connectivity can be found by quering <code>/servers/socket/2</code> (for IPv4)
- and <code>/servers/socket/26</code> (for IPv6).</p><pre><code># fsysopts /servers/socket/2</code></pre><p>If you run the above command you will see that the ethernet device
- that the Hurd uses is <code>/dev/eth0</code>.</p><p>The Hurd has a stateless (stateful is better) ethernet filter. For example, here
- is how to disable ssh access:</p><pre><code># settrans -c /dev/eth0f /hurd/eth-filter \
- -i /dev/eth0 -r &quot;not port 22&quot;</code></pre><p>I could then, tell the pfinit translator to use <code>/dev/eth0f</code> instead
- of <code>/dev/eth0</code> via (I think this how you would do it):</p><pre><code># fsysopts /server/socket/2 --interface=/dev/eth0f</code></pre><p>This is course is not persistant across reboots. I would probably
- need to replace <code>/dev/eth0</code> in <code>/etc/network/interfaces</code> with
- <code>/dev/eth0f</code>.</p><p>The Hurd lets you mount cd drives as a regular user. I should be able
- to look at the files in my CD drive via:</p><pre><code>cd /dev
- # ./MAKEDEV cd0
- # settrans /media/cdrom0 /hurd/is09660fs /dev/cd0
- $ cd /media/cdrom0</code></pre><p>Apparently the Hurd does have a network filesystem translator
- (<code>/hurd/nfs</code>), but I believe that that translator only supports
- NFSv2. So it may not be as performanent as one might want or support
- the latest NSF features.</p><p>Since I installed the stable Hurd release from 2021, the guide
- recommends that if I want a stable environment, then I can just
- configure apt to use the apt sources from 2021. That should let me
- have a fairly stable Hurd distro. So let’s try that.</p><pre><code>cat /etc/apt/apt.conf.d/99ignore-valid-until
- Acquire::Check-Valid-Until &quot;false&quot;;
- cat /etc/apt/sources.list
- deb [trusted=yes] https://snapshot.debian.org/archive/debian-ports/20210812T100000Z sid main
- deb [trusted=yes] https://snapshot.debian.org/archive/debian-ports/20210812T100000Z unreleased main
- deb-src [trusted=yes check-valid-until=no] https://snapshot.debian.org/archive/debian/20210812T100000Z sid main</code></pre><p>This mostly worked, but apt gave a warning about the debian gpg key
- had expired.</p><p>Well let’s try to upgrade anyway.</p><pre><code># apt update &amp;&amp; apt upgrade</code></pre><p>That seemed to work.</p><pre><code># apt install debian-ports-archive-keyring
- # apt update
- # apt upgrade
- # apt install git git-email
- $ git config --global user.name &quot;Joshua Branson&quot;
- $ git config --global user.email &quot;jbranso@dismail.de&quot;
- $ cd; git clone https://notabug.org/jbranso/prog</code></pre><p>Now I suppose that it is time to follow <a href="https://drewdevault.com/2019/12/30/dotfiles.html">Drew Devault’s guide</a> on how to
- manage your home directory’s configuration files as a git repository.</p><p>I should also read the <a href="https://www.debian.org/ports/hurd/hurd-doc-translator">hurd-doc-translator</a> webpage.</p><p>Apparently, the Hurd’s translators transform data into different data.
- The usual case, is that a translator translates bits of the filesystem
- into different data, and what is awesome is that translators run in
- userspace. Most of the time translators will need to get data from
- hardware, and they will request the kernel to help them get this data.
- There are some exceptions: <code>/dev/zero</code> does not need hardware data, so
- a read from <code>dev/zero</code> is entirely run in userspace.</p><p>There are two kinds of translators: active and passive. An active
- translator is currently running. You can change its settings or kill
- it via the <code>settrans -a</code> command. The <code>-a</code> refers to the <strong>active</strong>
- translator. So <code>settrans -a file.txt</code> will try to kill the userspace
- translator process. If you start a translator via the <code>-a</code> option,
- then the translator is not persistant accross reboot. For that reason,
- most of the time you do not want the <code>-a</code> option, which is what
- settrans by default does.</p><p>If you are ever curious to know if a filesystem node has an attached translator,
- then you can find out via this command:<code>showtrans NODE</code>. It will tell you what
- passive translators are set at a filesystem node.</p><p>Let's take a walk through some basic Hurd translators.</p><pre><code>settrans [OPTIONS...] NODE [TRANSLATOR ARGS...]</code></pre><p>For example, I can have a text file like so:</p><pre><code>cat ~/Documents/hello.txt
- boring text document.</code></pre><p>Now let’s set the <code>hello</code> translator on that filesystem node.</p><pre><code>settrans -a ~/Documents/hello.txt /hurd/hello
- cat ~/Documents/hello.txt
- Hello, world!</code></pre><p>Now let’s see that the file system options are for the <code>/hurd/hello</code>
- translator:</p><pre><code>fsysopts ~/Documents/hello.txt
- /hurd/hello --contents='Hello, world!
- '</code></pre><p>I can modify the <code>contents</code> of the hello translator via:</p><pre><code>fsysopts ~/Documents/hello.txt --contents=&quot;Hello Joshua
- &quot;
- cat ~/Documents/hello.txt
- Hello Joshua</code></pre><p>Notice that we changed the options for that translator without having
- to restart it with normal user privledges.</p><p>Now let’s make the hello translator go away:</p><pre><code>settrans -a ~/Documents/hello.txt
- cat ~/Documents/hello.txt
- boring text document.</code></pre><p>Now let’s try to stack these translators eh?</p><pre><code>settrans gnucode.me /hurd/httpfs http://gnucode.me
- ls gnucode.me/installing-wordpress.html
- gnucode.me/installing-wordpress.html
- settrans -c xml /hurd/xmfls ~/gnucode.me/feed.xml
- cd
- ls</code></pre><p>Here the ls command apparently hanged. <code>C-c</code> ended said hanging, but
- the Hurd locked up on me. I actually saw an error message that said
- something like “kbd queue full.” And then my keyboard become
- unresponsive. After a few hours, I pressed “Ctrl-Alt-Del,” and that
- saved my bacon. That killed the hurd console, and it let me switch to
- a virtual console. That enabled me to shut down the hurd gracefully.
- BUT…What went wrong? Why did <code>ls</code> hang?</p><p>Well here is a clue:</p><pre><code>ls ~/gnucode.me/feed.xml
- ls: cannot access feed.xml': No such file or directory</code></pre><p>Well, httpfs does not expose feed.xml. It does not recognize that as part of the
- gnucode.me website. <code>httpfs</code> only lists webpages that are listed on
- <code>index.html</code>. So <code>~/gnucode.me/feed.xml</code> does not translate to the local the
- filesystem. If I had to guess, I would say that xmlfs tries to run but does not
- check if its underlying file exists.</p><p>I should also mention that I am using a very minimal <code>.emacs.d/init.el</code>. It is
- possible to get doom emacs to run on the Hurd, but the last time that I tried
- it, emacs locked up on me. I was forced to do a hard shutdown, which resulted in
- filesystem corruption and I had to re-install. So for now, I am using a very
- simple and minimal emacs. You can actually install some emacs packages via apt.
- Just search for <code>apt search magit</code> to get you started.</p><p>I would like to try running i3 on the hurd at some point, because that
- is a very light-weight window manager, but I have not yet tried
- setting up X to run. Partly because I only have 1.5GB of RAM, and I
- have heard that X tends to lock up or be really slow on the Hurd.</p><p>Surprizingly the Hurd only uses about <code>161MB</code> of RAM, when I run emacs
- on the console.</p><ul><li><p>What I have done so far</p><ul><li><p>Emacs
- I would love to remap control and caps, but I am not certain how
- to do that in the console.</p></li><li><p>Irc (via Erc)</p></li><li><p>Gnus my email client
- But I still need to set up the ability to send email.</p></li></ul></li></ul><p>Packages to install (glibc-doc-reference) requires enabling non-free
- packages:</p><pre><code># apt install gnupg emacs surfraw msmtp glibc-doc glibc-doc-reference</code></pre><p>Trying to create/open a file in emacs that ends in *.gpg crashes
- Emacs. I have no idea why.</p><p>Currently, msmtp cannot securely send email, because it cannot decrypt
- the encrypted file that has my password.</p><p>My Hurd machine also has my “jbranso@dismail.de” gpg key. I was able
- to import the data via an ssh session.</p><p>I was actually surprized that the debian wiki mentioned this command:
- <code>service ssh restart</code> and not a systemd specific command, but
- apparently <code>man service</code> is the manual that I want to read.
- Apparently ssh is already running. I verified this with:</p><pre><code>echo $pw1 | sudo -S service --status-all | grep ssh
- [ + ] ssh</code></pre><p>I really should set up Sergey's terrible MDNS responder, so that I can ssh in
- the Hurd more easily, but that is a task that I will set for a later date. I
- should also possibly update my hard drive to a larger drive. I think the current
- one has 100GB or so. Maybe less. And it might not be a bad idea to set up an SSD
- or DVD drive via the CD-ROM bay and try the rumpdisk out. I would also like to
- be able to publish my blog from the Hurd too, but I have been unsuccessful to
- install Haunt on my Hurd box. I should also try to install Guix on it, but I am
- concerned about hard drive space at the moment.</p><p>Anyway, you can take a look at my <a href="https://notabug.org/jbranso/hurd-home">hurd
- home</a> git directory if you like. Safe
- travels!</p></content></entry><entry><title>Setting up Chimera Linux</title><id>https://gnucode.me/setting-up-chimera-linux.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-08-09T11:59:00Z</updated><link href="https://gnucode.me/setting-up-chimera-linux.html" rel="alternate" /><content type="html"><p>My friend ownes a <a href="https://www.raptorcs.com/TALOSII/">Talos II</a>, and he wanted some help setting it up. We have
- decided on setting up <a href="https://chimera-linux.org/">Chimera Linux</a>. Since Chimera Linux is new, we also installed the guix package manager as well. This blog post today is more of documentation and less story telling. You have been warned.</p><h1>upgrading chimera linux</h1><pre><code>doas apk update
- doas apk upgrade</code></pre><h1>DONE Getting X applications and gdm to run on chimera</h1><p>All Talos II machines have trouble running X, when a discrete GPU is installed.
- Basically the Talos II has an on board GPU, which when combined with an AMD GPU,
- X does not know which GPU to use. <a href="https://wiki.raptorcs.com/wiki/Troubleshooting/GPU#Xorg_will_not_start_.2F_crashes_when_a_discrete_GPU_is_installed">click here</a> to read more on the raptor wiki.</p><p>I did have trouble getting my friend’s Talos II to start gdm and X, but an
- update to chimera linux fixed the gdm issue. The below sections are for others
- that are using a Talos II with an AMD GPU. You do need to configure X to
- disable the onboard GPU and/or tell GDM to select a GPU at runtime.</p><h2>raptor pdf user’s guide:</h2><p><a href="https://wiki.raptorcs.com/w/images/e/e3/T2P9D01_users_guide_version_1_0.pdf">https://wiki.raptorcs.com/w/images/e/e3/T2P9D01_users_guide_version_1_0.pdf</a></p><h3>raptor wiki ways to fix this</h3><ol><li>Tell GDM to ignore a GPU</li></ol><p>In this case ignore the crappy onboard GPU.</p><pre><code> lspci | grep VGA
- 0005:02:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 41)
- 0030:01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon Pro WX 7100]
- cat /etc/udev/udev.conf
- # see udev.conf(5) for details
- #
- # udevd is also started in the initrd. When this file is modified you might
- # also want to rebuild the initrd, so that it will include the modified configuration.
-
- #udev_log=info
- #children_max=
- #exec_delay=
- #event_timeout=180
- #timeout_signal=SIGKILL
- #resolve_names=early
- TAG-=&quot;seat&quot;, ENV{ID_FOR_SEAT}==&quot;drm-pci-0005_02_00_0&quot;
- TAG-=&quot;seat&quot;, ENV{ID_FOR_SEAT}==&quot;graphics-pci-0005_02_00_0&quot;
- Do this to re-generate the initramfs.
- `doas apk fix linux-lts`</code></pre><ol><li><p>Xorg will not start / crashes when a discrete GPU is installed</p><p>We chose to do the workaround 2: select a desired GPU at runtime, which means
- that if we change the slot of the GPU, then we will have to re-create the Xorg
- configuration file.</p><pre><code>lspci | grep VGA
- 0005:02:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 41)
- 0030:01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon Pro WX 7100]
- cat /etc/X11/xorg.conf.d/21-gpu-driver.conf
- # AST2500
- Section &quot;Device&quot;
- Identifier &quot;GPU0&quot;
- Driver &quot;modesetting&quot;
- BusID &quot;PCI:2@5:0:0&quot;
- VendorName &quot;ASpeed Corporation&quot;
- EndSection
-
- # WX7100
- Section &quot;Device&quot;
- Identifier &quot;GPU1&quot;
- Driver &quot;modesetting&quot; # or amdgpu if you have xf86-video-amdgpu installed
- BusID &quot;PCI:1@48:0:0&quot;
- VendorName &quot;AMD Corporation&quot;
- EndSection
-
- # this is absolutely necessary, it tells xorg which GPU to use for the screen
- Section &quot;Screen&quot;
- Identifier &quot;Screen0&quot;
- Device &quot;GPU1&quot;
- EndSection</code></pre></li><li><p>upgrade the openBMC bios/firmware and disable onboard GPU via</p><p>I decided not to do this one. It's way too complicated. See the raptor wiki if you don't believe me.</p></li></ol><h2>Where to find X logs</h2><p><em>var/log/gdm/greeter.log
- /var/lib/gdm</em>.local/share/xorg/Xorg.1.log</p><h2>toggling gdm to use X/wayland</h2><p>This does not appear to work.</p><pre><code>cat /etc/gdm/custom.conf | grep 'Wayland'
- #WaylandEnable=false
- WaylandEnable=true</code></pre><h2>DONE install icewm, and put that in ~/.xinitrc &amp; startx</h2><p>Originally this did not work, because X refused to start. But after I upgraded
- Chimera linux one day, it worked.</p><h1>Setting up Bitcoin knots/bitcoin core</h1><p>My friend is an avid bitcoin user. He wanted me to help him set up bitcoin on
- his Talos II. If possible, he wanted me to set up bitcoin-knots, which was
- forked from bitcoin-core.</p><h2>github repo for bitcoin-knots</h2><p>The github repo has lots of good information to help me out:</p><p><a href="https://bitcoinknots.org/#download">https://bitcoinknots.org/#download</a></p><p><a href="https://github.com/bitcoinknots/bitcoin">https://github.com/bitcoinknots/bitcoin</a></p><p><a href="https://github.com/bitcoinknots/bitcoin/tree/23.x-knots/doc">https://github.com/bitcoinknots/bitcoin/tree/23.x-knots/doc</a></p><p><a href="https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-unix.md">https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-unix.md</a></p><p><a href="https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-freebsd.md">https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-freebsd.md</a></p><p><a href="https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/dependencies.md">https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/dependencies.md</a></p><p>I can get help from webchat.freenode.net #bitcoin-dev</p><p>luke-jr says that I can compile bitcoin knots from source fairly easily.</p><p>download a release. Install dependencies:</p><p><a href="https://download.qt.io/official_releases/qt/">https://download.qt.io/official_releases/qt/</a></p><pre><code>doas apk add libevent </code></pre><p><code>./configure gmake &amp;&amp; gmake check &amp;&amp; gmake install</code></p><h2>NO Packaging bitcoin knots for chimera linux</h2><p>q66 is NOT ok with me packaging bitcoin-coin for chimera linux, because it
- depends on qt5, which is soon to be replaced by qt6. So why bother packaging
- qt5 when qt6 is soon to supplant it?</p><p>This is the documentation for packaging in chimera.</p><p><a href="https://github.com/chimera-linux/cports">https://github.com/chimera-linux/cports</a>
- <a href="https://github.com/chimera-linux/chimerautils">https://github.com/chimera-linux/chimerautils</a></p><h2>Alternatively I can package bitcoin knots for guix and install</h2><p>guix on chimera linux. And guix already has qt packaged. Do they have
- 5.15.2 packaged? Why yes they do: They have qtbase version 5.15.8.</p><p>I have not packaged bitcoin-knots for guix yet. Instead my friend decided to
- run bitcoin-core.</p><h2>DONE Or I can just install bitcoin-core from guix and run that</h2><h1>guix stuff</h1><h2>installing guix on chimera linux</h2><p>You can install guix via these commands:</p><pre><code>wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
- doas chmod u+x guix-install.sh
- doas ./guix-install.sh</code></pre><p>Add in the export line so I can use the guix binaries.</p><pre><code>cat ~/.profile
- #!/usr/bin/bash
- export GUIX_LOCPATH=&quot;$HOME/.guix-profile/lib/locale&quot;
- gnome-shell --wayland</code></pre><h2>starting the guix daemon manually</h2><pre><code> ~root/.config/guix/current/bin/guix-daemon &amp;#x2013;build-users-group=guixbuild</code></pre><h2>set up guix daemon via dinit</h2><pre><code>cat /etc/dinit.d/guix-daemon
- # guix-daemon service
- type = process
- # run this command as root
- run-as = root
- command = /root/.config/guix/current/bin/guix-daemon --build-users-group=guixbuild
- # depends-on = bar
- # waits-for = baz
- # uncomment this next line once you know this works
- # before = login.target
- before = network.target</code></pre><p><a href="https://davmac.org/projects/dinit/man-pages-html/dinitcheck.8.html">https://davmac.org/projects/dinit/man-pages-html/dinitcheck.8.html</a></p><p><a href="https://davmac.org/projects/dinit/man-pages-html/dinit-service.5.html">https://davmac.org/projects/dinit/man-pages-html/dinit-service.5.html</a></p><p>So if you cannot get the daemon to autostart, then this will</p><p><code>doas dinitctl start guix-daemon</code> work.</p></content></entry><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" /><content type="html"><h1>set up doas</h1><p>Let’s make any user that is in the group “wheel” able to execute privledged
- commands.</p><pre><code># cat /etc/examples/doas.conf | sed 's/keepenv/persist keepevn/' &gt; /etc/doas.conf</code></pre><h1>install packages</h1><pre><code># pkg_add emacs dino netsurf dino git fish mpv firefox gpg \
- hack-fonts pkg_add isync evince libreoffice xfce4-terminal \
- xfce4-screenshooter xfce4-dict i3</code></pre><p>When I installed isync, I got a message that said,
- the following rcscripts were installed: /etc/rc.d/saslauthd
- apparently openbsd’s packaged isync, lets you set up a daemon to periodically
- fetch your email. looking at the file, I’m not sure what it is.</p><p>Well I could list all of the packages that I minually installed, it is actually
- much easier to create a list of packages.</p><pre><code>pkg_info -mz | tee openbsd-pkg-list</code></pre><p>Now, when I want to re-install those packages I can just do this:</p><pre><code># pkg_add -l list</code></pre><h1>clone my various repos</h1><pre><code>cd ~/
- git clone https://notabug.org/jbranso/prog
- cd prog
- mkdir -p gnu/guix/
- cd gnu/guix
- git clone https://notabug.org/jbranso/guix
- mv guix guix-src
- git clone https://notabug.org/jbranso/guix-config</code></pre><h1>update my OpenBSD install</h1><p><code># doas syspatch</code></p><h1>enable softupdates</h1><p>Unless you are using really old ancient hardware, you should enable softupdates.</p><p>change</p><p><code>43434930490.a / ffs rw 1 1</code></p><p>to</p><p><code>43434930490.a / ffs rw,softdep 1 1</code></p><h1>window manager stuff</h1><h2>modify my ~/.xsession</h2><p>auto start xfce, prefer utf-8, set up a background color, and lock X after some
- inactivity.</p><pre><code>cat ~/.xsession
- # prefer UTF-8 whenever possible
- export LC_CTYPE=&quot;en_US.UTF-8&quot;
- # use UTF-8 everywhere
- export LANG=en_US.UTF-8
- # specify location of kshrc
- export ENV=$HOME/.kshrc
- # set your background color
- xsetroot -solid dimgray
- xidle -delay 5 -sw -program &quot;/usr/X11R6/bin/xlock -mode flag&quot; \
- -timeout 300
- exec i3</code></pre><h2>set up polybar for i3</h2><p><a href="https://forum.endeavouros.com/t/tutorial-easy-setup-endeavour-xfce-i3-tiling-window-manager/13171">https://forum.endeavouros.com/t/tutorial-easy-setup-endeavour-xfce-i3-tiling-window-manager/13171</a></p><pre><code># doas pkg_add polybar
- $ mkdir ~/.config/polybar
- $ cp /usr/local/share/examples/polybar/config ~/.config/polybar</code></pre><p>This <a href="https://github.com/polybar/polybar/wiki/Fonts">wiki page</a> has a lot of details about setting up fonts.</p><p>More information is in my <a href="https://notabug.org/jbranso/openbsd-home/src/master/.config/polybar">polybar config</a>.</p><h1>If this is a laptop with a battery, then install this</h1><p><a href="https://dataswamp.org/~solene/2022-03-21-openbsd-cool-frequency.html">https://dataswamp.org/~solene/2022-03-21-openbsd-cool-frequency.html</a></p><pre><code># doas pkg_add obsdfreqd
- # rcctl enable obsdfreqd
- # rcctl stop apmd
- # rcctl disable apmd
- # rcctl start obsdfreqd</code></pre><h1>set up doom emacs</h1><p>(I also need to ensure that <code>~/prog/gnu/guix/</code> exists because my emacs looks for
- some guix snippets).</p><pre><code>git clone --depth 1 https://github.com/doomemacsdoomemacs ~/.config/emacs
- ~/.config/emacs/bin/doom install</code></pre><p>add doom emacs to path</p><pre><code>cat ~/.profile
- # $OpenBSD: dot.profile,v 1.8 2022/08/10 07:40:37 tb Exp $
- #
- # sh/ksh initialization
- #
- PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/home/joshua/.config/emacs/bin
- export PATH HOME TERM</code></pre><h1>copy my ~/ config files</h1><p>cp .authinfo.gpg, .ssh, .mbsyncrc, .gnupg/</p><p>cp documents to ~/</p><h1>import my gpg keys from my usb stick.</h1><p><code>gpg --import ./dismail.de.gpg.key.asc</code></p><p><code>git config --global commit.gpgsign true</code></p><p><code>gpg --list-secret-keys --keyid-format=long</code></p><p>Copy the really long alphanumeric word from the above command. It'll
- look something like:</p><p>62A42A3CC13497D626FZ686C750BCFEF3A5E1572</p><p><code>git config --global user.signingkey &lt;your alphanumeric word&gt;</code></p><h2>set up pinentry</h2><pre><code>pkg_add pinentry-dmenu</code></pre><p>There are two things that you need to do to set up pinentry-dmenu, so that when I
- need to sign commits or decrypt stuff, the pinentry-dmenu popup happens.</p><ul><li><p>set up gpg agent</p><pre><code>cat ~/.gnupg/gpg-agent.conf
- pinentry-program /usr/local/bin/pinentry-dmenu
-
- default-cache-ttl 3600</code></pre></li><li><p><code>man gpg-agent</code> says to do this:</p><pre><code>You should always add the following lines to your .bashrc or whatever
- initialization file is used for all shell invocations:
- cat ~/.profile | grep GPG_TTY
- GPG_TTY=$(tty)
- export GPG_TTY</code></pre></li><li><p>start a dbus session</p><p>This is only needed if you want to use pinentry-gnome3</p><pre><code>cat ~/.xsession | grep dbus
- # start a dbus session, which I believe gpg needs to for graphical pinentry
- # I found this command in /usr/local/share/doc/pkg-readmes/dbus
- if [ -x /usr/local/bin/dbus-launch -a -z &quot;${DBUS_SESSION_BUS_ADDRESS}&quot; ]; then
- eval `dbus-launch --sh-syntax --exit-with-x11`</code></pre></li></ul><p>If you have difficulty getting pinentry to work, here are some steps to
- manually get pinentry to work:</p><p>in a fish terminal a type in:</p><pre><code>gpgconf --kill gpg-agent
- set GPG_TTY $(tty)
- export GPG_TTY
- git commit -m &quot;my commit message&quot;</code></pre><h1>change <code>/etc/motd</code></h1><p>I once set an invalid option up in /etc/fstab that threw me in a root shell with
- only root mounted. All of a sudden vi would not work. That below command is
- how to fix it: <code>export TERM=vt200</code></p><pre><code>cat /etc/motd
- OpenBSD 7.2 (GENERIC.MP) #7: Sat Feb 25 14:07:58 MST 2023
- Welcome to OpenBSD: The proactively secure Unix-like operating system.
- Please use the sendbug(1) utility to report bugs in the system.
- Before reporting a bug, please try to reproduce it with the latest
- version of the code. With bug reports, please try to ensure that
- enough information to reproduce the problem is enclosed, and if a
- known fix for it exists, include that as well.
- If you are having trouble using vi in the console try this:
- export TERM=vt200;</code></pre><h1>install haunt on OpenBSD</h1><p><code>doas pkg_add guile info</code></p><p>First install guile-commonmark:</p><pre><code>$ cd ~/prog/guile
- $ git clone git clone https://github.com/OrangeShark/guile-commonmark
- $ cd guile-commonmark
- # export AUTOCONF_VERSION=2.71
- # export export AUTOMAKE_VERSION=1.16.5
- # doas pkg_add autoconf automake</code></pre><p>Why am I seeing 2 aclocal binaries? No idea.</p><pre><code>ls /usr/local/bin/aclocal*
- ls /usr/local/bin/automake*
- /usr/local/bin/aclocal
- /usr/local/bin/aclocal-1.16
- /usr/local/bin/automake
- /usr/local/bin/automake-1.16</code></pre><p>Arsen on irc helped me figure out the next incantation.</p><pre><code>AUTOMAKE=automake-1.16 ACLOCAL=aclocal-1.16 ./bootstrap
- ./configure
- make
- make check
- # make install</code></pre><p>Now let’s install haunt</p><pre><code>git clone https://git.dthompson.us/haunt.git
- cd haunt
- AUTOMAKE=automake-1.16 ACLOCAL=aclocal-1.16 ./bootstrap
- ./configure
- make
- make check
- # make install</code></pre></content></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" /><content type="html"><p>My last post talked about how I broke my OpenBSD laptop by telling OpenBSD that
- my usbstick was essential to the boot process, and then, when I booted the
- laptop, I did not have that usb stick mounted. That caused some problems. I
- since learned that the preferred way of automounting a usb stick under OpenBSD
- is with <code>hotplugd</code>.</p><p><a href="https://man.openbsd.org/hotplugd">hotplugd</a> is OpenBSD’s automounting functionality, and it’s actually super simple
- and easy. Just put your scripts at <code>/etc/hotplugd/attach</code> and
- <code>/etc/hotplugd/detach</code>. And the man page gives you an example shell script, but
- since I am not a big fan of <code>sh</code> (its syntax is confusing), I decided to write
- my attach script in <a href="https://www.gnu.org/software/guile/">GNU Guile</a>. Writing that script made me want to write more
- scripts in <a href="https://scsh.net/">scheme shell</a>, but I the last time I tried to install the scheme shell
- on OpenBSD, it failed to compile.</p><p>Anyway, it is really easy to write your own script. <code>hotplugd</code> will call your
- script like so:</p><pre><code>attach &lt;number&gt; &lt;label&gt;</code></pre><p>where <code>&lt;number&gt;</code> is one of the numbers in the table below and <code>&lt;label&gt;</code> is a
- short descriptive string of the device.</p><pre><code>|---+------------------------------------|
- | 0 | generic, no special info |
- |---+------------------------------------|
- | 1 | CPU (carries resource utilization) |
- |---+------------------------------------|
- | 2 | disk drive |
- |---+------------------------------------|
- | 3 | network interface |
- |---+------------------------------------|
- | 4 | tape device |
- |---+------------------------------------|
- | 5 | serial line interface |
- |---+------------------------------------|</code></pre><p>I am only really interested in <code>2</code> and <code>3</code>. Here is how I debbuged my attach
- script, and you can easily do the same.</p><p>First find out what <code>sd</code> device your usb stick is. Before you put in your usb
- stick type in:</p><pre><code>sysctl hw.disknames
- hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2</code></pre><p>Now put in your usb stick and run the same command.</p><pre><code>sysctl hw.disknames
- hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2,sd2:</code></pre><p>So now I know that my usb stick is sd2. Let’s do a disklabel command on it:</p><pre><code># disklabel sd2
- # /dev/rsd2c:
- type: SCSI
- disk: SCSI disk
- label: USB Flash Drive
- duid: 0000000000000000
- flags:
- bytes/sector: 512
- sectors/track: 63
- tracks/cylinder: 255
- sectors/cylinder: 16065
- cylinders: 1887
- total sectors: 30326784
- boundstart: 0
- boundend: 30326784
- 16 partitions:
- # size offset fstype [fsize bsize cpg]
- c: 14.5G 0 unused
- i: 14.5G 2048 MSDOS</code></pre><p>Notice from the output that this label is “USB Flash Drive”. That is the label
- that hotplugd will send to your attach script.</p><p>If you want a usb stick that is read-able/writeable accross all operating
- systems, currently you will want to use the <a href="https://wiki.archlinux.org/title/FAT">vfat</a> filesystem. That is what the
- output above shows. The <code>fstype</code> of <code>MSDOS</code> is a vfat filesystem. This usb stick
- is what I will use when I want to copy data between different OS-es (I do want
- an <a href="https://www.openbsd.org/faq/faq14.html#softraidCrypto">encrypted OpenBSD-specific usb stick</a> to store my gpg keys, but I have not yet
- set that up). According to some of the smart people on the <code>#openbsd</code> irc
- channel, if you have such a usb stick, then the <code>i</code> filesystem partition is the
- one that you want to mount to read the data. And we see that above as well (<code>c</code>
- is code for the whole drive. <code>/dev/rsd2c</code> is how you access the whole and raw
- disk).</p><p>Ok, so now that you know what arguments that <code>hotplugd</code> will send your script,
- go ahead and write your basic script. It probably won’t be perfect, which is ok.
- To test it, type in <code>su</code> in your terminal to get to root account, and then test
- your script in the exact same way that OpenBSD will use your script (<code>#</code> means
- that you are currently the root user):</p><pre><code># ./attach 2 &quot;USB Flash Drive&quot;</code></pre><p>You will probably get some weird errors, and that’s ok. After you have run your
- attach script, and it seemed to have no errors, verify that it properly mounted
- with:</p><pre><code>mount
- /dev/sd1a on / type ffs (local, softdep)
- /dev/sd1k on /home type ffs (local, nodev, nosuid, softdep)
- /dev/sd1d on /tmp type ffs (local, nodev, nosuid, softdep)
- /dev/sd1f on /usr type ffs (local, nodev, softdep)
- /dev/sd1g on /usr/X11R6 type ffs (local, nodev, softdep)
- /dev/sd1h on /usr/local type ffs (local, nodev, wxallowed, softdep)
- /dev/sd1j on /usr/obj type ffs (local, nodev, nosuid, softdep)
- /dev/sd1i on /usr/src type ffs (local, nodev, nosuid, softdep)
- /dev/sd1e on /var type ffs (local, nodev, nosuid, softdep)
- /dev/sd2i on /mnt/usb type msdos (local, nodev, noexec)</code></pre><p>And it look like I properly mounted my usb stick (the last line says it was).</p><p>One thing that users might find confusing is that OpenBSD passes in <code>2</code>, but
- Guile accepted the <code>2</code> as a string.</p><p>My simple <a href="https://notabug.org/jbranso/prog/src/master/gnu/guile/scripts/attach">attach script</a> works for me. It will only auto mount vfat filesystems,
- and I am pretty sure that weird things will happen if I plug in two usb sticks
- at once, but it works.</p></content></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" /><content type="html"><p>The end of my previous blog post was a bit of a cliff hanger:</p><p>I did have a great time the next day. I was hoping to automount my usb
- stick on boot. So I added this beauty to my <code>/etc/fstab</code>.</p><blockquote><p><code>sd1i /mnt/usb msdos rw 1 2</code></p></blockquote><p>The next time I booted it threw me into a rescue shell with only <code>/</code> mounted.</p><p>This is the story of how I fixed a broken fstab on OpenBSD. The day began like
- any other. It was cold and dark as I arose to play with my new OpenBSD
- computer. It was time to reboot! That magical moment when OpenBSD <a href="https://www.openbsd.org/innovations.html">relinks the
- kernel at boot</a>. How cool is that?</p><p>My admiration for this world class operating continues to rise as it boots, and
- OpenBSD proudly slaps me in the face (I did not write down the OpenBSD error
- message, but this is essentially what it said):</p><blockquote><p>mount cannot find device sd1i. You are now in a resque shell.</p><p>root&gt;</p></blockquote><p>Hmmm. Well that’s a bummer. It looks like I had told OpenBSD that that usb stick
- was necesary for boot. I also did not have the usb stick plugged in, and OpenBSD
- needed me to write <code>/dev/sd1i</code> not <code>sd1i</code>. It might be a good project idea to
- add <a href="https://man.openbsd.org/opendev">opendev</a> support to OpenBSD’s mount. Any takers?</p><p>Anyway, to fix this, I attempted to delete that last line from <code>/etc/fstab</code>. I
- tried to type out <code>cd /etc/</code>. Instead I got gibberish. Testing the keyboard a
- bit, I noticed that the keyboard was in the qwerty layout. I use dvorak. And my
- laptop keyboard physically shows a dvorak keyboard layout. It’s really hard to
- type correctly on a keyboard when pressing “‘,.pyf” is “qwerty”. Well let’s
- change my keyboard layout (notice that all commands below are run as the <code>root</code>
- user. The <code>#</code> means you are running as a root user).</p><p>I painstakingly typed out the following command.</p><pre><code># wsconctl keyboard.encoding=us.dvorak</code></pre><p>Awesome, that is an improvement. Let’s change <code>/etc/fstab</code>. The following
- commands did not work, because the shell could not find the binary:</p><ul><li><code>nano /etc/fstab</code></li><li><code>vim /etc/fstab</code></li><li><code>vi /etc/fstab</code></li></ul><p>Well that’s weird. Is <code>/usr/bin</code> not mounted?</p><pre><code># mount
- /dev/sd1a on / type ffs (ro)</code></pre><p>Oh great! I only have <code>/</code> mounted! So my commands are limited, and <code>/</code> is
- mounted read only. So even if I find a text editor that I can use, I cannot
- modify <code>/etc/fstab</code>. How do I mount <code>/</code> read-write? According to the irc people
- who helped me out, this is how: you update the mount information based on what
- <code>/etc/fstab</code> says.</p><pre><code># mount -uvw /
- # mount
- /dev/sd1a on / type ffs (rw)</code></pre><p>Awesome, <code>fstab</code> is editable! I tried to edit <code>/etc/fstab</code> but <code>vi</code> was not
- available, probably because <code>vi</code> is located in <code>/usr</code>, which is not yet mounted.</p><p>What I should have done was <code>mount -U</code>. This just mounts all mount points
- listed in <code>/etc/fstab</code>. I did not read that option in the manpage yet. So I
- decided to manually try to guess which filesytem was which.</p><p>Well let’s print out human read-able file sizes of my filesystem partitions and
- that will give me some clue which filesystem is which. (please note that I am
- intentionally removing the offsets).</p><pre><code># disklabel -h sd1
- 16 partitions:
- # size offset fstype [fsize bsize cpg]
- a: 1.0G 4.2BSD 2048 16384 12960
- b: 8.0G swap
- c: 931.5G unused
- d: 4.0G 4.2BSD 2048 16384 12960
- e: 19.5G 4.2BSD 2048 16384 12960
- f: 30.0G 4.2BSD 2048 16384 12960
- g: 1.0G 4.2BSD 2048 16384 12960
- h: 20.0G 4.2BSD 2048 16384 12960
- i: 3.0G 4.2BSD 2048 16384 12960
- j: 6.0G 4.2BSD 2048 16384 12960
- k: 300.0G 4.2BSD 4096 32768 26062</code></pre><p>Ok. Clearly the 300G is my <code>/home</code>. I can mount that now.</p><pre><code># mount /dev/sd1k /home</code></pre><p>Ok. How do I mount <code>/usr</code> so that I have text editors? I don’t really know which
- partition is which. I guess I will just guess. Eventually I did correctly mount
- <code>/usr</code>, so now I should have access to some text editors! So now I could edit
- <code>fstab</code>.</p><pre><code># vim /etc/fstab
- vim: unknown command</code></pre><p>Ok. vim is not installed. Let’s try vi.</p><pre><code># vi /etc/fstab
- vi: unknown terminal type</code></pre><p>So vi doesn’t run on the console? That’s odd. Ok. Lets see what <code>head</code>
- shows me:</p><pre><code># head /etc/fstab
- 5583d235b610c8a2.a / ffs rw,softdep 1 1
- 5583d235b610c8a2.k /home ffs rw,softdep,nodev,nosuid 1 2
- 5583d235b610c8a2.d /tmp ffs rw,softdep,nodev,nosuid 1 2
- 5583d235b610c8a2.f /usr ffs rw,softdep,nodev 1 2
- 5583d235b610c8a2.g /usr/X11R6 ffs rw,softdep,nodev 1 2
- 5583d235b610c8a2.h /usr/local ffs rw,wxallowed,softdep,nodev 1 2
- 5583d235b610c8a2.j /usr/obj ffs rw,softdep,nodev,nosuid 1 2
- 5583d235b610c8a2.i /usr/src ffs rw,softdep,nodev,nosuid 1 2
- 5583d235b610c8a2.e /var ffs rw,softdep,nodev,nosuid 1 2
- 5583d235b610c8a2.b none swap sw</code></pre><p>Hey would you look at that! There is no line with <code>/mnt/usb</code>. I should be able
- to just overwrite <code>fstab</code> with the output of <code>head</code>. Please do NOT copy or
- execute the following command:</p><pre><code># head /etc/fstab &gt; /etc/fstab</code></pre><p>I wish I had read the irc chat before I had executed the above command. In the
- words of a wise sage, “the redirection happens before head runs, so you’ll just
- get a blank file.” And that is exactly what happened. <code>/etc/fstab</code> was empty.
- Now how do I mount filesystem partitions in the correct locations? “Out of the
- frying pan and into the fire.”</p><p>Some of the people on irc mentioned that <code>/var/backups</code> should have a copy of my
- <code>fstab</code>. Unfortunately, that backup command had not run yet. This was a fresh
- OpenBSD install afterall.</p><p>One of the people on the OpenBSD chat showed me this <a href="https://github.com/openbsd/src/blob/master/sbin/disklabel/editor.c#L91">link</a>, which was super
- helpful, because it shows you the default size of the various partitions that
- the auto installer sets up. With that information, I was able to re-mount all my various
- partitions. Then someone on irc chat gave me this beauty of a command:</p><pre><code># mount | awk '{ print $1 &quot; &quot; $3 &quot; &quot; $5 &quot; rw 0 0&quot;}' &gt; /etc/fstab</code></pre><p>That created my <code>fstab</code> for me! Let’s check it out!</p><pre><code># cat /etc/fstab
- sd1.a / ffs rw 1 1
- sd1.k /home ffs rw 1 2
- sd1.d /tmp ffs rw 1 2
- sd1.f /usr ffs rw 1 2
- sd1.g /usr/X11R6 ffs rw 1 2
- sd1.h /usr/local ffs rw 1 2
- sd1.j /usr/obj ffs rw 1 2
- sd1.i /usr/src ffs rw 1 2
- sd1.e /var ffs rw 1 2
- sd1.b none swap sw</code></pre><p>Hmm, well the mount options are absent, and it is NOT using UIDs…But this
- should be enough to boot into a complete system. So I rebooted. Upon reboot, I
- was able to change the mount points to UIDs and copy the proper mount options
- from my desktop OpenBSD. I then very quickly set up <a href="https://man.openbsd.org/hotplugd">hotplugd</a>, which I will
- explain next time. Until then!</p></content></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" /><content type="html"><p>So I previously talked about my <a href="http://gnucode.me/installing-openbsd-on-a-vm.html">interest</a> <a href="http://gnucode.me/dual-booting-openbsd-guix-system.html">in OpenBSD</a>. Well last week, I
- have been more and more impressed with OpenBSD, especially after watching
- <a href="https://undeadly.org/cgi?action=article;sid=20230325163416">Theo’s recent talk</a>. I recently installed OpenBSD on my desktop, and I was
- satisfied. There are some things that I knew how to do on GNU Guix that I do not
- yet know how to do on OpenBSD. For example, there is a minor issue with the
- sound being a bit wonky but that is not a deal breaker.</p><p>A few days ago I switched to OpenBSD on my laptop. So now, with the exception of
- my PinePhone, all of my computing devices are using OpenBSD. The OpenBSD
- installer is getting support for autoencrypting your hard drive, but I wanted to
- document the manual set up process if I ever decide to set up a RAID+ecryption.
- I do not believe the installer will support RAID+encryption anytime soon.</p><p>The real problem was trying to get libreboot to even recognize the OpenBSD usb
- installer stick. The best method to boot OpenBSD on libreboot is to use the
- seaBIOS payload. I could NOT get this to work. I must have booted and rebooted
- 10+ times trying to get this to work. I even opened up a grub command line
- prompt, and it could not SEE the usb stick. <a href="https://misc.openbsd.narkive.com/auaZDqBe/bsd-rd-fails-to-boot-up-on-libreboot-x200-how-to-find-out-why">Others have reported this problem.</a></p><p>In grub you can get a feel for what partitions are available via:</p><pre><code>grub&gt; ls
- (hd0) (hd0,msdos1)</code></pre><p>This seems to only show my GNU/Linux Guix System partition. That’s not a good
- sign. There is another way to check. I can type out the following
- <code>set root=(hd0,msdos1)/</code></p><p>and then press TAB:</p><p>I was able to see <code>/bin</code>, <code>/boot</code>, <code>/etc</code>, etc. Going into <code>/var</code>, I saw
- <code>guix/</code>. So clearly <code>hd0</code> is my current SSD that has GNU/Linux Guix System. And
- grub and libreboot did NOT see the OpenBSD usb stick. I kept rebooting, tried
- searching for the OpenBSD stick, and finally the grub console showed me
- something other than <code>(hd0,msdos1)</code>. I think I have to use the right-most usb
- port. I think that is the secret.</p><p>Technically, <a href="https://notabug.org/swiftgeek/libreboot/src/master/docs/bsd/openbsd.md">grub can boot
- OpenBSD</a>,
- at least grub as packaged by Libreboot, but that is NOT advisable. And grub's
- ability to boot OpenBSD may disappear at any moment. Seeing no other option, I
- typed in this command to boot OpenBSD via grub:</p><pre><code>grub&gt; kopenbsd (usb0)/7.2/amd64/bsd.rd
- grub&gt; boot</code></pre><p>And OpenBSD started booting! Woo hoo! At the OpenBSD installer I typed in “s”
- to exit to the shell so that I could set up full disc encryption.</p><p>Before we get to the disc encryption, let me give a quick overview of how
- OpenBSD sets up partitions. OpenBSD supports both MBR and GPT partitions, which
- divide the physical disc into sections (MBR is old; GPT is the modern way to do
- it, and most people will want GPT on newer machines so for the rest of this blog
- post I will just talk about GPT). All operating systems recognize and use GPT
- partitions. Linux will install its filesystem partitions into seperate GPT
- partitions, which means that a &quot;partition&quot; in Linux means the GPT
- partition and the filesystem partion. Here's a handy graphic:</p><pre><code>|--------------+------------+----------------|
- | | Linux | |
- |--------------+------------+----------------|
- | GPT partiton | filesystem | mount location |
- | | partition | |
- |--------------+------------+----------------|
- | /dev/sda1 | ext4 | / |
- | /dev/sda2 | btrfs | /etc |
- | /dev/sda3 | xfs | /boot |
- | ... | ... | ... |
- | /dev/sda128 | vfat | /boot/efi |
- | | | |
- | /dev/sdb1 | ext4 | /data |
- |--------------+------------+----------------|</code></pre><p>OpenBSD is a little different. It uses one big GPT partition, and then it
- further splits up that one big GPT partition into filesystem partitions, which
- can be examined via <a href="https://man.openbsd.org/disklabel">disklabel</a>. So in
- OpenBSD <code>sd0</code> and <code>sd1</code> refer to the first and second hard drive. <code>/dev/sd0c</code>
- refers to the one big GPT partition and <code>/dev/sd0a</code> by convention is the <code>/</code>
- partition. <code>/dev/sd0b</code> is swap by convention and <code>d</code> through <code>p</code> could refor to
- any other arbitrary mount point. So &quot;partition&quot; in OpenBSD may refer to the GPT
- partion or the filesystem partitions.</p><pre><code>|--------------+-------------+----------------|
- | | OpenBSD | |
- |--------------+-------------+----------------|
- | GPT partiton | filesystem | mount location |
- | | partition | |
- | | (FFS) | |
- |--------------+-------------+----------------|
- | /dev/sd01 | /dev/sd0a | / |
- | /dev/sd01 | /dev/sd0b | swap |
- | /dev/sd01 | /dev/sd0c | not mounted |
- | /dev/sd01 | /dev/sd0d | /home |
- | | ... | |
- | /dev/sd01 | /dev/sd0e | /tmp |
- | | | |
- | /dev/sd11 | /dev/sd1i | /data |
- |--------------+-------------+----------------|</code></pre><p>I would highly recommend the OpenBSD
- <a href="https://www.openbsd.org/faq/faq14.html#intro">faq</a> page about this (as well as
- the disklabel man page), which will also act as a more official version of this
- blog post. Now on with the blog post!</p><p>Let’s figure out which drive is my usb stick, and which drive is my SSD with
- Guix on it. Please note that I did not write the output of this command down.
- Your output might look different.</p><pre><code>sysctl hw.disknames
- hw.disknames=sd0:ec557d42f5cbfa41,sd1:</code></pre><p>I typed in the next two commands to try to get a feel for which drive was my
- SSD.</p><pre><code>doas disklabel sd0
- doas disklabel sd1</code></pre><p>I forget what the above commands output-ed, but looking at the output I was able
- to determine that <code>sd0</code> was my GNU/Linux Guix System. Now it was time to set up a
- <a href="https://www.openbsd.org/faq/faq14.html#softraidFDE">full disc encryption</a>.</p><pre><code>cd /dev &amp;&amp; sh MAKEDEV sd0
- dd if=/dev/urandom of=/dev/rsd0c bs=1m</code></pre><p>That second command took 8+ hours to complete. It wrote random data on the
- whole SSD. That way, if an attacker ever stole my hard drive, when they
- examined my hard drive, they would not see:</p><p>00000000EncryptedData0000000EncryptedData000000</p><p>Instead they would see</p><p>RandomDataRandomDataRandomDataRandomDataRandomDataRandomData</p><p>where only the 2nd and 5th =RandomData= are actually my encrypted files. Trying
- to figure what is data and what is just random ones and zeros would be really
- hard. However, I should probably ask on <code>#openbsd</code> irc to make sure that I
- wrote the right command. Is there a way to search your raw hard drive for a
- section of disc that is just 10,000 zeros?</p><p>Anway, let’s partition the <code>sd0</code> drive and format it as a RAID. Random encrypted
- data will go to <code>sd0</code>. OpenBSD will read files from the unencrypted <code>sd1</code>,
- which will be encrypted and stored on <code>sd0</code>.</p><pre><code>fdisk -iy sd0
- sd0&gt; *a* *a*
- sd0&gt;size: [ ... ] ***
- sd0&gt; FS type: *RAID*
- sd0&gt; *w*
- sd0&gt; *q*</code></pre><p>This next command will ask you for a passphrase. If you use an alternative
- keyboard layout, then make your command use numbers and special characters on
- the 1-9 section. That way you can still type in the secret password on boot,
- because OpenBSD changes your keyboard layout after you unlock your encrypted
- volumes.</p><pre><code>bioctl -c C -l sd0a softraid0</code></pre><p>Now let’s set up <code>sd1</code>.</p><pre><code>cd /dev &amp;&amp; sh MAKEDEV sd1
- dd if=/dev/zero of=/dev/rsd1c bs=1m count=1
- exit</code></pre><p>This will return us to the main installer. When the installer asks you which
- hard drive to install OpenBSD on, I said <code>sd1</code>.</p><pre><code>[...]
- Available disks are: sd0 sd1.
- Which disk is the root disk? ('?' for details) [sd0] *sd1*</code></pre><p>And that was that! I did a few things to set up <code>XFCE</code>, which I quickly
- abandoned in favor of i3, and I was off to the races. Then I realized that my
- full-disk decryption passphrase was pretty weak. Basically, because I use a
- physical <a href="https://en.wikipedia.org/wiki/Dvorak_keyboard_layout">dvorak keyboard
- layout</a>, and OpenBSD uses
- the standard <a href="https://en.wikipedia.org/wiki/QWERTY">qwerty</a> layout when you type
- in the password to decrypt the disk, my initial full disk encryption password
- was just numbers. Now, I wanted to change it to my normal password.</p><p>Apparently you can do so while the encrypted volume <a href="https://dev.to/nabbisen/openbsd-disk-encryption-change-passphrase-4i8l">is
- mounted</a>!
- I made sure that I changed the keyboard layout to the standard qwerty, when I typed in
- the new passphase.</p><pre><code> doas bioctl -P sd1 # I was using the dvorak layout here</code></pre><p>In another terminal I typed in:</p><pre><code> setxkbmap -layout us</code></pre><p>Then I moved to the terminal that was asking me to change the full disk
- encryption password.</p><pre><code> Old Passphrase: # I typed in the numbers
- New Passphrase: # I typed in an awesome password
- Confirm Passphrase: # I typed it in again.</code></pre><p>Now let's get back to dvorak:</p><pre><code> setxkbmap -layout dvorak</code></pre><p>That's better. I did have a great time the next day. I was hoping to
- automatically automount my usb stick on boot. So I added this beauty to my
- <code>/etc/fstab</code>.</p><p><code>sd2i /mnt/usb msdos rw 1 2</code></p><p>The next time I booted it threw me into a rescue shell with only <code>/</code> mounted.
- That was a wild ride to fix, bit I will explain how I fixed that next time!</p></content></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" /><content type="html"><p>My friend has a <a href="https://www.raptorcs.com/TALOSII/">TalosII</a> machine. He currently uses void linux, but void has
- dropped their <a href="https://en.wikipedia.org/wiki/Power_ISA">Power ISA</a> support. So I convinced him to give Debian Gnu/Linux a
- try. First we downloaded the <a href="https://www.debian.org/">debian</a> image:</p><p>We navigated our way around the website to download a <a href="https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/">complete debian DVD image</a>,
- which was about 5 GB. We then tried to figure out how to <a href="https://www.debian.org/CD/verify">verify the installer
- image</a>, which basically means, to check that the file we downloaded was not
- malware.</p><p>Well let’s first import the debian GPG keys:</p><pre><code>gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
- &quot;1046 0DAD 7616 5AD8 1FBC 0CE9 9880 21A9 64E6 EA7D&quot;
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
- &quot;DF9B 9C49 EAA9 2984 3258 9D76 DA87 E80D 6294 BE9B&quot;
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
- &quot;F41D 3034 2F35 4669 5F65 C669 4246 8F40 09EA 8AC3&quot;</code></pre><p>Let’s double check that we have those signing keys:</p><pre><code>gpg --list-keys | grep debian
- uid [ unknown] Debian CD signing key &lt;debian-cd@lists.debian.org&gt;
- uid [ unknown] Debian CD signing key &lt;debian-cd@lists.debian.org&gt;
- uid [ unknown] Debian Testing CDs Automatic Signing Key &lt;debian-cd@lists.debian.org&gt;</code></pre><p>Sweet. Now what? How do we actually and practically, via what commands,
- verify the installer images? Well the debian page is not specific about
- what to do next. So I had to searching the internet for how to verify debian
- images. And I found this awesome <a href="https://danilodellaquila.com/en/blog/how-to-verify-authenticity-of-downloaded-debian-iso-images">blog post</a>. Here’s how we do it:</p><pre><code>wget https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/SHA512SUMS
- wget https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/SHA512SUMS.sign
- gpg --verify SHA512SUMS.sign
- gpg --verify SHA512SUMS.sign SHA512SUMS
- sha512sum -c SHA512SUMS 2&gt;/dev/null | grep debian-11.6.0-ppc64el-netinst.iso
- debian-11.6.0-ppc64el-netinst.iso: OK</code></pre><p>We then tried to boot the usb debian power image. That failed to boot. Then we
- tried burning that image to a DVD. That did not work.</p><p>So I am guessing that Debian GNU/Linux will work on power, BUT the graphical
- installer does not currently work on Debian (I found out later that the Debian
- ncuruses installer does work on power).</p><p>My friend then installed Ubuntu server. Ubuntu server's installer actually
- worked! Then we just turned Ubuntu server into a Xubuntu like environment via
- command like: <code>sudo apt install xfce -y</code>.</p><p>Then we rebooted and everything worked! Well, <code>Gnome</code> did not. And <code>Xubuntu</code> did
- not, but then we used <code>gdm</code> to log into <code>xfce</code> desktop. That worked flawlessly.</p><p>The <code>netsurf</code> web browser also worked really well! Which meant we could use any
- website that had virtually no javascript.</p><p>Then I thought, it would be great to have a modern web browser working on my
- friend’s desktop...</p><p>Well it looks like Firefox can run on Power9!</p><p><a href="https://www.talospace.com/search/label/Firefox">https://www.talospace.com/search/label/Firefox</a></p><p>The latest blog post says that you can run Firefox version 110 on
- Power9. You can either add in a <code>--disable-webrtc</code> in your
- <code>.mozconfig</code> or you can compile Firefox with a tiny patch.</p><p>AND nonguix has a recipe for building Firefox. Let’s see if I can
- just install <code>guix</code> set up the <code>nonguix channel</code> and build Firefox that way!</p><p>If the nonguix packaged Firefox doesn’t work, then I can try to set
- build firefox from source via this video:</p><p><a href="https://www.youtube.com/watch?v=Hx42tyEWPxk">https://www.youtube.com/watch?v=Hx42tyEWPxk</a></p><p>Devaun was also a possiblity. That is a fork of debian that does not use
- <code>systemd</code>. My friend is not a big fan of systemd.</p><p>I was also told that Fedora is probably the easiest linux distribution, in which
- to run GNU/Linux on Power9.</p><p>Well installing Fedora was actually easy. The installer just worked.
- (Apparently Debian GNU/Linux disables the ast driver by default, which means a
- VGA display will not work). And I have a working Firefox. Apparently I can run
- a slightly older version of firefox that has a <a href="https://copr.fedorainfracloud.org/coprs/sharkcz/talos/">working javascript JIT.</a></p><p>My friend now has a working Xfce desktop courtesy from <a href="https://getfedora.org/">Fedora GNU/Linux</a>. My only
- concern is that this <a href="https://www.talospace.com/2022/12/fedora-37-mini-review-on-blackbird-and.html">blog post</a> seems to suggest that updating Fedora on a Power9
- machine is going to be quite annoying. I would not want to have to re-install
- Fedora every time they upgrade. I personally no longer have any issues upgrading
- my laptop to my distro latest release, because I have found that GNU Guix System
- just works really well. And if an upgrade breaks, then I can always roll back
- to the previous known working system during the boot process.</p><p>It looks like Fedora can support something like this:</p><p><a href="https://sysguides.com/install-fedora-36-with-snapper-and-grub-btrfs/">https://sysguides.com/install-fedora-36-with-snapper-and-grub-btrfs/</a></p><p>Maybe it is already enabled by default. Who knows.</p><p>I would personally love to recommend my friend to use GNU Guix System, but
- currently you cannot boot Guix System from Power9. The next step for me in this
- journey to help my friend set up his TalosII is to make sure his AMDGPU works.
- This <a href="https://wiki.raptorcs.com/wiki/Troubleshooting/GPU,">wiki article</a> should help with that.</p><p>Also from the <code>#talos-workstation</code> chat log on irc, I found out that the Linux
- kernel is having some issues with the graphics drivers on Power9. Currently the
- user is required to do some manual fiddling. However those workarounds should
- not be necessary by kernel 6.3ish. So until my friend runs Linux 6.3, he will
- probably have the best desktop experience in Xfce or KDE. Gnome has some minor
- issues apparently.</p></content></entry><entry><title>Creating New Build Systems</title><id>https://gnucode.me/creating-new-build-systems.html</id><author><name>Mitchell Schmeisser <mitchellschmeisser@librem.one></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" /><content type="html"><p>In Guix each package must specify a so-called <code>build-system</code>, which
- knows how to bring a package from its inputs to deployment.
- Build systems are responsible for setting up the environment and performing
- build actions within that environment. The most ubiquitous of these is the
- <a href="https://www.gnu.org/software/automake/manual/html_node/GNU-Build-System.html"><code>gnu-build-system</code></a>.
- Guix builds packages using this build system via the usual
- <code>./configure &amp;&amp; make &amp;&amp; make install</code> process.</p><p>Any package can alter its build system by removing some steps or
- adding extra ones. This is extremely common and almost every package
- makes some adjustment to the build process. A <code>build-system</code> in Guix
- hides away some of the common configuration choices. For example, there is
- no need to specify <code>make</code> or <code>gcc</code> as native inputs when using the <code>gnu-build-system</code>,
- because they are added implicitly when a package is lowered into a <em>bag</em>.</p><h2>Anatomy of a Guix Build System</h2><p>The job of a build system is to compile our <em>packages</em> into <em>bags</em>.
- Bags are a lower level representation of a package without all the bells and whistles
- (Makes sense since we are implementing them here),
- the bags are further refined to derivations which are used by the
- build daemon to create an isolated environment suitable for our
- <em>build phases</em>.</p><p>Below is how guix defines a build system.
- It's surprisingly simple with just three items, two of which are for human consumption.</p><pre><code class="language-scheme">(define-record-type* &lt;build-system&gt; build-system make-build-system
- build-system?
- (name build-system-name) ; symbol
- (description build-system-description) ; short description
- (lower build-system-lower)) ; args ... -&gt; bags</code></pre><p>The last field <code>lower</code> is a function which takes the list of arguments
- given in the <code>(package ... (arguments ...))</code> field.
- The keyword arguments that we are allowed to supply when writing the
- package are defined by the build-system.</p><h1>Code Strata</h1><p>Guix builds are implemented in two parts.</p><ol><li><p>Code that compiles <code>packages-&gt;derivations</code>.</p><p>Derivations are the language the Guix Daemon speaks.
- They describe everything about how to <em>derive</em> our package
- from the inputs to the environment and all the code on how to drive
- the build tools.
- This code is run in a poorly defined &quot;user&quot; environment.
- Guix produces derivations that actually can be influenced by
- undeclared aspects of the environment, like manually installed Guile
- packages or code added with the `-L` flag.</p></li><li><p>The guix daemon runs the builder code in as isolated and reproducible build environment to produce the package from its inputs.</p><p>This code is executed in an explicitly defined build environment
- with nothing being introduced from the host.</p></li></ol><p>Code that runs in the host environment <em>stages</em> code, which will run in isolation.
- This is where G-Expressions really shine.
- They provide the syntax to describe this relationship.</p><h1>Build Phases</h1><p>All programs are built more or less the same way.</p><ol><li><p>Unpack the source code.</p><p>Whether it's tarball or a version controlled repository, the guix daemon must
- copy the software's source tree into our build environment.</p></li><li><p>Patch the shebangs.</p><p>Many projects contain scripts written to aid the build process.
- In Linux, executable scripts can contain a so-called <em>shebang</em>,
- which contains an absolute path to the program, which is meant to
- interpret it: e.g. <code>#!/bin/sh</code>. Most distributions provide a
- POSIX compliant shell interpreter at this location. Guix System does not do this.
- Instead, Guix System's <code>sh</code> is yet another component in the store, so all of these files must
- be patched to point to the new location, which is only known at
- build time. We cannot rely on our <code>PATH</code> to store this information,
- because the Linux kernel does not respect such things.</p></li><li><p>Configure the build.</p><p>Whether it is autotools or CMake or ninja, etc., if you are relying
- on tools from the host system, then you have a step, which enables the
- host system to tell you where to find those tools.</p></li><li><p>Patch the generated shebangs.</p><p>Sometimes the configure phases creates scripts, which run during the build phase,
- these often contain references to <code>/bin/sh</code>, and so guix must patch these scripts as well.</p></li><li><p>Build!</p><p>That's right folks we are off to the races, and the program is building.
- Usually this takes the form of a call to <code>make</code>, with a handful of
- flags and last minute definitions, but there are other more <em>exotic</em> methods.</p></li><li><p>Test.</p><p>Now that guix built our software, we should test it before we sent software
- updates to users. This helps the guix project catch and eleminate software
- bugs before they impact guix users. Not all packages have tests, and guix
- developers occasionally disables some packages' testsuites, but the
- guix policy is to run the software's testsuite, if it is exists.</p></li><li><p>Install.</p><p>Now that we've verified everything works as expected, it is time to run
- <code>make install</code> or the equivalent. This phase copies our build artifacts into
- their final resting place in the store.</p></li><li><p>Validate the Installation.</p><p>Here guix checks that our outputs do not contain any component paths, which
- are not specified by the package inputs. That would lead to incomplete
- deployment, harm <a href="https://reproducible-builds.org/">reproducible builds</a>,
- and would be &quot;bad&quot;.</p></li></ol><p>There are more steps, but they are not universally applicable.
- Of course no generic model, such as this, captures all the chaos of the
- world, and every package has exceptions to it.</p><p>Guix implements <em>build phases</em> as a list of lambdas.
- As such our package can modify this list and add/delete/replace
- lambdas as they require. It is so common Guix provides a syntax
- for manipulating build phases: <code>modify-phases</code>.</p><p>A build system contains a default set of phases called <code>%standard-phases</code>.
- Every build system starts with the <code>gnu-build-system</code>, <code>%standard-phases</code>,
- and modifies it to their needs.
- It is then provided to the packages using that build system.</p><p>The <code>cmake-build-system</code> is nearly identical to the <code>gnu-build-system</code>
- except two phases.</p><pre><code class="language-scheme">;;
- ;; Excerpt from `guix/build/cmake-build-system.scm`
- ;;
- (define %standard-phases
- ;; Everything is the same as the GNU Build System, except for the `configure'
- ;; and 'check' phases.
- (modify-phases gnu:%standard-phases
- (delete 'bootstrap)
- (replace 'check check)
- (replace 'configure configure)))</code></pre><h2>The Zephyr Build System</h2><p>Zephyr uses <code>cmake</code> to perform <em>physical component composition</em>.
- It searches the filesystem and generates scripts, which the toolchain will
- use to successfully combine those components into a firmware image.</p><p>The fact that Zephyr provides this mechanism is one reason I chose to
- target zephyr in the first place.</p><p>This separation of projects in an embedded context is a really great thing.
- It brings many of the advantages to the Linux world such as
- code re-use, smaller binaries, more efficient cache/RAM usage, etc.
- It also allows us to work as independent groups and compose
- contributions from many teams.</p><p>It also brings all of the complexity. Suddenly all of the problems
- that plague traditional deployment now apply to our embedded
- system. The fact that the libraries are statically linked at compile
- time instead of dynamically at runtime is simply an implementation detail.</p><p>We now have dependencies which we must track and compose in the correct environments.
- The Zephyr Project offers a tool to help manage this new complexity: <a href="https://docs.zephyrproject.org/latest/develop/west/index.html">The West Meta-tool</a>!
- To call it a &quot;meta-tool&quot; is an abuse of language. It is not even meta
- enough to bootstrap itself and relies on <a href="https://docs.zephyrproject.org/latest/develop/getting_started/index.html">other package managers</a> to get
- started.
- In fact, it is not even suitable for managing multiple embedded projects as a composition!
- The project recommends <a href="https://docs.zephyrproject.org/latest/build/sysbuild/index.html">Yet Another Tool</a> for this very common use case.</p><p>In fact, West does not really bring anything new to the table, and we can
- replace it in the same way we can replace every other language specific package
- manager, like node (js), Cabol (haskell), Dub (D), etc. <strong>PUTTING SOFTWARE ON
- THE SYSTEM IS THE JOB OF THE PACKAGE MANAGER!</strong>.</p><p>West is the way it is for a reason. It is very practical to design the package
- manager in this way, because it enables Windows users to access the build
- environment. A more in-depth discussion on the material conditions, which lead
- to this or that design decision of the West tool is beyond the scope of this
- post. Let's instead explain how to provide a meta-tool and bootstrap complex
- embedded systems, from the ground up, in a flexible, composable, and
- <em>reproducible</em> way.</p><h1>Why not use <code>cmake-build-system</code>?</h1><p>A fair question! Zephyr's CMake scripts require additional information
- about the build to be provided at configure time. Most tedius for
- zephyr-packages is the <code>ZEPHYR_MODULES</code> variable, which must be formatted and
- passed to CMake on the command line.</p><h1>Host Side</h1><p>Our job at this level is to take packages described using the <code>package</code> syntax and
- lower it into a derivation that the guix-daemon can understand.</p><p>Here is the derivation for building hello world for the <code>frdm_k64f</code> (hashes removed for brevity).
- The <code>package</code> syntax provides a human friendly veneer over this garbage.</p><pre><code class="language-sh">Derive
- ([(&quot;debug&quot;,&quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--debug&quot;,&quot;&quot;,&quot;&quot;)
- ,(&quot;out&quot;,&quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr-&quot;,&quot;&quot;,&quot;&quot;)]
- ,[(&quot;/gnu/store/...-newlib-nano-3.3.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-hal-nxp-3.1.0-0.708c958.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-make-4.3.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-findutils-4.8.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-grep-3.6.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-sed-4.8.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-ld-wrapper-0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-bash-minimal-5.1.8.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-hal-cmsis-5.8.0-0.093de61.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-gawk-5.1.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-gzip-1.10.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-six-1.16.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-zephyr-3.1.0-0.zephyr--checkout.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-linux-libre-headers-5.10.35.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-3.9.9.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-diffutils-3.8.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-arm-zephyr-eabi-nano-toolchain-12.1.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-pyelftools-0.28.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-guile-3.0.7.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-dateutil-2.8.2.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-patch-2.7.6.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-gcc-10.3.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-bzip2-1.0.8.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-dtc-1.6.1.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-cmake-minimal-3.21.4.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-pyyaml-6.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-packaging-21.3.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-arm-zephyr-eabi-binutils-2.38.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-glibc-2.33.drv&quot;,[&quot;out&quot;,&quot;static&quot;])
- ,(&quot;/gnu/store/...-qemu-7.2.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-ninja-1.10.2.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-tar-1.34.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-xz-5.2.5.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-binutils-2.37.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-pykwalify-1.7.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-zephyr-3.1.0-0.zephyr-.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-glibc-utf8-locales-2.33.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-gdb-arm-zephyr-eabi-12.1.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-module-import-compiled.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-file-5.39.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-pyparsing-3.0.6.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-python-docopt-0.6.2.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-arm-zephyr-eabi-sdk-0.15.0.drv&quot;,[&quot;out&quot;])
- ,(&quot;/gnu/store/...-coreutils-8.32.drv&quot;,[&quot;out&quot;])]
- ,[&quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--builder&quot;,&quot;/gnu/store/...-module-import&quot;]
- ,&quot;x86_64-linux&quot;,&quot;/gnu/store/...-guile-3.0.7/bin/guile&quot;,[&quot;--no-auto-compile&quot;
- ,&quot;-L&quot;,&quot;/gnu/store/...-module-import&quot;
- ,&quot;-C&quot;,&quot;/gnu/store/...-module-import-compiled&quot;
- ,&quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--builder&quot;]
- ,[(&quot;debug&quot;,&quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--debug&quot;)
- ,(&quot;out&quot;,&quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr-&quot;)])</code></pre><h3>Lowering packages to bags</h3><p>We must provide the build system with a function which the following lambda form.</p><pre><code class="language-scheme">(lambda* (name #:key #:allow-other-keys) ...)</code></pre><p>This means it takes one required argument <code>name</code> and any amount of keys.
- Individual procedures can specify keys they are interested in such as
- <code>inputs</code> or <code>outputs</code>.</p><p>Which keys are ultimately supported is defined by our <code>lower</code> function
- and our <em>build phases</em>.</p><pre><code class="language-scheme">;; Use module-ref instead of referencing the variables directly
- ;; to avoid circular dependencies.
- (define %zephyr-build-system-modules
- `((mfs build zephyr-build-system)
- ,@%cmake-build-system-modules))
- (define default-zephyr-base
- (module-ref (resolve-interface '(mfs packages zephyr))
- 'zephyr))
- (define default-zephyr-sdk
- (module-ref (resolve-interface '(mfs packages zephyr))
- 'arm-zephyr-eabi-sdk))
- (define default-ninja
- (module-ref (resolve-interface '(gnu packages ninja))
- 'ninja))
- (define default-cmake
- (module-ref (resolve-interface '(gnu packages cmake))
- 'cmake-minimal))
- (define* (lower name
- #:key source inputs native-inputs outputs system target
- (zephyr default-zephyr-base)
- (sdk default-zephyr-sdk)
- (ninja default-ninja)
- (cmake default-cmake)
- #:allow-other-keys
- #:rest arguments)
- &quot;Return a bag for NAME.&quot;
- (define private-keywords `(#:zephyr #:inputs #:native-inputs #:target))
- (bag
- (name name)
- (system system)
- (target target)
- (build-inputs `(,@(if source `((&quot;source&quot; ,source)) '())
- ,@`((&quot;cmake&quot; ,cmake))
- ,@`((&quot;zephyr-sdk&quot; ,sdk))
- ,@`((&quot;zephyr&quot; ,zephyr))
- ,@`((&quot;ninja&quot; ,ninja))
- ,@native-inputs
- ,@(standard-packages)))
- ;; Inputs need to be available at build time
- ;; since everything is statically linked.
- (host-inputs inputs)
- (outputs outputs)
- (build zephyr-build)
- (arguments (strip-keyword-arguments private-keywords arguments))))</code></pre><p>Here our <code>lower</code> function provides default values for the packages
- every zephyr package needs, the SDK, CMake, and <code>ZEPHYR_BASE</code> and adds
- them to the build-inputs.</p><p>Notice we also strip out some keywords, which do not get passed to the
- build function, because they get included as part of the broader
- abstractions the build system provides.</p><p>At this step it would be great to have a parser which could work out
- the required sdk from a <code>.config,</code> but this requires compiling the kconfig,
- which requires at least the sdk cmake files.
- There might be a way to make it happen, but until then if a board needs a different
- sdk, then they can specify it in an argument keyword.</p><h3>Lowering Bags to Derivations</h3><p>Here is the definition for the actual build procedure. There is a lot
- of abstract trickery going on here, so do not worry if you don't understand it,
- I barely understand it!
- It's mostly copy and pasted from the CMake build system.</p><pre><code class="language-scheme">(define* (zephyr-build name inputs
- #:key guile source
- board
- (outputs '(&quot;out&quot;)) (configure-flags ''())
- (search-paths '())
- (make-flags ''())
- (out-of-source? #t)
- (tests? #f)
- (test-target &quot;test&quot;)
- (parallel-build? #t) (parallel-tests? #t)
- (validate-runpath? #f)
- (patch-shebangs? #t)
- (phases '%standard-phases)
- (system (%current-system))
- (substitutable? #t)
- (imported-modules %zephyr-build-system-modules)
- ;; The modules referenced here contain code
- ;; which will be staged in the build environment with us.
- ;; Our build gexp down below will only be able to access this code
- ;; and we must be careful not to reference anything else.
- (modules '((zephyr build zephyr-build-system)
- (guix build utils))))
- &quot;Build SOURCE using CMAKE, and with INPUTS. This assumes that SOURCE
- provides a 'CMakeLists.txt' file as its build system.&quot;
- ;; This is the build gexp. It handles staging values from our host
- ;; system into code that our build system can run.
- (define build
- (with-imported-modules imported-modules
- #~(begin
- (use-modules #$@(sexp-&gt;gexp modules))
- #$(with-build-variables inputs outputs
- #~(zephyr-build #:source #+source
- #:system #$system
- #:outputs %outputs
- #:inputs %build-inputs
- #:board #$board
- #:search-paths '#$(sexp-&gt;gexp
- (map search-path-specification-&gt;sexp
- search-paths))
- #:phases #$(if (pair? phases)
- (sexp-&gt;gexp phases)
- phases)
- #:configure-flags #$(if (pair? configure-flags)
- (sexp-&gt;gexp configure-flags)
- configure-flags)
- #:make-flags #$make-flags
- #:out-of-source? #$out-of-source?
- #:tests? #$tests?
- #:test-target #$test-target
- #:parallel-build? #$parallel-build?
- #:parallel-tests? #$parallel-tests?
- #:validate-runpath? #$validate-runpath?
- #:patch-shebangs? #$patch-shebangs?
- #:strip-binaries? #f)))))
- (mlet %store-monad ((guile (package-&gt;derivation (or guile (default-guile))
- system #:graft? #f)))
- (gexp-&gt;derivation name build
- #:system system
- #:target #f
- #:graft? #f
- #:substitutable? substitutable?
- #:guile-for-build guile)))</code></pre><p>Finally we define our build system which the package definitions can reference.</p><pre><code class="language-scheme">(define zephyr-build-system
- (build-system
- (name 'zephyr)
- (description &quot;The standard Zephyr build system&quot;)
- (lower lower)))</code></pre><p>Easy right?</p><h1>Build Side</h1><p>The build side is not as complex as you might initially expect.
- Our build system is almost exactly the same as the CMake build system
- except our configure phase passes different values to CMake.
- Our job is much easier.</p><h3>Locating Modules</h3><p>Zephyr CMake requires the zephyr <em>modules</em> which are needed for the
- build to be supplied on the command line.
- Unfortunately for us, the
- <a href="https://docs.zephyrproject.org/3.1.0/develop/application/index.html#important-build-vars">documentation</a>
- is wrong, and the <code>ZEPHYR_MODULES</code> environment variable is not honored.
- Thus we must implement some other solution for locating modules, until
- this that is fixed.</p><p><strong>Input Scanning</strong> - Lucky for us we are keeping detailed information
- about our dependencies. It is a simple matter to write a file tree
- walker which collects all the zephyr modules in our inputs.</p><pre><code class="language-scheme">(define* (find-zephyr-modules directories)
- &quot;Return the list of directories containing zephyr/module.yml found
- under DIRECTORY, recursively. Return the empty list if DIRECTORY is
- not accessible.&quot;
- (define (module-directory file)
- (dirname (dirname file)))
- (define (enter? name stat result)
- ;; Skip version control directories.
- ;; Shouldn't be in the store but you never know.
- (not (member (basename name) '(&quot;.git&quot; &quot;.svn&quot; &quot;CVS&quot;))))
- (define (leaf name stat result)
- ;; Add module root directory to results
- (if (and (string= &quot;module.yml&quot; (basename name))
- (string= &quot;zephyr&quot; (basename (dirname name))))
- (cons (module-directory name) result)
- result))
- (define (down name stat result) result)
- (define (up name stat result) result)
- (define (skip name stat result) result)
- (define (find-modules directory)
- (file-system-fold enter? leaf down up skip error
- '() (canonicalize-path directory)))
- (append-map find-modules directories))
- (define (zephyr-modules-cmake-argument modules)
- &quot;Return a proper CMake list from MODULES, a list of filepaths&quot;
- (format #f &quot;-DZEPHYR_MODULES='~{~a~^;~}'&quot; modules))
- </code></pre><p>Here are two functions. The first one <code>find-zephyr-modules</code> walks a
- list of directories (package inputs) and returns a list of every module it finds.
- The second one is just for syntactic convenience when writing the CMake invokation.
- This is also slightly more robust than West's module discovery, because it allows for
- a single repository to provide multiple modules which are not <em>technically</em> required
- to be at the top level.</p><p>From here we just need to provide alternate implementations of <code>configure</code> and <code>install</code>.</p><pre><code class="language-scheme">(define* (configure #:key outputs (configure-flags '())
- inputs (out-of-source? #t)
- build-type
- #:allow-other-keys)
- &quot;Configure the given package.&quot;
- (let* ((out (assoc-ref outputs &quot;out&quot;))
- (abs-srcdir (getcwd))
- (srcdir (if out-of-source?
- (string-append &quot;../&quot; (basename abs-srcdir))
- &quot;.&quot;)))
- (format #t &quot;source directory: ~s (relative from build: ~s)~%&quot;
- abs-srcdir srcdir)
- (when out-of-source?
- (mkdir &quot;../build&quot;)
- (chdir &quot;../build&quot;))
- (format #t &quot;build directory: ~s~%&quot; (getcwd))
- ;; this is required because zephyr tries to optimize
- ;; future calls to the build scripts by keep a cache.
- (setenv &quot;XDG_CACHE_HOME&quot; (getcwd))
- (let ((args `(,srcdir
- ,@(if build-type
- (list (string-append &quot;-DCMAKE_BUILD_TYPE=&quot;
- build-type))
- '())
- ;; enable verbose output from builds
- &quot;-DCMAKE_VERBOSE_MAKEFILE=ON&quot;
- ,(zephyr-modules-cmake-argument
- (find-zephyr-modules (map cdr inputs)))
- ,@configure-flags)))
- (format #t &quot;running 'cmake' with arguments ~s~%&quot; args)
- (apply invoke &quot;cmake&quot; args))))
- (define* (install #:key outputs #:allow-other-keys)
- (let* ((out (string-append (assoc-ref outputs &quot;out&quot;) &quot;/lib/firmware&quot;))
- (dbg (string-append (assoc-ref outputs &quot;debug&quot;) &quot;/share/zephyr&quot;)))
- (mkdir-p out)
- (mkdir-p dbg)
- (copy-file &quot;zephyr/.config&quot; (string-append dbg &quot;/config&quot;))
- (copy-file &quot;zephyr/zephyr.map&quot; (string-append dbg &quot;/zephyr.map&quot;))
- (copy-file &quot;zephyr/zephyr.elf&quot; (string-append out &quot;/zephyr.elf&quot;))
- (copy-file &quot;zephyr/zephyr.bin&quot; (string-append out &quot;/zephyr.bin&quot;))))
- ;; Define new standard-phases
- (define %standard-phases
- (modify-phases cmake:%standard-phases
- (replace 'configure configure)
- (replace 'install install)))
- ;; Call cmake build with our new phases
- (define* (zephyr-build #:key inputs (phases %standard-phases)
- #:allow-other-keys #:rest args)
- (apply cmake:cmake-build #:inputs inputs #:phases phases args))</code></pre><p>One thing to note is the &quot;debug&quot; output. This exists so we don't
- retain references to our build environment and make the file system
- closure huge. If you put all of the build outputs in the same store
- path, then the deployment closure will grow from 2MB to 833MB.</p><h1>Defining Zephyr Packages</h1><p>Now that we have a proper build system, it's time to define some packages!</p><h3>Zephyr Base</h3><p>Zephyr base contains the Zephyr source code. It is equivalent (in my mind
- anyway) to the linux kernel, in that packages' definitions' specifications,
- which target the linux kernel, can be minimal.</p><p>The selection of operating system actually comes from the toolchain. For
- example, we build linux packages with the <a href="https://www.gnu.org/software/autoconf/manual/autoconf-2.65/html_node/Specifying-Target-Triplets.html">gnu
- triplet</a>.
- When we select the <code>arm-linux-gnueabihf,</code> we are specifying our operating system.</p><p>It is the same for Zephyr. When we build for zephyr we use the <code>arm-zephyr-eabi</code>
- toolchain. However, unlike linux applications, zephyr applications are
- embedded firmware images and are generally statically linked.
- Thus this package just consists of its source code and is not compiled directly.
- We cannot compile it now because applications/modules provide the required Kconfig
- options.</p><pre><code class="language-scheme">(define-public zephyr
- (let ((version &quot;3.1.0&quot;)
- (commit &quot;zephyr-v3.1.0&quot;))
- (package
- (name &quot;zephyr&quot;)
- (version version)
- (home-page &quot;https://zephyrproject.org&quot;)
- (source (origin (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/zephyr&quot;)
- (commit commit)))
- (file-name (git-file-name name version))
- (sha256
- (base32 &quot;1yl5y9757xc3l037k3g1dynispv6j5zqfnzrhsqh9cx4qzd485lx&quot;))
- (patches
- ;; this patch makes this package work in a symlinked profile
- (search-patches &quot;zephyr-3.1-linker-gen-abs-path.patch&quot;))))
- (build-system copy-build-system)
- (arguments
- `(#:install-plan
- '((&quot;.&quot; &quot;zephyr-workspace/zephyr&quot;))
- #:phases
- (modify-phases %standard-phases
- (add-after 'unpack 'patch-cmake-scripts
- (lambda* _
- (format #t &quot;~a~&amp;&quot; (getcwd))
- ;; Some cmake scripts assume the presence of a
- ;; git repository in the source directory.
- ;; We will just hard-code that information now
- (substitute* &quot;CMakeLists.txt&quot;
- ((&quot;if\\(DEFINED BUILD_VERSION\\)&quot; all)
- (format #f &quot;set(BUILD_VERSION \&quot;~a-~a\&quot;)~&amp;~a&quot;
- ,version ,commit all))))))))
- (propagated-inputs
- (list python-3
- python-pyelftools
- python-pykwalify
- python-pyyaml
- python-packaging))
- (native-search-paths
- (list (search-path-specification
- (variable &quot;ZEPHYR_BASE&quot;)
- (files '(&quot;zephyr-workspace/zephyr&quot;)))))
- (synopsis &quot;Source code for zephyr rtos&quot;)
- (description &quot;Zephyr rtos source code.&quot;)
- (license license:apsl2))))
- (define-public zephyr-3.2.0-rc3
- (package (inherit zephyr)
- (version &quot;3.2.0-rc3&quot;)
- (source (origin (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/zephyr&quot;)
- (commit &quot;v3.2.0-rc3&quot;)))
- (file-name (git-file-name &quot;zephyr&quot; version))
- (sha256
- (base32 &quot;06ksd9zj4j19jq0zg3lms13jx0gxzjc41433zgb91cnd2cqmn5cb&quot;))
- (patches
- (search-patches &quot;zephyr-3.1-linker-gen-abs-path.patch&quot;))))))</code></pre><p>Here we use the <code>copy-build-system</code> which takes a list of source destination
- pairs. In our case, we just copy everything to the output directory, but not
- before patching some files to accomodate our special environment.</p><p>While developing this I wanted to test some toolchain/board features
- on the latest release of Zephyr. I included an example of that package
- definition to show how we can easily accomodate side by side package
- variants and experiment without breaking anything.</p><h3>Modules</h3><p>It's finally time to define some firmware!
- Zephyr packages some examples in <code>$ZEPHYR_BASE/samples</code> including a
- basic hello world. The k64 development board is already supported
- by Zephyr so building the example is trivial.</p><p>In order to actually target the k64 we need to two modules, the NXP
- hardware abstraction layer, and CMSIS.
- Looking at <code>$ZEPHYR_BASE/west.yml</code> we can see the repositories
- and commits which contain these modules. This is how West does
- dependency management.</p><p>Defining these packages is not so bad (see footnote 1).</p><pre><code class="language-scheme">(define-public hal-cmsis
- (package
- (name &quot;hal-cmsis&quot;)
- (version &quot;5.8.0&quot;)
- (home-page &quot;https://developer.arm.com/tools-and-software/embedded/cmsis&quot;)
- (source (origin
- (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/cmsis&quot;)
- (commit &quot;093de61c2a7d12dc9253daf8692f61f793a9254a&quot;)))
- (file-name (git-file-name name version))
- (sha256
- (base32 &quot;0f7cipnwllna7iknsnz273jkvrly16yr6wm4y2018i6njpqh67wi&quot;))))
- (build-system zephyr-module-build-system)
- (arguments `(#:workspace-path &quot;/modules/hal/cmsis&quot;))
- (synopsis &quot;Zephyr module providing the Common Microcontroller
- Software Interface Standard&quot;)
- (description &quot;Zephyr module providing the Common Microcontroller
- Software Interface Standard&quot;)
- (license license:apsl2)))
- (define-public hal-nxp
- (package
- (name &quot;hal-nxp&quot;)
- (version &quot;3.1.0&quot;)
- (home-page &quot;https://nxp.com&quot;)
- (source (origin
- (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/hal_nxp&quot;)
- (commit &quot;708c95825b0d5279620935a1356299fff5dfbc6e&quot;)))
- (file-name (git-file-name name version))
- (sha256
- (base32 &quot;1c0i26bpk6cyhr1q4af183jclfmxshv4d15i7k3cz7brzb12m8q1&quot;))))
- (build-system zephyr-module-build-system)
- (arguments `(#:workspace-path &quot;/modules/hal/nxp&quot;))
- (native-search-paths
- (list (search-path-specification
- (variable &quot;ZEPHYR_MODULES&quot;)
- (files `(,(string-append %zephyr-workspace-name module-path)))
- (separator &quot;;&quot;))))
- (synopsis &quot;Zephyr module for NXP Hardware Abstraction Layer&quot;)
- (description &quot;Provides sources for NXP HAL zephyr module&quot;)
- (license license:bsd-3)))</code></pre><p>With these two modules defined we can write <code>zephyr-hello-world-frdm-k64f</code>.</p><h3>Hello world</h3><pre><code class="language-scheme">(define-public zephyr-hello-world-frdm-k64f
- (package
- (name &quot;zephyr-hello-world-frdm-k64f&quot;)
- (version (package-version zephyr))
- (home-page &quot;https://zephyrproject.org&quot;)
- (source (file-append (package-source zephyr)
- &quot;/samples/hello_world&quot;))
- (build-system zephyr-build-system)
- (arguments
- '(#:configure-flags '(&quot;-DBOARD=frdm_k64f&quot;)))
- (outputs '(&quot;out&quot; &quot;debug&quot;))
- (inputs
- (list hal-cmsis
- hal-nxp))
- (synopsis &quot;Hello world example from Zephyr Project&quot;)
- (description &quot;Sample package for zephyr project&quot;)
- (license license:apsl2)))</code></pre><h3>Building</h3><p>Our above definition can be built using the following:
- When testing package definitions, I use the <code>-L</code> flag to point to the local
- repository to load the new packages. I will be omitting that flag as
- if I had ~guix pull~ed successfully from <a href="https://github.com/paperclip4465/guix-zephyr">guix-zephyr</a>.</p><pre><code class="language-sh">guix build zephyr-hello-world-frdm-k64f
- /gnu/store/...-zephyr-hello-world-frdm-k64f-3.1.0-debug
- /gnu/store/...-zephyr-hello-world-frdm-k64f-3.1.0</code></pre><p>This actually doesn't fully test our toolchain. The hello world
- example, by default, will use a zephyr provided
- minimal implementation of the C library and will not link against
- newlib.</p><pre><code class="language-scheme">(define-public zephyr-hello-world-newlib-frdm-k64f
- (package
- (inherit zephyr-hello-world-frdm-k64f)
- (name &quot;zephyr-hello-world-newlib-frdm-k64f&quot;)
- (arguments
- (substitute-keyword-arguments (package-arguments zephyr-hello-world-frdm-k64f)
- ((#:configure-flags flags)
- `(append
- '(&quot;-DCONFIG_MINIMAL_LIBC=n&quot;
- &quot;-DCONFIG_NEWLIB_LIBC=y&quot;)
- ,flags))))))
- guix build zephyr-hello-world-newlib-frdm-k64f
- /gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-debug
- /gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0</code></pre><p>Woohoo!</p><h1>Further Musings</h1><p>One thing I learned while going through the pains of getting this
- working is that even though the components are &quot;modular&quot; there is
- still a lot rigid interdependencies, especially on the zephyr base.
- Just having two versions of Zephyr in the code base made component
- composition fragile.
- Modules rely on specific features from the kernel.
- This is hidden from developers normally by west automagically walking
- the `west.yml` of all of the declared dependencies recursively to
- discover the graph.</p><p>While there are many benefits to a modularized build system, a monolithic build
- system, like Zephyr, does have many benefits too.</p><p>Part of the problem comes from the domain itself. If you really want to be able
- to target the most resource constrained systems and deal with the &quot;industrial
- mess&quot; that comes from every board being unique, you have to be as generic and
- flexible as possible, which is hard in a guix-like modular build system.</p><p>Superficially the problem is solved in the same way Linux solved it, using
- device trees and having a very stable userland interface. However, unlike Linux
- where the device tree is compiled to a binary blob and interpreted by drivers at
- runtime, Zephyr device trees are compiled to a <code>.h</code> file and are mostly
- interpreted by the C pre-processor using an elaborate set of macros.</p><p>It goes beyond simply abstracting the hardware using clever hacks.
- Zephyr applications (and any zephyr module) can also introduce new
- &quot;kernel&quot; code, configuration options, and even linker script fragments
- at build time.
- Essentially the Zephyr CMake build system acts like a reverse ld.
- Instead of linking libraries after compilation, it discovers these
- things before gcc is ever invoked and provides additional code
- generation steps.</p><p>Zephyr does not have a stable &quot;userland&quot; interface for the same
- reason Linux does not have a stable &quot;kernel module&quot; interface.
- Because Zephyr applications are so tightly coupled to the hardware
- they run on it is not uncommon to bypass Zephyr utilities and directly
- touch hardware and memory.</p><p>In this way they are more related to kernel modules
- than userspace applications such as GNU Hello.</p><p>Perhaps there is a lispy way to track several zephyr releases without reducing
- the ability to freely modify components in the usual ways...I invite you dear
- reader to developer code to explore that possibility.</p><p>It is use-able for Guix anyway.</p><h1>Why a Special Build System? Why not <code>--target=frdm_k64f</code>?</h1><p>That is a fair question!
- At first glance you might imagine the following incantation:</p><pre><code class="language-sh">guix build --target=arm-zephyr-eabi hello</code></pre><p>The problem with calling the toolchain directly is that the architecture
- is specified by the board selection. It is not generally useful to
- compile a board to a different architecture.</p><p>Perhaps maybe something like this then.</p><pre><code class="language-sh">guix build --target=frdm_k64f hello</code></pre><p>The above command tells GNU hello to link against arm-zephyr-newlib and run on
- a specific board. The problem is that while this <em>may</em> work for GNU Hello, it
- will not work for anything, which requires inputs that are discovered by normal
- methods. Only packages which target zephyr explicitly could benefit from such an
- interface, and at that point, you may as well record which board is being targeted
- in the package definition.</p><p>In general not all zephyr applications can run on every board zephyr
- can run on, so the usefulness of the above command is dubious.</p><p>I think if you have firmware which targets multiple boards it is
- better to define a package for every board. It is likely every board
- will require special configuration flags anyway.</p><h1>Conclusion</h1><p>Zephyr has a very complex build process which can be difficult to
- understand and frustrating to set up.</p><p>Using Guix to define firmware packages makes these problems disappear.
- It is trivial to create a channel which contains all of the quirks of
- your platform and share it with a team or student.</p><p>Packages defined this way serve as a reproducible starting point for
- future hardware revisions and variations.</p><h1>Footnotes</h1><ol><li>I also made a <code>zephyr-module-build-system</code> as well which is just the
- <code>copy-build-system</code> that mimics the default zephyr workspace layout as provided
- by west. This way we do not need to provide the same install-plan for every
- module we package. However as I use the <code>copy-build-system</code> more often, it
- doesn't really provide much over just using the copy-build system.</li></ol></content></entry><entry><title>Building Toolchains with Guix</title><id>https://gnucode.me/building-toolchains-with-guix.html</id><author><name>Mitchell Schmeisser <mitchellschmeisser@librem.one></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" /><content type="html"><p>Today's post is a guest post from my new internet friend Mitchell. We met on the
- #guix irc channel, and I offered to post a few of his blog posts on this blog. Without further ado,
- here is Michell's first blog post (it's pretty fantastic)!</p><h1>Overview</h1><p>In order to deploy embedded software using Guix we first need to teach Guix
- how to build it. Since Guix bootstraps everything this means we must teach Guix
- how to build our toolchain.</p><p>The <a href="https://zephyrproject.org">Zephyr Project</a> uses its own fork of GCC with custom configs for
- the architectures supported by the project.</p><h1>Anatomy of a toolchain</h1><p>Toolchains are responsible for taking high level descriptions of programs and
- lowering them down to a series of equivalent machine instructions. This process
- involves more than just a compiler. The compiler uses the <code>binutils</code> to
- manipulate it’s internal representation down to a given architecture. It
- also needs the C standard library as well as a few other libraries needed for
- some compiler optimizations.</p><p>The C library provides the interface to the underlying kernel. System calls like <code>write</code>
- and <code>read</code> are provided by <code>Glibc</code> on most Linux distributions.</p><p>In embedded systems smaller implementations like <code>newlib</code> and <code>newlib-nano</code> are used.</p><h1>Bootstrapping a Toolchain</h1><p>In order to compile GCC we need a C library that’s been compiled for
- our target architecture. How can we cross compile our C library if we
- need our C library to build a cross compiler? The solution is to build
- a simpler compiler that doesn’t require the C library to function.
- It will not be capable of as many optimizations and it will be very slow,
- however it will be able to build the C libraries as well as the complete version
- of GCC.</p><p>In order to build the simpler compiler we need to compile the <code>binutils</code> to
- work with our target architecture.
- The <code>binutils</code> can be bootstrapped with our host GCC and have no target dependencies.</p><p><a href="https://crosstool-ng.github.io/docs/toolchain-construction/">For more information read this.</a></p><p>Doesn’t sound so bad right? It isn’t… in theory.
- However internet forums since time immemorial have been
- littered with the laments of those who came before.
- From incorrect versions of <code>ISL</code> to the wrong C library being linked
- or the host linker being used, etc.
- The one commonality between all of these issues is the environment.
- Building GCC is difficult because isolating build environments is hard.</p><p>In fact as of <code>v0.14.2</code> the zephyr SDK repository took down the build
- instructions and posted a sign that read “Building this is too
- complicated, don’t worry about it.” (I’m paraphrasing, but
- <a href="https://github.com/zephyrproject-rtos/sdk-ng/tree/v0.14.2#build-process">not by
- much</a>.)</p><p>We will neatly side step all of these problems and not
- risk destroying or polluting our host system with garbage
- by using Guix to manage our environments for us.</p><p>Our toolchain only requires the first pass compiler because
- newlib(-nano) is statically linked and introduced to the toolchain
- by normal package composition.</p><h1>Defining the Packages</h1><p>All of the base packages are defined in <code>zephyr/packages/zephyr.scm</code>.
- Zephyr modules are defined in <code>zephyr/packages/zephyr-xyz.scm</code>, following
- the pattern of other module systems implemented by Guix.</p><h2>Binutils</h2><p>First thing we need to build is the <code>arm-zephyr-eabi</code> binutils.
- This is very easy in Guix.</p><pre><code>(define-module (zephyr packages zephyr)
- #:use-module (guix packages)
- (define-public arm-zephyr-eabi-binutils
- (let ((xbinutils (cross-binutils &quot;arm-zephyr-eabi&quot;)))
- (package
- (inherit xbinutils)
- (name &quot;arm-zephyr-eabi-binutils&quot;)
- (version &quot;2.38&quot;)
- (source
- (origin (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/binutils-gdb&quot;)
- (commit &quot;6a1be1a6a571957fea8b130e4ca2dcc65e753469&quot;)))
- (file-name (git-file-name name version))
- (sha256 (base32 &quot;0ylnl48jj5jk3jrmvfx5zf8byvwg7g7my7jwwyqw3a95qcyh0isr&quot;))))
- (arguments
- `(#:tests? #f
- ,@(substitute-keyword-arguments (package-arguments xbinutils)
- ((#:configure-flags flags)
- `(cons &quot;--program-prefix=arm-zephyr-eabi-&quot; ,flags)))))
- (native-inputs
- (append
- (list texinfo
- bison
- flex
- gmp
- dejagnu)
- (package-native-inputs xbinutils)))
- (home-page &quot;https://zephyrproject.org&quot;)
- (synopsis &quot;binutils for zephyr RTOS&quot;))))</code></pre><p>The function <code>cross-binutils</code> returns a package which has been
- configured for the given gnu triplet. We simply inherit that package
- and replace the source.
- The zephyr build system expects the binutils to be prefixed with
- <code>arm-zephyr-eabi-</code> which is accomplished by adding another flag to the
- <code>#:configure-flags</code> argument.</p><p>We can test our package definition using the <code>-L</code> flag with <code>guix build</code>
- to add our packages.</p><pre><code>guix build -L guix-zephyr zephyr-binutils
- /gnu/store/a947nb4rb2vymz2gaqnafgm1bsq4ipqp-zephyr-binutils-2.38</code></pre><p>This directory contains the results of <code>make install</code>.</p><h2>GCC sans libc</h2><p>This one is a bit more involved. Don’t be afraid!
- This version of GCC wants ISL version 0.15. It’s easy enough
- to make that happen. Inherit the current version of ISL and swap
- out the source and update the version. For most packages the build process doesn’t
- change that much between versions.</p><pre><code>(define-public isl-0.15
- (package
- (inherit isl)
- (version &quot;0.15&quot;)
- (source (origin
- (method url-fetch)
- (uri (list (string-append &quot;mirror://sourceforge/libisl/isl-&quot;
- version &quot;.tar.gz&quot;)))
- (sha256
- (base32
- &quot;11vrpznpdh7w8jp4wm4i8zqhzq2h7nix71xfdddp8xnzhz26gyq2&quot;))))))</code></pre><p>Like the binutils, there is a function for creating cross-gcc packages. This one
- accepts keywords specifying which binutils and libc to use. If libc isn’t
- given (like here), gcc is configured with many options disabled to facilitate
- being built without libc. Therefore we need to add the extra options we want (I
- got them from the SDK configuration scripts on the <a href="https://github.com/zephyrproject-rtos/sdk-ng">sdk
- github</a> as well as the commits to
- use for each of the tools. ).</p><pre><code>(define-public gcc-arm-zephyr-eabi-12
- (let ((xgcc (cross-gcc &quot;arm-zephyr-eabi&quot;
- #:xbinutils zephyr-binutils)))
- (package
- (inherit xgcc)
- (version &quot;12.1.0&quot;)
- (source (origin (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/gcc&quot;)
- (commit &quot;0218469df050c33479a1d5be3e5239ac0eb351bf&quot;)))
- (file-name (git-file-name (package-name xgcc) version))
- (sha256
- (base32 &quot;1s409qmidlvzaw1ns6jaanigh3azcxisjplzwn7j2n3s33b76zjk&quot;))
- (patches
- (search-patches &quot;gcc-12-cross-environment-variables.patch&quot;
- &quot;gcc-cross-gxx-include-dir.patch&quot;))))
- (native-inputs
- (modify-inputs (package-native-inputs xgcc)
- ;; Get rid of stock ISL
- (delete &quot;isl&quot;)
- ;; Add additional dependencies that xgcc doesn't have
- ;; including our special ISL
- (prepend flex
- perl
- python-3
- gmp
- isl-0.15
- texinfo
- python
- mpc
- mpfr
- zlib)))
- (arguments
- (substitute-keyword-arguments (package-arguments xgcc)
- ((#:phases phases)
- `(modify-phases ,phases
- (add-after 'unpack 'fix-genmultilib
- (lambda _
- (substitute* &quot;gcc/genmultilib&quot;
- ((&quot;#!/bin/sh&quot;) (string-append &quot;#!&quot; (which &quot;sh&quot;))))
- #t))
- (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH
- (lambda* (#:key inputs #:allow-other-keys)
- (let ((gcc (assoc-ref inputs &quot;gcc&quot;)))
- ;; Remove the default compiler from CPLUS_INCLUDE_PATH to
- ;; prevent header conflict with the GCC from native-inputs.
- (setenv &quot;CPLUS_INCLUDE_PATH&quot;
- (string-join
- (delete (string-append gcc &quot;/include/c++&quot;)
- (string-split (getenv &quot;CPLUS_INCLUDE_PATH&quot;)
- #\:))
- &quot;:&quot;))
- (format #t
- &quot;environment variable `CPLUS_INCLUDE_PATH' changed to ~a~%&quot;
- (getenv &quot;CPLUS_INCLUDE_PATH&quot;))
- #t)))))
- ((#:configure-flags flags)
- ;; The configure flags are largely identical to the flags used by the
- ;; &quot;GCC ARM embedded&quot; project.
- `(append (list &quot;--enable-multilib&quot;
- &quot;--with-newlib&quot;
- &quot;--with-multilib-list=rmprofile&quot;
- &quot;--with-host-libstdcxx=-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm&quot;
- &quot;--enable-plugins&quot;
- &quot;--disable-decimal-float&quot;
- &quot;--disable-libffi&quot;
- &quot;--disable-libgomp&quot;
- &quot;--disable-libmudflap&quot;
- &quot;--disable-libquadmath&quot;
- &quot;--disable-libssp&quot;
- &quot;--disable-libstdcxx-pch&quot;
- &quot;--disable-nls&quot;
- &quot;--disable-shared&quot;
- &quot;--disable-threads&quot;
- &quot;--disable-tls&quot;
- &quot;--with-gnu-ld&quot;
- &quot;--with-gnu-as&quot;
- &quot;--enable-initfini-array&quot;)
- (delete &quot;--disable-multilib&quot; ,flags)))))
- (native-search-paths
- (list (search-path-specification
- (variable &quot;CROSS_C_INCLUDE_PATH&quot;)
- (files '(&quot;arm-zephyr-eabi/include&quot;)))
- (search-path-specification
- (variable &quot;CROSS_CPLUS_INCLUDE_PATH&quot;)
- (files '(&quot;arm-zephyr-eabi/include&quot;
- &quot;arm-zephyr-eabi/c++&quot;
- &quot;arm-zephyr-eabi/c++/arm-zephyr-eabi&quot;)))
- (search-path-specification
- (variable &quot;CROSS_LIBRARY_PATH&quot;)
- (files '(&quot;arm-zephyr-eabi/lib&quot;)))))
- (home-page &quot;https://zephyrproject.org&quot;)
- (synopsis &quot;GCC for zephyr RTOS&quot;))))</code></pre><p>This GCC can be built like so.</p><pre><code>guix build -L guix-zephyr gcc-cross-sans-libc-arm-zephyr-eabi
- /gnu/store/qmp8bzmwwimw0r6fh165hgfhkxkxilpj-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0-lib
- /gnu/store/38rli0rbn7ksmym3wq99cr4p2cjdz4a7-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0</code></pre><p>Great! We now have our stage-1 compiler.</p><h2>Newlib(-nano)</h2><p>The newlib package is quite straight forward (relatively).
- It is mostly adding in the relevent configuration flags and patching
- the files the <code>patch-shebangs</code> phase missed.</p><pre><code> (define-public zephyr-newlib
- (package
- (name &quot;zephyr-newlib&quot;)
- (version &quot;3.3&quot;)
- (source (origin
- (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/newlib-cygwin&quot;)
- (commit &quot;4e150303bcc1e44f4d90f3489a4417433980d5ff&quot;)))
- (sha256
- (base32 &quot;08qwjpj5jhpc3p7a5mbl7n6z7rav5yqlydqanm6nny42qpa8kxij&quot;))))
- (build-system gnu-build-system)
- (arguments
- `(#:out-of-source? #t
- #:configure-flags '(&quot;--target=arm-zephyr-eabi&quot;
- &quot;--enable-newlib-io-long-long&quot;
- &quot;--enable-newlib-io-float&quot;
- &quot;--enable-newlib-io-c99-formats&quot;
- &quot;--enable-newlib-retargetable-locking&quot;
- &quot;--enable-newlib-lite-exit&quot;
- &quot;--enable-newlib-multithread&quot;
- &quot;--enable-newlib-register-fini&quot;
- &quot;--enable-newlib-extra-sections&quot;
- &quot;--disable-newlib-wide-orient&quot;
- &quot;--disable-newlib-fseek-optimization&quot;
- &quot;--disable-newlib-supplied-syscalls&quot;
- &quot;--disable-newlib-target-optspace&quot;
- &quot;--disable-nls&quot;)
- #:phases
- (modify-phases %standard-phases
- (add-after 'unpack 'fix-references-to-/bin/sh
- (lambda _
- (substitute* '(&quot;libgloss/arm/cpu-init/Makefile.in&quot;
- &quot;libgloss/arm/Makefile.in&quot;
- &quot;libgloss/libnosys/Makefile.in&quot;
- &quot;libgloss/Makefile.in&quot;)
- ((&quot;/bin/sh&quot;) (which &quot;sh&quot;)))
- #t)))))
- (native-inputs
- `((&quot;xbinutils&quot; ,zephyr-binutils)
- (&quot;xgcc&quot; ,gcc-arm-zephyr-eabi-12)
- (&quot;texinfo&quot; ,texinfo)))
- (home-page &quot;https://www.sourceware.org/newlib/&quot;)
- (synopsis &quot;C library for use on embedded systems&quot;)
- (description &quot;Newlib is a C library intended for use on embedded
- systems. It is a conglomeration of several library parts that are easily
- usable on embedded products.&quot;)
- (license (license:non-copyleft
- &quot;https://www.sourceware.org/newlib/COPYING.NEWLIB&quot;))))</code></pre><p>And the build.</p><pre><code>guix build -L guix-zephyr zephyr-newlib
- /gnu/store/4lx37gga1jv3ckykrxsfgwy9slaamln4-zephyr-newlib-3.3</code></pre><h2>Complete toolchain</h2><p>Note that the toolchain is <em>Mostly</em> complete. libstdc++ does not build because
- `arm-zephyr-eabi` is not `arm-none-eabi` so a dynamic link check is
- performed/failed. I cannot figure out how crosstool-ng handles this.</p><p>Anyway, now that we’ve got the individual tools it’s time to create
- our complete toolchain. For this we need to do some package transformations.
- Because these transformations are must be done for every combination of
- binutils/gcc/newlib, it is best to create a function which we can reuse for
- every version of the SDK.</p><pre><code>(define (arm-zephyr-eabi-toolchain xgcc newlib version)
- &quot;Produce a cross-compiler zephyr toolchain package with the compiler XGCC and the C
- library variant NEWLIB.&quot;
- (let ((newlib-with-xgcc (package (inherit newlib)
- (native-inputs
- (alist-replace &quot;xgcc&quot; (list xgcc)
- (package-native-inputs newlib))))))
- (package
- (name (string-append &quot;arm-zephyr-eabi&quot;
- (if (string=? (package-name newlib-with-xgcc)
- &quot;newlib-nano&quot;)
- &quot;-nano&quot; &quot;&quot;)
- &quot;-toolchain&quot;))
- (version version)
- (source #f)
- (build-system trivial-build-system)
- (arguments
- '(#:modules ((guix build union)
- (guix build utils))
- #:builder
- (begin
- (use-modules (ice-9 match)
- (guix build union)
- (guix build utils))
- (let ((out (assoc-ref %outputs &quot;out&quot;)))
- (mkdir-p out)
- (match %build-inputs
- (((names . directories) ...)
- (union-build (string-append out &quot;/arm-zephyr-eabi&quot;)
- directories)
- #t))))))
- (inputs
- `((&quot;binutils&quot; ,zephyr-binutils)
- (&quot;gcc&quot; ,xgcc)
- (&quot;newlib&quot; ,newlib-with-xgcc)))
- (synopsis &quot;Complete GCC tool chain for ARM zephyrRTOS development&quot;)
- (description &quot;This package provides a complete GCC tool chain for ARM
- bare metal development with zephyr rtos. This includes the GCC arm-zephyr-eabi cross compiler
- and newlib (or newlib-nano) as the C library. The supported programming
- language is C.&quot;)
- (home-page (package-home-page xgcc))
- (license (package-license xgcc)))))</code></pre><p>This function creates a special package which consists of the toolchain in a special directory hierarchy, i.e <code>arm-zephyr-eabi/</code>.
- Our complete toolchain definition looks like this.</p><pre><code>(define-public arm-zephyr-eabi-toolchain-0.15.0
- (arm-zephyr-eabi-toolchain
- gcc-arm-zephyr-eabi-12
- zephyr-newlib
- &quot;0.15.0&quot;))</code></pre><p>To build:</p><pre><code>guix build -L guix-zephyr arm-zephyr-eabi-toolchain
- /gnu/store/9jnanr27v6na5qq3dlgljraysn8r1sad-arm-zephyr-eabi-toolchain-0.15.0</code></pre><h1>Integrating with Zephyr Build System</h1><p>Zephyr uses CMake as it’s build system. It contains numerous CMake files in both the so-called <code>ZEPHYR_BASE</code>,
- the zephyr source code repository, as well as a handful in the SDK which help select the correct toolchain
- for a given board.</p><p>There are standard locations the build system will look for the SDK. We are not
- using any of them. Our SDK lives in the store, immutable forever. According to
- <a href="https://docs.zephyrproject.org/latest/develop/west/without-west.html">this
- webpage</a>,
- the variable <code>ZEPHYR_SDK_INSTALL_DIR</code> needs to point to our custom spot.</p><p>We also need to grab the cmake files from the <a href="https://github.com/zephyrproject-rtos/sdk-ng">repository</a> and create a file <code>sdk_version</code> which
- contains the version string <code>ZEPHYR_BASE</code> uses to find a compatible SDK.</p><p>Along with the SDK proper we need to include a number of python packages required by the build system.</p><pre><code> (define-public zephyr-sdk
- (package
- (name &quot;zephyr-sdk&quot;)
- (version &quot;0.15.0&quot;)
- (home-page &quot;https://zephyrproject.org&quot;)
- (source (origin (method git-fetch)
- (uri (git-reference
- (url &quot;https://github.com/zephyrproject-rtos/sdk-ng&quot;)
- (commit &quot;v0.15.0&quot;)))
- (file-name (git-file-name name version))
- (sha256 (base32 &quot;04gsvh20y820dkv5lrwppbj7w3wdqvd8hcanm8hl4wi907lwlmwi&quot;))))
- (build-system trivial-build-system)
- (arguments
- `(#:modules ((guix build union)
- (guix build utils))
- #:builder
- (begin
- (use-modules (guix build union)
- (ice-9 match)
- (guix build utils))
- (let* ((out (assoc-ref %outputs &quot;out&quot;))
- (cmake-scripts (string-append (assoc-ref %build-inputs &quot;source&quot;)
- &quot;/cmake&quot;))
- (sdk-out (string-append out &quot;/zephyr-sdk-0.15.0&quot;)))
- (mkdir-p out)
- (match (assoc-remove! %build-inputs &quot;source&quot;)
- (((names . directories) ...)
- (union-build sdk-out directories)))
- (copy-recursively cmake-scripts
- (string-append sdk-out &quot;/cmake&quot;))
- (with-directory-excursion sdk-out
- (call-with-output-file &quot;sdk_version&quot;
- (lambda (p)
- (format p &quot;0.15.0&quot;)))
- #t)))))
- (propagated-inputs
- (list
- arm-zephyr-eabi-toolchain-0.15.0
- zephyr-binutils
- dtc))
- (native-search-paths
- (list (search-path-specification
- (variable &quot;ZEPHYR_SDK_INSTALL_DIR&quot;)
- (files '(&quot;&quot;)))))
- (synopsis &quot;SDK for zephyrRTOS&quot;)
- (description &quot;zephyr-sdk contains bundles a complete gcc toolchain as well
- as host tools like dtc, openocd, qemu, and required python packages.&quot;)
- (license license:apsl2)))</code></pre><h2>Testing</h2><p>In order to test we will need an environment with the SDK installed.
- We can take advantage of <code>guix shell</code> to avoid installing test packages into
- our home environment. This way, if it causes problems, we can just exit the shell
- and try again.</p><pre><code>guix shell -L guix-zephyr zephyr-sdk cmake ninja git</code></pre><p><code>ZEPHYR_BASE</code> can be cloned into a temporary workspace to test our toolchain
- functionality (For now. Eventually we will need to create a package for
- <code>zephyr-base</code> that our guix zephyr-build-system can use).</p><pre><code>mkdir /tmp/zephyr-project
- cd /tmp/zephyr-project
- git clone https://github.com/zephyrproject-rtos/zephyr
- export ZEPHYR_BASE=/tmp/zephyr-project/zephyr</code></pre><p>In order to build for the test board (k64f in this case) we need to get a hold
- of the vendor Hardware Abstraction Layers and CMSIS (These will also need to
- become guix packages to allow the build system to compose modules).</p><pre><code>git clone https://github.com/zephyrproject-rtos/hal_nxp &amp;&amp;
- git clone https://github.com/zephyrproject-rtos/cmsis</code></pre><p>To inform the build system about this module we pass it in with <code>-DZEPHYR_MODULES=</code> which is
- a semicolon separated list of paths containing a module.yml file.</p><p>To build the hello world sample we use the following incantation.</p><pre><code>cmake -Bbuild $ZEPHYR_BASE/samples/hello_world \
- -GNinja \
- -DBOARD=frdm_k64f \
- -DBUILD_VERSION=3.1.0 \
- -DZEPHYR_MODULES=&quot;/tmp/zephyr-project/hal_nxp;/tmp/zephyr-project/cmsis&quot; \
- &amp;&amp; ninja -Cbuild</code></pre><p>If everything is set up correctly we will end up with a <code>./build</code>
- directory with all our build artifacts. The SDK is installed correctly!</p></content></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" /><content type="html"><p>So I have wanted to run <a href="https://nextcloud.com/">nextcloud</a> for a while now. In my humble opinion, guix
- system makes maintaining websites super easy, so I would prefer to run nextcloud
- on guix system. Unfortunately, nextcloud will NOT be packaged in guix anytime
- soon for two reasons:</p><ol><li>Guix does not currently have a php build system or any php packages, though
- there is a 80% completed <a href="https://issues.guix.gnu.org/42338">work-in-progress issue.</a> So the php bits of nextcloud
- cannot be packaged properly.</li><li>Nextcloud has a lot of javascript dependencies, and javascript is <a href="https://dustycloud.org/blog/javascript-packaging-dystopia/">notoriously
- hard to package for guix.</a></li></ol><p>It seems like the easiest way to currently run nextcloud on guix system is by
- using the <a href="https://github.com/nextcloud/all-in-one">all in one docker image.</a> Please consider this a guide to set up
- running nextcloud on guix system via a linode, which currently costs me about $5
- per month.</p><p>Note, that while this is the easiest method to run nextcloud, apparently this
- all in one docker image has some security issues:</p><blockquote><p>The AIO image mounts the Docker socket, which is a security risk since it allows
- full access to other container as well as running any new container. It’s a bad
- idea and should be avoided.</p></blockquote><p>tl;dr Here are the 6 simple steps that you need to do:</p><ol><li><p>Set up a <a href="https://guix.gnu.org/en/cookbook/en/html_node/Running-Guix-on-a-Linode-Server.html#Running-Guix-on-a-Linode-Server">linode guix system server.</a> <code>info &quot;Guix Cookbook&quot; RET i linode RET</code>.</p></li><li><p>Buy a domain name. I use <a href="https://hover.com">hover.com</a>.</p></li><li><p>Point your domain name at your linode IP address.</p></li><li><p>Set up a basic nginx static website without encryption. This means that you
- don’t want to define <code>(service certbot-service-type)</code>.</p><pre><code>sudo mkdir -p /srv/www/html/yourdomainname.com
-
- # the command I did was this:
- sudo mkdir -p /srv/www/html/the-nx.com
-
- sudo chgrp -R users /srv
- sudo chmod -R g+rwx /srv</code></pre><p>Inside your newly created directory (<em>srv/www/html/yourdomainname.com</em>), put
- a simple HTML file and call it “index.html”. You could use this:</p><pre><code>&lt;!doctype html&gt;
- &lt;html class=&quot;no-js&quot; lang=&quot;&quot;&gt;
- &lt;head&gt;
- &lt;meta charset=&quot;utf-8&quot;&gt;
- &lt;meta http-equiv=&quot;x-ua-compatible&quot; content=&quot;ie=edge&quot;&gt;
- &lt;title&gt;the nx&lt;/title&gt;
- &lt;meta name=&quot;description&quot; content=&quot;&quot;&gt;
- &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
- &lt;link rel=&quot;apple-touch-icon&quot; href=&quot;/apple-touch-icon.png&quot;&gt;
-
- &lt;/head&gt;
- &lt;body&gt;
- &lt;!--[if lt IE 8]&gt;
- &lt;p class=&quot;browserupgrade&quot;&gt;
- You are using an &lt;strong&gt;outdated&lt;/strong&gt; browser. Please
- &lt;a href=&quot;http://browsehappy.com/&quot;&gt;upgrade your browser&lt;/a&gt; to improve
- your experience.
- &lt;/p&gt;
- &lt;![endif]--&gt;
-
- &lt;p&gt;Hello!&lt;/p&gt;
- &lt;/body&gt;
- &lt;/html&gt;</code></pre><p>Now set up a basic nginx configuration for a static website without
- encryption. It will end up looking something like:</p><pre><code>(service nginx-service-type
- (nginx-configuration
- (server-blocks
- (list
- (nginx-server-configuration
- (server-name '(&quot;the-nx.com&quot;))
- (listen (list &quot;80&quot; &quot;[::]:80&quot;))
- (root &quot;/srv/www/html/the-nx.com&quot;))))))</code></pre><p>Now you need to reconfigure so that the <code>nginx</code> user is created:</p><p><code>sudo guix system reconfigure config.scm</code></p><p>Now, nginx is running, but you will probably need to give nginx access to
- read the files in your /srv directory.</p><pre><code>sudo chown -R nginx /srv
- sudo chmod -R u-rwx /srv</code></pre><p>Open up a web browser and go to <a href="http://yourdomainname.com">http://yourdomainname.com</a> and check to see
- that you see a basic website.</p></li><li><p>Now you need to turn your basic static website, into a site that has https
- support. Now you need to edit your nginx config and add in a certbot config:</p><p>Before your <code>(operating-system ...)</code> declartion, define this bit of code:</p><pre><code>(define %nginx-deploy-hook
- (program-file
- &quot;nginx-deploy-hook&quot;
- #~(let ((pid (call-with-input-file &quot;/var/run/nginx/pid&quot; read)))
- (kill pid SIGHUP))))</code></pre><p>Also make sure that you add in a <code>certbot</code> service and a modified <code>nginx</code>
- service that look like this:</p><pre><code>(service certbot-service-type
- (certbot-configuration
- (email &quot;mysubscriptions@member.fsf.org&quot;)
- (webroot &quot;/srv/www/&quot;)
- (certificates
- (list
- (certificate-configuration
- (name &quot;the-nx.com&quot;)
- (domains '(&quot;the-nx.com&quot; &quot;www.the-nx.com&quot;))
- (deploy-hook %nginx-deploy-hook))))))
-
- (service nginx-service-type
- (nginx-configuration
- (server-blocks
- (list
- (nginx-server-configuration
- (server-name '(&quot;the-nx.com&quot;))
- (listen (list &quot;80&quot;
- &quot;443 ssl http2&quot;
- &quot;[::]:80&quot;
- &quot;[::80]:443 ssl http2&quot;))
- (root &quot;/srv/www/html/the-nx.com&quot;)
- (ssl-certificate &quot;/etc/letsencrypt/live/the-nx.com/fullchain.pem&quot;)
- (ssl-certificate-key &quot;/etc/letsencrypt/live/the-nx.com/privkey.pem&quot;)
- (locations
- (list
- (nginx-location-configuration ;; for certbot
- (uri &quot;/.well-known&quot;)
- (body (list &quot;root /srv/www;&quot;))))))))))</code></pre><p>Now we will have to reconfigure again to set up certbot:</p><pre><code>sudo guix system reconfigure config.scm
-
- # tell certbot to set up our certificates
- sudo /var/lib/certbot/renew-certificates</code></pre><p>Now you should be able to go to <a href="https://yourdomainname.com">https://yourdomainname.com</a> and see your site
- in glorious encrypted mode!</p></li><li><p>Modify your guix config based on my <a href="https://notabug.org/jbranso/linode-guix-system-configuration/src/master/the-nx.com-current-config.scm">the-nx.com-current-config.scm</a>.
- You will need to enable these services <code>(dbus-service)</code>, <code>(service docker-service-type)</code>, <code>(elogind service)</code>, <code>(service certbot-service-type)</code>,
- and <code>(service nginx-service-type)</code>.</p></li></ol><p>I just ran this command, and my local nextcloud just started working.</p><pre><code>sudo docker run \
- --sig-proxy=false \
- --name nextcloud-aio-mastercontainer \
- --restart always \
- --publish 80:80 \
- --publish 8080:8080 \
- --publish 8443:8443 \
- --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
- --volume /var/run/docker.sock:/var/run/docker.sock:ro \
- nextcloud/all-in-one:latest</code></pre><p>The following is the same quick guide as above, but has more details:</p><p>I decided to create a new linode image following the linode cookbook guide, and
- I noticed a tiny error in the guide:</p><p><code>sudo apt-get install gpg</code> failed. It worked after I ran <code>sudo apt-get update</code>.</p><p>Also the basic config example needs to migrate to the new &lt;swap-space&gt; record.
- It gave me this warning message:</p><p>/root/config.scm:11:0: warning: List elements of the field ’swap-devices’ should
- now use the &lt;swap-space&gt; record, as the old method is deprecated. See “(guix)
- operating-system Reference” for more details.</p><p>The cookbook guide also should probably mention that you may need to login to
- the server for the first time using linode’s weblish, and set up the root passwd
- with <code>passwd</code>. Then set up your user password with <code>passwd &lt;username&gt;</code>.</p><p>Now that we have a basic site set up, let’s set up certbot and the nginx services:</p><pre><code>(service certbot-service-type
- (certbot-configuration
- (email &quot;mysubscriptions@member.fsf.org&quot;)
- (webroot &quot;/srv/www/&quot;)
- (certificates
- (list
- (certificate-configuration
- (name &quot;the-nx.com&quot;)
- (domains '(&quot;the-nx.com&quot; &quot;www.the-nx.com&quot;))
- (deploy-hook %nginx-deploy-hook))))))
- (nginx-configuration
- (server-blocks
- (list
- (nginx-server-configuration
- (server-name '(&quot;the-nx.com&quot;))
- (listen (list &quot;80&quot;
- &quot;443 ssl http2&quot;
- ;;&quot;[::]:80&quot;
- ;;&quot;[::80]:443 ssl http2&quot;
- ))
- (root &quot;/srv/www/html/the-nx.com&quot;)
- (ssl-certificate &quot;/etc/letsencrypt/live/the-nx.com/fullchain.pem&quot;)
- (ssl-certificate-key &quot;/etc/letsencrypt/live/the-nx.com/privkey.pem&quot;)
- (locations
- (list
- (nginx-location-configuration ;; for certbot
- (uri &quot;/.well-known&quot;)
- (body (list &quot;root /srv/www;&quot;)))))))))</code></pre><p>Now let’s reconfigure and get a certbot certificate. <code>ssh</code> into the-nx.com and
- run these commands:</p><pre><code>sudo guix system reconfigure the-nx.com-current-config.scm
- # tell certbot to set up our certificates
- sudo /var/lib/certbot/renew-certificates</code></pre><p>So now my server has a valid certificate. It is time change the nginx
- configuration to proxy incoming requests to the docker all in one image.</p><p>Ok, maybe I can use sexpressions to tell nginx to redirect all incoming traffic
- to <code>the-nx.com</code> to the docker nextcloud image:</p><pre><code>(nginx-location-configuration
- (uri &quot;/&quot;)
- (body
- (list
- &quot;proxy_pass http://127.0.0.1:9000;\n&quot;
- &quot;proxy_set_header X-Real-IP $remote_addr;\n&quot;
- &quot;proxy_set_header Host $host;\n&quot;
- &quot;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n&quot;
- &quot;client_max_body_size 0;\n&quot;
- &quot;# Websocket\n&quot;
- &quot;proxy_http_version 1.1;\n&quot;
- &quot;proxy_set_header Upgrade $http_upgrade;\n&quot;)))</code></pre><p>I am going to deploy this image, and take a look at the generated nginx
- configuration file. I ran this command on my T400 laptop:</p><p><code>guix deploy the-nx.com-current-config.scm</code></p><p>Well, that’s super annoying. I do not know which nginx.conf file is the right
- one:</p><pre><code>find /gnu/store -name '*nginx.conf'
- /gnu/store/7m1ygzqk6njn5mywqmhwbydbb2z4b9li-nginx.conf
- /gnu/store/0gcfj61q4943h94jdqq7i9y0a0v9jr9q-nginx.conf
- /gnu/store/4mzrp39w5i4v94kxf98gxc13ws79l88n-nginx.conf
- /gnu/store/0nia2iqfw63ziasibbgq321wr9b3152n-nginx.conf
- /gnu/store/pf8d0sj1yf9b2ndsbc61yj3h6rp4pck2-nginx.conf
- /gnu/store/9nra62v41wsk08xf3msw5a1z35gji2gx-nginx-1.23.2/share/nginx/conf/nginx.conf
- /gnu/store/4b1szfyn0snwzf3lm1snvaapk6diz3yq-nginx.conf
- /gnu/store/fv5rg3nf5999vyg6qvp4sbgjysnkn1fc-nginx.conf
- /gnu/store/vmjwj2zwblcz4wx2whsmxdfc7zxcgjh5-nginx.conf
- /gnu/store/n3m2lihq9cjm6mxdln57q5nrbjgz53s6-nginx.conf
- /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/nginx.conf</code></pre><p>I guess I will reboot, run <code>guix system delete-generations</code> and <code>guix gc</code>, and
- run the above command again:</p><pre><code>find /gnu/store -name '*nginx.conf'
- /gnu/store/7m1ygzqk6njn5mywqmhwbydbb2z4b9li-nginx.conf
- /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/nginx.conf</code></pre><p>Well that looks promising. Let's check out my nginx.conf file.</p><pre><code>cat /gnu/store/i2mzdhg8wlbxv7iza8y4qk5v0vmvp27q-nginx.conf
- user nginx nginx;
- pid /var/run/nginx/pid;
- error_log /var/log/nginx/error.log info;
- events { }
- http {
- client_body_temp_path /var/run/nginx/client_body_temp;
- proxy_temp_path /var/run/nginx/proxy_temp;
- fastcgi_temp_path /var/run/nginx/fastcgi_temp;
- uwsgi_temp_path /var/run/nginx/uwsgi_temp;
- scgi_temp_path /var/run/nginx/scgi_temp;
- access_log /var/log/nginx/access.log;
- include /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/mime.types;
- server {
- listen 443 ssl http2;
- server_name the-nx.com ;
- ssl_certificate /etc/letsencrypt/live/the-nx.com/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/the-nx.com/privkey.pem;
- root /srv/www/html/the-nx.com;
- index index.html ;
- server_tokens off;
- location /.well-known {
- root /srv/www;
- }
- location / {
- proxy_pass http://127.0.0.1:9000;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- client_max_body_size 0;
- # Websocket
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- }
- }
- server {
- listen 80;
- listen [::]:80;
- server_name the-nx.com www.the-nx.com ;
- root /srv/http;
- index index.html ;
- server_tokens off;
- location /.well-known {
- root /srv/www/;
- }
- location / {
- return 301 https://$host$request_uri;
- }
- }
- }</code></pre><p>The generated configuration seems pretty wonky, and I am suprised that nginx is
- still running, but it is still running. And I suppose that it should work.</p><p>I was able to get nextcloud to start with this command:</p><pre><code>sudo docker run --sig-proxy=false --name nextcloud-aio-mastercontainer \
- --restart always \
- --publish 8080:8080 \
- -e APACHE_PORT=9000 \
- --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
- --volume /var/run/docker.sock:/var/run/docker.sock:ro \
- nextcloud/all-in-one:latest</code></pre><p>So now I can login at the-nx.com:8080 and configure various stuff. Also I really
- need to set up a firewall. That’s probably a really good idea. Also what’s nice
- about this docker image is that it will start itself if you update the guix
- system server and reboot.</p><p>MORE BONUS CONTENT:</p><p>If you see this blog post, and you decide to set up your nextcloud on a guix
- system server, and if your nginx config doesn’t seem to be proxying requests to
- your docker container, then you may follow these steps to delete the docker
- image and start over:</p><p>This <a href="https://help.nextcloud.com/t/aio-this-site-can-t-provide-a-secure-connection/128478/5">page</a> has some good commands for deleting the docker image and starting
- over:</p><pre><code>sudo docker stop nextcloud-aio-mastercontainer &amp;&amp; \\
- sudo docker rm nextcloud-aio-mastercontainer &amp;&amp; \\
- sudo docker container prune -f &amp;&amp; \\
- sudo docker volume prune -f &amp;&amp; \\
- sudo docker pull nextcloud/all-in-one:latest</code></pre><p>Ok, so it looks like the nextcloud all in one documentation has a <a href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md">page</a> for
- understanding the reverse proxy.</p><p>It would also be nice to get my nextcloud image to sync my contacts. I probably just need to add in another nginx
- location line for that. That will be a project for another day.</p></content></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" /><content type="html"><p>So I have been running this to upgrade the pinephone for a while now:</p><pre><code># apk upgrade
- # apk update
- # apk upgrade
- # apk update</code></pre><p>Today, when I rebooted I got a message that said that my pinephone’s version was
- no longer supported. I should <a href="https://postmarketos.org/upgrade">upgrade</a>:</p><p>I figured that I will probably do this again, so I might as well write down the
- steps for how to do the upgrade.</p><p>Before I really get started in this, I want to get set up in the <a href="https://wiki.postmarketos.org/wiki/Matrix_and_IRC">matrix chat
- room.</a> I used the web based interface for the matrix chat. It had me create an
- online account, and verify my email address, then I could talk in the matrix
- channel. That was easy, moving onto the next step.</p><p>First install <code>postmarketos-release-upgrade</code> package:</p><pre><code># apk add postmarketos-release-upgrade</code></pre><p>Next I want to create a <a href="https://wiki.postmarketos.org/wiki/Backup_and_restore_your_data">backup</a>, of the pinephone incase the upgrade fails or
- breaks the phone and I have to install postmarketOS.</p><p>Ok, in the pinephone’s terminal, start the sshd daemon:</p><pre><code>sudo service sshd start</code></pre><p>So possibly the best way to upgrade your pinephone is to connect the phone to
- your laptop/desktop via a usb cord and enable <a href="https://wiki.postmarketos.org/wiki/USB_Internet#Linux">usb internet.</a></p><p>Apparently after you connect the phone to your host machine, you should be able
- to run:</p><pre><code>ssh user@172.16.42.1</code></pre><p>That didn’t work. And it is quickly looking to me like the usb internet upgrade
- option is NOT going to work. Or rather, it will work, but it will take me a lot
- of time to get it to work.</p><p>So instead of using the usb internet upgrade option, I will try connecting the
- pinephone to the internet via an ethernet cord (I personally disabled the wifi
- on the phone to try to save power). Then I will make a backup of the pinephone.</p><p>Ok, now that I have my phinephone connected to an ethernet port, I used my
- laptop to ssh into the pinephone.</p><p>I found my pinephone’s ip address via running this on the pinephone’s terminal:</p><pre><code>ip a</code></pre><p>Ok, so the looking at eth0: the pinephone’s ip address is:</p><p>SOME.IP.Address.04</p><p>So, I can now ssh into the phone via:</p><p><code>ssh user@SOME.IP.Address.04</code></p><p>Since I have ssh-agent set up, lets set up ssh key login:</p><pre><code>ssh-copy-id user@SOME.IP.ADDRESS.04</code></pre><p>Now let’s create a backup on my host comptuter (laptop):</p><pre><code>mkdir ~/postmarket-os-backup
- rsync -avz --exclude=.cache user@SOME.IP.ADDRESS.04:/home/user/ .
- fish: Unknown command: rsync
- fish:
- rsync --server --sender -vlogDtprze.iLsfxCIvu . /home/user/
- ^
- rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
- rsync error: error in rsync protocol data stream (code 12) at io.c(231) [Receiver=3.2.7]</code></pre><p>Well that seems like a weird problem. Let’s go join the fish irc channel.</p><p>Well the channel is here:</p><p><code>#fish</code> at irc.oftc.net</p><p>I can find out how to connect via going to oftc.net. They ever have a <a href="https://webchat.oftc.net/">webchat</a>.
- That makes it easy. Just put in a goofy nickname and you are in the chat room!</p><p>It took the fish people a while to respond, so I also asked in the <code>#guix</code>
- channel, while I was waiting. A guix user said that I should try this:</p><pre><code>guix shell --network -C coreutils rsync openssh-sans-x</code></pre><p>And then run my rsync command.</p><p>That didn’t work, but then the <code>#fish</code> people just asked me if I have rsync
- installed on my pinephone…I didn’t realize I needed it installed on both
- devices.</p><p>So let’s do that on the pinephone: <code>sudo apk add rsync</code>.</p><p>Let’s try this again. On my laptop I ran this:</p><pre><code>rsync -avz --exclude=.cache user@SOME.IP.ADDRESS.04:/home/user/ ~/postmarket-os-backup</code></pre><p>Ok that worked!</p><p>The <a href="https://wiki.postmarketos.org/wiki/Upgrade_to_a_newer_postmarketOS_release">postmarketOS wiki</a> recommends that I use tmux or screen to update the
- pinephone, in case the ssh connection breaks. Well I believe that I have tried
- updating the pinephone before using just an ssh connection, and the ssh
- connection dropped. I did not know if they phone was done updating or if it had
- just died. So I forcefully shut off the device, and it failed to boot. Fun
- times.</p><p>Well let’s go ask in the postmarketOS irc channel or <a href="https://wiki.postmarketos.org/wiki/Category:Community">matrix</a> and ask about using
- tmux or screen. How does it make sure that the ssh connection does not break? I
- can also check out the archlinux wiki. Also it seems as if tmux is more user
- friendly, so I will check out the <a href="https://wiki.archlinux.org/title/Tmux">tmux</a> page to learn more about it.</p><p>Well let’s go ahead and install tmux on my laptop: <code>guix install tmux</code>.</p><p>Let’s try to run an ssh connection on the pinephone via tmux. I think this
- is how you do it:</p><pre><code>tmux
- ssh user@&lt;IP address of the pinephone&gt;</code></pre><p>Well I asked in the postmarketOS irc channel why they reccommend using tmux in
- case the ssh connection drops, and this is the answer that I got:</p><blockquote><p>if you use tmux, you can just restore your tmux session if the ssh connection drops
- and the command will still be running in there</p><p>run tmux
- then if the connection drops
- tmux list-sessions
- and then
- tmux attach-session
- I think</p></blockquote><p>Then if the ssh connection gets dropped, I can open up a new terminal and do
- this <code>tmux attach</code>, and I will be right back where I was. This <a href="https://www.youtube.com/watch?v=JQ0yDCVu44E">video</a> explains
- that. That is pretty awesome!</p><p>Here <a href="https://mutelight.org/practical-tmux">are</a> <a href="https://blog.hawkhost.com/2010/06/28/tmux-the-terminal-multiplexer/">some</a> <a href="https://blog.hawkhost.com/2010/07/02/tmux-%E2%80%93-the-terminal-multiplexer-part-2">tmux</a> <a href="https://man.archlinux.org/man/tmux.1">resources.</a></p><p>Next, I ran the following to update the pinephone:</p><pre><code>tmux
- ssh user@&lt;my Pinephone IP address&gt;
- postmarketos-release-upgrade</code></pre><p>Since, my phinephone had an ethernet connection, the upgrade process was over
- inside 5 minutes, and the phone rebooted itself. Nice work postmarketos
- developers!</p></content></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" /><content type="html"><p>Edit: Feb 12: The below firewall does NOT work. I currently do NOT use a
- firewall on my servers.</p><p>So my guix system servers have been running without a firewall. I have decided
- to actually fix that. Unfortunately, OpenBSD’s pf does not work on linux. It
- seems like the best packaged firewall for GNU Guix System is currently provided
- by the netfilter service. Luckily Guix’s default server provides a good basic
- configuration for enabling ssh access to the machine. That configuration looks
- like this:</p><pre><code>table inet filter {
- chain input {
- type filter hook input priority 0; policy drop;
- # early drop of invalid connections
- ct state invalid drop
- # allow established/related connections
- ct state { established, related } accept
- # allow from loopback
- iifname lo accept
- # allow icmp
- ip protocol icmp accept
- ip6 nexthdr icmpv6 accept
- # allow ssh
- tcp dport ssh accept
- # reject everything else
- reject with icmpx type port-unreachable
- }
- chain forward {
- type filter hook forward priority 0; policy drop;
- }
- chain output {
- type filter hook output priority 0; policy accept;
- }
- }</code></pre><p>So it looks like I just need to add in policies just after the <code>#allow ssh</code>
- line.</p><p>It seems like the easiest way to test this service out, is to first, <code>guix install nft</code>, then put your configuration into a file. Then load in those
- firewall rules via <code>sudo nft -f nftables.conf</code>. If those rules end up breaking
- things, you can revert the firewall to allow everything via <code>sudo nft flush ruleset</code>. You can also list the current ruleset via <code>sudo nft list ruleset</code>.
- You can also check the syntax in <code>nftables.conf</code> via <code>sudo nft -cf nftable.conf</code>.</p><p>Well I had a firewall working fairly well. I tested the firewall rules via
- <code>sudo nft -f nftables-lamora.conf</code>, and it worked really well. But this scheme
- code seemed to break everything on the server. Now, I can’t login to lamora and
- the websites it hosts are not working.</p><pre><code>(service nftables-service-type
- (nftables-configuration
- (ruleset
- (mixed-text-file &quot;nftables.conf&quot;
- &quot;./nftables-lamora.conf&quot;))))</code></pre><p>I reached out to linode support, and I am able to boot the machine in a rescue
- image, which is pretty awesome. From there I might be able to mount the
- <code>/dev/sda</code> drive such that <code>/gnu/store</code> is set up properly. But I think that is
- pretty much beyond me. Too much work to get correct. So instead, I shall start
- from scratch I suppose. :(</p><p>What if I had just run,</p><pre><code>mount /dev/sda /mnt
- chroot /mnt
- sudo guix system roll-back</code></pre><p>That might have worked. But it also might not have and it might have just taken me
- longer too.</p><p>Looks like I have a small basic guix image lying around that I can tell linode
- to use. Let’s try that.</p><p>Well that caused a kernel panic. That didn’t work. Probably because I told
- linode to set the root password, and linode doesn’t know how to mess with guix
- system?</p><p>So I whiped my linode server, and started over. And it looks like
- I need to modify the current cookbook entry about running guix system on linode via
- adding in</p><p><code>sudo apt-get update</code>, then <code>sudo apt-get install gpg</code>.</p><p>Here are some of the commands that I used to set up my new linode server. It's on the
- same IP address. It's currently hosting gnucode.me.</p><pre><code>wget https://notabug.org/jbranso/linode-guix-system-configuration/raw/master/gnucode.me-initial-config.scm
- mount /dev/sdc /mnt
- sudo guix system reconfigure locke-lamora-initial-config.scm
- guix install git
- mkdir -p ~/prog/gnu/guix/guix-config/
- cd ~/prog/gnu/guix/guix-config/
- git clone https://notabug.org/jbranso/linode-guix-system-configuration
- cd ../
- git clone https://git.sr.ht/~whereiseveryone/guixrus
- sudo mkdir -p /srv/www/html</code></pre><p>Now I need to git clone my various static websites on the server.</p><pre><code>cd /srv/www/html
- sudo git clone https://notabug.org/jbranso/gnucode.me.git
- sudo git clone https://notabug.org/jbranso/propernaming.git
- sudo git clone https://notabug.org/jbranso/gnu-hurd.com.git
- sudo mv propernaming propernaming.org</code></pre><p>So I believe that I need to chmod the files in /srv/www/html, so that nginx can
- actually serve them. Unfortunately, I cannot do a <code>sudo chown -R nginx /srv</code>,
- because my current guix system does not have an nginx user yet. But I believe
- that I can still reconfigure the system, even if nginx will not be able to serve
- the html files. After I have reconfigured, then I should be able chown the owner
- of /srv to nginx. In the end I actually just did a <code>cd /srv; sudo chmod -R o+r *</code> and just made every file readable by everyone. That sort of violates the
- principle of least privledge, oh well.</p><p>Now that I have made some modifications to my gnucode.me-current-config.scm that
- comments out various certificate files that are not there yet, I can attempt to
- reconfigure on the server:</p><pre><code>cd prog/gnu/guix/guix-config/linode-guix-system-configuration/
- sudo guix system reconfigure gnucode.me-current-config.scm
- guix system: error: aborting reconfiguration because commit
- 9fe5b490df83ff32e2e0a604bf636eca48b9e240 of channel 'guix' is not a descendant
- of 900d33527c9286a811f064d4bb8f4a9b18d1db0b</code></pre><p>Well let’s try this updating everything. And I believe that you need to do a
- guix pull as root at least once.</p><pre><code>su
- guix pull;
- exit;
- guix pull;</code></pre><p>Oh yeah, I also need to power down my linode, delete the debian partition, and
- resize the guix partition to full size.</p><p>Now I believe that I cannot reconfigure my server with the current
- <code>gnucode.me-current-config.scm</code>, because nginx will fail to start because the
- letsencrypt scripts are not there yet. So I need to modify the nginx bits before
- I can start the service. I also decided to set up <code>guix deploy</code> on my gnucode.me
- machine, so that reconfiguring the remote server is faster.</p><p>Ok, so I have my current-config for gnucode.me deployed. Geez, guix deploy is
- sooo super fast! And all you need to do is to set up ssh-agent and customize a
- deployment list. I set up ssh-agent via my <code>.bash_profile</code></p><pre><code>cat .bash_profile | grep eval -A 1
- if [[ -z $DISPLAY ]] &amp;&amp; [[ $(tty) = /dev/tty6 ]]; then
- eval `ssh-agent -s`
- ssh-add
- exec dbus-run-session sway
- fi</code></pre><p>Now all you need to do is customize this:</p><pre><code>(list (machine
- (operating-system %system)
- (environment managed-host-environment-type)
- (configuration (machine-ssh-configuration
- (host-name &quot;45.56.66.20&quot;)
- (system &quot;x86_64-linux&quot;)
- (user &quot;joshua&quot;)
- (identity &quot;~/.ssh/id_rsa&quot;)
- (host-key &quot;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJgL0hBTWmCVGGvNJYa+YS+fEXs89v0GbdkQ+M+LdZlf root@(none)&quot;)
- (port 63355)))))</code></pre><p>The port is the ssh port. And the ssh-ed25519 is found on your remote server’s
- <code>etc/ssh/ssh_host_ed25519_key.pub</code> file.</p><p>Now nginx serves my websites via http. Let’s get https working.</p><pre><code>sudo /var/lib/certbot/renew-certificates</code></pre><p>Alright, now I can set up my config.scm to allow nginx to serve web traffic via https.</p><p>Well, can I get a nftables service running now?</p><p>At first it seemed that <code>(service nftables-service-type)</code> is apparently good
- enough to be a decent firewall for my server. Then very quickly I realized that
- it was a terrible firewall for a server, because it blocked all http and https
- traffic.</p><p>It looks like the arch linux wiki has a decent configuration example for a server:</p><p>https://wiki.archlinux.org/title/Nftables#Examples</p><p>So I just took the example nftables configuration for a server and used that.
- The configuration file is here:</p><p>https://notabug.org/jbranso/linode-guix-system-configuration/src/master/nftables.scm</p><p>Let me know if you see that I did something silly in it, because I probably did.</p><p>Bonus paragraph! It took me about 2-4 hours to re-set up my server just the way
- it was before, except I haven't set up email yet. If you crashed your server
- lost your backups, how long would it take you to set up you server, just as it
- was? 2-4 hours is longer than I expected, but I think guix's declarative
- approach certainly is pretty awesome!</p></content></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" /><content type="html"><p>EDIT 02-24-2023: Through this whole process, I have used this guide to set up email.
- If you are going to try to set up your own email service, do check it out:
- <a href="https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/">https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/</a></p><p>I was recently encouraged by the delightfully friendly raghavgururajan to try to
- merge my opensmtpd service project into guixrus, which is a small community
- actively working to upstream packages and services into guix proper. I figured,
- why not? Sounds like fun. The following post will describe my developmental
- workflow, which is probably pretty poor…</p><p>tl;dr</p><p>Soonish, I will clean up the code for a proper ~opensmtpd-service-type~ with
- ~opensmtpd-records~ for guix system. It may take 6 months to get it in a clean
- state. Until it is merged, you may find it here:</p><p><a href="https://git.sr.ht/~whereiseveryone/guixrus/commit/255875f7d86e92bb64006a59be26c64430c0c046">https://git.sr.ht/~whereiseveryone/guixrus/commit/255875f7d86e92bb64006a59be26c64430c0c046</a></p><p>The current documentation is here:</p><p><a href="https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records-documentation.txt">https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records-documentation.txt</a></p><p>My server's config is here:</p><p><a href="https://notabug.org/jbranso/linode-guix-system-configuration/src/master/linode-locke-lamora-current-config.scm">https://notabug.org/jbranso/linode-guix-system-configuration/src/master/linode-locke-lamora-current-config.scm</a></p><p>The current task list is here:</p><p><a href="https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org">https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org</a></p><p>Added, the guixrus channel to my ~/.config/guix/channels.scm</p><pre><code>cat ~/.config/guix/channels.scm
- (cons* (channel ;; for firefox-wayland
- (name 'nonguix)
- (url &quot;https://gitlab.com/nonguix/nonguix&quot;)
- ;; Enable signature verification:
- (introduction
- (make-channel-introduction
- &quot;897c1a470da759236cc11798f4e0a5f7d4d59fbc&quot;
- (openpgp-fingerprint
- &quot;2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5&quot;))))
- (channel ;; for sway-latest
- (name 'guixrus)
- (url &quot;https://git.sr.ht/~whereiseveryone/guixrus&quot;)
- (introduction
- (make-channel-introduction
- &quot;7c67c3a9f299517bfc4ce8235628657898dd26b2&quot;
- (openpgp-fingerprint
- &quot;CD2D 5EAA A98C CB37 DA91 D6B0 5F58 1664 7F8B E551&quot;))))
- %default-channels)</code></pre><p>Before I submit the patch, I should make sure that the code actually works. To
- do that, I logged into my gnucode.me server tried to set up the opensmtpd
- server.</p><pre><code>guix pull --url=https://notabug.org/jbranso/guix/src/newOpensmtpdBranch \
- --branch=newOpensmtpdBranch
- Updating channel 'guix' from Git repository at 'https://notabug.org/jbranso/guix'...
- guix pull: error: Git error: cannot locate remote-tracking branch 'origin/keyring'
- guix pull --url=https://notabug.org/jbranso/guix \
- --commit=8abbb6c442d135ae8e7c1cb0e17525478fafe8f0
- Updating channel 'guix' from Git repository at 'https://notabug.org/jbranso/guix'...
- guix pull: error: Git error: cannot locate remote-tracking branch 'origin/keyring'</code></pre><p>Hmm, well my opensmtpd service is NOT using signed commits. That’s probably the
- problem. Hmmm… Well I guess I need to start signing my commits. Generate an
- gpg key. grrr….</p><p>These three pages are seem promising:</p><p><a href="https://moser-isi.ethz.ch/gpg.html">https://moser-isi.ethz.ch/gpg.html</a></p><p><a href="https://wiki.debian.org/Keysigning">https://wiki.debian.org/Keysigning</a></p><p><a href="https://risanb.com/code/backup-restore-gpg-key/">https://risanb.com/code/backup-restore-gpg-key/</a></p><pre><code>gpg --full-generate-key
- gpg: directory '/home/joshua/.gnupg/openpgp-revocs.d' created
- h.lgpg: revocation certificate stored as '/home/joshua/.gnupg/openpgp-revocs.d/LOTSOFNUMBERS.rev'</code></pre><p>I copied my Revocation-Certificate into my spare usb:</p><pre><code>sudo cp .gnupg/openpgp-revocs.d/LOTSOFNUMBERS.rev /mnt/gnucode.gpg.rev</code></pre><p>Let’s export my gpg key to the server.</p><pre><code>gpg --auto-key-locate keyserver -a --send-keys 67A42A3CC23F979886F9686C750BCFEF3A579572
- gpg -a --export gnucode
- -----BEGIN PGP PUBLIC KEY BLOCK-----
- mQINBGOSU7sBEAC/8renj2OgTHKJfbqz7CRplPQ0su8aasJXTkunx70IhVpTFBS+
- 9Bwvjbo7HM2aBYD/NYa6n24J3OXla17uDxFt2i63ojhbl5AVntac3ZOeyn661Y2U
- r9szIRM+edTieWZZvY5G49ZFTH5VJ+jZS2leRLpIqsYCst+Ru61MdUUggBNvPgBm
- q97HAylBqQs0kf7XfctyqKbkChLsvkuD5cR1X8BQL8KAn/KDXrDSwj4hIO+tSdv5
- VmaTC+6/xbdqfq6gpywJMEPkLNUjCArlF+Oz5UqQvLh1lRXWPejzFa0LmXsviqb3
- RmQh+9cNvDVge+kYIRWHhCXY5dTau7ABnYsgxnW3zlBkFNbc+I5Sqiz6LDcuInlA
- QznFw90GL3l0+1WGzeAD5DhNx6hgpOYvFZV7S3OgbOGeOHvF7bFBixB6Pa3oByMn
- euKqol+rOZiUkjcaxo5XUKsglFLgOaxfmZujO7lwoipYXxiyD7jf1+ou1WZ5C3l+
- YCOnia2qWE5DRpR/WDBRLQl3ZrCUtDQW7dKNAuweEgDT5T53k2m3Gqu1Z28SrzIS
- is+SHZcZhv4dx9Cs6sX6me3WzQ3wgoI9DNW5v8XGitaGQFjIRI33Y8MeGjEBMip3
- ZnT6Cl8WJgd0JBXsPQnKw1EO1sh2S5cU5drvHkuCPMA/PaBb8XrNpobSlwARAQAB
- tDNKb3NodWEgQWxsZW4gQnJhbnNvbiAoZ251Y29kZSkgPGpicmFuc29AZGlzbWFp
- bC5kZT6JAk4EEwEIADgWIQRnpCo8wj+XmIb5aGx1C8/vOleVcgUCY5JTuwIbAwUL
- CQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRB1C8/vOleVcgwwEACp4ZwBIM/4Udc9
- ndZvUJeegSP0W7o86v+9ELXfXdX99ZO0iErr6/XTWxov0mw7AaoDJRdETBTkYeU0
- /CDrLcjklW8b7RZe98+Cr0+IB9XSozpqNVhiP7/TogL80lkbu2+Khtk29E/UYupt
- 8rihR+2tkDKPaWOufGgi+6ftw8A9P9jlFsV1N1Oxo4rA+gbcXHtxbDiZ1dR2UOAS
- Ge7TJPpIjgSiG+nm6b9BIoAxLpjf5JrwpNm5wvDXic1YP27GC2Il9Ny7TdGyKpn9
- RCZXR1yEMQTVNn4iEiMK6XIcoAFUS1oWAP2JKQ4bCfcxM/VGx31rsGgNL36iW6yj
- zLD9yJYhbvm536CiRb2cTco+lAmwS9/iM4Bdpp/H9fZFPp2CxeB02mOd/P0HkC+2
- Po2KXpEj6Ettjp0xJcAQye75vRvjDMkHvTvugfY4FQg6V6a6N3jxSbfwuFUp426F
- fgfki4Y7OWm47mYa7goI4oDOG2qUdN5YkbhpVA+j2tGGHbbXmUtvj4MES4fnaSkF
- vc6+xMZpFTWcFRt8rVTqS1Vu1w8zfT/VUV+FC/J6hdSxIQJ4dg4WsaD2kzGflZzO
- miTyxMYPvdQ6I7Nshp/bEyfd9F40sXm/kzL6r+qm9+ly2uR5V+bIo9gu6CfkM0ZJ
- DDiIf9wkk+xSb/AGj1YVazQKpKS0wLkCDQRjklO7ARAAzrtyGaOFTtCHlItxxb51
- s0Qt5LZwG3sNUjI9P7n3oZrzI35sbPrWxWCX2MMW0gUIx79dlMzQBt1RXQEKiipr
- RdSrtuclTytxaMtLRP+VtmcRQkGgKb20ipCvFHX4oA7L+3Y8s2RQBsz+wo9h55Dt
- iQRxoONm9biHXBUZ4EJnR4B8z0dp9j+fctTR4ds6OI3jIeKHcd4AALYIpyBnh5ue
- 5Iictiv0evBjcogfCttHlg/NK3TVZpq8YYOG8x+8XVrvvJ5WKtmXduZuFIL3+Wmv
- jBv807a4zGLPLpB6OcD7fj/12Eo9n7d9gHZOV200rPguzt9YMIoRGgtSEEpMsvrJ
- 5upiFLPULj/14arXePdqZshlU01U0uE6glGJRUt7IVyU+1LbziQ8JqBlVTnRRYrb
- uKDFqzmtd3zhLDPAPLkv7xLtEjYUPcFDmrf33dz22FHUGeOB0G5Ur+e9qTedfmj0
- r5sHaoCspZzDcVR8sKyuUdAnRAGxJs9eIFUq2GkyxZGgfJoU2A9RMxg+YTfFfdQV
- guvvPj6udOF4ugmIW1EnDXza08UyDqOITLIadNu4GqZL407JRIRtYfw48qQgL3Zo
- 6lqxC/3n7orkuRU/cKvHArqQt1sP7ZYzAy5N/yoY0/m3o2RV9Li7SkF2m5By8EjH
- RNvQMPsipdvjWf4I+jLaAM0AEQEAAYkCNgQYAQgAIBYhBGekKjzCP5eYhvlobHUL
- z+86V5VyBQJjklO7AhsMAAoJEHULz+86V5Vy6U0QAJtjybCfDAqE5DIcKkiBDbIN
- erk+MTU+uOROuVigDCyvqJUuxtGaJPIRWdBQuHcQxnf6Bv1xoAeDk/7hyL7i5+rz
- 9vWZnSZRr4DB6pY8G5jz/HGdML4luEtuOrE5UMN8Bf5PM/9sj/c1QSuMhpAMw5TL
- GoAu+MY/uDCHLb2nzwLIaCPFDTX0q5HgFQA7Do78fdxxPLqPlbg9xeTsAP5P6Egb
- /8NUUa1SM4mfygriyL82nLH9SvwtnEbItovAWE+GH4XkE8xSjvWl6MpCk0+H0Xtr
- WdbxtKqE7BPzs0lN3NOi+mOJABDt5ozPGfVcUsB/nqz00YiF33CQWu0ote1Q1TKn
- NPOCLqFM3F1rG2z7Bf/LP9p6CpmfQGr54XmKpGinYNr8dqRtLEMVERCxGI+BuNhZ
- ppQLuqOlHinKPaBO58LCwLA0uMScbmjgTQrJiXolCGHYXorCx3rcqitvMzbAcswr
- wMeAXMREYKGM84Pf8fGxv+GZZwfQJHQNbOFrOTpnRITDAZvzKBD97yWkXcLGt6B7
- A5iRXOI8sv9CGM3kI78b+MCcgbz8HNGF2RQipGNQZhEgL4ixbhpMaMVUuTo7BrKr
- M3IeyVwUMpUBFbk5OqLsMqPbL2VvL6x1zgg4P0LmGQYoikKiwmPl/OyRQW6btWCG
- 1f7+w1RrcKjUANLQNjXm
- =Vl9S
- -----END PGP PUBLIC KEY BLOCK-----
- gpg -a --export gnucode &gt; gnucode.pub
- sudo cp gnucode.pub /mnt/</code></pre><p>Now let’s backup the gpg key.</p><pre><code> gpg --export-secret-keys --armor gnucode &gt; secret-key-backup.asc
- sudo mv secret-key-backup.asc /mnt/</code></pre><p>If I ever need to move that gpg key to another computer, all I have to do is:</p><pre><code>gpg --import /path/to/secret-key-backup.asc</code></pre><p>Let’s try testing a signed commit.</p><pre><code>git config --global commit.gpgsign true</code></pre><p><a href="https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key">https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key</a></p><pre><code>gpg --list-secret-keys --keyid-format=long
- # git config --global user.signingkey MYSIGNINGKEY
- git config --global alias.logs &quot;log --show-signature&quot;
- git commit -m &quot;mail.scm: minor sanitization improvements.&quot;</code></pre><p>Ok well let’s try this to see what the error was:</p><pre><code>GIT_TRACE=1 git commit -m &quot;blah&quot; -S
- 23:07:37.656401 git.c:460 trace: built-in: git commit -m blah -S
- 23:07:37.678825 run-command.c:655 trace: run_command: gpg --status-fd=2 -bsau 750BCFEF3A579572
- error: gpg failed to sign the data
- fatal: failed to write commit object
- gpg --status-fd=2 -bsau 750BCFEF3A579572</code></pre><p>As I was running through the above command, I realized that, it is possible that
- I did not have pinentry installed:</p><pre><code>guix install pinentry
- git logs</code></pre><p>Now I think I will try rebooting and check to see if I can still sign git
- commits.</p><p>And after I rebooted, I cannot sign commits with emacs…</p><p>Emacs says “hint: Waiting for your editor to close the file…”
- “Waiting for Emacs”</p><p>Well online, I see this as a possible solution</p><pre><code>git config --global core.editor emacs</code></pre><p>Well that didn’t quite work. I was able to squash two commits, via emacs, but
- only after I had the gpg agent had cached my private key password. That makes
- me think that magit is having a hard time querying my for my password.</p><p>Well let me try updating doom emacs. I doubt that will work, but I’ll try it.
- That didn’t work. :(</p><p>Well I found a possible error here:</p><p><a href="https://github.com/magit/with-editor/issues/69">https://github.com/magit/with-editor/issues/69</a></p><p><a href="https://emacs.stackexchange.com/questions/74097/magit-cannot-commit-emacsclient-on-path-pop-os">https://emacs.stackexchange.com/questions/74097/magit-cannot-commit-emacsclient-on-path-pop-os</a></p><p><a href="https://magit.vc/manual/with-editor/Configuring-With_002dEditor.html">https://magit.vc/manual/with-editor/Configuring-With_002dEditor.html</a></p><p>Then I thought, how about I disable the with-editor elisp package that doom
- emacs ships and instead <code>guix install emacs-with-editor</code>. Let’s try that.</p><pre><code>cat .doom.d/packages.el | grep with-editor
- (package! with-editor :disable t)
- doom upgrade
- doom sync
- guix install emacs-with-editor</code></pre><p>Nope. That didn’t work either. Hmmm. I can get emacs to commit the message,
- after the gpg agent caches my key’s password.</p><p>Well let’s try running emacs without any configuration: <code>emacs -q</code>. Nope. That
- also didn’t work. :(</p><p>My current theory is that my wayland only session is prohibiting the pinentry
- from displaying, which is NOT allowing me to enter in my gpg password. I shall
- try temporarily enabling Xwayland and see if that fixed it.</p><pre><code>cat config | grep xwayland
- # disable xwayland. Just trying it out
- xwayland enable</code></pre><p>Yup! That fixed it. With the above, I can now sign my commits with emacs! But
- I would rather keep my wayland only session. Let’s try pinetry-bemenu:</p><pre><code>guix package -i pinentry-bemenu -r pinentry
- cat config | grep xwayland
- # disable xwayland.
- xwayland disable</code></pre><p>Well that didn’t work. Let’s try pinetry-gnome3.</p><pre><code>guix package -r pinentry-bemenu -i pinentry-gnome3</code></pre><p>Nope. It’s X only. Let’s try qt:</p><pre><code>guix package -r pinentry-gnome3 -i pinentry-qt</code></pre><p>Nope. That also seems to be X only. grr. Maybe this bemenu thing works, but I
- need to configure it properly.</p><p>Well let’s install pinentry, and temporarily enable xwayland.</p><pre><code>guix package -r pinentry-tty -i pinentry
- cat config | grep xwayland
- # enable xwayland.
- xwayland enable</code></pre><p>Well I should probably try eventually to edit <code>.config/gpg.conf</code> and tell it to
- use pinentry-bemu as the pinentry program.</p><p>I think that spending all that time working on getting gpg key signing to work
- was probably a big waste of time. :( I think instead of keeping my opensmtpd
- code in guix-src/gnu/services/mail.scm, I will move it to
- guixrus/services/opensmtpd.scm. Then I can just copy opensmtpd.scm file to my
- linode server, and manually load in that code to start my opensmtpd service.</p><p>First I will delete the opensmtpd record stuff in gnu/services/mail.scm. I
- don’t want myself getting confused where I am storing my developmental code.</p><p>Now I will cp my opensmtpd.scm code into my linode service git repo.</p><pre><code>cp opensmtpd.scm ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/
- ls ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm
- cat ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm | tail
- /home/joshua/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm
- (service-extension pam-root-service-type
- (const %opensmtpd-pam-services))
- (service-extension profile-service-type
- (compose list opensmtpd-configuration-package))
- (service-extension shepherd-root-service-type
- opensmtpd-shepherd-service)
- (service-extension setuid-program-service-type
- opensmtpd-set-gids)))
- (description &quot;Run the OpenSMTPD, a lightweight @acronym{SMTP, Simple Mail
- Transfer Protocol} server.&quot;)))</code></pre><p>Now I will commit the changes to my linode git repo and push them.</p><pre><code>git add opensmtpd.scm
- git commit -m &quot;copying opensmtpd.scm from guixrus.&quot;
- [master 7399550] copying opensmtpd.scm from guixrus.
- 1 file changed, 7 insertions(+)
- rename opensmtpd.scm =&gt; guixrus/services/opensmtpd.scm (99%)</code></pre><p>Hmmm, was that commit signed? No idea.</p><p>Now let’s push that commit.</p><pre><code>git push</code></pre><p>Now let's log into the gnucode service and pull that commit.</p><pre><code>git pull
- cat opensmtpd.scm | tail
- Updating a8d88b9..7399550
- Fast-forward
- opensmtpd.scm =&gt; guixrus/services/opensmtpd.scm | 7 +++++++
- 1 file changed, 7 insertions(+)
- rename opensmtpd.scm =&gt; guixrus/services/opensmtpd.scm (99%)</code></pre><p>I am realizing that it will probably be easiest to reconfigure my server with my
- opensmtpd records, if my server has the same directory structure as my local
- machine. Namely my git repos are in the same directories. So I did some changes
- on my server to make sure that my server's directory structure matches my local
- one. Now my server’s <code>config.scm</code> is no longer at
- ~/linode-guix-system-configuration/linode-locke-lamora-current-config.scm. Now
- it is at:</p><pre><code>find . -name '*current-config.scm'
- ./prog/gnu/guix/guix-config/linode-guix-system-configuration/linode-locke-lamora-current-config.scm</code></pre><p>I want to make sure that my remote server has a copy of the guixrus source code
- with my newest commit committing <code>services/opensmtpd.scm</code>.</p><p>So, I made a guixrus repo on <a href="https://notabug.org/jbranso/guixrus">notabug.org</a>, then I pulled that repo on my server:</p><pre><code>git clone https://notabug.org/jbranso/guixrus
- git show HEAD | head
- commit 147a9ce316be2f9f7c9ed25b3e097fd84b8b01eb
- Author: Joshua Branson &lt;jbranso@dismail.de&gt;
- Date: Thu Dec 22 09:21:19 2022 -0500
- services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.
- Openmstpd-configuration may only be configured by a config-file that
- uses the smtpd.conf syntax. This patch, enables one to configure
- opensmtpd by using record types.</code></pre><p>It would be nice to test the configuration locally, to see if it will work
- before I push it to the server.</p><pre><code>guix system vm linode-locke-lamora-current-config.scm
- guix system: error: (cert &quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&quot;) is invalid.
- hint: Try a file.</code></pre><p>The above is actually a good sign. I do not have that certificate locally, but
- it is available on the server. If that is the only error, then let’s go ahead
- and try to reconfigure the server.</p><p>The relevant opensmtpd-service looks like:</p><pre><code>(service opensmtpd-service-type
- (let ([action-receive (opensmtpd-local-delivery
- (name &quot;receive&quot;)
- (method (opensmtpd-maildir
- (pathname &quot;/home/%{rcpt.user}/Maildir&quot;)
- (junk #t)))
- (virtual (opensmtpd-table
- (name &quot;vusers&quot;)
- (data '((&quot;joshua@gnucode.me&quot; . &quot;joshua&quot;)
- (&quot;jbranso@gnucode.me&quot; . &quot;joshua&quot;)
- (&quot;postmaster@gnucode.me&quot; . &quot;joshua&quot;))))))]
- [pki-gnucode (opensmtpd-pki
- (domain &quot;smtp.gnucode.me&quot;)
- (cert &quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&quot;)
- (key &quot;/etc/letsencrypt/live/gnucode.me/privkey.pem&quot;))]
- [filter-dkimsign (opensmtpd-filter
- (name &quot;dkimsign&quot;)
- (exec #t)
- (proc (list (file-append opensmtpd-filter-dkimsign &quot;/libexec/opensmtpd/filter-dkimsign&quot;)
- &quot; -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k &quot;
- &quot;/etc/dkim/private.key &quot;
- &quot;user nobody group nogroup&quot;)))]
- [table-creds (opensmtpd-table
- (name &quot;creds&quot;)
- (data
- (list
- (cons &quot;joshua&quot;
- &quot;$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.&quot;))))])
- (opensmtpd-configuration
- (interfaces
- (list
- ;; this forum help suggests that I listen on 0.0.0.0 and NOT eth0
- ;; https://serverfault.com/questions/726795/opensmtpd-wont-work-at-reboot
- ;; this listens for email from the outside world
- (opensmtpd-interface
- (interface &quot;eth0&quot;)
- (port 25)
- (secure-connection &quot;tls&quot;)
- (pki pki-gnucode))
- ;; this lets local users logged into the system via ssh send email
- (opensmtpd-interface
- (interface &quot;lo&quot;)
- (port 25)
- (secure-connection &quot;tls&quot;)
- (pki pki-gnucode))
- (opensmtpd-interface
- (interface &quot;eth0&quot;)
- (port 465)
- (secure-connection &quot;smtps&quot;)
- (pki pki-gnucode)
- (auth table-creds)
- (filters (list filter-dkimsign)))
- (opensmtpd-interface
- (interface &quot;eth0&quot;)
- (port 587)
- (secure-connection &quot;tls-require&quot;)
- (pki pki-gnucode)
- (auth table-creds)
- (filters (list filter-dkimsign)))))
- (matches (list
- (opensmtpd-match
- (action (opensmtpd-relay
- (name &quot;relay&quot;)))
- (options
- (list
- (opensmtpd-option
- (option &quot;for any&quot;))
- (opensmtpd-option
- (option &quot;from any&quot;))
- (opensmtpd-option
- (option &quot;auth&quot;)))))
- (opensmtpd-match
- (action action-receive)
- (options
- (list
- (opensmtpd-option
- (option &quot;from any&quot;))
- (opensmtpd-option
- (option &quot;for domain&quot;)
- (data (opensmtpd-table
- (name &quot;vdoms&quot;)
- (data (list &quot;gnucode.me&quot;
- &quot;gnu-hurd.com&quot;))))))))
- (opensmtpd-match
- (action action-receive)
- (options
- (list
- (opensmtpd-option
- (option &quot;for local&quot;))))))))))</code></pre><p>I was curious to see how outdated my server is. It’s dated apparently.</p><pre><code>guix system describe
- [1mGeneration 118 Aug 14 2022 02:45:18[0m (current)
- file name: /var/guix/profiles/system-118-link
- canonical file name: /gnu/store/7jkrafkf61bw3fdxlrlzvkrl98ys1icj-system
- label: GNU with Linux-Libre 5.18.16
- bootloader: grub
- root device: /dev/sda
- kernel: /gnu/store/iz6xn1b1dyk6pwaf6dym3jm3vwnh4gz9-linux-libre-5.18.16/bzImage
- channels:
- guix:
- repository URL: https://git.savannah.gnu.org/git/guix.git
- branch: master
- commit: 43decd1f7ea4ebd911199ad10c0ca555d0dffbd6
- configuration file: /gnu/store/rv7rhwn5kd9yxv8kayqlsgxwyhcz55ca-configuration.scm</code></pre><p>Let's try reconfiguring my server with the opensmtpd configuration.</p><pre><code>guix pull
- sudo guix system reconfigure linode-locke-lamora-current-config.scm
- In srfi/srfi-1.scm:
- 586:29 19 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type mingetty 7f8…&gt; …))
- 586:29 18 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type mingetty 7f8…&gt; …))
- 586:29 17 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type mingetty 7f8…&gt; …))
- 586:29 16 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type mingetty 7f8…&gt; …))
- 586:29 15 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type mingetty 7f8…&gt; …))
- 586:29 14 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type agetty 7f8c1…&gt; …))
- 586:29 13 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type syslog 7f8c1…&gt; …))
- 586:29 12 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type console-font…&gt; …))
- 586:29 11 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type virtual-term…&gt; …))
- 586:17 10 (map1 (#&lt;&lt;service&gt; type: #&lt;service-type opensmtpd 7f…&gt; …))
- In guixrus/services/opensmtpd.scm:
- 2567:27 9 (opensmtpd-shepherd-service #&lt;&lt;opensmtpd-configuration&gt;…&gt;)
- 2541:19 8 (opensmtpd-configuration-&gt;mixed-text-file #&lt;&lt;opensmtpd-…&gt;)
- 2496:3 7 (opensmtpd-configuration-&gt;string #&lt;&lt;opensmtpd-configura…&gt;)
- 2421:9 6 (opensmtpd-configuration-fieldname-&gt;string #&lt;&lt;opensmtp…&gt; …)
- 2430:10 5 (list-of-records-&gt;string (#&lt;&lt;opensmtpd-interface&gt; i…&gt; …) …)
- 2434:17 4 (loop (#&lt;&lt;opensmtpd-interface&gt; interface: &quot;eth0&quot; fam…&gt; …))
- 1848:5 3 (opensmtpd-interface-&gt;string #&lt;&lt;opensmtpd-interface&gt; in…&gt;)
- In unknown file:
- 2 (string-append &quot;&quot; &quot;&quot; &quot;&quot; &quot;&quot; &quot;&quot; &quot;tls &quot; #&lt;unspecified&gt; &quot;p…&quot; …)
- In ice-9/boot-9.scm:
- 1685:16 1 (raise-exception _ #:continuable? _)
- 1685:16 0 (raise-exception _ #:continuable? _)
- ice-9/boot-9.scm:1685:16: In procedure raise-exception:
- In procedure string-append: Wrong type (expecting string): #&lt;unspecified&gt;</code></pre><p>Ahh, I know what that problem is! Let’s fix that. So now I have make a local
- commit. Push it to my notabug.org/guixrus, ssh into lamora, run <code>git pull</code> on
- the guixrus repo, then try to reconfigure. This seems like a very odd/poor way
- to test changes. By making a commit locally, pushing it, pulling it, and then
- wondering if the reconfigure will work. I should really set up guix deploy.</p><pre><code>sudo guix system reconfigure linode-locke-lamora-current-config.scm
- module-import-compiled 1.0MiB 1.6MiB/s 00:01 [##################] 100.0%
- building /gnu/store/mw8x4pbl11a5pdgxqcw2vvczdccpmicf-switch-to-system.scm.drv...
- making '/gnu/store/0v5sbvlx9r151gjlc906lxyhps7xx1h8-system' the current system...
- setting up setuid programs in '/run/setuid-programs'...
- populating /etc from /gnu/store/1n0l349b03h7dclwai9l0kxglb8kwyv0-etc...
- checking syntax of /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf
- /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf:14: syntax error
- /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf:21: no such dispatcher: relay</code></pre><p>Ok, so I have a configuration error. Let’s take a look at the generated
- configuration file:</p><ul><li><p>The first error is this:</p><pre><code>cat /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf | grep '&lt;&quot;&lt;&quot;'
- listen on eth0 filter &quot;dkimsign&quot; smtps port 465 pki smtp.gnucode.me auth &lt;&quot;&lt;&quot;creds&quot;&gt;&quot;&gt;
- listen on eth0 filter &quot;dkimsign&quot; tls-require port 587 pki smtp.gnucode.me auth &lt;&quot;&lt;&quot;creds&quot;&gt;&quot;&gt;</code></pre><p>It should be &lt;“creds”&gt;.</p></li><li><p>Another error is this:</p><pre><code>cat /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf | grep match
- match !for any !from any !auth action &quot;relay&quot;
- match !from any !for domain &lt;&quot;vdoms&quot;&gt; action &quot;receive&quot;
- match !for local action &quot;receive&quot;</code></pre></li></ul><p>These match options should NOT be false. Let's quickly fix those issues
- reconfigure again:</p><pre><code>sudo guix system reconfigure linode-locke-lamora-current-config.scm
- checking syntax of /gnu/store/a69a5vn2r94glh58wlfq41ygfl38ikgn-smtpd.conf
- configuration OK</code></pre><p>That’s a good sign!</p><p>Let’s reboot and see what happens!</p><p>Well when I reboot, smtpd refused to start. Let’s look at the config file.</p><pre><code>cat /gnu/store/a69a5vn2r94glh58wlfq41ygfl38ikgn-smtpd.conf
- filter &quot;dkimsign&quot; proc-exec &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&quot;
- mta max-deferred 100
- table &quot;creds&quot; { &quot;joshua&quot; = &quot;$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.&quot; }
- table &quot;vusers&quot; { &quot;joshua@gnucode.me&quot; = &quot;joshua&quot;, &quot;jbranso@gnucode.me&quot; = &quot;joshua&quot;, &quot;postmaster@gnucode.me&quot; = &quot;joshua&quot; }
- table &quot;vdoms&quot; { &quot;gnucode.me&quot;, &quot;gnu-hurd.com&quot; }
- pki smtp.gnucode.me cert &quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&quot;
- pki smtp.gnucode.me key &quot;/etc/letsencrypt/live/gnucode.me/privkey.pem&quot;
- listen on eth0 tls port 25 pki smtp.gnucode.me
- listen on lo tls port 25 pki smtp.gnucode.me
- listen on eth0 filter &quot;dkimsign&quot; smtps port 465 pki smtp.gnucode.me auth &lt;&quot;creds&quot;&gt;
- listen on eth0 filter &quot;dkimsign&quot; tls-require port 587 pki smtp.gnucode.me auth &lt;&quot;creds&quot;&gt;
- action &quot;relay&quot; relay
- action &quot;receive&quot; maildir &quot;/home/%{rcpt.user}/Maildir&quot; junk virtual &lt;&quot;vusers&quot;&gt;
- match for any from any auth action &quot;relay&quot;
- match from any for domain &lt;&quot;vdoms&quot;&gt; action &quot;receive&quot;
- match for local action &quot;receive&quot;</code></pre><p>It seems to be just fine...hmmm. What does the error log say?</p><pre><code>cat /var/log/maillog | tail
- Dec 22 10:05:41 localhost smtpd[19325]: warn: lost processor: dkimsign exited abnormally
- Dec 22 10:05:41 localhost smtpd[19328]: dkimsign: Can't open key file (/etc/dkim/private.key): No such file or directory
- Dec 22 10:05:41 localhost smtpd[19330]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
- Dec 22 10:05:41 localhost smtpd[19325]: Exiting
- Dec 22 11:22:18 localhost smtpd[268]: info: OpenSMTPD 6.8.0p2 starting
- Dec 22 11:22:18 localhost smtpd[269]: warn: lost processor: dkimsign exited abnormally
- Dec 22 11:22:18 localhost smtpd[272]: dkimsign: Can't open key file (/etc/dkim/private.key): No such file or directory
- Dec 22 11:22:18 localhost smtpd[274]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
- Dec 22 11:22:18 localhost smtpd[269]: Exiting</code></pre><p>Ok, well I think I found the problem. haha. Let’s see, ah, looks like that key
- is here:</p><pre><code>find . -name '*key'
- /etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key</code></pre><p>Let’s commit my current-config locally, push it upstream, pull it from my server
- and reconfigure.</p><pre><code>sudo guix system reconfigure linode-locke-lamora-current-config.scm
- checking syntax of /gnu/store/42q90z8n03zi9rx29gwdnms4sdr2g2p9-smtpd.conf
- configuration OK</code></pre><p>After I rebooted, smtpd still was not starting. Let’s try to find out why:</p><pre><code>cat /var/log/maillog | tail
- Dec 22 11:38:03 localhost smtpd[498]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
- Dec 22 11:38:03 localhost smtpd[493]: warn: lost processor: dkimsign exited abnormally
- 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
- Dec 22 11:38:03 localhost smtpd[493]: Exiting
- Dec 22 11:40:02 localhost dovecot: master: Dovecot v2.3.19.1 (9b53102964) starting up for imap (core dumps disabled)
- Dec 22 11:42:41 localhost smtpd[258]: info: OpenSMTPD 6.8.0p2 starting
- Dec 22 11:42:41 localhost smtpd[259]: warn: lost processor: dkimsign exited abnormally
- 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
- Dec 22 11:42:41 localhost smtpd[264]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
- Dec 22 11:42:41 localhost smtpd[259]: Exiting</code></pre><p>Ok, this is just a permissions error. That’s an easy fix! I changed a
- <code>sudo chown -R smtpd /etc/opensmtpd</code>. Then I got this beauty:</p><pre><code>sudo herd start smtpd
- Service smtpd has been started.</code></pre><p>Woo hoo! Now let’s try to send an email and see if it works!</p><p>I sent an email to gmail, and if you select an email in gmail, you can click on
- view original. It showed me that I did pass dkimsigning! That’s awesome! And
- my email was in my gmail inbox. That’s a really good sign! Now I am off to
- submit a patch to guixrus!</p><p>I did get a tip from someone on irc that mentioned that I should verify my
- dkimsigning and SPF via https://dkimvalidator.com/ And when I used that tool, I
- discovered that my SPF was failing, so I will need to fix that.</p></content></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" /><content type="html"><p>Edit: Yes I am aware that I misspelled &quot;mispelling&quot;. I figure it's funny if I
- leave it as it is. :)</p><p>I had this simple coding problem that I wanted to solve. Here's the problem:</p><p>Suppose you are writing an guix service <a href="https://notabug.org/jbranso/guix/src/newOpensmtpdBranch/gnu/services/mail.scm">(like I happen to be)</a>, and you are
- sanitizing user input for various records. Suppose your user mispells an
- option. Wouldn't it be nice to include a nice helpful hint on what he probably
- did wrong?</p><pre><code class="language-scheme">(opensmtpd-option (option &quot;forany&quot;))</code></pre><p>error: (option &quot;forany&quot;) is invalid.
- hint: Try &quot;for rcpt-to&quot;, &quot;for domain&quot;, &quot;for local&quot;, &quot;for any&quot;, or &quot;for&quot;.</p><p>Using <code>string-prefix-length-ci</code>, I was able to construct a fairly naive
- prococedure that tries to guess what the user meant to type. Here's what I came
- up with:</p><pre><code class="language-scheme">;; if strings is (list &quot;auth&quot; &quot;for any&quot; &quot;from local&quot;)
- ;; Then this will return &quot;Try \&quot;auth\&quot;, \&quot;for any\&quot;, or \&quot;from local\&quot;.&quot;
- (define (try-string strings)
- (string-append &quot;Try &quot;
- (let loop ((strings strings))
- (cond ((= 1 (length strings))
- (string-append
- &quot;or \&quot;&quot; (car strings) &quot;\&quot;.\n&quot;))
- (else
- (string-append
- &quot;\&quot;&quot; (car strings) &quot;\&quot;, &quot;
- (loop (cdr strings))))))))
- ;; suppose string is &quot;for anys&quot;
- ;; and strings is (list &quot;for any&quot; &quot;for local&quot; &quot;for domain&quot;)
- ;; then hint-string will return &quot;Did you mean &quot;for any&quot;?&quot;
- (define* (hint-string string strings
- #:key (fieldname #f))
- (if (not (string? string))
- (try-string strings)
- (let loop ((current-max 1)
- (loop-strings strings)
- (hint-strings '()))
- (if (null? loop-strings)
- (cond ((= 1 (length hint-strings)) ;; only one worthwhile match
- (if fieldname
- (string-append &quot;Did you mean (&quot; fieldname &quot; \&quot;&quot;
- (car hint-strings) &quot;\&quot;) ?\n&quot;)
- (string-append &quot;Did you mean \&quot;&quot; (car hint-strings)
- &quot;\&quot;?\n&quot;)))
- (else (if (null? hint-strings)
- (try-string strings)
- (try-string hint-strings))))
- (let* ((element-string (car loop-strings))
- (element-max
- (string-prefix-length-ci element-string string)))
- (cond ((&gt; element-max current-max)
- (loop element-max (cdr loop-strings)
- (list element-string)))
- ((= element-max current-max)
- (loop current-max (cdr loop-strings)
- (cons element-string hint-strings)))
- (else (loop current-max
- (cdr loop-strings) hint-strings))))))))</code></pre><p>It won't recognize that &quot;or any&quot; or &quot;bor any&quot; should match &quot;for any&quot;, but for
- most mispellings, it should be half decent, provided the user got the first
- character right.</p><p>What do you all think? How would you write such a procedure?</p><p>EDIT: Well it turns out that the guix developers actually have a
- (string-closest) procedure. The relevant code can be found in
- (guix utils) and (guix combinators):</p><pre><code class="language-scheme">(define fold2
- (case-lambda
- ((proc seed1 seed2 lst)
- &quot;Like `fold', but with a single list and two seeds.&quot;
- (let loop ((result1 seed1)
- (result2 seed2)
- (lst lst))
- (if (null? lst)
- (values result1 result2)
- (call-with-values
- (lambda () (proc (car lst) result1 result2))
- (lambda (result1 result2)
- (loop result1 result2 (cdr lst)))))))
- ((proc seed1 seed2 lst1 lst2)
- &quot;Like `fold', but with two lists and two seeds.&quot;
- (let loop ((result1 seed1)
- (result2 seed2)
- (lst1 lst1)
- (lst2 lst2))
- (if (or (null? lst1) (null? lst2))
- (values result1 result2)
- (call-with-values
- (lambda () (proc (car lst1) (car lst2) result1 result2))
- (lambda (result1 result2)
- (loop result1 result2 (cdr lst1) (cdr lst2)))))))))
- (define (string-distance s1 s2)
- &quot;Compute the Levenshtein distance between two strings.&quot;
- ;; Naive implemenation
- (define loop
- (mlambda (as bt)
- (match as
- (() (length bt))
- ((a s ...)
- (match bt
- (() (length as))
- ((b t ...)
- (if (char=? a b)
- (loop s t)
- (1+ (min
- (loop as t)
- (loop s bt)
- (loop s t))))))))))
- (let ((c1 (string-&gt;list s1))
- (c2 (string-&gt;list s2)))
- (loop c1 c2)))
- (define* (string-closest trial tests #:key (threshold 3))
- &quot;Return the string from TESTS that is the closest from the TRIAL,
- according to 'string-distance'. If the TESTS are too far from TRIAL,
- according to THRESHOLD, then #f is returned.&quot;
- (identity ;discard second return value
- (fold2 (lambda (test closest minimal)
- (let ((dist (string-distance trial test)))
- (if (and (&lt; dist minimal) (&lt; dist threshold))
- (values test dist)
- (values closest minimal))))
- #f +inf.0
- tests)))</code></pre><p>A lot of the above code is a little bit above my head, but it sure looks cool.</p><p>And it actually works better than mine.:</p><pre><code class="language-scheme">;; old scheme code
- (display (hint-string &quot;bor any&quot; (list &quot;for any&quot; &quot;auth&quot; &quot;rdns&quot;)))
- Try &quot;for any&quot;, &quot;auth&quot;, or &quot;rdns&quot;.
- ;; It didn't match any string. :(
- ;; Let's try guix's (string-closest _) ...
- (string-closest &quot;bor any&quot; (list &quot;for any&quot; &quot;auth&quot; &quot;rdns&quot;))
- $1 = &quot;for any&quot;</code></pre><p>Awesome!</p></content></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" /><content type="html"><p>I have been using Doom emacs for about 6 months now, and I must say the
- experience is truly wonderful! It is hands down the best Emacs distribution
- that I have ever used. And it is <em>sooo fast</em>!</p><p>I used to own my own emacs config, which is something that everyone should do at
- some point to help you learn more about emacs, but maintaining your own emacs
- config is really hard. You have to:</p><ol><li>Fix any bugs that you have. <a href="https://elpa.gnu.org/packages/bug-hunter.html">bug hunter is really helpful for this</a></li><li>examine any cool packages that you may want to add.</li><li>Keep up to date with new packages that are probably better than the packages
- that you are using.</li><li>Update packages and deal with any new bugs they introduce.</li><li>Stay sane with all the complexity.</li></ol><p>I did the above for some time, and it is doable. I maintained my own Emacs for
- so long, because it was one of the few coding projects that I actively used and
- worked on. The problem was that my config’s stability varied week to week, and
- it made it harder to focus on actually helping <a href="https://guix.gnu.org">GNU Guix</a>. At a certain point I
- decided that I would rather let someone else maintain a config, so that I could
- spend more time helping a free software project.</p><p>I also realized that since I use Doom emacs so often, and it is in need of
- <a href="https://liberapay.com/hlissner">funding,</a> that I should probably go ahead and chip in. I highly reccommend you
- to check out Doom Emacs, and consider donating. Currently the maintainer of
- Doom can only allocate 12 hours per week on the project, but hopefully the
- community will be able to support his work full time.</p></content></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" /><content type="html"><p>When I was using Mobian GNU/Linux, I had some issues with the PinePhone. Namely,
- my phone no longer received SMS text messages. I switched to <a href="https://postmarketos.org/">PostMarketOS</a>, and
- my issues seemed to have gone away, at least if I keep using the phone as a dumb
- phone. I have disabled wifi on the phone, because I really don’t use it.</p><p>It would be nice if I could get the PinePhone to work well with <a href="https://jmp.chat">JMP.chat</a>, but
- currently the texts from my desktop machine do NOT sync well with the phone. So
- if I use two devices, I end up in a weird situation with out of sync text
- messages, which is really confusing. Plus using the internet on the phone
- drains the battery. So I have just disabled the internet on the phone via the
- hardware kill switches.</p><p>Texting works flawlessly, but I cannot get SMS images. Also the phone volume
- for calls is pretty poor. And sometimes when I make phone calls, I cannot hear
- what the other person is saying. So that is a little odd.</p><p>I highly recommend installing the reversed engineered and nearly <a href="https://github.com/the-modem-distro/pinephone_modem_sdk">libre custom
- firmware</a> for the PinePhone’s modem. It was actually <a href="https://www.youtube.com/watch?v=aokclNgnIbE">super easy to do</a>.</p><p>It might also not be a bad idea to edit the official PinePhone wiki and mention
- that <a href="https://tello.com/">Tello</a> is a fairly cheap provider. I pay them $8 per month and I have no
- data and unlimited calling and texting texts. That’s pretty good.</p><p>That’s the main update for today!</p></content></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" /><content type="html"><p>I am of the opinion, that in order to learn how to use an operating system, you
- have to use it often. Since I am madly in love with Guix System, but have an
- interest in the GNU/Hurd and OpenBSD, I might as well install those OSs on a
- virtual machine! I have already done that with the GNU/Hurd, and today I also
- did it for OpenBSD.</p><p>I was not that hard to do. I used this guide to <a href="https://wiki.qemu.org/index.php/Hosts/BSD#OpenBSD">install OpenBSD on a vm.</a></p><p>First let’s create a qemu img for OpenBSD.</p><p><code>qemu-img create -f qcow2 hd0.qcow2.img 100G</code></p><p>Now, let's create an install script.</p><pre><code>cat install-bsd.sh
- #!/bin/sh
- qemu-system-x86_64 -m 2048 \
- -no-reboot \
- -cdrom cd71.iso \
- -drive if=virtio,file=hd0.qcow2.img,format=qcow2 \
- -enable-kvm \
- -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
- -device virtio-net,netdev=mynet0 \
- -smp 2</code></pre><p>As always installing OpenBSD is an absolute breeze. I do not know how to
- manually partition things, so I just chose the auto install. Also OpenBSD
- supports a <code>us.swapcaps.dvorak</code> keyboard layout. That’s my layout! How cool is
- that!? And it sets up that layout for the console and X by default. Guix
- System does that, but not so well for wayland.</p><pre><code>cat run-bsd.sh</code></pre><p>Now let's create a run script.</p><pre><code>#!/bin/sh
- qemu-system-x86_64 -m 4G \
- -no-reboot \
- -drive if=virtio,file=hd0.qcow2.img,format=qcow2 \
- -enable-kvm \
- -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
- -device virtio-net,netdev=mynet0 \
- -smp 2</code></pre><p>I find the <code>-no-reboot</code> option helpful, because OpenBSD likes to try to autoreboot
- itself, even when you give it the command: <code>halt</code>.</p><p>I have ran OpenBSD before for about a week before, and it is always a pleasure
- to read man afterboot. With OpenBSD the man pages are absolutely excelent.</p><p>One of the first things I did was:</p><p><code># cp /etc/examples/doas.conf /etc/</code></p><p>Now my user <code>berno</code> can use <code>doas</code> to install packages! Let’s install Emacs!</p><p><code>doas pkg_add emacs</code></p><p>Also OpenBSD has a habit of printing clues to the console after you type in a
- command. For examle, after you install a package, OpenBSD tells you that it has
- installed README files in <code>/usr/local/bsah/blah/README/emacs/</code>. I find it really
- cool that it reminds you of this. Also, when you run <code>doas syspatch</code> it will
- tell you that it updated syspatch. It will also say something like:</p><blockquote><p>Please run syspatch again to apply the patches.</p></blockquote><p>That’s a handy tip! And indeed, <code>doas syspatch -c</code> showed that the patches had
- not yet been applied.</p><p>Also whilst searching for the internet for how to install OpenBSD on a vm image,
- I came accross <a href="https://www.skreutz.com/posts/autoinstall-openbsd-on-qemu/">blog post</a> that describes that you can automate OpenBSD installs.
- That might be something to play with later!</p><p>I would like to also set up my local OpenBSD to set up ssh. That way I could do
- something like this:</p><pre><code>#+BEGIN_SRC shell :dir /ssh:berno@localhost:/home/berno :exports both
- ls | wc -l
- #+END_SRC
- #+RESULTS:
- : 9</code></pre><p>I also think it would be fabulous if the OpenBSD team started to make a
- guix-like package manager/distro. I imagine that they could use perl to do it,
- since it seems like OpenBSD has embraced perl as their scripting language, and I
- think it their man pages show that perl can use some rather low lever operating
- system interfaces.</p></content></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" /><content type="html"><p>So I recently bought a guix system server! It cost me about $250. It’s got 16GB
- of RAM (I can upgrade to 32GB) with a 4TB harddrive. I may play with RAID at
- some point, but that’s a little down the line. If you want some help getting
- something like this for yourself, please contact me. This blog post is my first
- attempt at trying to figure out how to connect to <code>copertino</code>, to the
- internet. Now on with the blog post!</p><p>So when you are like me, and you start to wonder how the internets work, a good
- thing to learn first is difference between <strong>WAN</strong> and <strong>LAN</strong>. LAN is your local area
- network. When you are at home, on your computer, you are on your LAN. If your
- computer talks to another computer in your house, then those machines are using
- the LAN. When your computer talks to <code>www.gnu.org</code>, your computer is accessing
- the WAN, which is the wide area network, usually called the internet.</p><p>Computers talk to each other via IP addresses. An IP address is a numerical ID
- that is unique to each computer. Computers use IP address as essentially phone
- numbers to reach out and say, “Hey what time are we having this binary number
- crunching date?” What’s interesting, is computers have more than just a phone
- number, they have a phone number, plus several extensions.</p><p>When you call a business, and they say, “Thanks for calling Bank of Scotland.
- Please press 5 to talk to a manager, 4 to talk to a sales person, and 3 to open
- an account. Thanks!” 5, 4, and 3 are extensions. Computers have the same
- thing, on steroids. They calls extensions ports, and there are like 50,000+
- ports. Ports are usually set up to be used by specific applications. For
- example, your web browser uses port 80 and 443 to visit websites.</p><p>Here’s a crazy example.</p><pre><code>ping -c 1 gnu.org</code></pre><p>PING gnu.org (209.51.188.116): 56 data bytes
- 64 bytes from 209.51.188.116: icmp&lt;sub&gt;seq&lt;/sub&gt;=0 ttl=55 time=39.078 ms
- — gnu.org ping statistics —
- 1 packets transmitted, 1 packets received, 0% packet loss
- round-trip min/avg/max/stddev = 39.078/39.078/39.078/0.000 ms</p><p>So, we now know that gnu.org is serving it’s website on 209.51.188.116. Try
- posting this in a web browser url: 209.51.188.116. You’ll end up at
- savannah.nongnu.org, which is a website that the fabulous people at GNU run.</p><p>Anyway, let’s take a look at your IP address:</p><pre><code>ip address show</code></pre><p>1: lo: &lt;LOOPBACK,MULTICAST,UP,LOWER&lt;sub&gt;UP&lt;/sub&gt;&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- inet 127.0.0.1/8 scope global lo
- valid&lt;sub&gt;lft&lt;/sub&gt; forever preferred&lt;sub&gt;lft&lt;/sub&gt; forever
- 2: enp0s25: &lt;BROADCAST,MULTICAST,UP,LOWER&lt;sub&gt;UP&lt;/sub&gt;&gt; mtu 1500 qdisc pfifo&lt;sub&gt;fast&lt;/sub&gt; state UP group default qlen 1000
- link/ether 00:1c:25:9a:37:ba brd ff:ff:ff:ff:ff:ff
- inet 192.168.1.122/24 brd 192.168.1.255 scope global dynamic noprefixroute enp0s25
- valid&lt;sub&gt;lft&lt;/sub&gt; 22986sec preferred&lt;sub&gt;lft&lt;/sub&gt; 22986sec
- inet6 fe80::36a7:f91e:a1e0:16fe/64 scope link noprefixroute
- valid&lt;sub&gt;lft&lt;/sub&gt; forever preferred&lt;sub&gt;lft&lt;/sub&gt; forever
- 3: wlp2s0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
- link/ether b6:cf:27:17:7c:fc brd ff:ff:ff:ff:ff:ff permaddr e4:ce:8f:59:d6:bf</p><p>Let’s take the above output line by line:</p><pre><code>1: lo: &lt;LOOPBACK,MULTICAST,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- inet *127.0.0.1/8* scope global lo
- valid_lft forever preferred_lft forever
- lo is your loopback device, which is fancy talk for &quot;ME&quot;. The embolded
- *127.0.0.1* is a universal alias for &quot;ME&quot;. If you have a web site running on
- your computer, typing in 127.0.0.1:80 lets you access that website. 127.0.0.1:80
- means, talk to the computer at address 127.0.0.1 (which is me), and request the
- content on port 80.
- 2: *enp0s25*: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
- link/ether 00:1c:25:9a:37:ba brd ff:ff:ff:ff:ff:ff
- *inet* *192.168.1.122/24* brd 192.168.1.255 scope global dynamic noprefixroute enp0s25
- valid_lft 22986sec preferred_lft 22986sec
- *inet6* *fe80::36a7:f91e:a1e0:16fe/64* scope link noprefixroute
- valid_lft forever preferred_lft forever
- *enp0s25* is your ethernet device. Anything that begins with an 'e' is usually
- an ethernet device. Ethernet is usually the blue cable that you
- plug into your laptop or server. Laptops increasingly do not have ethernet,
- which is sad 'cause ethernet is faster than wifi.
- *init* means IPv4. Remember when I said that computers have IP address? Well
- than have one that looks like *192.168.1.122*. That is the IPv4 address. People
- now adays have phones, tablets, gaming consoles, smart watches, etc. and each
- need an IP address. As a result, the IPv4 address space is getting a little
- crowded. So some smart people introduced IPv6, which has much more unique IDs.
- (Keep reading to see an example IPv6 address).
- Unfortunately for me, an IP address of 192.168.number.number is a LAN IP. That
- means I have to be in my house to talk to view my personal website. I cannot
- view that website at work. :(
- *init6* is IPv6. And *fe80::36a7:f91e:a1e0:16fe* is this computer's IPv6
- address. fe80 is also a LAN IPv6 address. The outside world cannot use that
- address to talk to this local computer.
- 3: *wlp2s0*: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
- link/ether b6:cf:27:17:7c:fc brd ff:ff:ff:ff:ff:ff permaddr e4:ce:8f:59:d6:bf
- This is my wifi device. Anything that begins with an 'w' is usually a wifi device.
- ip route</code></pre><p>default via 192.168.1.1 dev enp0s25 proto dhcp metric 100
- 192.168.1.0/24 dev enp0s25 proto kernel scope link src 192.168.1.122 metric 100</p><p>The number after <strong>default</strong> is the default gateway. That is my router’s LAN IP
- address. If I type that into a web browser, when I am at home, then I can log
- into my router. Usually your router’s username and password is on a stick on the
- back of your router.</p><p>Also, it should be possible for me to log into the router and tell it to open up
- ports 80 and 443 (http and https), so that anyone connecting to say
- <code>www.copertino.me</code> would be connecting to my computer only, AND NOT my
- roommates’ laptop. However, an attacker could still potentially break into my
- guix system computer, and attack my roommate’s computer.</p><p>Also, if you decide to play around with customizing your router, I would
- recommend OpenBSD. OpenBSD potentially has some binary blobs for wifi, which is
- why the <a href="https://www.gnu.org/distros/free-distros.en.html">FSF</a> will not endorse it as a free distro. but if you don’t use wifi,
- then there is no software freedom issues. Anyway, I have recently developed
- quite the crush on OpenBSD, and I found this <a href="https://openbsdrouterguide.net/">guide</a>, that helps you use OpenBSD
- for your router. It’s actually quite comprehensive:</p><blockquote><p>In this guide we’re going to take a look at how we can use cheap and “low end”
- hardware to build an amazing OpenBSD router with firewalling capabilities,
- segmented local area networks, DNS with domain blocking, DHCP and more.</p><p>We will use a setup in which the router segments the local area network (LAN)
- into three separate networks, one for the grown-ups in the house, one for the
- children, and one for public facing servers (a DMZ), such as a private web
- server or mail server. We will also look at how we can use DNS to block out ads,
- porn, and other websites on the Internet. The OpenBSD router can also be used on
- small to mid-size offices.</p></blockquote></content></entry></feed>
|