<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Blogs | Alexander Kurilo</title>
    <link>https://kurilo.me/en/blog/</link>
      <atom:link href="https://kurilo.me/en/blog/index.xml" rel="self" type="application/rss+xml" />
    <description>Blogs</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en</language><copyright>© Alexander Kurilo. Opinions are my own. All the texts are licensed under CC BY-SA 4.0 unless otherwise noted.</copyright><lastBuildDate>Fri, 26 Dec 2025 00:00:00 +0000</lastBuildDate>
    <image>
      <url>https://kurilo.me/images/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_512x512_fill_box_center_3.png</url>
      <title>Blogs</title>
      <link>https://kurilo.me/en/blog/</link>
    </image>
    
    <item>
      <title>How To Get Back Surround Sound on Linux over HDMI</title>
      <link>https://kurilo.me/en/blog/linux-amd-hdmi-surround/</link>
      <pubDate>Fri, 26 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://kurilo.me/en/blog/linux-amd-hdmi-surround/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;If your system uses pulseaudio, check 
&lt;a href=&#34;https://wiki.archlinux.org/title/PulseAudio/Examples#Disabling_UCM/%22HiFi%22&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this&lt;/a&gt;, if it uses pipewire, do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d ~/.config/wireplumber/wireplumber.conf.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; mkdir -p ~/.config/wireplumber/wireplumber.conf.d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;monitor.alsa.properties = {\n    alsa.use-ucm = false\n}&amp;#34;&lt;/span&gt; &amp;gt; ~/.config/wireplumber/wireplumber.conf.d/10-disable-ucm.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl --user restart wireplumber pipewire pipewire-pulse
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-issue&#34;&gt;The Issue&lt;/h2&gt;
&lt;p&gt;This year, I bought a new laptop on AMD Ryzen 7 8845HS with Radeon 780M Graphics, and I was surprised to find out that the only sound profiles that are available are &amp;ldquo;Play HiFi quality Music&amp;rdquo; and &amp;ldquo;Pro Audio&amp;rdquo; when connected over HDMI. Neither of those used more than 2 channels. On my over a decade old desktop, there were corresponding profiles for surround sound, such as &amp;ldquo;Digital Stereo,&amp;rdquo; &amp;ldquo;Digital Surround 5.1,&amp;rdquo; and &amp;ldquo;Digital Surround 7.1.&amp;rdquo; On the newer system they were missing.&lt;/p&gt;
&lt;p&gt;Brief googling led me to the 
&lt;a href=&#34;https://wiki.archlinux.org/title/PulseAudio/Examples#Disabling_UCM/%22HiFi%22&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;corresponding article in the ArchLinux Wiki&lt;/a&gt;; while the issue description perfectly matched my case, the solution didn&amp;rsquo;t apply: when trying to restart pulseaudio I got an error from systemd that there was no such unit. &amp;ldquo;Well,&amp;rdquo; I thought, &amp;ldquo;pulseaudio was apparently out of fashion.&amp;rdquo; There was something else instead then, but what?&lt;/p&gt;
&lt;p&gt;When trying to find pulseaudio in &lt;code&gt;systemctl --user list-units&lt;/code&gt; output, something with &amp;ldquo;pulse&amp;rdquo; in its name popped up. I googled that &amp;ldquo;pipewire-pulse,&amp;rdquo; and it turned out that pipewire was the new pulseaudio, and it was even compatible with pulseaudio&amp;rsquo;s clients.&lt;/p&gt;
&lt;p&gt;So, the issue was pinpointed, but apparently the fix had to be ported to pipewire/wireplumber. First, I spent about an hour trying to make ChatGPT solve my original problem, but that was hopeless. It spat convincingly looking stuff that seemed to could have been related but I was out of luck. Then I gave up and asked it to translate the very specific thing from arch wiki (pulseaudio config) into a pipewire-specific config. The first attempt was a failure (it tried to configure a module that didn&amp;rsquo;t exist) but then, when I pointed at the hallucination, it facepalmed itself and suggested that it should rather be wireplumber configuration that worked immediately. It&amp;rsquo;s at the top of the page; I hope that if you experience the same issue, you won&amp;rsquo;t spend as much time looking for a solution as I did.&lt;/p&gt;
&lt;h2 id=&#34;credits&#34;&gt;Credits&lt;/h2&gt;
&lt;p&gt;I have also seen 
&lt;a href=&#34;https://blog.karssen.org/2024/10/19/fixing-absence-of-5-1-surround-sound-options-on-an-amd-linux-laptop/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this&lt;/a&gt; article, but removing a package in my case broke other dependecies: on my Arch system, &lt;code&gt;alsa-lib&lt;/code&gt; depended on it, and in turn nearly everything else (Firefox, Thunderbird, gnome-settings-daemon, etc.), so just removing a package can be a solution but apparently not always. Thanks to that post&amp;rsquo;s author, though: his post convinced me that I&amp;rsquo;m on the right track when I was in doubt.&lt;/p&gt;
&lt;p&gt;If you have anything to add, drop a comment below!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My Take on Managing Certbot with Ansible</title>
      <link>https://kurilo.me/en/blog/ansible_certbot_nginx/</link>
      <pubDate>Sat, 09 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://kurilo.me/en/blog/ansible_certbot_nginx/</guid>
      <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;Given there is a server that hosts few personal project, what is the most efficient way to let the projects use https? 
&lt;a href=&#34;https://letsencrypt.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; (further on referred to as &lt;strong&gt;LE&lt;/strong&gt;) is of course the answer; however, deploying 
&lt;a href=&#34;https://certbot.eff.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;certbot&lt;/a&gt; that automates obtaining and renewing TLS certificates appeared not so easy as it might seem at a glance, so I&amp;rsquo;d like to share my experience.&lt;/p&gt;
&lt;h2 id=&#34;the-setup&#34;&gt;The Setup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A virtual machine with Debian 10 (&amp;ldquo;Buster&amp;rdquo;) on board;&lt;/li&gt;
&lt;li&gt;HTTP server: &lt;strong&gt;nginx&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ansible&lt;/strong&gt; is used to maintain the machine and test the changes on a local one before applying them to production.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-first-challenge-picking-challenge&#34;&gt;The First Challenge: Picking Challenge&lt;/h2&gt;
&lt;p&gt;There are 
&lt;a href=&#34;https://letsencrypt.org/docs/challenge-types/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;multiple challenge types that LE supports&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;TLS-ALPN&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just few words about them.&lt;/p&gt;
&lt;h3 id=&#34;http&#34;&gt;HTTP&lt;/h3&gt;
&lt;p&gt;Requires an HTTP server running and responding to the requests designated for the host being verified. Certbot places a file with a random name in a &lt;code&gt;.well-known/acme-challenge&lt;/code&gt; directory, and LE server queries the file. If it finds it and the content of the file is correct, the challenge is passed.&lt;/p&gt;
&lt;h3 id=&#34;dns&#34;&gt;DNS&lt;/h3&gt;
&lt;p&gt;Requires creating a TXT record for &lt;code&gt;_acme-challenge&lt;/code&gt; subdomain of the domain being verified with a random value. Assuming that the domain being verified is &lt;code&gt;example.com&lt;/code&gt;, ACME server will query &lt;code&gt;TXT&lt;/code&gt; record for &lt;code&gt;_acme-challenge.example.com&lt;/code&gt;, and if its content equals to the expected random string, the challenge is passed.&lt;/p&gt;
&lt;h3 id=&#34;tls-alpn&#34;&gt;TLS-ALPN&lt;/h3&gt;
&lt;p&gt;Requires a server that implements ACME TLS ALPN, which likely means &amp;ldquo;a custom piece of software running on port 443 of the host that the domain being verified points to&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;So, TLS-ALPN is not an option: we want nginx to listen to 443, and it likely won&amp;rsquo;t implement the mentioned TLS ALPN in the nearest future. That leaves us to options.&lt;/p&gt;
&lt;p&gt;DNS challenge is really convenient in some cases because it doesn&amp;rsquo;t require any interference with HTTP server configuration. It&amp;rsquo;s also the only option for wildcard certificates and the only decent option if you have more than one server terminating SSL/TLS for your application. However, it requires access to changing DNS records, which is not something you usually want to put to the server where the application is hosted. Also, DNS providers don&amp;rsquo;t always allow to restrict API access to just a single subdomain (of few of them) and a specific record type, which means it would require to keep API token for changing the whole DNS zone on the server where the application runs, which apparently imposes some security risks, so let&amp;rsquo;s explore the only remaining option.
If you know any DNS providers that allow restricting API access with enough granularity to make described challenge secure other than 
&lt;a href=&#34;https://aws.amazon.com/route53/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Amazon Route 53&lt;/a&gt;, please drop a comment. If you&amp;rsquo;re looking for one, check out Route 53.&lt;/p&gt;
&lt;p&gt;HTTP challenge doesn&amp;rsquo;t need anything special: it just requires an HTTP server on the host the domain being verified points to, which we&amp;rsquo;ll have there anyway. Sounds like a win, doesn&amp;rsquo;t it? At a glance, it does. Let&amp;rsquo;s declare this kind of challenge the best fit for our use case and try to use it.&lt;/p&gt;
&lt;h2 id=&#34;the-second-challenge-learning-concepts&#34;&gt;The Second Challenge: Learning Concepts&lt;/h2&gt;
&lt;p&gt;When switching from DNS challenge that I ran on a separate host and then deployed a certificate to the target host, to HTTP challenge that wouldn&amp;rsquo;t require any &amp;ldquo;separate host,&amp;rdquo; I started from my own assumptions, and it took me almost a full day to understand that I got things somewhat wrong and had to start over. Here are main conclusions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you don&amp;rsquo;t want to maintain few configurations for your web server, you&amp;rsquo;ll have to get creative.&lt;/li&gt;
&lt;li&gt;If you want to sign your own CSR, you better drop this idea.&lt;/li&gt;
&lt;li&gt;If you want your certificates where you want them to be, you better drop this idea, embrace certbot&amp;rsquo;s locations, and just symlink to them.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;More details on these points below.&lt;/p&gt;
&lt;h3 id=&#34;the-flow&#34;&gt;The Flow&lt;/h3&gt;
&lt;p&gt;Certbot issues a certificate, saves the configuration it issues it with, and then, when invoked with crontab or another scheduler, traverses these &amp;ldquo;saved configurations,&amp;rdquo; for each of them checks certificate&amp;rsquo;s expiration date, and it&amp;rsquo;s less than 30 days ahead, renews the certificate for another 90 days. So, we only have to run it once to issue the certificate properly, set the crontab (which debian package maintainers already did for you), sit back and relax.&lt;/p&gt;
&lt;p&gt;Now, to the issues.&lt;/p&gt;
&lt;h3 id=&#34;race-condition&#34;&gt;Race Condition&lt;/h3&gt;
&lt;p&gt;This is the only one I expected.&lt;/p&gt;
&lt;p&gt;So, you probably want to configure nginx to serve your website over HTTPS and redirect requests that come over HTTP to HTTPS. So, if you use ansible or any other configuration management tool, you likely have a template where all these things are put together, e.g. in a single file. So, when you try to run a playbook (recipe, whatever it&amp;rsquo;s called), it will just leave you with a broken nginx because it won&amp;rsquo;t start until the certificates are there. However, in order to get certificates, you need a web server that serves files required for the challenge over HTTP. Do you see a circular reference here?&lt;/p&gt;
&lt;p&gt;There are 2 ways I see that can help break this circle:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Until a certificate exists, deploy only HTTP part of the configuration, run nginx, pass the challenge, get the certificate, put the rest of the configuration (for https), reload nginx. That would be the way to go if I were to do it all manually. I didn&amp;rsquo;t want to break the configuration into pieces without a reason induced by the configuration itself, though.&lt;/li&gt;
&lt;li&gt;If there&amp;rsquo;s no certbot&amp;rsquo;s certificate, put a self-signed &amp;ldquo;stub&amp;rdquo; certificate just so that nginx could start, issue a real certificate, replace the stub with a real certificate, reload nginx. This is what I ended up doing. Having a little trick to work around someone&amp;rsquo;s (cough certbot&amp;rsquo;s cough) tricky behavior is (arguably) better than adjusting my processes to play along with that tricky behavior.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;dont-use-your-own-csr&#34;&gt;Don&amp;rsquo;t Use Your Own CSR&lt;/h3&gt;
&lt;p&gt;I totally didn&amp;rsquo;t expect this one.&lt;/p&gt;
&lt;p&gt;As I needed a self-signed certificate at some point, I thought that it would be nice to use the same CSR for both the self-signed certificate and the real one with the only difference that in the former case I sign it myself and in the latter case LE signs it for me when I pass the challenge. While it works in general, there&amp;rsquo;s a huge pitfall nobody warns about. Flow with custom CSRs is considered to be &amp;ldquo;fire and forget.&amp;rdquo; Certbot doesn&amp;rsquo;t want to manage such certificates, so it won&amp;rsquo;t be able to renew it automatically; it only can issue them once; it doesn&amp;rsquo;t create &amp;ldquo;saved configuration&amp;rdquo; for them, &lt;code&gt;certbot certificates&lt;/code&gt; doesn&amp;rsquo;t list them as there&amp;rsquo;s no configuration, so it won&amp;rsquo;t be checked when the scheduler asks certbot to do its job, and they won&amp;rsquo;t be renewed. I neither know why, nor why it&amp;rsquo;s not mentioned anywhere is the docs.&lt;/p&gt;
&lt;p&gt;I only saw this mentioned explicitly once 
&lt;a href=&#34;https://community.letsencrypt.org/t/unable-to-renew-no-certs-found/58876&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;in a thread on LE comminity forum&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;dont-cross-the-path-of-certbot&#34;&gt;Don&amp;rsquo;t Cross The Path of Certbot&lt;/h3&gt;
&lt;p&gt;I thought it would be convenient to pass a filename to certbot and get a certificate in a location I wanted things to be; however, it just doesn&amp;rsquo;t work. Well, it kind of works, but not really. Certbot has convenient options that allow setting file names to write certificates into explicitly; however, it doesn&amp;rsquo;t always respect them and doesn&amp;rsquo;t put them into a renewal configuration. I found 
&lt;a href=&#34;https://community.letsencrypt.org/t/cert-path-chain-path-fullchain-path-seemingly-not-working/105484&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;a similar complaint&lt;/a&gt; on LE community forums which makes me think it doesn&amp;rsquo;t work for other people too, not just for me. The only advice out there was to also override a config directory which I don&amp;rsquo;t want to do because it would break &amp;ldquo;out of the box&amp;rdquo; renewal: I install certbot from a Debian package, and the package maintainer provides also a cron job and a logrotate config that is used instead of a built-in log rotating capability. So, if I overrode config dir, I would have to set my own cron job which uses the same non-default config path and keep rotating logs in mind. Nope, going to avoid that; hence, will have to use the default paths and place symlinks to them in &amp;ldquo;my place.&amp;rdquo; The only thing to remember here is that for predictability, I advise specifying certificate name: it will somewhat guarantee the location within certbot&amp;rsquo;s config dir: real certificates will reside in &lt;code&gt;/etc/letsencrypt/live/CERTNAME&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;will-there-be-code&#34;&gt;Will There Be Code?&lt;/h2&gt;
&lt;p&gt;This journey was less trivial than I expected it to be, so I decided to publish the result as an Ansible role. It likely won&amp;rsquo;t be useful to you as is (I don&amp;rsquo;t have plans to grow, thoroughly test, and maintain it) but there&amp;rsquo;s a chance you&amp;rsquo;ll pick up few ideas from there. Also, when it&amp;rsquo;s published, it&amp;rsquo;s easier for me to reuse it across my own projects, so here it is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&#34;https://github.com/kamazee/ansible-certbot-role&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;https://galaxy.ansible.com/kamazee/certbot&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ansible Galaxy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Ditch Google Authenticator</title>
      <link>https://kurilo.me/en/blog/ditch_google_authenticator/</link>
      <pubDate>Sun, 26 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://kurilo.me/en/blog/ditch_google_authenticator/</guid>
      <description>&lt;p&gt;Google Authenticator is a mobile app that generates 6-digit codes (
&lt;a href=&#34;https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm&#34; title=&#34;Article about Time-based One-time Password in Wikipedia&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;TOTP&lt;/a&gt;) for accessing various services that use multi-factor authentication (such as Google). It&amp;rsquo;s not flawless; let&amp;rsquo;s discuss my points against it.&lt;/p&gt;
&lt;h2 id=&#34;google-authenticator-stores-secrets-in-plain-text&#34;&gt;Google Authenticator stores secrets in plain text&lt;/h2&gt;
&lt;p&gt;Your OTP key is stored in an SQLite database, without any encryption. Well, no application but Google Authenticator itself can normally read it; there&amp;rsquo;s a &amp;ldquo;but&amp;rdquo;, though: one can never know what vendor can do. Also, it the phone is 
&lt;a href=&#34;https://en.wikipedia.org/wiki/Rooting_%28Android%29&#34; title=&#34;What rooting means, on Wikipedia&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;rooted&lt;/a&gt;, the database can be obtained by those who can escalate their privileges. If it&amp;rsquo;s not, a device might be affected by a vulnerability that allows to escalate privileges, such as 
&lt;a href=&#34;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-2215&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;CVE-2019-2215&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;google-authentication-binds-user-to-the-oneandonly-device&#34;&gt;Google Authentication binds user to the OneAndOnly™ device&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s no legal way to make a backup or restore application&amp;rsquo;s state from a backup. So, one has to be prepared to the fact that once their phone is lost, stolen, broken, etc, the ability to generate a one-time password goes away as soon as the phone does. Backup codes, such as ones that Google offers, are the only hope in this case if no alternatives to OTP from Google Authenticator were set. Regaining access to various services that Google Authenticator is used as the second factor to could be tedious: I had collected 15 OTP keys by the time I bought a new phone and started scratching my head what the migration plan was.&lt;/p&gt;
&lt;p&gt;Just in case, 
&lt;a href=&#34;https://www.protectimus.com/blog/google-authenticator-backup/&#34; title=&#34;How to Backup Google Authenticator or Transfer It to a New Phone&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;here&lt;/a&gt; is a decent article on how to back up Google Authenticator. Spoiler alert: it spreads hopelessness because the chances are that by the time you read this, all the things has already gone wrong, and there&amp;rsquo;s virtually no way to fix them. Well, almost: good for you if you use Android and have enough skills to root the phone and use adb to get SQLite out of it. If not, pulling hairs out seems to be the only option, unfortunately.&lt;/p&gt;
&lt;h2 id=&#34;so-what-do-i-do&#34;&gt;So, what do I do?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pay attention to the options for the second factor
&lt;ul&gt;
&lt;li&gt;Treat backup codes as you treat passwords&lt;/li&gt;
&lt;li&gt;Remember that SMS is 
&lt;a href=&#34;https://www.kaspersky.com/blog/2fa-practical-guide/24219/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;considered unsafe&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Store OTP keys in a password manager. I use 
&lt;a href=&#34;https://keepass.info&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;KeePass&lt;/a&gt; (
&lt;a href=&#34;https://keepassxc.org&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;KeePassXC&lt;/a&gt; for Linux and OSX; 
&lt;a href=&#34;https://play.google.com/store/apps/details?id=keepass2android.keepass2android&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Keepass2Android&lt;/a&gt; for Android); 1Password also 
&lt;a href=&#34;https://support.1password.com/one-time-passwords/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;claims it does support TOTP&lt;/a&gt;.
&lt;ul&gt;
&lt;li&gt;KeePassXC developers 
&lt;a href=&#34;https://keepassxc.org/docs/#faq-security-totp&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;note&lt;/a&gt; that OTP keys are safer when stored separately from passwords, ideally in a separate database with different keys and on different devices. Nevertheless, having OTP keys stored next to passwords is convenient and probably good enough for some cases: it&amp;rsquo;s definitely better than not having multi-factor authentication at all.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;benefit-of-the-doubt&#34;&gt;Benefit of the doubt&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Who the heck is that guy to throw shits at Google,&amp;rdquo; one might say. Part of me thinks the same. Given that most of the mobile phone vendors do not aim to steal customers&amp;rsquo; data in the most shameless way and users avoid rooting their phones, Google Authenticator might be okay. Maybe the need to go over all the services and regain access when the device is lost is intentional! Just use backup codes or other alternative to get in, Luke. And so can be all the bloodiness of the ways of making a copy of Google Authenticator: if there&amp;rsquo;s only a single copy of OTP keys, the odds of leaking them are reduced to a reasonable minimum. However, there are 2 things that make me think different. First, the very existence of 
&lt;a href=&#34;https://www.microsoft.com/en-us/account/authenticator&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Microsoft Authenticator&lt;/a&gt; and 
&lt;a href=&#34;https://authy.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Authy&lt;/a&gt;. Both 
&lt;a href=&#34;https://docs.microsoft.com/en-us/azure/active-directory/user-help/user-help-auth-app-backup-recovery&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;MS Authenticator&lt;/a&gt; and 
&lt;a href=&#34;https://authy.com/features/backup/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Authy&lt;/a&gt; offer backup as a first-class feature, and more than that, the latter also features 
&lt;a href=&#34;https://authy.com/features/multiple-devices/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;ability to use the same OTP key on multiple devices&lt;/a&gt;, for good or ill.&lt;/p&gt;
&lt;p&gt;So, I ditched Google Authenticator. It&amp;rsquo;s up to you to decide what you do; I just hope that now you have enough insight to make an educated move. Just do the right thing before you lose your phone.&lt;/p&gt;
&lt;p&gt;Feel free to leave a comment if you have anything to add.&lt;/p&gt;
&lt;p&gt;P.S.: I found 
&lt;a href=&#34;https://blog.trailofbits.com/2019/06/20/getting-2fa-right-in-2019/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;a great write-up&lt;/a&gt; on making multi-factor authentication right (also, there is a 
&lt;a href=&#34;https://news.ycombinator.com/item?id=20232164&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;discussion of it at Hacker News&lt;/a&gt;, also highly recommended).&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
