Guides on AlipourIm journeyshttp://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/categories/guides/Recent content in Guides on AlipourIm journeysHugo -- 0.146.0enTue, 09 Sep 2025 11:05:00 +0200Stealth Trojan VPN Behind Cloudflare Guidehttp://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/Tue, 09 Sep 2025 11:05:00 +0200http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/<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>We’ll anonymise domains and secrets, so substitute with your own:</p>Introduction

So you want a VPN that doesn’t 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).

We’ll anonymise domains and secrets, so substitute with your own:

  • VPN domain: web.example.com
  • Panel domain: panel.example.com
  • Secret WS path: /stealth-path_abcd1234
  • Password: <PASSWORD>

Architecture at a Glance

Think of it as a disguise party:

  • Trojan = the shy guest (your VPN protocol)
  • Nginx = the bouncer checking IDs (reverse proxy)
  • Cloudflare = the doorman who makes sure nobody sees who’s inside (CDN & proxy)
  • Your fake website = the mask (camouflage page)

Traffic flow:

C l i e n t C l o u d f l a r e ( 4 4 3 ) N g i n x ( 4 4 3 ) T r o j a n ( l o c a l h o s t : 5 4 3 2 1 )

Step 1: Panel Setup (panel.example.com)

  • Bind the 3x-ui panel to localhost (e.g., 127.0.0.1:46309).
  • Choose a funky web base path like /panel-bananas_42/.
  • Proxy it through Nginx with HTTPS + Basic Auth.
  • Test it at https://panel.example.com/panel-bananas_42/.

Pro tip: If you see a blank page → your base path is mismatched or Nginx is eating it. Check logs!


Step 2: Trojan Inbound

In 3x-ui, create a Trojan inbound:

  • Local port: 54321
  • Transport: WebSocket
  • Path: /stealth-path_abcd1234
  • Security: none
  • Password: <PASSWORD>

Step 3: Nginx for VPN Domain (web.example.com)

Your Nginx is the gatekeeper. Sample config:

server {
    listen 443 ssl http2;
    server_name web.example.com;

    ssl_certificate     /etc/letsencrypt/live/web.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/web.example.com/privkey.pem;

    # Fake website at root
    location / {
        root /var/www/html;
        index index.html;
    }

    # Real VPN under secret WS path
    location /stealth-path_abcd1234 {
        proxy_pass http://127.0.0.1:54321;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Step 4: Firewall Rules

Lock things down! Only Cloudflare should reach you:

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw deny 54321/tcp

Step 5: Client Config

Trojan URI:

t r o j a n : / / < P A S S W O R D > @ w e b . e x a m p l e . c o m : 4 4 3 ? t y p e = w s & s e c u r i t y = t l s & h o s t = w e b . e x a m p l e . c o m & p a t h = % 2 F s t e a l t h - p a t h _ a b c d 1 2 3 4 & s n i = w e b . e x a m p l e . c o m # M y S t e a l t h V P N

iOS clients: Shadowrocket, Stash, FoXray
Android clients: v2rayNG, Clash Meta, NekoBox


Debugging Time (a.k.a. “Why the heck doesn’t it work?!”)

Symptom: 520 Unknown Error (Cloudflare)

  • Likely cause: Nginx couldn’t talk to Trojan.
  • Check Nginx error log:
    tail -n 50 /var/log/nginx/error.log
    
  • If you see upstream sent no valid HTTP/1.0 header → you’re mixing HTTPS/HTTP between Nginx and Trojan.

Symptom: 526 Invalid SSL certificate

  • Cloudflare → Nginx cert mismatch.
  • Run:
    openssl s_client -connect web.example.com:443 -servername web.example.com -showcerts
    
  • Make sure CN = web.example.com. If not, fix your cert.

Symptom: Blank page on panel

  • Check if the base path matches exactly (case-sensitive, slash-sensitive).
  • Watch for sneaky trailing spaces!
  • Test locally:
    curl -s -D- http://127.0.0.1:46309/panel-bananas_42/
    

Symptom: Client won’t connect

  • Run a WebSocket test:
    curl -i -k -H "Connection: Upgrade" -H "Upgrade: websocket" https://web.example.com/stealth-path_abcd1234
    
    Expect 101 Switching Protocols. If not, check Nginx config.

Symptom: Censor still blocks you

  • Did you expose another service (like SSH, Matrix, or Minecraft) on the same IP?
    → They’ll find your origin IP. Use a second VPS or lock those ports down.
  • Did you use an obvious path like /ws?
    → Use a random-looking one like /cdn-assets-329df/.

Pro Tips & Fun Tricks

  • Serve a fake blog or portfolio at root so your domain looks legit.
  • Rotate WebSocket paths occasionally.
  • Use Cloudflare Page Rules to disable Rocket Loader & Minify for your VPN domain.
  • Make friends with your Nginx error.log — it will roast you but it tells the truth.

Conclusion

By putting Trojan behind Cloudflare, you’ve given your VPN a shiny new disguise:

  • Looks like normal HTTPS.
  • Hides your origin IP.
  • Forces censors into a tough choice: block Cloudflare (and half the web) or let you pass.

Congrats — you’ve built a VPN with both style and stealth. 🥷

]]>
Self-Hosting HedgeDoc with Docker + Nginx + Let's Encrypthttp://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/Fri, 29 Aug 2025 00:00:00 +0000http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/hedge_doc/<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 we’ll 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 Let’s 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>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 we’ll 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 Let’s 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:

openssl rand -base64 32

3. Create docker-compose.yml

version: "3.9"

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: hedgedoc
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: hedgedoc
    volumes:
      - db:/var/lib/postgresql/data
    restart: unless-stopped

  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:1.10.2
    depends_on:
      - db
    environment:
      CMD_DB_URL: postgres://hedgedoc:${POSTGRES_PASSWORD}@db:5432/hedgedoc
      CMD_DOMAIN: ${HD_DOMAIN}
      CMD_PROTOCOL_USESSL: "true"
      CMD_URL_ADDPORT: "false"
      CMD_PORT: "3000"
      CMD_EMAIL: "true"
      CMD_ALLOW_EMAIL_REGISTER: "false"
    volumes:
      - uploads:/hedgedoc/public/uploads
    ports:
      - "127.0.0.1:3000:3000"
    restart: unless-stopped

volumes:
  db:
  uploads:

Bring it up:

docker compose up -d

4. Get a Let’s Encrypt certificate

Request a cert with a DNS challenge:

sudo certbot certonly   --manual   --preferred-challenges dns   -d notes.alipourimjourneys.ir   -m you@example.com   --agree-tos --no-eff-email

Add the TXT record certbot asks for, wait for DNS to propagate, then continue.
Certificates will be in:

/etc/letsencrypt/live/notes.alipourimjourneys.ir/

5. Configure Nginx

Create /etc/nginx/sites-available/notes.alipourimjourneys.ir:

server {
  server_name notes.alipourimjourneys.ir;

  listen 80;
  listen [::]:80;
  return 301 https://$host$request_uri;
}

server {
  server_name notes.alipourimjourneys.ir;

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  ssl_certificate     /etc/letsencrypt/live/notes.alipourimjourneys.ir/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/notes.alipourimjourneys.ir/privkey.pem;

  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

Enable the config and reload Nginx:

sudo ln -s /etc/nginx/sites-available/notes.alipourimjourneys.ir /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

6. Create users

Because we disabled self-registration, create accounts manually:

docker compose exec hedgedoc ./bin/manage_users --add alice@example.com

You’ll be prompted for a password.
To reset a password later:

docker compose exec hedgedoc ./bin/manage_users --reset alice@example.com

7. Done!

Visit https://notes.alipourimjourneys.ir and log in with the user you created. You now have your own collaborative Markdown editor 🎉


Extras:

  • Backups: dump the PostgreSQL database and save the uploads volume.
  • Upgrades: docker pull quay.io/hedgedoc/hedgedoc:latest && docker compose up -d.
  • Integrations: HedgeDoc supports S3/MinIO image storage, GitHub/GitLab/Google login, and more.
]]>