<?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: spmahapatra</title>
    <description>The latest articles on DEV Community by spmahapatra (@spmahapatra).</description>
    <link>https://dev.to/spmahapatra</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2935765%2F32fa9f16-f43d-48ea-8148-249dd19c2b24.png</url>
      <title>DEV Community: spmahapatra</title>
      <link>https://dev.to/spmahapatra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/spmahapatra"/>
    <language>en</language>
    <item>
      <title>Installing Minikube on Debian</title>
      <dc:creator>spmahapatra</dc:creator>
      <pubDate>Sun, 23 Aug 2026 22:59:01 +0000</pubDate>
      <link>https://dev.to/spmahapatra/installing-minikube-on-debian-1aj4</link>
      <guid>https://dev.to/spmahapatra/installing-minikube-on-debian-1aj4</guid>
      <description>&lt;h1&gt;
  
  
  Installing Minikube on Debian
&lt;/h1&gt;

&lt;p&gt;Minikube is a practical way to run a small Kubernetes cluster on a Debian workstation or development instance. This guide installs Minikube with the Docker driver, starts a named profile, runs a temporary deployment, and removes the test resources afterward.&lt;/p&gt;

&lt;p&gt;This is a local development setup, not a production Kubernetes distribution. The commands target Debian 12 (Bookworm), Debian 13 (Trixie), or a compatible newer Debian release on an x86-64 host.&lt;/p&gt;

&lt;p&gt;The goal is a repeatable local baseline rather than a particular Minikube release number. Minikube and Kubernetes change over time, so the release documentation remains the authority for supported versions and driver behavior. The commands deliberately verify each boundary: the Debian host, Docker, the Minikube profile, the Kubernetes node, and a real workload. That makes a later failure easier to classify. For example, a failed &lt;code&gt;docker run&lt;/code&gt; is a runtime problem, while a successful Docker test followed by a failed rollout belongs in the cluster or workload layer.&lt;/p&gt;

&lt;p&gt;Run the commands as the same non-root user who will use Minikube afterward. Mixing &lt;code&gt;sudo minikube&lt;/code&gt; with normal-user commands creates separate configuration and cache locations, which can make a healthy cluster appear to be missing. Keeping one user and one named profile throughout the walkthrough avoids that confusing split.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You will have a Docker-backed Minikube profile named &lt;code&gt;local-kube-cluster&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Reserve at least 2 CPUs, 4 GiB of memory, and 20 GiB of free disk space for a comfortable first run.&lt;/li&gt;
&lt;li&gt;The Docker driver avoids a second virtual machine, but it still needs a working Docker daemon and permission to access it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Is Minikube?
&lt;/h2&gt;

&lt;p&gt;Minikube runs a single-node Kubernetes cluster locally so you can develop manifests, test controllers, and follow tutorials without provisioning a remote cluster. The Docker driver runs the node inside a container managed by Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The driver is the important choice:&lt;/strong&gt; Minikube manages the Kubernetes node, while Docker provides the container runtime and host-level isolation. If either layer is unhealthy, Kubernetes startup errors can be misleading.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mental Model
&lt;/h2&gt;

&lt;p&gt;Think of the installation as four independent checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Host capacity:&lt;/strong&gt; the machine has enough CPU, memory, disk, and network access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container runtime:&lt;/strong&gt; Docker is installed, running, and usable by the current user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cluster profile:&lt;/strong&gt; Minikube creates and stores a named cluster configuration. A profile can retain a driver choice and resource settings from an earlier attempt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes workload:&lt;/strong&gt; a &lt;code&gt;Ready&lt;/code&gt; node only proves the control plane started. A deployment and service smoke test proves that the cluster can schedule a workload and expose it through the selected driver.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This model also explains the safest troubleshooting order: check the host first, then Docker, then the Minikube profile, and only then the Kubernetes workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Debian 12, Debian 13, or a compatible newer Debian release&lt;/li&gt;
&lt;li&gt;x86-64 Linux, unless you download the matching Minikube architecture binary&lt;/li&gt;
&lt;li&gt;A non-root user with &lt;code&gt;sudo&lt;/code&gt; access&lt;/li&gt;
&lt;li&gt;At least 2 CPUs, 4 GiB RAM, and 20 GiB of free disk space&lt;/li&gt;
&lt;li&gt;Outbound access to Debian, Docker, Kubernetes, and Minikube download endpoints&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;systemd&lt;/code&gt; available if you want Docker managed as a system service&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Confirm the Debian host has enough capacity
&lt;/h3&gt;

&lt;p&gt;Update the package index, install the utilities used by the setup, and inspect the resources before downloading anything.&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="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&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; ca-certificates curl gnupg lsb-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;nproc
&lt;/span&gt;free &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;span class="nb"&gt;sudo df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not continue with the default profile if the host has fewer than 2 CPUs or less than 4 GiB of usable memory. A cluster can technically start with less, but image pulls and system pods will compete for the same constrained resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Install and verify Docker Engine
&lt;/h3&gt;

&lt;p&gt;Before continuing, install Docker Engine by following the dedicated &lt;a href="https://spmahapatra.github.io/install-docker-engine-on-debian/" rel="noopener noreferrer"&gt;Install Docker Engine on Debian&lt;/a&gt; guide. It uses Docker's official APT repository and covers conflicting packages, repository key configuration, daemon access, firewall considerations, and cleanup.&lt;/p&gt;

&lt;p&gt;After Docker is installed, verify it as the same user who will run Minikube:&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="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl is-active docker
docker version
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;docker version&lt;/code&gt; reports a permission error, follow the non-root access and new-login-session instructions in the Docker guide. The Docker group grants root-equivalent control over the host, so only trusted users should receive this access.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Install the Minikube binary
&lt;/h3&gt;

&lt;p&gt;Download the latest stable x86-64 Linux binary from Minikube's official release location and install it in &lt;code&gt;/usr/local/bin&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; root &lt;span class="nt"&gt;-g&lt;/span&gt; root &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 minikube-linux-amd64 /usr/local/bin/minikube
&lt;span class="nb"&gt;rm &lt;/span&gt;minikube-linux-amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the installation and make Docker the default driver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube version
minikube config &lt;span class="nb"&gt;set &lt;/span&gt;driver docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For ARM64, download the matching binary from the &lt;a href="https://github.com/kubernetes/minikube/releases/latest" rel="noopener noreferrer"&gt;Minikube releases page&lt;/a&gt; instead of the x86-64 file above.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Install kubectl locally
&lt;/h3&gt;

&lt;p&gt;Install the latest stable x86-64 &lt;code&gt;kubectl&lt;/code&gt; binary, verify its SHA-256 checksum, and move it into &lt;code&gt;/usr/local/bin&lt;/code&gt;:&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="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nv"&gt;KUBECTL_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://dl.k8s.io/release/stable.txt&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; &lt;span class="s2"&gt;"https://dl.k8s.io/release/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KUBECTL_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/linux/amd64/kubectl"&lt;/span&gt;
curl &lt;span class="nt"&gt;-fLO&lt;/span&gt; &lt;span class="s2"&gt;"https://dl.k8s.io/release/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KUBECTL_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/linux/amd64/kubectl.sha256"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;kubectl.sha256&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;  kubectl"&lt;/span&gt; | &lt;span class="nb"&gt;sha256sum&lt;/span&gt; &lt;span class="nt"&gt;--check&lt;/span&gt;
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; root &lt;span class="nt"&gt;-g&lt;/span&gt; root &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 kubectl /usr/local/bin/kubectl
&lt;span class="nb"&gt;rm &lt;/span&gt;kubectl kubectl.sha256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the local client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl version &lt;span class="nt"&gt;--client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands above target x86-64 Linux. For an ARM64 host, replace &lt;code&gt;amd64&lt;/code&gt; in both download URLs with &lt;code&gt;arm64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Keep the client and cluster lifecycle separate. &lt;code&gt;kubectl&lt;/code&gt; is the command-line client installed on the Debian host, while Minikube owns the local cluster and its certificates. Starting the profile writes or updates a context in the current user's kubeconfig. After activating &lt;code&gt;local-kube-cluster&lt;/code&gt;, &lt;code&gt;kubectl&lt;/code&gt; uses that active context by default. Run &lt;code&gt;kubectl config get-contexts&lt;/code&gt; if you need to inspect available contexts.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Start a Docker-backed cluster profile
&lt;/h3&gt;

&lt;p&gt;Create a named profile with explicit resources. Naming the profile makes it possible to inspect, stop, and delete this cluster without affecting another Minikube profile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube start &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--driver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4096 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make the named profile active, then check both the Minikube state and the Kubernetes node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube profile local-kube-cluster
minikube status &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster
minikube profile
kubectl config current-context
kubectl get nodes
kubectl get pods &lt;span class="nt"&gt;--all-namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;minikube profile&lt;/code&gt; command should now print &lt;code&gt;local-kube-cluster&lt;/code&gt;, and &lt;code&gt;kubectl config current-context&lt;/code&gt; should show the same context. The profile should report &lt;code&gt;Running&lt;/code&gt;, one node should report &lt;code&gt;Ready&lt;/code&gt;, and system pods may need a short time to settle during the first image pull.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Run and remove a Kubernetes smoke test
&lt;/h3&gt;

&lt;p&gt;Create a temporary deployment, expose it as a NodePort service, and wait for the rollout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create deployment minikube-smoke &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kicbase/echo-server:1.0
kubectl expose deployment minikube-smoke &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NodePort &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
kubectl rollout status deployment/minikube-smoke &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;120s
kubectl get deployment,service,pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask Minikube for a URL to the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube service minikube-smoke &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster &lt;span class="nt"&gt;--url&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove the temporary objects after the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete service minikube-smoke
kubectl delete deployment minikube-smoke
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging &amp;amp; Common Pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Docker permission denied
&lt;/h3&gt;

&lt;p&gt;If Docker works with &lt;code&gt;sudo&lt;/code&gt; but not as your normal user, the current shell has not picked up the new group membership. Run &lt;code&gt;groups&lt;/code&gt; and &lt;code&gt;id -nG&lt;/code&gt;, start a new login session, and retry &lt;code&gt;docker run --rm hello-world&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insufficient resources
&lt;/h3&gt;

&lt;p&gt;Check &lt;code&gt;free -h&lt;/code&gt;, &lt;code&gt;nproc&lt;/code&gt;, and &lt;code&gt;df -h /&lt;/code&gt;. Stop competing workloads or increase the instance size before changing Kubernetes settings. Reducing memory can make the cluster appear to start while leaving system pods unable to schedule reliably.&lt;/p&gt;

&lt;h3&gt;
  
  
  Profile uses the wrong driver
&lt;/h3&gt;

&lt;p&gt;Profiles retain configuration. Inspect existing profiles and recreate the named profile if it was previously started with another driver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube profile list
minikube delete &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster
minikube start &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster &lt;span class="nt"&gt;--driver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker &lt;span class="nt"&gt;--memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4096 &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Startup fails behind a proxy
&lt;/h3&gt;

&lt;p&gt;Image pulls and package downloads need network access from both the host and Docker. Configure the proxy according to your environment, then inspect the profile diagnostics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube logs &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster
minikube status &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A failed start leaves stale resources
&lt;/h3&gt;

&lt;p&gt;Delete the profile and retry only after checking the logs. Repeating &lt;code&gt;minikube start&lt;/code&gt; without removing a partially created profile can preserve the original driver or resource settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Minikube suitable for production?
&lt;/h3&gt;

&lt;p&gt;No. Minikube is designed for local development, learning, and repeatable experiments. Use a production-oriented Kubernetes distribution or managed service when you need high availability, durable operations, and multi-node failure handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why install standalone kubectl?
&lt;/h3&gt;

&lt;p&gt;The standalone client provides the normal Kubernetes workflow and can switch among contexts with &lt;code&gt;kubectl config get-contexts&lt;/code&gt;. Installing it once also keeps the commands in this guide consistent with other Kubernetes tools and scripts. Minikube still manages the cluster and writes the &lt;code&gt;local-kube-cluster&lt;/code&gt; context into your kubeconfig.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use the Docker driver on Debian?
&lt;/h3&gt;

&lt;p&gt;It is usually the simplest option when Docker is already part of the development workflow. It avoids managing a second virtual machine, though it still consumes host CPU, memory, disk, and Docker daemon resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should I do when the profile is no longer needed?
&lt;/h3&gt;

&lt;p&gt;Stop it to retain its downloaded data and configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube stop &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete it to remove the profile and its resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube delete &lt;span class="nt"&gt;--profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;local-kube-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>minikube</category>
      <category>debian</category>
      <category>docker</category>
    </item>
    <item>
      <title>Install Docker Engine on Debian</title>
      <dc:creator>spmahapatra</dc:creator>
      <pubDate>Sun, 23 Aug 2026 22:59:00 +0000</pubDate>
      <link>https://dev.to/spmahapatra/install-docker-engine-on-debian-4dga</link>
      <guid>https://dev.to/spmahapatra/install-docker-engine-on-debian-4dga</guid>
      <description>&lt;h1&gt;
  
  
  Install Docker Engine on Debian
&lt;/h1&gt;

&lt;p&gt;Docker Engine provides the daemon, CLI, and runtime needed to build and run containers on Debian. This guide installs Docker Engine from Docker's official APT repository, verifies the service with a test container, and configures the current user to run Docker without &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The repository method is preferable for a long-lived Debian instance because APT can receive Docker updates through the normal package workflow. Docker currently documents Debian 13 (Trixie), Debian 12 (Bookworm), and Debian 11 (Bullseye), with packages for amd64, armhf, arm64, and ppc64el. Package names and supported releases can change, so the official &lt;a href="https://docs.docker.com/engine/install/debian/" rel="noopener noreferrer"&gt;Docker Debian installation page&lt;/a&gt; remains the authority when this article is updated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install Docker Engine from Docker's signed APT repository rather than mixing distribution packages with Docker packages.&lt;/li&gt;
&lt;li&gt;Test the daemon with &lt;code&gt;docker run hello-world&lt;/code&gt; before configuring applications or Kubernetes tools.&lt;/li&gt;
&lt;li&gt;Membership in the &lt;code&gt;docker&lt;/code&gt; group grants root-equivalent access to the host. Add only trusted users, or keep using &lt;code&gt;sudo&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Is Docker Engine?
&lt;/h2&gt;

&lt;p&gt;Docker Engine is the host-side service that builds images, stores container data, creates networks, and starts containers. The Docker CLI sends requests to that service through its local socket. Installing the CLI alone does not provide a working container runtime.&lt;/p&gt;

&lt;p&gt;The installation has three separate concerns: repository trust, package installation, and daemon access. The repository's signing key lets APT verify Docker packages. The packages install the daemon and related plugins. The Unix socket controls which users can ask that daemon to perform privileged operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mental Model
&lt;/h2&gt;

&lt;p&gt;Treat the setup as a chain of checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Operating system:&lt;/strong&gt; confirm the Debian release and architecture are supported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conflicting packages:&lt;/strong&gt; remove unofficial packages that can provide overlapping commands or incompatible runtime dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APT trust:&lt;/strong&gt; install Docker's keyring and repository definition with readable, explicit permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engine service:&lt;/strong&gt; install the daemon, CLI, containerd, Buildx, and Compose plugins, then confirm the service is active.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User access:&lt;/strong&gt; decide whether commands should use &lt;code&gt;sudo&lt;/code&gt;, Docker-group membership, or rootless mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network policy:&lt;/strong&gt; review firewall behavior before publishing container ports.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A successful &lt;code&gt;docker version&lt;/code&gt; proves that the CLI can reach the daemon. A successful &lt;code&gt;docker run hello-world&lt;/code&gt; proves that the daemon can pull an image, create a container, start it, and report its output. Run both checks; they catch different failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Incident
&lt;/h2&gt;

&lt;p&gt;On a new Debian instance, I once treated Docker installation as a single package command and moved directly to a Kubernetes setup. The package installation completed, but the normal user could not access the Docker socket, so Minikube reported a driver failure that looked like a Kubernetes problem. I spent time checking cluster settings before checking &lt;code&gt;docker run&lt;/code&gt;. The real fix was a new login session after changing group membership. The lesson was simple: validate Docker as the exact user and shell that will run the next tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Debian 11, 12, or 13 on a supported architecture&lt;/li&gt;
&lt;li&gt;A non-root user with &lt;code&gt;sudo&lt;/code&gt; access&lt;/li&gt;
&lt;li&gt;Outbound HTTPS access to Debian mirrors and &lt;code&gt;download.docker.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A terminal session on the target Debian instance&lt;/li&gt;
&lt;li&gt;A firewall plan if containers will publish ports outside the host&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before installing, identify the release and architecture:&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="nb"&gt;.&lt;/span&gt; /etc/os-release
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'Debian release: %s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'Codename: %s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Remove conflicting Docker packages
&lt;/h3&gt;

&lt;p&gt;Debian may provide packages such as &lt;code&gt;docker.io&lt;/code&gt;, while other tools may install &lt;code&gt;containerd&lt;/code&gt; or &lt;code&gt;runc&lt;/code&gt; separately. Docker's official packages bundle compatible runtime dependencies. Remove conflicting packages if they are present:&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="nb"&gt;sudo &lt;/span&gt;apt remove &lt;span class="nt"&gt;-y&lt;/span&gt; docker.io docker-compose docker-doc docker-buildx podman-docker containerd runc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;APT may report that some packages are not installed. This command does not remove Docker's stored images, containers, volumes, or networks. Existing data may still be present under &lt;code&gt;/var/lib/docker&lt;/code&gt; and &lt;code&gt;/var/lib/containerd&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Configure Docker's signed APT repository
&lt;/h3&gt;

&lt;p&gt;Install the keyring directory and Docker's official signing key, then create a deb822 repository definition. The architecture expression prevents APT from selecting packages for a different architecture.&lt;/p&gt;

&lt;p&gt;If Docker was previously configured with an older &lt;code&gt;.list&lt;/code&gt; file, remove that duplicate source before adding the &lt;code&gt;.sources&lt;/code&gt; definition below. Keeping two entries for the same repository with different signing keys makes APT stop with a &lt;code&gt;Conflicting values set for option Signed-By&lt;/code&gt; error. This removes repository configuration only; it does not remove Docker packages or container data.&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="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/apt/sources.list.d/docker.list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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; &lt;span class="nt"&gt;-y&lt;/span&gt; ca-certificates curl
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/debian/gpg &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.asc
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.sources &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
Components: stable
Architectures: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
Signed-By: /etc/apt/keyrings/docker.asc
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refresh package metadata and confirm Docker packages are visible:&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="nb"&gt;sudo &lt;/span&gt;apt update
apt list &lt;span class="nt"&gt;--all-versions&lt;/span&gt; docker-ce 2&amp;gt;/dev/null | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'1,5p'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Debian testing or a derivative distribution, &lt;code&gt;VERSION_CODENAME&lt;/code&gt; may not match a Docker repository suite. Check the official documentation before substituting the corresponding Debian codename.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Install Docker Engine and its standard plugins
&lt;/h3&gt;

&lt;p&gt;Install the engine, command-line client, containerd, Buildx, and Compose plugin:&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="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io &lt;span class="se"&gt;\&lt;/span&gt;
  docker-buildx-plugin docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that the service is active and that the client can reach it:&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="nb"&gt;sudo &lt;/span&gt;systemctl is-active docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker version
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a normal Debian installation, Docker starts with the service installation. If it is inactive, start it and inspect the service status:&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="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status docker &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Verify the installation with a test container
&lt;/h3&gt;

&lt;p&gt;Run Docker's small verification image:&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="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command downloads the image if necessary, creates a temporary container, prints a confirmation message, and removes the container because of &lt;code&gt;--rm&lt;/code&gt;. A failure here should be resolved before installing Minikube, Compose applications, or other Docker-dependent tooling.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Configure non-root Docker access deliberately
&lt;/h3&gt;

&lt;p&gt;The simplest access model is to prefix Docker commands with &lt;code&gt;sudo&lt;/code&gt;. If the instance is trusted and the workflow requires normal-user commands, add the current user to the Docker group:&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="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start a new login session so the shell receives the new group membership. Then verify the exact user path:&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="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-nG&lt;/span&gt;
docker version
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not use &lt;code&gt;sudo docker&lt;/code&gt; as a substitute for refreshing the session when testing group access. The root and non-root clients can use different configuration files and caches, which makes troubleshooting harder.&lt;/p&gt;

&lt;p&gt;The Docker group is not equivalent to an ordinary application group. A user who can control the Docker daemon can generally gain root-level access to the host. Use the group only for trusted administrators, or investigate Docker's documented rootless mode when that privilege boundary matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Verify Compose and Buildx
&lt;/h3&gt;

&lt;p&gt;The installation includes the modern Compose and Buildx plugins. Confirm both are available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose version
docker buildx version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are plugin commands, so &lt;code&gt;docker-compose&lt;/code&gt; and an old standalone &lt;code&gt;docker-buildx&lt;/code&gt; command are not required for the documented workflow. Existing scripts may need updating if they depend on legacy command names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with Docker Daily
&lt;/h2&gt;

&lt;p&gt;Useful commands for a new instance include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List running containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List running and stopped containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker images&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List locally stored images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker logs &amp;lt;container&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read container output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker exec -it &amp;lt;container&amp;gt; sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open a shell in a running container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker inspect &amp;lt;container&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show low-level container configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker system df&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show Docker disk usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker compose up -d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start a Compose application in the background&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Keep the daemon healthy with &lt;code&gt;systemctl is-active docker&lt;/code&gt; and monitor disk usage. Images, writable layers, build cache, and container logs can fill a small instance even when few containers are running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging &amp;amp; Common Pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;docker: permission denied&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The daemon may be healthy while the current user lacks permission to access &lt;code&gt;/var/run/docker.sock&lt;/code&gt;. Check the service, socket ownership, and active groups:&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="nb"&gt;sudo &lt;/span&gt;systemctl is-active docker
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /var/run/docker.sock
&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-nG&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;sudo docker ...&lt;/code&gt;, or start a new login session after &lt;code&gt;usermod -aG docker "$USER"&lt;/code&gt;. Avoid changing the socket to world-writable permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  APT cannot find &lt;code&gt;docker-ce&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The Docker repository may be missing, the codename may be wrong, or &lt;code&gt;sudo apt update&lt;/code&gt; may have failed. Inspect the source definition and run the update again:&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="nb"&gt;cat&lt;/span&gt; /etc/apt/sources.list.d/docker.sources
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On supported Debian releases, the &lt;code&gt;Suites&lt;/code&gt; value should correspond to the Debian codename. Do not blindly use &lt;code&gt;stable&lt;/code&gt; as the suite; &lt;code&gt;stable&lt;/code&gt; belongs in &lt;code&gt;Components&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker service fails to start
&lt;/h3&gt;

&lt;p&gt;Read the service log before reinstalling packages:&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="nb"&gt;sudo &lt;/span&gt;systemctl status docker &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; docker.service &lt;span class="nt"&gt;-n&lt;/span&gt; 100 &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for storage-driver, dependency, disk, or network errors. A previous installation may have left incompatible runtime packages or configuration under &lt;code&gt;/etc/docker&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Published ports bypass expected firewall rules
&lt;/h3&gt;

&lt;p&gt;Docker warns that ports published with &lt;code&gt;-p&lt;/code&gt; can bypass rules managed by &lt;code&gt;ufw&lt;/code&gt; or firewalld. Docker is compatible with &lt;code&gt;iptables-nft&lt;/code&gt; and &lt;code&gt;iptables-legacy&lt;/code&gt;; rules created only with unsupported native nftables workflows may not behave as expected. Review Docker's firewall documentation and place filtering rules in the &lt;code&gt;DOCKER-USER&lt;/code&gt; chain where appropriate before exposing services.&lt;/p&gt;

&lt;h3&gt;
  
  
  The server runs out of disk
&lt;/h3&gt;

&lt;p&gt;Inspect Docker's usage before deleting anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system &lt;span class="nb"&gt;df
sudo du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; /var/lib/docker /var/lib/containerd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove only resources you understand. &lt;code&gt;docker system prune&lt;/code&gt; can remove stopped containers, unused networks, dangling images, and build cache; adding &lt;code&gt;--volumes&lt;/code&gt; can remove unused data volumes and should be treated as a destructive operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Should I install &lt;code&gt;docker.io&lt;/code&gt; or &lt;code&gt;docker-ce&lt;/code&gt; on Debian?
&lt;/h3&gt;

&lt;p&gt;Use Docker's official packages when you want Docker's documented Engine release stream: &lt;code&gt;docker-ce&lt;/code&gt;, &lt;code&gt;docker-ce-cli&lt;/code&gt;, &lt;code&gt;containerd.io&lt;/code&gt;, &lt;code&gt;docker-buildx-plugin&lt;/code&gt;, and &lt;code&gt;docker-compose-plugin&lt;/code&gt;. Do not mix the distribution's &lt;code&gt;docker.io&lt;/code&gt; package with those packages without checking the resulting dependency and upgrade behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I run Docker without &lt;code&gt;sudo&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Yes, but adding a user to the Docker group grants root-equivalent control over the host. A new login session is required after changing membership. Keeping &lt;code&gt;sudo&lt;/code&gt; is simpler for a tightly controlled administrative workflow; rootless mode is another option when its limitations fit the workload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does installing Docker automatically start the daemon?
&lt;/h3&gt;

&lt;p&gt;Docker's Debian package normally starts the service. Verify with &lt;code&gt;sudo systemctl is-active docker&lt;/code&gt;, and use &lt;code&gt;sudo systemctl enable --now docker&lt;/code&gt; if the service is inactive or is not enabled for boot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is the convenience script better than the APT repository?
&lt;/h3&gt;

&lt;p&gt;The convenience script is useful for disposable development environments and automation experiments, but it provides less control over repository setup and package choices. The APT repository is the better default for a Debian instance that will be maintained over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I completely uninstall Docker?
&lt;/h3&gt;

&lt;p&gt;First remove the packages:&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="nb"&gt;sudo &lt;/span&gt;apt purge &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io &lt;span class="se"&gt;\&lt;/span&gt;
  docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then remove the repository definition and key if they are no longer needed:&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="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/apt/sources.list.d/docker.sources
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/apt/keyrings/docker.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Images, containers, volumes, and custom configuration are not automatically removed by package removal. Delete &lt;code&gt;/var/lib/docker&lt;/code&gt; and &lt;code&gt;/var/lib/containerd&lt;/code&gt; only after confirming that all required data has been backed up or discarded.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>debian</category>
      <category>containers</category>
      <category>linux</category>
    </item>
    <item>
      <title>Installing Debian on WSL2 in Windows 11</title>
      <dc:creator>spmahapatra</dc:creator>
      <pubDate>Sat, 25 Apr 2026 23:14:06 +0000</pubDate>
      <link>https://dev.to/spmahapatra/how-to-set-up-wsl2-on-windows-11-53oi</link>
      <guid>https://dev.to/spmahapatra/how-to-set-up-wsl2-on-windows-11-53oi</guid>
      <description>&lt;h1&gt;
  
  
  Installing Debian on WSL2 in Windows 11
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WSL2 with Debian gives you a full Linux kernel and systemd support — a legitimate CI parity environment on Windows hardware without running a separate VM.&lt;/li&gt;
&lt;li&gt;Take a snapshot with &lt;code&gt;wsl --export&lt;/code&gt; before installing any project tooling (Step 7). It's a one-minute operation that has saved me multiple full reinstalls.&lt;/li&gt;
&lt;li&gt;Steps 1–5 get you a working Debian environment with systemd. Steps 6–7 (Windows Terminal, snapshot) are worth doing the same session.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Is WSL2?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;WSL2 (Windows Subsystem for Linux 2) ships a real Linux kernel inside a lightweight Hyper-V virtual machine.&lt;/strong&gt; Unlike WSL1, which translated Linux syscalls into Windows calls, WSL2 runs an actual Linux kernel — meaning full syscall compatibility, &lt;code&gt;systemd&lt;/code&gt;, and &lt;code&gt;eBPF&lt;/code&gt; all work without a separate VM.&lt;/p&gt;

&lt;p&gt;As of Windows 11 22H2, WSL2 supports &lt;code&gt;systemd&lt;/code&gt; natively with no workarounds, persistent background services, and GPU passthrough via CUDA on supported hardware. This makes it the first Windows-native environment where you can run production-parity workloads alongside your Windows desktop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mental Model
&lt;/h2&gt;

&lt;p&gt;WSL2 runs inside a single lightweight Hyper-V VM (the "WSL2 utility VM"). Each installed distro is a separate filesystem image (&lt;code&gt;ext4.vhdx&lt;/code&gt;) running inside that VM. The VM boots once; all distros share the kernel.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Windows filesystem (&lt;code&gt;C:\&lt;/code&gt;) is mounted at &lt;code&gt;/mnt/c/&lt;/code&gt;&lt;/strong&gt; — I/O across this boundary is slow. Keep project files in &lt;code&gt;~/&lt;/code&gt; (inside the distro), not in &lt;code&gt;/mnt/c/Users/...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;wsl.exe&lt;/code&gt; is your control plane&lt;/strong&gt;: install, unregister, export, import, and configure distros from PowerShell. Think of it as &lt;code&gt;docker&lt;/code&gt; but for Linux distros.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking is NAT'd by default&lt;/strong&gt;: WSL2 gets its own IP that changes on reboot. Windows 11 23H2+ adds a mirrored networking mode that eliminates this.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Windows 11 (Build 22000 or later — verify with &lt;code&gt;winver&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;PowerShell running as Administrator&lt;/li&gt;
&lt;li&gt;Virtualization enabled in BIOS (check Task Manager → Performance → CPU → "Virtualization: Enabled")&lt;/li&gt;
&lt;li&gt;4 GB free disk space minimum; 10 GB recommended for a comfortable base install&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install WSL2 and Debian
&lt;/h3&gt;

&lt;p&gt;Open PowerShell as Administrator (right-click Start → &lt;strong&gt;Terminal (Admin)&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fast path — works on most Windows 11 machines:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables the WSL feature, sets version 2 as default, and installs Debian. Once the install finishes, a Debian terminal opens automatically and prompts you to create a user account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter new UNIX username: yourname
New password:
Retype new password:
passwd: password updated successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The password won't display as you type — that's normal. Once done, close the Debian window and reboot:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; The Microsoft Store's Debian package ships a patched &lt;code&gt;/init&lt;/code&gt; that silently breaks &lt;code&gt;systemd&lt;/code&gt; — services you enable will appear to succeed but never start. Use &lt;code&gt;wsl --install&lt;/code&gt; above, not the Store app, if you need reliable service management.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Manual path — use this if &lt;code&gt;wsl --install&lt;/code&gt; errors out:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dism.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/online&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/enable-feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/featurename:Microsoft-Windows-Subsystem-Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/norestart&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;dism.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/online&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/enable-feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/featurename:VirtualMachinePlatform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/norestart&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;span class="nt"&gt;--set-default-version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot to activate the hypervisor, then after restart run &lt;code&gt;wsl --install -d Debian&lt;/code&gt; again — the username/password prompt will appear automatically when install completes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Launch Debian After Reboot
&lt;/h3&gt;

&lt;p&gt;After rebooting, Debian won't open automatically. Launch it from PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should land at your user prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yourname@MACHINE-NAME:~&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to verify:&lt;/strong&gt; Launch it from PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--status&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Default Version: 2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Kernel version: 5.15.x or higher&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;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# NAME      STATE     VERSION&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Debian    Running   2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If VERSION shows &lt;code&gt;1&lt;/code&gt;, force the upgrade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--set-version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Launch Debian — Four Ways
&lt;/h3&gt;

&lt;p&gt;After first-launch setup, Debian won't automatically open on future reboots. Pick whichever method fits your workflow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From PowerShell or CMD (fastest):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or just &lt;code&gt;wsl&lt;/code&gt; if Debian is your default distro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the Start menu:&lt;/strong&gt;&lt;br&gt;
Search for &lt;strong&gt;Debian&lt;/strong&gt; — it appears as an app. Pin it to your taskbar for one-click access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From Windows Terminal:&lt;/strong&gt;&lt;br&gt;
Click the &lt;strong&gt;&lt;code&gt;+&lt;/code&gt;&lt;/strong&gt; dropdown tab arrow → select &lt;strong&gt;Debian&lt;/strong&gt;. Each click opens a new tab in your existing terminal window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From any File Explorer folder:&lt;/strong&gt;&lt;br&gt;
Right-click inside a folder → &lt;strong&gt;Open Linux shell here&lt;/strong&gt; (Windows 11 with Terminal installed). Opens a Debian shell with that folder already set as the working directory — useful when you want to run Linux tools on Windows files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you get dropped into a &lt;code&gt;root&lt;/code&gt; shell instead of your user account, check that &lt;code&gt;[user] default=yourname&lt;/code&gt; is set in &lt;code&gt;/etc/wsl.conf&lt;/code&gt; (Step 4 covers this).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  4. Enable systemd
&lt;/h3&gt;

&lt;p&gt;Inside your Debian terminal:&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="nb"&gt;sudo tee&lt;/span&gt; /etc/wsl.conf &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
[boot]
systemd=true

[user]
default=your_unix_username
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart WSL from PowerShell, then re-enter the distro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&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;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nt"&gt;--no-pager&lt;/span&gt; status
&lt;span class="c"&gt;# State: running&lt;/span&gt;
&lt;span class="c"&gt;# (NOT "System is degraded" — if degraded, run: systemctl --failed)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Update and Install Base Packages
&lt;/h3&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="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  curl wget git build-essential &lt;span class="se"&gt;\&lt;/span&gt;
  ca-certificates gnupg lsb-release &lt;span class="se"&gt;\&lt;/span&gt;
  htop tmux jq unzip

&lt;span class="nb"&gt;sudo &lt;/span&gt;timedatectl set-timezone America/New_York   &lt;span class="c"&gt;# adjust to your zone&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;timedatectl
&lt;span class="c"&gt;# Local time: ...&lt;/span&gt;
&lt;span class="c"&gt;# System clock synchronized: yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Install Windows Terminal
&lt;/h3&gt;

&lt;p&gt;WSL2 works in the default console but Windows Terminal is significantly better — tabs, split panes, per-distro profiles, and proper font rendering for tools like &lt;code&gt;tmux&lt;/code&gt; and &lt;code&gt;htop&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft.WindowsTerminal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or install from the Microsoft Store. Once installed, open it and your Debian distro will already appear as a profile in the &lt;code&gt;+&lt;/code&gt; dropdown — no configuration needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to verify:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open Windows Terminal → click the &lt;code&gt;+&lt;/code&gt; dropdown → confirm &lt;strong&gt;Debian&lt;/strong&gt; appears as a profile. Select it — you should land at your Debian user prompt, not a root shell.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Export a Backup Snapshot Before Installing Anything Else
&lt;/h3&gt;

&lt;p&gt;Before you install project-specific tooling, export a clean snapshot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In PowerShell — create the backup directory first&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\wsl-backups&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;span class="nt"&gt;--export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\wsl-backups\debian-clean.tar&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To restore from backup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--unregister&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&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;span class="nt"&gt;--import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\WSL\Debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\wsl-backups\debian-clean.tar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What to verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;whoami&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Should print your username, not root&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accessing Files Between Windows and Linux
&lt;/h2&gt;

&lt;p&gt;This trips up almost every first-timer. WSL2 runs in its own filesystem, but both sides can reach each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From inside Debian — access Windows files:&lt;/strong&gt;&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="nb"&gt;ls&lt;/span&gt; /mnt/c/Users/YourWindowsUsername/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your Windows drives are mounted under &lt;code&gt;/mnt/&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; I/O across this boundary is 10–30× slower than native Linux I/O. Never run &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;git clone&lt;/code&gt;, or heavy build operations on files under &lt;code&gt;/mnt/c/&lt;/code&gt; — always keep project files in &lt;code&gt;~/&lt;/code&gt; inside the distro.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;From Windows Explorer — browse your Linux filesystem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Type this path directly in the Explorer address bar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\\wsl$\Debian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens your Debian home directory in Windows Explorer. You can drag, copy, and edit files here as if they were Windows files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shortcut — open current Linux folder in Explorer:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;explorer.exe &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this from any directory inside WSL2 and it opens that exact folder in Windows Explorer. Useful for accessing build artifacts from your IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  WSL Command Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --install -d Debian&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Install a specific distro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --list --online&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show all available distros&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl -l -v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List installed distros with version and state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --shutdown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stop all running WSL instances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --update&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update the WSL kernel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl -d Debian&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Launch a specific distro by name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --export Debian file.tar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export distro to a backup file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --import Debian path file.tar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Restore distro from backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --unregister Debian&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove a distro (destructive — backup first)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wsl --set-version Debian 2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Convert an existing distro to WSL2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Advanced Configuration
&lt;/h2&gt;

&lt;p&gt;These settings are optional — apply them once your base Debian environment is working.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capping WSL2 Memory Usage
&lt;/h3&gt;

&lt;p&gt;The Hyper-V VM holds memory it has used even after processes exit. Without a cap it can consume several GB that Windows never reclaims. Create &lt;code&gt;C:\Users\YourName\.wslconfig&lt;/code&gt;:&lt;br&gt;
&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;memory&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;4GB&lt;/span&gt;
&lt;span class="py"&gt;processors&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;4&lt;/span&gt;
&lt;span class="py"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;2GB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply with &lt;code&gt;wsl --shutdown&lt;/code&gt;. Verify inside Debian: &lt;code&gt;free -h&lt;/code&gt; should show the capped total.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mirrored Networking (Windows 11 23H2+)
&lt;/h3&gt;

&lt;p&gt;By default, WSL2 uses NAT and gets a dynamic IP that changes on reboot. Mirrored mode gives WSL2 the same IP as your Windows host — services are reachable from your LAN without port-forwarding rules.&lt;/p&gt;

&lt;p&gt;Add to &lt;code&gt;C:\Users\YourName\.wslconfig&lt;/code&gt;:&lt;br&gt;
&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;networkingMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mirrored&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply with &lt;code&gt;wsl --shutdown&lt;/code&gt;. Verify inside Debian: &lt;code&gt;ip addr&lt;/code&gt; should show your Windows LAN IP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging &amp;amp; Common Pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Error: 0x80370102&lt;/code&gt; — virtualization not enabled
&lt;/h3&gt;

&lt;p&gt;This is the most common error on first install. Reboot into BIOS/UEFI and enable &lt;strong&gt;Intel VT-x&lt;/strong&gt; (Intel CPUs) or &lt;strong&gt;AMD-V&lt;/strong&gt; (AMD CPUs). It's usually under Advanced → CPU Configuration. Some corporate laptops have this locked by IT policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distro stuck at "Installing" with 0% progress after reboot
&lt;/h3&gt;

&lt;p&gt;Two common causes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Virtual Machine Platform not enabled&lt;/strong&gt; — rerun Step 1 and reboot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft Store pending update&lt;/strong&gt; — open the Microsoft Store, check for pending updates, let them finish, then try again. The Debian app itself sometimes needs to complete a Store update before first launch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Inspect the event log for the underlying error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LogName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft-Windows-Hyper-V-Guest-Drivers/Admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-MaxEvents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  systemctl reports "System is degraded"
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;systemctl --failed&lt;/code&gt; to see which units failed. Three common WSL2-specific culprits that are safe to mask:&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="nb"&gt;sudo &lt;/span&gt;systemctl mask multipathd.service      &lt;span class="c"&gt;# storage multipath — not applicable in WSL2&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl mask systemd-remount-fs.service  &lt;span class="c"&gt;# WSL2 filesystem quirk&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl mask apparmor.service        &lt;span class="c"&gt;# WSL2 kernel has no AppArmor modules&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;wsl --install&lt;/code&gt; says WSL is already installed but nothing works
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;wsl --update&lt;/code&gt; to make sure the kernel is current, then &lt;code&gt;wsl --shutdown&lt;/code&gt; and try again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--update&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;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;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the distro still won't launch, check its status: &lt;code&gt;wsl -l -v&lt;/code&gt;. If STATE shows "Stopped" and it won't start, export it for backup, unregister, and re-import from your backup snapshot (Step 7, Export a Backup Snapshot).&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I run WSL2 on Windows 10?
&lt;/h3&gt;

&lt;p&gt;Yes — WSL2 is available on Windows 10 version 1903 (Build 18362) and later. However, native &lt;code&gt;systemd&lt;/code&gt; support requires Windows 11 22H2 or Windows 10 Build 22000+. On older Windows 10 builds you need the &lt;code&gt;genie&lt;/code&gt; or &lt;code&gt;distrod&lt;/code&gt; workaround to get systemd running. Everything else in this guide works as written.&lt;/p&gt;

&lt;h3&gt;
  
  
  My WSL2 distro is slow when accessing files under &lt;code&gt;/mnt/c/&lt;/code&gt;. Is this normal?
&lt;/h3&gt;

&lt;p&gt;That slowness is real and it doesn't go away. Cross-filesystem I/O crosses a virtual filesystem boundary — Linux talking to a Windows-hosted NTFS volume through a translation layer. Always keep active project files inside the Linux distro filesystem (&lt;code&gt;~/projects/&lt;/code&gt;), not under &lt;code&gt;/mnt/c/Users/...&lt;/code&gt;. The gap can be 10–30× on large file operations like &lt;code&gt;npm install&lt;/code&gt; or &lt;code&gt;git clone&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I access my WSL2 Debian from another machine on my LAN?
&lt;/h3&gt;

&lt;p&gt;By default, WSL2 uses NAT and is not directly accessible from the LAN. Three options: (1) Windows port forwarding — &lt;code&gt;netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=$(wsl hostname -I)&lt;/code&gt;. (2) Switch to mirrored networking in &lt;code&gt;.wslconfig&lt;/code&gt; under &lt;code&gt;[wsl2]&lt;/code&gt; — available on Windows 11 23H2+ and gives WSL2 the same IP as your Windows host. (3) Expose services via a reverse proxy like Caddy running inside the distro, bound to &lt;code&gt;0.0.0.0&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>wsl2</category>
      <category>debian</category>
      <category>windows</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
