<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dmitry Gordin</title>
    <description>The latest articles on Forem by Dmitry Gordin (@gordinmitya).</description>
    <link>https://forem.com/gordinmitya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F655818%2Fb3c5971a-792b-476d-ba21-3c49c38b02be.jpeg</url>
      <title>Forem: Dmitry Gordin</title>
      <link>https://forem.com/gordinmitya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gordinmitya"/>
    <language>en</language>
    <item>
      <title>The minimal setup for OpenVino iGPU</title>
      <dc:creator>Dmitry Gordin</dc:creator>
      <pubDate>Mon, 03 Nov 2025 14:03:22 +0000</pubDate>
      <link>https://forem.com/gordinmitya/the-minimal-setup-for-openvino-igpu-2a4f</link>
      <guid>https://forem.com/gordinmitya/the-minimal-setup-for-openvino-igpu-2a4f</guid>
      <description>&lt;p&gt;Python script to print available execution providers and devices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;onnxruntime&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ort&lt;/span&gt;

&lt;span class="c1"&gt;# pip install onnxruntime-openvino
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_onnx_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_available_providers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Onnx providers: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenVINOExecutionProvider&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;onnxruntime.capi.onnxruntime_pybind11_state&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;get_available_openvino_device_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;available_devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_available_openvino_device_ids&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenVINO devices: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;available_devices&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenVINOExecutionProvider is available but get_available_openvino_device_ids not found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;log_onnx_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access iGPU on host machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install clinfo intel-opencl-icd intel-gpu-tools
sudo usermod -a -G render $LOGNAME
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;re-login and you're good to start using igpu for inference from both openvino or through onnxruntime-openvino.&lt;/p&gt;

&lt;p&gt;For docker:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;requirements.txt&lt;/code&gt; should contain &lt;code&gt;onnxruntime-openvino&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim-bookworm&lt;/span&gt;

&lt;span class="c"&gt;# intel-opencl-icd is required&lt;/span&gt;
&lt;span class="c"&gt;# htop, clinfo and intel-gpu-tools are optional&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DEBIAN_FRONTEND=noninteractive&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; htop clinfo intel-opencl-icd intel-gpu-tools &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt-get clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "main.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/dev/dri:/dev/dri&lt;/span&gt;
    &lt;span class="na"&gt;group_add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;video&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>performance</category>
      <category>python</category>
      <category>tutorial</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Self-hosting nowadays is easier than never before</title>
      <dc:creator>Dmitry Gordin</dc:creator>
      <pubDate>Thu, 19 Jun 2025 12:12:12 +0000</pubDate>
      <link>https://forem.com/gordinmitya/self-hosting-nowadays-is-easier-than-never-before-55ec</link>
      <guid>https://forem.com/gordinmitya/self-hosting-nowadays-is-easier-than-never-before-55ec</guid>
      <description>&lt;p&gt;Cloudflare tunnel allows you to host from any machine without a white static IP address or any port-forwarding settings. E.g., you can tether Wi-Fi from your phone to a "server" PC and happily host anything to the public internet.&lt;/p&gt;

&lt;p&gt;We'll focus on managing multiple services from different docker-compose files for convenience.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cloudflare Setup
&lt;/h3&gt;

&lt;p&gt;First, you need a domain name managed by Cloudflare. Let you figure out this yourself.&lt;/p&gt;

&lt;p&gt;Then go to admin console → Zero Trust → Network → Tunnels → Create tunnel.&lt;br&gt;
No need to install anything — we'll use Docker. Just take the token and save it to a &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In "Public hostnames" you have two possibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a specific domain name,&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;*&lt;/code&gt; star to move managing subdomains to the Caddyfile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then specify where on local machine to forward requests: we'll use &lt;a href="http://proxy:80" rel="noopener noreferrer"&gt;http://proxy:80&lt;/a&gt; as destination - because this is our Caddy's container name in docker compose file.&lt;/p&gt;

&lt;p&gt;When you first create a rule — it'll update DNS settings for you, but later if you manually change something — pay attention if corresponding changes are done in DNS.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Docker Network
&lt;/h3&gt;

&lt;p&gt;To the technical part: we need to create a network that will be available between multiple docker-compose files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker network create tunnel-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Base docker-compose.yml (cloudflared + caddy)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cloudflared&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cloudflare/cloudflared:latest&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;TUNNEL_TOKEN=${TUNNEL_TOKEN}&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tunnel-proxy&lt;/span&gt;

  &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;caddy:latest&lt;/span&gt;
    &lt;span class="c1"&gt;# tunnel is configured to forward requests to http://proxy:80&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;proxy&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./Caddyfile:/etc/caddy/Caddyfile&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;caddy_data:/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;caddy_config:/config&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cloudflared&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tunnel-proxy&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;caddy_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;caddy_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="c1"&gt;# this network is created manually beforehand:&lt;/span&gt;
&lt;span class="c1"&gt;# sudo docker network create tunnel-proxy&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tunnel-proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Caddyfile example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    admin off
    auto_https off
}

# inside tunnel everything is http on port 80
# https is done later by Cloudflare

http://hello.example.net:80 {
    # can serve content right away
    # refer to Caddy documentation for details
    respond "Hello, world!" 200
}

http://container-name.example.net:80 {
    # or reverse proxy to container from another docker-compose.yml
    reverse_proxy container-name:80
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save your token from Cloudflare to &lt;code&gt;.env&lt;/code&gt; file: &lt;code&gt;TUNNEL_TOKEN=abcdefg&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Another docker-compose.yml for your service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;anything&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# must match name in www/Caddyfile&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;container-name&lt;/span&gt;
    &lt;span class="c1"&gt;# here's your service you want to host&lt;/span&gt;
    &lt;span class="c1"&gt;# caddy is just an example&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;caddy:latest&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./Caddyfile:/etc/caddy/Caddyfile&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;caddy_data:/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;caddy_config:/config&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tunnel-proxy&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;caddy_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;caddy_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tunnel-proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>webdev</category>
    </item>
    <item>
      <title>NVIDIA Drivers with Secure Boot on Ubuntu</title>
      <dc:creator>Dmitry Gordin</dc:creator>
      <pubDate>Wed, 15 Jan 2025 10:54:22 +0000</pubDate>
      <link>https://forem.com/gordinmitya/nvidia-drivers-with-secure-boot-on-ubuntu-59h4</link>
      <guid>https://forem.com/gordinmitya/nvidia-drivers-with-secure-boot-on-ubuntu-59h4</guid>
      <description>&lt;p&gt;After enabling Secure Boot in BIOS settings on my PC with Kubuntu, I noticed laggy animations. When checking nvidia-smi, I got this error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Updating apt packages and drivers didn't help. After a day of troubleshooting, here's what worked for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install necessary tools&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; openssl mokutil

&lt;span class="c"&gt;# Create directory for keys&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/lib/shim-signed/mok/

&lt;span class="c"&gt;# Generate the key that will be used to sign drivers&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-newkey&lt;/span&gt; rsa:2048 &lt;span class="nt"&gt;-keyout&lt;/span&gt; /var/lib/shim-signed/mok/MOK.priv &lt;span class="nt"&gt;-outform&lt;/span&gt; DER &lt;span class="nt"&gt;-out&lt;/span&gt; /var/lib/shim-signed/mok/MOK.der &lt;span class="nt"&gt;-days&lt;/span&gt; 36500 &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s2"&gt;"/CN=MyKey4Nvidia/"&lt;/span&gt; &lt;span class="nt"&gt;-nodes&lt;/span&gt;

&lt;span class="c"&gt;# Import generated key&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mokutil &lt;span class="nt"&gt;--import&lt;/span&gt; /var/lib/shim-signed/mok/MOK.der
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you will be prompted to enter a new password, this can be any string (not necessary your user's password). Remember it! You'll need to enter it after reboot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Reinstall NVIDIA drivers&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt purge &lt;span class="s1"&gt;'nvidia*'&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt autoremove
&lt;span class="nb"&gt;sudo &lt;/span&gt;ubuntu-drivers autoinstall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot your system. At the beginning of the boot process, you'll see a countdown for 10 seconds to enter the MOK management menu.&lt;br&gt;
Select "Enroll MOK", press continue, and enter the password you created earlier. After enrollment, select the reboot option.&lt;/p&gt;

&lt;p&gt;That's it! After booting up, you should have working NVIDIA drivers. Verify this with the nvidia-smi command.&lt;/p&gt;

</description>
      <category>ubuntu</category>
      <category>nvidia</category>
      <category>linux</category>
    </item>
    <item>
      <title>Disable Dualsence touchpad on Ubuntu</title>
      <dc:creator>Dmitry Gordin</dc:creator>
      <pubDate>Mon, 27 May 2024 11:59:01 +0000</pubDate>
      <link>https://forem.com/gordinmitya/disable-dualsence-touchpad-on-ubuntu-2j2i</link>
      <guid>https://forem.com/gordinmitya/disable-dualsence-touchpad-on-ubuntu-2j2i</guid>
      <description>&lt;p&gt;Valve's efforts in making the Steam Deck (which runs a Debian-based distro) have enabled hassle-free gaming on Linux machines. I finished Witcher 3 with Sony's DualSense controller and am now playing Helldivers 2. Surprisingly, HD2 even supports &lt;strong&gt;haptic feedback and adaptive triggers&lt;/strong&gt;. I didn't think I would be able to try these features without a PS5.&lt;/p&gt;

&lt;p&gt;However, one little annoying thing was preventing me from fully enjoying the game and spreading managed democracy — the &lt;em&gt;touchpad of the DualSense was interpreted as a mouse&lt;/em&gt;. Anytime I wanted to open the in-game map, it acted as a mouse and changed the control to the keyboard. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sudo nano /etc/X11/xorg.conf.d/30--dualsense-touchpad.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Section "InputClass"
    Identifier "Sony Interactive Entertainment Wireless Controller Touchpad"
    Driver "libinput"
    MatchIsTouchpad "on"
    Option "Ignore" "true"
EndSection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, log out from user or just reboot pc. &lt;br&gt;
Now the DualSense acts exactly the same way as if it were attached to a PS5.&lt;/p&gt;

&lt;p&gt;Credits &lt;a href="https://bbs.archlinux.org/viewtopic.php?id=277941"&gt;archlinux forum&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>ubuntu</category>
      <category>linux</category>
      <category>gaming</category>
    </item>
    <item>
      <title>Hikvision camera configuration via ISAPI</title>
      <dc:creator>Dmitry Gordin</dc:creator>
      <pubDate>Mon, 07 Aug 2023 11:02:08 +0000</pubDate>
      <link>https://forem.com/gordinmitya/hikvision-camera-configuration-via-isapi-11oh</link>
      <guid>https://forem.com/gordinmitya/hikvision-camera-configuration-via-isapi-11oh</guid>
      <description>&lt;p&gt;Hikvision company makes good cameras and terrible documentation for their software.&lt;br&gt;
If you've ended up here, chances are you've tried digging through their "isapi.pdf" file and didn't find much help there.&lt;/p&gt;

&lt;p&gt;First, I'd suggest you get your camera set up via the web interface. Next, grab a reference template of the settings in XML format. Do it by opening in you browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://192.168.1.64/ISAPI/Streaming/channels/1"&gt;http://192.168.1.64/ISAPI/Streaming/channels/1&lt;/a&gt; - for streaming options (resolution, fps, bitrate),&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://192.168.1.64/ISAPI/Image/channels/1"&gt;http://192.168.1.64/ISAPI/Image/channels/1&lt;/a&gt; - for image settings (white balance, WDR, lightning, etc).
You will be asked for camera's login and pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case you have different models of cameras, probably you need to get this templates from all of them, compare, and find common basis.&lt;/p&gt;

&lt;p&gt;To deploy this config to camera simply &lt;code&gt;PUT&lt;/code&gt; this xml text to camera by the same url!&lt;/p&gt;

&lt;p&gt;Sample python code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;requests.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTTPDigestAuth&lt;/span&gt;

&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;camera_password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;stream_xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;StreamingChannel version=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; xmlns=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://www.hikvision.com/ver20/XMLSchema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
    &amp;lt;id&amp;gt;1&amp;lt;/id&amp;gt;
blah blah blah
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://192.168.1.64/ISAPI/Streaming/channels/1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stream_xml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;HTTPDigestAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

&lt;span class="n"&gt;image_xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;ImageChannel xmlns=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://www.hikvision.com/ver20/XMLSchema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; version=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
    &amp;lt;id&amp;gt;1&amp;lt;/id&amp;gt;
    &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;
    &amp;lt;videoInputID&amp;gt;1&amp;lt;/videoInputID&amp;gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://192.168.1.64/ISAPI/Image/channels/1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;image_xml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;HTTPDigestAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get response like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ResponseStatus&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"2.0"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.hikvision.com/ver20/XMLSchema"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;requestURL&amp;gt;&amp;lt;/requestURL&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;statusCode&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/statusCode&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;statusString&amp;gt;&lt;/span&gt;OK&lt;span class="nt"&gt;&amp;lt;/statusString&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;subStatusCode&amp;gt;&lt;/span&gt;ok&lt;span class="nt"&gt;&amp;lt;/subStatusCode&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ResponseStatus&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In more complex case, when you need different configs for each camera model, use: &lt;code&gt;http://192.168.1.64/ISAPI/System/deviceInfo&lt;/code&gt; to find out camera model.&lt;/p&gt;

</description>
      <category>computervision</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
  </channel>
</rss>
