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,17 @@
<!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="index, follow"><title>Guides | AlipourIm journeys</title>
<meta name=keywords content><meta name=description content><meta name=author content="Iman Alipour"><link rel=canonical href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/><link crossorigin=anonymous href=/assets/css/stylesheet.51e3b550fcc0c3f3a10e2d7b70445c6cb21171bed36521d66dc7427208cafbf9.css integrity="sha256-UeO1UPzAw/OhDi17cERcbLIRcb7TZSHWbcdCcgjK+/k=" 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/categories/guides/index.xml><link rel=alternate hreflang=en href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/><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><meta property="og:url" content="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/"><meta property="og:site_name" content="AlipourIm journeys"><meta property="og:title" content="Guides"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta name=twitter:card content="summary"><meta name=twitter:title content="Guides"><meta name=twitter:description content></head><body class=list id=top><script>localStorage.getItem("pref-theme")==="dark"?document.body.classList.add("dark"):localStorage.getItem("pref-theme")==="light"?document.body.classList.remove("dark"):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" 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 1111.21 3 7 7 0 0021 12.79z"/></svg><svg id="sun" 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"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></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><header class=page-header><div class=breadcrumbs><a href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/>Home</a>&nbsp;»&nbsp;<a href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/>Categories</a></div><h1>Guides
<a href=/categories/guides/index.xml title=RSS aria-label=RSS><svg viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" height="23"><path d="M4 11a9 9 0 019 9"/><path d="M4 4a16 16 0 0116 16"/><circle cx="5" cy="19" r="1"/></svg></a></h1></header><article class="post-entry tag-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 + 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 tag-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 + Nginx + Let'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 && 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 + Nginx + Let's Encrypt" href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/></a></article></main><footer class=footer><span>&copy; 2025 <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 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><a href=/index.xml rel=alternate type=application/rss+xml title=RSS class=rss-link><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 019 9"/><path d="M4 4a16 16 0 0116 16"/><circle cx="5" cy="19" r="1"/></svg>
<span>RSS</span>
</a><script>let menu=document.getElementById("menu");menu&&(menu.scrollLeft=localStorage.getItem("menu-scroll-position"),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script><script>var mybutton=document.getElementById("top-link");window.onscroll=function(){document.body.scrollTop>800||document.documentElement.scrollTop>800?(mybutton.style.visibility="visible",mybutton.style.opacity="1"):(mybutton.style.visibility="hidden",mybutton.style.opacity="0")}</script><script>document.getElementById("theme-toggle").addEventListener("click",()=>{document.body.className.includes("dark")?(document.body.classList.remove("dark"),localStorage.setItem("pref-theme","light")):(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))})</script></body></html>

View file

@ -0,0 +1,508 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Guides on AlipourIm journeys</title><link>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/</link><description>Recent content in Guides on AlipourIm journeys</description><generator>Hugo -- 0.146.0</generator><language>en</language><lastBuildDate>Tue, 09 Sep 2025 11:05:00 +0200</lastBuildDate><atom:link href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/index.xml" rel="self" type="application/rss+xml"/><item><title>Stealth Trojan VPN Behind Cloudflare Guide</title><link>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/</link><pubDate>Tue, 09 Sep 2025 11:05:00 +0200</pubDate><guid>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>So you want a VPN that &lt;strong>doesn&amp;rsquo;t scream &amp;ldquo;I am a VPN&amp;rdquo;&lt;/strong> to every censor and firewall out there?&lt;br>
Welcome to the world of &lt;strong>Trojan over WebSocket + TLS behind Cloudflare&lt;/strong>.&lt;/p>
&lt;p>This guide not only shows you how to set it up but also sprinkles in some &lt;strong>debugging magic&lt;/strong> so you can figure out why things break (and they &lt;em>will&lt;/em> break, trust me).&lt;/p>
&lt;p>Well anonymise domains and secrets, so substitute with your own:&lt;/p></description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>So you want a VPN that <strong>doesn&rsquo;t scream &ldquo;I am a VPN&rdquo;</strong> to every censor and firewall out there?<br>
Welcome to the world of <strong>Trojan over WebSocket + TLS behind Cloudflare</strong>.</p>
<p>This guide not only shows you how to set it up but also sprinkles in some <strong>debugging magic</strong> so you can figure out why things break (and they <em>will</em> break, trust me).</p>
<p>Well anonymise domains and secrets, so substitute with your own:</p>
<ul>
<li>VPN domain: <code>web.example.com</code></li>
<li>Panel domain: <code>panel.example.com</code></li>
<li>Secret WS path: <code>/stealth-path_abcd1234</code></li>
<li>Password: <code>&lt;PASSWORD&gt;</code></li>
</ul>
<hr>
<h2 id="architecture-at-a-glance">Architecture at a Glance</h2>
<p>Think of it as a disguise party:</p>
<ul>
<li><strong>Trojan</strong> = the shy guest (your VPN protocol)</li>
<li><strong>Nginx</strong> = the bouncer checking IDs (reverse proxy)</li>
<li><strong>Cloudflare</strong> = the doorman who makes sure nobody sees who&rsquo;s inside (CDN &amp; proxy)</li>
<li><strong>Your fake website</strong> = the mask (camouflage page)</li>
</ul>
<p>Traffic flow:</p>
<div class="goat svg-container ">
<svg
xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 536 25"
>
<g transform='translate(8,16)'>
<text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'></text>
<text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>(</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>3</text>
<text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'>)</text>
<text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'></text>
<text text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'>(</text>
<text text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'>3</text>
<text text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'>)</text>
<text text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'></text>
<text text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'>(</text>
<text text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'>:</text>
<text text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'>5</text>
<text text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'>3</text>
<text text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'>2</text>
<text text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'>1</text>
<text text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'>)</text>
</g>
</svg>
</div>
<hr>
<h2 id="step-1-panel-setup-panelexamplecom">Step 1: Panel Setup (<code>panel.example.com</code>)</h2>
<ul>
<li>Bind the 3x-ui panel to localhost (e.g., <code>127.0.0.1:46309</code>).</li>
<li>Choose a funky <strong>web base path</strong> like <code>/panel-bananas_42/</code>.</li>
<li>Proxy it through Nginx with HTTPS + Basic Auth.</li>
<li>Test it at <code>https://panel.example.com/panel-bananas_42/</code>.</li>
</ul>
<p><strong>Pro tip:</strong> If you see a blank page → your base path is mismatched or Nginx is eating it. Check logs!</p>
<hr>
<h2 id="step-2-trojan-inbound">Step 2: Trojan Inbound</h2>
<p>In 3x-ui, create a Trojan inbound:</p>
<ul>
<li>Local port: <code>54321</code></li>
<li>Transport: WebSocket</li>
<li>Path: <code>/stealth-path_abcd1234</code></li>
<li>Security: none</li>
<li>Password: <code>&lt;PASSWORD&gt;</code></li>
</ul>
<hr>
<h2 id="step-3-nginx-for-vpn-domain-webexamplecom">Step 3: Nginx for VPN Domain (<code>web.example.com</code>)</h2>
<p>Your Nginx is the gatekeeper. Sample config:</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> <span style="color:#ae81ff">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">web.example.com</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/web.example.com/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/web.example.com/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># Fake website at root
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">root</span> <span style="color:#e6db74">/var/www/html</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></span><span style="display:flex;"><span> <span style="color:#75715e"># Real VPN under secret WS path
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/stealth-path_abcd1234</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:54321</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_http_version</span> <span style="color:#ae81ff">1</span><span style="color:#e6db74">.1</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Upgrade</span> $http_upgrade;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Connection</span> <span style="color:#e6db74">&#34;upgrade&#34;</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><hr>
<h2 id="step-4-firewall-rules">Step 4: Firewall Rules</h2>
<p>Lock things down! Only Cloudflare should reach you:</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>ufw allow 22/tcp
</span></span><span style="display:flex;"><span>ufw allow 80/tcp
</span></span><span style="display:flex;"><span>ufw allow 443/tcp
</span></span><span style="display:flex;"><span>ufw deny 54321/tcp
</span></span></code></pre></div><hr>
<h2 id="step-5-client-config">Step 5: Client Config</h2>
<p>Trojan URI:</p>
<div class="goat svg-container ">
<svg
xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 1160 25"
>
<g transform='translate(8,16)'>
<text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'>:</text>
<text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>&lt;</text>
<text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>W</text>
<text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>O</text>
<text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>D</text>
<text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>@</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'>:</text>
<text text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'>3</text>
<text text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'>?</text>
<text text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'>&amp;</text>
<text text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'>&amp;</text>
<text text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'>&amp;</text>
<text text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'>%</text>
<text text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'>2</text>
<text text-anchor='middle' x='712' y='4' fill='currentColor' style='font-size:1em'>F</text>
<text text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='728' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='736' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='744' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='752' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='760' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='768' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='776' y='4' fill='currentColor' style='font-size:1em'>-</text>
<text text-anchor='middle' x='784' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='792' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='800' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='808' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='816' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='824' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='832' y='4' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='840' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='848' y='4' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='856' y='4' fill='currentColor' style='font-size:1em'>1</text>
<text text-anchor='middle' x='864' y='4' fill='currentColor' style='font-size:1em'>2</text>
<text text-anchor='middle' x='872' y='4' fill='currentColor' style='font-size:1em'>3</text>
<text text-anchor='middle' x='880' y='4' fill='currentColor' style='font-size:1em'>4</text>
<text text-anchor='middle' x='888' y='4' fill='currentColor' style='font-size:1em'>&amp;</text>
<text text-anchor='middle' x='896' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='904' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='912' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='920' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='928' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='936' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='944' y='4' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='952' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='960' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='968' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='976' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='984' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='992' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='1000' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='1008' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='1016' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='1024' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='1032' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='1040' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='1048' y='4' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='1056' y='4' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='1064' y='4' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='1072' y='4' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='1080' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='1088' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='1096' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='1104' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='1112' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='1120' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='1128' y='4' fill='currentColor' style='font-size:1em'>V</text>
<text text-anchor='middle' x='1136' y='4' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='1144' y='4' fill='currentColor' style='font-size:1em'>N</text>
</g>
</svg>
</div>
<p>iOS clients: Shadowrocket, Stash, FoXray<br>
Android clients: v2rayNG, Clash Meta, NekoBox</p>
<hr>
<h2 id="debugging-time-aka-why-the-heck-doesnt-it-work">Debugging Time (a.k.a. “Why the heck doesnt it work?!”)</h2>
<h3 id="symptom-520-unknown-error-cloudflare">Symptom: <strong>520 Unknown Error (Cloudflare)</strong></h3>
<ul>
<li>Likely cause: Nginx couldnt talk to Trojan.</li>
<li>Check Nginx error log:
<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>tail -n <span style="color:#ae81ff">50</span> /var/log/nginx/error.log
</span></span></code></pre></div></li>
<li>If you see <code>upstream sent no valid HTTP/1.0 header</code> → youre mixing HTTPS/HTTP between Nginx and Trojan.</li>
</ul>
<hr>
<h3 id="symptom-526-invalid-ssl-certificate">Symptom: <strong>526 Invalid SSL certificate</strong></h3>
<ul>
<li>Cloudflare → Nginx cert mismatch.</li>
<li>Run:
<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>openssl s_client -connect web.example.com:443 -servername web.example.com -showcerts
</span></span></code></pre></div></li>
<li>Make sure CN = <code>web.example.com</code>. If not, fix your cert.</li>
</ul>
<hr>
<h3 id="symptom-blank-page-on-panel">Symptom: <strong>Blank page on panel</strong></h3>
<ul>
<li>Check if the base path matches exactly (case-sensitive, slash-sensitive).</li>
<li>Watch for sneaky trailing spaces!</li>
<li>Test locally:
<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 -s -D- http://127.0.0.1:46309/panel-bananas_42/
</span></span></code></pre></div></li>
</ul>
<hr>
<h3 id="symptom-client-wont-connect">Symptom: <strong>Client wont connect</strong></h3>
<ul>
<li>Run a WebSocket test:
<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 -k -H <span style="color:#e6db74">&#34;Connection: Upgrade&#34;</span> -H <span style="color:#e6db74">&#34;Upgrade: websocket&#34;</span> https://web.example.com/stealth-path_abcd1234
</span></span></code></pre></div>Expect <code>101 Switching Protocols</code>. If not, check Nginx config.</li>
</ul>
<hr>
<h3 id="symptom-censor-still-blocks-you">Symptom: <strong>Censor still blocks you</strong></h3>
<ul>
<li>Did you expose another service (like SSH, Matrix, or Minecraft) on the same IP?<br>
→ Theyll find your origin IP. Use a second VPS or lock those ports down.</li>
<li>Did you use an obvious path like <code>/ws</code>?<br>
→ Use a random-looking one like <code>/cdn-assets-329df/</code>.</li>
</ul>
<hr>
<h2 id="pro-tips--fun-tricks">Pro Tips &amp; Fun Tricks</h2>
<ul>
<li>Serve a fake blog or portfolio at root so your domain looks legit.</li>
<li>Rotate WebSocket paths occasionally.</li>
<li>Use Cloudflare <strong>Page Rules</strong> to disable Rocket Loader &amp; Minify for your VPN domain.</li>
<li>Make friends with your Nginx error.log — it will roast you but it tells the truth.</li>
</ul>
<hr>
<h2 id="conclusion">Conclusion</h2>
<p>By putting Trojan behind Cloudflare, youve given your VPN a shiny new disguise:</p>
<ul>
<li>Looks like normal HTTPS.</li>
<li>Hides your origin IP.</li>
<li>Forces censors into a tough choice: block Cloudflare (and half the web) or let you pass.</li>
</ul>
<p>Congrats — youve built a VPN with both <strong>style</strong> and <strong>stealth</strong>. 🥷</p>
]]></content:encoded></item><item><title>Self-Hosting HedgeDoc with Docker + Nginx + Let's Encrypt</title><link>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/</link><pubDate>Fri, 29 Aug 2025 00:00:00 +0000</pubDate><guid>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/</guid><description>&lt;p>HedgeDoc is an open-source collaborative Markdown editor. Think &lt;em>Google Docs for Markdown&lt;/em>: 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.&lt;/p>
&lt;hr>
&lt;h2 id="prerequisites">Prerequisites&lt;/h2>
&lt;ul>
&lt;li>A Linux server with &lt;strong>Docker&lt;/strong> and &lt;strong>Docker Compose&lt;/strong>&lt;/li>
&lt;li>A domain name pointing to your server (e.g. &lt;code>notes.alipourimjourneys.ir&lt;/code>)&lt;/li>
&lt;li>&lt;strong>Nginx&lt;/strong> installed for reverse proxying&lt;/li>
&lt;li>&lt;strong>Certbot&lt;/strong> for Lets Encrypt certificates&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="1-create-the-project-directory">1. Create the project directory&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>mkdir ~/hedgedoc &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> cd ~/hedgedoc&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;hr>
&lt;h2 id="2-create-env">2. Create &lt;code>.env&lt;/code>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-env" data-lang="env">&lt;span style="display:flex;">&lt;span>POSTGRES_PASSWORD&lt;span style="color:#f92672">=&lt;/span>ChangeThisStrongPassword
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>HD_DOMAIN&lt;span style="color:#f92672">=&lt;/span>notes.alipourimjourneys.ir&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>Generate a strong password with:&lt;/p></description><content:encoded><![CDATA[<p>HedgeDoc is an open-source collaborative Markdown editor. Think <em>Google Docs for Markdown</em>: 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.</p>
<hr>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>A Linux server with <strong>Docker</strong> and <strong>Docker Compose</strong></li>
<li>A domain name pointing to your server (e.g. <code>notes.alipourimjourneys.ir</code>)</li>
<li><strong>Nginx</strong> installed for reverse proxying</li>
<li><strong>Certbot</strong> for Lets Encrypt certificates</li>
</ul>
<hr>
<h2 id="1-create-the-project-directory">1. Create the project directory</h2>
<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>mkdir ~/hedgedoc <span style="color:#f92672">&amp;&amp;</span> cd ~/hedgedoc</span></span></code></pre></div>
<hr>
<h2 id="2-create-env">2. Create <code>.env</code></h2>
<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-env" data-lang="env"><span style="display:flex;"><span>POSTGRES_PASSWORD<span style="color:#f92672">=</span>ChangeThisStrongPassword
</span></span><span style="display:flex;"><span>HD_DOMAIN<span style="color:#f92672">=</span>notes.alipourimjourneys.ir</span></span></code></pre></div>
<p>Generate a strong password with:</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>openssl rand -base64 <span style="color:#ae81ff">32</span></span></span></code></pre></div>
<hr>
<h2 id="3-create-docker-composeyml">3. Create <code>docker-compose.yml</code></h2>
<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-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#34;3.9&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">db</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">image</span>: <span style="color:#ae81ff">postgres:16</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_USER</span>: <span style="color:#ae81ff">hedgedoc</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_PASSWORD</span>: <span style="color:#ae81ff">${POSTGRES_PASSWORD}</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_DB</span>: <span style="color:#ae81ff">hedgedoc</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#ae81ff">db:/var/lib/postgresql/data</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">hedgedoc</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">image</span>: <span style="color:#ae81ff">quay.io/hedgedoc/hedgedoc:1.10.2</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">depends_on</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#ae81ff">db</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_DB_URL</span>: <span style="color:#ae81ff">postgres://hedgedoc:${POSTGRES_PASSWORD}@db:5432/hedgedoc</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_DOMAIN</span>: <span style="color:#ae81ff">${HD_DOMAIN}</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_PROTOCOL_USESSL</span>: <span style="color:#e6db74">&#34;true&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_URL_ADDPORT</span>: <span style="color:#e6db74">&#34;false&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_PORT</span>: <span style="color:#e6db74">&#34;3000&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_EMAIL</span>: <span style="color:#e6db74">&#34;true&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">CMD_ALLOW_EMAIL_REGISTER</span>: <span style="color:#e6db74">&#34;false&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#ae81ff">uploads:/hedgedoc/public/uploads</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span> - <span style="color:#e6db74">&#34;127.0.0.1:3000:3000&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">db</span>:
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">uploads:</span></span></span></code></pre></div>
<p>Bring it up:</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>docker compose up -d</span></span></code></pre></div>
<hr>
<h2 id="4-get-a-lets-encrypt-certificate">4. Get a Lets Encrypt certificate</h2>
<p>Request a cert with a <strong>DNS challenge</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 certbot certonly --manual --preferred-challenges dns -d notes.alipourimjourneys.ir -m you@example.com --agree-tos --no-eff-email</span></span></code></pre></div>
<p>Add the TXT record certbot asks for, wait for DNS to propagate, then continue.<br>
Certificates will be in:</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>/etc/letsencrypt/live/notes.alipourimjourneys.ir/</span></span></code></pre></div>
<hr>
<h2 id="5-configure-nginx">5. Configure Nginx</h2>
<p>Create <code>/etc/nginx/sites-available/notes.alipourimjourneys.ir</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">server_name</span> <span style="color:#e6db74">notes.alipourimjourneys.ir</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#e6db74">[::]:80</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://</span>$host$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:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">notes.alipourimjourneys.ir</span>;
</span></span><span style="display:flex;"><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></span><span style="display:flex;"><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></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/notes.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/notes.alipourimjourneys.ir/privkey.pem</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></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:3000</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Real-IP</span> $remote_addr;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-For</span> $proxy_add_x_forwarded_for;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-Proto</span> <span style="color:#e6db74">https</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_http_version</span> <span style="color:#ae81ff">1</span><span style="color:#e6db74">.1</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Upgrade</span> $http_upgrade;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Connection</span> <span style="color:#e6db74">&#34;upgrade&#34;</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
<p>Enable the config and reload Nginx:</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 -s /etc/nginx/sites-available/notes.alipourimjourneys.ir /etc/nginx/sites-enabled/
</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>
<hr>
<h2 id="6-create-users">6. Create users</h2>
<p>Because we disabled self-registration, create accounts manually:</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>docker compose exec hedgedoc ./bin/manage_users --add alice@example.com</span></span></code></pre></div>
<p>Youll be prompted for a password.<br>
To reset a password later:</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>docker compose exec hedgedoc ./bin/manage_users --reset alice@example.com</span></span></code></pre></div>
<hr>
<h2 id="7-done">7. Done!</h2>
<p>Visit <a href="https://notes.alipourimjourneys.ir">https://notes.alipourimjourneys.ir</a> and log in with the user you created. You now have your own collaborative Markdown editor 🎉</p>
<hr>
<p><strong>Extras:</strong></p>
<ul>
<li>Backups: dump the PostgreSQL database and save the <code>uploads</code> volume.</li>
<li>Upgrades: <code>docker pull quay.io/hedgedoc/hedgedoc:latest &amp;&amp; docker compose up -d</code>.</li>
<li>Integrations: HedgeDoc supports S3/MinIO image storage, GitHub/GitLab/Google login, and more.</li>
</ul>
]]></content:encoded></item></channel></rss>

View file

@ -0,0 +1,2 @@
<!doctype html><html lang=en><head><title>http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/</title>
<link rel=canonical href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/"></head></html>