How to Run Tor Bridge with obfs4 for VPS
Set up an obfs4 Tor bridge on one cheap VPS with torrc directives, port and firewall choices, working log lines, and how users fit get your bridge.
Wetin be Tor bridge, and why e dey exist
Tor bridge na entry point into Tor network wey dem no publish im address for public relay list. Dem dey call that list consensus. Na signed document wey anybody fit download, and censor fit download am too. To block Tor from am no hard: fetch consensus, then drop every address wey dey inside am for border. Bridges dey exist because the published list na the weak point. Dem dey give out bridge addresses small-small, so no single request go hand over the complete set.
Address wey no dey listed na only half of the answer. Deep packet inspection (DPI), wey dey classify traffic by wetin dey inside am instead of the address, fit recognise Tor connection from the shape of im TLS (transport layer security) handshake. Censor wey no get the list still fit see say “this one look like Tor” and drop the connection. Pluggable transport dey remove that signal. E dey wrap Tor stream inside another thing for client side, then your bridge go unwrap am.
obfs4 na the transport wey most bridges dey run. E dey turn the stream into bytes wey no get header or fixed handshake, so DPI no get pattern to match. E still dey authenticate the client. The cert= value inside bridge line na key wey client must prove say e hold before bridge go answer at all. This one dey stop active probing: censor wey connect to your address to test whether e dey speak Tor no go get reply and no go learn anything.
Wetin pluggable transport you suppose run?
- obfs4 need one VPS, two TCP ports, and no domain name. Na the easiest useful thing wey you fit run, and na wetin this guide dey cover.
- WebTunnel dey hide the connection inside normal HTTPS traffic go one real website. Tor Project list the requirements as static IPv4 address, domain wey you control, working web server like NGINX or Apache, valid TLS certificate, and at least 1 GB of RAM, with 4 GB recommended. E fit networks where random-looking traffic by itself dey suspicious, because country wey allow almost nothing apart from web browsing still dey allow HTTPS.
- Snowflake na different kind contribution. Volunteers dey run short-lived WebRTC proxies, so the entry points dey change all the time and censor no get stable address to block. You no dey operate bridge for am. You dey run proxy, and e no need fixed address.
Start with obfs4. Later, you fit add WebTunnel bridge for second address: if you run both for one IP, blocking one address go take down both.
Wetin running a bridge go cost you?
The data behind this chart
[
{
"label": "Bridge, minimum",
"min_upstream_mbit": 1
},
{
"label": "Guard or middle relay, minimum",
"min_upstream_mbit": 10
},
{
"label": "Guard or middle relay, recommended",
"min_upstream_mbit": 16
}
]As of August 2026, Tor Project dey ask bridge for at least 1 Mbit/s upstream and downstream bandwidth. Dem dey ask guard or middle relay for 10 Mbit/s, and 16 Mbit/s na the recommendation. These na published requirements, no be measurements. New bridge usually dey far below its own minimum for weeks. The same requirements page dey ask relay for at least 100 GByte outbound traffic every month. Even the smallest plans don already cover this. So read wetin small VPS really cost every month before you size anything bigger.
The abuse surface small, and na here people dey get am wrong. Bridge na the first hop. Traffic wey leave your server dey go another Tor relay, never to website wey user choose. Your IP address no dey show for stranger web log as the source of request. So complaint mail wey exit relay operators dey handle no go reach here. Still check your provider acceptable use policy, because some hosts treat any Tor service as special case. Bridge and onion service na mirror images for this matter: bridge useful only because people fit reach its address and later receive am, while v3 onion service for the same kind VPS useful only while your public IP stay hidden.
Make you no do one thing: convert existing public relay to bridge for the same address. Tor Project advice for that case na to change "IP address, name and fingerprint", because old address don already dey inside consensus wey censors dey download. Bridge wey be public relay last week na bridge wey don already dey blocklist.
Uptime matter pass speed. Relay requirements talk say "if your relay is not running for more than 2 hours a day its usefulness is limited". Bridge dey worse than relay for this matter, because each client get one address and no fallback. Restart go disconnect every user wey dey use am. Set up TCP port check for Uptime Kuma against the obfs4 port, so you go know the day e stop to answer.
Tor install from Tor Project repository
Distribution package dey behind, and bridge na security software wey suppose stay current. Add the project's own repository first.
sudo apt update
sudo apt install -y apt-transport-https gnupg wget lsb-release
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/nullNow write the source file. The Suites: line must contain your release codename, so read am from the system instead of typing am from memory.
sudo tee /etc/apt/sources.list.d/tor.sources >/dev/null <<EOF
Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: $(lsb_release -cs)
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpg
EOF
sudo apt update
sudo apt install -y tor deb.torproject.org-keyring obfs4proxyIf apt update report say repository no get Release file for your codename, Tor Project no carry that release. Delete /etc/apt/sources.list.d/tor.sources, run sudo apt update again, and install the tor package wey your distribution ship. Everything below remain the same.
The obfs4proxy package come from Debian and Ubuntu themselves (version 0.0.14 for Debian 13, as of August 2026). Confirm where the binary land, because na that path go enter the config:
command -v obfs4proxy || command -v lyrebirdUpstream rename the project to lyrebird, so newer package fit install /usr/bin/lyrebird instead. Use whichever path that command print.
Configure bridge for /etc/tor/torrc
BridgeRelay 1
ORPort 8443
ServerTransportPlugin obfs4 exec /usr/bin/obfs4proxy
ServerTransportListenAddr obfs4 0.0.0.0:9443
ExtORPort auto
ContactInfo you@example.com
Nickname PickANickname
BridgeDistribution anyEvery line for here get one possible failure attached, so check dem one after another.
BridgeRelay 1 dey tell tor make e send descriptor go bridge authority instead of public consensus. Na this one line make relay no dey listed.
ORPort na the real Tor port. E must dey reachable from internet, because tor dey test am and e no go publish descriptor until the test pass.
ServerTransportPlugin dey give tor the command wey e go run. tor dey start obfs4proxy as child process and dey talk to am through pipe. So obfs4proxy no get service unit of im own, and e no go show for systemctl status.
ServerTransportListenAddr dey set the port wey obfs4proxy dey listen on. If you leave this line out, obfs4proxy go pick any free port when e start. E fit pick different port after most restart. That one mean every bridge line wey you don give people go still point to port wey nothing dey listen on. Those clients go get refused connection and stop trying.
ExtORPort auto dey open extended ORPort. Na loopback channel wey obfs4proxy dey use to hand completed connections back to tor together with client address. Tor Project setup guide dey include am for every bridge, because without am the transport no fit report that address to tor.
ContactInfo and Nickname both dey public. Use address wey you go dey check, because na through am Tor Project go reach you about broken bridge. Choose nickname wey no identify you if you prefer make you remain quiet.
BridgeDistribution dey choose which distributor go give users your address. The accepted values na https, email, telegram, settings, none and any. Use any for your first bridge and allow the system decide. Use none for private bridge wey you dey share yourself. This one keep the address completely out of public distribution.
Wetin make port choice important
Avoid using 9001 for both ports. Tor Project talk am directly, because 9001 na the traditional ORPort and censors dey scan internet for am. The two ports must also different from each other, because tor and obfs4proxy each bind their own listener.
The strongest obfs4 port na 443. Outbound 443 dey open for almost every restricted network, and long-lived connection to am look like normal web session. Binding port below 1024 need one extra step, because obfs4proxy no dey run as root:
sudo setcap cap_net_bind_service=+ep /usr/bin/obfs4proxy
sudo systemctl edit tor@.service tor@default.serviceAdd these two lines for each editor wey opens:
[Service]
NoNewPrivileges=noThe capability alone no enough. systemd's NoNewPrivileges stops process from gaining any privilege wey its parent no get, and file capability na exactly that. Because of this, obfs4proxy go fail to bind 443 while the setting dey enabled.
If you prefer avoid that step, choose one high port wey no look unusual and write am down. Any port wey you choose, no change the obfs4 port later. A bridge line pins address, port, fingerprint and certificate together, so every copy wey don already dey inside user's browser go break immediately the moment the port changes.
Open both firewall dem ports
sudo ufw allow 8443/tcp
sudo ufw allow 9443/tcp
sudo ufw statusBoth ports need to dey open, and most providers get another firewall for their control panel wey ufw no sabi anything about. Rule wey dey for the server but no dey for the panel go create bridge wey nobody fit reach and wey no dey publish descriptor. If any part of this process new to you, the ufw rules wey fresh VPS need and wetin listening port really mean for Linux explain am. While you dey there, secure SSH with keys and hardened sshd config. Bridge wey no dey listed for server wey still dey use password SSH na still server wey dey use password SSH.
Start am, then read the log
sudo systemctl enable --now tor.service
sudo systemctl restart tor.service
sudo journalctl -e -u tor@defaultDebian and Ubuntu release two units. tor.service na small wrapper, while tor@default.service na the process wey dey do the actual work. Na why journalctl -u tor dey look almost empty, while the log wey you need dey under tor@default.
Two lines show say e work:
Self-testing indicates your ORPort is reachable from the outside. Excellent. Publishing server descriptor.
Registered server transport 'obfs4' at '0.0.0.0:9443'The first one mean say the reachability test pass and the descriptor reach the bridge authority. If e no ever show, something between internet and your server dey drop traffic go the ORPort. The second line must show the port wey you configure. If another port show there, e mean say tor no apply ServerTransportListenAddr. The usual cause na transport name wey no match: e must read obfs4 for both directives.
Confirm say the two listeners dey exist:
sudo ss -lntp | grep -E 'tor|obfs4|lyrebird'Wetin be my bridge line?
obfs4proxy dey write one template inside tor data directory:
sudo cat /var/lib/tor/pt_state/obfs4_bridgeline.txtThat directory belong to tor user and mode na 700, so if you no use sudo, you go get Permission denied. The file get one line for this format:
Bridge obfs4 <IP ADDRESS>:<PORT> <FINGERPRINT> cert=<CERTIFICATE> iat-mode=0Replace <IP ADDRESS> with your server public address, <PORT> with the obfs4 port, no be the ORPort, and <FINGERPRINT> with the identity fingerprint wey tor write inside im data directory:
sudo cat /var/lib/tor/fingerprint
sudo cat /var/lib/tor/hashed-fingerprintThe first file get your nickname and the identity fingerprint wey suppose dey inside bridge line. The second get the hashed fingerprint. Na this one you paste for Relay Search to check whether your bridge dey run and roughly how many clients dey reach am. You no fit use the two interchangeably. Bridge line wey carry the hashed value no match the identity key wey your bridge dey present, so the client go reject the connection wey e just open.
Bridge dey reach users how?
You no dey hand your bridge line give anybody. Once descriptor reach bridge authority, distribution system (rdsys, wey be successor to BridgeDB) go assign your bridge to one distributor, and users go ask that distributor for bridges. As of August 2026, routes na these:
- The web form for bridges.torproject.org/options, wey go serve bridge lines after captcha.
- Email to bridges@torproject.org from Gmail or Riseup address, wey go reply with bridge lines. This provider restriction dey because unlimited free accounts fit allow one censor enumerate every bridge.
- The Telegram bot @GetBridgesBot. Send
/start, then/obfs4or/webtunnel. - Tor Browser itself, under Settings then Connection, where "Request bridges" dey fetch dem through moat channel.
New bridge go show for Relay Search about three hours after setup. Users fit take much longer: Tor Project wording be say, "It can take several days or weeks until you see a consistent set of users." If users no show plenty for the first fortnight, na normal; e no mean say fault dey.
Setting BridgeDistribution none go opt out of everything. Then na you get the bridge line to send give the people wey need am, through channel wey censor no dey read.
Wen something no work
No self-testing line for the log. The ORPort no dey reachable. Test am from another machine with nc -vz your.ip 8443. If e hang, packets dey drop, so check ufw and provider panel. If e refuse connection, tor no dey listen, so check ss -lntp and read the log for config error.
The registered transport show port wey you no pick. tor ignore ServerTransportListenAddr. The transport name must match the one for ServerTransportPlugin exactly, and both must be obfs4.
obfs4proxy no go bind port 443. Confirm the capability with getcap /usr/bin/obfs4proxy, then confirm say the override reach the unit with systemctl show tor@default -p NoNewPrivileges. If e print NoNewPrivileges=yes, your drop-in go to unit wey no dey run.
Nothing inside /var/lib/tor/pt_state/. tor never start the transport, so the path for ServerTransportPlugin no correct. Compare am with the output of command -v obfs4proxy.
Clients stop connecting after change. Any change to the address or obfs4 port make every bridge line wey you don distribute before invalid. Check whether the server public IP change too. Some providers dey do this when dem rebuild the server.
tor no go start at all. Run sudo -u debian-tor tor --verify-config -f /etc/tor/torrc. E parse the file, print the line wey e object to, and leave the running service as e be.
FAQ
VPS provider go complain about Tor bridge?
Bridge na entry point, so traffic wey dey leave your server go other Tor relays, e no go ever go site wey user choose. Your IP address no go show for anybody web log as source of request, and na this one dey cause the complaints wey exit relay operators dey handle. Hosting rules still dey vary, and some providers dey treat any Tor service as special case, so read acceptable use policy before you start and put address wey you read into ContactInfo.
How much bandwidth Tor bridge dey use?
Published minimum na 1 Mbit/s up and down, while guard or middle relay need 10 Mbit/s. Real use dey start near zero, because your bridge only carry traffic for users wey distributor send come am. If you want hard ceiling, set RelayBandwidthRate and RelayBandwidthBurst for torrc.
Why nobody don connect to my new bridge?
Bridge dey take about three hours before e appear for Relay Search, and Tor Project guidance be say consistent set of users fit take several days or weeks. Check say descriptor publish, wey be the self-testing line for journalctl -u tor@default, look up your hashed fingerprint for Relay Search, and confirm say BridgeDistribution no set to none.
I suppose run obfs4 or WebTunnel?
Run obfs4 if na your first bridge: one VPS, two ports, no domain, no certificate. Run WebTunnel where dem dey block traffic wey look random, because e need domain wey you control, real web server, valid TLS certificate, and at least 1 GB of RAM. Put dem for separate addresses if you run both, because one blocked IP fit remove two bridges at once.
Wetin go happen if I change obfs4 port later?
Every bridge line wey dem don distribute go stop to work. Bridge line dey tie address, port, fingerprint, and certificate together, so client wey hold old line go open connection to port wey nothing dey listen on, then e go give up. Same thing apply when server public IP change. Choose port during setup and leave am that way.