cronyakatsuki.xyz/public/blog/setup-dns-pihole-unbound/index.html
2025-05-10 09:35:02 +02:00

294 lines
26 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="/css/style.css" rel="stylesheet" />
<script defer data-domain="cronyakatsuki.xyz" src="https://plausible.cronyakatsuki.xyz/js/script.js"></script>
<title>
Setup dns with adblock and dot/doh with pi-hole and unbound - Crony Akatsuki
</title>
<meta property="og:title" content="Setup dns with adblock and dot/doh with pi-hole and unbound" />
<meta property="og:description" content="Just another day I seted up my own private dns server that has adblocking ( and other stuff ) using pihole and uses unbound as a resolver. To safelly connect to the dns server I&rsquo;m using DNS over HTTPS for my browser&rsquo;s and HTTPS over TLS for stuffy for my whole desktop and private dns in android ( Android has DoH support but only for google and cloudflare right now). Let&rsquo;s get on to setting everything up" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://cronyakatsuki.xyz/blog/setup-dns-pihole-unbound/" /><meta property="article:section" content="blog" />
<meta property="article:published_time" content="2023-09-27T00:00:00+00:00" />
<meta property="article:modified_time" content="2023-09-27T00:00:00+00:00" /><meta property="og:site_name" content="Crony Akatsuki&#39;s Website" />
</head>
<body>
<header>
<h1>Crony Akatsuki</h1>
<nav>
<span><a href="/">Home</a></span>
<span>|</span>
<span><a href="/about">About</a></span>
<span>|</span>
<span><a href="/blog">Blog</a></span>
<span>|</span>
<span><a href="/services">Services</a></span>
</nav>
</header>
<main>
<div id="content">
<h1>Setup dns with adblock and dot/doh with pi-hole and unbound</h1>
<div id="blog-meta">
<p id="date">27-09-2023</p>
<p>
<span>|</span>
<a href="https://cronyakatsuki.xyz/tags/self-host/">self-host</a> <span>|</span>
<a href="https://cronyakatsuki.xyz/tags/dns/">dns</a> <span>|</span>
<a href="https://cronyakatsuki.xyz/tags/pi-hole/">pi-hole</a> <span>|</span>
<a href="https://cronyakatsuki.xyz/tags/unbound/">unbound</a></p>
<hr>
</div>
<p>Just another day I seted up my own private dns server that has adblocking ( and
other stuff ) using pihole and uses unbound as a resolver. To safelly connect to
the dns server I&rsquo;m using DNS over HTTPS for my browser&rsquo;s and HTTPS over TLS for
stuffy for my whole desktop and private dns in android ( Android has DoH support
but only for google and cloudflare right now). Let&rsquo;s get on to setting
everything up</p>
<!-- raw HTML omitted -->
<h2 id="1-pihole">1. Pihole</h2>
<p>Let&rsquo;s start with setting up pihole. I will be installing it with their script on
a debian system for easier unbound integration ( unbound doesn&rsquo;t have an
official docker container ).</p>
<p>I recommend to read up on the pihole&rsquo;s docs on exactly how to install it since
pihole get&rsquo;s frequent updates.
<a href="https://docs.pi-hole.net/main/basic-install/">DOCS</a></p>
<p>I recommend you to install the admin page for easier managmenet and ability to
change the upstream dns server ( needed for changing it to unbound later on ).
To be able to access the admin page I use an nginx configuration like this one.</p>
<div class="highlight"><pre tabindex="0" style="color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#ca9ee6">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">server_name</span> <span style="color:#a6d189">example.com</span> ;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">location</span> <span style="color:#a6d189">/</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">return</span> <span style="color:#ef9f76">403</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">location</span> <span style="color:#a6d189">/admin</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_pass</span> <span style="color:#a6d189">http://127.0.0.1:8185/admin</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_set_header</span> <span style="color:#a6d189">Host</span> <span style="color:#f2d5cf">$host</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># If you want to log user activity, comment these
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">access_log</span> <span style="color:#a6d189">/dev/null</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">error_log</span> <span style="color:#a6d189">/dev/null</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">listen</span> <span style="color:#a6d189">[::]:443</span> <span style="color:#a6d189">ssl</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">listen</span> <span style="color:#ef9f76">443</span> <span style="color:#a6d189">ssl</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">ssl_certificate</span> <span style="color:#a6d189">/etc/letsencrypt/live/example.com/fullchain.pem</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">ssl_certificate_key</span> <span style="color:#a6d189">/etc/letsencrypt/live/example.com/privkey.pem</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">include</span> <span style="color:#a6d189">/etc/letsencrypt/options-ssl-nginx.conf</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">ssl_dhparam</span> <span style="color:#a6d189">/etc/letsencrypt/ssl-dhparams.pem</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span>}
</span></span><span style="display:flex;"><span><span style="color:#ca9ee6">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">if</span> <span style="color:#a6d189">(</span><span style="color:#f2d5cf">$host</span> = <span style="color:#a6d189">example.com)</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">return</span> <span style="color:#ef9f76">301</span> <span style="color:#a6d189">https://</span><span style="color:#f2d5cf">$host$request_uri</span>;
</span></span><span style="display:flex;"><span> } <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">server_name</span> <span style="color:#a6d189">example.com</span> ;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">listen</span> <span style="color:#ef9f76">80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">listen</span> <span style="color:#a6d189">[::]:80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">return</span> <span style="color:#ef9f76">404</span>; <span style="color:#737994;font-style:italic"># managed by Certbot
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span>}
</span></span></code></pre></div><p>The main point of this config is the <code>/admin</code> location that you need to pass the
lighttpd port to acces the website, you can just do it on your main website
also. Also to make lighttpd work with nginx listening on port 80 you need to
edit the <code>server.port</code> to port you wan&rsquo;t to use in lighttpd config file located
at <code>/etc/lighttpd/lighttpd.conf</code> and then just restart lighttpd</p>
<h2 id="2-unbound">2. Unbound</h2>
<p>For this part I will just link the pi-hole&rsquo;s unbound documentation because it is
the most correct one and updated as things change regulary.
<a href="https://docs.pi-hole.net/guides/dns/unbound/">Pi-hole unbound docs</a></p>
<h2 id="3-dns-over-tls">3. DNS over TLS</h2>
<p>For dns over tls you need to first have a ssl certificate. I recommend on using
certbot to generate one with this command <code>certbot --nginx -d dot.example.com</code>.</p>
<p>Next you will need a reverse proxy, in my case I use nginx. You will need to add
this configuration to your main nginx config located at <code>/etc/nginx/nginx.conf</code>.
<strong>Make sure to add this outside of the http block and change example.com to your
domain</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#ca9ee6">stream</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">log_format</span> <span style="color:#a6d189">basic</span> <span style="color:#a6d189">&#39;</span><span style="color:#f2d5cf">$remote_addr</span> <span style="color:#a6d189">[</span><span style="color:#f2d5cf">$time_local]</span> <span style="color:#f2d5cf">$protocol</span> <span style="color:#f2d5cf">$status</span> <span style="color:#f2d5cf">$bytes_sent</span> <span style="color:#f2d5cf">$bytes_received</span> <span style="color:#f2d5cf">$session_time</span> <span style="color:#f2d5cf">$upstream_addr&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">upstream</span> <span style="color:#a6d189">dns</span>
</span></span><span style="display:flex;"><span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">zone</span> <span style="color:#a6d189">dns</span> <span style="color:#ef9f76">64k</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">server</span> 127.0.0.1:<span style="color:#ef9f76">53</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">listen</span> <span style="color:#ef9f76">853</span> <span style="color:#a6d189">ssl</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">access_log</span> <span style="color:#a6d189">/var/log/nginx/dot-access.log</span> <span style="color:#a6d189">basic</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">error_log</span> <span style="color:#a6d189">/var/log/nginx/dot-error.log</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_certificate</span> <span style="color:#a6d189">/etc/letsencrypt/live/dot.example.com/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_certificate_key</span> <span style="color:#a6d189">/etc/letsencrypt/live/dot.example.com/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_protocols</span> <span style="color:#a6d189">TLSv1.2</span> <span style="color:#a6d189">TLSv1.3</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_ciphers</span> <span style="color:#a6d189">HIGH:!aNULL:!MD5</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_handshake_timeout</span> <span style="color:#a6d189">10s</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_session_cache</span> <span style="color:#a6d189">shared:SSL:20m</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_session_timeout</span> <span style="color:#a6d189">4h</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_pass</span> <span style="color:#a6d189">dns</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_responses</span> <span style="color:#ef9f76">1</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_timeout</span> <span style="color:#a6d189">1s</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Also make sure to enable port 853, example ufw command is <code>ufw allow 853/tcp</code>.
Then restart nginx, to test if this configuration is working you can use your
android phone by setting the private dns address to <code>dot.example.com</code> and then
visit the website<a href="https://dnsleaktest.com">dnsleaktest</a></p>
<h2 id="4-dns-over-https">4. DNS over HTTPS</h2>
<p>For using dns over https we will be installing additional package called
dnsdinst. On debian systems just run <code>apt install dnsdinst</code>. Next you will need
to setup dnsdinst config and restart it. Make sure to change example.com.</p>
<pre tabindex="0"><code class="language-conf" data-lang="conf">-- dnsdist configuration file, an example can be found in /usr/share/doc/dnsdist/examples/
-- disable security status polling via DNS
setSecurityPollSuffix(&#34;&#34;)
-- fix up possibly badly truncated answers from pdns 2.9.22
-- truncateTC(true)
-- Answer to only clients from this subnet
setACL(&#34;127.0.0.1/8&#34;)
-- Define upstream DNS server (Pi-hole)
newServer({address=&#34;127.0.0.1&#34;, name=&#34;Pi-hole&#34;, checkName=&#34;example.com&#34;, checkInterval=60, mustResolve=true})
-- Create local DOH server listener in DNS over HTTP mode, otherwise the information coming from nginx won&#39;t be processed well
addDOHLocal(&#34;127.0.0.1:5300&#34;, nil, nil, &#34;/dns-query&#34;, { reusePort=true })
</code></pre><p>Next we will need another ssl certificate for the doh domain, for that we will
once again using certbot with this command
<code>certbot --nginx -d doh.example.com</code>after that add this configuratin to nginx
either in sites-available and linking it to sites enabled or in http block in
main nginx configuration.</p>
<div class="highlight"><pre tabindex="0" style="color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#737994;font-style:italic"># Proxy Cache storage - so we can cache the DoH response from the upstream
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span><span style="color:#ca9ee6">proxy_cache_path</span> <span style="color:#a6d189">/var/run/doh_cache</span> <span style="color:#a6d189">levels=1:2</span> <span style="color:#a6d189">keys_zone=doh_cache:10m</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ca9ee6">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">listen</span> <span style="color:#ef9f76">80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">server_name</span> <span style="color:#a6d189">doh.example.com</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">return</span> <span style="color:#ef9f76">301</span> <span style="color:#a6d189">https://doh.example.com/</span><span style="color:#f2d5cf">$request_uri</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"># This virtual server accepts HTTP/2 over HTTPS
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span><span style="color:#ca9ee6">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">listen</span> <span style="color:#ef9f76">443</span> <span style="color:#a6d189">ssl</span> <span style="color:#a6d189">http2</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">server_name</span> <span style="color:#a6d189">doh.example.com</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">access_log</span> <span style="color:#a6d189">/var/log/nginx/doh.access</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">error_log</span> <span style="color:#a6d189">/var/log/nginx/doh.error</span> <span style="color:#a6d189">error</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_certificate</span> <span style="color:#a6d189">/etc/letsencrypt/live/doh.example.com/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_certificate_key</span> <span style="color:#a6d189">/etc/letsencrypt/live/doh.example.com/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># DoH may use GET or POST requests, Cache both
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">proxy_cache_methods</span> <span style="color:#a6d189">GET</span> <span style="color:#a6d189">POST</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># Return 404 to all responses, except for those using our published DoH URI
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">location</span> <span style="color:#a6d189">/</span> {
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">try_files</span> <span style="color:#f2d5cf">$uri</span> <span style="color:#f2d5cf">$uri/</span> =<span style="color:#ef9f76">404</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">ssl_protocols</span> <span style="color:#a6d189">TLSv1.2</span> <span style="color:#a6d189">TLSv1.3</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_ssl_ciphers</span> <span style="color:#a6d189">HIGH:!aNULL:!MD5</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># This is our published DoH URI
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">location</span> <span style="color:#a6d189">/dns-query</span> {
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># Proxy HTTP/1.1, clear the connection header to enable Keep-Alive
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">proxy_http_version</span> <span style="color:#ef9f76">1</span><span style="color:#a6d189">.1</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_set_header</span> <span style="color:#a6d189">Connection</span> <span style="color:#a6d189">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># Enable Cache, and set the cache_key to include the request_body
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">proxy_cache</span> <span style="color:#a6d189">doh_cache</span>;
</span></span><span style="display:flex;"><span> <span style="color:#81c8be">proxy_cache_key</span> <span style="color:#f2d5cf">$scheme$proxy_host$uri$is_args$args$request_body</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># proxy pass to dnsdist
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">proxy_pass</span> <span style="color:#a6d189">http://127.0.0.1:5300</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#737994;font-style:italic"># proxy pass address
</span></span></span><span style="display:flex;"><span><span style="color:#737994;font-style:italic"></span> <span style="color:#81c8be">proxy_set_header</span> <span style="color:#a6d189">X-Forwarded-For</span> <span style="color:#f2d5cf">$proxy_add_x_forwarded_for</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>After restarting nginx with this configuration you can it to your web browser as
a DNS over HTTPS resolver and once again checkout
<a href="https://dnsleaktest.com">dnsleaktest</a> website and check if it is all working.</p>
<p>Hope this has been helpfull and if anybody has any way on how to make this guied
better you can open a pull request or make an issue on the website&rsquo;s
<a href="https://git.cronyakatsuki.xyz/crony/cronyakatsuki.xyz">repo</a>.</p>
</div>
</main>
<footer>
<div id="links">
<span><a href="https://git.cronyakatsuki.xyz">Code</a></span>
<span>|</span>
<span><a href="https://steamcommunity.com/id/CronyAkatsuki/">Steam</a></span>
<span>|</span>
<span><a href="https://osu.ppy.sh/users/18953565">Osu!</a></span>
<span>|</span>
<span><a href="https://anilist.co/user/CronyAkatsuki/">Anilist</a></span>
<span>|</span>
<span><a href="https://trakt.tv/users/cronyakatsuki">Trakt.tv</a></span>
<span>|</span>
<span><a href="https://www.last.fm/user/Crony-Akatsuki">Last.fm</a></span>
<span>|</span>
<span><a href="https://youtube.com/channel/UClFdlNlUipHG5Kit8GbFz5Q">Gaming Channel</a></span>
<span>|</span>
<span><a href="https://uptime.cronyakatsuki.xyz/status/public">Services Status</a></span>
<span>|</span>
<span><a href="https://lemmy.cronyakatsuki.xyz/u/crony">Lemmy</a></span>
<span>|</span>
<span><a href="https://sharkey.cronyakatsuki.xyz/u/crony">Sharkey</a></span>
<span>|</span>
<span><a href="https://plausible.cronyakatsuki.xyz/cronyakatsuki.xyz">Selfhosted Plausible Analytics</a></span>
</div>
<div id="banners">
<a rel="noreferrer" href="/" target="_blank"><img src="/88x31.png"
alt="Me" title="Me" /></a>
<a rel="noreferrer" href="https://kernel.org" target="_blank"><img src="https://cyber.dabamos.de/88x31/linux_powered.gif"
alt="linux kernel" title="Best kernel in the world" /></a>
<a rel="noreferrer" href="https://debian.org" target="_blank"><img src="https://cyber.dabamos.de/88x31/debian.gif"
alt="debian" title="This website run's on debian" /></a>
<a rel="noreferrer" href="https://bitwarden.com" target="_blank"><img src="https://cyber.dabamos.de/88x31/bitwarden.gif"
alt="Bitwarden" title="Bitwarden/Vaultwarden for the win" /></a>
<a rel="noreferrer" target="_blank"><img src="https://cyber.dabamos.de/88x31/free.gif"
alt="foss" title="Foss is the way" /></a>
<a rel="noreferrer" href="https://neovim.io" target="_blank"><img src="/assets/badges/neovim.gif"
alt="Neovim" title="Written in neovim" /></a>
<a rel="noreferrer" href="https://landchad.net" target="_blank"><img src="https://landchad.net/pix/landchad.gif"
alt="LandChad" title="Get A Website!" /></a>
<a rel="noreferrer" href="https://poggerer.xyz" target="_blank"><img src="https://poggerer.xyz/88x31.png"
alt="Tulg" title="Tulg" /></a>
<a rel="noreferrer" href="https://arthurmelton.com" target="_blank"><img src="https://arthurmelton.com/88x31.png"
alt="AMTitan" title="AMTitan" /></a>
<a rel="noreferrer" href="https://aadi.net.in" target="_blank"><img src="https://aadi.net.in/88x31.png"
alt="Aadi" title="Aadi" /></a>
<a rel="noreferrer" href="https://bear.oops.wtf/" target="_blank"><img src="https://bear.oops.wtf/download/88x31.png"
alt="Bear" title="Bear" /></a>
</div>
</footer>
</body>
</html>