{"title":"S\u00e9rgio Cipriano's Website","link":{"@attributes":{"href":"https:\/\/www.sergiocipriano.com\/atom.xml","rel":"self"}},"updated":"2026-05-13T10:05:35-03:00","author":{"name":"S\u00e9rgio de Almeida Cipriano J\u00fanior"},"id":"tag:www.sergiocipriano.com,2025-05-17:default-atom-feed","entry":[{"title":"My experience at MiniDebConf Campinas 2026","content":"<h1 id=\"my-experience-at-minidebconf-campinas-2026\">My experience at\nMiniDebConf Campinas 2026<\/h1>\n<p>Last week, I spent the entire week in Campinas attending MiniDebConf\nand MiniDebCamp. The Debian Brazil community organizes this event every\nyear, and this year's edition was the biggest so far.<\/p>\n<p>During MiniDebCamp, I sponsored a few uploads and spent two days\nteaching packaging to two participants. I usually teach packaging\nonline, so it was refreshing to do it in person. I believe the\nexperience was much better than teaching online.<\/p>\n<p>One of my mentees introduced me to the <a\nhref=\"https:\/\/ddtp.debian.org\/ddtss\/index.cgi\/xx\">DDTSS<\/a> (Debian\nDistributed Translation Server Satellite). Even though there are many\ni18n contributors in Brazil, this was my first time learning about this\nsystem. I plan to contribute to translations over the next few weeks\nusing DDTSS.<\/p>\n<h2 id=\"my-activities\">My Activities<\/h2>\n<blockquote>\n<p><strong>NOTE:<\/strong> I translated every talk title; the original\ntitles are in PT-BR, so some details may have been lost in\ntranslation.<\/p>\n<\/blockquote>\n<p>I presented three talks and led one BoF session. The talks are all\navailable on Debian's Peertube:<\/p>\n<ul>\n<li><a\nhref=\"https:\/\/peertube.debian.social\/w\/mCR5z937EAKAYWoZ4Kj3Gk\">Get to\nknow dh-make-vim<\/a><\/li>\n<li><a\nhref=\"https:\/\/peertube.debian.social\/w\/8UwXnn967dqm6Dwfn1M4bX\">Zero-Code\nInstrumentation of an application using eBPF<\/a><\/li>\n<li><a\nhref=\"https:\/\/peertube.debian.social\/w\/sgZBgKbxtxBes51KEh4JHs?start=29m31s\">DD\nnon-uploading can upload<\/a><\/li>\n<\/ul>\n<p>You can also find my slides at <a\nhref=\"https:\/\/people.debian.org\/~cipriano\/talks\/minidebconfbrazil2026\/\">people.d.o<\/a>.<\/p>\n<p>My first talk was a showcase of <a\nhref=\"https:\/\/salsa.debian.org\/vim-team\/dh-make-vim\/\">dh-make-vim<\/a>, a\ntool I created and have been using for a few months. Some people tested\nit and found bugs, which was really nice to see.<\/p>\n<p>My second talk was essentially a live version of my blog post <a\nhref=\"https:\/\/sergiocipriano.com\/beyla-envoy.html\">Zero-Code\nInstrumentation of an Envoy TCP Proxy using eBPF<\/a>.<\/p>\n<p>I also gave a lightning talk about something many people are not\naware of: non-uploading DDs can also sponsor uploads.<\/p>\n<p>If you're interested, this bug report provides more context: <a\nhref=\"https:\/\/bugs.debian.org\/cgi-bin\/bugreport.cgi?bug=1111611\">tracker.debian.org:\nSigned by field is missing when sponsoring as DD non-uploading<\/a><\/p>\n<p>Finally, I led the BoF session <a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/33-experiencias-aprendizados-e-proximos-passos-das-mentorias\/\">\"Experiences,\nlessons learned, and next steps from the mentoring sessions\"<\/a>. This\nwas my favorite session, we had many participants with different\nperspectives and ideas, which led to a very engaging discussion. I'm\nstill working on the action plans and I plan to release them soon.<\/p>\n<p>Here are some photos of these activities:<\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/bof_1.jpeg\"\nalt=\"Mentorship BoF\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/bof_2.jpeg\"\nalt=\"Mentorship BoF\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/dd-non-uploader-uploading.jpeg\"\nalt=\"DD non-uploading can upload talk\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/dh-make-vim.jpeg\"\nalt=\"dh-make-vim showcase\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\"assets\/minidebconf-campinas-2026\/obi.jpeg\"\nalt=\"Zero-Code Instrumentation showcase\"\nclass=\"markdown-img\"><\/p>\n<h2 id=\"my-favorite-activities\">My favorite activities<\/h2>\n<p>This is a list, in no particular order, of some of the sessions I\nenjoyed the most:<\/p>\n<ul>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/76-salsa-ci-mostrando-features-que-quase-ninguem-conhece\/\">Salsa\nCI, showing features that almost nobody knows<\/a><\/p>\n<p>I wrote a <a\nhref=\"https:\/\/sergiocipriano.com\/salsaci-build-rdeps.html\">blog post<\/a>\nabout one of the things I learned in this talk, and there is still a lot\nmore to explore. Aquila Macedo is developing many cool features in Salsa\nCI.<\/p><\/li>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/31-software-livre-liberdade-autonomia-soberania\/\">Free\nSoftware: Freedom, Autonomy, Sovereignty<\/a><\/p>\n<p>I had been really looking forward to this one. Alexandre Oliva is a\nvery important figure in the Free Software movement, especially in South\nAmerica. I'll need to rewatch it, my futures talks about Free Software\nwill likely be inspired by this one.<\/p><\/li>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/36-o-que-vivi-em-33-anos-de-debian-software-livre-em-geral\/\">What\nI've lived\/seen in 33 Years of Debian &amp; Free Software in\ngeneral<\/a><\/p>\n<p>Eduardo Ma\u00e7an was the first Debian Developer in Brazil, so it's\nalways valuable to hear the story from someone who was part of\nit.<\/p><\/li>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/71-simbologia-uma-introducao\/\">Symbolism\n- an introduction<\/a><\/p>\n<p>Despite the title, this talk was not about astrology! I'll probably\nrewatch it as well, as there is a lot of information to take in. I\nreally like the passion S\u00e9rgio Durigan has for C. He is also a great\nspeaker and knows how to guide the audience through the topic.<\/p><\/li>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/28-debate-polemicas-contemporaneas-no-debian\/\">Debate:\nContemporary controversies in Debian<\/a><\/p>\n<p>The debate itself was great, but the conversations we had afterward\nwere even better. I changed some of my opinions after hearing different\nperspectives. I don't think this format would work at DebConf, but I\nwould definitely like to attend another one like this.<\/p><\/li>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/18-por-que-lts-no-debian\/\">Why\nLTS on Debian?<\/a><\/p>\n<p>I had a few questions about LTS, and Kanashiro and Santiago answered\nthem both during the talk and in the Q&amp;A session. They also shared\nsome challenges and how to avoid them, it was a great learning\nexperience.<\/p><\/li>\n<li><p><a\nhref=\"https:\/\/campinas.mini.debconf.org\/talks\/54-da-primeira-contribuicao-ao-debian-maintainer\/\">From\nmy first contribution to the Debian Maintainer<\/a><\/p>\n<p>Polkorny was a bit shy but did a great job! I really enjoy this kind\nof talk. It is always nice to see the different paths people\ntake.<\/p><\/li>\n<\/ul>\n<p>Unfortunatly, I couldn't attend everything I was interested in, as\nalways.<\/p>\n<h2 id=\"daytrip---the-brazilian-particle-accelerator\">DayTrip - The\nBrazilian Particle Accelerator<\/h2>\n<p>Sirius is the largest and most complex scientific infrastructure ever\nbuilt in Brazil and one of the most advanced synchrotron light sources\nin the world. My jaw dropped the entire time; it's hard to describe how\nincredible this is.<\/p>\n<p>My favorite detail: they're running Debian :)<\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/daytrip-1.jpeg\"\nalt=\"\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/daytrip-2.jpeg\"\nalt=\"\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/daytrip-3.jpeg\"\nalt=\"\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/daytrip-4.jpeg\"\nalt=\"\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/daytrip-5.jpeg\"\nalt=\"\"\nclass=\"markdown-img\"><\/p>\n<p><img src=\".\/assets\/minidebconf-campinas-2026\/daytrip-6.jpeg\"\nalt=\"\"\nclass=\"markdown-img\"><\/p>\n<h2 id=\"wrap-up\">Wrap up<\/h2>\n<p>I believe this was the best MiniDebConf Brazil so far. There were\nmany other things I chose not to include here, as this post is already\nquite long. Still, here are a few more highlights:<\/p>\n<ul>\n<li>A Bug Squashing Party<\/li>\n<li>Driving Samuel Henrique's drones<\/li>\n<li>Lots of capybaras<\/li>\n<li>A small birthday party<\/li>\n<li>A visit to two data centers<\/li>\n<\/ul>","link":{"@attributes":{"href":"minidebconf-campinas-2026.html"}},"id":"tag:www.sergiocipriano.com,2026-04-30:posts\/minidebconf-campinas-2026.md","published":"2026-04-30T16:14:47-03:00","updated":"2026-05-13T10:05:21-03:00"},{"title":"How to build reverse dependencies using Salsa CI","content":"<h1 id=\"how-to-build-reverse-dependencies-using-salsa-ci\">How to build\nreverse dependencies using Salsa CI<\/h1>\n<p>Last week, I attended MiniDebConf Campinas, and one of my favorites\ntalks was <a\nhref=\"https:\/\/youtu.be\/agbcw-xKHQI?si=igCMvFQGyXc1qFHi\">\"Salsa CI,\nshowing features that almost nobody knows\"<\/a> by Aquila Macedo.<\/p>\n<p>One of the things I learned is that we can easily build reverse\ndependencies using:<\/p>\n<pre><code>$ git push -o ci.variable=&quot;SALSA_CI_DISABLE_BUILD_REVERSE_DEPENDENCIES=0&quot;<\/code><\/pre>\n<p>I tried this option before uploading typer version 0.20.0-1:<\/p>\n<p><img src=\".\/assets\/salsaci-build-rdeps\/example.png\" alt=\"example of salsa ci\nbuild rdeps working\" class=\"markdown-img\"><\/p>\n<p>This is an amazing feature. Thanks to everyone involved in making it\nhappen!<\/p>","link":{"@attributes":{"href":"salsaci-build-rdeps.html"}},"id":"tag:www.sergiocipriano.com,2026-04-29:posts\/salsaci-build-rdeps.md","published":"2026-04-29T23:27:46-03:00","updated":"2026-04-29T23:27:46-03:00"},{"title":"How to view the Debian Upload Queue","content":"<h1 id=\"how-to-view-the-debian-upload-queue\">How to view the Debian\nUpload Queue<\/h1>\n<p>Some people may not know this, but the Debian Upload Queue is public\nand very easy to access:<\/p>\n<pre><code>$ curl ftp:\/\/ftp.upload.debian.org\/pub\/UploadQueue\/\ndrwxr-sr-x   18 1518     1281         4096 Jun 26  2019 DELAYED\n-rw-r--r--    1 1518     1281         3442 Jul 14  2025 README\n-rw-r-----    1 117      1281         3052 Apr 20 21:32 neovim-tokyonight_4.14.1-1.debian.tar.xz\n-rw-r-----    1 117      1281         2119 Apr 20 21:32 neovim-tokyonight_4.14.1-1.dsc\n-rw-r-----    1 117      1281         5533 Apr 20 21:32 neovim-tokyonight_4.14.1-1_amd64.buildinfo\n-rw-r-----    1 117      1281         2637 Apr 20 21:32 neovim-tokyonight_4.14.1-1_source.changes\n-rw-r-----    1 117      1281       197584 Apr 20 21:32 neovim-tokyonight_4.14.1.orig.tar.gz<\/code><\/pre>","link":{"@attributes":{"href":"list-upload-queue.html"}},"id":"tag:www.sergiocipriano.com,2026-04-21:posts\/list-upload-queue.md","published":"2026-04-21T12:16:58-03:00","updated":"2026-04-21T12:16:58-03:00"},{"title":"Zero-Code Instrumentation of an Envoy TCP Proxy using eBPF","content":"<h1\nid=\"zero-code-instrumentation-of-an-envoy-tcp-proxy-using-ebpf\">Zero-Code\nInstrumentation of an Envoy TCP Proxy using eBPF<\/h1>\n<p>I recently had to debug an <a\nhref=\"https:\/\/www.envoyproxy.io\/docs\/envoy\/latest\/configuration\/listeners\/network_filters\/tcp_proxy_filter\">Envoy\nNetwork Load Balancer<\/a>, and the options Envoy provides just weren't\nenough. We were seeing a small number of HTTP 499 errors caused by\nlatency somewhere in our <a href=\"https:\/\/magalu.cloud\/\">cloud<\/a>, but\nit wasn't clear what the bottleneck was. As a result, each team had to\nset up additional instrumentation to catch latency spikes and figure out\nwhat was going on.<\/p>\n<p>My team is responsible for the LBaaS product (Load Balancer as a\nService) and, of course, we are the first suspects when this kind of\nproblem appear.<\/p>\n<p>Before going for the current solution, I read a lot of Envoy's\ndocumentation.<\/p>\n<p>It is possible to enable <a\nhref=\"https:\/\/www.envoyproxy.io\/docs\/envoy\/latest\/configuration\/observability\/access_log\/usage\">access\nlogs<\/a> for Envoy, but they don't provide the information required for\nthis debug. This is an example of the output:<\/p>\n<pre><code>[2025-12-08T20:44:49.918Z] &quot;- - -&quot; 0 - 78 223 1 - &quot;-&quot; &quot;-&quot; &quot;-&quot; &quot;-&quot; &quot;172.18.0.2:8080&quot;<\/code><\/pre>\n<p>I won't go into detail about the line above, since it's not possible\nto trace the request using access logs alone.<\/p>\n<p>Envoy also has <a\nhref=\"https:\/\/www.envoyproxy.io\/docs\/envoy\/latest\/start\/sandboxes\/opentelemetry\">OpenTelemetry\ntracing<\/a>, which is perfect for understanding sources of latency.\nUnfortunatly, it is only available for Application Load Balancers.<\/p>\n<p>Most of the HTTP 499 were happening every 10 minutes, so we managed\nto get some of the requests with tcpdump, <a\nhref=\"https:\/\/www.wireshark.org\/\">Wireshark<\/a> and using http headers\nto filter the requests.<\/p>\n<p>This approach helped us reproduce and track down the problem, but it\nwasn't a great solution. We clearly needed better tools to catch this\nkind of issue the next time it happened.<\/p>\n<p>Therefore, I decided to try out <a\nhref=\"https:\/\/github.com\/open-telemetry\/opentelemetry-ebpf-instrumentation\">OpenTelemetry\neBPF Instrumentation<\/a>, also referred to as OBI.<\/p>\n<p>I saw the announcement of Grafana Beyla before it was renamed to OBI,\nbut I didn't have the time or a strong reason to try it out until now.\nEven then, I really liked the idea, and the possibility of using eBPF to\nsolve this instrumentation problem had been in the back of my mind.<\/p>\n<p>OBI promises zero-code automatic instrumentation for Linux services\nusing eBPF, so I put together a minimal setup to see how well it\nworks.<\/p>\n<h2 id=\"reproducible-setup\">Reproducible setup<\/h2>\n<p>I used the following tools:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/\">Docker Compose<\/a><\/li>\n<li><a href=\"https:\/\/www.envoyproxy.io\/\">EnvoyProxy<\/a><\/li>\n<li><a href=\"https:\/\/go.dev\/\">Go<\/a><\/li>\n<li><a\nhref=\"https:\/\/github.com\/open-telemetry\/opentelemetry-ebpf-instrumentation\">OBI<\/a><\/li>\n<\/ul>\n<p>Setting up a TCP Proxy with Envoy was straightforward:<\/p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">static_resources<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">listeners<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_listener<\/span><\/span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">socket_address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"fl\">0.0.0.0<\/span><\/span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">port_value<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8000<\/span><\/span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">filter_chains<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">filters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoy.filters.network.tcp_proxy<\/span><\/span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">typed_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-12\"><a href=\"#cb2-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy<\/span><\/span>\n<span id=\"cb2-13\"><a href=\"#cb2-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">stat_prefix<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_tcp<\/span><\/span>\n<span id=\"cb2-14\"><a href=\"#cb2-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">cluster<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb2-15\"><a href=\"#cb2-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">clusters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-16\"><a href=\"#cb2-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb2-17\"><a href=\"#cb2-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">connect_timeout<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 1s<\/span><\/span>\n<span id=\"cb2-18\"><a href=\"#cb2-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">type<\/span><span class=\"kw\">:<\/span><span class=\"at\"> LOGICAL_DNS<\/span><\/span>\n<span id=\"cb2-19\"><a href=\"#cb2-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">load_assignment<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-20\"><a href=\"#cb2-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">cluster_name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb2-21\"><a href=\"#cb2-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">endpoints<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-22\"><a href=\"#cb2-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">lb_endpoints<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-23\"><a href=\"#cb2-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-24\"><a href=\"#cb2-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-25\"><a href=\"#cb2-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">socket_address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb2-26\"><a href=\"#cb2-26\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><span class=\"at\"> target-backend<\/span><\/span>\n<span id=\"cb2-27\"><a href=\"#cb2-27\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">port_value<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8080<\/span><\/span><\/code><\/pre><\/div>\n<p>This is the simplest Envoy TCP proxy configuration: a listener on\nport 8000 forwarding traffic to a backend running on port 8080.<\/p>\n<p>For the backend, I used a basic Go HTTP server:<\/p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode go\"><code class=\"sourceCode go\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">package<\/span> main<\/span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">import<\/span> <span class=\"op\">(<\/span><\/span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"st\">&quot;fmt&quot;<\/span><\/span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"st\">&quot;net\/http&quot;<\/span><\/span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"op\">)<\/span><\/span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">func<\/span> main<span class=\"op\">()<\/span> <span class=\"op\">{<\/span><\/span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    http<span class=\"op\">.<\/span>Handle<span class=\"op\">(<\/span><span class=\"st\">&quot;\/&quot;<\/span><span class=\"op\">,<\/span> http<span class=\"op\">.<\/span>FileServer<span class=\"op\">(<\/span>http<span class=\"op\">.<\/span>Dir<span class=\"op\">(<\/span><span class=\"st\">&quot;.&quot;<\/span><span class=\"op\">)))<\/span><\/span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    server <span class=\"op\">:=<\/span> http<span class=\"op\">.<\/span>Server<span class=\"op\">{<\/span>Addr<span class=\"op\">:<\/span> <span class=\"st\">&quot;:8080&quot;<\/span><span class=\"op\">}<\/span><\/span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-13\"><a href=\"#cb3-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    fmt<span class=\"op\">.<\/span>Println<span class=\"op\">(<\/span><span class=\"st\">&quot;Starting server on :8080&quot;<\/span><span class=\"op\">)<\/span><\/span>\n<span id=\"cb3-14\"><a href=\"#cb3-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"bu\">panic<\/span><span class=\"op\">(<\/span>server<span class=\"op\">.<\/span>ListenAndServe<span class=\"op\">())<\/span><\/span>\n<span id=\"cb3-15\"><a href=\"#cb3-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"op\">}<\/span><\/span><\/code><\/pre><\/div>\n<p>Finally, I wrapped everything together with Docker Compose:<\/p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">services<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">autoinstrumenter<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> otel\/ebpf-instrument:main<\/span><\/span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">pid<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;service:envoy&quot;<\/span><\/span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">privileged<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"ch\">true<\/span><\/span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">environment<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">OTEL_EBPF_TRACE_PRINTER<\/span><span class=\"kw\">:<\/span><span class=\"at\"> text<\/span><\/span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">OTEL_EBPF_OPEN_PORT<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8000<\/span><\/span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">envoy<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoyproxy\/envoy:v1.33-latest<\/span><\/span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">ports<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> 8000:8000<\/span><\/span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/envoy.yaml:\/etc\/envoy\/envoy.yaml <\/span><\/span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">depends_on<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> target-backend<\/span><\/span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><\/span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">target-backend<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> golang:1.22-alpine<\/span><\/span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">command<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go run \/app\/backend.go<\/span><\/span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/backend.go:\/app\/backend.go:ro<\/span><\/span>\n<span id=\"cb4-24\"><a href=\"#cb4-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">expose<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb4-25\"><a href=\"#cb4-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"dv\">8080<\/span><\/span><\/code><\/pre><\/div>\n<p>OBI should output traces to the standard output similar to this when\na HTTP request is made to Envoy:<\/p>\n<pre><code>2025-12-08 20:44:49.12884449 (305.572\u00b5s[305.572\u00b5s]) HTTPClient 200 GET \/(\/) [172.18.0.3 as envoy:36832]-&gt;[172.18.0.2 as localhost:8080] contentLen:78B responseLen:0B svc=[envoy generic] traceparent=[00-529458a2be271956134872668dc5ee47-6dba451ec8935e3e[06c7f817e6a5dae2]-01]\n2025-12-08 20:44:49.12884449 (1.260901ms[366.65\u00b5s]) HTTP 200 GET \/(\/) [172.18.0.1 as 172.18.0.1:36282]-&gt;[172.18.0.3 as envoy:8000] contentLen:78B responseLen:223B svc=[envoy generic] traceparent=[00-529458a2be271956134872668dc5ee47-06c7f817e6a5dae2[0000000000000000]-01]<\/code><\/pre>\n<p>This is exactly what we needed, with zero-code. The above trace\nshows:<\/p>\n<ul>\n<li><code>2025-12-08 20:44:49.12884449<\/code>: time of the trace.<\/li>\n<li><code>(1.260901ms[366.65\u00b5s])<\/code>: total response time for the\nrequest, with the actual internal execution time of the request (not\ncounting the request enqueuing time).<\/li>\n<li><code>HTTP 200 GET \/<\/code>: protocol, response code, HTTP method,\nand URL path.<\/li>\n<li><code>[172.18.0.1 as 172.18.0.1:36282]-&gt;[172.18.0.3 as envoy:8000]<\/code>:\nsource and destination host:port. The initial request originates from my\nmachine through the gateway (172.18.0.1), hits the Envoy (172.23.0.3),\nthe proxy then forwards it to the backend application (172.23.0.2).<\/li>\n<li><code>contentLen:78B<\/code>: HTTP Content-Length. I used curl and\nthe default request size for it is 78B.<\/li>\n<li><code>responseLen:223B<\/code>: Size of the response body.<\/li>\n<li><code>svc=[envoy generic]<\/code>: traced service.<\/li>\n<li><code>traceparent<\/code>: ids to trace the parent request. We can\nsee that the Envoy makes a request to the target and this request has\nthe other one as parent.<\/li>\n<\/ul>\n<p>Let's add one more Envoy to show that it's also possible to track\nmultiple services.<\/p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">envoy1<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoyproxy\/envoy:v1.33-latest<\/span><\/span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">ports<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> 9000:9000<\/span><\/span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/envoy1.yaml:\/etc\/envoy\/envoy.yaml<\/span><\/span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">depends_on<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> envoy<\/span><\/span><\/code><\/pre><\/div>\n<p>The new Envoy will listen on port 9000 and forward the request to the\nother Envoy listening on port 8000. Now we just need to change OBI open\nport variable to look at a range:<\/p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">OTEL_EBPF_OPEN_PORT<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 8000-9000<\/span><\/span><\/code><\/pre><\/div>\n<p>And change the pid field of the autoinstrumenter service to use the\nhost's PID namespace inside the container:<\/p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">pid<\/span><span class=\"kw\">:<\/span><span class=\"at\"> host<\/span><\/span><\/code><\/pre><\/div>\n<p>This is the output I got after one curl:<\/p>\n<pre><code>2025-12-09 12:28:05.12912285 (2.202041ms[1.524713ms]) HTTP 200 GET \/(\/) [172.19.0.1 as 172.19.0.1:59030]-&gt;[172.19.0.5 as envoy:9000] contentLen:78B responseLen:223B svc=[envoy generic] traceparent=[00-69977bee0c2964b8fe53cdd16f8a9d19-856c9f700e73bf0d[0000000000000000]-01]\n2025-12-09 12:28:05.12912285 (1.389336ms[1.389336ms]) HTTPClient 200 GET \/(\/) [172.19.0.5 as envoy:59806]-&gt;[172.19.0.4 as localhost:8000] contentLen:78B responseLen:0B svc=[envoy generic] traceparent=[00-69977bee0c2964b8fe53cdd16f8a9d19-caa7f1ad1c68fa77[856c9f700e73bf0d]-01]\n2025-12-09 12:28:05.12912285 (1.5431ms[848.574\u00b5s]) HTTP 200 GET \/(\/) [172.19.0.5 as 172.19.0.5:59806]-&gt;[172.19.0.4 as envoy:8000] contentLen:78B responseLen:223B svc=[envoy generic] traceparent=[00-69977bee0c2964b8fe53cdd16f8a9d19-cbca9d64d3d26b40[caa7f1ad1c68fa77]-01]\n2025-12-09 12:28:05.12912285 (690.217\u00b5s[690.217\u00b5s]) HTTPClient 200 GET \/(\/) [172.19.0.4 as envoy:34256]-&gt;[172.19.0.3 as localhost:8080] contentLen:78B responseLen:0B svc=[envoy generic] traceparent=[00-69977bee0c2964b8fe53cdd16f8a9d19-5502f7760ed77b5b[cbca9d64d3d26b40]-01]\n2025-12-09 12:28:05.12912285 (267.9\u00b5s[238.737\u00b5s]) HTTP 200 GET \/(\/) [172.19.0.4 as 172.19.0.4:34256]-&gt;[172.19.0.3 as backend:8080] contentLen:0B responseLen:0B svc=[backend go] traceparent=[00-69977bee0c2964b8fe53cdd16f8a9d19-ac05c7ebe26f2530[5502f7760ed77b5b]-01]<\/code><\/pre>\n<p>Each log line represents a span belonging to the same trace\n<code>(69977bee0c2964b8fe53cdd16f8a9d19)<\/code>. For readability, I\nordered the spans by their traceparent relationship, showing the\nrequest's path as it moves through the system: from the client-facing\nEnvoy, through the internal Envoy hop, and finally to the Go backend.\nYou can see both server-side (HTTP) and client-side (HTTPClient) spans\nat each hop, along with per-span latency, source and destination\naddresses, and response sizes, making it easy to pinpoint where time is\nspent along the request chain.<\/p>\n<p>The log lines are helpful, but we need better ways to visualize the\ntraces and the metrics generated by OBI. I'll share another setup that\nmore closely reflects what we actually use.<\/p>\n<h2 id=\"production-setup\">Production setup<\/h2>\n<p>I'll be using the following tools this time:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/\">Docker Compose<\/a><\/li>\n<li><a href=\"https:\/\/www.python.org\/\">Python<\/a><\/li>\n<li><a\nhref=\"https:\/\/github.com\/open-telemetry\/opentelemetry-ebpf-instrumentation\">OBI<\/a><\/li>\n<li><a href=\"https:\/\/www.jaegertracing.io\/\">Jaeger<\/a><\/li>\n<li><a href=\"https:\/\/prometheus.io\/\">Prometheus<\/a><\/li>\n<li><a href=\"https:\/\/grafana.com\/\">Grafana<\/a><\/li>\n<li><a\nhref=\"https:\/\/linuxcontainers.org\/incus\/docs\/main\/\">Incus<\/a><\/li>\n<li><a\nhref=\"https:\/\/github.com\/open-telemetry\/opentelemetry-collector-contrib\">Otel\nCollector<\/a><\/li>\n<\/ul>\n<p>The goal of this setup is to mirror an environment similar to what I\nused in production. This time, I've omitted the load balancer and\nshifted the emphasis to observability instead.<\/p>\n<p><img\nsrc=\".\/assets\/beyla-envoy-post\/obi-instrumentation.svg\"\nalt=\"setup diagram\"\nclass=\"markdown-img\"><\/p>\n<p>I will run three HTTP servers on port 8080: two inside Incus\ncontainers and one on the host machine. The OBI process will export\nmetrics and traces to an OpenTelemetry Collector, which will forward\ntraces to Jaeger and expose a metrics endpoint for Prometheus to scrape.\nGrafana will also be added to visualize the collected metrics using\ndashboards.<\/p>\n<p>The aim of this approach is to instrument only one of the HTTP\nservers while ignoring the others. This simulates an environment with\nhundreds of Incus containers, where the objective is to debug a single\ncontainer without being overwhelmed by excessive and irrelevant\ntelemetry data from the rest of the system.<\/p>\n<p>OBI can filter metrics and traces based on attribute values, but I\nwas not able to filter by process PID. This is where the OBI Collector\ncomes into play, it allows me to use a processor to filter telemetry\ndata by the PID of the process being instrumented.<\/p>\n<p>These are the steps to reproduce this setup:<\/p>\n<ol type=\"1\">\n<li>Create the incus containers.<\/li>\n<\/ol>\n<pre><code>$ incus launch images:debian\/trixie server01\nLaunching server01\n$ incus launch images:debian\/trixie server02\nLaunching server02<\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Start the HTTP server on each container.<\/li>\n<\/ol>\n<pre><code>$ apt install python3 --update -y\n$ tee \/etc\/systemd\/system\/server.service &gt; \/dev\/null &lt;&lt;&#39;EOF&#39;\n[Unit]\nDescription=Python HTTP server\nAfter=network.target\n\n[Service]\nUser=root\nGroup=root\nType=simple\nExecStart=\/usr\/bin\/python3 -m http.server 8080\nRestart=always\nStandardOutput=journal\nStandardError=journal\n\n[Install]\nWantedBy=multi-user.target\nEOF\n$ systemctl start server.service<\/code><\/pre>\n<ol start=\"3\" type=\"1\">\n<li>Start the HTTP server on the host.<\/li>\n<\/ol>\n<pre><code>$ python3 -m http.server 8080<\/code><\/pre>\n<ol start=\"4\" type=\"1\">\n<li>Start the Docker compose.<\/li>\n<\/ol>\n<div class=\"sourceCode\" id=\"cb13\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">services<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">autoinstrumenter<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> otel\/ebpf-instrument:main<\/span><\/span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">pid<\/span><span class=\"kw\">:<\/span><span class=\"at\"> host<\/span><\/span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">privileged<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"ch\">true<\/span><\/span>\n<span id=\"cb13-6\"><a href=\"#cb13-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">environment<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-7\"><a href=\"#cb13-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">OTEL_EBPF_CONFIG_PATH<\/span><span class=\"kw\">:<\/span><span class=\"at\"> \/etc\/obi\/obi.yml <\/span><\/span>\n<span id=\"cb13-8\"><a href=\"#cb13-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-9\"><a href=\"#cb13-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/obi.yml:\/etc\/obi\/obi.yml<\/span><\/span>\n<span id=\"cb13-10\"><a href=\"#cb13-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb13-11\"><a href=\"#cb13-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">otel-collector<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-12\"><a href=\"#cb13-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> otel\/opentelemetry-collector-contrib:0.98.0<\/span><\/span>\n<span id=\"cb13-13\"><a href=\"#cb13-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">command<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"st\">&quot;--config=\/etc\/otel-collector-config.yml&quot;<\/span><span class=\"kw\">]<\/span><\/span>\n<span id=\"cb13-14\"><a href=\"#cb13-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-15\"><a href=\"#cb13-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/otel-collector-config.yml:\/etc\/otel-collector-config.yml<\/span><\/span>\n<span id=\"cb13-16\"><a href=\"#cb13-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">ports<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-17\"><a href=\"#cb13-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;4318:4318&quot;<\/span><span class=\"co\"> # Otel Receiver<\/span><\/span>\n<span id=\"cb13-18\"><a href=\"#cb13-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;8889:8889&quot;<\/span><span class=\"co\"> # Prometheus Scrape<\/span><\/span>\n<span id=\"cb13-19\"><a href=\"#cb13-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">depends_on<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-20\"><a href=\"#cb13-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> autoinstrumenter<\/span><\/span>\n<span id=\"cb13-21\"><a href=\"#cb13-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> jaeger<\/span><\/span>\n<span id=\"cb13-22\"><a href=\"#cb13-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> prometheus<\/span><\/span>\n<span id=\"cb13-23\"><a href=\"#cb13-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb13-24\"><a href=\"#cb13-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">prometheus<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-25\"><a href=\"#cb13-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> prom\/prometheus<\/span><\/span>\n<span id=\"cb13-26\"><a href=\"#cb13-26\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-27\"><a href=\"#cb13-27\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/prometheus.yml:\/etc\/prometheus\/prometheus.yml<\/span><\/span>\n<span id=\"cb13-28\"><a href=\"#cb13-28\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">ports<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-29\"><a href=\"#cb13-29\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;9090:9090&quot;<\/span><span class=\"co\"> # Prometheus UI<\/span><\/span>\n<span id=\"cb13-30\"><a href=\"#cb13-30\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb13-31\"><a href=\"#cb13-31\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">grafana<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-32\"><a href=\"#cb13-32\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> grafana\/grafana<\/span><\/span>\n<span id=\"cb13-33\"><a href=\"#cb13-33\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">restart<\/span><span class=\"kw\">:<\/span><span class=\"at\"> always<\/span><\/span>\n<span id=\"cb13-34\"><a href=\"#cb13-34\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">environment<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-35\"><a href=\"#cb13-35\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> GF_SECURITY_ADMIN_USER=admin<\/span><\/span>\n<span id=\"cb13-36\"><a href=\"#cb13-36\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> GF_SECURITY_ADMIN_PASSWORD=RandomString123!<\/span><\/span>\n<span id=\"cb13-37\"><a href=\"#cb13-37\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">volumes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-38\"><a href=\"#cb13-38\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> .\/grafana-ds.yml:\/etc\/grafana\/provisioning\/datasources\/datasource.yml<\/span><\/span>\n<span id=\"cb13-39\"><a href=\"#cb13-39\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">ports<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-40\"><a href=\"#cb13-40\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;3000:3000&quot;<\/span><span class=\"co\"> # Grafana UI<\/span><\/span>\n<span id=\"cb13-41\"><a href=\"#cb13-41\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb13-42\"><a href=\"#cb13-42\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">jaeger<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-43\"><a href=\"#cb13-43\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">image<\/span><span class=\"kw\">:<\/span><span class=\"at\"> jaegertracing\/all-in-one<\/span><\/span>\n<span id=\"cb13-44\"><a href=\"#cb13-44\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">container_name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> jaeger<\/span><\/span>\n<span id=\"cb13-45\"><a href=\"#cb13-45\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">ports<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb13-46\"><a href=\"#cb13-46\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;16686:16686&quot;<\/span><span class=\"co\"> # Jaeger UI<\/span><\/span>\n<span id=\"cb13-47\"><a href=\"#cb13-47\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;4317:4317&quot;<\/span><span class=\"co\">  # Jaeger OTLP\/gRPC Collector<\/span><\/span><\/code><\/pre><\/div>\n<p>Here's what the configuration files look like:<\/p>\n<ul>\n<li>obi.yml:<\/li>\n<\/ul>\n<div class=\"sourceCode\" id=\"cb14\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb14-1\"><a href=\"#cb14-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">log_level<\/span><span class=\"kw\">:<\/span><span class=\"at\"> INFO<\/span><\/span>\n<span id=\"cb14-2\"><a href=\"#cb14-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">trace_printer<\/span><span class=\"kw\">:<\/span><span class=\"at\"> text<\/span><\/span>\n<span id=\"cb14-3\"><a href=\"#cb14-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb14-4\"><a href=\"#cb14-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">discovery<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb14-5\"><a href=\"#cb14-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">instrument<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb14-6\"><a href=\"#cb14-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">open_ports<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8080<\/span><\/span>\n<span id=\"cb14-7\"><a href=\"#cb14-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb14-8\"><a href=\"#cb14-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">otel_metrics_export<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb14-9\"><a href=\"#cb14-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><span class=\"at\"> http:\/\/otel-collector:4318<\/span><\/span>\n<span id=\"cb14-10\"><a href=\"#cb14-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">otel_traces_export<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb14-11\"><a href=\"#cb14-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><span class=\"at\"> http:\/\/otel-collector:4318<\/span><\/span><\/code><\/pre><\/div>\n<ul>\n<li>prometheus.yml:<\/li>\n<\/ul>\n<div class=\"sourceCode\" id=\"cb15\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb15-1\"><a href=\"#cb15-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">global<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb15-2\"><a href=\"#cb15-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">scrape_interval<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 5s<\/span><\/span>\n<span id=\"cb15-3\"><a href=\"#cb15-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb15-4\"><a href=\"#cb15-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">scrape_configs<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb15-5\"><a href=\"#cb15-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">job_name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"st\">&#39;otel-collector&#39;<\/span><\/span>\n<span id=\"cb15-6\"><a href=\"#cb15-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">static_configs<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb15-7\"><a href=\"#cb15-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">targets<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"st\">&#39;otel-collector:8889&#39;<\/span><span class=\"kw\">]<\/span><\/span><\/code><\/pre><\/div>\n<ul>\n<li>grafana-ds.yml:<\/li>\n<\/ul>\n<div class=\"sourceCode\" id=\"cb16\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb16-1\"><a href=\"#cb16-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">apiVersion<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">1<\/span><\/span>\n<span id=\"cb16-2\"><a href=\"#cb16-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb16-3\"><a href=\"#cb16-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">datasources<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb16-4\"><a href=\"#cb16-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> Prometheus<\/span><\/span>\n<span id=\"cb16-5\"><a href=\"#cb16-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">type<\/span><span class=\"kw\">:<\/span><span class=\"at\"> prometheus<\/span><\/span>\n<span id=\"cb16-6\"><a href=\"#cb16-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">access<\/span><span class=\"kw\">:<\/span><span class=\"at\"> proxy<\/span><\/span>\n<span id=\"cb16-7\"><a href=\"#cb16-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">url<\/span><span class=\"kw\">:<\/span><span class=\"at\"> http:\/\/prometheus:9090<\/span><\/span>\n<span id=\"cb16-8\"><a href=\"#cb16-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">isDefault<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"ch\">true<\/span><\/span><\/code><\/pre><\/div>\n<ul>\n<li>otel-collector-config.yml:<\/li>\n<\/ul>\n<div class=\"sourceCode\" id=\"cb17\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb17-1\"><a href=\"#cb17-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">receivers<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-2\"><a href=\"#cb17-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">otlp<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-3\"><a href=\"#cb17-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">protocols<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-4\"><a href=\"#cb17-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">http<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-5\"><a href=\"#cb17-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><span class=\"at\"> otel-collector:4318<\/span><\/span>\n<span id=\"cb17-6\"><a href=\"#cb17-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb17-7\"><a href=\"#cb17-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">exporters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-8\"><a href=\"#cb17-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">otlp\/jaeger<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-9\"><a href=\"#cb17-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><span class=\"at\"> jaeger:4317<\/span><\/span>\n<span id=\"cb17-10\"><a href=\"#cb17-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">tls<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-11\"><a href=\"#cb17-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">insecure<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"ch\">true<\/span><\/span>\n<span id=\"cb17-12\"><a href=\"#cb17-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb17-13\"><a href=\"#cb17-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">prometheus<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-14\"><a href=\"#cb17-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 0.0.0.0:8889<\/span><\/span>\n<span id=\"cb17-15\"><a href=\"#cb17-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">namespace<\/span><span class=\"kw\">:<\/span><span class=\"at\"> default<\/span><\/span>\n<span id=\"cb17-16\"><a href=\"#cb17-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb17-17\"><a href=\"#cb17-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">service<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-18\"><a href=\"#cb17-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">pipelines<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-19\"><a href=\"#cb17-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">traces<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-20\"><a href=\"#cb17-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">receivers<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">otlp<\/span><span class=\"kw\">]<\/span><\/span>\n<span id=\"cb17-21\"><a href=\"#cb17-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">exporters<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">otlp\/jaeger<\/span><span class=\"kw\">]<\/span><\/span>\n<span id=\"cb17-22\"><a href=\"#cb17-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb17-23\"><a href=\"#cb17-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">metrics<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb17-24\"><a href=\"#cb17-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">receivers<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">otlp<\/span><span class=\"kw\">]<\/span><span class=\"at\"> <\/span><\/span>\n<span id=\"cb17-25\"><a href=\"#cb17-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">exporters<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">prometheus<\/span><span class=\"kw\">]<\/span><\/span><\/code><\/pre><\/div>\n<p>We're almost there, the OpenTelemetry Collector is just missing a\nprocessor. To create the processor filter, we can look at the OBI logs\nto find the PID of the HTTP server being instrumented:<\/p>\n<div class=\"sourceCode\" id=\"cb18\"><pre\nclass=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb18-1\"><a href=\"#cb18-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">autoinstrumenter-1<\/span>  <span class=\"kw\">|<\/span> <span class=\"va\">time<\/span><span class=\"op\">=<\/span>2025-12-30T19:57:17.593Z <span class=\"va\">level<\/span><span class=\"op\">=<\/span>INFO <span class=\"va\">msg<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;instrumenting process&quot;<\/span> <span class=\"va\">component<\/span><span class=\"op\">=<\/span>discover.traceAttacher <span class=\"va\">cmd<\/span><span class=\"op\">=<\/span>\/usr\/bin\/python3.13 <span class=\"va\">pid<\/span><span class=\"op\">=<\/span>297514 <span class=\"va\">ino<\/span><span class=\"op\">=<\/span>460310 <span class=\"va\">type<\/span><span class=\"op\">=<\/span>python <span class=\"va\">service<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;&quot;<\/span><\/span>\n<span id=\"cb18-2\"><a href=\"#cb18-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">autoinstrumenter-1<\/span>  <span class=\"kw\">|<\/span> <span class=\"va\">time<\/span><span class=\"op\">=<\/span>2025-12-30T19:57:18.320Z <span class=\"va\">level<\/span><span class=\"op\">=<\/span>INFO <span class=\"va\">msg<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;instrumenting process&quot;<\/span> <span class=\"va\">component<\/span><span class=\"op\">=<\/span>discover.traceAttacher <span class=\"va\">cmd<\/span><span class=\"op\">=<\/span>\/usr\/bin\/python3.13 <span class=\"va\">pid<\/span><span class=\"op\">=<\/span>310288 <span class=\"va\">ino<\/span><span class=\"op\">=<\/span>722998 <span class=\"va\">type<\/span><span class=\"op\">=<\/span>python <span class=\"va\">service<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;&quot;<\/span><\/span>\n<span id=\"cb18-3\"><a href=\"#cb18-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">autoinstrumenter-1<\/span>  <span class=\"kw\">|<\/span> <span class=\"va\">time<\/span><span class=\"op\">=<\/span>2025-12-30T19:57:18.512Z <span class=\"va\">level<\/span><span class=\"op\">=<\/span>INFO <span class=\"va\">msg<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;instrumenting process&quot;<\/span> <span class=\"va\">component<\/span><span class=\"op\">=<\/span>discover.traceAttacher <span class=\"va\">cmd<\/span><span class=\"op\">=<\/span>\/usr\/bin\/python3.13 <span class=\"va\">pid<\/span><span class=\"op\">=<\/span>315183 <span class=\"va\">ino<\/span><span class=\"op\">=<\/span>2888480 <span class=\"va\">type<\/span><span class=\"op\">=<\/span>python <span class=\"va\">service<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;&quot;<\/span><\/span><\/code><\/pre><\/div>\n<p>Which can also be obtained using standard GNU\/Linux utilities:<\/p>\n<pre><code>$ cat \/sys\/fs\/cgroup\/lxc.payload.server01\/system.slice\/server.service\/cgroup.procs \n297514\n$ cat \/sys\/fs\/cgroup\/lxc.payload.server02\/system.slice\/server.service\/cgroup.procs \n310288\n$ ps -aux | grep http.server\nUSER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\n1000000   297514  0.0  0.1  32120 14856 ?        Ss   16:03   0:00 \/usr\/bin\/python3 -m http.server 8080\n1000000   310288  0.0  0.1  32120 10616 ?        Ss   16:09   0:00 \/usr\/bin\/python3 -m http.server 8080\ncipriano  315183  0.0  0.1 103476 11480 pts\/3    S+   16:17   0:00 python -m http.server 8080<\/code><\/pre>\n<p>If we search for the PID in the OpenTelemetry Collector endpoint\nwhere Prometheus metrics are exposed, we can find the attribute values\nto filter on.<\/p>\n<pre><code>$ curl http:\/\/localhost:8889\/metrics | rg 297514\ndefault_target_info{host_id=&quot;148f400ad3ea&quot;,host_name=&quot;148f400ad3ea&quot;,instance=&quot;148f400ad3ea:297514&quot;,job=&quot;python3.13&quot;,os_type=&quot;linux&quot;,service_instance_id=&quot;148f400ad3ea:297514&quot;,service_name=&quot;python3.13&quot;,telemetry_sdk_language=&quot;python&quot;,telemetry_sdk_name=&quot;opentelemetry-ebpf-instrumentation&quot;,telemetry_sdk_version=&quot;main&quot;} 1<\/code><\/pre>\n<p>Now we just need to add the processor to the collector\nconfiguration:<\/p>\n<div class=\"sourceCode\" id=\"cb21\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb21-1\"><a href=\"#cb21-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">processors<\/span><span class=\"kw\">:<\/span><span class=\"co\"> # &lt;--- NEW BLOCK<\/span><\/span>\n<span id=\"cb21-2\"><a href=\"#cb21-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">filter\/host_id<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-3\"><a href=\"#cb21-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">traces<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-4\"><a href=\"#cb21-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">span<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-5\"><a href=\"#cb21-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"st\">&#39;resource.attributes[&quot;service.instance.id&quot;] == &quot;148f400ad3ea:297514&quot;&#39;<\/span><\/span>\n<span id=\"cb21-6\"><a href=\"#cb21-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb21-7\"><a href=\"#cb21-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">service<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-8\"><a href=\"#cb21-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">pipelines<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-9\"><a href=\"#cb21-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">traces<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-10\"><a href=\"#cb21-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">receivers<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">otlp<\/span><span class=\"kw\">]<\/span><\/span>\n<span id=\"cb21-11\"><a href=\"#cb21-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">processors<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">filter\/host_id<\/span><span class=\"kw\">]<\/span><span class=\"co\"> # &lt;--- NEW LINE<\/span><\/span>\n<span id=\"cb21-12\"><a href=\"#cb21-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">exporters<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">otlp\/jaeger<\/span><span class=\"kw\">]<\/span><\/span>\n<span id=\"cb21-13\"><a href=\"#cb21-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb21-14\"><a href=\"#cb21-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">metrics<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb21-15\"><a href=\"#cb21-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">receivers<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">otlp<\/span><span class=\"kw\">]<\/span><span class=\"at\"> <\/span><\/span>\n<span id=\"cb21-16\"><a href=\"#cb21-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">processors<\/span><span class=\"kw\">:<\/span><span class=\"co\">  # &lt;--- NEW BLOCK<\/span><\/span>\n<span id=\"cb21-17\"><a href=\"#cb21-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"kw\">-<\/span><span class=\"at\"> filter\/host_id<\/span><\/span>\n<span id=\"cb21-18\"><a href=\"#cb21-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">exporters<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"at\">prometheus<\/span><span class=\"kw\">]<\/span><\/span><\/code><\/pre><\/div>\n<p>That's it! The processor will handle the filtering for us, and we'll\nonly see traces and metrics from the HTTP server running in the\n<code>server01<\/code> container. Below are some screenshots from Jaeger\nand Grafana:<\/p>\n<p><img\nsrc=\".\/assets\/beyla-envoy-post\/jaeger_all_traces.png\"\nalt=\"jaeger search will all traces\"\nclass=\"markdown-img\"><\/p>\n<p><img\nsrc=\".\/assets\/beyla-envoy-post\/jaeger_trace.png\"\nalt=\"one jaeger trace\"\nclass=\"markdown-img\"><\/p>\n<p><img\nsrc=\".\/assets\/beyla-envoy-post\/grafana.png\"\nalt=\"grafana request duration panel\"\nclass=\"markdown-img\"><\/p>\n<h2 id=\"closing-notes\">Closing Notes<\/h2>\n<p>I am still amazed at how powerful OBI can be.<\/p>\n<p>For those curious about the debug, we found out that a service\nresponsible for the network orchestration of the Envoy containers was\nrunning <code>netplan apply<\/code> every 10 minutes because of a bug.\nNetplan apply causes interfaces to go down temporarily and this made the\nlatency go above 500ms which caused the 499s.<\/p>","link":{"@attributes":{"href":"beyla-envoy.html"}},"id":"tag:www.sergiocipriano.com,2025-12-31:posts\/beyla-envoy.md","published":"2025-12-31T11:15:25-03:00","updated":"2025-12-31T11:15:25-03:00"},{"title":"Avoiding 5XX errors by adjusting Load Balancer Idle Timeout","content":"<h1\nid=\"avoiding-5xx-errors-by-adjusting-load-balancer-idle-timeout\">Avoiding\n5XX errors by adjusting Load Balancer Idle Timeout<\/h1>\n<p>Recently I faced a problem in production where a client was running a\nRabbitMQ server behind the Load Balancers we provisioned and the TCP\nconnections were closed every minute.<\/p>\n<p>My team is responsible for the LBaaS (Load Balancer as a Service)\nproduct and this Load Balancer was an Envoy proxy provisioned by our\ncontrol plane.<\/p>\n<p>The error was similar to this:<\/p>\n<pre><code>[2025-10-03 12:37:17,525 - pika.adapters.utils.connection_workflow - ERROR] AMQPConnector - reporting failure: AMQPConnectorSocketConnectError: timeout(&quot;TCP connection attempt timed out: &#39;&#39;\/(&lt;AddressFamily.AF_INET: 2&gt;, &lt;SocketKind.SOCK_STREAM: 1&gt;, 6, &#39;&#39;, (&#39;&lt;IP&gt;&#39;, 5672))&quot;)\n[2025-10-03 12:37:17,526 - pika.adapters.utils.connection_workflow - ERROR] AMQP connection workflow failed: AMQPConnectionWorkflowFailed: 1 exceptions in all; last exception - AMQPConnectorSocketConnectError: timeout(&quot;TCP connection attempt timed out: &#39;&#39;\/(&lt;AddressFamily.AF_INET: 2&gt;, &lt;SocketKind.SOCK_STREAM: 1&gt;, 6, &#39;&#39;, (&#39;&lt;IP&gt;&#39;, 5672))&quot;); first exception - None.\n[2025-10-03 12:37:17,526 - pika.adapters.utils.connection_workflow - ERROR] AMQPConnectionWorkflow - reporting failure: AMQPConnectionWorkflowFailed: 1 exceptions in all; last exception - AMQPConnectorSocketConnectError: timeout(&quot;TCP connection attempt timed out: &#39;&#39;\/(&lt;AddressFamily.AF_INET: 2&gt;, &lt;SocketKind.SOCK_STREAM: 1&gt;, 6, &#39;&#39;, (&#39;&lt;IP&gt;&#39;, 5672))&quot;); first exception - None<\/code><\/pre>\n<p>At first glance, the issue is simple: the Load Balancer's idle\ntimeout is shorter than the RabbitMQ heartbeat interval.<\/p>\n<p>The idle timeout is the time at which a downstream or upstream\nconnection will be terminated if there are no active streams. Heartbeats\ngenerate periodic network traffic to prevent idle TCP connections from\nclosing prematurely.<\/p>\n<p>Adjusting these timeout settings to align properly solved the\nissue.<\/p>\n<p>However, what I want to explore in this post are other similar\nscenarios where it's not so obvious that the idle timeout is the\nproblem. Introducing an extra network layer, such as an Envoy proxy, can\nintroduce unpredictable behavior across your services, like intermittent\n5XX errors.<\/p>\n<p>To make this issue more concrete, let's look at a minimal,\nreproducible setup that demonstrates how adding an Envoy proxy can lead\nto sporadic errors.<\/p>\n<h2 id=\"reproducible-setup\">Reproducible setup<\/h2>\n<p>I'll be using the following tools:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.docker.com\/\">Docker<\/a><\/li>\n<li><a href=\"https:\/\/www.envoyproxy.io\/\">EnvoyProxy<\/a><\/li>\n<li><a href=\"https:\/\/go.dev\/\">Go<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/hatoo\/oha\/\">oha<\/a><\/li>\n<\/ul>\n<p>This setup is based on what Kai Burjack presented in his <a\nhref=\"https:\/\/medium.com\/@kburjack\/fixing-503-errors-when-using-istio-envoy-bf63aa720826\">article<\/a>.<\/p>\n<p>Setting up Envoy with Docker is straightforward:<\/p>\n<pre><code>$ docker run \\\n    --name envoy --rm \\\n    --network host \\\n    -v $(pwd)\/envoy.yaml:\/etc\/envoy\/envoy.yaml \\\n    envoyproxy\/envoy:v1.33-latest<\/code><\/pre>\n<p>I'll be running experiments with two different\n<code>envoy.yaml<\/code> configurations: one that uses Envoy's TCP proxy,\nand another that uses Envoy's HTTP connection manager.<\/p>\n<p>Here's the simplest Envoy TCP proxy setup: a listener on port 8000\nforwarding traffic to a backend running on port 8080.<\/p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">static_resources<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">listeners<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_listener<\/span><\/span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">socket_address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"fl\">0.0.0.0<\/span><\/span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">port_value<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8000<\/span><\/span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">filter_chains<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">filters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoy.filters.network.tcp_proxy<\/span><\/span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">typed_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy<\/span><\/span>\n<span id=\"cb3-13\"><a href=\"#cb3-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">stat_prefix<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_tcp<\/span><\/span>\n<span id=\"cb3-14\"><a href=\"#cb3-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">cluster<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb3-15\"><a href=\"#cb3-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">clusters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-16\"><a href=\"#cb3-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb3-17\"><a href=\"#cb3-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">connect_timeout<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 1s<\/span><\/span>\n<span id=\"cb3-18\"><a href=\"#cb3-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">type<\/span><span class=\"kw\">:<\/span><span class=\"at\"> static<\/span><\/span>\n<span id=\"cb3-19\"><a href=\"#cb3-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">load_assignment<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-20\"><a href=\"#cb3-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">cluster_name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb3-21\"><a href=\"#cb3-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">endpoints<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-22\"><a href=\"#cb3-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">lb_endpoints<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-23\"><a href=\"#cb3-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-24\"><a href=\"#cb3-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-25\"><a href=\"#cb3-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">socket_address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb3-26\"><a href=\"#cb3-26\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"fl\">127.0.0.1<\/span><\/span>\n<span id=\"cb3-27\"><a href=\"#cb3-27\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">port_value<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8080<\/span><\/span><\/code><\/pre><\/div>\n<p>The default idle timeout if not otherwise specified is 1 hour, which\nis the case here.<\/p>\n<p>The backend setup is simple as well:<\/p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode go\"><code class=\"sourceCode go\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">package<\/span> main<\/span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">import<\/span> <span class=\"op\">(<\/span><\/span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"st\">&quot;fmt&quot;<\/span><\/span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"st\">&quot;net\/http&quot;<\/span><\/span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"st\">&quot;time&quot;<\/span><\/span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"op\">)<\/span><\/span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">func<\/span> helloHandler<span class=\"op\">(<\/span>w http<span class=\"op\">.<\/span>ResponseWriter<span class=\"op\">,<\/span> r <span class=\"op\">*<\/span>http<span class=\"op\">.<\/span>Request<span class=\"op\">)<\/span> <span class=\"op\">{<\/span><\/span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>  w<span class=\"op\">.<\/span>Write<span class=\"op\">([]<\/span><span class=\"dt\">byte<\/span><span class=\"op\">(<\/span><span class=\"st\">&quot;Hello from Go!&quot;<\/span><span class=\"op\">))<\/span><\/span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"op\">}<\/span><\/span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">func<\/span> main<span class=\"op\">()<\/span> <span class=\"op\">{<\/span><\/span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    http<span class=\"op\">.<\/span>HandleFunc<span class=\"op\">(<\/span><span class=\"st\">&quot;\/&quot;<\/span><span class=\"op\">,<\/span> helloHandler<span class=\"op\">)<\/span><\/span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    server <span class=\"op\">:=<\/span> http<span class=\"op\">.<\/span>Server<span class=\"op\">{<\/span><\/span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        Addr<span class=\"op\">:<\/span>        <span class=\"st\">&quot;:8080&quot;<\/span><span class=\"op\">,<\/span><\/span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        IdleTimeout<span class=\"op\">:<\/span> <span class=\"dv\">3<\/span> <span class=\"op\">*<\/span> time<span class=\"op\">.<\/span>Second<span class=\"op\">,<\/span><\/span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"op\">}<\/span><\/span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    fmt<span class=\"op\">.<\/span>Println<span class=\"op\">(<\/span><span class=\"st\">&quot;Starting server on :8080&quot;<\/span><span class=\"op\">)<\/span><\/span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"bu\">panic<\/span><span class=\"op\">(<\/span>server<span class=\"op\">.<\/span>ListenAndServe<span class=\"op\">())<\/span><\/span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"op\">}<\/span><\/span><\/code><\/pre><\/div>\n<p>The IdleTimeout is set to 3 seconds to make it easier to test.<\/p>\n<p>Now, <code>oha<\/code> is the perfect tool to generate the HTTP\nrequests for this test. The Load test is not meant to stress this setup,\nthe idea is to wait long enough so that some requests are closed. The\n<code>burst-delay<\/code> feature will help with that:<\/p>\n<pre><code>$ oha -z 30s -w --burst-delay 3s --burst-rate 100 http:\/\/localhost:8000<\/code><\/pre>\n<p>I'm running the Load test for 30 seconds, sending 100 requests at\nthree-second intervals. I also use the <code>-w<\/code> option to wait\nfor ongoing requests when the duration is reached. The result looks like\nthis:<\/p>\n<p><img\nsrc=\".\/assets\/idle-timeout-post\/oha-tcp-proxy-fail.png\"\nalt=\"oha test report tcp fail\"\nclass=\"markdown-img\"><\/p>\n<p>We had 886 responses with status code 200 and 64 connections closed.\nThe backend terminated 64 connections while the load balancer still had\nactive requests directed to it.<\/p>\n<p>Let's change the Load Balancer <code>idle_timeout<\/code> to two\nseconds.<\/p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">filter_chains<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">filters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoy.filters.network.tcp_proxy<\/span><\/span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">typed_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy<\/span><\/span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">stat_prefix<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_tcp<\/span><\/span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">cluster<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">idle_timeout<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 2s<\/span><span class=\"co\"> # &lt;--- NEW LINE<\/span><\/span><\/code><\/pre><\/div>\n<p>Run the same test again.<\/p>\n<p><img\nsrc=\".\/assets\/idle-timeout-post\/oha-tcp-proxy-success.png\"\nalt=\"oha test report tcp success\"\nclass=\"markdown-img\"><\/p>\n<p>Great! Now all the requests worked.<\/p>\n<p>This is a common issue, not specific to Envoy Proxy or the setup\nshown earlier. Major cloud providers have all documented it.<\/p>\n<p><a\nhref=\"https:\/\/docs.aws.amazon.com\/elasticloadbalancing\/latest\/application\/load-balancer-troubleshooting.html#http-502-issues\">AWS\ntroubleshoot guide for Application Load Balancers<\/a> says this:<\/p>\n<p><code>The target closed the connection with a TCP RST or a TCP FIN while the load balancer had an outstanding request to the target. Check whether the keep-alive duration of the target is shorter than the idle timeout value of the load balancer.<\/code><\/p>\n<p><a\nhref=\"https:\/\/cloud.google.com\/load-balancing\/docs\/https\/troubleshooting-ext-https-lbs\">Google\ntroubleshoot guide for Application Load Balancers<\/a> mention this as\nwell:<\/p>\n<p><code>Verify that the keepalive configuration parameter for the HTTP server software running on the backend instance is not less than the keepalive timeout of the load balancer, whose value is fixed at 10 minutes (600 seconds) and is not configurable.<\/code><\/p>\n<p><code>The load balancer generates an HTTP 5XX response code when the connection to the backend has unexpectedly closed while sending the HTTP request or before the complete HTTP response has been received. This can happen because the keepalive configuration parameter for the web server software running on the backend instance is less than the fixed keepalive timeout of the load balancer. Ensure that the keepalive timeout configuration for HTTP server software on each backend is set to slightly greater than 10 minutes (the recommended value is 620 seconds).<\/code><\/p>\n<p><a\nhref=\"https:\/\/www.rabbitmq.com\/docs\/heartbeats#tcp-proxies\">RabbitMQ\ndocs<\/a> also warn about this:<\/p>\n<p><code>Certain networking tools (HAproxy, AWS ELB) and equipment (hardware load balancers) may terminate \"idle\" TCP connections when there is no activity on them for a certain period of time. Most of the time it is not desirable.<\/code><\/p>\n<p>Most of them are talking about Application Load Balancers and the\ntest I did was using a Network Load Balancer. For the sake of\ncompleteness, I will do the same test but using Envoy's HTTP connection\nmanager.<\/p>\n<p>The updated <code>envoy.yaml<\/code>:<\/p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"fu\">static_resources<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">listeners<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> listener<\/span><\/span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">socket_address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"fl\">0.0.0.0<\/span><\/span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">port_value<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8000<\/span><\/span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">filter_chains<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">filters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoy.filters.network.http_connection_manager<\/span><\/span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">typed_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager<\/span><\/span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">stat_prefix<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_http<\/span><\/span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">access_log<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoy.access_loggers.stdout<\/span><\/span>\n<span id=\"cb7-16\"><a href=\"#cb7-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">typed_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-17\"><a href=\"#cb7-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog<\/span><\/span>\n<span id=\"cb7-18\"><a href=\"#cb7-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">http_filters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-19\"><a href=\"#cb7-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> envoy.filters.http.router<\/span><\/span>\n<span id=\"cb7-20\"><a href=\"#cb7-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">typed_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-21\"><a href=\"#cb7-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.filters.http.router.v3.Router<\/span><\/span>\n<span id=\"cb7-22\"><a href=\"#cb7-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">route_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-23\"><a href=\"#cb7-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> http_route<\/span><\/span>\n<span id=\"cb7-24\"><a href=\"#cb7-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">virtual_hosts<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-25\"><a href=\"#cb7-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> local_service<\/span><\/span>\n<span id=\"cb7-26\"><a href=\"#cb7-26\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">domains<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">[<\/span><span class=\"st\">&quot;*&quot;<\/span><span class=\"kw\">]<\/span><\/span>\n<span id=\"cb7-27\"><a href=\"#cb7-27\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">routes<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-28\"><a href=\"#cb7-28\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">match<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-29\"><a href=\"#cb7-29\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                  <\/span><span class=\"fu\">prefix<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"st\">&quot;\/&quot;<\/span><\/span>\n<span id=\"cb7-30\"><a href=\"#cb7-30\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">route<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-31\"><a href=\"#cb7-31\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                  <\/span><span class=\"fu\">cluster<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb7-32\"><a href=\"#cb7-32\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">clusters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-33\"><a href=\"#cb7-33\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb7-34\"><a href=\"#cb7-34\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">type<\/span><span class=\"kw\">:<\/span><span class=\"at\"> STATIC<\/span><\/span>\n<span id=\"cb7-35\"><a href=\"#cb7-35\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">load_assignment<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-36\"><a href=\"#cb7-36\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">cluster_name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb7-37\"><a href=\"#cb7-37\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">endpoints<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-38\"><a href=\"#cb7-38\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">lb_endpoints<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-39\"><a href=\"#cb7-39\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">endpoint<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-40\"><a href=\"#cb7-40\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">            <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-41\"><a href=\"#cb7-41\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">              <\/span><span class=\"fu\">socket_address<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb7-42\"><a href=\"#cb7-42\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">address<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"fl\">0.0.0.0<\/span><\/span>\n<span id=\"cb7-43\"><a href=\"#cb7-43\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">                <\/span><span class=\"fu\">port_value<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"dv\">8080<\/span><\/span><\/code><\/pre><\/div>\n<p>The yaml above is an example of a service proxying HTTP from\n0.0.0.0:8000 to 0.0.0.0:8080. The only difference from a <a\nhref=\"https:\/\/www.envoyproxy.io\/docs\/envoy\/latest\/configuration\/overview\/examples.html\">minimal<\/a>\nconfiguration is that I enabled access logs.<\/p>\n<p>Let's run the same tests with oha.<\/p>\n<p><img\nsrc=\".\/assets\/idle-timeout-post\/oha-http-fail.png\"\nalt=\"oha test report http fail\"\nclass=\"markdown-img\"><\/p>\n<p>Even thought the success rate is 100%, the status code distribution\nshow some responses with status code 503. This is the case where is not\nthat obvious that the problem is related to idle timeout.<\/p>\n<p>However, it's clear when we look the Envoy access logs:<\/p>\n<pre><code>[2025-10-10T13:32:26.617Z] &quot;GET \/ HTTP\/1.1&quot; 503 UC 0 95 0 - &quot;-&quot; &quot;oha\/1.10.0&quot; &quot;9b1cb963-449b-41d7-b614-f851ced92c3b&quot; &quot;localhost:8000&quot; &quot;0.0.0.0:8080&quot;<\/code><\/pre>\n<p><code>UC<\/code> is the short name for\n<code>UpstreamConnectionTermination<\/code>. This means the <a\nhref=\"https:\/\/www.envoyproxy.io\/docs\/envoy\/latest\/intro\/arch_overview\/intro\/terminology\">upstream<\/a>,\nwhich is the golang server, terminated the connection.<\/p>\n<p>To fix this once again, the Load Balancer idle timeout needs to\nchange:<\/p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode yaml\"><code class=\"sourceCode yaml\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"fu\">clusters<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">  <\/span><span class=\"kw\">-<\/span><span class=\"at\"> <\/span><span class=\"fu\">name<\/span><span class=\"kw\">:<\/span><span class=\"at\"> go_server_cluster<\/span><\/span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">type<\/span><span class=\"kw\">:<\/span><span class=\"at\"> STATIC<\/span><\/span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">    <\/span><span class=\"fu\">typed_extension_protocol_options<\/span><span class=\"kw\">:<\/span><span class=\"co\"> # &lt;--- NEW BLOCK<\/span><\/span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">      <\/span><span class=\"fu\">envoy.extensions.upstreams.http.v3.HttpProtocolOptions<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">&quot;@type&quot;<\/span><span class=\"kw\">:<\/span><span class=\"at\"> type.googleapis.com\/envoy.extensions.upstreams.http.v3.HttpProtocolOptions<\/span><\/span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">common_http_protocol_options<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">idle_timeout<\/span><span class=\"kw\">:<\/span><span class=\"at\"> 2s<\/span><span class=\"co\"> # &lt;--- NEW VALUE<\/span><\/span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">        <\/span><span class=\"fu\">explicit_http_config<\/span><span class=\"kw\">:<\/span><\/span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"at\">          <\/span><span class=\"fu\">http_protocol_options<\/span><span class=\"kw\">:<\/span><span class=\"at\"> <\/span><span class=\"kw\">{}<\/span><\/span><\/code><\/pre><\/div>\n<p>Finally, the sporadic 503 errors are over:<\/p>\n<p><img\nsrc=\".\/assets\/idle-timeout-post\/oha-http-success.png\"\nalt=\"oha test report http success\"\nclass=\"markdown-img\"><\/p>\n<h1 id=\"to-sum-up\">To Sum Up<\/h1>\n<p>Here's an example of the values my team recommends to our\nclients:<\/p>\n<p><img\nsrc=\".\/assets\/idle-timeout-post\/recap.png\"\nalt=\"recap drawing\"\nclass=\"markdown-img\"><\/p>\n<p>Key Takeaways:<\/p>\n<ol type=\"1\">\n<li>The Load Balancer idle timeout should be less than the backend\n(upstream) idle\/keepalive timeout.<\/li>\n<li>When we are working with long lived connections, the client\n(downstream) should use a keepalive smaller than the LB idle\ntimeout.<\/li>\n<\/ol>","link":{"@attributes":{"href":"idle-timeout.html"}},"id":"tag:www.sergiocipriano.com,2025-10-10:posts\/idle-timeout.md","published":"2025-10-10T11:56:37-03:00","updated":"2025-10-10T14:04:22-03:00"},{"title":"Running Docker (OCI) Images in Incus","content":"<h1 id=\"running-docker-oci-images-in-incus\">Running Docker (OCI) Images\nin Incus<\/h1>\n<p><a\nhref=\"https:\/\/discuss.linuxcontainers.org\/t\/incus-6-15-has-been-released\/24333\">Incus\n6.15<\/a> released with a lot of cool features, my favorite so far is the\nauthentication support for OCI registries.<\/p>\n<p>Here's an example:<\/p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">$<\/span> incus remote add docker https:\/\/docker.io <span class=\"at\">--protocol<\/span><span class=\"op\">=<\/span>oci<\/span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">$<\/span> incus launch docker:debian:sid sid<\/span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">$<\/span> incus shell sid<\/span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">root@sid:~#<\/span> apt update <span class=\"kw\">&amp;&amp;<\/span> <span class=\"ex\">apt<\/span> upgrade <span class=\"at\">-y<\/span><\/span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">root@sid:~#<\/span> cat \/etc\/os-release <\/span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">PRETTY_NAME<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;Debian GNU\/Linux forky\/sid&quot;<\/span><\/span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">NAME<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;Debian GNU\/Linux&quot;<\/span><\/span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">VERSION_CODENAME<\/span><span class=\"op\">=<\/span>forky<\/span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">ID<\/span><span class=\"op\">=<\/span>debian<\/span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">HOME_URL<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;https:\/\/www.debian.org\/&quot;<\/span><\/span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">SUPPORT_URL<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;https:\/\/www.debian.org\/support&quot;<\/span><\/span>\n<span id=\"cb1-12\"><a href=\"#cb1-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"va\">BUG_REPORT_URL<\/span><span class=\"op\">=<\/span><span class=\"st\">&quot;https:\/\/bugs.debian.org\/&quot;<\/span><\/span><\/code><\/pre><\/div>\n<p>This has been really useful for creating containers to test packages,\nmuch better than launching the official Debian stable Incus images and\nthen manually changing the sources list.<\/p>","link":{"@attributes":{"href":"incus-dockerhub.html"}},"id":"tag:www.sergiocipriano.com,2025-08-11:posts\/incus-dockerhub.md","published":"2025-08-11T23:18:00-03:00","updated":"2025-08-11T23:18:00-03:00"},{"title":"Query Debian changelogs by keyword with the FTP-Master API","content":"<h1\nid=\"query-debian-changelogs-by-keyword-with-the-ftp-master-api\">Query\nDebian changelogs by keyword with the FTP-Master API<\/h1>\n<p>In my post about <a\nhref=\"https:\/\/sergiocipriano.com\/track-debian-uploads.html\">tracking my\nDebian uploads<\/a>, I used the <a\nhref=\"https:\/\/wiki.debian.org\/ProjectB\">ProjectB<\/a> database directly\nto retrieve how many uploads I had so far.<\/p>\n<p>I was pleasantly surprised to receive a message from Joerg Jaspert,\nwho introduced me to the <a\nhref=\"https:\/\/ftp-team.pages.debian.net\/dak\/docs\/generated\/dakweb.html#module-dakweb\">Debian\nArchive Kit web API<\/a> (dak), also known as the FTP-Master API.<\/p>\n<p>Joerg gave the idea of integrating the query I had written into the\ndak API, so that anyone could obtain the same results without needing to\nuse the mirror host, with a simple http request.<\/p>\n<p>I liked the idea and I decided to work on it. The endpoint is already\navailable and you can try by yourself by doing something like this:<\/p>\n<pre><code>$ curl https:\/\/api.ftp-master.debian.org\/changelogs?search_term=almeida+cipriano<\/code><\/pre>\n<blockquote>\n<p><strong>\u26a0\ufe0f WARNING:<\/strong> Check v2: <a\nhref=\"https:\/\/people.debian.org\/~gladk\/blog\/posts\/202601_ftp-master-changelog-v2\/\">https:\/\/people.debian.org\/~gladk\/blog\/posts\/202601_ftp-master-changelog-v2\/<\/a><\/p>\n<\/blockquote>\n<p>The query provides a way to search through the changelogs of all\nDebian packages currently published. The source code is available at <a\nhref=\"https:\/\/salsa.debian.org\/ftp-team\/dak\/-\/commit\/fdeb7a8adeb0e3c6ab5df298a0e243d14cd9e031\">Salsa<\/a>.<\/p>\n<p>I'm already using it to track my uploads, I made <a\nhref=\"https:\/\/people.debian.org\/~cipriano\/uploads\/changelogs.html\">this\npage<\/a> that updates every day. If you want to setup something similar,\nyou can use my <a\nhref=\"https:\/\/salsa.debian.org\/cipriano\/people.debian.org\/-\/blob\/main\/public_html\/uploads\/generate.py?ref_type=heads\">script<\/a>\nand just change the <code>search_term<\/code> to the name you use in your\nchangelog entries.<\/p>\n<p>I\u2019m running it using a systemd timer. Here\u2019s what I\u2019ve got:<\/p>\n<pre><code># .config\/systemd\/user\/track-uploads.service\n[Unit]\nDescription=Track my uploads using the dak API\nStopWhenUnneeded=yes\n\n[Service]\nType=oneshot\nWorkingDirectory=\/home\/cipriano\/public_html\/uploads\nExecStart=\/usr\/bin\/python3 generate.py<\/code><\/pre>\n<pre><code># .config\/systemd\/user\/track-uploads.timer\n[Unit]\nDescription=Run track-uploads script daily\n\n[Timer]\nOnCalendar=daily\nPersistent=true\n\n[Install]\nWantedBy=timers.target<\/code><\/pre>\n<p>After placing every file in the right place you just need to run:<\/p>\n<pre><code>$ systemctl --user daemon-reload\n$ systemctl --user enable --now track-uploads.timer\n$ systemctl --user start track-uploads.service # generates the html now<\/code><\/pre>\n<p>If you want to get a bit fancier, I\u2019m also using an Ansible playbook\nfor that. The source code is available on my <a\nhref=\"https:\/\/gitlab.com\/sergiosacj\/homelab\/-\/blob\/main\/ansible\/roles\/people.d.o\/tasks\/main.yml?ref_type=heads\">GitLab<\/a>\nrepository.<\/p>\n<p>If you want to learn more about dak, there is a <a\nhref=\"https:\/\/api.ftp-master.debian.org\/list_paths\">web docs<\/a>\navailable.<\/p>\n<p>I\u2019d like to thank Joerg once again for suggesting the idea and for\nreviewing and merging the change so quickly.<\/p>","link":{"@attributes":{"href":"dak-changelogs.html"}},"id":"tag:www.sergiocipriano.com,2025-08-03:posts\/dak-changelogs.md","published":"2025-08-03T16:52:06-03:00","updated":"2026-01-27T14:20:46-03:00"},{"title":"Handling malicious requests with fail2ban","content":"<h1 id=\"handling-malicious-requests-with-fail2ban\">Handling malicious\nrequests with fail2ban<\/h1>\n<p>I've been receiving a lot of malicious requests for a while now, so I\ndecided to try out fail2ban as a possible solution.<\/p>\n<p>I see fail2ban as nice to have tool that is useful to keep down the\n\"noise\", but I wouldn't rely on it for security. If you need a tool to\nblock unauthorized attempts or monitor log files excessively, you are\nprobably doing something wrong.<\/p>\n<p>I'm currently using fail2ban 1.0.2-2 from Debian Bookworm.\nUnfortunatly, I quickly ran into a problem, fail2ban doesn't work out of\nthe box with this version:<\/p>\n<pre><code>systemd[1]: Started fail2ban.service - Fail2Ban Service.\nfail2ban-server[2840]: 2025-07-28 14:40:13,450 fail2ban.configreader   [2840]: WARNING &#39;allowipv6&#39; not defined in &#39;Definition&#39;. Using default one: &#39;auto&#39;\nfail2ban-server[2840]: 2025-07-28 14:40:13,456 fail2ban                [2840]: ERROR   Failed during configuration: Have not found an y log file for sshd jail\nfail2ban-server[2840]: 2025-07-28 14:40:13,456 fail2ban                [2840]: ERROR   Async configuration of server failed\nsystemd[1]: fail2ban.service: Main process exited, code=exited, status=255\/EXCEPTION\nsystemd[1]: fail2ban.service: Failed with result &#39;exit-code&#39;.<\/code><\/pre>\n<p>The good news is that this issue has already been addressed for\nDebian Trixie.<\/p>\n<p>Since I prefer to manage my own configuration, I removed the default\nfile at <code>\/etc\/fail2ban\/jail.d\/defaults-debian.conf<\/code> and\nreplaced it with a custom setup. To fix the earlier issue, I also added\na systemd backend to the sshd jail so it would stop expecting a\nlogpath.<\/p>\n<p>Here's the configuration I'm using:<\/p>\n<pre><code>$ cat \/etc\/fail2ban\/jail.d\/custom.conf \n[DEFAULT]\nmaxretry = 3\nfindtime = 24h\nbantime  = 24h\n\n[nginx-bad-request]\nenabled  = true\nport     = http,https\nfilter   = nginx-bad-request\nlogpath  = \/var\/log\/nginx\/access.log\n\n[nginx-botsearch]\nenabled  = true\nport     = http,https\nfilter   = nginx-botsearch\nlogpath  = \/var\/log\/nginx\/access.log\n\n[sshd]\nenabled  = true\nport     = ssh\nfilter   = sshd\nbackend  = systemd<\/code><\/pre>\n<p>I like to make things explicit, so I did repeat some lines from the\ndefault jail.conf file. In the end, I'm quite happy with it so far. Soon\nafter I set it up, fail2ban was already banning a few hosts.<\/p>\n<pre><code>$ sudo fail2ban-client status nginx-bad-request\nStatus for the jail: nginx-bad-request\n|- Filter\n|  |- Currently failed: 42\n|  |- Total failed: 454\n`- Actions\n   |- Currently banned: 12\n   |- Total banned: 39<\/code><\/pre>","link":{"@attributes":{"href":"fail2ban.html"}},"id":"tag:www.sergiocipriano.com,2025-07-28:posts\/fail2ban.md","published":"2025-07-28T12:36:55-03:00","updated":"2025-08-03T00:52:26-03:00"},{"title":"How I finally tracked my Debian uploads correctly","content":"<h1 id=\"how-i-finally-tracked-my-debian-uploads-correctly\">How I finally\ntracked my Debian uploads correctly<\/h1>\n<p>A long time ago, I became aware of <a\nhref=\"https:\/\/udd.debian.org\/\">UDD<\/a> (Ultimate Debian Database), which\ngathers various Debian data into a single SQL database.<\/p>\n<p>At that time, we were trying to do something simple: list the\ncontributions (package uploads) of our local community, Debian Bras\u00edlia.\nWe ended up with a <a\nhref=\"https:\/\/salsa.debian.org\/debian-brasilia-team\/site\/-\/blob\/fa2e1b793fac5e1f8580091184c6703cefad0a2d\/contributors\/main.py\">script<\/a>\nthat counted uploads to unstable and experimental.<\/p>\n<p>I was never satisfied with the final result because some uploads were\nalways missing. Here is an <a\nhref=\"https:\/\/tracker.debian.org\/news\/1242004\/accepted-debci-30-source-into-experimental\/\">example<\/a>:<\/p>\n<pre><code>debci (3.0) experimental; urgency=medium\n...\n   [ Sergio de almeida cipriano Junior ]\n   * Fix Style\/GlovalVars issue\n   * Rename blacklist to rejectlist\n...<\/code><\/pre>\n<p>I made changes in debci 3.0, but the upload was done by someone else.\nThis kind of contribution cannot be tracked by that script.<\/p>\n<p>Then, a few years ago, I learned about <a\nhref=\"https:\/\/nm.debian.org\/minechangelogs\/search\/\">Minechangelogs<\/a>,\nwhich allows us to search through the changelogs of all Debian packages\ncurrently published.<\/p>\n<p>Today, I decided to explore how this was done, since I couldn't find\nanything useful for that kind of query in UDD's tables.<\/p>\n<p>That's when I came across <a\nhref=\"https:\/\/wiki.debian.org\/ProjectB\">ProjectB<\/a>. It was my first\ntime hearing about it. ProjectB is a database that stores all the\nmetadata about the packages in the Debian archive, including the\nchangelogs of those packages.<\/p>\n<p>Now that I'm a Debian Developer, I have access to this database. If\nyou also have access and want to try some queries, you can do this:<\/p>\n<pre><code>$ ssh mirror.ftp-master.debian.org -N -L 15434:danzi.debian.org:5435\n$ psql postgresql:\/\/guest@localhost:15434\/projectb?sslmode=allow<\/code><\/pre>\n<p>In the end, it finally solved my problem.<\/p>\n<p>Using the code below, with UDD, I get 38 uploads:<\/p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode python\"><code class=\"sourceCode python\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"im\">import<\/span> psycopg2<\/span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>contributor <span class=\"op\">=<\/span> <span class=\"st\">&#39;almeida cipriano&#39;<\/span><\/span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"cf\">try<\/span>:<\/span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    connection <span class=\"op\">=<\/span> psycopg2.<span class=\"ex\">connect<\/span>(<\/span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        user<span class=\"op\">=<\/span><span class=\"st\">&quot;udd-mirror&quot;<\/span>,<\/span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        password<span class=\"op\">=<\/span><span class=\"st\">&quot;udd-mirror&quot;<\/span>,<\/span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        host<span class=\"op\">=<\/span><span class=\"st\">&quot;udd-mirror.debian.net&quot;<\/span>,<\/span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        port<span class=\"op\">=<\/span><span class=\"st\">&quot;5432&quot;<\/span>,<\/span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        database<span class=\"op\">=<\/span><span class=\"st\">&quot;udd&quot;<\/span><\/span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    )<\/span>\n<span id=\"cb3-13\"><a href=\"#cb3-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-14\"><a href=\"#cb3-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    cursor <span class=\"op\">=<\/span> connection.cursor()<\/span>\n<span id=\"cb3-15\"><a href=\"#cb3-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-16\"><a href=\"#cb3-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    query <span class=\"op\">=<\/span> <span class=\"ss\">f&quot;SELECT source,version,date,distribution,signed_by_name <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb3-17\"><a href=\"#cb3-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">FROM public.upload_history <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb3-18\"><a href=\"#cb3-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">WHERE changed_by_name ILIKE &#39;%<\/span><span class=\"sc\">{<\/span>contributor<span class=\"sc\">}<\/span><span class=\"ss\">%&#39; <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb3-19\"><a href=\"#cb3-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">ORDER BY date;&quot;<\/span><\/span>\n<span id=\"cb3-20\"><a href=\"#cb3-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-21\"><a href=\"#cb3-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    cursor.execute(query)<\/span>\n<span id=\"cb3-22\"><a href=\"#cb3-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    records <span class=\"op\">=<\/span> cursor.fetchall()<\/span>\n<span id=\"cb3-23\"><a href=\"#cb3-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-24\"><a href=\"#cb3-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"bu\">print<\/span>(<span class=\"ss\">f&quot;I have <\/span><span class=\"sc\">{<\/span><span class=\"bu\">len<\/span>(records)<span class=\"sc\">}<\/span><span class=\"ss\"> uploads.&quot;<\/span>)<\/span>\n<span id=\"cb3-25\"><a href=\"#cb3-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-26\"><a href=\"#cb3-26\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    cursor.close()<\/span>\n<span id=\"cb3-27\"><a href=\"#cb3-27\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    connection.close()<\/span>\n<span id=\"cb3-28\"><a href=\"#cb3-28\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb3-29\"><a href=\"#cb3-29\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"cf\">except<\/span> (<span class=\"pp\">Exception<\/span>, psycopg2.Error) <span class=\"im\">as<\/span> error:<\/span>\n<span id=\"cb3-30\"><a href=\"#cb3-30\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"bu\">print<\/span>(<span class=\"st\">&quot;Error while fetching data from PostgreSQL&quot;<\/span>, error)<\/span><\/code><\/pre><\/div>\n<p>Using the code bellow, with ProjectB, I get 43 uploads (the correct\namount):<\/p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode python\"><code class=\"sourceCode python\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"im\">import<\/span> psycopg2<\/span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>contributor <span class=\"op\">=<\/span> <span class=\"st\">&#39;almeida cipriano&#39;<\/span><\/span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"cf\">try<\/span>:<\/span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"co\"># SSH tunnel is required to access the database:<\/span><\/span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"co\"># ssh &lt;username&gt;@mirror.ftp-master.debian.org -N -L 15434:danzi.debian.org:5435<\/span><\/span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    connection <span class=\"op\">=<\/span> psycopg2.<span class=\"ex\">connect<\/span>(<\/span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        user<span class=\"op\">=<\/span><span class=\"st\">&quot;guest&quot;<\/span>,<\/span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        host<span class=\"op\">=<\/span><span class=\"st\">&quot;localhost&quot;<\/span>,<\/span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        port<span class=\"op\">=<\/span><span class=\"st\">&quot;15434&quot;<\/span>,<\/span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        database<span class=\"op\">=<\/span><span class=\"st\">&quot;projectb&quot;<\/span>,<\/span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>        sslmode<span class=\"op\">=<\/span><span class=\"st\">&quot;allow&quot;<\/span><\/span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    )<\/span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    connection.set_client_encoding(<span class=\"st\">&#39;UTF8&#39;<\/span>)<\/span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    cursor <span class=\"op\">=<\/span> connection.cursor()<\/span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    query <span class=\"op\">=<\/span> <span class=\"ss\">f&quot;SELECT c.source, c.version, c.changedby <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">FROM changes c <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">JOIN changelogs ch ON ch.id = c.changelog_id <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">WHERE c.source != &#39;debian-keyring&#39; <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">  AND (<\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-24\"><a href=\"#cb4-24\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">    ch.changelog ILIKE &#39;%<\/span><span class=\"sc\">{<\/span>contributor<span class=\"sc\">}<\/span><span class=\"ss\">%&#39; <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-25\"><a href=\"#cb4-25\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">    OR c.changedby ILIKE &#39;%<\/span><span class=\"sc\">{<\/span>contributor<span class=\"sc\">}<\/span><span class=\"ss\">%&#39; <\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-26\"><a href=\"#cb4-26\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">  )<\/span><span class=\"op\">\\<\/span><\/span>\n<span id=\"cb4-27\"><a href=\"#cb4-27\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ss\">ORDER BY c.seen;&quot;<\/span><\/span>\n<span id=\"cb4-28\"><a href=\"#cb4-28\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-29\"><a href=\"#cb4-29\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    cursor.execute(query)<\/span>\n<span id=\"cb4-30\"><a href=\"#cb4-30\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    records <span class=\"op\">=<\/span> cursor.fetchall()<\/span>\n<span id=\"cb4-31\"><a href=\"#cb4-31\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-32\"><a href=\"#cb4-32\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"bu\">print<\/span>(<span class=\"ss\">f&quot;I have <\/span><span class=\"sc\">{<\/span><span class=\"bu\">len<\/span>(records)<span class=\"sc\">}<\/span><span class=\"ss\"> uploads.&quot;<\/span>)<\/span>\n<span id=\"cb4-33\"><a href=\"#cb4-33\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-34\"><a href=\"#cb4-34\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    cursor.close()<\/span>\n<span id=\"cb4-35\"><a href=\"#cb4-35\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    connection.close()<\/span>\n<span id=\"cb4-36\"><a href=\"#cb4-36\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><\/span>\n<span id=\"cb4-37\"><a href=\"#cb4-37\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"cf\">except<\/span> (<span class=\"pp\">Exception<\/span>, psycopg2.Error) <span class=\"im\">as<\/span> error:<\/span>\n<span id=\"cb4-38\"><a href=\"#cb4-38\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>    <span class=\"bu\">print<\/span>(<span class=\"st\">&quot;Error while fetching data from PostgreSQL&quot;<\/span>, error)<\/span><\/code><\/pre><\/div>\n<p>It feels good to finally solve this itch I've had for years.<\/p>","link":{"@attributes":{"href":"track-debian-uploads.html"}},"id":"tag:www.sergiocipriano.com,2025-07-05:posts\/track-debian-uploads.md","published":"2025-07-05T10:28:37-03:00","updated":"2025-07-23T09:02:05-03:00"},{"title":"How I deployed this Website","content":"<h1 id=\"how-i-deployed-this-website\">How I deployed this Website<\/h1>\n<p>I will describe the step-by-step process I followed to make this\nstatic website accessible on the Internet.<\/p>\n<h2 id=\"dns\">DNS<\/h2>\n<p>I bought this domain on NameCheap and am using their DNS for now,\nwhere I created these records:<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">Record Type<\/th>\n<th style=\"text-align: center;\">Host<\/th>\n<th style=\"text-align: center;\">Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: center;\">A<\/td>\n<td style=\"text-align: center;\">sergiocipriano.com<\/td>\n<td style=\"text-align: center;\">201.54.0.17<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center;\">CNAME<\/td>\n<td style=\"text-align: center;\">www<\/td>\n<td style=\"text-align: center;\">sergiocipriano.com<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"virtual-machine\">Virtual Machine<\/h2>\n<p>I am using <a href=\"https:\/\/magalu.cloud\/\">Magalu Cloud<\/a> for\nhosting my VM, since employees have free credits.<\/p>\n<p>Besides creating a VM with a public IP, I only needed to set up a\nSecurity Group with the following rules:<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">Type<\/th>\n<th style=\"text-align: center;\">Protocol<\/th>\n<th style=\"text-align: center;\">Port<\/th>\n<th style=\"text-align: center;\">Direction<\/th>\n<th style=\"text-align: center;\">CIDR<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: center;\">IPv4 \/ IPv6<\/td>\n<td style=\"text-align: center;\">TCP<\/td>\n<td style=\"text-align: center;\">80<\/td>\n<td style=\"text-align: center;\">IN<\/td>\n<td style=\"text-align: center;\">Any IP<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center;\">IPv4 \/ IPv6<\/td>\n<td style=\"text-align: center;\">TCP<\/td>\n<td style=\"text-align: center;\">443<\/td>\n<td style=\"text-align: center;\">IN<\/td>\n<td style=\"text-align: center;\">Any IP<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"firewall\">Firewall<\/h2>\n<p>The first thing I did in the VM was enabling <code>ufw<\/code>\n(Uncomplicated Firewall).<\/p>\n<p>Enabling ufw without pre-allowing SSH is a common pitfall and can\nlock you out of your VM. I did this once :)<\/p>\n<p>A safe way to enable ufw:<\/p>\n<pre><code>$ sudo ufw allow OpenSSH      # or: sudo ufw allow 22\/tcp\n$ sudo ufw allow &#39;Nginx Full&#39; # or: sudo ufw allow 80,443\/tcp\n$ sudo ufw enable<\/code><\/pre>\n<p>To check if everything is ok, run:<\/p>\n<pre><code>$ sudo ufw status verbose\nStatus: active\nLogging: on (low)\nDefault: deny (incoming), allow (outgoing), disabled (routed)\nNew profiles: skip\n\nTo                           Action      From\n--                           ------      ----\n22\/tcp (OpenSSH)             ALLOW IN    Anywhere                  \n80,443\/tcp (Nginx Full)      ALLOW IN    Anywhere                  \n22\/tcp (OpenSSH (v6))        ALLOW IN    Anywhere (v6)             \n80,443\/tcp (Nginx Full (v6)) ALLOW IN    Anywhere (v6) <\/code><\/pre>\n<h2 id=\"reverse-proxy\">Reverse Proxy<\/h2>\n<p>I'm using Nginx as the reverse proxy. Since I use the Debian package,\nI just needed to add this file:<\/p>\n<pre><code>\/etc\/nginx\/sites-enabled\/sergiocipriano.com<\/code><\/pre>\n<p>with this content:<\/p>\n<pre><code>server {\n    listen 443 ssl;      # IPv4\n    listen [::]:443 ssl; # IPv6\n\n    server_name sergiocipriano.com www.sergiocipriano.com;\n\n    root \/path\/to\/website\/sergiocipriano.com;\n    index index.html;\n\n    location \/ {\n        try_files $uri \/index.html;\n    }\n}\n\nserver {\n    listen 80;\n    listen [::]:80;\n\n    server_name sergiocipriano.com www.sergiocipriano.com;\n\n    # Redirect all HTTP traffic to HTTPS\n    return 301 https:\/\/$host$request_uri;\n}<\/code><\/pre>\n<h2 id=\"tls\">TLS<\/h2>\n<p>It's really easy to setup TLS thanks to Let's Encrypt:<\/p>\n<pre><code>$ sudo apt-get install certbot python3-certbot-nginx\n$ sudo certbot install --cert-name sergiocipriano.com\nSaving debug log to \/var\/log\/letsencrypt\/letsencrypt.log\nDeploying certificate\nSuccessfully deployed certificate for sergiocipriano.com to \/etc\/nginx\/sites-enabled\/sergiocipriano.com\nSuccessfully deployed certificate for www.sergiocipriano.com to \/etc\/nginx\/sites-enabled\/sergiocipriano.com<\/code><\/pre>\n<p>Certbot will edit the nginx configuration with the path to the\ncertificate.<\/p>\n<h2 id=\"http-security-headers\">HTTP Security Headers<\/h2>\n<p>I decided to use wapiti, which is a web application vulnerability\nscanner, and the report found this problems:<\/p>\n<ol type=\"1\">\n<li>CSP is not set<\/li>\n<li>X-Frame-Options is not set<\/li>\n<li>X-XSS-Protection is not set<\/li>\n<li>X-Content-Type-Options is not set<\/li>\n<li>Strict-Transport-Security is not set<\/li>\n<\/ol>\n<p>I'll explain one by one:<\/p>\n<ol type=\"1\">\n<li>The Content-Security-Policy header prevents XSS and data injection\nby restricting sources of scripts, images, styles, etc.<\/li>\n<li>The X-Frame-Options header prevents a website from being embedded in\niframes (clickjacking).<\/li>\n<li>The X-XSS-Protection header is deprecated. It is <a\nhref=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Reference\/Headers\/X-XSS-Protection\">recommended<\/a>\nthat CSP is used instead of XSS filtering.<\/li>\n<li>The X-Content-Type-Options header stops MIME-type sniffing to\nprevent certain attacks.<\/li>\n<li>The Strict-Transport-Security header informs browsers that the host\nshould only be accessed using HTTPS, and that any future attempts to\naccess it using HTTP should automatically be upgraded to HTTPS.\nAdditionally, on future connections to the host, the browser will not\nallow the user to bypass secure connection errors, such as an invalid\ncertificate. HSTS identifies a host by its domain name only.<\/li>\n<\/ol>\n<p>I added this security headers inside the HTTPS and HTTP server block,\noutside the location block, so they apply globally to all responses.\nHere's how the Nginx config look like:<\/p>\n<pre><code>add_header Content-Security-Policy &quot;default-src &#39;self&#39;; style-src &#39;self&#39;;&quot; always;\nadd_header X-Frame-Options &quot;DENY&quot; always;\nadd_header X-Content-Type-Options &quot;nosniff&quot; always;\nadd_header Strict-Transport-Security &quot;max-age=31536000; includeSubDomains&quot; always;<\/code><\/pre>\n<p>I added <code>always<\/code> to ensure that nginx sends the header\nregardless of the response code.<\/p>\n<p>To add Content-Security-Policy header I had to move the css to a\nseparate file, because browsers block inline styles under strict CSP\nunless you allow them explicitly. They're considered unsafe inline\nunless you move to a separate file and link it like this:<\/p>\n<pre><code>&lt;link rel=&quot;stylesheet&quot; href=&quot;.\/resources\/header.css&quot;&gt;<\/code><\/pre>","link":{"@attributes":{"href":"blog-setup.html"}},"id":"tag:www.sergiocipriano.com,2025-06-29:posts\/blog-setup.md","published":"2025-06-29T15:57:07-03:00","updated":"2025-08-01T11:50:14-03:00"},{"title":"Why package X is installed in your Debian","content":"<h1 id=\"why-package-x-is-installed-in-your-debian\">Why package X is\ninstalled in your Debian<\/h1>\n<p>When I was looking for alternatives to mount a USB flash drive\nwithout sudo, I came across udisks2. To my surprise, this package was\nalready installed on my machine.<\/p>\n<p>I found these two methods to understand why:<\/p>\n<pre><code>$ apt rdepends udisks2 --installed\nudisks2\nReverse Depends:\n  Depends: gnome-disk-utility (&gt;= 2.7.6)\n  Depends: gvfs-daemons\n  Recommends: fwupd<\/code><\/pre>\n<pre><code>$ aptitude why udisks2\ni   task-gnome-desktop Depends gnome-core                \ni A gnome-core         Depends gnome-disk-utility (&gt;= 46)\ni A gnome-disk-utility Depends udisks2 (&gt;= 2.7.6)<\/code><\/pre>\n<p>The <code>i<\/code> marker means installed packages.<\/p>\n<p>The <code>A<\/code> marker means the package was installed\nautomatically.<\/p>","link":{"@attributes":{"href":"why-pkg-installed.html"}},"id":"tag:www.sergiocipriano.com,2025-06-05:posts\/why-pkg-installed.md","published":"2025-06-05T17:08:32-03:00","updated":"2025-06-09T13:38:54-03:00"},{"title":"Disable sleep on lid close","content":"<h1 id=\"disable-sleep-on-lid-close\">Disable sleep on lid close<\/h1>\n<p>I am using an old laptop in my homelab, but I want to do everything\nfrom my personal computer, with ssh. The default behavior in Debian is\nto suspend when the laptop lid is closed, but it's easy to change that,\njust edit<\/p>\n<pre><code>\/etc\/systemd\/logind.conf<\/code><\/pre>\n<p>and change the line<\/p>\n<pre><code>#HandleLidSwitch=suspend<\/code><\/pre>\n<p>to<\/p>\n<pre><code>HandleLidSwitch=ignore<\/code><\/pre>\n<p>then<\/p>\n<pre><code>$ sudo systemctl restart systemd-logind<\/code><\/pre>\n<p>That's it.<\/p>","link":{"@attributes":{"href":"sleep-lid-close.html"}},"id":"tag:www.sergiocipriano.com,2025-06-04:posts\/sleep-lid-close.md","published":"2025-06-04T11:15:04-03:00","updated":"2025-07-02T22:49:18-03:00"},{"title":"Why this website exists","content":"<h1 id=\"why-this-website-exists\">Why this website exists<\/h1>\n<p>I believe I can learn more by writing.<\/p>\n<p>Besides, I have a terrible memory. This is an attempt to document\nwhat I'm learning so that I can refer to it in the future.<\/p>\n<p>There are also many concepts that I don't fully understand yet, even\nthe ones I use daily. My idea is to write about these things and explain\nhow they work. This will force me to study them.<\/p>\n<p>Lastly, I don't like relying on LinkedIn to share my resume.<\/p>","link":{"@attributes":{"href":"why-blog.html"}},"id":"tag:www.sergiocipriano.com,2025-06-03:posts\/why-blog.md","published":"2025-06-03T23:01:05-03:00","updated":"2025-06-03T23:01:05-03:00"}]}