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,474 @@
<!DOCTYPE html>
<html lang="en" dir="auto">
<head>
<meta name="generator" content="Hugo 0.146.0"><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>AlipourIm journeys</title>
<meta name="description" content="">
<meta name="author" content="Iman Alipour">
<link rel="canonical" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/">
<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" type="application/rss+xml" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/index.xml">
<link rel="alternate" type="application/json" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/index.json">
<link rel="alternate" hreflang="en" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/">
<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="list" 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-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Running my blog on Tor (.onion) and the Clearnet with Hugo &#43; PaperMod
</h2>
</header>
<div class="entry-content">
<p> TL;DR — The site is built once (Hugo project), published twice:
Onion: http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/ via Tor, no TLS/HSTS, bound to 127.0.0.1:3301. Clearnet: https://blog.alipourimjourneys.ir behind Cloudflare, Lets Encrypt cert, Onion-Location header pointing to the onion mirror. 1) Tor hidden service (onion) basics I used Tors v3 onion services and mapped onion port 80 → my local web server on 127.0.0.1:3301.
Install &amp; configure Tor (Debian/Ubuntu):
sudo apt update &amp;&amp; sudo apt install -y tor sudoedit /etc/tor/torrc Add:
...</p>
</div>
<footer class="entry-footer"><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>
</footer>
<a class="entry-link" aria-label="post link to Running my blog on Tor (.onion) and the Clearnet with Hugo &#43; PaperMod" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/tor_clearnet_blog/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Stealth Trojan VPN Behind Cloudflare Guide
</h2>
</header>
<div class="entry-content">
<p>Introduction So you want a VPN that doesnt scream “I am a VPN” to every censor and firewall out there?
Welcome to the world of Trojan over WebSocket &#43; TLS behind Cloudflare.
This guide not only shows you how to set it up but also sprinkles in some debugging magic so you can figure out why things break (and they will break, trust me).
Well anonymise domains and secrets, so substitute with your own:
...</p>
</div>
<footer class="entry-footer"><span title='2025-09-09 11:05:00 +0200 +0200'>September 9, 2025</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</footer>
<a class="entry-link" aria-label="post link to Stealth Trojan VPN Behind Cloudflare Guide" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Augest &#39;25
</h2>
</header>
<div class="entry-content">
<p>This month started with me setting up a deadline for Conext student workshop. I wanted to submit something not only to get the chance to attend a nice conference, but to create a network, meet researchers, and to get a chance to present my work and get feedback on it. I also worked on my code-base, finally making everything work by replacing Jool with clatd for performing CxLAT. This darn thing wasted so much of my time! I did learn a bit along the way, but oh well. Such is life!
...</p>
</div>
<footer class="entry-footer"><span title='2025-08-31 07:49:24 +0000 UTC'>August 31, 2025</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/phd_journey/augest_2025/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</footer>
<a class="entry-link" aria-label="post link to Augest &#39;25" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/phd_journey/augest_2025/"></a>
</article>
<article class="post-entry">
<figure class="entry-cover">
<img loading="lazy" src="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/images/hedgedoc-cover.png" alt="HedgeDoc collaborative editing">
</figure>
<header class="entry-header">
<h2 class="entry-hint-parent">Self-Hosting HedgeDoc with Docker &#43; Nginx &#43; Let&#39;s Encrypt
</h2>
</header>
<div class="entry-content">
<p>HedgeDoc is an open-source collaborative Markdown editor. Think Google Docs for Markdown: multiple people can edit the same note in real-time, with support for diagrams, math, polls, and slide decks. In this post well walk through setting up your own instance on a server, secured with HTTPS.
Prerequisites A Linux server with Docker and Docker Compose A domain name pointing to your server (e.g. notes.alipourimjourneys.ir) Nginx installed for reverse proxying Certbot for Lets Encrypt certificates 1. Create the project directory mkdir ~/hedgedoc &amp;&amp; cd ~/hedgedoc 2. Create .env POSTGRES_PASSWORD=ChangeThisStrongPassword HD_DOMAIN=notes.alipourimjourneys.ir Generate a strong password with:
...</p>
</div>
<footer class="entry-footer"><span title='2025-08-29 00:00:00 +0000 UTC'>August 29, 2025</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</footer>
<a class="entry-link" aria-label="post link to Self-Hosting HedgeDoc with Docker &#43; Nginx &#43; Let&#39;s Encrypt" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/"></a>
</article>
<article class="post-entry">
<figure class="entry-cover">
<img loading="lazy" src="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/images/matrix-cover.png" alt="Matrix, Signal but distributed">
</figure>
<header class="entry-header">
<h2 class="entry-hint-parent">Self-hosting Matrix &#43; Element Call with LiveKit: from zero to working (and the [not so!!] fun debugging along the way)
</h2>
</header>
<div class="entry-content">
<p> TL;DR: The call kept saying “waiting for media” because the browser never opened a WebSocket to LiveKit. The root cause was duplicate Access-Control-Allow-Origin headers on /sfu/get (CORS), which stopped the JWT response. Fixing CORS and ensuring the WS proxy worked (HTTP 101 in logs) solved it.
What Im building A Matrix homeserver (Synapse) at matrix.example.com (replace with your domain). TURN/STUN (coTURN) for NAT traversal. Element Call backed by LiveKit, fronted by rtc.example.com. Nginx (host) as the single reverse proxy for everything. Cloudflare DNS (with rtc.* set to DNS-only, no orange cloud). UFW firewall opened for Matrix federation, TURN, and LiveKit media ports. I used Docker for Synapse, PostgreSQL, LiveKit and the JWT helper. I used host Nginx (not Nginx in Docker) to avoid port binding conflicts on 80/443/8448.
...</p>
</div>
<footer class="entry-footer"><span title='2025-08-26 00:00:00 +0000 UTC'>August 26, 2025</span>&nbsp;·&nbsp;8 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/matrix_setup/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</footer>
<a class="entry-link" aria-label="post link to Self-hosting Matrix &#43; Element Call with LiveKit: from zero to working (and the [not so!!] fun debugging along the way)" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/matrix_setup/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Hello World
</h2>
</header>
<div class="entry-content">
<p>This is a test hello world post just to make sure everything works!
Downloads: Markdown · Signature (.asc) View OpenPGP signature -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEVaKl3oR5K6zGyu4/tYgoUOBMjSoFAmpkbukACgkQtYgoUOBM jSpEQQ//WGvzlIkJyaez/yiM50pAlVusmd8LsNXrAPj97ZjyAiY&#43;8puTLs6Na2t7 SfwQP03lYHajkmNmH1Sq2vCVTnTWcWOc81AUW7o5fAUl47FT2CzqwaimpGCxUhCB IOvJT8CCXtLroLXqHk8bfLc8s6iGTQt0f2iV2D2TzPLHOEeh27JuWXu8FQX&#43;uFYE B3ioZqc4wJyDFaGWO&#43;ZLEOBXPMR837rztabWYhqOkCuKNlZ06zTF6e4O0ZQ4nNVC roZVMsh0voreT700bmzJmN5QJngzX0c/cmlMBXzsyQ8BDlmmAj92atR24a5AQ7vZ dSyHfXs/or3HlAWCDPfyZOMM9y0PVIuX&#43;odMAUq13Ec2gIZvYa6NPAk0fnQrmjYJ NZ13gDdb0I7My0KLSCDpTTajOZIf9ExdM9Ogpp8wix1kZuxNdJ4/ya9PhkOh8wEc 62eMm1khV99Gljg&#43;XbAG6A0KI7nO5TS464/JkU1&#43;d/inWjXmSkocTep9p1H/M&#43;nt 7jvNN/agYJh5HOuiA34zli8v2/GflACgFlE&#43;AcGR7cb9CxicTuzs8K&#43;kLzQBQSep oy8FiFCh8msbfmCmvKANkU3nO27NmHbNu9e40A/vxtPZtM0zJnngb/B&#43;5rhDP4uT 6Q1OmbB4xs7jM&#43;WX1X7pHI2XBDNlAGy8hi4rZnmXqhMe4rVZJVo= =kuAP -----END PGP SIGNATURE----- Verify locally:
torsocks curl -fSLO http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/sources/posts/hello-world.md torsocks curl -fSLO http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/sources/posts/hello-world.md.asc gpg --verify hello-world.md.asc hello-world.md </p>
</div>
<footer class="entry-footer"><span title='2025-08-25 08:53:38 +0000 UTC'>August 25, 2025</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hello-world/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</footer>
<a class="entry-link" aria-label="post link to Hello World" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hello-world/"></a>
</article>
<footer class="page-footer">
<nav class="pagination">
<a class="prev" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/page/3/">
«&nbsp;Prev&nbsp;
</a>
</nav>
</footer>
</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>
<script src="/isso/js/count.min.js" data-isso="/isso" async></script>
<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>
</body>
</html>