[{"content":"In the last few months, I\u0026rsquo;ve been working extensively on my transition to Platform Engineering, and that includes my online profile. The very fact that you\u0026rsquo;re reading this means, I may modestly say, that it\u0026rsquo;s working!\nToday, a short write-up about a nice improvement to my GitHub Profile: automatically listing my latest blog posts. Since I use the Hugo Papermod theme, I had to make sure the site was producing an RSS feed. This is achieved by ensuring that hugo.yaml has RSS as an element of outputs.home. Additionally, I added the RSS icon to my header by adding the following element to params.socialIcons:\n- name: rss url: \u0026#34;https://fabriciojm.github.io/index.xml\u0026#34; Now that the site is producing an RSS feed, we can simply follow the instructions by Gautam Krishna R to add a workflow to the GitHub profile page: https://github.com/gautamkrishnar/blog-post-workflow. They are easy to follow, and that\u0026rsquo;s about it: a list of the last five posts appears on the profile page!\nTo be fair, this is nothing new, and it\u0026rsquo;s fairly straightforward to figure out. I still find two valuable things about it:\nI wanted to copy something I like. There\u0026rsquo;s something about reading other people\u0026rsquo;s writing that you can\u0026rsquo;t figure out in any other way. Hopefully, this will give you some insight into how I learn and build. I left the GitHub Actions workflow untouched. It has a parameter to set how many blog posts it will show (max_post_count), whose default value is five. When the result appeared on my page, the list couldn\u0026rsquo;t show all my posts because (drum roll) I had already published six posts, and this would be the seventh. I got a small (but great) sense of accomplishment out of that. ","permalink":"https://fabriciojm.github.io/posts/20260629-blog-posts-github/","summary":"\u003cp\u003eIn the last few months, I\u0026rsquo;ve been working extensively on my transition to Platform Engineering, and that includes my online profile. The very fact that you\u0026rsquo;re reading this means, I may modestly say, that it\u0026rsquo;s working!\u003c/p\u003e\n\u003cp\u003eToday, a short write-up about a nice improvement to \u003ca href=\"https://github.com/fabriciojm\"\u003emy GitHub Profile\u003c/a\u003e: automatically listing \u003ca href=\"https://github.com/fabriciojm#writing\"\u003emy latest blog posts\u003c/a\u003e. Since I use the Hugo Papermod theme, I had to make sure the site was producing an RSS feed. This is achieved by ensuring that \u003ccode\u003ehugo.yaml\u003c/code\u003e has \u003ccode\u003eRSS\u003c/code\u003e as an element of \u003ccode\u003eoutputs.home\u003c/code\u003e. Additionally, I added the RSS icon to my header by adding the following element to \u003ccode\u003eparams.socialIcons\u003c/code\u003e:\u003c/p\u003e","title":"Listing my Latest Blog Posts on my GitHub Profile"},{"content":"I am a lucky guy. I have a great family. I was brought up in what was still a moderately functional country: Venezuela. I received a good education and attended the best school I could back home.\nThen I left, did my studies and research in several countries, and eventually established myself in France. My departure coincided with the a major escalation of many problems that would lead to the worst years in the country\u0026rsquo;s history. I believe that most of those problems have their origin in the bad faith of some individuals, but we have also had our fair share of bad luck. This post is not about politics, though.\nPart of my luck is that I don\u0026rsquo;t have to live through those events directly, but living them abroad is a strange experience, to say the least. One thing is homesickness, which on its own can be pretty bad; another is getting bad news all the time on top of that. I could probably make a list of one major terrible event for every year I\u0026rsquo;ve been away. This year, the occasion is a major earthquake in my home state and neighboring regions. My family is safe and my hometown didn\u0026rsquo;t suffer major damages or losses, but the news and images coming from Caracas and La Guaira are devastating.\nOver the years, I\u0026rsquo;ve adopted a sort of resignation when it comes to Venezuela. It\u0026rsquo;s not that I don\u0026rsquo;t want good things to happen. Of course I do. I\u0026rsquo;ve simply found some peace in accepting that there\u0026rsquo;s very little I can do from here. Believe me, I\u0026rsquo;m not giving advice here, and I genuinely admire people who remain hopeful. I\u0026rsquo;m not proud nor ashamed of it, this is simply what has helped me. Part of that was leaving my personal social media in 2024 (guess what? After a terrible event).\nIn this kind of context it\u0026rsquo;s almost impossible to concentrate or work under these circumstances for most people, and I\u0026rsquo;m no exception. Doing nothing only makes me more anxious. What helps me is just writing. I remember poet José Lezama Lima\u0026rsquo;s last words to Reinaldo Arenas (Cuban writer and dissident): \u0026ldquo;Remember that our only salvation lies in the word; write.\u0026rdquo;\n","permalink":"https://fabriciojm.github.io/posts/20260625-writing-saves/","summary":"\u003cp\u003eI am a lucky guy. I have a great family. I was brought up in what was still a moderately functional country: Venezuela. I received a good education and attended the best school I could back home.\u003c/p\u003e\n\u003cp\u003eThen I left, did my studies and research in several countries, and eventually established myself in France. My departure coincided with the a major escalation of many problems that would lead to the worst years in the country\u0026rsquo;s history. I believe that most of those problems have their origin in the bad faith of some individuals, but we have also had our fair share of bad luck. This post is not about politics, though.\u003c/p\u003e","title":"I Write When I Think I Can't Think"},{"content":"I keep a commonplace book on my GitHub.\nCommonplace books have existed since antiquity and persisted through modern times. They are simply personal notebooks where the author collects anything interesting or potentially useful.\nThese notebooks serve the purpose of capturing a thought or an observation for future reference. I believe that, at their core, every learning or knowledge-production system implements some version of a commonplace book. Wikipedia says:\nThey can variously contain notes, proverbs, adages, aphorisms, maxims, recipes, quotes, letters, poems, tables of weights and measures, prayers, legal formulas, and other professional references.\u0026quot;\nI\u0026rsquo;d go further: the author can even sketch proper arguments or concepts there. That\u0026rsquo;s why it\u0026rsquo;s so fascinating to look at the commonplace notebooks of prominent thinkers: they reveal something at the core of their thought process.\nIn the digital era, we have all heard the popular adage: \u0026ldquo;build in public.\u0026rdquo; Which is great advice, for sure; we get to see the repos and code produced by great engineers (these days, the agents they orchestrate). But once you find those great engineers, you may become interested in what they are learning. You may want to see their notes, or how they implemented something before adapting it into a particular project. That part of the thought process is not necessarily something you can figure out from a project repo alone. I think a variation on the theme is worth exploring: \u0026ldquo;show how you build in public.\u0026rdquo;\nFor me, that takes the form of a GitHub repo where I keep code snippets, templates, and some of my notes from things I\u0026rsquo;m learning. I made it public for two reasons:\nTo benefit from the minimal standard of coherence and quality that comes from knowing a third person might see it. That standard is always higher than the one I apply to something I keep private. In the hope that someone else may find it useful in the future. That may include future collaborators. At the very least, it has already proven useful to my future self more than once. Needless to say, none of these ideas are mine, and while writing this, I think credit is in order.\nThe advice of having a public learning repo I got from Mischa van den Burg, and him from RWXROB. I heard about commonplace books first through Parker Settecase. Although I already had had the privilege of seeing some of Da Vinci\u0026rsquo;s notebooks at Le Louvre, with some explanation about his note-taking process; certainly the most fascinating part of the exhibition for me. Miscelaneous: during the reading and the rabbit holes any worthy writing entails, today I learned that code version control was pioneered by Bell Labs (what did they not pioneer?) and that code notebooks were introduced by Wolfram Research. ","permalink":"https://fabriciojm.github.io/posts/20260624-commonplace-repo/","summary":"\u003cp\u003eI keep a commonplace book on my GitHub.\u003c/p\u003e\n\u003cp\u003eCommonplace books have existed since antiquity and persisted through modern times. They are simply personal notebooks where the author collects anything interesting or potentially useful.\u003c/p\u003e\n\u003cp\u003eThese notebooks serve the purpose of capturing a thought or an observation for future reference. I believe that, at their core, every learning or knowledge-production system implements some version of a commonplace book. Wikipedia says:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThey can variously contain notes, proverbs, adages, aphorisms, maxims, recipes, quotes, letters, poems, tables of weights and measures, prayers, legal formulas, and other professional references.\u0026quot;\u003c/p\u003e","title":"The Commonplace Repo or (Show How You) Build in Public"},{"content":"You docker run. You get containers with networking. It\u0026rsquo;s that simple. But is it?\nUnder the hood, Docker creates network namespaces, virtual Ethernet devices, bridges, routing rules and everything else needed for containers to communicate. I\u0026rsquo;m following Drew Elliot\u0026rsquo;s Networking Course lessons; the first of which is mostly about how networking happens in containers. What follows is based on the notes I made during the course and revised on my own, including some concepts I wanted to revise.\nDocker Container Automatic Setup Imagine you create three containers:\nfor cont in blue green red; do docker run -d --name $cont alpine sleep 1000 done Docker automatically sets up all the networking for us.\nA Linux bridge called docker0 is created:\nip link show docker0 ip link show master docker0 The first command shows the bridge and the second lists the interfaces enslaved to it.\nEach container receives its own virtual network interface:\nfor cont in blue green red; do docker exec $cont ip addr show eth0 done Docker also keeps track of the bridge configuration:\ndocker network inspect bridge This shows, among other things, the containers attached to the bridge and the IP addresses Docker assigned to them.\nFor example, on my machine blue is 172.17.0.3 and red is 172.17.0.4. The containers can communicate directly:\ndocker exec red ping -c 3 172.17.0.3 They also have Internet connectivity out of the box:\ndocker exec green ping -c 3 8.8.8.8 From a single docker run, Docker has already put in place the whole network machinery needed. In the next section we\u0026rsquo;ll build a simpler version of that ourselves.\nContainer Networking by Hand Containers are just Linux processes with some extra isolation mechanisms. That means everything Docker does under the hood is built on top of standard Linux features. Let\u0026rsquo;s recreate a minimal container network.\nThe network looks like this: two \u0026ldquo;containers\u0026rdquo; running in a host (our already familiar red and blue), where we want to enable communication between themselves and eventually reach the internet.\nSome Concepts Let\u0026rsquo;s briefly illustrate some concepts that are useful for this networking exercise.\nNetwork Namespaces A network namespace is a Linux kernel feature that provides an isolated network stack. Each namespace has its own network interfaces, routing table, firewall rules and so on. Containers rely on network namespaces to isolate their networking from the host and from each other.\nLinux Bridge It\u0026rsquo;s a virtual data switch that operates at the Data Link Layer (Layer 2) of the OSI Model. A bridge can typically connect:\nPhysical Network Interface Controllers (NICs, e.g. eth0). Virtual Interfaces (see below). Virtual Machines. A software bridge can be thought as a software Ethernet switch running inside Linux. Virtual Ethernet Pair (veth pair) It\u0026rsquo;s the virtual cabling between the bridge and the container, each of which has a virtual interface. It also operates at the Data Link Layer. Virtual interfaces are created by the kernel and always come in pairs: typically, one end is placed inside a container and the other is attached to the Linux bridge.\nNAT and Masquerade Network Address Translation (NAT) modifies IP addresses and/or ports in packets. Typically, NATs are put in place so that devices can communicate beyond private networks. Masquerade is a special form of Source NAT that automatically replaces the packet\u0026rsquo;s source address with the IP address of the outgoing interface. Linux keeps track of these translations so replies can be delivered back to the correct namespace.\nDefining Namespaces, Bridges, Interfaces and Wiring \u0026ldquo;by Hand\u0026rdquo; Now let\u0026rsquo;s create every piece shown in the diagram ourselves.\nFirst create the network namespaces blue and red, which will play the role of our containers:\nsudo ip netns add blue sudo ip netns add red sudo ip netns exec red ip link show red links should show only the loopback interface.\nThen add a link of type bridge and name br-study, bring it up, assign an ip address pointing to the bridge.\nsudo ip link add br-study type bridge sudo ip link set br-study up sudo ip addr add 10.0.0.254/24 dev br-study For the red namespace:\nCreate a veth pair where veth-r will live inside the red namespace and veth-r-br will remain on the bridge. Move veth-r into the red namespace. Attach (enslave) veth-r-br to the bridge. Bring up veth veth-r. sudo ip link add veth-r type veth peer name veth-r-br sudo ip link set veth-r netns red sudo ip link set veth-r-br master br-study sudo ip link set veth-r-br up Inside each namespace, assign an IP address and bring both the interface and the loopback device up.\nsudo ip netns exec red ip addr add 10.0.0.1/24 dev veth-r sudo ip netns exec red ip link set veth-r up sudo ip netns exec red ip link set lo up Now we do the same for blue:\nsudo ip link add veth-b type veth peer name veth-b-br sudo ip link set veth-b netns blue sudo ip link set veth-b-br master br-study sudo ip link set veth-b-br up sudo ip netns exec blue ip addr add 10.0.0.2/24 dev veth-b sudo ip netns exec blue ip link set veth-b up sudo ip netns exec blue ip link set lo up We can now test the network:\nsudo ip netns exec red ping -c 3 10.0.0.2 Accessing the Internet The namespaces cannot reach networks outside their own subnet yet. They only know about the directly connected network (10.0.0.0/24) and have no default route for everything else; we can see that with:\nsudo ip netns exec blue ip route # 10.0.0.0/24 dev veth-b proto kernel scope link src 10.0.0.2 The default route for the machine is:\nip route show default # default via 192.168.1.1 dev enp0s25 proto dhcp src \u0026lt;your-ip\u0026gt; metric 100 Configure the bridge IP (10.0.0.254) as the default gateway for both namespaces:\nsudo ip netns exec blue ip route add default via 10.0.0.254 sudo ip netns exec red ip route add default via 10.0.0.254 Allow packet forwarding in the Linux kernel by setting the corresponding parameter to true (i.e. Linux can act as a router):\nsudo sysctl -w net.ipv4.ip_forward=1 Define iptables rules to accept forward requests (input and output) for br-study:\nsudo iptables -A FORWARD -i br-study -j ACCEPT sudo iptables -A FORWARD -o br-study -j ACCEPT Then a rule that defines the NAT and Masquerade:\nsudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o enp0s25 -j MASQUERADE Here\n-t nat: type NAT -A POSTROUTING: Apply the rule after the kernel has decided where the packet will leave the host. -s 10.0.0.0/24: Source is network identifier with mask And now the namespaces/containers can reach the internet.\nsudo ip netns exec red ping -c 3 8.8.8.8 Once you take a detailed look at it, you realize that Docker combines and automates a bunch of Linux networking features that we often take for granted. That\u0026rsquo;s why I believe this kind of exercise should be done at least once. The more time we invest in them, the better our mental models become of the foundations behind the tools we use every day as IT engineers. In my opinion, there\u0026rsquo;s a significant difference between repeating \u0026ldquo;containers are just Linux\u0026rdquo; and actually getting your hands dirty with namespaces, system resources, routing, and so on. The latter gives you a problem-solving advantage that the former never will.\n","permalink":"https://fabriciojm.github.io/posts/20260623-container-networking-by-hand/","summary":"\u003cp\u003eYou \u003ccode\u003edocker run\u003c/code\u003e. You get containers with networking. It\u0026rsquo;s that simple. But is it?\u003c/p\u003e\n\u003cp\u003eUnder the hood, \u003ca href=\"https://docs.docker.com/engine/network/\"\u003eDocker\u003c/a\u003e creates network namespaces, virtual Ethernet devices, bridges, routing rules and everything else needed for containers to communicate. I\u0026rsquo;m following \u003ca href=\"https://github.com/drewelliott/kubecraft/tree/main\"\u003eDrew Elliot\u0026rsquo;s Networking Course\u003c/a\u003e lessons; the first of which is mostly about how networking happens in containers. What follows is based on the notes I made during the course and revised on my own, including some concepts I wanted to revise.\u003c/p\u003e","title":"Container Networking by Hand"},{"content":"Recently, I\u0026rsquo;ve learned about development in dev containers. This idea is great because it allows for siloed, reproducible, full-featured environments for development. Since DevOps is about enabling product work, dev containers are a great example of that.\nThis idea can actually go further: dev containers can also be used for management, admin, and DevOps tasks, like Kubernetes cluster management. In that case, tools and configuration files are as important as application code. One can have a dedicated management environment for a single cluster, reducing the risk of accidentally targeting the wrong cluster.\nThe setup I\u0026rsquo;m currently using is based on Rio Kierkel’s approach, combining dev containers (managed by DevPod) with chezmoi for dotfile management and templating, and mise for tool installation and environment configuration. This results in a powerful and portable environment. In a sense, the “product” being enabled here is DevOps itself.\nOne day I’ll write more about how this setup is made. (For now, you can already take a look at my homelab and my dotfiles.) But today I wanted to just point out how to connect the host\u0026rsquo;s SSH agent to a dev container.\nI\u0026rsquo;ll state the obvious: it is expected for the dev container to be able to communicate with remote repos. If the host machine is already configured with an SSH key for GitHub, and the key is loaded into an SSH agent (for example using keychain):\neval \u0026#34;$(keychain --eval --quiet ~/.ssh/\u0026lt;key-name\u0026gt;)\u0026#34; the dev container does not need its own private key, as it\u0026rsquo;s possible to forward the host\u0026rsquo;s SSH agent socket into the container. That is done by adding to the dev container configuration file, i.e. the devcontainer.json file:\n\u0026#34;mounts\u0026#34;: [ \u0026#34;source=${localEnv:SSH_AUTH_SOCK},target=/ssh-agent,type=bind\u0026#34; ], \u0026#34;remoteEnv\u0026#34;: { \u0026#34;SSH_AUTH_SOCK\u0026#34;: \u0026#34;/ssh-agent\u0026#34; } Here localEnv refers to the environment of the machine running the container. The env variable SSH_AUTH_SOCK, exported by keychain (pointing to the host\u0026rsquo;s ssh-agent), exposes only the ssh socket but the private key itself stays on the host. This can, of course, be done for multiple dev containers simultaneously. Pretty neat, I think.\n","permalink":"https://fabriciojm.github.io/posts/20260622-devcontainers-ssh/","summary":"\u003cp\u003eRecently, I\u0026rsquo;ve learned about development in \u003ca href=\"https://containers.dev/\"\u003edev containers\u003c/a\u003e. This idea is great because it allows for siloed, reproducible, full-featured environments for development. Since DevOps is about enabling product work, dev containers are a great example of that.\u003c/p\u003e\n\u003cp\u003eThis idea can actually go further: dev containers can also be used for management, admin, and DevOps tasks, like Kubernetes cluster management. In that case, tools and configuration files are as important as application code. One can have a dedicated management environment for a single cluster, reducing the risk of accidentally targeting the wrong cluster.\u003c/p\u003e","title":"Dev Contaniners and SSH"},{"content":"Security is one (if not the) main priority of many Linux administrators, and now more than ever this is the case in the context of the large number of systems we typically manage today: containerized systems running in clusters, cloud microservices, ephemeral environments, and so on.\nWe talk a lot about the essentials: good password, key and secrets management, firewall policies, encryption, and similar topics; which is obviously critical. But I also believe that threats can be mitigated through small habits, in the commands we do daily.\nHere are two small practices I’ve adopted over the years that I think are especially relevant for Linux users and, of course, for anyone working in cloud, infrastructure, or DevOps.\nUse absolute paths for password-related commands The first practice is invoking sensitive commands through their absolute paths. Think about /bin/su instead of su and /usr/bin/ssh instead of ssh, instead of relying blindly on $PATH. The reason is simple: command lookup itself can become part of the attack surface.\nIf an attacker manages to compromise a user account (but not root), they may be able to place a fake ssh, scp, or similar executable earlier in the victim’s $PATH, or alias those commands in shell configuration files. A convincing fake password prompt can be enough to capture credentials. Using absolute paths bypasses that entire class of tricks.\nThis is, of course, not something most individual Linux users should worry too much about. But for people who regularly administer remote systems, clusters, or production infrastructure, I think it is a reasonable habit to build.\nI even have shortcuts in my .inputrc for the commands I use most often, so the absolute paths are inserted automatically.\nsudo \u0026gt; sudo -i \u0026gt; sudo su Some people escalate privileges with:\nsudo su but in most cases this is unnecessary, because Linux already provides sudo with a more direct way to obtain a root login shell, if needed:\nsudo -i Depending on the use case, sudo -s or simply sudo \u0026lt;command\u0026gt; may be more appropriate. (Just ironymaxxing here, no absolute paths in blog code blocks 😉)\nUsing sudo su adds an extra layer: sudo launches su, which then launches a shell. In practice, there is usually little benefit over sudo -i. Beyond that, auditability and accountability are also part of the discussion. One of the strengths of sudo is that privileged actions are associated with a specific sudo-capable user.\nHowever, once administrators routinely jump into long-lived root shells, attribution becomes weaker. Inside the shell, commands are simply being executed as root, and distinguishing who did what afterwards becomes harder without additional auditing tooling.\nWe can see it in a little demo here. Start a Debian container:\ndocker run -it debian:stable bash Install sudo and create two users, Alice and Bob:\n# Install sudo and syslog apt update \u0026amp;\u0026amp; apt install -y sudo rsyslog # Add users, assign their passwords (same as user names), # give them sudo privileges useradd -m alice useradd -m bob echo \u0026#39;alice:alice\u0026#39; | chpasswd echo \u0026#39;bob:bob\u0026#39; | chpasswd usermod -aG sudo alice usermod -aG sudo bob # Turn on logging daemon rsyslogd -n -iNONE \u0026amp; Now if Alice logs in (docker exec -it --user alice \u0026lt;container-name\u0026gt; bash) and performs an action with sudo:\nsudo touch /root/alice-file The logs will show that Alice executed exactly that command; in /var/sys/auth.log:\nalice : ... USER=root ; COMMAND=/usr/bin/touch /root/alice-file But if Bob logs in and, on the other hand, does:\nsudo su - # password touch /root/privileged-user-file{1..3} rm /root/privileged-user-file2 echo \u0026#34;foobar\u0026#34; \u0026gt; /root/privileged-user-file3 the logs mainly show that Bob opened a root shell.\nbob : ... USER=root ; COMMAND=/usr/bin/su - The individual commands executed afterwards are no longer clearly attributed through sudo itself.\nTo be rigorous, the same limitation also applies to sudo -i: once you are inside a root shell, attribution naturally becomes weaker. So the rule of thumb is: use sudo as much as possible and, if unavoidable get a root shell via sudo -i.\nPerhaps the broader lesson here for cloud and DevOps practitioners is that security is not only about “big” security tooling. Infrastructure work is full of little repeated actions: logging into servers, escalating privileges, copying files, running automation, and jumping between environments.\n","permalink":"https://fabriciojm.github.io/posts/20260527-linux-tips/","summary":"\u003cp\u003eSecurity is one (if not \u003cem\u003ethe\u003c/em\u003e) main priority of many Linux administrators, and now more than ever this is the case in the context of the large number of systems we typically manage today: containerized systems running in clusters, cloud microservices, ephemeral environments, and so on.\u003c/p\u003e\n\u003cp\u003eWe talk a lot about the essentials: good password, key and secrets management, firewall policies, encryption, and similar topics; which is obviously critical. But I also believe that threats can be mitigated through small habits, in the commands we do daily.\u003c/p\u003e","title":"Two Linux Security Tips"},{"content":"About a half a life ago, I had my first Linux lesson, and the best so far. I was a freshman at uni and started learning Linux at Laboratorio Docente de Computación. After a few weeks there, the first important homework was a seemingly simple one: create a new user (your user) in a Linux machine using the terminal.\nBut there\u0026rsquo;s a catch (see what I\u0026rsquo;m doing here?): no adduser or useradd scripts allowed. I could bring my notes but not my laptop.\nAt the time, our reference was The UNIX System Administration Handbook, 3rd Edition, which already a few years old at the time. The answer was actually there in Chapter 6, but deciphering all that took about a day per page. People at the lab were half friendly, half observant on how you took on the challenge, but without a doubt this homework let me figure out so many things, to name a few:\nBasic commands: bash, filesystem navigation, file inspection and manipulation. VIm basics: opening, navigating, editing, saving a file. UNIX users basics: permissions, root vs. non-root users, groups, the /etc/passwd and /etc/shadow files and the passwd command. When you felt ready, you would come to a staff member of the lab and they\u0026rsquo;d give you a root shell on the machine and supervise your steps. The idea is that you knew what you were doing before running anything you do, from running a command, to the meaning of an information typed in a file. In hindsight, the amount of information contained in all steps was pretty massive; most of it was foundational Linux knowledge and some of it ended up in what would become funny anecdotes after some time; for example, I remember pondering for a couple of days what would be the right way of filling the GECOS field (mostly historical and virtually irrelevant), or which would be the best shell interpreter among sh, ksh, csh or tcsh (me distinctly skipping bash, which was the standard).\nCreating a user could have been an unremarkable interaction with useradd but it was instead an enriching experience. Everyone I knew at the lab felt this power of having touched the inside of Linux after creating a user.\nTo do justice to my past self, here\u0026rsquo;s how to create a new user in a Docker container:\nSpin up a busybox container:\ndocker run -it --name c-user busybox sh Inside the container, add entries for user (and group), create home directory, change ownership and permissions, modify password and check:\n# Instead of the two commands below I used vim at the time echo \u0026#39;foo:x:88:88:foo:/home/foo:/bin/sh\u0026#39; \u0026gt;\u0026gt; /etc/passwd echo \u0026#39;bar:x:88:\u0026#39; \u0026gt;\u0026gt; /etc/group mkdir -p /home/foo chown foo:bar /home/foo chmod 700 /home/foo passwd foo # Enter password twice su - foo whoami # foo If we detach from the container (CTRL+P then CTRL+Q) we can run from outside:\ndocker exec -u foo c-user sh -c \u0026#39;echo Hello from $(whoami)\u0026#39; # foo Of course, managing users across multiple hosts and services is no longer done this way. Even back then, the lab relied on centralized authentication services (i.e. LDAP) and local users were mostly a pedagogical exercise.\nToday, identity and access management are handled through much more sophisticated systems, often integrated with cloud platforms and centralized authorization policies. But the underlying ideas are still there: users, groups, ownership, permissions, and the question of who is allowed to do what on a system. Because, in the end, almost everything either is or runs in Linux.\nThe bottom line is: if I were to teach Linux to someone, I would start by telling them to figure out how to create a new user. It is a great first example of learning beyond the abstraction layer. And even if it sounds like bait, surprisingly many engineers do not know how to do it.\n","permalink":"https://fabriciojm.github.io/posts/20260518-linux-user/","summary":"\u003cp\u003eAbout a half a life ago, I had my first Linux lesson, and the best so far. I was a freshman at uni and started learning Linux at \u003ca href=\"https://www.ldc.usb.ve\"\u003eLaboratorio Docente de Computación\u003c/a\u003e. After a few weeks there, the first important homework was a seemingly simple one: create a new user (your user) in a Linux machine using the terminal.\u003c/p\u003e\n\u003cp\u003eBut there\u0026rsquo;s a catch (see what I\u0026rsquo;m doing here?): \u003cstrong\u003eno\u003c/strong\u003e \u003ccode\u003eadduser\u003c/code\u003e or \u003ccode\u003euseradd\u003c/code\u003e scripts allowed. I could bring my notes but not my laptop.\u003c/p\u003e","title":"My First and Best Linux Lesson"}]