Saturday, November 18, 2017

Deploy ZeroNet to Heroku as a Public or Private ZeroNet Proxy Service

Note: due to formatting issues, some bash commands below have incomplete display. Just copy and paste the bash code block somewhere for the complete commands.

Introduction

This is a tutorial on deploying ZeroNet to Heroku as a Python web app. You can host a (1) public or (2) private ZeroNet proxy, or only host (3) your personal zsites (ZeroNet site) statically (with all your zsite contents there) or dynamically (as an open gate to the clearnet and fetch your zsite contents from the zero network) on Heroku.
An example zsite hosted on Heroku:
(https://dcentral.herokuapp.com)
Things are much easier if you have a VPS and wish to host ZeroNet on it, please check the following two video tutorials:
How to Create a Private ZeroNet Proxy (for Phones, only for yourself)
How to Create a ZeroNet Public Proxy for Everyone to Use
However, VPS will cost you some money. On the other hand, you can deploy and use ZeroNet on Heroku for free, although with some limitations.

Limitations

  • No persistent storage with Heroku dynos.
    • If you host a (1) public or (2) private ZeroNet proxy, your user data will not be saved on Heroku. For example, if you visit your proxy and subscribed some new sites, and next time you visit the proxy again, all subscriptions will disappear and it is like a fresh new deployment. The reason is data/zsites downloaded on Heroku are on a temporary space and will be erased whenever a session ends (e.g., when your dyno sleeps and restarts, at most every 24 hours).
    • If you want to host (3) your personal zsites statically, you need to deploy every change of your zsite (e.g., after you published a new post) to Heroku. Otherwise, it is equivalent to host it dynamically because user interactions through the ZeroNet UI will not be saved, and the Heroku copy of your zsite files is always the same as your last deployment, which can be older than the latest copy in the zero network. Although it will update automatically and fetch your latest zsite contents from the zero network whenever you visit your zsite hosted on Heroku, the updates can not be saved for your next visit, which means it has to download even the same updates from the zero network next time — in other words, it is like to host your zsite dynamically.
  • Heroku does not allow opening ports or use multiple ports. By default, ZeroNet use the port 43110 to serve the web UI, and also want the port 15441 for peer communication, although the second port is optional. However, Heroku only allows you to use one port, so we have to use the only one for ZeroNet web UI. Without a port for peer communication means we have to run ZeroNet in slow mode and creating new sites or publishing new contents may not work well (but you can do that locally).
  • The free dyno of Heroku has some quota limitations: (https://devcenter.heroku.com/articles/free-dyno-hours)
Tips: If you want to host a public ZeroNet proxy without any restriction on users, you can do it in just one-click by using the Heroku deployment button in this repository:
(https://github.com/BruceJawn/HeroNet)
Otherwise, you should read the following contents.
Assume you’re with Ubuntu/Linux. If you’re using Mac or Windows, it’s better to use VirtualBox with a pre-installed Ubuntu desktop image (http://www.osboxes.org/ubuntu/) to save time.

Step 1. Register a Heroku account.

Register your account here: (https://signup.heroku.com/signup/dc)

Step 2. Install Python 2. (Optional)

Python version 2.X (instead of Python 3.X) is needed for testing and using ZeroNet locally. If you only want to host a (2) private ZeroNet proxy, you can skip this step. If you want to host a (1) public ZeroNet proxy without a zsites whitelist so any user can visit any zsite through your proxy, you can also skip this step. But if you want to host a (1) public ZeroNet proxy and only allow users to visit some whitelisted zsites (disallow users to add new sites), or host (3) your personal zsites, you must be able to run ZeroNet locally.
Ubuntu should have Python 2 installed by default, you can check it by:
python2 --version
If not, to install Python 2.X, you can refer to (http://docs.python-guide.org/en/latest/starting/install/linux/)

Step 3. Install Git.

sudo apt-get update
sudo apt-get install git

Step 4. Install Heroku CLI.

# Run this from your terminal.
# The following will add our apt repository and install the CLI:
sudo add-apt-repository "deb https://cli-assets.heroku.com/branches/stable/apt ./"
curl -L https://cli-assets.heroku.com/apt/release.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install heroku
Now login Heroku,
heroku login
then input your registered email and password for Heroku.

Step 5. Prepare the ZeroNet app.

Firstly, clone the ZeroNet source code:
git clone https://github.com/HelloZeroNet/ZeroNet.git
cd ZeroNet
Now, add the Python runtime requirement file for Heroku:
cat > runtime.txt << EOF
python-2.7.14
EOF
Alternatively, manually create a file named “runtime.txt” in the folder “ZeroNet”, with the following content
python-2.7.14
Now go to Step 6 if you want to host a (1) public ZeroNet proxy.
Or go to Step 7 if you want to host a (2) private ZeroNet proxy.

Step 6. This step is for hosing a (1) public ZeroNet proxy.

If you want to disallow users to add new sites to your proxy, go to Step 6.1.
If you want to allow users to access any zsite, go to Step 6.2 directly.

Step 6.1.

Run ZeroNet locally, and visit all the zsites you want to be whitelisted for your users.
sudo apt-get update
sudo apt-get install msgpack-python python-gevent
python2 zeronet.py
Open (http://127.0.0.1:43110/) in your browser to visit zsites.
You now can delete the file “GeoLite2-City.mmdb” in the “ZeroNet/data” folder to save space for deployment. The file “users.json” in the “ZeroNet/data” folder contains a “master_seed” and a list of zsites you just visited/subscribed. You can login using the “master_seed” as the administrator later to add and delete subscribed sites through the ZeroNet UI in multi-user mode. Make sure your “ZeroNet/data” folder contains a complete copy of the default homepage site “1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D” in the folder “ZeroNet/data/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D”.
Now enable git to include files in “ZeroNet/data” folder:
nano .gitignore
find and change the following two lines
# Data dir
data/*
*.db
to
# Data dir
#data/*
#*.db
then ctrl+o, enter key to save and ctrl+x to exit.

Step 6.2.

Enable multi-user mode for ZeroNet,
mv  ./plugins/disabled-Multiuser ./plugins/Multiuser
Alternatively, manually rename the folder “disabled-Multiuser” in “ZeroNet/core/plugins/” to “Multiuser”.

Step 6.3.

Now, add the Procfile for Heroku:
If you want to disallow users to add new sites to your proxy,
cat > Procfile << EOF
web: python zeronet.py --ui_ip "*" --ui_port \$PORT --multiuser_no_new_sites
EOF
If you want to allow users to add new sites to your proxy,
cat > Procfile << EOF
web: python zeronet.py --ui_ip "*" --ui_port \$PORT
EOF
Alternatively, manually create a file named “Procfile” in the “ZeroNet” folder with the following content
web: python zeronet.py --ui_ip "*" --ui_port $PORT --multiuser_no_new_sites
or
web: python zeronet.py --ui_ip "*" --ui_port $PORT
depending on whether you want to disallow users to add new sites or not.
Note, ZeroNet use the default local IP 127.0.0.1 and port 43110 to serve the web UI. However, as you will install ZeroNet on a remote machine, you must set the UI IP as “*”, as described in (https://zeronet.readthedocs.io/en/latest/faq/#is-it-possible-to-install-zeronet-to-a-remote-machine). Also, Heroku requires all web app to bind a dynamic port (which can be accessed by the environment var “PORT”.
Now go to Step 9.

Step 7. This step is for hosing a (2) private ZeroNet proxy.

Now enable the UiPassword, so a user can only access the UI with the password.
mv  ./plugins/disabled-UiPassword ./plugins/UiPassword
Alternatively, manually rename the folder “disabled-UiPassword” in “ZeroNet/core/plugins/” to “UiPassword”.
Now add the Procfile for Heroku:
cat > Procfile << EOF
web: python zeronet.py --ui_ip "*" --ui_port \$PORT --ui_password yourpassword
EOF
Alternatively, manually create a file named “Procfile” in the “ZeroNet” folder with the following content
web: python zeronet.py --ui_ip "*" --ui_port $PORT --ui_password yourpassword
Change “yourpassword” above to your desired password to access the ZeroNet UI.
Tips: you can use Heroku’s config variables to set your password later. Just replace “–ui_password yourpassword” above by “–ui_password $mypassword” and you can later add and set the config variable “mypassword” in your Heroku dashboard, (https://dashboard.heroku.com/apps/your_heroku_app_name/settings) -> Config Variables, then restart your dyno,
heroku restart
or you can use Heroku CLI to set the config variable
heroku config:set mypassword=yourpassword
Now go to Step 9.

Step 8. This step is for hosing (3) only your zsite.

Assume you have a zsite with address “1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui”. Check the tutorial: (https://zeronet.readthedocs.io/en/latest/using_zeronet/create_new_site/) for creating your zsites.
Run ZeroNet locally, and visit your zsite “1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui”
sudo apt-get update
sudo apt-get install msgpack-python python-gevent
python2 zeronet.py
Open (http://127.0.0.1:43110/1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui) in your browser to visit your zsite.
If you want to host your zsite, make sure a full updated copy of your latest zsite is downloaded to, e.g., “ZeroNet/Data/1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui”.
Now enable git to include files in “ZeroNet/data” folder:
nano .gitignore
find and change the following two lines
# Data dir
data/*
*.db
to
# Data dir
#data/*
#*.db
then ctrl+o to save and ctrl+x to exit.
Next, enable multi-user mode for ZeroNet,
mv  ./plugins/disabled-Multiuser ./plugins/Multiuser
Alternatively, manually rename the folder “disabled-Multiuser” in “ZeroNet/core/plugins/” to “Multiuser”.
Now add the Procfile for Heroku:
cat > Procfile << EOF
web: python zeronet.py --ui_ip "*" --ui_port \$PORT --multiuser_no_new_sites --homepage 1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui
EOF
Alternatively, manually create a file named “Procfile” in the “ZeroNet” folder with the following content
web: python zeronet.py --ui_ip "*" --ui_port $PORT --multiuser_no_new_sites --homepage 1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui
Change “1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui” above to your zsite address.
Note the default homepage for ZeroNet UI web interface is “1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D”, you can change it to your zsite using the flag “–homepage”.
Tips: you can use Heroku’s config variables to set your site address later. Just replace “–homepage 1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui” above by “–homepage $mysiteaddress” and you can later add and set the config variable “mysiteaddress” in your Heroku dashboard, (https://dashboard.heroku.com/apps/your_heroku_app_name/settings) -> Config Variables, then restart your dyno,
heroku restart
or just use Heroku CLI to set the config variable
heroku config:set mysiteaddress=1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui
Also, you can use a custom domain and point its root to (https://yourappname.herokuapp.com/1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui).

Step 9. Deploy ZeroNet to Heroku.

#Create an app on Heroku with a random app name
heroku create
#Use the following if you want to specify your app name
# heroku apps:create myappname

#Commit all changes, you need to do the following Steps A, B, C 
#every time you modified something before deploy/update your changes to Heroku
#(A) add the modified files to the local git repository:
git add .
#(B) commit the changes to the repository:
git commit -m "notes_on_changes"
#(C) deploy the code:
git push heroku master

#Ensure that at least one instance of the app is running:
heroku ps:scale web=1

#Now visit the app at the URL generated by its app name
heroku open

#View logs
heroku logs --tail
In you browser, you should be able to see the ZeroNet web UI served by Heroku at your Heroku app URL.

Step 10. If you want to update something.

Firstly, make the changes using your local copy of ZeroNet. For example, you can update “ZeroNet/data/users.json” to whitelist some new zsites by visiting them using your local ZeroNet copy. Or if you’re hosting your own zsite statically, you can post some new contents through your local ZeroNet, so your local copy of
“ZeroNet/Data/1DCNTRLnCAGxhZh4GEbkLAJu8AVFAM82ui” is newer and has more contents than the Heroku copy.
Then, deploy the changes,
#(A) add the modified files to the local git repository:
git add .
#(B) commit the changes to the repository:
git commit -m "notes_on_changes"
#(C) deploy the code:
git push heroku master
If you only want to host your zsite dynamically, you don’t need to deploy again after you updated your zsite.

References:

https://github.com/HelloZeroNet/ZeroNet/issues/824 (Other modification is if you enable –multiuser_no_new_sites, then normal users will not able to add new sites (users in data/users.json still can))
https://github.com/HelloZeroNet/ZeroNet/issues/1011 (–multiuser_no_new_sites)
https://devcenter.heroku.com/articles/getting-started-with-python
https://stackoverflow.com/questions/21984960/escaping-a-dollar-sign-in-unix-inside-the-cat-command

Sponsors