Saturday, January 27, 2018

Using Tor with ZeroNet on Heroku


This tutorial will let you 1. create a hidden service for your ZeroNet proxy on Heroku, so you can access your proxy not only through a clearnet URL like “” but also via a Tor URL “XXX.onion”. Example: http://dcntrli7i2ytw57h.onion (can also be visited from clearnet by a Tor proxy, e.g., 2. enable Tor support for ZeroNet connections on Heroku. Example: (check the Tor Status at the upper right corner, the “TOR: ERROR” should be “TOR: AVAILABLE”)

First of all, you should know how to deploy ZeroNet to Heroku. Read this tutorial if you don’t.

To run your ZeroNet proxy on Heroku as a hidden service, you can use this Tor Hidden Service Buildpack for Heroku:
For example, in your Heroku app directory, add the buildpack,

heroku buildpacks:add

Insert “./tor/bin/run_tor” to your Procfile, e.g.,

web: ./tor/bin/run_tor python --ui_ip "*" --ui_port ${PORT}

And deploy again to update.

Note, it seems that the “run_tor” command of the “heroku-buildpack-tor” buildpack has a problem with the original Python commands for running ZeroNet with some arguments. In particular, the variable “$PORT” is not recognized by the “exec” bash command used in the buildpack, so it will not be able to start ZeroNet correctly. To solve this problem, use ${PORT} instead of $PORT as shown above. Another simple way to solve this problem is adding a “&” before your command to run ZeroNet, i.e., change the above Procfile to

web: ./tor/bin/run_tor & python --ui_ip "*" --ui_port $PORT

Then, you need to add the config variables “HIDDEN_PRIVATE_KEY” and “HIDDEN_DOT_ONION” (your .onion web URL), so you can access your proxy by the .onion URL through Tor.
Tips: some tools to generate your .onion key and URL:

If you want your proxy only be accessible over Tor, change your app type from “web” to something else, e.g., modify the Procfile to

torweb: ./tor/bin/run_tor python --ui_ip "*" --ui_port ${PORT}

Besides, you may encounter a “Forbidden Invalid host:” error when you visit your .onion URL, and the reason is ZeroNet has a ui_host restriction, see also To let the ZeroNet UI be accessible through both the clearnet URL (e.g., and .onion URL (e.g., http://dcntrli7i2ytw57h.onion), you must add the parameter “ui_host” and change your Procfile to

web: ./tor/bin/run_tor python --ui_ip "*" --ui_port ${PORT} --ui_host dcntrli7i2ytw57h.onion

However, in order to enable Tor support for your ZeroNet connections, as instructed in, you must enable Tor control port 9051, which cannot be done directly.

So to solve all the problems with Tor, I suggest you fork the buildpack and customize the compile script to satisfy your needs. An example fork: Check the file “bin/compile” at, in which I added several lines for ZeroNet, e.g., to generate the “zeronet.conf” file,

echo "Setting up ZeroNet"
cat > ${HOME}/zeronet.conf << EOZ
ui_ip = *
ui_port = \${PORT}
homepage = \${mysiteaddress}
ui_host =
tor = \${USE_TOR}

and to use Tor control port

echo "controlPort 9051" >> $HOME/tor/etc/tor/torrc
echo "CookieAuthentication 1" >> $HOME/tor/etc/tor/torrc

To try my fork, in your Heroku app directory, add the buildpack,

heroku buildpacks:add

change your Procfile to

web: ./tor/bin/run_tor python

and deploy.

Note in my fork, I added the config var $CLEARNET_URL which can be used to specify the clearnet URL for your proxy. If you want to set up a public proxy without user restrictions, or a private proxy, you can set the config var $mysiteaddress to the default HelloZero address “1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D”, or just remove the following line for specifying the homepage (which is used for hosting your zsite only) in “bin/compile”

homepage = \${mysiteaddress}

You also need to add the config var $ZERONET_CONFIG. If you want to disallow users to add new sites, you can set the config var $ZERONET_CONFIG to “multiuser_no_new_sites”, otherwise, set it empty.
Finally, you should add the config var $USE_TOR, and set its value to “disable”, “enable” or “always” depending on how you want to use Tor.