<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Aloys' corner</title><id>https://aloysberger.com/feed.xml</id><subtitle>Recent Posts</subtitle><updated>2026-10-15T20:07:31Z</updated><link href="https://aloysberger.com/feed.xml" rel="self" /><link href="https://aloysberger.com" /><entry><title>WasmOS: implementing a virtual monitor</title><id>https://aloysberger.com/2026-10-15-20-02.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-15T20:02:00Z</updated><link href="https://aloysberger.com/2026-10-15-20-02.html" rel="alternate" /><content type="html">&lt;p&gt;
Things are slowly starting to fall in place with my idea of an &amp;quot;OS&amp;quot; in the browser.
The idea is to create a &amp;quot;kernel&amp;quot; on top of the WASM runtime.
Hardware will be emulated by the browser and/or JS, and maybe extended to WASI compatible runtime in the future.
&lt;/p&gt;&lt;p&gt;
Being a visual person, my first victim is the display..
The canvas will act as a monitor, receiving a framebuffer from the &amp;quot;kernel&amp;quot; written in Zig.
&lt;/p&gt;&lt;p&gt;
I'm completely out of my league here, so my apologies if the terminology is approximate.
I expect to read this in a year and think: &amp;quot;You know nothing, John Snow&amp;quot;
&lt;/p&gt;</content></entry><entry><title>WASM Component Model: the future of SDKs?</title><id>https://aloysberger.com/2026-10-14-14-12.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-14T14:12:00Z</updated><link href="https://aloysberger.com/2026-10-14-14-12.html" rel="alternate" /><content type="html">&lt;p&gt;
I started digging into WASM, and its component model.
&lt;/p&gt;&lt;p&gt;
This feels like a dream for SDK: you could implement a SDK into one language, and have it run in many languages and environment.
&lt;/p&gt;&lt;p&gt;
It's still too early to say if this will go anywhere, but it does have very attractive aspect to it, such as using the right language for the right component, rather than whatever the language is written in.
&lt;/p&gt;</content></entry><entry><title>WasmOS: Introduction</title><id>https://aloysberger.com/wasmos-introduction.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-12T18:06:00Z</updated><link href="https://aloysberger.com/wasmos-introduction.html" rel="alternate" /><content type="html">&lt;p&gt;
I am a 'self-taught' developer.
&lt;/p&gt;&lt;p&gt;
I put 'self-taught' between quotes because I didn't teach myself: the internet was full of excellent resources to learn to code&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.1&quot; href=&quot;#fn.1&quot; class=&quot;footref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;&lt;p&gt;
Product of my era, I learned to code with React circa 2017.
It was great for a while and I had a lot of fun grokking React and its ecosystem.
&lt;/p&gt;&lt;p&gt;
Fortunately, being curious by nature, I didn't stop there and slowly worked my way &lt;i&gt;down&lt;/i&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.2&quot; href=&quot;#fn.2&quot; class=&quot;footref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; the stack as time went on.
I developed a knack for good UI and UX and worked as a UX engineer.
I then moved onto full-stack roles, and dipped into infrastructure and devops.
Self-hosting came next and with it, a dabble of networking.
&lt;/p&gt;&lt;p&gt;
However, almost ten years later I still had not a complete understanding of what was going on under the hood.
I always worked at a high level of abstraction.
&lt;/p&gt;&lt;p&gt;
Fast forward to today, I am now finally getting into low level programming and I am currently going through the excellent &lt;a href=&quot;https://pages.cs.wisc.edu/~remzi/OSTEP/&quot;&gt;OSTEP&lt;/a&gt; book.
This lead me to this idea of WasmOS.
&lt;/p&gt;&lt;p&gt;
WasmOS is (or rather, will one day be, maybe?) a virtual OS running in the browser.
&lt;/p&gt;&lt;p&gt;
It is purely an educational and experimental project.
&lt;/p&gt;&lt;p&gt;
It won't be a complete OS, there are obvious limitations to creating a virtual OS in a browser.
&lt;/p&gt;&lt;div id=&quot;outline-container-org4cdc174&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4cdc174&quot;&gt;Goal&lt;/h2&gt;
&lt;div id=&quot;text-org4cdc174&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
WasmOS is an educational and experimental project.
&lt;/p&gt;

&lt;p&gt;
The overarching idea is to &lt;b&gt;&lt;i&gt;expand my circle knowledge while having fun&lt;/i&gt;&lt;/b&gt;.
&lt;/p&gt;

&lt;p&gt;
In particular, I wish to:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;acquire experience with lower level system programming,&lt;/li&gt;
&lt;li&gt;find an excuse to use zig,&lt;/li&gt;
&lt;li&gt;build a deeper understanding of the underlying machine,&lt;/li&gt;
&lt;li&gt;combat 'AI' fatigue,&lt;/li&gt;
&lt;li&gt;follow my curiosity,&lt;/li&gt;
&lt;li&gt;document my way through my learnings,&lt;/li&gt;
&lt;li&gt;create an endless project to tinker on, without boundaries or deadline,&lt;/li&gt;
&lt;li&gt;recreate the now extinct magical feeling of creating things by typing on a keyboard in a flow state while listening to good tunes (RIP),&lt;/li&gt;
&lt;li&gt;go slow and go deep,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The project has no real world application, this is a purely curiosity-driven project.
&lt;/p&gt;

&lt;p&gt;
It might not (and most likely won't) be useful beyond the intellectual stimulation of pursuing a lofty goal.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org0d5ddda&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0d5ddda&quot;&gt;Rules&lt;/h2&gt;
&lt;div id=&quot;text-org0d5ddda&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
Given the nature of the project, these are the rules I am setting to ensure the project is successful&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.3&quot; href=&quot;#fn.3&quot; class=&quot;footref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org64376b2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org64376b2&quot;&gt;No LLM to generate or review code&lt;/h3&gt;
&lt;div id=&quot;text-org64376b2&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
Niet. Nada. Nope. Rien.
&lt;/p&gt;

&lt;p&gt;
LLMs may have a place when there is a time-bound or financial goal. Maybe.
&lt;/p&gt;

&lt;p&gt;
But in this case, the use of LLMs to generate the code would be entirely counter-productive to the success of this project.
&lt;/p&gt;

&lt;p&gt;
Every line of (questionable) code in this repo will be handwritten by myself.
&lt;/p&gt;

&lt;p&gt;
No LLM generated code. No exception.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orge2ccce1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orge2ccce1&quot;&gt;No LLM to research or validate ideas&lt;/h3&gt;
&lt;div id=&quot;text-orge2ccce1&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
I have no idea what I'm doing here, and that's the point!
&lt;/p&gt;

&lt;p&gt;
I intend to &lt;b&gt;not&lt;/b&gt; use LLM to do any research or validation of my theory so I can fail.
&lt;/p&gt;

&lt;p&gt;
I want to fail. Failing is good.
&lt;/p&gt;

&lt;p&gt;
Avoiding LLMs will push me to come up with my own theories and mental models, and test them out.
&lt;/p&gt;

&lt;p&gt;
I expect to be in struggle-city a lot on this project, and that's by design.
&lt;/p&gt;

&lt;p&gt;
Failing is becoming a luxury in the LLMs age, I believe it's robbing us of creating expertise in many cases.
&lt;/p&gt;

&lt;p&gt;
I will still use books and internet, but I will not use any LLM-driven chatbot.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org7d96aa7&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org7d96aa7&quot;&gt;No time limits&lt;/h3&gt;
&lt;div id=&quot;text-org7d96aa7&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
This is intended to be an ongoing experiment.
&lt;/p&gt;

&lt;p&gt;
I might choose to terminate it early - or I will never finish it.
&lt;/p&gt;

&lt;p&gt;
I won't put any deadlines on myself and approach it with a slow productivity mindset.
&lt;/p&gt;

&lt;p&gt;
In the current insane pace of the modern world, I want to create an environment where things take the time they take.
&lt;/p&gt;

&lt;p&gt;
Go slow or go home.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgbf116fe&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgbf116fe&quot;&gt;Devlog&lt;/h3&gt;
&lt;div id=&quot;text-orgbf116fe&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
As I'm writing this, in October 2026, I don't know much about operating systems.
&lt;/p&gt;

&lt;p&gt;
I am about one third of my way through the awesome &lt;a href=&quot;https://pages.cs.wisc.edu/~remzi/OSTEP/&quot;&gt;OSTEP&lt;/a&gt; book, but that is as far as my experience goes with operating system.
&lt;/p&gt;

&lt;p&gt;
I am a web developer, not a system programming expert (yet!).
And what an opportunity!
&lt;/p&gt;

&lt;p&gt;
LLMs have robbed us of the beginner's trough (which is a tragedy in my opinion).
&lt;/p&gt;

&lt;p&gt;
Nothing like a fresh start, when you have no idea what you're doing and you suck at it.
That's the dreamer's stage, nothing is impossible.
&lt;/p&gt;

&lt;p&gt;
As part of this project, I will be writing a devlog of my progression as I go along.
&lt;/p&gt;

&lt;p&gt;
I will do my best to describe my thinking; I expect to write stupid ideas and be often incorrect, but I'm looking forward to it.
&lt;/p&gt;

&lt;p&gt;
This will give me the opportunity to improve my written communication, cement the knowledge I acquire, and give me the opprtunity to look back in a few years and think: &amp;quot;Man, I have come a long way!&amp;quot;.
&lt;/p&gt;

&lt;p&gt;
There is nothing as satisfying to me as looking back and seeing the progress you made.
&lt;/p&gt;

&lt;p&gt;
In my opinion, the journey is the most important part of any endeavor, be it life, or a geeky pursuit like this.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org63a6965&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org63a6965&quot;&gt;Have fun&lt;/h3&gt;
&lt;div id=&quot;text-org63a6965&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
Finally, the most important rule: this is about having fun - there is no expectations here.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orga6ad39c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orga6ad39c&quot;&gt;Where to start?&lt;/h2&gt;
&lt;div id=&quot;text-orga6ad39c&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
That's a good question. I don't really know where to start!
&lt;/p&gt;

&lt;p&gt;
The first question I need to answer is: what part of the OS can I realistically build in WASM?
What does an OS in WASM look like?
&lt;/p&gt;

&lt;p&gt;
My first task is to do some research about WASM and see what it is all about.
&lt;/p&gt;

&lt;p&gt;
The second, is simply to set up a Zig development environment.
&lt;/p&gt;

&lt;p&gt;
I did the Ziglings about a year ago, but I haven't used it or touch it since then.
I won't do them again, I am just going to &lt;a href=&quot;https://learnxinyminutes.com/zig/&quot;&gt;use a refresher&lt;/a&gt; and learn as I go.
&lt;/p&gt;

&lt;p&gt;
Alright, I will be back once I have a clearer picture of what I am actually trying to build here.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.1&quot; href=&quot;#fnr.1&quot; class=&quot;footnum&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;unfortunately, it seems that software engineering education content was another victim of 'AI'&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.2&quot; href=&quot;#fnr.2&quot; class=&quot;footnum&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;or sideways, I guess?&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.3&quot; href=&quot;#fnr.3&quot; class=&quot;footnum&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;my definition of success is to &lt;i&gt;expand my circle of knowledge while having fun&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;</content></entry><entry><title>Grieving the loss of details</title><id>https://aloysberger.com/2026-10-12-09-29.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-12T09:29:00Z</updated><link href="https://aloysberger.com/2026-10-12-09-29.html" rel="alternate" /><content type="html">&lt;p&gt;
Alisa Sireneva's &lt;a href=&quot;https://purplesyringa.moe/blog/grieving-the-loss-of-details/&quot;&gt;blog post&lt;/a&gt; is saddening. It reflects the current loss of meaning in the software industry that some of use are experiencing
Some people thrive with the advent of LLM, I don't.
&lt;/p&gt;&lt;p&gt;
As stated in my AI manifesto, I use it at work when I believe it in the interest of my employer.
I don't enjoy it; but if there is clear upside for my company, then I believe it is my duty to use it.
&lt;/p&gt;&lt;p&gt;
However, the definition of a &amp;quot;clear upside&amp;quot; is hard to define. The gain of speed at the cost of loss of comprehension of the codebase is a particularly hard one to judge.
&lt;/p&gt;&lt;p&gt;
In the comments on &lt;a href=&quot;https://news.ycombinator.com/item?id=49980880&quot;&gt;HackerNews&lt;/a&gt;, there is one that is really potent:
&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;
I agree with many perspectives in this thread. I empathize with OP. I’m scared about the future of my job and already feel it less fulfilling, despite being more productive than ever.
&lt;/p&gt;

&lt;p&gt;
But I have one singular counterexample to most scary narratives and essays about LLMs writing software, which is my coworker who hardly uses LLMs at all. At least, he hardly uses them compared to me. He still writes most of his code by hand. He still greps around the codebase without claude code. Like he’s definitely using claude code, but only for like one-off specific tasks.
&lt;/p&gt;

&lt;p&gt;
He’s a totally average developer, like everybody else on my team (including me). But he’s clearly more helpful than the rest of us. When people from other teams have questions about how something works, he’s always the first to respond. He’s always the one providing useful context in planning calls. He catches stuff in code review that I didn’t catch, and claude/copilot didn’t catch.
&lt;/p&gt;

&lt;p&gt;
I think I’ve leaned too far into AI, partly because I’m a lazybones and am kind of burned out already. But there’s a stark contrast between me and my coworker that there didn’t used to be. I think the context rot is really setting in, and getting worse. So I think there’s still value in caring about the details.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;
This is something I struggle with. There is an undeniable gain of speed when using LLM in my work, but it's not free.
The cognitive debt is stacking rapidly.
It's too early to know if this an acceptable risk or not.
&lt;/p&gt;</content></entry><entry><title>Toying with Elm</title><id>https://aloysberger.com/2026-10-11-18-46.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-11T18:46:00Z</updated><link href="https://aloysberger.com/2026-10-11-18-46.html" rel="alternate" /><content type="html">&lt;p&gt;
On another note, I'm currently building a basic tetris clone in Elm.
I don't think I'll continue to use Elm in the future; I believe WASM will make it less relevant.
I always wanted to try it out, it has been on my radar for a few years.
&lt;/p&gt;&lt;p&gt;
It's very enjoyable, and overall, a very nice language.
&lt;/p&gt;&lt;p&gt;
I will do a proper &amp;quot;review&amp;quot; of it once I finish the tetris clone, mostly likely in the coming week.
&lt;/p&gt;</content></entry><entry><title>Surflog:</title><id>https://aloysberger.com/2026-10-11-18-42.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-11T18:42:00Z</updated><link href="https://aloysberger.com/2026-10-11-18-42.html" rel="alternate" /><content type="html">&lt;p&gt;
A friend gifted me a shortboard, and man, it is a different sport from longboarding!
It's fun, but the technique is very different: the drop in is much later and deeper.
You need bigger and steeper waves.
So far I can't really surf it; I'm mostly getting wiped out - but I'm having a ball.
I still love longboarding, but I can see myself picking up the shortboard this summer as the swell builds up.
&lt;/p&gt;</content></entry><entry><title>Book review: 451 Fahrenheit by Ray Bradbury</title><id>https://aloysberger.com/book-review-451-fahrenheit-by-ray-bradbury.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-10-02T09:20:00Z</updated><link href="https://aloysberger.com/book-review-451-fahrenheit-by-ray-bradbury.html" rel="alternate" /><content type="html">&lt;p&gt;
This is a rather short book from Ray Bradbury. I had never heard about it, but it seems quite popular.
It's in the line of 1984 by George Orwell.
&lt;/p&gt;&lt;p&gt;
The novel is taking place in a dystopian future where the state &amp;quot;enslave&amp;quot; their citizens by destroying knowledge and promoting a hedonic lifestyle.
&lt;/p&gt;&lt;p&gt;
The protagonist is a fireman. However, in this future, the firemen don't put fires down. Their jobs is to burn books.
Owning books is forbidden. In this world, knowledge is evil and ignorance is bliss.
Citizens numbs themselves by watching TV shows without any meaning. They wear portable audio devices (i.e. earbuds!) pouring endless ads in their ears around the clock. Then, they take pills to get to sleep. They don't think for themselves - they don't even remember much about who they are.
&lt;/p&gt;&lt;p&gt;
The book was written in 1953 (!), and it gave me an eerie feeling of similarity with some of what is happening in the current world.
We put convenience and pleasure at the top of our priorities to the detriment of the pursuit of harder, more tenuous but also more rewarding activities.
&lt;/p&gt;&lt;p&gt;
It reminds me of the current mindset around LLMs.
We celebrate ignorance: &amp;quot;Look, I don't even know how to do X, yet I made Y. How great!&amp;quot;.
&lt;/p&gt;&lt;p&gt;
The Greek had a word for this, &lt;i&gt;Amathia&lt;/i&gt;, which means &amp;quot;willful ignorance&amp;quot;. I believe it is a very slippery slope.
&lt;/p&gt;&lt;p&gt;
I won't spoil the end of the book; however after the last few pages we can only wonder if this ignorance was worldwide, or if the protagonists lived in an ignorance prison which prevented them from seeking a better way to live.
&lt;/p&gt;&lt;p&gt;
I highly enjoyed the book. I am especially impressed with the creativity of the writer, and how 73 years later it is still relevant.
&lt;/p&gt;</content></entry><entry><title>Enjoyment grows with skills</title><id>https://aloysberger.com/2026-09-29-17-51.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-09-29T17:51:00Z</updated><link href="https://aloysberger.com/2026-09-29-17-51.html" rel="alternate" /><content type="html">&lt;p&gt;
Today I was reflecting on the enjoyment we draw from activities.
Enjoyment tends to grow with skills: the better you are at something, the more enjoyable it becomes.
I have observed this with my own person across a wide range of activities, including extremely mundane and/or repetitive ones.
&lt;/p&gt;&lt;p&gt;
I find that the mindset really matters: when we suck at something, forcing ourselves to enjoy the learning curve is very important.
Over time, as skills build, we can get more creative with the activity, get in the flow, or enjoy the new skills acquired.
&lt;/p&gt;&lt;p&gt;
Smiling, when starting something and sucking at it, is a great trick.
&lt;/p&gt;&lt;p&gt;
I have surfed on and off for the last 10 years, and frankly, I sucked at it for a very long time.
After deciding to invest time into it this year and surfing 3 to 5 times a week, my skills have grown a lot.
I still suck - and if I didn't enjoy sucking at it, I would have given up. However I stuck to it.
Today I can really enjoy longboarding and I am glad I didn't throw the towel.
&lt;/p&gt;&lt;p&gt;
I can't help but link this to the loss of joy I have with programming when using LLMs.
We trick ourselves in trying to jump over the learning phase, and there is little joy in it.
&lt;/p&gt;&lt;p&gt;
Using it for areas I would consider myself an expert, such as React, is not as damaging.
&lt;/p&gt;&lt;p&gt;
[I am putting my thoughts on the screen as they appear - so this is a bit of an omelette of ideas!]
&lt;/p&gt;</content></entry><entry><title>Finished the first &quot;section&quot; of OSTEP: CPU virtualisation</title><id>https://aloysberger.com/2026-09-22-20-12.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-09-22T20:12:00Z</updated><link href="https://aloysberger.com/2026-09-22-20-12.html" rel="alternate" /><content type="html">&lt;p&gt;
OSTEP (OS in three easy pieces) is a great read so far; I have learnt a lot through the first section which covers CPU virtualisation and scheduler. I am excited to get into the section about file systems and memory.
&lt;/p&gt;</content></entry><entry><title>Working on the &quot;thing&quot; is not doing the &quot;thing&quot;</title><id>https://aloysberger.com/2026-09-21-11-16.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-09-21T11:16:00Z</updated><link href="https://aloysberger.com/2026-09-21-11-16.html" rel="alternate" /><content type="html">&lt;p&gt;
I have done extensive work on the blog and my &amp;quot;microblog&amp;quot; section was out of order.
I fell into the typical trap where ones spends more time tweaking the blog than actually writing!
&lt;/p&gt;</content></entry><entry><title>Replacing elfeed with newsticker (built-in)</title><id>https://aloysberger.com/replacing-elfeed-with-newsticker-built-in.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-09-15T17:11:00Z</updated><link href="https://aloysberger.com/replacing-elfeed-with-newsticker-built-in.html" rel="alternate" /><content type="html">&lt;div id=&quot;outline-container-org11d8f5a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org11d8f5a&quot;&gt;Intro: Are my decisions, mine?&lt;/h2&gt;
&lt;div id=&quot;text-org11d8f5a&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
&lt;i&gt;Skip this if you are only here of the Emacs bits!&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
The other day someone asked me what I chose &lt;code&gt;caddy&lt;/code&gt; over &lt;code&gt;nginx&lt;/code&gt; for my reverse proxy.
&lt;/p&gt;

&lt;p&gt;
That's a great question, why?
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;Caddy&lt;/code&gt; has some great quality-of-life features, such as configuring TLS out of the box for you whereas &lt;code&gt;nginx&lt;/code&gt; does not.
&lt;/p&gt;

&lt;p&gt;
But how hard is it to configure TLS? Well, I wouldn't know. I never used &lt;code&gt;nginx&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
And here is the interesting part. Why did I choose &lt;code&gt;caddy&lt;/code&gt;, if it solves a pain I never felt?
&lt;/p&gt;

&lt;p&gt;
The truth is, I didn't choose &lt;code&gt;caddy&lt;/code&gt;; I let others choose it for me.
&lt;/p&gt;

&lt;p&gt;
I read online somewhere that someone was using &lt;code&gt;caddy&lt;/code&gt;, and simply followed.
&lt;/p&gt;

&lt;p&gt;
And this prevented me from investing a few hours in understanding how to setup TLS for a domain using an ubiquitous and trusted, widely available technology.
&lt;/p&gt;

&lt;p&gt;
It's intriguing that I went straight to get the  solution to a problem I didn't have.
&lt;/p&gt;

&lt;p&gt;
In this case, it is not an issue: &lt;code&gt;caddy&lt;/code&gt; is a great tool.
&lt;/p&gt;

&lt;p&gt;
But it made me wonder: how often my thoughts are truly mine? How often my decision are mine?
&lt;/p&gt;

&lt;p&gt;
I consume tons of information. I read a lot. Listen to many podcasts.
&lt;/p&gt;

&lt;p&gt;
It feels like thinking, but is it? I am not so sure.
&lt;/p&gt;

&lt;p&gt;
I want to cultivate my critical thinking. I believe it's a muscle that is easy to not exercise in our modern world.
&lt;/p&gt;

&lt;p&gt;
For the last few months, I have started to really try to protect my thinking space fiercely.
&lt;/p&gt;

&lt;p&gt;
For example I turned off comments on Youtube by default. I avoid listening to podcast first thing in the morning.
I write a book review before looking at what others think of the book.
&lt;/p&gt;

&lt;p&gt;
I want to force myself to think before yielding my thinking to some strangers online.
&lt;/p&gt;

&lt;p&gt;
This is my frame of mind for deciding to give &lt;code&gt;newstickers&lt;/code&gt; a go rather than using &lt;code&gt;elfeed&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orge76bfd9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orge76bfd9&quot;&gt;My newsticker configuration&lt;/h2&gt;
&lt;div id=&quot;text-orge76bfd9&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
This is my configuration:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;olivetti-mode&lt;/code&gt; is enabled (it centers the text, a.k.a. 'Zen mode'&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.1&quot; href=&quot;#fn.1&quot; class=&quot;footref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;), and the article window is selected.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;variable-pitch-mode&lt;/code&gt; is enabled to improve readability.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TAB&lt;/code&gt; and &lt;code&gt;S-TAB&lt;/code&gt; are set to jump to links (and back). Once on a link, &lt;code&gt;Enter&lt;/code&gt; will open the link at point in &lt;code&gt;eww&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;q&lt;/code&gt; is set to &lt;code&gt;newsticker-treeview-quit&lt;/code&gt; everywhere, so all newstickers buffers are closed.&lt;/li&gt;
&lt;li&gt;the mode-line are hidden to remove distraction. I have thin borders to keep each window distinct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I played with the idea of modifying &lt;code&gt;newsticker--treeview-window-init&lt;/code&gt; to use vertical panes for the list of articles to mimick &lt;code&gt;elfeed&lt;/code&gt;, but in the end I prefer the layout proposed by &lt;code&gt;newstickers&lt;/code&gt;. It is a bit on the heavy side
&lt;/p&gt;

&lt;p&gt;
Now I hit &lt;code&gt;&amp;quot;C-c e e&amp;quot;&lt;/code&gt; and &lt;code&gt;newstickers&lt;/code&gt; opens.
I use &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;F&lt;/code&gt; to selected my next or previous feed.
&lt;code&gt;n&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt; to select the next article of the current feed, or &lt;code&gt;N&lt;/code&gt; to select the next unread of any feed.
Finally, I can use &lt;code&gt;i&lt;/code&gt; to mark an article as &amp;quot;immortal&amp;quot; so it is never removed.
&lt;/p&gt;

&lt;p&gt;
This does everything I need from my RSS feed.
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(use-package newsticker
  :bind
  ((&amp;quot;C-c e e&amp;quot; . #'newsticker-show-news))
  :hook
  ((newsticker-treeview-item-mode . my/setup-newsticker)
    ((newsticker-treeview-mode
       newsticker-treeview-list-mode
       newsticker-treeview-item-mode) . my/hide-mode-line))
  :preface
  (defun my/hide-mode-line ()
    (setq mode-line-format nil))
  (defun my/setup-newsticker()
    (olivetti-mode)
    (variable-pitch-mode)
    ;; Focus on the article window
    (select-window (newsticker--treeview-item-window)))
  :config
  ;; Set the key TAB and S-TAB to be bound to shr-next-link and shr-previous-link to cycle through links easily
  (keymap-set newsticker-treeview-item-mode-map &amp;quot;TAB&amp;quot; #'shr-next-link)
  (keymap-set newsticker-treeview-item-mode-map &amp;quot;&amp;lt;backtab&amp;gt;&amp;quot; #'shr-previous-link)
  ;; set q to quit tree view (I only use tree view)
  (keymap-set newsticker-mode-map &amp;quot;q&amp;quot; #'newsticker-treeview-quit)
  ;; hide the mode line on newsticker-mode and newsticker-treeview-mode
  (add-to-list 'display-buffer-alist
    '((or (derived-mode . newsticker-mode)
          (derived-mode . newsticker-treeview-mode))
       (display-buffer-use-some-window)
       (window-parameters . ((mode-line-format . none)))))
  :custom
  (newsticker-automatically-mark-items-as-old nil) ;; Only mark as old (read) when opened
  (newsticker-url-list
    '((&amp;quot;Derek Sivers&amp;quot; &amp;quot;https://sive.rs/en.atom&amp;quot;)
       (&amp;quot;Drew DeVault's blog&amp;quot; &amp;quot;https://drewdevault.com/blog/index.xml&amp;quot;)
       (&amp;quot;Fritz Gabo&amp;quot; &amp;quot;https://fritzgrabo.com/posts/rss.xml&amp;quot;)
       (&amp;quot;Joshua Blais&amp;quot; &amp;quot;https://joshblais.com/index.xml&amp;quot;)
       (&amp;quot;mccd.space&amp;quot; &amp;quot;https://mccd.space/feed.xml&amp;quot;)
       (&amp;quot;Ploum&amp;quot; &amp;quot;https://ploum.net/atom_en.xml&amp;quot;)
       (&amp;quot;Ratfactor Feed&amp;quot; &amp;quot;https://ratfactor.com/atom.xml&amp;quot;)
       (&amp;quot;Sophie Koonin&amp;quot; &amp;quot;https://localghost.dev/feed.xml&amp;quot;)
       (&amp;quot;Sourcery Zone&amp;quot; &amp;quot;https://sourcery.zone/index.xml&amp;quot;)
       (&amp;quot;Xenodium, solopreneur and emacs&amp;quot; &amp;quot;https://xenodium.com/rss&amp;quot;)
       (&amp;quot;マリウス&amp;quot; &amp;quot;https://xn--gckvb8fzb.com/index.xml&amp;quot;)
       (&amp;quot;James Cherti&amp;quot; &amp;quot;https://www.jamescherti.com/feed/&amp;quot;)
       (&amp;quot;Planet Emacslife&amp;quot; &amp;quot;https://planet.emacslife.com/atom.xml&amp;quot;)
       (&amp;quot;Wai Hon's Blog&amp;quot; &amp;quot;https://whhone.com/index.xml&amp;quot;))))

&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;
Thank you for reading,
Aloys.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.1&quot; href=&quot;#fnr.1&quot; class=&quot;footnum&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;Surely I could write my own Olivetti?&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;</content></entry><entry><title>Increase the TTY font on Asahi Linux</title><id>https://aloysberger.com/increase-the-tty-font-on-asahi-linux.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-09-11T17:31:00Z</updated><link href="https://aloysberger.com/increase-the-tty-font-on-asahi-linux.html" rel="alternate" /><content type="html">&lt;p&gt;
My personal laptop is a Macbook M1 running &lt;a href=&quot;https://asahilinux.org/&quot;&gt;Asahi linux&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
When starting the laptop, the font on the TTY is ridiculously small, as the resolution of the screen is very high.
&lt;/p&gt;&lt;p&gt;
I wanted to use a bigger font, and this is how I solved the issue.
&lt;/p&gt;&lt;div id=&quot;outline-container-org82a24be&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org82a24be&quot;&gt;Find a font and try it out&lt;/h2&gt;
&lt;div id=&quot;text-org82a24be&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
The first step is to find the fonts installed on your system.
You can find them in &lt;code&gt;/usr/lib/kbd/consolefonts&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Most fonts will have an indication of the size in their name, the number representing the size.
&lt;/p&gt;

&lt;p&gt;
For example &lt;code&gt;latarcybheb-sun16&lt;/code&gt; would be 16px high, as opposed to &lt;code&gt;latarcybheb-sun32&lt;/code&gt; being 32px.
&lt;/p&gt;

&lt;p&gt;
You can try the font out by jumping into another TTY via &lt;code&gt;Ctrl + Alt + F&amp;lt;n&amp;gt;&lt;/code&gt; where &lt;code&gt;&amp;lt;n&amp;gt;&lt;/code&gt; is the TTY number, e.g. &lt;code&gt;Ctrl + Alt + F2&lt;/code&gt; will switch to the second TTY&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.1&quot; href=&quot;#fn.1&quot; class=&quot;footref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;

&lt;p&gt;
Then type &lt;code&gt;setfont &amp;lt;my-font&amp;gt;&lt;/code&gt; to try out a font. Replace &lt;code&gt;&amp;lt;my-font&amp;gt;&lt;/code&gt; with the desired font, such as:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;setfont latarcyrheb-sun32
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org716c26e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org716c26e&quot;&gt;Set the font permanently&lt;/h2&gt;
&lt;div id=&quot;text-org716c26e&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
In order to set the font permanently you need to edit two files:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;The configuration file for the virtual console (&lt;code&gt;man 5 vconsole.conf&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Modify and Regenerate the GRUB configuration file (&lt;code&gt;man grub-mkconfig&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf31289a&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf31289a&quot;&gt;Virtual configuration file&lt;/h3&gt;
&lt;div id=&quot;text-orgf31289a&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
In &lt;code&gt;/etc/vconsole.conf&lt;/code&gt;, modify the &lt;code&gt;FONT&lt;/code&gt; variable such as:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;KEYMAP=&amp;quot;us&amp;quot;
FONT=&amp;quot;latarcyrheb-sun32&amp;quot; # &amp;lt;-- the chosen font
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org816dea6&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org816dea6&quot;&gt;Grub configuration file&lt;/h3&gt;
&lt;div id=&quot;text-org816dea6&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
In &lt;code&gt;/etc/default/grub&lt;/code&gt;, append to &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/code&gt; &lt;code&gt;&amp;quot;vconsole.font=&amp;lt;my-font&amp;gt;&amp;quot;&lt;/code&gt; such as:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GRUB_DISABLE_SUBMENU=true
GRUB_DISABLE_RECOVERY=true
GRUB_DISABLE_OS_PROBER=true
GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;rootflags=subvol=root vconsole.font=latarcyrheb-sun32&amp;quot; #&amp;lt;-- Append the font chosen here
GRUB_DISTRIBUTOR=&amp;quot;Fedora Linux Asahi Remix&amp;quot;
GRUB_ENABLE_BLSCFG=true
GRUB_GFXMODE=auto
GRUB_TERMINAL_INPUT=&amp;quot;console&amp;quot;
GRUB_TERMINAL_OUTPUT=&amp;quot;gfxterm&amp;quot;
GRUB_TIMEOUT=5
GRUB_TIMEOUT_STYLE=menu
GRUB_DEFAULT=saved
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Then regenerate the configuration by running &lt;code&gt;grub2-mkconfig&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
That's it! Now reboot your system and you should see the new font configuration.
&lt;/p&gt;

&lt;p&gt;
I chose &lt;code&gt;latarcybheb-sun32&lt;/code&gt; as it is large enough to read, and look standard.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.1&quot; href=&quot;#fnr.1&quot; class=&quot;footnum&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;TIL, this is a pretty handy tip!&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;</content></entry><entry><title>Chrono Trigger</title><id>https://aloysberger.com/2026-09-01-07-17.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-09-01T07:17:00Z</updated><link href="https://aloysberger.com/2026-09-01-07-17.html" rel="alternate" /><content type="html">&lt;p&gt;
I finished Chrono Trigger this weekend.
I am not a gamer, but we purchased a gameboy / NES emulator a few months back and it has been a great source of entertainment; even tough sometimes, it sits on the shelf for weeks without being touched.
&lt;/p&gt;&lt;p&gt;
I picked up Chrono Trigger about two months ago, and it has been an absolute joy to play it.
The game is over 30 years old! It aged beautifully.
&lt;/p&gt;&lt;p&gt;
I beat the game this weekend but I am sure I will give it another go in the future.
&lt;/p&gt;</content></entry><entry><title>Friction and constraints are good.</title><id>https://aloysberger.com/2026-08-24-18-33.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-24T18:33:00Z</updated><link href="https://aloysberger.com/2026-08-24-18-33.html" rel="alternate" /><content type="html"></content></entry><entry><title>Adding syntax highlighting to my blog via Haunt and guile-syntax-highlight: challenging!</title><id>https://aloysberger.com/2026-08-21-19-38.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-21T19:38:00Z</updated><link href="https://aloysberger.com/2026-08-21-19-38.html" rel="alternate" /><content type="html">&lt;p&gt;
Challenging, but slowly getting there.
There is not other way but to read the source code.
&lt;/p&gt;&lt;p&gt;
Scheme is starting to click, and reading it is becoming easier everyday.
It's growing on me.
&lt;/p&gt;</content></entry><entry><title>Emacs is the gift that keeps on giving</title><id>https://aloysberger.com/2026-08-19-12-23.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-19T12:23:00Z</updated><link href="https://aloysberger.com/2026-08-19-12-23.html" rel="alternate" /><content type="html">&lt;p&gt;
The learning curve of emacs was quite steep; in a way, steeper than (neo)vim.
Vim is clearly an editor, whereas emacs is a lisp interpreter with text editing capabilities.
&lt;/p&gt;&lt;p&gt;
This makes its footprint much larger, making the upfront learning cost higher.
&lt;/p&gt;&lt;p&gt;
However, it seems to make its reward comparatively higher as emacs and elisp start to &lt;i&gt;click&lt;/i&gt;.
&lt;/p&gt;&lt;p&gt;
I absolutely enjoy it, and rarely open vim these days.
&lt;/p&gt;</content></entry><entry><title>AI;DR: AI; Didn't read</title><id>https://aloysberger.com/2026-08-18-07-55.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-18T07:55:00Z</updated><link href="https://aloysberger.com/2026-08-18-07-55.html" rel="alternate" /><content type="html">&lt;p&gt;
&lt;a href=&quot;https://www.rickmanelius.com/p/aidr-ai-didnt-read&quot;&gt;Rick Manelius on reading AI material.&lt;/a&gt;
Whatever your stance is on generative AI, this is relevant.
I totally follow the AI;DR policy.
&lt;/p&gt;&lt;p&gt;
If it's not worth the time writing, it's not worth the time reading.
&lt;/p&gt;</content></entry><entry><title>Writing a Guix service from scratch, as a beginner</title><id>https://aloysberger.com/writing-a-guix-service-from-scratch-as-a-beginner.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-17T22:29:00Z</updated><link href="https://aloysberger.com/writing-a-guix-service-from-scratch-as-a-beginner.html" rel="alternate" /><content type="html">&lt;p&gt;
I am in the middle of migrating my machines from NixOS to Guix.
&lt;/p&gt;&lt;p&gt;
My first milestone is to migrate my VPS to Guix.
&lt;/p&gt;&lt;p&gt;
My VPS has essentially three majors roles:
&lt;/p&gt;&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;host my email server.&lt;/li&gt;
&lt;li&gt;host my wireguard server.&lt;/li&gt;
&lt;li&gt;act as a proxy server to access services on my home server (thus, hiding my home IP).&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;
The mail server is up and running, using exim as the MTA and dovecot as the IMAP server.
I had to jump through a few hoops to get exim up and running.
I would have preferred postfix over exim, but only exim is available out of the box on the official Guix channel.
&lt;/p&gt;&lt;p&gt;
At the time, I didn't know how to define my own custom services.
I intend to use Guix for the foreseeable future, I want to build a deep understanding of it.
Learning to create my own services, suited to my own needs, is an important part of mastering Guix.
&lt;/p&gt;&lt;p&gt;
Which brings us to the motivation behind this article:  the time had come to create my own service.
&lt;/p&gt;&lt;p&gt;
For the proxy server, I enjoy using Caddy.
Caddy isn't available as a service on Guix.&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.1&quot; href=&quot;#fn.1&quot; class=&quot;footref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;&lt;p&gt;
This seems like the perfect time to finally dive into custom services.
&lt;/p&gt;&lt;p&gt;
As I navigated my way through the docs and the source code, I decided to document my learning and share it here, as guide for other newcomers.
&lt;/p&gt;&lt;p&gt;
In this article, we will be writing a custom service for our Caddy reverse proxy.
&lt;/p&gt;&lt;p&gt;
This service involves setting up a configuration file for Caddy via Guix, creating a system user and configuring Shepherd to run the daemon.
&lt;/p&gt;&lt;p&gt;
It's a perfect first custom service: t is simple enough to ease into custom services, yet it includes a good overview of them.
&lt;/p&gt;&lt;p&gt;
Furthermore, most of the services I run on my home server are essentially a combination of those three actions: configure users, manage configuration files and run the daemon.
&lt;/p&gt;&lt;div id=&quot;outline-container-orgf38ff2b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgf38ff2b&quot;&gt;Who is this for?&lt;/h2&gt;
&lt;div id=&quot;text-orgf38ff2b&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
This article is suitable to Guix newcomers and beginners.
As a matter of fact, I wrote this as I went along, stumbling my way through it, without any extensive knowledge beyond reading the documentation.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org296bc22&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org296bc22&quot;&gt;Pre-requirements&lt;/h2&gt;
&lt;div id=&quot;text-org296bc22&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
The only true prerequisite is to have the Caddy package ready to go on your Guix instance, so we can build the service on top of it.
At the time of writing this blog, the Guix repository doesn't contain the Caddy package but the team is working on it.
&lt;/p&gt;

&lt;p&gt;
In the meantime, you can follow my &lt;a href=&quot;https://aloysberger.com/posts/guix-packaging-a-binary-as-a-guix-beginner.html&quot;&gt;blog post to create one easily&lt;/a&gt;. It only takes a few lines of code.
&lt;/p&gt;

&lt;p&gt;
You don't need to have a high proficiency or deep expertise in Scheme (I certainly don't), but a basic understanding of it is highly recommended.
&lt;/p&gt;

&lt;p&gt;
I assume that you are, like me, fairly new to Guix - however this isn't a replacement to the documentation.
I will be paraphrasing the documentation a lot with my own interpretation of it.
I encourage you to keep the documentation on the side while following this article.
&lt;/p&gt;

&lt;p&gt;
I obviously assume that you have Guix installed and a working configuration. 
If not, you can find one &lt;a href=&quot;https://guix.gnu.org/manual/devel/en/html_node/Using-the-Configuration-System.html&quot;&gt;here.&lt;/a&gt; 
&lt;/p&gt;

&lt;p&gt;
Finally, you need to know how to reconfigure your system (hint: &lt;code&gt;sudo guix system reconfigure my-config.scm&lt;/code&gt;).
&lt;/p&gt;

&lt;p&gt;
When I reference the Guix source code, I will use the notation &lt;code&gt;file-name:line&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org606e688&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org606e688&quot;&gt;The plan&lt;/h2&gt;
&lt;div id=&quot;text-org606e688&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
Alright, with this out the way, let's talk about what we are concretely going to build here.
&lt;/p&gt;

&lt;p&gt;
In order to keep things as simple as possible, I decided to define our service to be as simple and bare-bones as possible.
&lt;/p&gt;

&lt;p&gt;
Our plan will be as follow:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Define an empty service, and successfully &amp;quot;enable&amp;quot; it.&lt;/li&gt;
&lt;li&gt;Create the dameon user and group..&lt;/li&gt;
&lt;li&gt;Copy the Caddy configuration to the right location.&lt;/li&gt;
&lt;li&gt;Configure Shepherd to run the service as a daemon in the background.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
This is the bare mininum Caddy service; it will do the job, but it won't be the most elegant.
&lt;/p&gt;

&lt;p&gt;
Most of the configuration options will be hard coded; the service won't be ready to be distributed.
However, it will be functional and fulfill our needs.
&lt;/p&gt;

&lt;p&gt;
Once completed, we can expect to have accumulated enough knowledge along the way to revisit, refactor and improve it.
&lt;/p&gt;

&lt;p&gt;
As soon as this article is out, I plan on improving it and if I feel brave, I might even propose it to the Guix repository.
&lt;/p&gt;

&lt;p&gt;
But for now, let's stick to the basics. We don't want to let perfection get in the way of done.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3637281&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3637281&quot;&gt;What is a service?&lt;/h3&gt;
&lt;div id=&quot;text-org3637281&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
The documentation defines a service as &amp;quot;&lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Service-Composition.html&quot;&gt;something that extends the functionality of the operating system&lt;/a&gt;&amp;quot;.
&lt;/p&gt;

&lt;p&gt;
This definition is quite vague, but that's because a service can have a wide variety of functionalities.
The most obvious type of a service is a daemon running a process in the background (our case), but it's not the only type of service.
&lt;/p&gt;

&lt;p&gt;
As we will see, a service can be a process which is run once, such as creating accounts or copying files to the store.
It can be a recurring process, such as a cron job.
&lt;/p&gt;

&lt;p&gt;
In a way, it is a primitive to configure our system in a declarative manner.
&lt;/p&gt;

&lt;p&gt;
One interesting aspect of services, is that they are designed from the ground up to be extensible and composable.
A service can extends one or more services, and can itself be extended by one or more services.
We will dive a deeper on that subject further below; I find this architecture fantastic.
&lt;/p&gt;

&lt;p&gt;
You can read more about services in the &lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Service-Composition.html&quot;&gt;documentation&lt;/a&gt;.
If you still don't quite understand the concept of services,, it's completely normal.
It didn't click for me until I started writing this Caddy service.
&lt;/p&gt;

&lt;p&gt;
So if you don't fully grasp what a service is yet, follow along, it will make more sense as we progress.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org4950302&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org4950302&quot;&gt;1. Define an empty service&lt;/h2&gt;
&lt;div id=&quot;text-org4950302&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
Our first step is to break the ice by creating the simplest service we can: a bare service that does nothing.
The goal is just to get familiar with services.
&lt;/p&gt;

&lt;p&gt;
First, we need to define the service type of our service.
&lt;/p&gt;

&lt;p&gt;
A service type is essentially a blueprint for a service.
Think of it as what a class is to an instantiated object.
&lt;/p&gt;

&lt;p&gt;
A service is enabled or &amp;quot;instantiated&amp;quot; (if we keep our analogy of classes) by the &lt;code&gt;service&lt;/code&gt; procedure.
The &lt;code&gt;service&lt;/code&gt; procedure takes as an argument a &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; record and a value.
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;my-service-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;my-service-value&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
If a value isn't provided, the &lt;code&gt;default-value&lt;/code&gt; defined in the &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; definition is used.
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;my-service-type&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; this service is using the default-value defined in &amp;lt;my-service-type&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
To enable the &lt;code&gt;service&lt;/code&gt;, we add it to the list provided to the &lt;code&gt;services&lt;/code&gt; procedure:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;services&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;my-service-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;my-service-value&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%base-services&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Now let's look inside the &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; record.
&lt;/p&gt;

&lt;p&gt;
You can find the definition of &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; in &lt;code&gt;gnu/services.scm:187&lt;/code&gt;.
The service type is well documented, but grepping the codebase is very valuable tool when working with Guix (or any
other software if you ask me!).
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define-record-type*&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;&amp;lt;service-type&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;make-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;service-type?&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt;       &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-name&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                  &lt;span class=&quot;syntax-comment&quot;&gt;;symbol (for debugging)
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; Things extended by services of this type.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-extensions&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;syntax-comment&quot;&gt;;list of &amp;lt;service-extensions&amp;gt;
&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; Given a list of extensions, &amp;quot;compose&amp;quot; them.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;compose&lt;/span&gt;    &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-compose&lt;/span&gt;                &lt;span class=&quot;syntax-comment&quot;&gt;;list of Any -&amp;gt; Any
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Extend the services' own parameters with the extension composition.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend&lt;/span&gt;     &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-extend&lt;/span&gt;                 &lt;span class=&quot;syntax-comment&quot;&gt;;list of Any -&amp;gt; parameters
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Optional default value for instances of this type.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-default-value&lt;/span&gt;       &lt;span class=&quot;syntax-comment&quot;&gt;;Any
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;&amp;amp;no-default-value&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Meta-data.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-description&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;         &lt;span class=&quot;syntax-comment&quot;&gt;;string
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;location&lt;/span&gt;     &lt;span class=&quot;syntax-symbol&quot;&gt;service-type-location&lt;/span&gt;             &lt;span class=&quot;syntax-comment&quot;&gt;;&amp;lt;location&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;and=&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;current-source-location&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;syntax-symbol&quot;&gt;source-properties-&amp;gt;location&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;innate&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
We notice that the &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; requires a &lt;code&gt;name&lt;/code&gt; and a list of &lt;code&gt;extensions&lt;/code&gt;.
It also contains optional fields: &lt;code&gt;compose&lt;/code&gt;, &lt;code&gt;extend&lt;/code&gt;, &lt;code&gt;default-value&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;location&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Let's define our &lt;code&gt;caddy-service-type&lt;/code&gt;.
We set the name of our service to &lt;code&gt;'caddy&lt;/code&gt;.
We also set the &lt;code&gt;extensions&lt;/code&gt; to &lt;a href=&quot;https://doc.guix.gnu.org/guile/latest/en/html_node/Nil.html&quot;&gt;nil&lt;/a&gt; (the empty list), which means that we aren't extending any existing services for now.
We also leave the &lt;code&gt;default-value&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Regarding the optional fields, let's only care about the &lt;code&gt;description&lt;/code&gt; for now. It takes a &lt;code&gt;string&lt;/code&gt; and is used for - you guessed it - the description.
&lt;/p&gt;

&lt;p&gt;
I will cover the &lt;code&gt;compose&lt;/code&gt;, &lt;code&gt;extend&lt;/code&gt; and &lt;code&gt;extensions&lt;/code&gt; fields later, let's not worry about them for now.
&lt;/p&gt;

&lt;p&gt;
Our &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; for our Caddy service looks like this:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'caddy&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; an empty list
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Caddy is an extensible server platform that uses TLS by default.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
That's it. This is the simplest service type: it only has a name and a description.
&lt;/p&gt;

&lt;p&gt;
Let's enable it by adding it to the &lt;code&gt;services&lt;/code&gt; procedure.
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; config.scm
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-modules&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;gnu&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-service-modules&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;networking&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ssh&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-package-modules&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;ssh&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;operating-system&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;host-name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;timezone&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;locale&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bootloader&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;file-systems&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;packages&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;services&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;....&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;;; Pre-existing services
&lt;/span&gt;                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy-service-type&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; &amp;lt;-- Add this line here
&lt;/span&gt;              &lt;span class=&quot;syntax-symbol&quot;&gt;%base-services&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;syntax-comment&quot;&gt;;; %base-services are the default services
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Now, run &lt;code&gt;sudo guix system reconfigure config.scm&lt;/code&gt; and celebrate your first custom service.
&lt;/p&gt;

&lt;p&gt;
We &amp;quot;instantiated&amp;quot; a service of type &lt;code&gt;caddy-service-type&lt;/code&gt; without a value, defaulting to the default-value of &lt;code&gt;nil&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
It's not doing anything, but it still is a service.
&lt;/p&gt;

&lt;p&gt;
If you have a graphical display, you can run the following command to generate a graph of your system:
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;guix system extension-graph config.scm | guix shell xdot -- xdot -&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
You will notice that the Caddy service is present in your services.
Nice. Now let's make that service do something useful.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgeb62fa8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgeb62fa8&quot;&gt;2. Create the daemon user&lt;/h2&gt;
&lt;div id=&quot;text-orgeb62fa8&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
The next step to improve our service is to instruct it to create the &lt;code&gt;caddy&lt;/code&gt; user and group.
&lt;/p&gt;

&lt;p&gt;
It is always a good idea to create a non-root user to run a background process: if the process is compromised, the area of attack is much smaller.
&lt;/p&gt;

&lt;p&gt;
This user will:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Start the daemon.&lt;/li&gt;
&lt;li&gt;Have read access to the Caddy configuration file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
In order to create the user and group, we will use the power of &lt;code&gt;extensions&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Guix contains a large number of services out of the box; one of them is the &lt;code&gt;account-service-type&lt;/code&gt;.
This service is used to create users and groups on our operating system.
&lt;/p&gt;

&lt;p&gt;
In order to use that service, we will need to add it to the &lt;code&gt;extensions&lt;/code&gt; field of our &lt;code&gt;caddy-service-type&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;extensions&lt;/code&gt; field is a bit hard to grasp at first.
My first instinct was that the &lt;code&gt;extensions&lt;/code&gt; field allows you to modify your service by extending its own capability,
giving it extra functionality. For example, in this case, I expected that extending the &lt;code&gt;account-service-type&lt;/code&gt; would add the capability to create users and groups to our &lt;code&gt;caddy-service-type&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
However it is the opposite! You don't &amp;quot;add&amp;quot; capability to your service, you modify the target service (&lt;code&gt;account-service-type&lt;/code&gt; here) to perform actions for your service.
How the target service-type is modified is defined by the rules in its &lt;code&gt;compose&lt;/code&gt; and &lt;code&gt;extend&lt;/code&gt; fields. We'll go over them in more details further below.
&lt;/p&gt;

&lt;p&gt;
For now, let's continue on our account creation to illustrate this concept.
We want to create a user, &lt;code&gt;caddy&lt;/code&gt;, and a group with the same name, &lt;code&gt;caddy&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;account-service-type&lt;/code&gt; is defined as extendable. This means that it offers an interface for other services to create user accounts.
The &lt;code&gt;account-service-type&lt;/code&gt; doesn't need to know who is creating accounts and why; it only exposes a way to do so.
&lt;/p&gt;

&lt;p&gt;
This is the beauty of this architecture: it makes the system completely declarative.
When a service extends the &lt;code&gt;account-service-type&lt;/code&gt;, then Guix will create the accounts when the service is enabled.
If the service is not enabled, those accounts aren't created.
&lt;/p&gt;

&lt;p&gt;
It's a fantastic architecture when you think about it, it reminds me of the principle of &lt;i&gt;Inversion of Control&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
In order to instruct the &lt;code&gt;account-service-type&lt;/code&gt; to create our caddy user when the &lt;code&gt;caddy-service-type&lt;/code&gt; is enabled, we extend the &lt;code&gt;account-service-type&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
We now understand the concept of the &lt;code&gt;extensions&lt;/code&gt; field.
It allows you to 'extend' a target service-type to, for example, create more users.
But we still don't really know how to specify it in practice.
&lt;/p&gt;

&lt;p&gt;
We have a few ways of finding out set it up: reading the docs, grepping examples, or looking at the source.
&lt;/p&gt;

&lt;p&gt;
For the sake of getting better at understanding services, let's look at the source.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgeebed02&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgeebed02&quot;&gt;Deeper dive: extend and compose&lt;/h3&gt;
&lt;div id=&quot;text-orgeebed02&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
Being curious and eager to really assimilate how services extensions work, I tried find out if we can guess the shape of the accounts by looking at the &lt;code&gt;account-service-type&lt;/code&gt; service, defined in &lt;code&gt;shadow.scm:547&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
This is how the &lt;code&gt;account-service-type&lt;/code&gt; is defined. We should be familiar with the &lt;code&gt;&amp;lt;service-type&amp;gt;&lt;/code&gt; record structure.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;account-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'account&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Concatenate &amp;lt;user-account&amp;gt;, &amp;lt;user-group&amp;gt;, and skeleton
&lt;/span&gt;    &lt;span class=&quot;syntax-comment&quot;&gt;;; lists.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;compose&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;concatenate&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;activation-service-type&lt;/span&gt;
              &lt;span class=&quot;syntax-symbol&quot;&gt;account-activation&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;shepherd-root-service-type&lt;/span&gt;
          &lt;span class=&quot;syntax-symbol&quot;&gt;account-shepherd-service&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-comment&quot;&gt;;; Have 'user-processes' depend on 'user-homes' so that
&lt;/span&gt;        &lt;span class=&quot;syntax-comment&quot;&gt;;; daemons start after their home directory has been
&lt;/span&gt;        &lt;span class=&quot;syntax-comment&quot;&gt;;; created.
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;user-processes-service-type&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;user-homes&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;etc-service-type&lt;/span&gt;
          &lt;span class=&quot;syntax-symbol&quot;&gt;etc-files&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt;
      &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Ensure the specified user accounts and groups exist, as well
as each account home directory.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
The first thing we can see, is that the &lt;code&gt;default-value&lt;/code&gt; is an empty list, which means that the &lt;code&gt;account-service-type&lt;/code&gt; itself is expecting a list as a value.
But a list of &lt;i&gt;what&lt;/i&gt;?
&lt;/p&gt;

&lt;p&gt;
In this case, the comments give us the answer: a list of &lt;code&gt;&amp;lt;user-account&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;user-group&amp;gt;&lt;/code&gt;.
If it was not for the comments, you could look at the &lt;code&gt;account-activation&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Before moving on, let's talk about &lt;code&gt;compose&lt;/code&gt; and &lt;code&gt;extend&lt;/code&gt; fields.
This is how they are defined in &lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Service-Types-and-Services.html&quot;&gt;the documentation&lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
&amp;gt; compose
&lt;/p&gt;

&lt;p&gt;
This is the procedure to compose the list of extensions to services of this type.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;
&amp;gt; extend
&lt;/p&gt;

&lt;p&gt;
This procedure defines how the value of the service is extended with the composition of the extensions.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
This is a bit vague and left me a bit scratching my head, but what it means is that:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;p&gt;
&lt;code&gt;Compose&lt;/code&gt; defines how to the service &lt;i&gt;composes&lt;/i&gt; multiple services &lt;i&gt;extending&lt;/i&gt; this service-type.
&lt;/p&gt;

&lt;p&gt;
For example,if we have three services listing &lt;code&gt;accounts-service-type&lt;/code&gt; as an extension, how do we handle each value?
Do we only take the first? The last?
&lt;/p&gt;

&lt;p&gt;
Obviously, if three services are defining users by extending the &lt;code&gt;account-service-type&lt;/code&gt;, we want to create all those users.
Therefore, we want to concatenate the values provided by the &lt;i&gt;extending&lt;/i&gt; services.
&lt;/p&gt;

&lt;p&gt;
We can imagine other services behaving differently. For example, let's imagine a service whose role is to manage a port.
Let's call it &lt;code&gt;open-port-22-service-type&lt;/code&gt;.
Let's also imagine that two services extend this service: one wants to &lt;i&gt;open&lt;/i&gt; the port, the other &lt;i&gt;close&lt;/i&gt; it.
&lt;/p&gt;

&lt;p&gt;
What shall we do? Open it, or close it? We have conflicting values.
&lt;/p&gt;

&lt;p&gt;
Maybe we want to err on the caution side and define &lt;code&gt;open-port-22-service-type&lt;/code&gt; to prioritise 'close' values if it receives contradicting values.
&lt;/p&gt;

&lt;p&gt;
That's what the &lt;code&gt;compose&lt;/code&gt; field is for. It defines how to &lt;code&gt;compose&lt;/code&gt; multiple extending service values.
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;Extend&lt;/code&gt; defines how the &lt;i&gt;composition&lt;/i&gt; from the &lt;code&gt;compose&lt;/code&gt; field interact with the service's value itself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
It is, in a way, quite similar to &lt;code&gt;compose&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
Let's imagine a service-type which displays a welcome message when the computer boots, called &lt;code&gt;welcome-message-service-type&lt;/code&gt;.
If a service extends it with a different message, we might want to give priority to the extending service value.
&lt;/p&gt;

&lt;p&gt;
In this case, we would use &lt;code&gt;extend&lt;/code&gt; to instruct the &lt;code&gt;welcome-message-service-type&lt;/code&gt; to replace its own value with the composed values from the extending services.
&lt;/p&gt;

&lt;p&gt;
Note that &lt;code&gt;compose&lt;/code&gt; and &lt;code&gt;extend&lt;/code&gt; accept procedures which takes the service itself as an argument. It gives the user a lot of freedom and power when defining the rules.
&lt;/p&gt;

&lt;p&gt;
Let's finish with the &lt;code&gt;user-account-service-type&lt;/code&gt; as a final example.
&lt;/p&gt;

&lt;p&gt;
In the case of users, we want to:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;code&gt;compose&lt;/code&gt;: concatenate the values to create all the users and groups received.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;extend&lt;/code&gt;: append to the service value. so we create all the users and groups received AND the ones specified by the &lt;code&gt;user-account-service-type&lt;/code&gt; service itself (remember that we can instantiate the service with a value).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Zooming back to the architecture, we can see that services are all built upon each other.
A service, when installed, will modify the services listed in its &lt;code&gt;extensions&lt;/code&gt; field.
Those will in turn modify the service-type of their own extensions.
&lt;/p&gt;

&lt;p&gt;
This &amp;quot;chain reaction&amp;quot; will continue until all services are collected in the &lt;code&gt;system-service-type&lt;/code&gt;,  which is the root of all services.
Under the hood, we end up with a collection of all our services in one, large, single structure.
I assume that this is conglomerate of services is then handled by Guix when configuring the system.
&lt;/p&gt;

&lt;p&gt;
Ok, we now know the &lt;code&gt;account-service-type&lt;/code&gt;:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Accept a list of &lt;code&gt;&amp;lt;user-account&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;user-group&amp;gt;&lt;/code&gt; records&lt;/li&gt;
&lt;li&gt;Concatenate any values received as per its &lt;code&gt;compose&lt;/code&gt; rule.&lt;/li&gt;
&lt;li&gt;Append the (concatenated) received values to its own value, as per the &lt;code&gt;extend&lt;/code&gt; rule.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgf368d73&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgf368d73&quot;&gt;Back to our &amp;lt;user-account&amp;gt; and &amp;lt;group-account&amp;gt;&lt;/h3&gt;
&lt;div id=&quot;text-orgf368d73&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
So, by either following in my 'deep dive', reading the documentation or looking up examples in the code base, we found out that our group and user are defined as a &lt;code&gt;&amp;lt;user-account&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;user-group&amp;gt;&lt;/code&gt; respectively.
&lt;/p&gt;

&lt;p&gt;
Both records can be found in &lt;code&gt;accounts.scm&lt;/code&gt; at line 71 and 90 respectively.
&lt;/p&gt;

&lt;p&gt;
We define our accounts like so:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-accounts&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;user-account&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Run the caddy daemon&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;system?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;;&amp;lt;-- the caddy user is a system user, not a real user
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;user-group&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;system?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Now  we can add them the  &lt;code&gt;account-service-type&lt;/code&gt; extension.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;extensions&lt;/code&gt; procedure accepts a list of &lt;code&gt;&amp;lt;service-extension&amp;gt;&lt;/code&gt;.
A &lt;code&gt;service-extension&lt;/code&gt; is a record that accept two parameters.
&lt;/p&gt;

&lt;p&gt;
The first is the name of the target &lt;code&gt;service-type&lt;/code&gt; . This is &lt;code&gt;account-service-type&lt;/code&gt; in our case.
The second parameter to a &lt;code&gt;service&lt;/code&gt;-extension is a procedure that takes the service itself (the current caddy service) and returns a list of object to extend the target service (&lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Service-Types-and-Services.html&quot;&gt;see documentation&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
The second parameter seems complicated, but it's simply a procedure that returns the &amp;quot;value&amp;quot; for the extension.
In our case, a list of user and group account.
You can imagine that using this second argument, we could create the user dynamically based on the value of our &lt;code&gt;caddy-service-type&lt;/code&gt; if we wanted make our service configurable. That's how configurable services are structured.
&lt;/p&gt;

&lt;p&gt;
Let's define our service-extension for the &lt;code&gt;account-service-type&lt;/code&gt; and add it to the &lt;code&gt;extension&lt;/code&gt; field.
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'caddy&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;account-service-type&lt;/span&gt;
                        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-accounts&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Caddy is an extensible server platform that uses TLS by default.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
We used &lt;code&gt;const&lt;/code&gt; here, which is the syntactic sugar for &lt;code&gt;(lambda(_)(%caddy-accounts))&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Alright, time to finally test it out!
&lt;/p&gt;

&lt;p&gt;
Run &lt;code&gt;sudo guix system reconfigure config.scm&lt;/code&gt; to apply our changes.
&lt;/p&gt;

&lt;p&gt;
Let's check the presence of the caddy user by running &lt;code&gt;sudo id caddy&lt;/code&gt;.
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; sudo id caddy
# uid=982(caddy) gid=976(caddy) groups=976(caddy)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Nice! Our &lt;code&gt;caddy&lt;/code&gt; user and group were created!
&lt;/p&gt;

&lt;p&gt;
What we have learned so far:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Services are 'things' that modify the system.&lt;/li&gt;
&lt;li&gt;Services can be extended and can extend other services.&lt;/li&gt;
&lt;li&gt;Services define how they can be extended, via the &lt;code&gt;compose&lt;/code&gt; and &lt;code&gt;extend&lt;/code&gt; fields.&lt;/li&gt;
&lt;li&gt;Services define the service they extend, via the &lt;code&gt;extensions&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;All services are eventually &amp;quot;collected&amp;quot; in the &lt;code&gt;system-service-type&lt;/code&gt;, the root service.&lt;/li&gt;
&lt;li&gt;We have learned to how to extend the &lt;code&gt;account-service-type&lt;/code&gt; to create a user and a group for our service.&lt;/li&gt;
&lt;li&gt;We have also learned to dig around the source code to learn more about services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Now let's see how we can write the config, the Caddy file, into &lt;code&gt;/etc/caddy&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org1deaf33&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org1deaf33&quot;&gt;3. Copy the caddy configuration file to the right location&lt;/h2&gt;
&lt;div id=&quot;text-org1deaf33&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
In order to keep matters simple, the &lt;code&gt;caddy-service-type&lt;/code&gt; will be static.
We will write the &lt;code&gt;Caddyfile&lt;/code&gt; manually and provide it to our Caddy service.
We won't be in charge of generating the &lt;code&gt;Caddyfile&lt;/code&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.2&quot; href=&quot;#fn.2&quot; class=&quot;footref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;

&lt;p&gt;
The Caddy service will simply be in charge of copying it to the right location.
&lt;/p&gt;

&lt;p&gt;
The target location for &lt;code&gt;Caddyfile&lt;/code&gt; is &lt;code&gt;/etc/caddy/caddy.conf&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
As before, we will be leveraging extensions to do so.
To execute an arbitrary procedure when a service is enabled, we can use the &lt;code&gt;activation-service-type&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Note that there is  a service doing exactly this task, the &lt;code&gt;etc-service-type&lt;/code&gt;.
However I believe that using the more general &lt;code&gt;activation-service-type&lt;/code&gt; for didactic purpose is a better choice.
It's a widely used service; a lot of the service in the Guix repository rely on it.
&lt;/p&gt;

&lt;p&gt;
The activation service is a service that is executed at activation of our service.
&lt;/p&gt;

&lt;p&gt;
Interestingly enough, I couldn't find much about it in the documentation, except in &lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Service-Types-and-Services.html&quot;&gt;this example.&lt;/a&gt;
Let's look at the source code instead.
&lt;/p&gt;

&lt;p&gt;
In &lt;code&gt;services.scm:792&lt;/code&gt; we get a bit more information:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;syntax-comment&quot;&gt;;; The activation service produces the activation script from the gexps it
&lt;/span&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; receives.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
We can also look at its definition &lt;code&gt;services.scm:776&lt;/code&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;activation-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'activate&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;boot-service-type&lt;/span&gt;
              &lt;span class=&quot;syntax-symbol&quot;&gt;gexps-&amp;gt;activation-gexp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;system-service-type&lt;/span&gt;
          &lt;span class=&quot;syntax-symbol&quot;&gt;activation-profile-entry&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;compose&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;second-argument&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt;
      &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Run @dfn{activation} code at boot time and upon
@command{guix system reconfigure} completion.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Alright, we see (from the comment and the lambda &lt;code&gt;gexps-&amp;gt;activation-gexp&lt;/code&gt;) that the value required by a service is a &lt;b&gt;G-Expression&lt;/b&gt; or &lt;b&gt;gexp&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
What is a gexp? A gexp, or g-exp, or G-expression&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.3&quot; href=&quot;#fn.3&quot; class=&quot;footref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; is a Guix  of staging code to be executed later in the build environment.
&lt;/p&gt;

&lt;p&gt;
If you know what a G-expression is, you can skip the next section.
If not, let's briefly introduce the concept of G-expression&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.4&quot; href=&quot;#fn.4&quot; class=&quot;footref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org79656db&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org79656db&quot;&gt;Shallow dive: G-exps&lt;/h3&gt;
&lt;div id=&quot;text-org79656db&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
I won't go to deep into the concept of G-exps; there is a lot to cover and it merits its own article.
We will keep a high level overview.
&lt;/p&gt;

&lt;p&gt;
To understand what G-expression are, you need to know that Guix runs in two environments.
&lt;/p&gt;

&lt;p&gt;
When building packages, the guix daemon creates something akin to containers.
They aren't quite containers, but the concept is close enough for our understanding.
&lt;/p&gt;

&lt;p&gt;
To ensure reproducibility, each package is built in its own &amp;quot;container&amp;quot;, which only includes the required inputs.
For this to happen, part of the code in package definition needs to be staged for later execution, inside that &amp;quot;container&amp;quot;.
G-expressions is how we staging code to be executed at build time.
&lt;/p&gt;

&lt;p&gt;
The two environments of Guix are often referred as:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;The &amp;quot;host&amp;quot; environment, in which we define packages and configurations (what we are doing here).&lt;/li&gt;
&lt;li&gt;The &amp;quot;build&amp;quot; environment, in which the Guix daemon is performing the actual build actions inside the &amp;quot;container&amp;quot;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
G-expressions are expressed with the &lt;code&gt;#~&lt;/code&gt; macro, such as  &lt;code&gt;#~( ;; this is a g-expression  ;; )&lt;/code&gt;.
Whenever you see the macro &lt;code&gt;#~&lt;/code&gt;, it means that the code inside the bracket will be executed later, inside the build &amp;quot;container&amp;quot;.
&lt;/p&gt;

&lt;p&gt;
Inside a G-exp, we can  evaluate some expressions using the &lt;code&gt;#$&lt;/code&gt; macro, or &lt;code&gt;ungexp&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
For example, let's have a look at this G-expression:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#$output&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/another/folder/path&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
In this instance, when the code is evaluated &lt;code&gt;#$output&lt;/code&gt; will be replaced (or &lt;code&gt;ungexp&lt;/code&gt;) and the expression will be:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/the/output/dir&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/another/folder/path&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
In concept, it's similar to the quasi-quote and comma in Scheme.
&lt;/p&gt;

&lt;p&gt;
As the G-expression is evaluated in a different environment, it will not have automatically access to the modules imported in the current environment.
In order to give the G-expression access to modules, we need to import them in the &amp;quot;build&amp;quot; environment in which the G-expression will be evaluated.
&lt;/p&gt;

&lt;p&gt;
To do so, we use the &lt;code&gt;with-imported-modules&lt;/code&gt; syntax like so:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-imported-modules&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;begin&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-modules&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir-p&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/the/output/dir&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;;mkdir-p is a utility found in guix build utils.
&lt;/span&gt;      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir-p&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/another/folder/path&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
In the example above, &lt;code&gt;mkdir-p&lt;/code&gt; is a procedure from in &lt;code&gt;guix/build/utils.scm&lt;/code&gt;.
The &lt;code&gt;with-imported-modules&lt;/code&gt; provides the modules to the G-expression environment.
We can then use the standard &lt;code&gt;use-modules&lt;/code&gt; syntax as we would in a normal Scheme environment.
&lt;/p&gt;

&lt;p&gt;
There is a lot more to G-expressions, but it merits its own article so I won't go any further.
&lt;/p&gt;

&lt;p&gt;
This is all we need to know at this stage:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;G-expression is code staged to be executed in the &amp;quot;build&amp;quot; phase of Guix.&lt;/li&gt;
&lt;li&gt;G-expression are written with the &lt;code&gt;#~&lt;/code&gt; macro.&lt;/li&gt;
&lt;li&gt;We can &lt;code&gt;ungexp&lt;/code&gt; part of the G-expression with the &lt;code&gt;#$&lt;/code&gt; macro.&lt;/li&gt;
&lt;li&gt;We can import modules into the G-expression with the &lt;code&gt;with-imported-modules&lt;/code&gt; syntax.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
If you want to dig deeper, some excellent resources are:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/G_002dExpressions.html&quot;&gt;G-Expressions in the documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XdxYsdFOLd&quot;&gt;FOSDEM Talk about G-exps&lt;/a&gt; (video)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/1709.00833&quot;&gt;Code Staging in GNU Guix&lt;/a&gt; (paper, but very accessible)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgeca7ab0&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;orgeca7ab0&quot;&gt;Back to the activation service&lt;/h3&gt;
&lt;div id=&quot;text-orgeca7ab0&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
With this newly acquired knowledge, let's think about what we are trying to achieve here.
&lt;/p&gt;

&lt;p&gt;
We want to:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;Create the &lt;code&gt;/etc/caddy&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Copy the configuration file at &lt;code&gt;/etc/caddy/caddyfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ensure that the configuration file is read-only for the &lt;code&gt;caddy&lt;/code&gt; user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
We need to express those three instructions in a G-expression that we will pass as an argument to the
&lt;code&gt;service-extension&lt;/code&gt; for the &lt;code&gt;activation-service-type&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
This is how we can do so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddyfile&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;plain-file&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;CaddyFile&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;:8080 { respond \&amp;quot;Hello world!\&amp;quot;}&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;syntax-comment&quot;&gt;;; Generate a plain caddyfile configuration.
&lt;/span&gt;&lt;span class=&quot;syntax-comment&quot;&gt;;; Refer to https://caddyserver.com/docs/caddyfile-tutorial for more information
&lt;/span&gt;
&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-activation&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-imported-modules&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; we need some utilities, such as `mkdir-p
&lt;/span&gt;    &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;begin&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-modules&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir-p&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; 1. Create the directory
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;copy-file&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#$%caddyfile&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; 2. Copy the configuration file at the right location (notice the ungexp!).
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;chown&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;passwd:uid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getpwnam&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; 3. Change the ownership to root:caddy.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;group:gid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getgrnam&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;chmod&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;750&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; 4. Set permissions.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
You notice that the &lt;code&gt;%caddy-activation&lt;/code&gt; procedure accepts an argument.
As discussed earlier, it can receive the current &lt;code&gt;service&lt;/code&gt; as an argument, allowing you to dynamically modify the output.
For example, you could imagine giving the &lt;code&gt;caddy-service-type&lt;/code&gt; the ability to configure the &lt;code&gt;caddy&lt;/code&gt; username.
&lt;/p&gt;

&lt;p&gt;
Ok, let's try it out:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'caddy&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Run Caddy, the simple proxy server.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;account-service-type&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-accounts&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;activation-service-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-activation&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; &amp;lt;- Adding the extension here.
&lt;/span&gt;        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Now run &lt;code&gt;sudo guix system reconfigure config.scm&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Inspect the content of &lt;code&gt;/etc/caddy/caddyfile&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; sudo cat /etc/caddy/caddyfile
# :8080 { respond &amp;quot;Hello world!&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Great, we now have our user and our configuration file.
We can test out our service by starting &lt;code&gt;caddy&lt;/code&gt; manually.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo caddy -c /etc/caddy/caddyfile&amp;quot; # you need sudo here, we will resolve this in part 4.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
In a second terminal, run &lt;code&gt;curl localhost:8080&lt;/code&gt;.
You should obtain the response &lt;code&gt;&amp;quot;Hello world!&amp;quot;&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
We now have successfully created a service to run caddy!
&lt;/p&gt;

&lt;p&gt;
This concludes the configuration of our service. Our service:
&lt;/p&gt;
&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;creates the daemon user and group.&lt;/li&gt;
&lt;li&gt;generate the caddy configuration file&lt;/li&gt;
&lt;li&gt;copy it to the right location.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
The last part is about making it run as a daemon managed by Shepherd in the background, so we don't need to start it manually.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org62801db&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org62801db&quot;&gt;4. Configure shepherd to run the service in the background (&lt;i&gt;shepherd service&lt;/i&gt;).&lt;/h2&gt;
&lt;div id=&quot;text-org62801db&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
We now have a working Caddy service.
The last remaining part to this guide is to modify our service to instruct Shepherd to run it in the background.
&lt;/p&gt;

&lt;p&gt;
We should by now have a hunch of what needs to be done: we need to extend the Shepherd service.
&lt;/p&gt;

&lt;p&gt;
Before we do this, we need to do a final detour and talk about privileged ports.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3214555&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org3214555&quot;&gt;Privileged users and privileged programs&lt;/h3&gt;
&lt;div id=&quot;text-org3214555&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
On most linux distributions, including Guix, any port numbers below 1024 are special: standard users are not allowed to bind process to them.
&lt;/p&gt;

&lt;p&gt;
Since our &lt;code&gt;caddy&lt;/code&gt; user is not a privileged user, it won't be able to run the Caddy server on port 80 (http) and 443 (https).
We need to allow the Caddy process to be run on those ports.
&lt;/p&gt;

&lt;p&gt;
The way to go about this in Guix is to use &lt;a href=&quot;https://guix.gnu.org/manual/devel/en/html_node/Privileged-Programs.html&quot;&gt;privileged programs&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
To make Caddy a privilived program, we append it to the &lt;code&gt;%default-privileged-programs&lt;/code&gt; and assign it the necessary extra capabilities.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;privileged-programs&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;privileged-program&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;program&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;file-append&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/bin/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;capabilities&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;cap_net_bind_service=ep&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;%default-privileged-programs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
If you're extra curious, you can take a peek at the list of &lt;code&gt;privileged-programs&lt;/code&gt; in &lt;code&gt;system.scm:1267&lt;/code&gt;.
It contains a lot of well known utility requiring extra privileges, such as &lt;code&gt;sudo&lt;/code&gt;, &lt;code&gt;su&lt;/code&gt;, &lt;code&gt;passwd&lt;/code&gt;, &lt;code&gt;ping&lt;/code&gt; or &lt;code&gt;mount&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Here, we are adding the capability &lt;b&gt;CAP&lt;sub&gt;NET&lt;/sub&gt;&lt;sub&gt;BIND&lt;/sub&gt;&lt;sub&gt;SERVICE&lt;/sub&gt;&lt;/b&gt; as described in &lt;a href=&quot;https://linux.die.net/man/7/capabilities&quot;&gt;man 7 capabilities&lt;/a&gt; as &lt;i&gt;Bind a socket to Internet domain privileged ports (port numbers less than 1024)&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;=ep&lt;/code&gt; means that capability is *e*ffective and *p*ermitted, essentially giving it the capability there and then.
&lt;/p&gt;

&lt;p&gt;
An important thing to note: when we make a program privileged, it is relocated outside of the store.
The store cannot contain privileged for security concerns, you can &lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Privileged-Programs.html&quot;&gt;read more about it here&lt;/a&gt;.
The privileged programs are located in &lt;code&gt;/run/privileged&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Our 'privilged'&lt;code&gt;Caddy&lt;/code&gt; program is located at &lt;code&gt;/run/privileged/bin/caddy&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org4dafe5e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org4dafe5e&quot;&gt;Configuring Shepherd&lt;/h3&gt;
&lt;div id=&quot;text-org4dafe5e&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
The next step is to configure Shepherd.
To do so, we need to extend the &lt;code&gt;shepherd-root-service-type&lt;/code&gt; with a &lt;code&gt;shepherd-service&lt;/code&gt; record.
&lt;/p&gt;

&lt;p&gt;
In this case, I won't go into too much detail.
The &lt;a href=&quot;https://guix.gnu.org/manual/devel/en/html_node/Shepherd-Services.html&quot;&gt;Shepherd service documentation&lt;/a&gt; is very helpful and detailed, I highly recommend you to read it.
In particular the page about &lt;a href=&quot;https://doc.guix.gnu.org/shepherd/latest/en/html_node/Service-De_002d-and-Constructors.html&quot;&gt;the page about service constructor and destructors&lt;/a&gt; explains the role of &lt;code&gt;make-forkexec-constructor&lt;/code&gt; and &lt;code&gt;make-kill-desstructor&lt;/code&gt;, both doing a lot of the heavy lifting here.
&lt;/p&gt;

&lt;p&gt;
Instead, I will comment the intentions on the extension itself:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-shepherd-service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                                 &lt;span class=&quot;syntax-comment&quot;&gt;;; We ignore the config argument as we will not use it.
&lt;/span&gt;  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;shepherd-service&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;provision&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;caddy&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                                      &lt;span class=&quot;syntax-comment&quot;&gt;;; this is purely an arbitrary naming handle.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;documentation&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Run the caddy daemon&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                    &lt;span class=&quot;syntax-comment&quot;&gt;;; self explanatory
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;requirement&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;networking&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;user-processes&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                &lt;span class=&quot;syntax-comment&quot;&gt;;; We instruct shepherd to start the caddy daemon after the networking and user modules.
&lt;/span&gt;          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-forkexec-constructor&lt;/span&gt;                       &lt;span class=&quot;syntax-comment&quot;&gt;;; the command to start the process: note the use of g-exps! Refer to the doc for an exhaustive list of options
&lt;/span&gt;                     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/run/privileged/bin/caddy&amp;quot;&lt;/span&gt;               &lt;span class=&quot;syntax-comment&quot;&gt;;; Note the location of our privileged version of caddy. The &amp;quot;run&amp;quot; commands and its arguments are Caddy related; refer to the caddy documentation
&lt;/span&gt;                       &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;run&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;--config&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt;
                       &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;--adapter&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddyfile&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:user&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;                                  &lt;span class=&quot;syntax-comment&quot;&gt;;; The user and group in charge of the daemon
&lt;/span&gt;                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:group&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:log-file&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/var/log/caddy.log&amp;quot;&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:environment-variables&lt;/span&gt;                         &lt;span class=&quot;syntax-comment&quot;&gt;;; Required for the logs
&lt;/span&gt;                     &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;HOME=/var/lib/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;stop&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-kill-destructor&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;                        &lt;span class=&quot;syntax-comment&quot;&gt;;; The destructor, called when the process is killed. Refer to the documentation
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
A few point worth mentioning:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;'user-processes&lt;/code&gt; is a requirement for most &lt;code&gt;shepherd-service&lt;/code&gt; as mentioned in the &lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Shepherd-Services.html&quot;&gt;documentation&lt;/a&gt;. We need the file systems for the user to be mounted before starting Caddy.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'networking&lt;/code&gt; is also set as a requirement, we want the network stack up before we start &lt;code&gt;caddy&lt;/code&gt;. I found this while
looking at how the exim service was written. As far as I can tell, these aren't documented. You will need to look
directly in the source code.&lt;/li&gt;
&lt;li&gt;I don't quite recall why I set up the environment variable, but I believe it was a requirement for the logs. The
service would otherwise it would complain. It is &lt;a href=&quot;https://caddyserver.com/docs/running&quot;&gt;mentionned in the Caddy documentation when using systemctl&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-orgeeced86&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgeeced86&quot;&gt;Final code&lt;/h2&gt;
&lt;div id=&quot;text-orgeeced86&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
This is how our entire service looks like:
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-modules&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;gnu&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;licenses&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;gexp&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;;; Redacted ... many modules
&lt;/span&gt;  &lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-service-modules&lt;/span&gt;
  &lt;span class=&quot;syntax-comment&quot;&gt;;; Redacted... many modules
&lt;/span&gt;  &lt;span class=&quot;syntax-symbol&quot;&gt;desktop&lt;/span&gt;
  &lt;span class=&quot;syntax-symbol&quot;&gt;networking&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; Our caddy package, as seen in a previous article
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;package&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;2.11.4&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;origin&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;url-fetch&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;string-append&lt;/span&gt;
                     &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;https://github.com/caddyserver/caddy/releases/download/v&amp;quot;&lt;/span&gt;
                     &lt;span class=&quot;syntax-symbol&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/caddy_&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;_linux_amd64.tar.gz&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;sha256&lt;/span&gt;
                &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;base32&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;1fbvxj6mifdqhwm5s1f8snr805k0anllzlri7cg9l61rgj8vyzsj&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;build-system&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;copy-build-system&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;arguments&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-keyword&quot;&gt;#:install-plan&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#~'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;bin/&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;home-page&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;https://caddyserver.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;synopsis&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Web server with automatic HTTPS&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Caddy is an extensible web server with automatic TLS.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;license&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;asl2.0&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; Our caddy user:group for the daemon
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-accounts&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;user-account&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;system?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Caddy daemon user&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;home-directory&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/var/lib/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;create-home-directory?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;shell&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;file-append&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;shadow&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/sbin/nologin&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;user-group&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;system?&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; Our Caddyfile
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddyfile&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;plain-file&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Caddyfile&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;aloysberger.com {
       root * /srv/http/blog
       file_server
     }
     :8080 {
        respond \&amp;quot;Hello, World!\&amp;quot;
     }&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; There is more to my Caddyfile, but yes, it serves this blog!
&lt;/span&gt;
&lt;span class=&quot;syntax-comment&quot;&gt;;; The activation to copy the Caddy file
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-activation&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;with-imported-modules&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;begin&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;use-modules&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;guix&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;mkdir-p&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;copy-file&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#$%caddyfile&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;chown&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;passwd:uid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getpwnam&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;group:gid&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;getgrnam&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;chmod&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;750&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; The Shepherd definition for our Caddy daemon
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-shepherd-service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;shepherd-service&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;provision&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;caddy&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;documentation&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Run the caddy daemon&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;requirement&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;networking&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-forkexec-constructor&lt;/span&gt;
                     &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/run/privileged/bin/caddy&amp;quot;&lt;/span&gt;
                       &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;run&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;--config&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/etc/caddy/caddyfile&amp;quot;&lt;/span&gt;
                       &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;--adapter&amp;quot;&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddyfile&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:user&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:group&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;caddy&amp;quot;&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:log-file&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/var/log/caddy.log&amp;quot;&lt;/span&gt;
                     &lt;span class=&quot;syntax-keyword&quot;&gt;#:environment-variables&lt;/span&gt;
                     &lt;span class=&quot;syntax-symbol&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;HOME=/var/lib/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;stop&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#~&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;make-kill-destructor&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-comment&quot;&gt;;; And finally, the entire service
&lt;/span&gt;&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-special&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy-service-type&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-type&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;'caddy&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Run Caddy, the simple proxy server.&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;extensions&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;account-service-type&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-accounts&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;activation-service-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-activation&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service-extension&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;shepherd-root-service-type&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;%caddy-shepherd-service&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;default-value&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;operating-system&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;locale&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;en_AU.utf8&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;timezone&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;Australia/Brisbane&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;keyboard-layout&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;keyboard-layout&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;au&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;host-name&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;[REDACTED]&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;cons*&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;user-account&lt;/span&gt;
                  &lt;span class=&quot;syntax-comment&quot;&gt;;; [REDACTED - Users are defined here
&lt;/span&gt;                  &lt;span class=&quot;syntax-symbol&quot;&gt;%base-user-accounts&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax-comment&quot;&gt;;; Elevating Caddy's privilege to bind to port under 1024.
&lt;/span&gt;    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;privileged-programs&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;privileged-program&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;program&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;file-append&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;/bin/caddy&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;capabilities&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;cap_net_bind_service=ep&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-symbol&quot;&gt;%default-privileged-programs&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;services&lt;/span&gt;
      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; [REDACTED] Many services here: SSH, paperless, mail...
&lt;/span&gt;                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;caddy-service-type&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;syntax-comment&quot;&gt;;; &amp;lt;-- Our Caddy service!
&lt;/span&gt;                      &lt;span class=&quot;syntax-symbol&quot;&gt;%base-services&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bootloader&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bootloader-configuration&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;bootloader&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;grub-bootloader&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;[REDACTED]&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;keyboard-layout&lt;/span&gt; &lt;span class=&quot;syntax-symbol&quot;&gt;keyboard-layout&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;swap-devices&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;swap-space&lt;/span&gt;
                              &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;syntax-open&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-symbol&quot;&gt;uuid&lt;/span&gt; &lt;span class=&quot;syntax-string&quot;&gt;&amp;quot;[REDACTED&amp;quot;&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;syntax-close&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Alright, time to start it:	
&lt;code&gt;sudo guix system reconfigure config.scm&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;
Once started, we can check the health of our daemon using the &lt;code&gt;herd&lt;/code&gt; command:
&lt;code&gt;sudo herd status caddy&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
You should see something like so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status of caddy:
It is running since Wed Jul  8 18:06:04 2026 (41 days ago).
Main PID: 17241
Command: /run/privileged/bin/caddy run --config /etc/caddy/caddyfile --adapter caddyfile
It is enabled.
Provides: caddy
Requires: networking
Replacement pending (restart to upgrade).
Will be respawned.
Log file: /var/log/caddy.log
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Let's verify it works:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; curl localhost:8080
# Hello, World!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
Nice. Our service is working and the process is running in the background, managed by Shepherd.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org55b4034&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;org55b4034&quot;&gt;How to modify the Caddyfile&lt;/h3&gt;
&lt;div id=&quot;text-org55b4034&quot; class=&quot;outline-text-3&quot;&gt;
&lt;p&gt;
If you wish to change the Caddyfile, you can modify our &lt;code&gt;%caddyfile&lt;/code&gt; and reconfigure the system.
Alternatively, for quick debugging purpose, you can modify the file directly at &lt;code&gt;/etc/caddy/caddyfile&lt;/code&gt;  and restart the caddy server with &lt;code&gt;sudo herd restart caddy&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;outline-container-org608f945&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org608f945&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div id=&quot;text-org608f945&quot; class=&quot;outline-text-2&quot;&gt;
&lt;p&gt;
If you have read thus far, thank you!
&lt;/p&gt;

&lt;p&gt;
As a summary, let's review what we have covered:
&lt;/p&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;Guix services and the extensions architecture.&lt;/li&gt;
&lt;li&gt;executing an arbitrary command when enabling a service (&lt;code&gt;activation-service-type&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;creating and managing users declaratively (&lt;code&gt;user-account-service-type&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;a (quick!) primer on G-expressions.&lt;/li&gt;
&lt;li&gt;elevating program privileges with &lt;code&gt;privileged-programs&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;running a service as a daemon in the background using Shepherd (&lt;code&gt;shepherd-service-type&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
As stated in the title, I am not an expert in Guix or Scheme.
I stumbled my way through this creating this service; and it probably show!
In any case, I hope that it will help you getting start with custom services and that it clarified some concepts around services.
&lt;/p&gt;

&lt;p&gt;
I am sure there are improvements to be made, such as using the &lt;code&gt;etc-service-type&lt;/code&gt; instead of the &lt;code&gt;activation-service-type&lt;/code&gt;.
If you have any comments, please kindly send them to contact@aloysberger.com.
&lt;/p&gt;

&lt;p&gt;
I hope you enjoyed this article.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.1&quot; href=&quot;#fnr.1&quot; class=&quot;footnum&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;Not available yet, but I did see a PR a couple of months ago, so it might already be available.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.2&quot; href=&quot;#fnr.2&quot; class=&quot;footnum&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;in the future, I want to write a small DSL to generate the caddy config file in a declarative matter.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.3&quot; href=&quot;#fnr.3&quot; class=&quot;footnum&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;unsure what is the convention here? I have seen all three&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.4&quot; href=&quot;#fnr.4&quot; class=&quot;footnum&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;We won't do a deep dive into G-exps, there is enough to warrant its own article&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;</content></entry><entry><title>Book review: Sapiens by Yuval Noah Harari.</title><id>https://aloysberger.com/book-review-sapiens-by-yuval-noah-harari.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-17T19:38:00Z</updated><link href="https://aloysberger.com/book-review-sapiens-by-yuval-noah-harari.html" rel="alternate" /><content type="html">&lt;p&gt;
&lt;i&gt;Sapiens&lt;/i&gt; appears on many book recommendation lists, and I now understand why.
&lt;/p&gt;&lt;p&gt;
The author, Yuval Noah Harari, gives you a brief commented history of humankind.
He explains how, as a specie, we arrived to where we are today and why we think the way we do&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.1&quot; href=&quot;#fn.1&quot; class=&quot;footref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;&lt;p&gt;
In each chapter, Yuval introduce and discuss an aspect of humanity, in a chronological order.
For example, the birth of money, the difference between chimpanzee and us or the role of the state in the community.
He remains very open on all subjects, often presenting a compelling idea followed by a counter argument as strong as the idea itself.
&lt;/p&gt;&lt;p&gt;
At first, it seemed like the author doesn't want to give his opinion. However, I believe the goal is to invite the reader to think and reflect on the idea; which he successfully did with me.
&lt;/p&gt;&lt;p&gt;
The book has more value in what is &lt;i&gt;not&lt;/i&gt; written, rather than what is written.
&lt;/p&gt;&lt;p&gt;
&lt;i&gt;Sapiens&lt;/i&gt; will remain a staple on my bookshelf; I'm not very knowledgeable when it comes to history and anthropology: &lt;i&gt;Sapiens&lt;/i&gt; was an excellent primer to both areas.
&lt;/p&gt;&lt;p&gt;
I highly recommend it.
&lt;/p&gt;&lt;p&gt;
I especially enjoyed the later chapters on the last four centuries, from the rise of science in Europe to the birth of capitalism and how it shaped the world as we know it today.
&lt;/p&gt;&lt;p&gt;
The second to last chapter on happiness was also a pleasant surprise. I did not expect it in this book.
It is a subject I am curious about, and the content in the twenty or so pages about happiness were very thought-provoking.
&lt;/p&gt;&lt;p&gt;
Interestingly, the book was written in 2014 the last chapter is already feeling a tad obsolete&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fnr.2&quot; href=&quot;#fn.2&quot; class=&quot;footref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; as it praise how stable and peaceful the world has been in the last decade.
&lt;/p&gt;&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.1&quot; href=&quot;#fnr.1&quot; class=&quot;footnum&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;At least, in the western world.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a role=&quot;doc-backlink&quot; id=&quot;fn.2&quot; href=&quot;#fnr.2&quot; class=&quot;footnum&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div role=&quot;doc-footnote&quot; class=&quot;footpara&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;for worse, unfortunately&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;</content></entry><entry><title>Finished reading &quot;Sapiens&quot; by Yuval Noah Harari</title><id>https://aloysberger.com/2026-08-17-11-36.html</id><author><name>Aloys Berger</name><email>me@aloysberger.com</email></author><updated>2026-08-17T11:36:00Z</updated><link href="https://aloysberger.com/2026-08-17-11-36.html" rel="alternate" /><content type="html">&lt;p&gt;
I will write a short review shortly, but I understand why this often comes as a highly recommended book.
It contains a lot of intriguing ideas, and challenge some widely accepted view on humanity.
&lt;/p&gt;</content></entry></feed>