<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shaishav Kumar | @wiresurfer</title>
    <description>The latest articles on DEV Community by Shaishav Kumar | @wiresurfer (@wiresurfer).</description>
    <link>https://dev.to/wiresurfer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1966132%2F87ed9064-7fc6-4e82-8ac3-17a0d9be9494.jpg</url>
      <title>DEV Community: Shaishav Kumar | @wiresurfer</title>
      <link>https://dev.to/wiresurfer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wiresurfer"/>
    <language>en</language>
    <item>
      <title>Manage Sensitive API Keys in Public Dotfiles Using PGP and SOPS</title>
      <dc:creator>Shaishav Kumar | @wiresurfer</dc:creator>
      <pubDate>Wed, 11 Sep 2024 09:58:38 +0000</pubDate>
      <link>https://dev.to/wiresurfer/manage-sensitive-api-keys-in-public-dotfiles-using-pgp-and-sops-5mn</link>
      <guid>https://dev.to/wiresurfer/manage-sensitive-api-keys-in-public-dotfiles-using-pgp-and-sops-5mn</guid>
      <description>&lt;p&gt;In modern development environment, it’s common to host dotfiles&lt;br&gt;
publicly—especially for sharing across machines or with the broader developer&lt;br&gt;
community. However, this convenience introduces security risks, such as&lt;br&gt;
accidentally exposing sensitive information like API keys, tokens, and&lt;br&gt;
credentials in public repositories. API keys for services like OpenAI,&lt;br&gt;
Anthropic, Google Cloud, and more, if exposed, can lead to security breaches and&lt;br&gt;
unauthorized access.&lt;/p&gt;



&lt;p&gt;Imagine pushing your meticulously crafted dotfiles to GitHub, only to realize&lt;br&gt;
hours later that you've just exposed your OpenAI API key to the entire internet.&lt;br&gt;
Sounds like a nightmare? Unfortunately, it's an all-too-common reality for many&lt;br&gt;
developers.&lt;/p&gt;

&lt;p&gt;The recent explosion of interest in AI development has brought a wave of&lt;br&gt;
excitement - and a flood of new developers eager to experiment with powerful AI&lt;br&gt;
APIs. From ChatGPT, anthropic to midjourney, flux, these tools are reshaping how&lt;br&gt;
we approach software development.&lt;/p&gt;

&lt;p&gt;But with great power comes great responsibility, and I've noticed an alarming&lt;br&gt;
trend: more and more developers, especially those new to development, are&lt;br&gt;
accidentally exposing their API keys and other sensitive credentials in public&lt;br&gt;
repositories.&lt;/p&gt;

&lt;p&gt;This isn't just a rookie mistake - even seasoned developers can fall into this&lt;br&gt;
trap when rushing to share their latest AI project or dotfiles setup. The&lt;br&gt;
consequences can be severe: unauthorized API usage, compromised accounts, and in&lt;br&gt;
some cases, significant financial losses. It's this recurring issue that&lt;br&gt;
compelled me to write this guide. We need a solution that's both secure and&lt;br&gt;
accessible, especially for those just starting their journey in AI development.&lt;/p&gt;

&lt;p&gt;In today's interconnected development landscape, we often find ourselves walking&lt;br&gt;
a tightrope between convenience and security. We want to share our development&lt;br&gt;
setups across multiple machines, collaborate with team members, and contribute&lt;br&gt;
to the open-source community. But how do we do this without compromising our&lt;br&gt;
sensitive data? This post delves into a bare bones solution for this pervasive&lt;br&gt;
problem. We'll explore how to leverage the power of PGP encryption and Mozilla's&lt;br&gt;
SOPS to create a system where your API keys, tokens, and other secrets remain&lt;br&gt;
hidden, even in public repositories. By the end of this guide, you'll have a&lt;br&gt;
Unix-native, cost-effective method to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Securely store sensitive data in your dotfiles&lt;/li&gt;
&lt;li&gt;Easily share your development setup across multiple machines&lt;/li&gt;
&lt;li&gt;Maintain the convenience of public repositories without sacrificing security&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whether you're a solo developer juggling multiple AI projects or part of a team&lt;br&gt;
managing shared configurations, this guide will provide you with the tools to&lt;br&gt;
keep your secrets... well, secret. Let's dive in and transform those vulnerable&lt;br&gt;
dotfiles into a fortress of security!&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Functional Requirements
&lt;/li&gt;
&lt;li&gt;  Solutions Considered
&lt;/li&gt;
&lt;li&gt;  Solution Blueprint
&lt;/li&gt;
&lt;li&gt;  PGP
&lt;/li&gt;
&lt;li&gt;  SOPS
&lt;/li&gt;
&lt;li&gt;  Setting up SOPS with PGP
&lt;/li&gt;
&lt;li&gt;  Conclusion
&lt;/li&gt;
&lt;li&gt;  TLDR
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Functional Requirements
&lt;/h2&gt;

&lt;p&gt;Before diving into the solution, let’s outline the functional and non-functional&lt;br&gt;
requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Must work as early as &lt;code&gt;.profile&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Should enable easy sharing of the same setup across multiple machines.&lt;/li&gt;
&lt;li&gt;  Must remain as &lt;strong&gt;Unix-native&lt;/strong&gt; as possible (i.e., avoid desktop password
managers or proprietary key-sharing solutions).&lt;/li&gt;
&lt;li&gt;  Should not introduce ongoing costs for key management.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Solutions Considered
&lt;/h2&gt;

&lt;p&gt;Here are the primary options we explored for managing sensitive data in&lt;br&gt;
dotfiles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Enterprise Tools&lt;/strong&gt;: Solutions like HashiCorp Vault or Azure KMS offer
robust key management but come with added complexity and cost.

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Pros&lt;/strong&gt;: Secure, widely used, highly customizable.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cons&lt;/strong&gt;: Requires maintenance, has a learning curve, and may incur
costs for smaller teams.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Password Managers or Secret Managers&lt;/strong&gt;: Storing secrets in managers like
LastPass or Bitwarden is an option.

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Pros&lt;/strong&gt;: Easy to use, available on multiple platforms.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cons&lt;/strong&gt;: Not ideal for dotfiles or Unix-native environments; overkill
for this use case.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;PGP + SOPS&lt;/strong&gt;: This is the Unix-native method we will focus on. It’s
simple, secure, and there’s no ongoing cost. &lt;strong&gt;PGP&lt;/strong&gt; encrypts your secrets,
and &lt;strong&gt;SOPS&lt;/strong&gt; manages them effortlessly.

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Pros&lt;/strong&gt;: Cost-effective, simple, Unix-friendly.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cons&lt;/strong&gt;: Requires knowledge of PGP and some configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Solution Blueprint
&lt;/h2&gt;

&lt;p&gt;To manage your secrets in public dotfiles, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  [ ] Install PGP (&lt;code&gt;gpg&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  [ ] Install Mozilla SOPS.&lt;/li&gt;
&lt;li&gt;  [ ] Generate a PGP key and store it securely.&lt;/li&gt;
&lt;li&gt;  [ ] Create a secrets file (&lt;code&gt;~/secrets.env&lt;/code&gt;) outside of your git repository.&lt;/li&gt;
&lt;li&gt;  [ ] Use PGP and SOPS to encrypt the secrets file and commit the encrypted
    version to your dotfiles (&lt;code&gt;~/dot-files/secrets.gpg.env&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  [ ] Modify your &lt;code&gt;.profile&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt; to decrypt and source the secrets
    directly into memory on startup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a diagram to visualize the solution flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frg0jp3a1fonlhwi7jzg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frg0jp3a1fonlhwi7jzg6.png" alt="For the visual learner, here's sops + keymanagement with 1password value.  We use pgp instead" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  PGP
&lt;/h3&gt;

&lt;p&gt;PGP is a powerful encryption system that uses &lt;strong&gt;public-key cryptography&lt;/strong&gt;. In&lt;br&gt;
our solution, the &lt;strong&gt;client&lt;/strong&gt; (your machine) uses a &lt;strong&gt;public key&lt;/strong&gt; to encrypt the&lt;br&gt;
data, and the &lt;strong&gt;server&lt;/strong&gt; (or another machine) uses a &lt;strong&gt;private key&lt;/strong&gt; to decrypt&lt;br&gt;
it.&lt;/p&gt;

&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You encrypt your secrets file using your public PGP key.&lt;/li&gt;
&lt;li&gt;  On the machine where you need the secrets (such as a server), you decrypt
the file using the corresponding private key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re unfamiliar with PGP’s encryption mechanism, read this simplified&lt;br&gt;
explanation of&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Web_of_trust#Simplified_Explanation" rel="noopener noreferrer"&gt;Web of Trust&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  SOPS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SOPS (Secrets OPerationS)&lt;/strong&gt;, created by Mozilla, is a powerful tool that makes&lt;br&gt;
working with encrypted files easy. It supports PGP, AWS KMS, Google Cloud KMS,&lt;br&gt;
and other encryption systems.&lt;/p&gt;

&lt;p&gt;For our solution, we’ll use PGP with SOPS. SOPS ensures the secrets are&lt;br&gt;
encrypted in place and can easily be decrypted when needed. You can either use a&lt;br&gt;
&lt;strong&gt;single PGP key&lt;/strong&gt; for all your environments or assign a unique key for each&lt;br&gt;
service.&lt;/p&gt;

&lt;p&gt;In more complex setups, you might want to look into using &lt;strong&gt;AWS KMS&lt;/strong&gt; to manage&lt;br&gt;
your keys, as it decouples key management from access credentials, which offers&lt;br&gt;
a higher level of security for larger teams.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up SOPS with PGP
&lt;/h2&gt;

&lt;p&gt;Let’s walk through the step-by-step process of setting up &lt;strong&gt;SOPS&lt;/strong&gt; with &lt;strong&gt;PGP&lt;/strong&gt;&lt;br&gt;
to secure your secrets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install PGP and SOPS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate a PGP key&lt;/strong&gt; by running &lt;code&gt;gpg --gen-key&lt;/code&gt; and configuring as follows:

&lt;ul&gt;
&lt;li&gt;Key type: RSA and RSA&lt;/li&gt;
&lt;li&gt;Key size: 2048&lt;/li&gt;
&lt;li&gt;Expiration: 0 (never expires)&lt;/li&gt;
&lt;li&gt;Real name: "{repo} PGP"&lt;/li&gt;
&lt;li&gt;Email: "{email}"&lt;/li&gt;
&lt;li&gt;Comment: "PGP credentials for {repo} secrets"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create an encrypted secrets file&lt;/strong&gt; using SOPS:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;sops &lt;span class="nt"&gt;--pgp&lt;/span&gt; &lt;span class="s1"&gt;'{full_fingerprint}'&lt;/span&gt; secret.enc.yml
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Store your private key securely&lt;/strong&gt;, for instance, in a cloud vault or&lt;br&gt;
outside the git repository:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--export-secret-keys&lt;/span&gt; &lt;span class="nt"&gt;--armor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;fingerprint&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; private.rsa
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Modify your &lt;code&gt;.profile&lt;/code&gt; to decrypt the secrets on startup&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;sops &lt;span class="nt"&gt;--decrypt&lt;/span&gt; ~/dot-files/secrets.gpg.env | xargs&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we've explored in this guide, managing sensitive information in public&lt;br&gt;
dotfiles is not just a best practice—it's a critical component of modern secure&lt;br&gt;
development, especially in the rapidly evolving world of AI and machine&lt;br&gt;
learning.&lt;/p&gt;

&lt;p&gt;By leveraging the power of PGP and SOPS, we've unlocked a robust, Unix-native&lt;br&gt;
solution that allows us to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Encrypt our secrets securely, ensuring they're only accessible to intended
recipients&lt;/li&gt;
&lt;li&gt;Share our development setups across multiple machines without compromising
security&lt;/li&gt;
&lt;li&gt;Contribute to open-source projects and share our dotfiles publicly with
confidence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach scales well from individual developers to small and medium-sized&lt;br&gt;
teams, integrating seamlessly with existing Unix-like environments. It's&lt;br&gt;
particularly valuable for those working with AI APIs, where exposed credentials&lt;br&gt;
can lead to significant security breaches and unexpected costs.&lt;/p&gt;

&lt;p&gt;Remember, as you continue your journey in AI development or any field requiring&lt;br&gt;
API keys and other secrets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Regularly audit your public repositories for any accidentally exposed
credentials&lt;/li&gt;
&lt;li&gt;  Consider implementing this PGP + SOPS solution as part of your standard
development workflow&lt;/li&gt;
&lt;li&gt;  Educate your team or community about the importance of secure credential
management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those looking to take their security posture to the next level, consider&lt;br&gt;
exploring more advanced setups supported by SOPS, such as integrating with AWS&lt;br&gt;
KMS for larger-scale key management, or incorporating these practices into your&lt;br&gt;
CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;Securing your secrets doesn't have to come at the cost of collaboration or&lt;br&gt;
convenience. With the approach outlined in this guide, you can embrace the open,&lt;br&gt;
sharing culture of the developer community while keeping your sensitive&lt;br&gt;
information locked down tight.&lt;/p&gt;

&lt;p&gt;Stay curious, keep experimenting with AI, and above all, keep your secrets&lt;br&gt;
secret. Happy (and secure) coding!&lt;/p&gt;

&lt;p&gt;Here's the steps in a single "not thoroghly tested" bash script. It should be&lt;br&gt;
easy to follow and even easier to fix&lt;/p&gt;
&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Greybeard Territory: Proceed with Caution ⚠️&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the Impatient Greybeards: The All-in-One Setup Script&lt;/p&gt;

&lt;p&gt;The following section contains a bash script that automates the entire setup&lt;br&gt;
process. It's for those who prefer to dive in headfirst and tweak things&lt;br&gt;
later. If you're new to this, we strongly recommend following the step-by-step&lt;br&gt;
guide above instead.&lt;/p&gt;

&lt;p&gt;Remember: With great power comes great responsibility. This script will make&lt;br&gt;
changes to your system. Review it carefully before running, and maybe pour&lt;br&gt;
yourself a strong cup of coffee first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For those of you who scoffed at the detailed explanations and just want to get&lt;br&gt;
things running, here's a bash script that sets up the entire PGP + SOPS&lt;br&gt;
environment in one go. It's not thoroughly tested, so consider this a starting&lt;br&gt;
point for your own customized setup.&lt;/p&gt;

&lt;p&gt;To use this script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save it as &lt;code&gt;setup_secrets.sh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make it executable: &lt;code&gt;chmod +x setup_secrets.sh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run it: &lt;code&gt;./setup_secrets.sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, this script is a starting point. You might need to adjust it based on&lt;br&gt;
your specific environment or requirements. And as always, review any script&lt;br&gt;
carefully before running it on your system.&lt;/p&gt;

&lt;p&gt;Now, for those of you who skipped straight to this section: go back and read the&lt;br&gt;
rest of the post. There's valuable context and explanations up there that will&lt;br&gt;
help you understand what this script is actually doing. Don't say we didn't warn&lt;br&gt;
you!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Function to confirm actions from the user&lt;/span&gt;
confirm&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;Are&lt;/span&gt;&lt;span class="p"&gt; you sure? [y/N]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt; response
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;yY][eE][sS]|[yY]&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nb"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nb"&gt;false&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Install GPG (GNU Privacy Guard)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;confirm &lt;span class="s2"&gt;"Do you want to install GPG (GNU Privacy Guard)? [y/N]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Installing GPG..."&lt;/span&gt;
    &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
    &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; gnupg
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Skipping GPG installation."&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Install SOPS (Secrets OPerationS)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;confirm &lt;span class="s2"&gt;"Do you want to install Mozilla SOPS? [y/N]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Installing SOPS..."&lt;/span&gt;
    wget https://github.com/mozilla/sops/releases/download/v3.7.3/sops-v3.7.3.linux &lt;span class="nt"&gt;-O&lt;/span&gt; sops
    &lt;span class="nb"&gt;chmod&lt;/span&gt; +x sops
    &lt;span class="nb"&gt;sudo mv &lt;/span&gt;sops /usr/local/bin/
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Skipping SOPS installation."&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Remove SOPS default PGP keys&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;confirm &lt;span class="s2"&gt;"Do you want to remove any default SOPS PGP keys? [y/N]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Listing GPG keys..."&lt;/span&gt;
    gpg &lt;span class="nt"&gt;--list-keys&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Enter the fingerprint of the key you want to delete (or press Enter to skip):"&lt;/span&gt;
    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; fingerprint
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$fingerprint&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deleting key with fingerprint &lt;/span&gt;&lt;span class="nv"&gt;$fingerprint&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
        gpg &lt;span class="nt"&gt;--delete-keys&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$fingerprint&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        gpg &lt;span class="nt"&gt;--delete-secret-keys&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$fingerprint&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No keys deleted."&lt;/span&gt;
    &lt;span class="k"&gt;fi
else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Skipping sops default key deletion."&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="c"&gt;# Generate a GPG key&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;confirm &lt;span class="s2"&gt;"Do you want to generate a new GPG key for encrypting secrets? [y/N]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Generating GPG key..."&lt;/span&gt;
    gpg &lt;span class="nt"&gt;--gen-key&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Skipping GPG key generation."&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Create the secrets.env file&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;confirm &lt;span class="s2"&gt;"Do you want to create a new secrets.env file at ~/secrets.env? [y/N]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating a new secrets.env file at ~/secrets.env..."&lt;/span&gt;
    &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOL&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; ~/secrets.env
# Add your secrets here in KEY=VALUE format
API_KEY=your_api_key_here
SECRET_KEY=your_secret_key_here
&lt;/span&gt;&lt;span class="no"&gt;EOL
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Created secrets.env. Please add your sensitive data."&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Skipping secrets.env creation."&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# List available GPG keys and their fingerprints&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Encrypting your ~/secrets.env"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Select Available GPG keys:"&lt;/span&gt;
gpg &lt;span class="nt"&gt;--list-keys&lt;/span&gt; &lt;span class="nt"&gt;--fingerprint&lt;/span&gt;

&lt;span class="c"&gt;# Ask the user to select a GPG key fingerprint&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Enter the fingerprint of the GPG key you want to use for encryption:"&lt;/span&gt;
&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; fingerprint

&lt;span class="c"&gt;# Check if the user input is empty&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$fingerprint&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No fingerprint provided. Aborting encryption."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Encrypt the secrets.env file using the selected fingerprint and save it as secrets.gpg.env&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/secrets.env &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Encrypting secrets.env into secrets.gpg.env..."&lt;/span&gt;
    sops &lt;span class="nt"&gt;--encrypt&lt;/span&gt; &lt;span class="nt"&gt;--pgp&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$fingerprint&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; ~/secrets.env &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/secrets.gpg.env
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Encryption complete. Encrypted file saved as ~/secrets.gpg.env"&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"secrets.env not found in home directory. Please create it first."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Setup complete!"&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;PGP vs. SSH Encryption:
&lt;a href="https://en.wikipedia.org/wiki/Web_of_trust#Simplified_Explanation" rel="noopener noreferrer"&gt;Link to Wikipedia&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SOPS GitHub Repo:
&lt;a href="https://github.com/mozilla/sops/tree/0494bc41911bc6e050ddd8a5da2bbb071a79a5b7#up-and-running-in-60-seconds" rel="noopener noreferrer"&gt;SOPS on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Here's a great info-graphic of all the ways sops can be used by the good
folks at GitGuardian

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.gitguardian.com/files/securityzines-sops?ref=blog.gitguardian.com" rel="noopener noreferrer"&gt;Infographic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.gitguardian.com/a-comprehensive-guide-to-sops/" rel="noopener noreferrer"&gt;Blog post&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;




</description>
      <category>security</category>
      <category>devops</category>
      <category>linux</category>
      <category>bash</category>
    </item>
    <item>
      <title>Unleash the Forbidden - Enabling eBPF/XDP for Kernel Tinkering on WSL2</title>
      <dc:creator>Shaishav Kumar | @wiresurfer</dc:creator>
      <pubDate>Fri, 23 Aug 2024 07:39:00 +0000</pubDate>
      <link>https://dev.to/wiresurfer/unleash-the-forbidden-enabling-ebpfxdp-for-kernel-tinkering-on-wsl2-43fj</link>
      <guid>https://dev.to/wiresurfer/unleash-the-forbidden-enabling-ebpfxdp-for-kernel-tinkering-on-wsl2-43fj</guid>
      <description>&lt;p&gt;Running eBPF on WSl2 running on Windows 10 feels forbidden. And yet, that's the entire premise of this blog. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Heck Would We Do That?
&lt;/h2&gt;

&lt;p&gt;As proud nerds, we find joy in understanding the deepest workings of our systems. Enabling eBPF in WSL2 is one of those pursuits that opens up a world of debugging possibilities. It allows us to use eBPF tools, provides full tracing support via DebugFS, and gives us insights into WSL2's networking stack. This article will guide you through enabling eBPF in WSL2. Future posts will delve deeper into specific use cases and the fascinating world of eBPF.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08gfnsfrowj5dryejv5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08gfnsfrowj5dryejv5u.png" alt="Err! eBPF on WSL2 in Linux?|350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the Plan?
&lt;/h2&gt;

&lt;p&gt;We'll focus on enabling eBPF on Ubuntu 20.04 running on WSL2. You can try it on 18.04, but your mileage may vary. Here’s a high-level overview of what we’ll do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recompile the WSL2 kernel with specific eBPF-related flags enabled.&lt;/li&gt;
&lt;li&gt;Change the WSL2 configuration in Windows to point to our newly compiled kernel.&lt;/li&gt;
&lt;li&gt;Restart WSL2.&lt;/li&gt;
&lt;li&gt;Verify the new kernel is running and eBPF is enabled.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01876nagc4y269t6y1yo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01876nagc4y269t6y1yo.png" alt="How do you go about enabling eBPF and tracing on WSL2. Here's the plan|325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me the Code?!
&lt;/h2&gt;

&lt;p&gt;Let's get our hands dirty with some kernel compiling. hold tight.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install Dependencies
&lt;/h3&gt;

&lt;p&gt;First, make sure you have the necessary tools installed:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;build-essential libncurses-dev bison flex libssl-dev libelf-dev


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  2. Clone the WSL2 Kernel Source
&lt;/h3&gt;

&lt;p&gt;Download the source code of the WSL2 kernel:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WSL2-Linux-Kernel


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  3. Configure the Kernel
&lt;/h3&gt;

&lt;p&gt;Copy the default WSL2 kernel configuration:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cp &lt;/span&gt;Microsoft/config-wsl .config


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

&lt;/div&gt;

&lt;p&gt;Linux kernel devs have made it intuitive to toggle various features in the linux kernel using a handy TUI.&lt;br&gt;&lt;br&gt;
To edit the build configuration of the kernel we have three options. &lt;/p&gt;

&lt;p&gt;We use the TUI configurator, and then carefully toggle the features. Its gonna take a little more effort, but will let you see how you can change kernel characteristics. Great Learning, Would Recommend, at least once. :)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

make menuconfig


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

&lt;/div&gt;

&lt;p&gt;In the menu, navigate to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;General setup&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;code&gt;Debug Filesystem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BPF subsystem&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;code&gt;BPF syscall support&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Enable bpf() system call&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Enable extended BPF (eBPF) JIT&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;Networking support&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;code&gt;Networking options&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Packet socket&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Network packet filtering framework (Netfilter)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;BPF-based packet filtering framework&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;(optionally) Enable &lt;code&gt;XDP sockets&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;(optionally) Enable &lt;code&gt;XDP sockets: Monitoring interface&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;(optionally) enable &lt;code&gt;BPF_STREAM_PARSES&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;(optionally) go into &lt;code&gt;Network Testing&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Enable as Module (M) &lt;code&gt;Packet Generator (USE WITH CAUTION)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Alternatively, you can manually edit the &lt;code&gt;.config&lt;/code&gt; file and ensure the following options are set:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_NETFILTER_XT_MATCH_BPF=m
CONFIG_BPFILTER=y
CONFIG_BPFILTER_UMH=m


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

&lt;/div&gt;

&lt;p&gt;Third and probably the most uninspired way would be, well here is a prepared config file. Download this, and place it in the &lt;code&gt;WLS2-kernel&lt;/code&gt; folder. &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Compile the Kernel
&lt;/h3&gt;

&lt;p&gt;Compile the kernel with the new configuration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

make &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  5. Set WSL2 to Use the Custom Kernel
&lt;/h3&gt;

&lt;p&gt;Copy the compiled kernel to a suitable location:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cp arch&lt;/span&gt;/x86/boot/bzImage /mnt/c/wsl_custom_kernel


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

&lt;/div&gt;

&lt;p&gt;Edit your &lt;code&gt;.wslconfig&lt;/code&gt; file (create it if it doesn’t exist) in your Windows home directory (&lt;code&gt;C:\Users\&amp;lt;YourUsername&amp;gt;\.wslconfig&lt;/code&gt;) and add the following lines:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;

&lt;span class="nn"&gt;[wsl2]&lt;/span&gt;
&lt;span class="py"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;wsl_custom_kernel&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Restart the WSL2 instance to apply the new kernel:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--shutdown&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  6. Verify the New Kernel and eBPF
&lt;/h3&gt;

&lt;p&gt;Check if your new kernel is running:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You should see a version number corresponding to your custom kernel build.&lt;/p&gt;

&lt;p&gt;Verify eBPF support:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;ls&lt;/span&gt; /sys/kernel/debug


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

&lt;/div&gt;

&lt;p&gt;You should see &lt;code&gt;bpf&lt;/code&gt; listed among the directories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy Kernel Hacking!
&lt;/h2&gt;

&lt;p&gt;Congratulations! You've successfully enabled eBPF in WSL2. This setup will serve as a solid foundation for further kernel debugging and customization. Stay tuned for future posts where we'll dive deeper into utilizing these capabilities for various debugging tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6ie0ja0j5lz0qqqbe1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6ie0ja0j5lz0qqqbe1y.png" alt="Come to the Future, Around the Back"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;](&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n60s5eaj03ldp8rup8el.png" rel="noopener noreferrer"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n60s5eaj03ldp8rup8el.png&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When using &lt;code&gt;make menuconfig&lt;/code&gt; to change the kernel compilation options, I want to highlight some data-centre or Edge site specific options. These show up once in a while and for the curious, it might be worth a few clicks and research. 

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Networking support&lt;/code&gt; 

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Enable MPTCP&lt;/code&gt; : &lt;a href="https://www.redhat.com/en/blog/understanding-multipath-tcp-networking-highway-future#:~:text=MPTCP%20is%20an%20evolutionary%20step,no%20obstruction%20for%20miles%20ahead." rel="noopener noreferrer"&gt;&lt;strong&gt;MPTCP&lt;/strong&gt;&lt;/a&gt; is an evolutionary step forward for the TCP protocol to enable redundancy for multiple network connections for any device. Your phone with Wifi and Mobile 5G. yup, you guessed it. It can use MPTCP to route data over both these network paths. Some OEMs enable this, or else, in the wild west, there are some AOSP kernels which are compiled with this flag on. &lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;HSR/PRP  High Availability Seamless Redundancy&lt;/code&gt;: Another one of those esoteric protocols which aims to solve the high available, automatic failover network links problem. You would find this in router kernels like pfSense. It operated on Layer1/2 and somewhat similar in spirit to what MPTCP does it across two different Layer 1/2 links but redundant on a Layer 3+ level.&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Open vSwitch&lt;/code&gt; : &lt;a href="https://docs.openvswitch.org/en/latest/intro/what-is-ovs/" rel="noopener noreferrer"&gt;Open vSwitch&lt;/a&gt; is an open-source implementation of a distributed virtual multilayer switch. It provides a switching stack for hardware virtualization environments, while supporting multiple protocols and standards used in computer networks.&lt;/li&gt;
&lt;li&gt;Enable &lt;code&gt;Netlink: socket monitoring tool&lt;/code&gt;: Netlink is used by &lt;a href="https://www.man7.org/linux/man-pages/man8/ss.8.html" rel="noopener noreferrer"&gt;SS&lt;/a&gt;. a socket monitoring tool which can dump linux socket statistics. its like netstat on steroids with more TCP state information. Very useful in debugging odd TCP network congestion and timing related bugs. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Note that under &lt;code&gt;Networking Support&lt;/code&gt;, there's an option &lt;code&gt;Hyper - V transport  for Virtual Sockets&lt;/code&gt; which is enabled. This is a Microsoft contributed transport module which enables network packets to escape via a virtual socket onto a hyper V network switch. Its a good source code read for someone interested. &lt;/li&gt;

&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;Have feedback or questions, or want to be notified about more such articles? Follow me on Twitter &lt;a href="https://x.com/wiresurfer" rel="noopener noreferrer"&gt;@wiresurfer&lt;/a&gt; &amp;gt; &lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>linux</category>
      <category>performance</category>
      <category>devops</category>
      <category>tooling</category>
    </item>
    <item>
      <title># Booting up Linux Kernel - Linux for Engineers #1</title>
      <dc:creator>Shaishav Kumar | @wiresurfer</dc:creator>
      <pubDate>Thu, 22 Aug 2024 18:18:05 +0000</pubDate>
      <link>https://dev.to/wiresurfer/-booting-up-linux-kernel-linux-for-engineers-1-2lk1</link>
      <guid>https://dev.to/wiresurfer/-booting-up-linux-kernel-linux-for-engineers-1-2lk1</guid>
      <description>&lt;p&gt;Ever wondered what happens when your Linux machine starts? There is a&lt;br&gt;
fascinating song and dance between different components which brings a machine&lt;br&gt;
to life. Lets dive into the world of booting Linux Kernel.&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;Linux kernel is a monumental achievement of collaboration in the world of&lt;br&gt;
open-source software.&lt;br&gt;&lt;br&gt;
 It has resulted in a powerful, versatile operating system base that powers an&lt;br&gt;
estimated 80-90% of the modern tech world&lt;br&gt;&lt;br&gt;
 From smartphones in our pockets to the vast cloud infrastructure, Linux is&lt;br&gt;
the backbone of many technologies we rely on daily.&lt;br&gt;&lt;br&gt;
 This series chronicles different aspects of modern day Linux system.&lt;br&gt;&lt;br&gt;
 Each article aims to be a &lt;strong&gt;tldr;&lt;/strong&gt; While linking to amazing&lt;br&gt;
talks/presentations/articles by some great minds.&lt;br&gt;&lt;br&gt;
 Treat this as a crash course for the lazy and a jump-off point for the&lt;br&gt;
curious.&lt;br&gt;&lt;br&gt;
 Happy reading!&lt;br&gt;&lt;br&gt;
 Have feedback or questions, or want to be notified about more such articles?&lt;br&gt;
Follow me on Twitter &lt;a href="https://x.com/wiresurfer" rel="noopener noreferrer"&gt;@wiresurfer&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  ⚡ And then there was light! ⚡
&lt;/h2&gt;

&lt;p&gt;Ever wondered what happens when you press the power button on your machines.&lt;br&gt;&lt;br&gt;
The fan's come to life, your RGB lights light up, there is a bell sound, and the&lt;br&gt;
screen shows a sea of gibberish [or if you started using laptops, you probably&lt;br&gt;
see a fancy logo and a spinner. How boring is that!]&lt;br&gt;&lt;br&gt;
By the end of this article, I want to unwrap the song and dance that goes on&lt;br&gt;
between hardware and different types of software to finally bring to you a&lt;br&gt;
usable PC.&lt;/p&gt;

&lt;p&gt;I won't hold back on some technical details and gloss over some in the interest&lt;br&gt;
of salvaging some brevity.&lt;/p&gt;

&lt;p&gt;This post in particular will have a buildup and posturing in the beginning about&lt;br&gt;
hardware, bios and grub.&lt;br&gt;&lt;br&gt;
While it isn't absolutely necessary for a Linux Kernel bootup saga, I do feel&lt;br&gt;
its important for a well rounded understanding.&lt;/p&gt;

&lt;p&gt;For the impatient, feel free to jump to&lt;br&gt;
Linux Kernel Bootup Sequence&lt;/p&gt;


&lt;h2&gt;
  
  
  🖥️ Modern PC Architecture
&lt;/h2&gt;

&lt;p&gt;A modern day PC hasn't changed its core design philosophy for over 30 years.&lt;br&gt;
Yes, there has been miniaturization and our electronics design has improved by&lt;br&gt;
leaps and bounds, but the basic building blocks have remained the same.&lt;br&gt;&lt;br&gt;
Here is a picture of a motherboard annotated to show different subsystems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zc4qyw1x0ijcob6zj05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zc4qyw1x0ijcob6zj05.png" alt="Modern PC Architecture. Its been this way for decades|600" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even this can be simplified down to the following block diagram.&lt;br&gt;&lt;br&gt;
If you pay attention, most of the peripherals used with modern machines connect&lt;br&gt;
over the PCI express bus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2noetyecj9xgiwllz0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2noetyecj9xgiwllz0s.png" alt="North/South Bridge on a Motherboard" width="800" height="770"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Most demanding high throughput devices are the graphics cards and memory&lt;br&gt;
modules. They attach directly to the CPU over dedicated lanes often referred&lt;br&gt;
to as the &lt;strong&gt;Northbridge&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Southbridge&lt;/strong&gt; on the other hand is a separate bus controller which manages&lt;br&gt;
other peripherals and connects to the CPU with a dedicated link.&lt;br&gt;
[&lt;a href="https://en.wikipedia.org/wiki/Direct_Media_Interface" rel="noopener noreferrer"&gt;&lt;strong&gt;D&lt;/strong&gt;irect &lt;strong&gt;M&lt;/strong&gt;edia &lt;strong&gt;I&lt;/strong&gt;nterface or DMI3.0 is an Intel specific link&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing omitted in this block diagram is a plethora of&lt;br&gt;
&lt;a href="https://www.wevolver.com/article/i2c-vs-uart" rel="noopener noreferrer"&gt;i2c, uart, serial &lt;/a&gt;,&lt;br&gt;
&lt;a href="https://www.ekwb.com/blog/what-is-pwm-and-how-does-it-work/" rel="noopener noreferrer"&gt;PWM&lt;/a&gt; and GPIO&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;br&gt;
which help the motherboard maintain its function.&lt;/p&gt;

&lt;p&gt;Notable peripherals in a motherboard include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  CMOS Clock [helps with timekeeping specially in embedded devices. Modern
OS's often use NTP to sync time]&lt;/li&gt;
&lt;li&gt;  Temperature Sensors &lt;sup id="fnref2"&gt;2&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;  PWM controllers for fan control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first step in bringing the computer to working order is performed by a&lt;br&gt;
special program called the BIOS which is programmed onto a ROM chip on the&lt;br&gt;
motherboard, right from the factory. Lets see what happens in the BIOS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkafs5m04wxal66i5vmah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkafs5m04wxal66i5vmah.png" alt="High level Sequence of Boot up Steps |475" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🧩 BIOS and Power-On Self Test (POST)
&lt;/h2&gt;

&lt;p&gt;BIOS is an embedded program responsible for starting the computer and performing&lt;br&gt;
a POST (Power-On Self Test). UEFI is the new modern reincarnation on the BIOS&lt;br&gt;
and the new kid on the block. From the Linux kernel bootup perspective, BIOS vs&lt;br&gt;
UEFI has limited implications in the startup process&lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewtw99tvqtobtot5mfiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewtw99tvqtobtot5mfiv.png" alt="Minimum POST checks at startup. Pic Credit: CGDirector.com |475" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Power-On Self Test (POST):&lt;/strong&gt; During POST, the BIOS initializes the CPU and
memory subsystem. It checks if these components are functioning correctly. If
they start properly, the computer is ready to boot. However, this depends on
the rest of the hardware functioning correctly as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware Initialization:&lt;/strong&gt; The BIOS initializes and lists all other
peripheral hardware attached to the system. These peripherals are generally
connected via buses like I2C, PCI Express, and SATA, which connect them to
the CPU&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CMOS Battery Check:&lt;/strong&gt; Keeping correct time is important. Not so critical
these days, but back in the day, a depleted CMOS battery could lead to a lot
of mess. Often a motherboard would refuse to boot automatically if it
detected a fault in the CMOS Clock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAM check&lt;/strong&gt;: Verify RAM speed and make sure the bus speed of various
subsystems are compatible. Overclockers tinker with the voltage levels of the
RAM and the CPU to force it to run at higher than prescribed clock speeds.
BIOS/UEFI these days protects such folks from frying up their threadripper/i9
cpu&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boot a Storage Device:&lt;/strong&gt; Try to find bootable storage devices. Either a
disk with Master Boot Record entries, or a GPT UUID partitioned disk.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc7qkvtlaszuv2f83u36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc7qkvtlaszuv2f83u36.png" alt="BIOS and UEFI both perform POST on motherboards. UEFI just happens to be with the times.|625" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Handing over to a Bootloader
&lt;/h3&gt;

&lt;p&gt;As we learned &lt;strong&gt;BIOS&lt;/strong&gt; acts as the first sanity check, initializing the system&lt;br&gt;
and performing POST. It hands over control to a &lt;strong&gt;Bootloader&lt;/strong&gt;, a somewhat more&lt;br&gt;
advanced program that is tasked with loading operating systems&lt;/p&gt;


&lt;h2&gt;
  
  
  💽 Bootloader and GRUB
&lt;/h2&gt;

&lt;p&gt;After POST, BIOS looks for special I/O devices to provide the next program to&lt;br&gt;
run, typically the bootloader.&lt;br&gt;&lt;br&gt;
Locating the bootloader is done by following a few conventions which have been&lt;br&gt;
in the PC world for decades. In short, BIOS has a configured set of boot&lt;br&gt;
devices. This preference is stored in the CMOS.&lt;/p&gt;

&lt;p&gt;After POST, BIOS will start going through each Boot Device and verify if it has&lt;br&gt;
a &lt;a href="https://en.wikipedia.org/wiki/Master_boot_record" rel="noopener noreferrer"&gt;Master Boot Record&lt;/a&gt;. This&lt;br&gt;
is where GRUB enters the picture. &lt;a href="https://en.wikipedia.org/wiki/GNU_GRUB" rel="noopener noreferrer"&gt;GRUB&lt;/a&gt;&lt;br&gt;
is a program residing in the Master Boot Record of a bootable device.&lt;/p&gt;

&lt;p&gt;Here is a quick anatomy of the Master Boot Record. Its the first sector of a&lt;br&gt;
disk. A disk sector is traditionally 512bytes. Modern disks have larger sectors&lt;br&gt;
up to 4096 bytes [Advanced Format Disks] but even these disks access the&lt;br&gt;
physical media in 512byte emulated mode [512e]&lt;/p&gt;

&lt;p&gt;512bytes of the MBR are broken up as follows&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  1-446bytes - Bootloader code. Grub &lt;strong&gt;boot.img&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  64 bytes - Master Partition Entries, Up to 4 entries, 16 bytes each.&lt;/li&gt;
&lt;li&gt;  Last 2bytes - A special magic number &lt;strong&gt;0xAA55&lt;/strong&gt;. This indicates to the BIOS,
there is a bootloader on this disk device.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that out of the way, lets look at GRUB as a bootloader.&lt;/p&gt;

&lt;p&gt;Now. lets be honest. 512bytes is a tight space, and adding things like splash&lt;br&gt;
image, nice graphics and menus to dual boot an OS will take way more than&lt;br&gt;
512bytes. For eg. &lt;a href="https://easybmp.sourceforge.net/" rel="noopener noreferrer"&gt;EasyBMP&lt;/a&gt; a tiny library to&lt;br&gt;
display images on screen when statically linked is 20kb!&lt;/p&gt;

&lt;p&gt;To work around this limitation, Grub does a multi-stage boot.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Stage 1&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;Boot.img&lt;/em&gt;&lt;/strong&gt;, Fits in 440byte MBR. Its a simple sled program&lt;br&gt;
which loads Stage 1.5 using a&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Logical_block_addressing" rel="noopener noreferrer"&gt;LBA address jump&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Stage 1.5&lt;/strong&gt;: &lt;em&gt;Core.img&lt;/em&gt;, Fits in 32kb. It has just enough file system modules&lt;br&gt;
to load &lt;em&gt;\/boot\/grub&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Stage 2:&lt;/strong&gt; &lt;em&gt;\/boot\/grub&lt;/em&gt; is a special folder in /boot partition or a path on&lt;br&gt;
the root / partition. This is where all grub modules are available. It contains&lt;br&gt;
module drives for a large set of IO devices including networking booting. It&lt;br&gt;
also brings some nice things like a GUI, selection menus and splash pages!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00ndo92d152yzo7y25fp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00ndo92d152yzo7y25fp.png" alt="Grub and MBR sector layout|500" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now all that theory out of the way, how do we boot the kernel itself? We usually&lt;br&gt;
just select a menu and boom! Linux starts loading up?&lt;br&gt;&lt;br&gt;
Well, there is a bunch of configuration files and menu entries which makes that&lt;br&gt;
happen. Just peek into &lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt;. But we aren't looking at GRUB and&lt;br&gt;
its magic. Lets try to boot a system by first principles.&lt;/p&gt;

&lt;p&gt;Here is the minimal set of commands you can use on a GRUB prompt to start a&lt;br&gt;
Linux system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;insmod linux
set root=(hd0,1)
linux /boot/vmlinuz-3.13.0-29-generic root=/dev/sda1
initrd /boot/initrd.img-3.13.0-29-generic
boot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick description of what's happening.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Load the linux grub module. This module tells grub how to start a Linux like
operating system.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;hd0,1&lt;/code&gt; - This is the tricky bit! This is grub's way of selecting a hard
drive partition. varies on each machine, depending on how it was
partitioned. This
&lt;a href="https://superuser.com/questions/182161/grub-how-find-partition-number-hd0-x" rel="noopener noreferrer"&gt;stackexchange discussion should come in handy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/boot/vmlinuz-3.13.0-29-generic&lt;/code&gt; is the compressed compiled linux kernel.
Tab completion is your friend. Version number &lt;code&gt;3.13.0&lt;/code&gt; would likely change
in your case.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/dev/sda1&lt;/code&gt; is the root file system device.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/boot/initrd.img-3.13.0-29-generic&lt;/code&gt; is the initial ram disk&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;boot&lt;/code&gt; kicks off the boot process and runs vmlinux.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we write boot, GRUB is officially trying to hand over control to the&lt;br&gt;
kernel. Phew!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Future Topics&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you're interested, I can cover BIOS and bootloader in more detail in future&lt;br&gt;
posts. However, for practicality, most of us won't be dealing directly with&lt;br&gt;
building BIOS or bootloaders. This high-level overview should provide a clear&lt;br&gt;
understanding of the initial steps in the boot sequence.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
   🐧 Linux Kernel Bootup Sequence
&lt;/h2&gt;

&lt;p&gt;Many seasoned developers have observed a Linux system boot up, witnessing a&lt;br&gt;
stream of text scrolling by on the screen. This output primarily consists of&lt;br&gt;
driver initializations and service startups. Despite its apparent complexity,&lt;br&gt;
the Linux kernel boot process is relatively straightforward. Let's delve into&lt;br&gt;
the most prevalent Linux kernel boot sequence&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffirkuquknuunq13lf6rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffirkuquknuunq13lf6rj.png" alt="Linux Boot Process in a Nutshell" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bare Minimum Linux Kernel?
&lt;/h3&gt;

&lt;p&gt;As we saw in the grub commands, achieving a minimal boot for a practical PC&lt;br&gt;
experience requires,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;vmlinuz&lt;/strong&gt; : Compressed compiled linux kernel binary&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;initramfs&lt;/strong&gt; or &lt;strong&gt;initrd&lt;/strong&gt; : compressed archive which can be expanded by
vmlinuz or grub and placed into memory&lt;/li&gt;
&lt;li&gt;  (additionally) &lt;strong&gt;root filesystem&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Linux follows a two stage booting process. The bootloader first loads the stage&lt;br&gt;
1 kernel.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage 1&lt;/em&gt; kernel's aim is simple and can be listed as follows&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Load just enough kernel modules to mount a proper filesystem.&lt;/li&gt;
&lt;li&gt;  Mount said root file system&lt;/li&gt;
&lt;li&gt;  Hand over control to an init executable in the root filesystem. (/init,
/sbin/init or configured paths in
&lt;a href="https://github.com/torvalds/linux/blob/4a4be1ad3a6efea16c56615f31117590fd881358/init/main.c#L1523" rel="noopener noreferrer"&gt;linux/init/main.c at torvalds/linux · GitHub&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because storage hardware comes in various formats (curse of linux's ubiquity),&lt;br&gt;
kernel developers have chosen to break the booting process into an initial&lt;br&gt;
in-memory file system load (&lt;strong&gt;Initramfs&lt;/strong&gt; or &lt;strong&gt;initrd&lt;/strong&gt;) which then mounts and&lt;br&gt;
loads the &lt;strong&gt;root filesystem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stage 2&lt;/em&gt; kernel boot is where the init process starts configuring hardware and&lt;br&gt;
running services, usually running programs initiated in userspace but invoking&lt;br&gt;
kernel space syscalls. This ensures the boot process can be configured without&lt;br&gt;
having to recompile the kernel for every small customizations. This design&lt;br&gt;
choice is the reason why we all aren't kernel developers (yet)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: About minimal linux&lt;br&gt;&lt;br&gt;
For a truly minimal boot experience we could have a stripped down &lt;strong&gt;vmlinuz&lt;/strong&gt;&lt;br&gt;
which runs a statically compiled &lt;em&gt;/sbin/init&lt;/em&gt; program to print hello world!&lt;br&gt;
all in &amp;lt; 10mbs of RAM, if you configure your kernel boot correctly!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initramfs&lt;/strong&gt; and &lt;strong&gt;initrd&lt;/strong&gt; (initial ramdisk) serve a similar purpose.&lt;br&gt;
initramfs is a modern take on initrd;&lt;br&gt;&lt;br&gt;
Write to me if you think I should write about the internals of&lt;br&gt;
initramfs/initrd.&lt;br&gt;&lt;br&gt;
PS: A quick search would point to some great resources.&lt;br&gt;&lt;br&gt;
I do find&lt;br&gt;
&lt;a href="https://www.baeldung.com/linux/initrd-vs-initramfs" rel="noopener noreferrer"&gt;What’s the Difference Between initrd and initramfs? | Baeldung on Linux&lt;/a&gt;&lt;br&gt;
a good reference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🌴 Root File System : Linux Kernel Directory Structure
&lt;/h2&gt;

&lt;p&gt;Upon starting, the Linux kernel prepares and virtually presents some special&lt;br&gt;
file system in a specific way. The root file system and the initial RAM file&lt;br&gt;
system (initramfs) are crucial parts of this structure.&lt;br&gt;&lt;br&gt;
Initramfs is the first file system that the kernel mounts and operates in&lt;br&gt;
memory, rather than on disk.&lt;br&gt;&lt;br&gt;
Root filesystem is then loaded and presents more kernel modules, libraries,&lt;br&gt;
binary utilities and daemons.&lt;br&gt;&lt;br&gt;
The root filesystem also starts various daemons which could further mount other&lt;br&gt;
storage devices and filesystems.&lt;/p&gt;

&lt;p&gt;We need to be aware of &lt;code&gt;/proc&lt;/code&gt; and &lt;code&gt;/sys&lt;/code&gt; directories, which contain information&lt;br&gt;
about the running kernel and allow certain kernel parameters to be modified.&lt;br&gt;&lt;br&gt;
We also need to learn how all these file systems are combined together to&lt;br&gt;
provide a singular working view of the running system using overlayfs&lt;/p&gt;

&lt;h3&gt;
  
  
  Init Process and the Role of PID 1: systemd and upstart in modern linux distros
&lt;/h3&gt;

&lt;p&gt;In the world of Linux, PID 1 holds a special place. PID 1, or Process ID 1, is&lt;br&gt;
the first process started by the Linux kernel during the boot sequence and is&lt;br&gt;
the ancestor of all other processes. Understanding PID 1 and its role is crucial&lt;br&gt;
for grasping how a Linux system initializes and manages services.&lt;/p&gt;

&lt;p&gt;When the Linux kernel finishes its initial setup, it launches the first&lt;br&gt;
user-space process, which is assigned PID 1. Traditionally, this process was the&lt;br&gt;
&lt;code&gt;init&lt;/code&gt; system, responsible for starting system processes, handling system&lt;br&gt;
initialization, and managing services. The &lt;code&gt;init&lt;/code&gt; system follows a predefined&lt;br&gt;
sequence to bring the system to a usable state.&lt;/p&gt;

&lt;p&gt;PID 1 is critical because it remains running as long as the system is up and&lt;br&gt;
serves as the parent for all other processes. If PID 1 terminates, the kernel&lt;br&gt;
will panic, causing the system to halt or reboot, as there would be no process&lt;br&gt;
to adopt orphaned child processes.&lt;/p&gt;

&lt;h4&gt;
  
  
  systemd as init
&lt;/h4&gt;

&lt;p&gt;In modern Linux distributions, &lt;code&gt;systemd&lt;/code&gt; has largely replaced the traditional&lt;br&gt;
&lt;code&gt;init&lt;/code&gt; system as the default system and service manager. &lt;code&gt;systemd&lt;/code&gt; is designed&lt;br&gt;
to provide a more efficient and feature-rich way of managing system processes&lt;br&gt;
and services. It still occupies the PID 1 slot and takes on the responsibilities&lt;br&gt;
of its predecessor but with enhanced capabilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  How systemd Works?
&lt;/h4&gt;

&lt;p&gt;When the kernel passes control to &lt;code&gt;systemd&lt;/code&gt; as PID 1, &lt;code&gt;systemd&lt;/code&gt; begins its&lt;br&gt;
initialization process by mounting the initial file systems and starting&lt;br&gt;
essential services. It reads its configuration from unit files located in&lt;br&gt;
&lt;code&gt;/etc/systemd/system/&lt;/code&gt; and &lt;code&gt;/usr/lib/systemd/system/&lt;/code&gt;. These unit files describe&lt;br&gt;
how to manage services, sockets, devices, and other system components.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;systemd&lt;/code&gt; also sets up the cgroups (control groups) to manage resource&lt;br&gt;
allocation and limits for processes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj9z4msz1y1hg4vfjq2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj9z4msz1y1hg4vfjq2m.png" alt="SystemD heirarchy|850" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Kernel Privilege rings and security. PID 1's security implications
&lt;/h3&gt;

&lt;p&gt;In the architecture of modern computer systems, privilege rings play a crucial&lt;br&gt;
role in maintaining security and stability. The Linux kernel operates in these&lt;br&gt;
rings to control access to resources and enforce security policies.&lt;br&gt;
Understanding the concept of privilege rings and the security implications of&lt;br&gt;
PID 1 helps in comprehending how Linux ensures a secure environment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Privilege Rings Explained
&lt;/h4&gt;

&lt;p&gt;Privilege rings are hierarchical levels of privileges that a system's processes&lt;br&gt;
can have. They range from Ring 0, the highest level of privilege, to Ring 3, the&lt;br&gt;
lowest.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Ring 0 (Kernel Mode):&lt;/strong&gt; The most privileged level, where the operating
system kernel operates. It has unrestricted access to all system resources
and hardware.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ring 3 (User Mode):&lt;/strong&gt; The least privileged level, where user applications
run. It has restricted access, requiring sudo to elevate to kernelmode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2o2ud8fx3um6beddz6v9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2o2ud8fx3um6beddz6v9.png" alt="Kernel Rings Explained" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The kernel mode (Ring 0) allows the operating system to execute critical tasks&lt;br&gt;
that require direct access to hardware and memory. User mode (Ring 3) provides a&lt;br&gt;
restricted environment for applications, preventing them from directly accessing&lt;br&gt;
hardware and system memory, thus protecting the system from malicious software&lt;br&gt;
and user errors.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ironically Ring 1 and Ring 2 have felt out of favor.&lt;/p&gt;

&lt;p&gt;As a hobbyist Linux nerd, I discovered that the benefits of rings 1 and 2 in&lt;br&gt;
the modern protection model are greatly diminished due to paging only&lt;br&gt;
distinguishing between privileged (ring 0, 1, 2) and unprivileged levels.&lt;/p&gt;

&lt;p&gt;Anecdotally Intel designed rings 1 and 2 to house device drivers, providing&lt;br&gt;
them with some privileges while keeping them somewhat separate from kernel&lt;br&gt;
code. Although rings 1 and 2 can access supervisor pages, they still trigger a&lt;br&gt;
General Protection Fault (GPF) if they use a privileged instruction, similar&lt;br&gt;
to ring 3. Despite this, rings 1 and 2 are useful in certain designs.&lt;/p&gt;

&lt;p&gt;For instance, VirtualBox places guest kernel code in ring 1, and some&lt;br&gt;
operating systems do utilize them, though it is not a widely popular design&lt;br&gt;
choice at present.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🏁 Conclusion
&lt;/h2&gt;

&lt;p&gt;Dear reader, I hope this gives you a glimpse into the fascinating engineering&lt;br&gt;
that powers your PC.&lt;br&gt;&lt;br&gt;
We followed a popular path through the woods of bootloaders and linux kernels.&lt;br&gt;&lt;br&gt;
In reality, there are many ways to boot a machine. We've got three components to&lt;br&gt;
mix and match. The BIOS, Bootloader and the OS/Kernel.&lt;/p&gt;

&lt;p&gt;In modern devices with a single powerful &lt;strong&gt;System on Chip&lt;/strong&gt; design, we sometimes&lt;br&gt;
encounter BIOS and Bootloader becoming very slim and having features to offer&lt;br&gt;
OEM locking and security. In most systems there is a proprietary "BIOS".&lt;sup id="fnref4"&gt;4&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Keen readers would noticed how Grub was a two stage bootloader, and Linux kernel&lt;br&gt;
was a two stage OS boot system. There have been efforts like &lt;strong&gt;Direct Kernel&lt;br&gt;
Boot&lt;/strong&gt;&lt;sup id="fnref5"&gt;5&lt;/sup&gt; to merge these two components + four steps into a streamlined two&lt;br&gt;
step process. This speeds up the boot process and is usually seen as an option&lt;br&gt;
in Virtualization solutions and hypervisors.&lt;/p&gt;

&lt;p&gt;In no particular order or importance, here are some interesting projects&lt;br&gt;
powering the modern device bootup space.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://source.denx.de/u-boot/u-boot" rel="noopener noreferrer"&gt;U-Boot&lt;/a&gt; - Usually used in embedded
devices. Gives fine grained control of where the kernel gets loaded into
device memory. As seen in:

&lt;ul&gt;
&lt;li&gt;  SpaceX Dragon/falcon/&lt;/li&gt;
&lt;li&gt;  Ubiquiti/TP-Link network devices&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;a href="https://coreboot.org/" rel="noopener noreferrer"&gt;Coreboot&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;  Chrome OS devices, Lenovo ThinkPad's and&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Android Devices :

&lt;ul&gt;
&lt;li&gt;  While android uses a variant of the Linux kernel, there is no standard
boot loader prescribed for running android os.&lt;/li&gt;
&lt;li&gt;  OEMs implement their own boot loader depending on the storage options
available and the SoC used.&lt;/li&gt;
&lt;li&gt;  Qualcomm chipsets use Little Kernel and try to be UEFI compatible.&lt;/li&gt;
&lt;li&gt;  MediaTek chipsets use a variant of U-Boot.&lt;/li&gt;
&lt;li&gt;  Major players like Samsung have their own variants of the bootloader.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Cloud VMs : AWS/Azure/GCP support custom virtualized BIOS/UEFI for their
VMs.

&lt;ul&gt;
&lt;li&gt;  Cloud BIOS supports emulating keyboard/serial console during the boot
process, even before the bootloader or OS has loaded. This makes
supporting any standard bootloader possible on cloud infrastructure.
Critical for disaster recovery scenarios where your server, 7000kms away
stops booting!&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/virtualization_types.html" rel="noopener noreferrer"&gt;Virtio and OS Images&lt;/a&gt;:
Cloud Boot disks are virtualized and attached on demand. You could
explore &lt;strong&gt;virtio&lt;/strong&gt; locally on qemu kvm. Virtualized storage enables
using pre-built images for different operating systems. A superpower for
running repeatable consistent infrastructure at scale!&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;a href="https://cloud-init.io/" rel="noopener noreferrer"&gt;Cloud-Init&lt;/a&gt;&lt;/strong&gt; : They also have additional
initialization steps after the kernel and operating system start called
&lt;strong&gt;cloud-init&lt;/strong&gt;. This helps setup networking, user accounts, passwords
and ssh keys, networking and services. It also helps platform operators
to further extend the boot process.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;Have feedback or questions, or want to be notified about more such articles?&lt;br&gt;
Follow me on Twitter &lt;a href="https://x.com/wiresurfer" rel="noopener noreferrer"&gt;@wiresurfer&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Footnotes
&lt;/h3&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;GPIOs are common in embedded boards like raspberry pi or industrial PCs.&lt;br&gt;
Here is an insightful stackoverflow discussion about hacks to&lt;br&gt;
&lt;a href="https://superuser.com/questions/993690/do-desktop-computer-motherboards-have-gpio-if-they-do-how-to-read-from-or-writ" rel="noopener noreferrer"&gt;use GPIOs on desktop motherboards&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;PWM Controllers and Temperature Sensors together play a critical role in&lt;br&gt;
thermal management. Most modern UEFI motherboards offer fine grained control&lt;br&gt;
over the sensor readings and the Fan control curve. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;This is a loose statement and I accept its far from true. For all you&lt;br&gt;
advanced practitioners out there, remember we are writing this guide down to&lt;br&gt;
be approachable. I am shying away from a lot of complexity and keeping&lt;br&gt;
things simple.&lt;br&gt;
&lt;a href="https://www.happyassassin.net/posts/2014/01/25/uefi-boot-how-does-that-actually-work-then/" rel="noopener noreferrer"&gt;Adam Williamson from Redhat, who has written about Linux, has a great post about this&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;"BIOS" is a symbolic name here. Each SoC needs to start the hardware and do&lt;br&gt;
some rudimentary POST. Most Mobile devices also need to initialize a special&lt;br&gt;
telephony subsystem which runs its own Baseband OS. A traditional BIOS/UEFI&lt;br&gt;
introduced here would mean pushing a square peg through a round hole. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/virtualization_administration_guide/sub-sect-op-sys-dir-kern-boot" rel="noopener noreferrer"&gt;20.2.3. Direct kernel boot Red Hat Enterprise Linux 6 | Red Hat Customer Portal&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
