<?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: Kernel notes (sunshout)</title>
    <description>The latest articles on DEV Community by Kernel notes (sunshout) (@sunshoutkernel).</description>
    <link>https://dev.to/sunshoutkernel</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%2F4093254%2F6e3ad529-261c-47ab-ab9d-59f0b51d1c56.png</url>
      <title>DEV Community: Kernel notes (sunshout)</title>
      <link>https://dev.to/sunshoutkernel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sunshoutkernel"/>
    <language>en</language>
    <item>
      <title>KVM SR-IOV: intel_iommu=on is not SR-IOV until you create VFs</title>
      <dc:creator>Kernel notes (sunshout)</dc:creator>
      <pubDate>Tue, 25 Aug 2026 04:32:36 +0000</pubDate>
      <link>https://dev.to/sunshoutkernel/kvm-sr-iov-inteliommuon-is-not-sr-iov-until-you-create-vfs-2fbh</link>
      <guid>https://dev.to/sunshoutkernel/kvm-sr-iov-inteliommuon-is-not-sr-iov-until-you-create-vfs-2fbh</guid>
      <description>&lt;p&gt;A lot of homelab notes stop at GRUB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pci=assign-busses iommu=pt intel_iommu=on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;update-grub&lt;/code&gt; or on CentOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grub2-mkconfig &lt;span class="nt"&gt;-o&lt;/span&gt; /boot/grub2/grub.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot. &lt;code&gt;dmesg&lt;/code&gt; shows &lt;code&gt;Intel-IOMMU: enabled&lt;/code&gt;. That means the &lt;strong&gt;IOMMU is on&lt;/strong&gt;. It does not mean you have virtual functions. SR-IOV is a PCIe capability on a physical function (PF). You still have to ask the PF to spawn VFs.&lt;/p&gt;

&lt;p&gt;Commands I actually ran, with the dmesg checks, are on the original note:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sunshout.tistory.com/1615" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1615&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirm the IOMMU before you blame the NIC
&lt;/h2&gt;

&lt;p&gt;Intel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dmesg | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; DMAR &lt;span class="nt"&gt;-e&lt;/span&gt; IOMMU
&lt;span class="c"&gt;# expect Intel-IOMMU: enabled&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that line is missing, the GRUB tokens did not reach the kernel (&lt;code&gt;/proc/cmdline&lt;/code&gt;) or the board has IOMMU off in firmware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then create VFs
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lspci&lt;/code&gt; — you want a PF that advertises SR-IOV. On the box I used it was an Intel 82599 10G:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;04:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ ...
04:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spawn four VFs on the first PF:&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;echo &lt;/span&gt;4 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /sys/bus/pci/devices/0000:04:00.0/sriov_numvfs
lspci | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; virtual
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;sriov_numvfs&lt;/code&gt; does not exist, the firmware VF count is zero, the kernel driver does not support it, or you echoed into the VF by mistake. Use the &lt;strong&gt;PF&lt;/strong&gt; address.&lt;/p&gt;

&lt;p&gt;Make it survive reboot with a udev rule or a oneshot systemd unit. sysfs is not persistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  vfio-pci bind fails after VFs appear
&lt;/h2&gt;

&lt;p&gt;Usually IOMMU &lt;strong&gt;groups&lt;/strong&gt;, not the echo. A device in a group with a sibling you cannot stub out will refuse assignment. &lt;code&gt;find /sys/kernel/iommu_groups -type l&lt;/code&gt; and ACS / firmware settings are the next stop — not a second &lt;code&gt;intel_iommu=on&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolation is a separate post
&lt;/h2&gt;

&lt;p&gt;Pinning the datapath CPU so host interrupts do not land on the poll thread is &lt;code&gt;isolcpus&lt;/code&gt; + IRQ affinity, not SR-IOV. That write-up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sunshout.tistory.com/1620" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1620&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;sriov_numvfs&lt;/code&gt; is missing on a card the vendor claims is SR-IOV capable, dump &lt;code&gt;lspci -vvv -s 04:00.0 | grep -i sriov&lt;/code&gt; before you buy another NIC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related lab notes (canonical originals)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TLS vs SSL, three jobs of the tunnel: &lt;a href="https://sunshout.tistory.com/2206" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2206&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;isolcpus isolates the scheduler, not IRQs: &lt;a href="https://sunshout.tistory.com/1620" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1620&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;QEMU virtio-blk &lt;code&gt;aio=io_uring&lt;/code&gt; is a host flag: &lt;a href="https://sunshout.tistory.com/2156" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2156&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kvm</category>
      <category>linux</category>
      <category>networking</category>
      <category>virtualization</category>
    </item>
    <item>
      <title>isolcpus= takes CPUs off the scheduler. Hardware IRQs still land there.</title>
      <dc:creator>Kernel notes (sunshout)</dc:creator>
      <pubDate>Tue, 25 Aug 2026 03:46:13 +0000</pubDate>
      <link>https://dev.to/sunshoutkernel/isolcpus-takes-cpus-off-the-scheduler-hardware-irqs-still-land-there-ihe</link>
      <guid>https://dev.to/sunshoutkernel/isolcpus-takes-cpus-off-the-scheduler-hardware-irqs-still-land-there-ihe</guid>
      <description>&lt;p&gt;The blunt tool is still in a lot of GRUB files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/span&gt;=&lt;span class="s2"&gt;"isolcpus=0,1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;update-grub&lt;/code&gt; (or &lt;code&gt;grub2-mkconfig&lt;/code&gt;) and reboot. Userspace tasks stop landing on CPU0/1. That is all most people verify — they fire a few busy loops and &lt;code&gt;top&lt;/code&gt; looks empty on those cores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IRQs do not care.&lt;/strong&gt; &lt;code&gt;isolcpus&lt;/code&gt; is a &lt;em&gt;scheduler&lt;/em&gt; isolation hint. Hardware interrupts can still fire on the "isolated" CPUs. I watched seven tight loops leave 0/1 idle for processes while &lt;code&gt;/proc/interrupts&lt;/code&gt; still ticked on those cores.&lt;/p&gt;

&lt;p&gt;If you wanted a CPU for DPDK, a user-space NIC, or a cycle-accurate loop, scheduler isolation is necessary and &lt;strong&gt;not sufficient&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lab notes (English original is short; this write-up is the missing IRQ half):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sunshout.tistory.com/1620" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1620&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to see what you actually isolated
&lt;/h2&gt;

&lt;p&gt;After reboot:&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; /proc/cmdline          &lt;span class="c"&gt;# isolcpus=0,1 must be there&lt;/span&gt;
&lt;span class="nb"&gt;grep &lt;/span&gt;PREEMPT /boot/config-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;taskset &lt;span class="nt"&gt;-cp&lt;/span&gt; 1              &lt;span class="c"&gt;# pick a known userspace pid; it should not be 0,1&lt;/span&gt;
watch &lt;span class="nt"&gt;-n1&lt;/span&gt; &lt;span class="s1"&gt;'grep "^ *[0-9]" /proc/interrupts | head'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If IRQs still increment on CPU0/1, isolation is incomplete. That is expected with classic &lt;code&gt;isolcpus=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On newer kernels the story split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;isolcpus=domain&lt;/code&gt; / cpusets / cgroup cpuset — userspace&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isolcpus=managed_irq&lt;/code&gt; or manual &lt;code&gt;irqaffinity&lt;/code&gt; / &lt;code&gt;/proc/irq/*/smp_affinity&lt;/code&gt; — interrupts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nohz_full=&lt;/code&gt; — tick reduction, another knob, not a substitute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;isolcpus&lt;/code&gt; is also marked deprecated in some trees in favor of cpusets. The IRQ caveat did not go away when the docs changed the preferred interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving IRQs by hand
&lt;/h2&gt;

&lt;p&gt;Find the noisy ones (&lt;code&gt;eth0&lt;/code&gt;, NVMe, GPU):&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;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'eth|nvme|enp'&lt;/span&gt; /proc/interrupts
&lt;span class="c"&gt;# smp_affinity is a hex CPU mask. CPU2 only → 4&lt;/span&gt;
&lt;span class="nb"&gt;echo &lt;/span&gt;4 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /proc/irq/IRQNUM/smp_affinity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or set the default affinity so &lt;em&gt;new&lt;/em&gt; IRQs skip 0/1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irqaffinity=2-7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in the same GRUB line (adjust to your CPU count). Some devices ignore this (managed IRQs, VFIO). Then you isolate at the driver: bind the NIC to vfio-pci and poll from a pinned thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  When this shows up next to SR-IOV
&lt;/h2&gt;

&lt;p&gt;Passing a VF into KVM does not pin host IRQs for you. IOMMU on (&lt;code&gt;intel_iommu=on iommu=pt&lt;/code&gt;) is a different checklist. I wrote the VF creation half here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sunshout.tistory.com/1615" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1615&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Typical datapath box:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IOMMU on, VFs created, vfio-pci bound.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isolcpus&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; IRQ affinity so the poll thread is not preempted by the host NIC's own interrupt.&lt;/li&gt;
&lt;li&gt;Confirm with &lt;code&gt;/proc/interrupts&lt;/code&gt;, not with &lt;code&gt;top&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your kernel is 6.x, say so in the comments — the flags moved, the IRQ rule did not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related lab notes (canonical originals)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TLS vs SSL, three jobs of the tunnel: &lt;a href="https://sunshout.tistory.com/2206" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2206&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;KVM SR-IOV: &lt;code&gt;intel_iommu=on&lt;/code&gt; is not VFs until you create them: &lt;a href="https://sunshout.tistory.com/1615" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1615&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;QEMU virtio-blk &lt;code&gt;aio=io_uring&lt;/code&gt; is a host flag: &lt;a href="https://sunshout.tistory.com/2156" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2156&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>kernel</category>
      <category>networking</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Stop saying SSL: TLS only does three jobs, and your 'SSL cert' is usually not the outage</title>
      <dc:creator>Kernel notes (sunshout)</dc:creator>
      <pubDate>Tue, 25 Aug 2026 03:34:23 +0000</pubDate>
      <link>https://dev.to/sunshoutkernel/stop-saying-ssl-tls-only-does-three-jobs-and-your-ssl-cert-is-usually-not-the-outage-26dh</link>
      <guid>https://dev.to/sunshoutkernel/stop-saying-ssl-tls-only-does-three-jobs-and-your-ssl-cert-is-usually-not-the-outage-26dh</guid>
      <description>&lt;p&gt;Runbooks still say "renew the SSL certificate" when the browser warning is &lt;strong&gt;obsolete protocol&lt;/strong&gt;. The certificate can be brand new. The tunnel is still TLS 1.0.&lt;/p&gt;

&lt;p&gt;This is a shortened English note. The tables, handshake diagram, and OpenSSL CLI checks live on the original post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sunshout.tistory.com/2206" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2206&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SSL vs TLS (the only distinction that matters)
&lt;/h2&gt;

&lt;p&gt;SSL is a Netscape protocol from the 1990s. SSL 3.0 is withdrawn (POODLE and friends). What every browser speaks now is &lt;strong&gt;TLS&lt;/strong&gt;, currently 1.2 or 1.3.&lt;/p&gt;

&lt;p&gt;People still say "SSL cert" because vendors sold that phrase. The file is an X.509 certificate. The handshake that uses it is TLS.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;SSL&lt;/th&gt;
&lt;th&gt;TLS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Who&lt;/td&gt;
&lt;td&gt;Netscape&lt;/td&gt;
&lt;td&gt;IETF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Versions you might still see&lt;/td&gt;
&lt;td&gt;2.0 / 3.0 (disable)&lt;/td&gt;
&lt;td&gt;1.0 / 1.1 (disable), &lt;strong&gt;1.2 / 1.3 (use)&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;td&gt;Forbidden&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If a ticket says "SSL is broken", translate it to: &lt;em&gt;which TLS version did the handshake negotiate, and which cipher?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The tunnel only has three jobs
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Confidentiality&lt;/strong&gt; — encryption so a tap does not yield plaintext.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity&lt;/strong&gt; — a MAC (today: AEAD) so a MITM cannot flip bits unnoticed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt; — the certificate binds this hostname to a key a CA will vouch for.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;https is that tunnel. It is not "the lock icon means the page is safe to click." It means the bits on the wire are for that name, encrypted, and unmodified. XSS and a malicious origin are a different layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The outage that is not the certificate
&lt;/h2&gt;

&lt;p&gt;Symptom: new Let's Encrypt leaf, browsers still scream &lt;em&gt;obsolete TLS&lt;/em&gt; or refuse the handshake on phones.&lt;/p&gt;

&lt;p&gt;Cause: nginx/Apache/openssl still allow TLS 1.0/1.1, or the server has no 1.2+. Renewing the cert does nothing.&lt;/p&gt;

&lt;p&gt;Check, do not guess:&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;# must fail&lt;/span&gt;
openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; example.com:443 &lt;span class="nt"&gt;-tls1&lt;/span&gt;
&lt;span class="c"&gt;# must work&lt;/span&gt;
openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; example.com:443 &lt;span class="nt"&gt;-tls1_2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep TLS 1.2 next to 1.3 if you still have old Android or old Java. New services can prefer 1.3.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to put in the cipher line
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Key exchange: &lt;strong&gt;ECDHE&lt;/strong&gt; (forward secrecy). Static RSA key exchange is how yesterday's traffic gets decrypted after a key leak.&lt;/li&gt;
&lt;li&gt;Bulk: &lt;strong&gt;AES-GCM&lt;/strong&gt; or &lt;strong&gt;ChaCha20-Poly1305&lt;/strong&gt;. CBC + HMAC is how Lucky Thirteen-class bugs keep showing up.&lt;/li&gt;
&lt;li&gt;Drop: 3DES, RC4, MD5, SHA-1 as a PRF.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenSSL 1.0.2 / 1.1.1 are past EOL. Heartbleed was a reminder that "it still links" is not a security policy. Run 3.x LTS and patch when the project says High/Critical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Encrypt vs OpenSSL
&lt;/h2&gt;

&lt;p&gt;Let's Encrypt &lt;strong&gt;issues&lt;/strong&gt; the certificate. OpenSSL (or BoringSSL, or the language runtime) &lt;strong&gt;runs the handshake&lt;/strong&gt; with that certificate. Buying a cert does not harden &lt;code&gt;ssl_protocols&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Private key files: &lt;code&gt;chmod 400&lt;/code&gt; or &lt;code&gt;600&lt;/code&gt;, owned by the daemon user, not world-readable. Compression off (&lt;code&gt;SSL_OP_NO_COMPRESSION&lt;/code&gt;) — CRIME/BREACH.&lt;/p&gt;

&lt;p&gt;I keep the longer Korean original, including the four-step handshake and a cipher table, here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sunshout.tistory.com/2206" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2206&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your site opens but a scanner still flags TLS 1.0, paste the &lt;code&gt;openssl s_client -tls1&lt;/code&gt; output before you renew anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related lab notes (canonical originals)
&lt;/h2&gt;

&lt;p&gt;These are the Korean posts with the tables and command output. English is a short version.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;isolcpus isolates the scheduler, not IRQs: &lt;a href="https://sunshout.tistory.com/1620" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1620&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;KVM SR-IOV: &lt;code&gt;intel_iommu=on&lt;/code&gt; is not VFs: &lt;a href="https://sunshout.tistory.com/1615" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/1615&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;QEMU virtio-blk &lt;code&gt;aio=io_uring&lt;/code&gt; is a host flag: &lt;a href="https://sunshout.tistory.com/2156" rel="noopener noreferrer"&gt;https://sunshout.tistory.com/2156&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tls</category>
      <category>openssl</category>
      <category>security</category>
      <category>nginx</category>
    </item>
  </channel>
</rss>
