SSD Nodes Learn 🎉 VPS $4.99/মাস থেকে
নির্দেশিকা Matt Connorদ্বারা Matt Connor

VPN দিয়ে Docker container route করলে port কেন অদৃশ্য হয়

Gluetun-এর সঙ্গে shared network namespace ব্যবহার করলে port ও service name কেন হারায়, exact error string কী এবং কাজের Docker Compose উদাহরণটি দেখুন।

VPN-এর মাধ্যমে Docker container route করলে port কেন অদৃশ্য হয়ে যায়

Docker container-গুলোকে VPN-এর মাধ্যমে route করতে একটি container-কে tunnel দিন। এরপর network_mode: "service:gluetun" ব্যবহার করে অন্য container-গুলোকে তার network namespace-এর সঙ্গে যুক্ত করুন। এই সংযোগের বিষয়টিই অনেককে অবাক করে। সংযুক্ত container-এর নিজস্ব network আর থাকে না। তাই তার published port এবং Docker service name-ও আর থাকে না। port-গুলো VPN container-এ publish করুন। এরপর অন্য container-গুলো VPN container-এর name ব্যবহার করে অ্যাপটিতে পৌঁছাতে পারবে।

সংযুক্ত container-এ ports: block রেখে দিলে Docker সেটি তৈরি করতেই অস্বীকার করে:

Error response from daemon: conflicting options: port publishing and the container type network mode

এখানে ব্যবহৃত tool হলো Gluetun। এটি এমন একটি container, যা WireGuard বা OpenVPN-এর মাধ্যমে commercial VPN (virtual private network) provider-এর সঙ্গে সংযোগ স্থাপন করে এবং নিজস্ব firewall পরিচালনা করে। August 2026 অনুযায়ী v3.41.3 হলো বর্তমান release। উদাহরণগুলোতে WireGuard-এর সঙ্গে Mullvad ব্যবহার করা হয়েছে। তাই আপনার provider-এর একটি account এবং key প্রয়োজন। আপনি যদি নিজের মালিকানাধীন hardware-এ tunnel terminate করতে চান, তাহলে VPS-এ নিজের WireGuard server চালানো tunnel-এর অপর প্রান্ত তৈরি করে। আর Docker-এ wg-easy এর জন্য একটি web interface প্রদান করে।

network_mode: "service:gluetun" আসলে কী করে

প্রতিটি Docker container সাধারণত নিজস্ব network namespace পায়: নিজস্ব interface, routing table, firewall rule এবং listening socket। service: mode এই ধাপটি বাদ দিয়ে gluetun-এর namespace-এর ভেতরে container চালু করে। একটি namespace মানে একটি IP address। এর ফলে ছয়টি বিষয় পরিবর্তিত হয়।

  • অ্যাপটির নিজস্ব কোনো address থাকে না। এর address হলো gluetun-এর address।
  • অ্যাপটি কোনো Docker network-এর সঙ্গে যুক্ত থাকে না। তাই এর service name কখনো register বা resolve হয় না। অন্য container-গুলোকে gluetun ব্যবহার করতে হবে।
  • একই namespace-এর container-গুলো localhost-এর মাধ্যমে একে অপরের কাছে পৌঁছায়।
  • একই namespace-এর দুটি container একই port-এ listen করতে পারে না। Gluetun documentation-এ বিষয়টি স্পষ্টভাবে বলা হয়েছে: এর কোনো workaround নেই।
  • Capabilities namespace-এর নয়, container-এর অন্তর্ভুক্ত। Tunnel interface তৈরি করার কারণে gluetun-এর কাছে NET_ADMIN এবং /dev/net/tun থাকে। সংযুক্ত container এগুলো inherit করে না।
  • কোনো service একই সঙ্গে network_mode এবং networks সেট করলে Compose সেই file গ্রহণ করে না। gluetun-কে আপনার network-গুলোর সঙ্গে যুক্ত করুন; অ্যাপটি সেই network ব্যবহার করবে।

gluetun restart করলে এর সঙ্গে সংযুক্ত সবকিছুর connection বিচ্ছিন্ন হয়। এটি documented behaviour। Connection ব্যর্থ হলে gluetun container থেকে exit না করে container-এর ভেতরেই VPN process restart করে—এর কারণ এটাই। আপনি নিজে gluetun restart বা recreate করার পরে এর সঙ্গে সংযুক্ত container-গুলোও restart করুন।

কার্যকর compose file

services:
  gluetun:
    image: qmcgaw/gluetun:v3
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      - VPN_SERVICE_PROVIDER=mullvad
      - VPN_TYPE=wireguard
      - SERVER_CITIES=Amsterdam
      - TZ=Europe/Amsterdam
    env_file:
      - ./gluetun.env
    volumes:
      - ./gluetun:/gluetun
    ports:
      - 127.0.0.1:8080:8080/tcp
    restart: unless-stopped

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    network_mode: "service:gluetun"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - WEBUI_PORT=8080
    volumes:
      - ./qbittorrent:/config
      - ./downloads:/downloads
    depends_on:
      gluetun:
        condition: service_healthy
    restart: unless-stopped

:v3 tag হলো v3 series-এর সর্বশেষ stable release। :latest tag master branch-এর শেষ commit নির্দেশ করে। এটি development edge। তাই মঙ্গলবার debug করতে চান না এমন মেশিনে :v3 pin করুন।

WEBUI_PORT=8080-এর মান published port-এর সঙ্গে মিলতে হবে। qBittorrent gluetun-এর namespace-এর ভেতরে bind করে, আর publish rule host-এর traffic সেখানে port 8080-এ পাঠায়। একটি সংখ্যা পরিবর্তন করে অন্যটি অপরিবর্তিত রাখলে port কোনো উত্তর দেবে না। 127.0.0.1:8080:8080 web interface-কে host-এর loopback address-এ সীমাবদ্ধ রাখে। শুধু 8080:8080 ব্যবহার করলে সব interface-এ port publish হয় এবং নিজস্ব firewall rule তৈরি হয়। এভাবেই Docker-এর published port সরাসরি ufw-এর নিয়ম এড়িয়ে যায়

এটি চালু করুন। তারপর নিচের ক্রমে পরীক্ষা করুন:

docker compose up -d
docker compose ps
docker compose logs gluetun | tail -30

docker compose ps-এ gluetun-এর অবস্থা healthy এবং qbittorrent-এর অবস্থা running দেখানো উচিত। এরপর namespace-এর ভেতর থেকে exit address নিশ্চিত করুন। এই পরীক্ষার ফলই পরবর্তী সবকিছু নির্ধারণ করে:

docker run --rm --network=container:gluetun alpine:3.22 sh -c "apk add wget && wget -qO- https://ipinfo.io"

ওই JSON-এর ip field-এ আপনার VPN provider-এর address থাকা উচিত। সেখানে যদি আপনার server-এর নিজস্ব address থাকে, তাহলে app-টি tunnel-এর মধ্যে নেই। সে ক্ষেত্রে নিচের কোনো আচরণই বর্ণনা অনুযায়ী হবে না।

compose ফাইলের বাইরে key রাখুন

gluetun.env-এ credentials থাকে এবং এটি git-এর বাইরে থাকে:

WIREGUARD_PRIVATE_KEY=wOEI9rqqbDwnN8/Bpp22sVz48T71vJ4fYmFWujulwUU=
WIREGUARD_ADDRESSES=10.64.222.21/32

উভয় value আপনার provider-এর account area-তে তৈরি করা WireGuard configuration file থেকে আসে। ফাইলটির mode 600 নির্ধারণ করুন। এতে কী সুরক্ষা পাওয়া যায়, তা স্পষ্টভাবে বুঝুন: key আপনার repository-তে থাকে না, কিন্তু Docker socket-এ পৌঁছাতে পারে এমন যে কেউ docker inspect gluetun চালিয়ে প্রতিটি environment variable দেখতে পারে। আরও শক্তিশালী বিকল্পের জন্য Docker Compose-এ environment file এবং secret দেখুন।

টানেলের বাইরের একটি container কীভাবে টানেলের ভেতরের একটির সঙ্গে যোগাযোগ করে

উভয় দিকেই যোগাযোগ করা যায়, তবে প্রতিটি ক্ষেত্রে আলাদা নাম ব্যবহার করতে হয়। দুটি container-এর একটি shared Docker network প্রয়োজন। এটি gluetun-এর network হতে হবে, কারণ সংযুক্ত container-এর নিজস্ব কোনো network নেই। Docker Compose network কীভাবে সংযুক্ত হয়-এ default আচরণগুলি ব্যাখ্যা করা হয়েছে।

বাইর থেকে ভেতরে যোগাযোগের জন্য gluetun-এর নাম এবং app যে port-এ listen করে সেটি ব্যবহার করুন। একটি reverse proxy container gluetun:8080-এ qBittorrent web interface-এ পৌঁছাতে পারে। এর জন্য কোনো ports: entry প্রয়োজন নেই, কারণ container-to-container traffic Docker network-এর মধ্যেই থাকে এবং কখনো host port ব্যবহার করে না।

ভেতর থেকে বাইরে যোগাযোগের জন্য অন্য container-এর service name ব্যবহার করুন, যেমন postgres:5432। v3.41 থেকে gluetun নিজের namespace-এর ভেতর অন্য container-এর নাম resolve করতে পারে। কোনো নাম resolve না হলে সেই version বা তার পরের version নির্দিষ্ট করুন।

কে gluetun-এর কাছে connection খুলতে পারবে, তা Gluetun-এর firewall নির্ধারণ করে। gluetun-এর নিজস্ব Docker network থেকে আসা traffic অনুমোদিত থাকে। ভিন্ন subnet-এর কোনো client, আপনার LAN-এর কোনো laptop অথবা আলাদা bridge network-এর কোনো container-এর traffic অনুমোদিত হবে না, যতক্ষণ না আপনি সেই subnet উল্লেখ করেন:

FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24

নথিভুক্ত অর্থটি নির্দিষ্ট: comma দিয়ে পৃথক করা subnet-গুলোর client Gluetun এবং তার network stack ভাগ করা container-গুলোতে access করতে পারবে।

Internet থেকে আসা inbound connection আলাদা সমস্যা। কোনো torrent client-এর peer VPN দিক দিয়ে আসে, তাই host-এ port 6881 publish করলেও তাদের জন্য কিছু হয় না। আপনার provider-এর কাছ থেকে একটি forwarded port নিতে হবে এবং সেটি FIREWALL_VPN_INPUT_PORTS-এ উল্লেখ করতে হবে। এই option VPN server দিক থেকে আসা port-গুলো অনুমোদন করে। এই অংশটিই অধিকাংশ Docker Compose দিয়ে তৈরি media stack-এ অসম্পূর্ণ থেকে যায়।

kill switch: tunnel বিচ্ছিন্ন হলে কী ঘটে

ব্যর্থতার সময় এই কাঠামোর জটিলতা সার্থক হয়। সংযুক্ত container-এর দ্বিতীয় কোনো route নেই। মেশিনের বাইরে যাওয়ার একমাত্র পথ হলো যে namespace এটি share করে; তাই tunnel down থাকলে fallback করার কোনো পথ থাকে না। Gluetun firewall-ও বিপরীত দিক থেকে একই নিয়ম কার্যকর করে: outbound traffic tunnel হয়ে অথবা VPN server endpoint-এ যায়, আর অন্য সব traffic drop করা হয়। client reconnect করার সময় plain interface দিয়ে packet leak হওয়ার কোনো সুযোগ থাকে না।

Gluetun নিজের connection পর্যবেক্ষণ করে। প্রতি মিনিটে এটি HEALTH_ICMP_TARGET_IPS-এ থাকা address-গুলোতে ICMP echo (একটি ping) পাঠায়; এগুলোর default হলো 1.1.1.1,8.8.8.8। প্রতি পাঁচ মিনিটে এটি HEALTH_TARGET_ADDRESSES-এ সম্পূর্ণ TCP ও TLS (transport layer security) connection স্থাপন করে; default হলো cloudflare.com:443,github.com:443। এগুলো ব্যর্থ হলে এটি container-এর ভেতরে VPN restart করে এবং log-এ তা লিখে:

WARN [vpn] restarting VPN because it failed to pass the healthcheck: periodic check: dialing: dial tcp4: lookup cloudflare.com: i/o timeout

এই বিষয়টি মনে রেখে সংযুক্ত container-এর log পড়ুন। app-এর ভেতরে connection refused, operation not permitted এবং i/o timeout-এর মতো line dead tunnel-এর পরিণতি, কারণ নয়। Gluetun documentation-এ এটি স্পষ্টভাবে বলা আছে, কারণ অনেকে পরিণতিটি report করে এবং ঘণ্টার পর ঘণ্টা ভুল কারণ অনুসরণ করে।

HEALTH_RESTART_VPN=on হলো default এবং এটি চালু রাখা উচিত। একটি নির্দিষ্ট failure debug করার সময়ই কেবল এটি বন্ধ করুন, কারণ এটি বন্ধ থাকলে dead tunnel dead-ই থেকে যায়।

টানেল চালু হওয়ার আগে স্ট্যাকের শুরু বন্ধ রাখা

ইমেজে একটি Docker healthcheck রয়েছে:

HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=1 CMD /gluetun-entrypoint healthcheck

এই কমান্ডটি gluetun-এর আরেকটি স্বল্পস্থায়ী কপি চালায়। এটি http://127.0.0.1:9999/-এ চলমান gluetun-এর health server-এ query পাঠায়। টানেল সচল থাকলে 200 OK-এর উত্তর পাওয়া যায়। টানেল বিকল থাকলে 500 Internal server error-এর সঙ্গে একটি error string পাওয়া যায়, এবং একবার ব্যর্থ হলেই container-টিকে unhealthy হিসেবে চিহ্নিত করা হয়।

condition: service_healthy এই ফলাফলের জন্য অপেক্ষা করে। সাধারণ depends_on: [gluetun] শুধু container শুরু হওয়া পর্যন্ত অপেক্ষা করে। এটি handshake সম্পন্ন হওয়ার কয়েক সেকেন্ড আগেই ঘটে। ফলে app একটি অচল network নিয়ে শুরু হয় এবং প্রথম connection attempt-এই প্রায়ই ব্যর্থ হয়। Docker Compose-এ healthcheck-এ syntax এবং timing field-গুলো ব্যাখ্যা করা হয়েছে।

একটি সীমাবদ্ধতা অনেকের নজর এড়িয়ে যায়। Compose container তৈরি করার সময় এই condition একবার মূল্যায়ন করে। পরে gluetun unhealthy হয়ে গেলেও এটি app বন্ধ বা পুনরায় শুরু করে না। সেই পরিস্থিতি gluetun-এর অভ্যন্তরীণ auto-healing সামলায়। তাই container নয়, VPN process পুনরায় শুরু করা হয়।

সেটআপে আস্থা রাখার আগে DNS leak পরীক্ষা করুন

DNS (domain name system) হলো এমন leak, যা সঠিক tunnel থাকলেও থেকে যায়। Gluetun namespace-এর ভেতরে নিজস্ব resolver চালায় এবং ডিফল্টভাবে DoT (DNS over TLS) ব্যবহার করে Cloudflare-এ query পাঠায়: DNS_UPSTREAM_RESOLVER_TYPE=dot এবং DNS_UPSTREAM_RESOLVERS=cloudflare। দুটিই অপরিবর্তিত রাখুন। তাহলে আপনার lookup encrypted থাকবে এবং tunnel-এর মধ্য দিয়েই যাবে।

যে setting এটি নষ্ট করে, সেটি হলো DNS_UPSTREAM_PLAIN_ADDRESSES। কোনো name resolve না হলে অনেকে এটি ব্যবহার করেন, যাতে router বা provider-এর resolver উত্তর দিতে পারে। Gluetun documentation-এ এর ক্ষতি স্পষ্টভাবে বলা আছে: সব DNS traffic VPN tunnel-এর মধ্য দিয়ে যাবে না এবং tunnel-এর বাইরে leak হবে। আপনার traffic private থাকবে। কিন্তু কোন hostname-গুলোতে lookup করছেন, সেই তালিকা private থাকবে না। WireGuard tunnel-এ একই ভুলের ব্যাখ্যা আছে WireGuard tunnel-এর মাধ্যমে DNS resolve হওয়া বন্ধ হলে

পরীক্ষার জন্য gluetun-এ HTTPPROXY=on সেট করুন এবং 8888:8888/tcp publish করুন। এরপর browser-কে ওই proxy-তে point করে একটি DNS leak test খুলুন। ফলাফলে আপনার provider বা Cloudflare-এর নাম থাকা উচিত। আপনার home router-এর নাম থাকা উচিত নয়। Gluetun-এর নিজস্ব documentation সতর্ক করে যে কিছু leak test অস্বাভাবিক ফল দেখাতে পারে, কারণ namespace-এর ভেতরের resolver হলো একটি local caching intermediary, শেষ পর্যন্ত উত্তর দেওয়া server নয়। ভুল country অথবা আপনার নিজের ISP-এর resolver দেখা গেলে সেটিকেই প্রকৃত signal হিসেবে ধরুন।

VPN sidecar-এর পাশে Tailscale যোগ করা এবং কোনটি অগ্রাধিকার পায়

Tailscale হলো WireGuard-এর ওপর নির্মিত একটি overlay network, যা নিজের মেশিনে সংযোগ করতে ব্যবহৃত হয়। অনেকে provider VPN-এর পাশাপাশি এটি চালান, যাতে stack-এ প্রশাসনিক প্রবেশপথ বজায় থাকে। একটি কারণের জন্য এই দুইটি সাধারণত একে অপরের সঙ্গে সংঘাতে জড়ায় না। Tailscale-এর documentation অনুযায়ী, এটি একটি overlay network হিসেবে কাজ করে, শুধু Tailscale চলমান device-গুলোর মধ্যে traffic route করে এবং public Internet traffic-এ হস্তক্ষেপ করে না।

তাই উত্তরটি একটি setting-এর ওপর নির্ভর করে।

  • Tailscale নিজস্ব container-এ, default configuration-এ: এটি কখনও app-এর outbound traffic দেখতে পায় না। Gluetun সেই traffic বহন করে। Tailscale gluetun:8080-এ app-এ পৌঁছায়, ঠিক অন্য যেকোনো বাইরের container-এর মতো।
  • network_mode: "service:gluetun" ব্যবহার করে Tailscale-কে gluetun-এর namespace-এ যুক্ত করলে: এর নিজস্ব cap_add of net_admin এবং net_raw প্রয়োজন, কারণ namespace-এর সঙ্গে capabilities স্বয়ংক্রিয়ভাবে পাওয়া যায় না। Default userspace networking mode-এ TS_USERSPACE চালু থাকে। tailscaled কোনো interface তৈরি করে না এবং SOCKS5 বা HTTP proxy হিসেবে কাজ করে। তাই এটি routing পরিবর্তন করতে পারে না। Gluetun আগের মতোই সব traffic বহন করে।
  • একই configuration-এ TS_USERSPACE=false ব্যবহার করলে: tailscaled একটি tunnel device তৈরি করে এবং route install করে। তবে এগুলো শুধু tailnet range 100.64.0.0/10 এবং TS_ROUTES দিয়ে advertise করা subnet route-এর জন্য প্রযোজ্য। Public traffic এখনও gluetun-এর মাধ্যমে বের হয়।
  • উপরোক্ত যেকোনো configuration-এ exit node নির্বাচন করা হলে, sudo tailscale set --exit-node=<exit-node-ip>: Tailscale default route গ্রহণ করে এবং অগ্রাধিকার পায়। এটি gluetun-এর সঙ্গে একত্রে ব্যবহার করবেন না। একটি default route-এর একজন owner থাকা উচিত।

Tailscale tunnel-এর ভেতরে চললে একটি পার্শ্বপ্রতিক্রিয়া দেখা যায়। এর peer-গুলো VPN provider-এর address দেখতে পায়। তাই এটি বেশি ঘন ঘন relay-এ fallback করতে পারে। এমন হলে tailscale status, direct-এর বদলে peer-এর পাশে relay "..." দেখায়। সংযোগ কাজ করে, তবে ধীর হয়। আপনার আসলে শুধু overlay প্রয়োজন হলে, সাধারণ WireGuard এবং Tailscale-এর পার্থক্য দিয়ে শুরু করাই ভালো।

কী ব্যর্থ হয় এবং আপনি যে বার্তাটি দেখবেন

Docker app container তৈরি করতে অস্বীকার করে। Error response from daemon: conflicting options: port publishing and the container type network mode-এর অর্থ হলো সংযুক্ত service-এ এখনও একটি ports: block রয়েছে। সেটি gluetun-এ সরিয়ে দিন।

Compose পুরো file গ্রহণ করতে অস্বীকার করে। কোনো service একই সঙ্গে network_mode এবং networks সেট করতে পারে না। network-গুলো gluetun-এ দিন।

অন্য container app-টির নাম resolve করতে পারে না। curl: (6) Could not resolve host: qbittorrent সঠিক আচরণ, কারণ সংযুক্ত container-টি কোনো network-এ যোগ দেয়নি এবং কোনো name register করেনি। gluetun এবং port ব্যবহার করুন।

দ্বিতীয় সংযুক্ত container start হয় না। একই namespace-এ থাকা দুটি process একই port-এ bind করতে পারে না। যে process bind করতে পারে না, সেটি address ইতিমধ্যে ব্যবহৃত হওয়ার বার্তা দেয়। app-এর internal port পরিবর্তন করুন, অথবা দ্বিতীয় gluetun চালান।

gluetun পরিবর্তন করার পরে app-এর network নেই। gluetun restart বা recreate করলে এর সঙ্গে সংযুক্ত সবকিছুর connectivity বিচ্ছিন্ন হয়। ওই container-গুলো restart করুন।

ছোট page load হয়, কিন্তু বড় page আটকে থাকে। এটি MTU (maximum transmission unit) সমস্যা। tunnel অতিরিক্ত overhead যোগ করে, এবং path-এর কোনো অংশ error না পাঠিয়ে অতিরিক্ত বড় packet বাদ দেয়। WIREGUARD_MTU কমান, 1400 চেষ্টা করুন, তারপর 1320

Gluetun কখনও healthy হয় না। startup check প্রথম যে কারণগুলো পরীক্ষা করতে বলে সেগুলো হলো: WARN [vpn] restarting VPN because it failed to pass the healthcheck: startup check: dialing: dial tcp4: lookup cloudflare.com: i/o timeout। key-এর মেয়াদ শেষ হয়েছে কি না পরীক্ষা করুন। এরপর server list পুরোনো কি না দেখুন। সবশেষে host firewall outbound UDP block করছে কি না যাচাই করুন।

FAQ

Gluetun-এর পেছনে আমার container-এর published port কেন কাজ করা বন্ধ করল?

কারণ network_mode: "service:gluetun" container-টিকে gluetun-এর network namespace-এর মধ্যে রাখে। একটি namespace-এ একটি IP address এবং listening port-এর একটি সেট থাকে। অ্যাপটি listening অবস্থায় থাকে, কিন্তু publish rule-টি যে container namespace-এর মালিক, সেখানে থাকতে হয়। ports: list-টি gluetun service-এ সরিয়ে নিন। এটি attached service-এ রেখে দিলে Docker সেটি তৈরি পর্যন্ত করবে না: Error response from daemon: conflicting options: port publishing and the container type network mode

VPN tunnel-এর ভেতরের container-এ VPN tunnel-এর বাইরের container থেকে কীভাবে পৌঁছাব?

Gluetun-এর service name এবং অ্যাপটি যে port-এ listen করে, সেটি ব্যবহার করুন। উদাহরণ: gluetun:8080। Attached container-টির নিজস্ব কোনো Docker network নেই, তাই তার নিজের name resolve হবে না। Container-to-container traffic-এর জন্য কিছু publish করার দরকার নেই। উল্টো দিকে, namespace-এর ভেতরের container Gluetun v3.41 এবং পরবর্তী সংস্করণে service name ব্যবহার করে বাইরের container-এ পৌঁছাতে পারে, যেমন postgres:5432। ভিন্ন subnet-এর কোনো client, যেমন আপনার LAN-এর laptop, gluetun-এর firewall-এ আটকে যাবে, যতক্ষণ না সেই subnet-টি FIREWALL_OUTBOUND_SUBNETS-এ যোগ করেন।

VPN সংযোগ বিচ্ছিন্ন হলে Gluetun কি kill switch হিসেবে কাজ করে?

হ্যাঁ, এবং একই সঙ্গে দুটি কারণে। Attached container-এর shared namespace-এ থাকা route ছাড়া অন্য কোনো route নেই। তাই tunnel বন্ধ হলে সেটির machine-এর বাইরে যাওয়ার কোনো পথ থাকে না। Gluetun-এর firewall-ও outbound traffic কেবল tunnel এবং VPN server endpoint-এর মাধ্যমে যেতে দেয়। Gluetun নিজে restart না হয়ে VPN-টি অভ্যন্তরীণভাবে আবার চালু করে এবং WARN [vpn] restarting VPN because it failed to pass the healthcheck log করে। কারণ gluetun নিজে restart হলে প্রতিটি attached container তার network হারায়।

একই stack-এ Tailscale এবং Gluetun থাকলে outbound traffic কোনটি বহন করে?

একটি configuration ছাড়া সব configuration-এ Gluetun। Tailscale ডিফল্টভাবে শুধু আপনার tailnet-এর device-গুলোর মধ্যে traffic route করে এবং public traffic অপরিবর্তিত রাখে। Container image-এর default userspace mode-এ এটি কোনো interface তৈরি করে না। তাই routing-এ এর কোনো প্রভাব পড়ে না। TS_USERSPACE=false ব্যবহার করলে এটি শুধু 100.64.0.0/10 এবং আপনার advertised subnet-এর জন্য route install করে। ব্যতিক্রম হলো exit node: sudo tailscale set --exit-node=<exit-node-ip> Tailscale-কে default route বানায়, তাই তখন সেটিই অগ্রাধিকার পায়। Default route-এর দায়িত্ব একটির ওপরই দিন; দুটি product একসঙ্গে stack করবেন না।