Initial import of Hugo site to Forgejo

This commit is contained in:
Iman Alipour 2026-07-28 12:47:20 +00:00
commit cb1ba0317f
1259 changed files with 236349 additions and 0 deletions

View file

@ -0,0 +1,793 @@
<!DOCTYPE html>
<html lang="en" dir="auto">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Running my blog on Tor (.onion) and the Clearnet with Hugo &#43; PaperMod | AlipourIm journeys</title>
<meta name="keywords" content="tor, nginx, hugo, papermod, cloudflare, letsencrypt">
<meta name="description" content="How I hosted a Hugo &#43; PaperMod site both as a Tor onion service and a normal HTTPS site behind Cloudflare, with clean configs, dual builds, and a one-command deploy.">
<meta name="author" content="Iman Alipour">
<link rel="canonical" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/tor_clearnet_blog/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.31b150d909186c48d6dbbf653acc2489945fa9ac2c8f8cd3fe8448e89e40fccf.css" integrity="sha256-MbFQ2QkYbEjW279lOswkiZRfqawsj4zT/oRI6J5A/M8=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/apple-touch-icon.png">
<link rel="mask-icon" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="en" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/tor_clearnet_blog/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript><script>
(function () {
window.goatcounter = { endpoint: "/count" };
const s = document.createElement("script");
s.async = true;
s.src = "/js/count.js";
document.head.appendChild(s);
})();
</script>
<script>
(function () {
const GC = "";
const nf = new Intl.NumberFormat();
const SING = "visit";
const PLUR = "visits";
function ready(fn) {
if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(fn, 0);
else document.addEventListener("DOMContentLoaded", fn);
}
function gcPath() {
try {
return window.goatcounter && window.goatcounter.get_data
? window.goatcounter.get_data().p
: location.pathname;
} catch (_) {
return location.pathname;
}
}
async function fetchCount(path, period) {
try {
const q = new URLSearchParams({ t: String(Date.now()) });
if (period) q.set("start", period);
const url = `${GC}/counter/${encodeURIComponent(path)}.json?${q}`;
const r = await fetch(url, { credentials: "omit" });
if (r.status === 404) return 0;
if (!r.ok) throw 0;
const j = await r.json();
const n = Number(String(j.count).replace(/,/g, ""));
return Number.isFinite(n) ? n : 0;
} catch {
return null;
}
}
const labelVisits = (n) =>
n === null ? "—" : `${nf.format(n)} ${n === 1 ? SING : PLUR}`;
ready(async function () {
const post = document.querySelector(".post-single");
if (post) {
const meta = post.querySelector(
".post-header .post-meta, .post-header .entry-meta, .post-meta"
);
const visits = await fetchCount(gcPath());
if (meta) {
let span = meta.querySelector(".post-views");
if (!span) {
span = document.createElement("span");
span.className = "post-views";
meta.appendChild(span);
}
span.textContent = labelVisits(visits ?? 0);
}
}
const cards = document.querySelectorAll("article.post-entry");
await Promise.all(
Array.from(cards).map(async (card) => {
const meta = card.querySelector(".entry-footer, .post-meta");
const link = card.querySelector("a.entry-link, h2 a, .entry-title a");
if (!meta || !link) return;
try {
const u = new URL(link.getAttribute("href"), location.origin);
if (u.origin !== location.origin) return;
let span = meta.querySelector(".post-views");
if (!span) {
span = document.createElement("span");
span.className = "post-views";
meta.appendChild(span);
}
span.textContent = labelVisits((await fetchCount(u.pathname)) ?? 0);
} catch {}
})
);
const uvEl = document.getElementById("gc_site_visitors_week");
if (uvEl) {
const n = await fetchCount("TOTAL", "week");
uvEl.textContent = n === null ? "—" : nf.format(n);
}
});
})();
</script>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/" accesskey="h" title="AlipourIm journeys (Alt + H)">AlipourIm journeys</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)" aria-label="Toggle theme">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
</div>
</div>
<ul id="menu">
<li>
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/" title="Posts">
<span>Posts</span>
</a>
</li>
<li>
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/phd_journey/" title="PhD_journey">
<span>PhD_journey</span>
</a>
</li>
<li>
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/about/" title="About">
<span>About</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<div class="breadcrumbs"><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/">Home</a>&nbsp;»&nbsp;<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/">Posts</a></div>
<h1 class="post-title entry-hint-parent">
Running my blog on Tor (.onion) and the Clearnet with Hugo &#43; PaperMod
</h1>
<div class="post-description">
How I hosted a Hugo &#43; PaperMod site both as a Tor onion service and a normal HTTPS site behind Cloudflare, with clean configs, dual builds, and a one-command deploy.
</div>
<div class="post-meta"><span title='2025-09-19 00:00:00 +0000 UTC'>September 19, 2025</span>&nbsp;·&nbsp;6 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/tor_clearnet_blog/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</div>
</header> <div class="toc">
<details open>
<summary accesskey="c" title="(Alt + C)">
<span class="details">Table of Contents</span>
</summary>
<div class="inner"><ul>
<li>
<a href="#1-tor-hidden-service-onion-basics" aria-label="1) Tor hidden service (onion) basics">1) Tor hidden service (onion) basics</a></li>
<li>
<a href="#2-nginx-for-the-onion-localhost-only" aria-label="2) Nginx for the onion (localhost-only)">2) Nginx for the onion (localhost-only)</a></li>
<li>
<a href="#3-hugo--papermod-setup-and-version-bumps" aria-label="3) Hugo &#43; PaperMod setup (and version bumps)">3) Hugo + PaperMod setup (and version bumps)</a></li>
<li>
<a href="#4-dual-builds-clearnet--onion-and-one-command-deploy" aria-label="4) Dual builds (clearnet &#43; onion) and one-command deploy">4) Dual builds (clearnet + onion) and one-command deploy</a></li>
<li>
<a href="#5-clearnet-behind-cloudflare--lets-encrypt-manual-dns-01" aria-label="5) Clearnet behind Cloudflare &#43; Lets Encrypt (manual DNS-01)">5) Clearnet behind Cloudflare + Lets Encrypt (manual DNS-01)</a></li>
<li>
<a href="#6-troubleshooting-i-ran-into-and-fixes" aria-label="6) Troubleshooting I ran into (and fixes)">6) Troubleshooting I ran into (and fixes)</a></li>
<li>
<a href="#7-not-secure-in-tor-browser" aria-label="7) “Not secure” in Tor Browser?">7) “Not secure” in Tor Browser?</a></li>
<li>
<a href="#8-day-to-day-workflow" aria-label="8) Day-to-day workflow">8) Day-to-day workflow</a></li>
<li>
<a href="#final-notes" aria-label="Final notes">Final notes</a>
</li>
</ul>
</div>
</details>
</div>
<div class="post-content"><blockquote>
<p>TL;DR — The site is built once (Hugo project), <strong>published twice</strong>:</p>
<ul>
<li><strong>Onion</strong>: <code>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/</code> via Tor, no TLS/HSTS, bound to <code>127.0.0.1:3301</code>.</li>
<li><strong>Clearnet</strong>: <code>https://blog.alipourimjourneys.ir</code> behind Cloudflare, Lets Encrypt cert, <code>Onion-Location</code> header pointing to the onion mirror.</li>
</ul></blockquote>
<hr>
<h2 id="1-tor-hidden-service-onion-basics">1) Tor hidden service (onion) basics<a hidden class="anchor" aria-hidden="true" href="#1-tor-hidden-service-onion-basics">#</a></h2>
<p>I used Tors v3 onion services and mapped onion port 80 → my local web server on <code>127.0.0.1:3301</code>.</p>
<p><strong>Install &amp; configure Tor (Debian/Ubuntu):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt update <span style="color:#f92672">&amp;&amp;</span> sudo apt install -y tor
</span></span><span style="display:flex;"><span>sudoedit /etc/tor/torrc
</span></span></code></pre></div><p>Add:</p>
<div class="mermaid">HiddenServiceDir /var/lib/tor/hidden_site/
HiddenServicePort 80 127.0.0.1:3301</div>
<p>Make sure the directory is owned by Tors user and private:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mkdir -p /var/lib/tor/hidden_site
</span></span><span style="display:flex;"><span>sudo chown -R debian-tor:debian-tor /var/lib/tor/hidden_site
</span></span><span style="display:flex;"><span>sudo chmod <span style="color:#ae81ff">700</span> /var/lib/tor/hidden_site
</span></span></code></pre></div><p><strong>Important:</strong> use the right systemd unit:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># validate as the Tor user</span>
</span></span><span style="display:flex;"><span>sudo -u debian-tor tor -f /etc/tor/torrc --verify-config
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># (re)start the real service</span>
</span></span><span style="display:flex;"><span>sudo systemctl enable --now tor@default
</span></span><span style="display:flex;"><span>sudo systemctl restart tor@default
</span></span></code></pre></div><p>Get the onion address:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo cat /var/lib/tor/hidden_site/hostname
</span></span></code></pre></div><p>Quick check (do remote DNS via SOCKS):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -I --socks5-hostname 127.0.0.1:9050 <span style="color:#e6db74">&#34;http://</span><span style="color:#66d9ef">$(</span>sudo cat /var/lib/tor/hidden_site/hostname<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><hr>
<h2 id="2-nginx-for-the-onion-localhost-only">2) Nginx for the onion (localhost-only)<a hidden class="anchor" aria-hidden="true" href="#2-nginx-for-the-onion-localhost-only">#</a></h2>
<p>I keep the onion site strictly on localhost: <strong>no HTTPS, no redirects, no HSTS</strong>. Tor already provides e2e encryption and authenticity.</p>
<p><code>/etc/nginx/sites-available/onion-blog</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-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:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> 127.0.0.1:<span style="color:#ae81ff">3301</span> <span style="color:#e6db74">default_server</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">&lt;your-56-char&gt;.onion</span> 127.0.0.1 <span style="color:#e6db74">localhost</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># keep onion simple; no HSTS/redirects here
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">add_header</span> <span style="color:#e6db74">Referrer-Policy</span> <span style="color:#e6db74">no-referrer</span> <span style="color:#e6db74">always</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">add_header</span> <span style="color:#e6db74">X-Content-Type-Options</span> <span style="color:#e6db74">nosniff</span> <span style="color:#e6db74">always</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">add_header</span> <span style="color:#e6db74">X-Frame-Options</span> <span style="color:#e6db74">SAMEORIGIN</span> <span style="color:#e6db74">always</span>;
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># (optional) strict CSP so nothing leaks to clearnet
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e"># add_header Content-Security-Policy &#34;default-src &#39;self&#39;; img-src &#39;self&#39; data:; style-src &#39;self&#39; &#39;unsafe-inline&#39;; script-src &#39;self&#39;&#34; always;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">root</span> <span style="color:#e6db74">/srv/hugo/mysite/public-onion</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">index</span> <span style="color:#e6db74">index.html</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> { <span style="color:#f92672">try_files</span> $uri $uri/ <span style="color:#e6db74">/index.html</span>; }
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> ~<span style="color:#e6db74">*</span> <span style="color:#e6db74">\.(css|js|ico|png|jpg|jpeg|gif|svg|webp|txt|xml)</span>$ {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">access_log</span> <span style="color:#66d9ef">off</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">add_header</span> <span style="color:#e6db74">Cache-Control</span> <span style="color:#e6db74">&#34;public,</span> <span style="color:#e6db74">max-age=31536000,</span> <span style="color:#e6db74">immutable&#34;</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">try_files</span> $uri =<span style="color:#ae81ff">404</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Enable/reload:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ln -sf /etc/nginx/sites-available/onion-blog /etc/nginx/sites-enabled/onion-blog
</span></span><span style="display:flex;"><span>sudo nginx -t <span style="color:#f92672">&amp;&amp;</span> sudo systemctl reload nginx
</span></span></code></pre></div><blockquote>
<p>Gotcha I hit: I had <strong>two</strong> server blocks on <code>127.0.0.1:3301</code>, which caused 404s via onion. Make sure only the intended vhost listens there (or mark it <code>default_server</code>). Also, if you ever use a regex in <code>server_name</code>, the syntax is <code>server_name ~* \.onion$</code> (note the space after <code>~*</code>).</p></blockquote>
<hr>
<h2 id="3-hugo--papermod-setup-and-version-bumps">3) Hugo + PaperMod setup (and version bumps)<a hidden class="anchor" aria-hidden="true" href="#3-hugo--papermod-setup-and-version-bumps">#</a></h2>
<p>PaperMod now requires <strong>Hugo Extended ≥ 0.146.0</strong>. I installed the extended binary from the official tarball to avoid Snaps sandbox limitations (Snap cant read <code>/srv</code> paths by default).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># install Hugo extended (example)</span>
</span></span><span style="display:flex;"><span>VER<span style="color:#f92672">=</span>0.146.0
</span></span><span style="display:flex;"><span>cd /tmp
</span></span><span style="display:flex;"><span>wget https://github.com/gohugoio/hugo/releases/download/v<span style="color:#e6db74">${</span>VER<span style="color:#e6db74">}</span>/hugo_extended_<span style="color:#e6db74">${</span>VER<span style="color:#e6db74">}</span>_Linux-amd64.tar.gz
</span></span><span style="display:flex;"><span>tar -xzf hugo_extended_<span style="color:#e6db74">${</span>VER<span style="color:#e6db74">}</span>_Linux-amd64.tar.gz
</span></span><span style="display:flex;"><span>sudo mv hugo /usr/local/bin/hugo
</span></span><span style="display:flex;"><span>hugo version <span style="color:#75715e"># should say &#34;extended&#34; and &gt;= 0.146.0</span>
</span></span></code></pre></div><p>Create the site and theme:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mkdir -p /srv/hugo <span style="color:#f92672">&amp;&amp;</span> sudo chown -R <span style="color:#e6db74">&#34;</span>$USER<span style="color:#e6db74">&#34;</span>:<span style="color:#e6db74">&#34;</span>$USER<span style="color:#e6db74">&#34;</span> /srv/hugo
</span></span><span style="display:flex;"><span>cd /srv/hugo
</span></span><span style="display:flex;"><span>hugo new site mysite
</span></span><span style="display:flex;"><span>cd mysite
</span></span><span style="display:flex;"><span>git init
</span></span><span style="display:flex;"><span>git submodule add https://github.com/adityatelange/hugo-PaperMod themes/PaperMod
</span></span></code></pre></div><p><strong>Config updates:</strong> in newer Hugo, <code>paginate</code> is deprecated → use:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#75715e"># config/_default/hugo.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">title</span> = <span style="color:#e6db74">&#34;My Blog&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">theme</span> = <span style="color:#e6db74">&#34;PaperMod&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">enableRobotsTXT</span> = <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">pagination</span>]
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">pagerSize</span> = <span style="color:#ae81ff">10</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">params</span>]
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">defaultTheme</span> = <span style="color:#e6db74">&#34;auto&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">showReadingTime</span> = <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">showPostNavLinks</span> = <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">showBreadCrumbs</span> = <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">showCodeCopyButtons</span> = <span style="color:#66d9ef">true</span>
</span></span></code></pre></div><p>I added per-environment overrides so I can build two outputs with different <code>baseURL</code>s:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#75715e"># config/clearnet/hugo.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">baseURL</span> = <span style="color:#e6db74">&#34;https://blog.alipourimjourneys.ir/&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># config/onion/hugo.toml</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">baseURL</span> = <span style="color:#e6db74">&#34;http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/&#34;</span>
</span></span></code></pre></div><hr>
<h2 id="4-dual-builds-clearnet--onion-and-one-command-deploy">4) Dual builds (clearnet + onion) and one-command deploy<a hidden class="anchor" aria-hidden="true" href="#4-dual-builds-clearnet--onion-and-one-command-deploy">#</a></h2>
<p>I publish the same content twice—once for each base URL and docroot:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd /srv/hugo/mysite
</span></span><span style="display:flex;"><span><span style="color:#75715e"># clearnet build (served over HTTPS)</span>
</span></span><span style="display:flex;"><span>hugo --minify --environment clearnet -d public-clearnet
</span></span><span style="display:flex;"><span><span style="color:#75715e"># onion build (served via Tor)</span>
</span></span><span style="display:flex;"><span>hugo --minify --environment onion -d public-onion
</span></span><span style="display:flex;"><span>sudo systemctl reload nginx
</span></span></code></pre></div><p>Helper script I use:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo tee /usr/local/bin/build-both &gt;/dev/null <span style="color:#e6db74">&lt;&lt;&#39;EOF&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">#!/usr/bin/env bash
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">set -euo pipefail
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">cd /srv/hugo/mysite
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">hugo --minify --environment clearnet -d public-clearnet
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">hugo --minify --environment onion -d public-onion
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">sudo systemctl reload nginx
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">echo &#34;Deployed both at $(date)&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span>sudo chmod +x /usr/local/bin/build-both
</span></span></code></pre></div><p>While editing, I sometimes auto-rebuild on file save:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt install -y entr
</span></span><span style="display:flex;"><span>cd /srv/hugo/mysite
</span></span><span style="display:flex;"><span>find content layouts assets static config -type f | entr -r build-both
</span></span></code></pre></div><hr>
<h2 id="5-clearnet-behind-cloudflare--lets-encrypt-manual-dns-01">5) Clearnet behind Cloudflare + Lets Encrypt (manual DNS-01)<a hidden class="anchor" aria-hidden="true" href="#5-clearnet-behind-cloudflare--lets-encrypt-manual-dns-01">#</a></h2>
<p>Cloudflare is set to <strong>Full (strict)</strong>. I issued a public cert for <code>blog.alipourimjourneys.ir</code> using <strong>manual DNS-01</strong> (no API token):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo snap install --classic certbot
</span></span><span style="display:flex;"><span>sudo certbot certonly --manual --preferred-challenges dns -d blog.alipourimjourneys.ir --agree-tos -m you@example.com --no-eff-email
</span></span></code></pre></div><p>Certbot tells you to add a TXT record <code>_acme-challenge.blog.alipourimjourneys.ir</code>. Add it in Cloudflare DNS, verify with <code>dig</code>, then continue. Cert ends up at:</p>
<div class="mermaid">/etc/letsencrypt/live/blog.alipourimjourneys.ir/fullchain.pem
/etc/letsencrypt/live/blog.alipourimjourneys.ir/privkey.pem</div>
<p>Clearnet Nginx vhosts:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-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:#75715e"># HTTP → HTTPS redirect (optional; CF usually talks HTTPS to origin anyway)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>; <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">blog.alipourimjourneys.ir</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">return</span> <span style="color:#ae81ff">301</span> <span style="color:#e6db74">https://blog.alipourimjourneys.ir</span>$request_uri;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># HTTPS origin (behind Cloudflare)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">443</span> <span style="color:#e6db74">ssl</span> <span style="color:#e6db74">http2</span>; <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:443</span> <span style="color:#e6db74">ssl</span> <span style="color:#e6db74">http2</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">blog.alipourimjourneys.ir</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/blog.alipourimjourneys.ir/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate_key</span> <span style="color:#e6db74">/etc/letsencrypt/live/blog.alipourimjourneys.ir/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># HSTS on clearnet only
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">add_header</span> <span style="color:#e6db74">Strict-Transport-Security</span> <span style="color:#e6db74">&#34;max-age=31536000</span>; <span style="color:#f92672">includeSubDomains</span>; <span style="color:#f92672">preload&#34;</span> <span style="color:#e6db74">always</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># Help Tor Browser discover the onion mirror (safe on clearnet)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">add_header</span> <span style="color:#e6db74">Onion-Location</span> <span style="color:#e6db74">&#34;http://&lt;your-56-char&gt;.onion</span>$request_uri&#34; <span style="color:#e6db74">always</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">root</span> <span style="color:#e6db74">/srv/hugo/mysite/public-clearnet</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">index</span> <span style="color:#e6db74">index.html</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> { <span style="color:#f92672">try_files</span> $uri $uri/ <span style="color:#e6db74">/index.html</span>; }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><blockquote>
<p>Note: dont add HSTS or HTTPS redirects to the <strong>onion</strong> vhost. Keep onion pure HTTP on localhost.</p></blockquote>
<hr>
<h2 id="6-troubleshooting-i-ran-into-and-fixes">6) Troubleshooting I ran into (and fixes)<a hidden class="anchor" aria-hidden="true" href="#6-troubleshooting-i-ran-into-and-fixes">#</a></h2>
<ul>
<li><strong>Tor unit confusion:</strong> <code>tor.service</code> is a tiny master; the real daemon is <code>tor@default</code>. Use that unit and verify config as <code>debian-tor</code>.</li>
<li><strong>Permissions:</strong> <code>HiddenServiceDir</code> must be owned by <code>debian-tor</code> and mode <code>700</code>.</li>
<li><strong>Mapping mismatch:</strong> If <code>HiddenServicePort 80 127.0.0.1:3301</code> is set, visit <code>http://&lt;onion&gt;/</code> (no <code>:3301</code>). If you set <code>HiddenServicePort 3301 127.0.0.1:3301</code>, you must use <code>http://&lt;onion&gt;:3301/</code>.</li>
<li><strong>Curl &amp; .onion:</strong> modern curl refuses <code>.onion</code> unless you use remote DNS via SOCKS:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -I --socks5-hostname 127.0.0.1:9050 <span style="color:#e6db74">&#34;http://&lt;onion&gt;/&#34;</span>
</span></span></code></pre></div></li>
<li><strong>Two Nginx vhosts on the same port:</strong> I had a duplicate server on <code>127.0.0.1:3301</code> pointing somewhere else, which caused onion 404s. Keep only one (or mark one <code>default_server</code>).</li>
<li><strong>Regex in <code>server_name</code>:</strong> if you use it, write <code>server_name ~* \.onion$</code> (space after <code>~*</code>). I fixed an <code>invalid variable name</code> error caused by a missing space.</li>
<li><strong>PaperMod with old Hugo:</strong> upgraded to <strong>extended ≥ 0.146.0</strong>. Also updated <code>paginate</code><code>[pagination].pagerSize</code>.</li>
<li><strong>Snap confinement:</strong> Snaps <code>hugo</code> couldnt read <code>/srv</code> (<code>.../void: permission denied</code>). Switched to the tarball build in <code>/usr/local/bin</code>.</li>
</ul>
<hr>
<h2 id="7-not-secure-in-tor-browser">7) “Not secure” in Tor Browser?<a hidden class="anchor" aria-hidden="true" href="#7-not-secure-in-tor-browser">#</a></h2>
<p>That message can appear because onion uses <strong>HTTP</strong>. Its OK: Tor provides e2e encryption + onion auth. If you enable HTTPS-Only Mode, add an exception for the site. Also ensure the onion build doesnt reference <strong>clearnet</strong> resources (scan the built HTML for <code>http(s)://</code> links that arent your onion).</p>
<hr>
<h2 id="8-day-to-day-workflow">8) Day-to-day workflow<a hidden class="anchor" aria-hidden="true" href="#8-day-to-day-workflow">#</a></h2>
<ul>
<li>Create content:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>hugo new posts/my-first-post.md <span style="color:#75715e"># then set draft: false</span>
</span></span></code></pre></div></li>
<li>Publish both:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>build-both
</span></span></code></pre></div></li>
<li>(Optional) Auto on save:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>find content layouts assets static config -type f | entr -r build-both
</span></span></code></pre></div></li>
<li>(Optional) Git push-to-deploy with a bare repo + post-receive hook that runs <code>build-both</code>.</li>
</ul>
<hr>
<h2 id="final-notes">Final notes<a hidden class="anchor" aria-hidden="true" href="#final-notes">#</a></h2>
<ul>
<li>Clearnet gets <strong>HTTPS + HSTS</strong> and an <code>Onion-Location</code> header.</li>
<li>Onion gets <strong>no HSTS/redirects</strong>, and all assets are self-hosted to avoid mixed content.</li>
<li>Serving both worlds from one Hugo repo is easy: <strong>two builds, two vhosts, one workflow</strong>.</li>
</ul>
<hr>
<div class="signature-block" style="margin-top:1rem">
<p><strong>Downloads:</strong>
<a href="/sources/posts/tor_clearnet_blog.md">Markdown</a> ·
<a href="/sources/posts/tor_clearnet_blog.md.asc">Signature (.asc)</a>
</p><details class="signature">
<summary>View OpenPGP signature</summary>
<pre style="font-size:0.85em; overflow-x:auto; padding:0.75rem;">-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEVaKl3oR5K6zGyu4/tYgoUOBMjSoFAmpkbuQACgkQtYgoUOBM
jSr80hAAqr/XVnG0YNXXgG5FmVK/xBo5VVdYxba&#43;znAc1rCWJuzwHe2Ih0aYsq7d
DMWRkpE9YTfQl/kSYpzlk96KCKv&#43;6lHQXqcPyq&#43;nQTDl/D7iCaOhb8Dog3W/2qN4
6G05f47EoiOJY&#43;G/XgUHKqK75QhJrGUtom71t30alciaEGW2SauewBVTGmD&#43;x4y4
UN8LABLuB/ZE8sInjoTRr28LWVj6XeHMueY9/tpS9Fm3yw3nHnE4Fv77FtTHQiMo
FwGfnomCwVwd5GpaP7LQdtP/a&#43;x4s/bya2keFLW89xgwXolWB6U3y5BLFeVHptQm
slRx0&#43;P27gH&#43;CRtoXKI4kHThbmkmjM9ohJc7kxrkkbzB3ujkrxjC&#43;rZnHXPCdbsZ
TTiwtJ/jLLbX&#43;NfycW9qR6gVxloO35QA90AY7050tOgAsyH&#43;YUn&#43;Rtj2KVj91E0o
VzljG7RAly7yTe&#43;yxzC6OO&#43;iCJvLS6OpLEN5oIG9CmRm5cw/qB2rl8g/Qsru0t7/
OrTnJ8fJqq&#43;XRhBet/eR4zogcSEo7fTMp0pDdapMYkO3Xe5VPQ/3Gu7xr8utoXXZ
N6VbRTRfq2Vnp&#43;A9NshVsaKqXXaXsAL8GivMk37/bqteZ2BWedvzk1PpGf3f9HS8
700JFbZi9uEECoxtnv0uK67i8lkax/gsiTiGdjmx5mzfXfUQXVM=
=QlNw
-----END PGP SIGNATURE-----
</pre>
</details><p><em>Verify locally:</em></p>
<pre style="font-size:0.85em; overflow-x:auto; padding:0.75rem;">torsocks curl -fSLO http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/sources/posts/tor_clearnet_blog.md
torsocks curl -fSLO http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/sources/posts/tor_clearnet_blog.md.asc
gpg --verify tor_clearnet_blog.md.asc tor_clearnet_blog.md
</pre>
</div>
</div>
<footer class="post-footer">
<ul class="post-tags">
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/tor/">Tor</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/nginx/">Nginx</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/hugo/">Hugo</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/papermod/">PaperMod</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/cloudflare/">Cloudflare</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/letsencrypt/">Letsencrypt</a></li>
</ul>
<nav class="paginav">
<a class="prev" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/minecraft_server/">
<span class="title">« Prev</span>
<br>
<span>Dockerizing my Minecraft Server &#43; Geyser: from &#39;no space left&#39; to stable releases</span>
</a>
<a class="next" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/">
<span class="title">Next »</span>
<br>
<span>Stealth Trojan VPN Behind Cloudflare Guide</span>
</a>
</nav>
</footer><div class="comments-switch" style="display:flex;gap:.5rem;margin:.5rem 0 1rem;">
<button id="btn-isso" type="button" aria-pressed="true">Anonymous (Isso)</button>
<button id="btn-giscus" type="button" aria-pressed="false">GitHub (Giscus)</button>
<a href="https://github.com/AlipourIm/blog-comments/discussions/categories/comments" target="_blank" rel="noopener">Open on GitHub ↗</a>
</div>
<div id="panel-giscus" style="display:none">
<section id="giscus-thread"></section>
</div>
<div id="panel-isso">
<section id="isso-thread"
data-isso-id="/posts/tor_clearnet_blog/"
data-title="Running my blog on Tor (.onion) and the Clearnet with Hugo &#43; PaperMod">
<noscript>Javascript needs to be activated to view comments.</noscript>
</section>
<script
src="/isso/js/embed.min.js"
data-isso="/isso/"
data-isso-css="false"
data-isso-lang="en"
data-isso-max-comments-nested="5"
data-isso-sorting="newest"
async>
</script>
<small class="isso-powered" style="display:block;margin:.5rem 0;color:var(--secondary,#888)">
Comments powered by <a href="https://isso-comments.de" target="_blank" rel="noopener">Isso</a>
</small>
</div>
<script>
(function () {
var panelIsso = document.getElementById('panel-isso');
var panelGisc = document.getElementById('panel-giscus');
var issoBtn = document.getElementById('btn-isso');
var giscBtn = document.getElementById('btn-giscus');
var gLoaded = false;
function isDark() {
var pref = localStorage.getItem('pref-theme');
if (pref === 'dark') return true;
if (pref === 'light') return false;
var html = document.documentElement, body = document.body;
if (
(html.classList && html.classList.contains('dark')) ||
(body.classList && body.classList.contains('dark')) ||
html.getAttribute('data-theme') === 'dark' ||
body.getAttribute('data-theme') === 'dark' ||
(html.classList && html.classList.contains('theme-dark')) ||
(body.classList && body.classList.contains('theme-dark'))
) return true;
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
function gTheme(){ return isDark() ? 'dark_dimmed' : 'noborder_light'; }
function loadGiscus() {
if (gLoaded) return;
var s = document.createElement('script');
s.src = 'https://giscus.app/client.js';
s.async = true;
s.crossOrigin = 'anonymous';
s.setAttribute('data-repo','AlipourIm/blog-comments');
s.setAttribute('data-repo-id','R_kgDOQGARyA');
s.setAttribute('data-category','Comments');
s.setAttribute('data-category-id','DIC_kwDOQGARyM4Cw3x-');
s.setAttribute('data-mapping','pathname');
s.setAttribute('data-strict','0');
s.setAttribute('data-reactions-enabled','1');
s.setAttribute('data-emit-metadata','0');
s.setAttribute('data-input-position','bottom');
s.setAttribute('data-lang','en');
s.setAttribute('data-theme', gTheme());
document.getElementById('giscus-thread').appendChild(s);
function reTheme(){
var iframe = document.querySelector('iframe.giscus-frame');
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage(
{ giscus: { setConfig: { theme: gTheme() } } },
'https://giscus.app'
);
}
}
var tbtn = document.getElementById('theme-toggle');
if (tbtn) tbtn.addEventListener('click', function(){ setTimeout(reTheme, 0); });
var mo = new MutationObserver(function(){ reTheme(); });
mo.observe(document.documentElement, { attributes:true, attributeFilter:['class','data-theme'] });
mo.observe(document.body, { attributes:true, attributeFilter:['class','data-theme'] });
gLoaded = true;
}
function show(which) {
var showIsso = which === 'isso';
panelIsso.style.display = showIsso ? 'block' : 'none';
panelGisc.style.display = showIsso ? 'none' : 'block';
if (issoBtn) issoBtn.setAttribute('aria-pressed', showIsso ? 'true' : 'false');
if (giscBtn) giscBtn.setAttribute('aria-pressed', showIsso ? 'false' : 'true');
if (!showIsso) loadGiscus();
}
if (issoBtn) issoBtn.addEventListener('click', function(e){ e.preventDefault(); show('isso'); });
if (giscBtn) giscBtn.addEventListener('click', function(e){ e.preventDefault(); show('giscus'); });
show('isso');
})();
</script>
</article>
</main>
<footer class="footer">
<span>&copy; 2026 <a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/">AlipourIm journeys</a></span> ·
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<div class="site-meta-row" style="display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;">
<a href="/index.xml" rel="alternate" type="application/rss+xml" title="RSS"
class="rss-link" style="display:inline-flex;align-items:center;gap:.35rem;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M4 11a9 9 0 0 1 9 9" />
<path d="M4 4a16 16 0 0 1 16 16" />
<circle cx="5" cy="19" r="1" />
</svg>
<span>RSS</span>
</a>
<span aria-hidden="true">·</span>
<span>Visitors this week: <span id="gc_site_visitors_week"></span></span>
</div>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
<script>
document.querySelectorAll('pre > code').forEach((codeblock) => {
const container = codeblock.parentNode.parentNode;
const copybutton = document.createElement('button');
copybutton.classList.add('copy-code');
copybutton.innerHTML = 'copy';
function copyingDone() {
copybutton.innerHTML = 'copied!';
setTimeout(() => {
copybutton.innerHTML = 'copy';
}, 2000);
}
copybutton.addEventListener('click', (cb) => {
if ('clipboard' in navigator) {
navigator.clipboard.writeText(codeblock.textContent);
copyingDone();
return;
}
const range = document.createRange();
range.selectNodeContents(codeblock);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
try {
document.execCommand('copy');
copyingDone();
} catch (e) { };
selection.removeRange(range);
});
if (container.classList.contains("highlight")) {
container.appendChild(copybutton);
} else if (container.parentNode.firstChild == container) {
} else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
} else {
codeblock.parentNode.appendChild(copybutton);
}
});
</script>
</body>
</html>