NFTs and Dark Web Shenanagins
A based design that makes a web that’s true
ICANNs and NATs embrace shall be no more
Behind a Pi or in the cloud for you
We use that tool be I2P or Tor
Come join a world of speech that can flow free
The words by truths of math they shall be bound
A power built right in that’s DHT
Identity by key pairs holds its ground
IPFS a poggers web design
ID by content not by where it is
Defi domain to own your name online
A world that’s free of gov and free of biz
Come build a web like this, it must be done
For you and me a web like this is won.
Skibidi.1
A while back I started mirroring my site on a couple of decentralized networks, mainly Tor and I2P. Just about any non HTTP and ICANN method of serving a site has some sort of benefit, and although fewer people use them, I like their concepts and the idea of supporting them by utilizing them. However, beyond just Tor & I2P, there’s a couple other ways to host content in non standard ways, so I thought I’d talk about them as well.
Table of Contents:
- Tor & I2P
- IPFS
- Decentralized Domains
- Microblogging Protocols
- Nostr (nsite)
- Gemini, Gopher, ’n such
- Conclusions
- Footnotes
Tor & I2P
Isn’t Tor just for criminals?
Short answer: No. Long answer: still no, but with more context.
Approximately 3 percent of Tor traffic is dark web traffic as apposed to accessing the clearnet, of which less than half is criminal or illicit, not too far off from 2-5% of transactions by financial institutions being money laundering. Like most things, it’s overwhelmingly used for good or benign purposes.
And, being American, it’s easy to forget what many jurisdictions consider ‘crimes’ - so I’m going to pick on Germany for a bit. Say you’re German and you see your local senator break a law that said senator voted for, so you call him a dick on social media. Welp, enjoy having your home raided. Then, let’s say you’re curious about what the international media is saying about that, so you get around the great firewall of Germany and see what Russia Today said about it. You then reproduce said reporting on the internet. Enjoy risking prison and a 120k fine. Germany theoretically has free speech protections under both the EU and the German constitution, with more outwardly totalitarian nations being even worse on that sort of stuff. Although the above technically constitute crimes there, they’re certainly not considered crimes by American standards, and I’m glad the technology enables people to speak more freely.
Now, a small percent isn’t 0%, so it is a valid critique of the software. However, it’s important to note it’s not like it’s some magic crime enabler; criminal services get shut down regularly, just like they do when offered any other way. Similarly, it’s not like dark web markets made drugs a problem - that sort of stuff was always there, and the existence of a different way to acquire them likely had minimal or no effect on the amount used. Though there is evidence to suggest that their presence lowers violence and the risk of taking contaminated drugs.
This has all been about Tor so far. I2P is a bit smaller and is mostly used by either hobbyists or more mundane (by American standards) people trying to blog (often anonymously) or mirror news. Outside of copyright infringement, I’m not sure there’s much crime that occurs on I2P.
y tho?
What would you - the presumably rather tame person who reads and/or writes blogs - get from using Tor &/or I2P?
One of the biggest pros is networking, which comes in two parts. First, you don’t need to open ports or perform any fancy network configuration. You could be behind half a dozen NATs, and yet that random device you’re using as a server can still host things all the same. Secondly, there’s no need for anything static. You can change your IP to one halfway across the world, and within a few moments users should be able to access your site at the new location. Unlike traditional self hosting, which is often not possible on your default home internet setup, both Tor and I2P will work flawlessly just about anywhere.
There are also no ICANN domains required. Annoying tech nerds like me are often not fond of one central authority like ICANN gatekeeping the internet, but both Tor and I2P use key based domain names which the user generates. While they are difficult to remember and need to be stored in bookmarks or a similar tracking method, they completely cut out the need for a central authority to decide what points where. Although Tor does not support it, I2P does have an optional way to use more ICANN like domains, by either subscribing to a list from a service that acts as a registry or manually setting a short domain (say nate.i2p) to resolve to a longer key based domain (say g5lt4bvjhtyi6evknarf6srj2od2e6rcn3ld65qqnpnb6dpz5wyq.b32.i2p).
Server privacy can also be useful. Beyond the networking related hurdles of trying to self host things on a residential IP address, there’s also the fact that your IP is going to be known to everybody2. You can also do easy per device configuration, so for example you can set xyz.onion/.i2p to resolve to virtual port 80, but port 22 can’t be accessed by anybody who has the domain.
Finally, as touched on a bit above, there’s some basic free speech protections. If you start a darknet market eventually the authorities are going to catch you, but doing something more mundane like calling a politician a dick on an anonymous blog or message board in a nation where that’s illegal is likely not going to be something they’ll track you down for. Go call Andy Grote a dick, read the banned books, peruse the foreign news outlets, and do all forms of shenanigans.
Tor vs I2P
Tor and I2P are similar in a lot of ways: both providing anonymity through routing connections between multiple devices, both using key pairs to identify sites instead of a centralized naming service, and both capable of hosting or receiving content in a networking environment that’d be otherwise hostile to the same actions for a variety of reasons. Still, there are a few differences as well.
First off, despite predating Tor, I2P is smaller. If you’re looking to reach a larger audience, regardless of what you wish to reach them with, focusing on Tor over I2P is the way to go. Tor also has more ‘serious’ sites, for lack of a better term. Using Tor you can send a tip to American federal agencies, buy crack, read legitimate news outlets, and browse numerous official dark web mirrors (including Facebook and Reddit). Using I2P you’re likely to stumble across endless blogs and small forums. The size and scope isn’t necessarily a pro or a con, in fact it’s one of the reasons why I enjoy hanging out on I2P, but it all depends on what you’re looking to do.
Tor is also a lot more centralized than I2P. On Tor the naming system, despite being key based, is managed as a centralized-but-distributed database. Similarly, the Tor project dictates which devices are permitted to act as relays and exit nodes. I2P, on the other hand, is more decentralized. Both the key based naming database, and the devices that participate in the network, are decentralized. This does come at the cost of easier attacks (e.g. routers joining the network to send spam requests and such), but it means that it’s also more resilient and harder to block3.
I2P is entirely focused on building its own internal ‘dark web,’ while Tor is capable of being used as a proxy to access the clearweb (regular internet) - which makes up the majority of Tor usage.
Tor is a lot quicker and more user friendly to set up. To access the Tor browser on desktop or mobile it’s a couple clicks to get the the website, appstore, repo, etc and install. On the first run, you’re pretty much set to go, being capable of browsing in ~30 seconds + download time. I2P is a bit more complicated to set up: after downloading you need to go through the installation, which takes a bit longer, then manually start the router and open a localhost URL in your browser and configure your browser to use it as a proxy. You then need to manually start/stop the router when you want to use it.
Once installed, however, I2P offers a lot more features. In the default Java installation, you have a GUI, the ability to manually set/pull human readable domains, a torrent client, and links to useful resources all within a dashboard. If you’re hosting content on I2P, you’re also going to be able to do so very easily from within said dashboard. Tor is a lot more minimalistic, and if you want to host something you’ll need to manually edit configuration files.
All in all, Tor is the way to go if you really need to get some important information out there, reach the most amount of people, and be accessible to people with less know how than I2P. If, however, you’re just looking to participate in an alternative to the standard IPV4+ICANN internet and share a blog or something then I2P might be a better alternative - especially since people can access a clearnet site via Tor, but I2P users generally cannot access content outside of I2P4.
Reading Blogs ’n Such on Tor/I2P
I’m going to assume that, if you’re reading my blog, you’ll know how to install Tor and/or I2P. Both have instructions on how to do so on their sites, and will walk you through once you begin the installation process.
There’s a couple of different ways to follow RSS links through Tor & I2P, all of which are going to require Tor & I2P to be installed. The most convenient way, however, I’ve found is to use an in browser feed reader. Browsers like Brave, Vivaldi, and PaleMoon all have built in feed readers, and extensions like FeedBro can add feed reading to any browser that supports extensions. As long as you’ve configured your browser to use Tor or I2P in the browser’s proxy settings you should be able to add Tor and I2P urls respectively into the browser’s feed reader and follow them like anything else. I’d recommend making profiles for I2P and/or Tor to make things simpler5.6
It’s also, however, possible to use a dedicated feed reader as long as said feed reader supports adding a proxy. For example, ThunderBird is capable of following either Tor or I2P RSS feeds if you set it to use one of them as a proxy. Dedicated feed readers often don’t let you have multiple profiles, however, so you might need multiple feed readers if you wanted to follow clearnet feeds, Tor feeds, and I2P feeds. It is worth noting that if you use Tor as a proxy you can follow both clearnet feeds and onion feeds, though following Tor and I2P feeds require mutually exclusive proxy configurations unless you have some form of a proxy manager that lets you combine them both into one.
Doing something like this on Android is a lot trickier. You can install I2P’s Android app or within Termux, as well as using Orbot for a local Tor proxy, to access I2P and Tor feeds on mobile. Some readers like Feeder will load Tor feeds if you’re using Orbot, although some others won’t like Brave (which will find the feed but not load the contents of it). That said, I’m not sure of any feed readers that support setting a proxy on Android. The Fennec browser does support extensions, including FoxyProxy. However, it doesn’t seem to support any feed reading extensions like FeedBro, so you might be out of luck in reading I2P feeds within an Android app. You could set up some sort of Linux environment in Termux or Android’s Linux shell, then use a desktop feed reader - and I’m sure there’s some way you could get a SOCKs proxy setup as a VPN - but in most cases you’re probably just better off leaving reading I2P feeds to desktop.
If you’re looking to test your feed reader setup, I’ve got my Tor and I2P enabled RSS feeds below:
Tor: http://natetcpfw5nrvukszupzetfmraziq2x2odbe72va6fhcc6urfmk2f7ad.onion/index.xml
I2P: http://g5lt4bvjhtyi6evknarf6srj2od2e6rcn3ld65qqnpnb6dpz5wyq.b32.i2p/index.xml
While I doubt I have the reach to make something like this trendy, I would love to see following content through I2P & Tor become more trendy in the random nerd space of the internet. Not only are both the quintessential self hosting setups, allowing you to spin up a server just about anywhere with little difficulty, but there’s also a lot more you can follow than just random blogs. Many news outlets and a few social media sites both support RSS and have official onion URLs, and there are a number of unofficial Tor & I2P mirrors of everything from YouTube to news outlets (which you can also follow through RSS).
The more people who follow stuff like this, the more people will implement mirrors on the services (officially and unofficially). And in a world where a lot of countries have taken suddenly totalitarian turns in regard to speech, having more services on these protocols could be really good.
Hosting content on Tor & I2P
There’s a million ways you could go about setting up a website on Tor or I2P, but there’s three that I figured I’d go over.
Pro tip: if you have I2P installed on a non-graphical device, use port forwarding via SSH to get to the console. For example: ssh -L 8085:localhost:7657 [email protected]
will allow you to access the remote console from localhost:8085 on your device.
1: Static Content on I2P only
The standard I2P client has a static web server built in, which is probably the easiest way to dip your toes in the water of hosting/mirroring content on I2P. The site does have to be static, hosting a dynamic site like WordPress won’t work here, but it’s both rather simple and babyproof since everything works out of the box. Especially if you either didn’t care about having content on Tor, or have clearnet content which can be accessed via Tor anyway, this could be the best way to go about dipping your toes into the darknet.
Open the I2P dashboard of the device you want to host content on and click the web server button. It should pull up a page with detailed instructions, including the directory of the content the web server will host. Place your static files in that directory, go back to the dashboard, click the Hidden Services Manager button, and start the web server.
That’s it; you’ve got a site that should now be accessible via I2P. You’ll probably want to click on the web server within the Hidden Services Manager and check the box that will cause it to start when the router starts (no point in needing to manually start the server after every update or reboot). You’ll also potentially want to register a short domain (e.g. like how I have nate.i2p), for which there’s instructions on the web server page, but the long key based domain will work on its own as well.
There are a couple limitations to this, however:
- You can’t host multiple sites with the included I2P web server
- The site won’t be accessible over Tor
- It won’t support dynamic sites
Otherwise, if it does meet your needs, it’s probably the easiest way to setup a self hosted website of any kind - much less a website on the ‘dark net’. It’s pre-configured, meaning no need to worry about server hardening or anything like that. It’s also super easy to setup on a myriad of devices (I hosted I2P content on a phone via Termux once), so if you just wanted a simple I2P site or mirror then this will probably be the way to go.
Backup Your Keys! Like anything cryptography based, if you lose your keys you lose the service. Open your I2P key backup folder in /home/USERNAME/.i2p/i2ptunnel-keyBackup/ and grab a copy of the key that matches your I2P url that you just created. That way, even if the server loses all the data on it, you can still keep the same address.
2: Static Content on Tor only
Though Tor doesn’t have a built in GUI static host like I2P does, the tool OnionShare serves a very similar function - allowing you to host websites, share files, and create chats on most devices. It has a CLI version, though for this I’m just going to assume you’re using the GUI version. You can get it here or on Flathub, the Snap Store, and many different repos.
Once installed, open OnionShare and wait for it to connect to Tor, then click the Host a Website button. It should bring you to a screen where you can add a static website’s folder to be hosted. Once you’ve selected the folder there’s a few checkboxes you’ll want to check:
- Check the option to not send the default security policy IF your static site relies on remote resources.
- Check the option to always open that tab when opening OnionShare. This makes the website permanent, otherwise it’ll be lost when you close the program.
- Check the box that states this is a public website.
Now click the start sharing button and it’ll give you a link. It’s live and all set, just like the built in I2P web server there’s no need to harden a web server or do any sort of advanced configuration - it’s all set and ready to go out of the box. There are a few limitations, namely:
- Your site won’t be accessible over I2P
- You can’t host anything dynamic
Otherwise, if you’re just looking to get a Tor site or mirror an existing site on Tor, this is probably the easiest way to go about it.
Backup Your Keys! Like anything cryptography based, if you lose your keys you lose the service. You can find your private keys at /.config/onionshare/persistant (/snap/current/.config/onionshare/persistant for the snap version) on Linux. There should be a .json file with three random words, back that up as it contains the private key of your website.
3: Tor & I2P (static or dynamic) - how I host my stuff
Before starting, install Tor and I2P. Also, either install nginx (sudo apt install nginx) to follow along with the tutorial for static sites, or setup whatever other server you would like to host before hand and skip the nginx process. For the guide I’m going to assume that you’re hosting on a Debian based version of Linux, which automatically has Nginx running underneath its own username - which will affect the commands we run later. I’m also going to assume that you’re either creating a user on a server dedicated to the project, or are on a dedicated VM/VPS/device. Finally, I’ll assume you’re doing everything via SSH.
The first step, which is optional, is to generate a vanity address for Tor. For example, my blog’s Tor address is natetcpfw5nrvukszupzetfmraziq2x2odbe72va6fhcc6urfmk2f7ad.onion
. Using something like mkp224o you can generate a custom name. Follow the instructions provided on the GitHub page.
Next, you’ll need to get your local server setup. For this guide I’ll walk you through setting up an nginx static webserver, but you can use anything else. I previously used Apache, and if you wanted something like a WordPress site, then you’d set that up and make it available locally INSTEAD of following this part of the guide.
Start by creating a directory to store your static site in. Assuming you’re going to create a site called “blog”, something like cd /var/www && sudo mkdir blog
will work, and we can always create another folder in “www” if more sites are wanted later. Now grant folder permissions with the following commands:
sudo chown -R :www-data /var/www/blog
sudo chmod -R 775 /var/www/blog
sudo chmod g+s /var/www/blog
sudo usermod -aG www-data user
replacing “user” with your username in the final command. With folder permissions granted you should now be able to copy the contents of your static site into the blog folder.
I’d recommend using sftp to copy your files. You can add a remote location in your file browser on Windows and most Linux desktops, and you’ll sign in with the same creds as you ssh in with. Also, make sure to use local links in your static site so that the same static site will work from both Tor and I2P urls.
Next, we’ll want to configure Nginx. First, delete the default site cd /etc/nginx/sites-available && sudo rm default && cd /etc/nginx/sites-enabled && sudo rm default
. Now we can add our new site. First, create the site’s config file sudo nano /etc/nginx/conf.d/blog.conf
. I created a template you can download here and paste it in, which should work out of the box if you’re following along here.
Dropdown: what the config does
The config file is fairly standard, but does a couple things differently since we’re using it as a local server that we’ll serve over Tor & I2P. First, it uses the non-standard port 8081, just so that anything trying to access content on the server won’t get anything if they try looking for a standard web server. Secondly, it blocks all traffic that’s not localhost, so nothing can access the server directly without using Tor or I2P unless we’re accessing it from the server itself (or through an SSH tunnel). Finally, it also keeps the port from showing up in URLs, which is something that can happen if we’re using a non-standard port.Now, before we call it good, let’s configure Nginx to not tell visitors what the server is running. Run sudo nano /etc/nginx/nginx.conf
and scroll down until you find the line that says # server_tokens off;
. You’re going to want to uncomment that by deleting the “#” symbol and the space between “#” and “server…”. Now it won’t tell visitors what OS or version of Nginx is running, which is useful if there’s ever a security vulnerability since would be attacker’s will have a harder time identifying what potential ways things could be attacked. With that done you can now restart nginx with sudo systemctl restart nginx
Your static site should now be up and running. You can only access it through localhost, but if you port forward with SSH using ssh -L 8081:localhost:8081 [username]@serverIP
you should be able to go into localhost:8081 in your browser and access it.
If you followed the Nginx portion of the guide your server should be running, or maybe you setup something completely different and skipped that part of the guide. Either way, we’re now ready to start making it available on Tor and I2P. Let’s start with I2P so we can take a quick break from the CLI. Assuming you have I2P installed, SSH into your machine using port forwarding ssh -L 8085:localhost:7657 username@ipaddress
, start the I2P router, and go to http://127.0.0.1:8085/ in your browser. If you haven’t already, go through the setup process.
Note: setting yourself to hidden mode will prevent you from sharing traffic, and will not require you to deal with opening any ports (http://127.0.0.1:8085/confignet if you’re following this guide). While I would generally recommend being a good netizen and participate in the network, if you’re trying to minimize the amount of resources your device will utilize it may be something you wish to enable.
Once you’re in your router console, you’ll first likely want to go into the hidden services manager and prevent the various services from running. They’re handy if you’re on your own computer trying to access content on I2P, but useless on a server. Click on each tunnel, uncheck “Automatically start tunnel when router starts”, save your changes, then go back to the tunnels page and stop the tunnel. Repeat the process for all default tunnels.
Now we can setup our own tunnel so our local server is accessible over I2P. In the tunnel manager page, click on tunnel Wizard, select server tunnel, and hit next. Choose to create an “http” tunnel, hit next again, and name your tunnel. Now we can tell I2P where the tunnel is; if you’re following along with this guide you’ll leave the IP at 127.0.0.1 and then set the port to 8081. Set it to auto start upon booting the router, click finish, then save the tunnel.
Congrats! It should be running. In the “Destination” field of the tunnel on the tunnel manager you should see something like g5lt4bvjhtyi6evknarf6srj2od2e6rcn3ld65qqnpnb6dpz5wyq.b32.i2p/
, which is accessible to any device running I2P. Try to access it via I2P on your personal computer, and when it comes up you’re all set.
Before we call it good, however, let’s quickly backup our keys. Open your I2P key backup folder in /home/USERNAME/.i2p/i2ptunnel-keyBackup/ and grab a copy of the key that matches your I2P url that you just created. That way, even if the server loses all the data on it, you can still keep the same address.
With I2P setup, let’s now setup a Tor server. As a quick side note, there’s also an official guide that you may wish to check out. Still, if you’re following along and just want to copy-paste, we’re going to deviate from it slightly here. Tor also has an installation guide for servers if you haven’t already installed it, since it’s a tad more complicated than installing I2P in a CLI environment.
With Tor installed you’re going to want to begin by editing torrc sudo nano /etc/tor/torrc
. Specifically, you’re going to want to scroll down in the file and remove the “#” from the lines “#HiddenServiceDir” and “#HiddenServicePort 80 127.0.0.1:80”. Since we are using a server that’s not on port 80, you’ll also want to edit “127.0.0.1:80” to instead be 127.0.0.1:8081
. If you are using a vanity address you’ll also want to add your keys to /var/lib/tor/hidden_service, but otherwise if you didn’t then Tor will generate keys automatically.
Save the file, and then run sudo systemctl restart tor
. Your Tor website should be running, but as you might have noticed, unless you used a custom key you don’t have the address to your site. We can get the address and backup our keys in one quick swoop, first by copying your keys to your home directory since we can’t access the keys without root perms. sudo cp -r /var/lib/tor/ ~/ && sudo chown -R USERNAME ~/tor
(make sure to replace USERNAME with your username). Now open the Tor folder in your home directory with something like sftp.
First, backup the hidden service folder, which should be titled “hidden_service” if you’re following along the guide or otherwise whatever you chose to name it. This contains your keys, which allow you to restore your site if your server ever dies. Next, open the “hostname” file in the hidden service folder (use a text editor). This contains the URL to access your new hidden service. Finally, now that you have your hostname and have backed up your keys, delete the copied tor folder with rm -r ~/tor
. There’s no point in keeping keys in your home directory like that.
Open the url you got from the hostname file in the Tor browser, and you should now have a site accessible in Tor as well. As long as you see your website everything’s complete. Congrats!
IPFS
I wrote about IPFS about two years ago, but in short, IPFS is a decentralized protocol that identifies content by hashes. Unlike something like a standard HTTP server or Tor/I2P, instead of focusing on where the content is, it instead focuses on what the content is. When you request a file on IPFS, since the hash guarantees the file you get is exactly what was requested, anybody on the network who has the file can provide it to you. Very similar to a torrent, the difference being that IPFS is focused on being one large network that connects people with others who have any file on the network, where torrents are usually focused on a group of users distributing a single file.
Note: there’s more to IPFS than just hosting a website with it, but this post is just focused on websites and such.
Benefits of IPFS
There’s a few reasons why you might consider using IPFS over a standard web server to host content. First of all, just like Tor & I2P, IPFS doesn’t rely on ICANN domain names. Outside of the key based IPNS names (I’ll touch on that in a sec), IPFS uses hashes to identify content rather than the Tor/I2P key based domains to identify locations - but it’s an identifier powered by math as opposed to a central authority non-the-less.
There’s also redundancy in IPFS, which can aid in three ways. First, you can have multiple servers hosting the same piece of content, which both forms your own little CDN and keeps the content online regardless of if one goes down or is unreachable. Secondly, even if your host goes down, if somebody else decides to keep a copy of your content, it’ll still be available all the same. Finally, if a file is suddenly highly requested - just like a torrent - those requesters will also help the network by serving the content to other requesters once they have a copy, preventing a single centralized host from being overloaded.
Further, just like Tor and I2P, it’ll work behind a NAT. Though there’s no anonymization like Tor or I2P, like most decentralized software there’s no need for an HTTP host setup with you opening ports or needing a static IP address.
However, there are some cons as well. The first thing, which is both a pro and a con, is immutability. Immutability is great when you want to serve something that never changes, or when preventing a hacker from maliciously modifying contents you’re distributing (on your server directly or while contents are in transit). However, from a website hosting perspective, it means you’ll need to work around its immutability to update your website.
Beyond something that can be both a pro and a con, when it comes to hosting sites specifically there’s different implementations that might behave differently. For example, the hash of my website (prior to publishing this post) is bafybeiacbwiip2o7puiveojzyvil63tgcx3nmlrpwxr7hjxgkgnmompwsa
. Opening that hash in ipfs.io gives a jumbled mess because it won’t load the local javascript files. Opening the same hash in dweb.link, however, will load everything just fine. If you host a site on IPFS, depending on how you do so, people may get different results depending on their means of accessing it.
Finally, there’s speed. On a standard web server, it’s as simple as querying a DNS server, then going to the IP listed. On IPFS your client needs to first figure out who has the file, then reach out to the various file hosters to request a file. That takes a lot more time, and while being able to pull from multiple hosts simultaneously may make large downloads faster, if we’re talking hosting a website it’ll be slower than a standard server.
Accessing Content on IPFS
There’s basically two ways to access IPFS: gateways and running things locally. Gateways are by far the easiest, being a server that is on the network and able to serve you content from IPFS via http. IPFS.io or dweb.link are two examples of gateways - going to ipfs.io/ipfs/hash
or hash
.ipfs.dweb.link will give you the contents of the IPFS hash through your web browser. This, of course, is super easy - and as I’ll touch on in the hosting section - chances are you’ve accessed IPFS content via a gateway without even knowing it.
However, since you’re relying on a centralized service you’re losing out on some of the benefits of IPFS. It’s not all lost; you still have a hash, so if a gateway goes down you can still go elsewhere and access the same content. Similarly, if the original host goes down, or would have never hosted it over http to begin with because of network constraints, it will still be online. Still, however, that brings us to the next form of accessing IPFS.
The other option is installing the client locally. If you install an IPFS client you can actually participate in the network yourself. While it’ll require running separate software, and it will take time for your IPFS client to become integrated with the network, running the client locally is still the best means of accessing content over IPFS. Running it locally means you get all the redundancy built into IPFS, contribute to the network by serving files, and don’t need to worry about a centralized service going down.
There are other ways to access content on IPFS too, from browser plugins to Cloudflare serving IPFS content over http as if it were any other website. But in all those cases they’re either going to rely on a remote gateway or utilize your local IPFS client.
Hosting Content on IPFS
The first thing you’ll need to do when hosting content is choose how you will identify your content. If you’re hosting fairly static content, or can get by with simply updating a hash every now and then, sharing the IPFS hash itself will work. However, If you want to have one identifier that can change which IPFS hash it points to, there’s a few ways to go about it.
First is IPNS, which is basically IPFS’s naming system. An IPNS hash is controlled by your private key and, similar to Tor/I2P, lets you direct users to the hash of your choosing. This allows you to update IPFS hashes any time you want, directing users to a new IPFS hash when you update your content. However, to host an IPNS hash your device hosting it has to be online at least once every 24 hours, and it has to be on a device you control since sharing your private keys is a bad idea (no pinning services available for something like this). However, there are also three different ways to serve dynamic content on IPFS:
- First is dns link, which is a way of adding an entry to an ICANN domain to identify which IPFS hash to go to. It’ll be relying on ICANN domains, but if you wanted to participate in IPFS and want an easy means of providing dynamic content it’d potentially be the way to go.
- Secondly, there’s decentralized domains, which I’ll ramble about in the next section.
- Finally, there are services like Cloudflare, which you can set to ‘host’ your website by serving IPFS content from their gateway. Even though the user might see example.com, it’ll actually just be Cloudflare serving content from the IPFS hash of the owner’s choosing, which can be updated by the domain owner any time they wish.
Finally, once you have your identifier figured out, now comes hosting the content. The first way is to use the client, whether it be the GUI or CLI version. Either add a file, or add an existing hash, then pin it. It doesn’t matter whether it’s a VPS, a phone7, or a Raspberry Pi behind a NAT and a regularly changing IP address - as long as you have a connection, the content will be available.
The other option, and the one I use, is to use a pinning service. No need to run a server or anything; just give them a file or select an existing hash, and they’ll keep a copy of it available on the network. There’s a lot of pinning services, most of which offer free plans (which offer plenty of bandwidth to host a simple static site). I personally use Pinata, which offers 10g of bandwidth a month for free - something I don’t expect to ever get close to using up.
My website on IPFS is bafkreigqa6leyslcjjscaxzruqttqjevmb6uhlgmken5zxng4y72kha7ga
, which as you can tell isn’t really my full website - just a simple landing page, which I did for two reasons. First, mirroring my full site would likely break for a lot of people. The most popular gateway ipfs.io doesn’t work with a website referencing local files within the IPFS folder, which means that a lot of people would probably open it to find it broken. Secondly, unlike Tor or I2P where it’s just sftp some files onto a remote server to update the site, it’d be more effort to keep updating an IPFS website.
Decentralized Domains
POV you realize Nate’s going to talk about NFTs, then realize it’s going to be in a positive light.
Alright, hold your horses; let’s talk about definitions. NFT stands for Non-Fungible Token.
- Non-Fungible just means that each individual ’token’ is unique. A dollar bill is fungible; regardless of which physical bill you have, it holds the same value. Something like a domain is unique, and it is important to keep track of who owns which one. A bank doesn’t need to track which specific dollar bill belongs to who, just who has how much money - while a domain registrar needs to know that I own mecca1.net and Google owns google.com.
- A token, in this context, is just an entry in a blockchain.
- A blockchain is a database, broken into segments for easier distribution, that is then distributed among a bunch of devices participating in the network it’s on.
So yeah, this is very different from something like the bored ape yacht club. They use the same technology to identify ownership, but that’s where it stops - an apt centralized equivalent would be comparing an ICANN domain to an entry on a centralized SQL database that said you owned a Pokemon card.
Decentralized domains, like I’m talking about now, are actually almost identical to a standard ICANN domain. You make a payment to rent or buy a domain (some decentralized domains are rented, some are outright owned), often ~$3-$10, then an entry is created in a database stating you own it. The difference being that the fee went to reward the network of computers hosting said database (and the domain’s previous owner if you bought it from them) as opposed to a centralized registrar; the network answering to the consensus of the devices on it instead of a centralized authority. You can then choose where to point the domain, and that information is again spread across the same decentralized network - as opposed to being spread across DNS servers at the behest of an ICANN registrar.
Different Decentralized Domains
Alright, beyond the explanation of ’they’re not NFTs, at least not what the average person thinks of NFTs’, there’s a lot of different decentralized domains which act fairly similar. .eth is probably the biggest one, offering the ability to rent a domain for $5 a year (with the exception of short domains, which sell for a premium).
There’s quite a lot, however, and many are permanent. Most other domains will run between $2-$20 for longer domains (again, most charge a premium for smaller domains), and then once you purchase them they’re yours forever. The permanence is definitely something I’m a fan of; the idea of losing my domain either because I forgot to renew it or a central authority had an error is not fun. Asymmetric encryption is a good way of owning your own identity without needing any authority, centralized or decentralized, but a human memorable domain that’s truly mine is neat.
Finally, one random thing of note, Brave recently launched their own decentralized domain. The domain itself isn’t too special; it works just like any other decentralized domain8, but according to them, they’ve submitted an application to ICANN to have it work as a standard domain. While I’m guessing the chances are somewhat slim, it’s probably not impossible since Google and Microsoft could claim domains of their own, and if on the slim chance it went through then it’d be possible to own a decentralized domain that would work with normal DNS.
Accessing content
Accessing content on a decentralized domain is fairly simple, with some browsers like Brave and Opera having built-in support for some domains. Otherwise, installing the MetaMask plugin will allow you to resolve .eth domains and installing the Unstoppable Domains (either as a standalone extension or as a ‘snap’ for Metamask) will allow you to resolve most other decentralized domains6. If the domain owner sets an IPFS hash for the domain, entering that in your address bar will open the content - redirecting you to an IPFS gateway if your browser doesn’t support IPFS, or acting however you set your browser to handle IPFS if it does.
Hosting Content
Hosting content is pretty straightforward. You’ll probably want to use ens.domains for an eth domain, or Unstoppable Domains for most other ones9. However, I personally haven’t purchased a domain from ens.domains so I’m just going to cover what I did to create an IPFS based site on a domain from Unstoppable Domains. The process of purchasing a decentralized domain from Unstoppable Domains is nearly identical to purchasing a regular domain, with the exception of managing ownership.
Just as a heads up, remember, generally longer domains are cheaper. If you’re just looking to toy around I’d recommend getting something longer for $2-$5 rather than splurging on something short. here are the domains Brave supports (.brave coming soon), and here are the domains Opera supports.
You can own a decentralized domain in two different ways. The first, which is probably the best if you just want to toy around with them, is to use Unstoppable Domain’s custodial wallet. Basically, Unstoppable Domains will hold and manage the private keys of your domain by default, letting you use it without needing to interact with anything more technical than making a payment and pasting in an IPFS hash. Otherwise, however, you can connect your own wallet to your account via something like Metamask or Brave Wallet and manage your own keys - very much recommended if you’re more technical and/or want to be 100% sure you own your domain.
Otherwise, once you’ve decided whether or not to connect your own wallet (remember, you can always transfer in and out of self custody later) you can purchase a domain just like purchasing an ICANN domain. Once you have a domain, go to the My Domains section, click on your domain, and click the Website button on the sidebar. Click Manage, and set the IPFS hash to whatever you’re looking for.
Just like I mentioned in the IPFS section, any website that requires local links may break depending on the user’s setup. Best bet, especially if you just want to toy around with them, is to keep things a simple single HTML file. Some people choose to have an HTML file that just redirects the user to their normal domain, although I chose to make a simple about style page with links. I wound up purchasing a couple, which you can check out below:
Microblogging protocols
I was drafting this a few months ago and then got busy and stuff, then started working on it again in early June and saw hzrd149 made a custom Nostr NIP for static sites as well as nsite.lol. I was already going to mention using various microblogging protocols as an alternative to distributing blog style content, but this is a whole new way as well, so I’ll discuss it separately.
Standard microblogging protocols
There’s three big microblogging protocols out there right now: ActivityPub, Nostr, and AT. There’s pros and cons to each, but right now I’m going to be focused on just using said protocols as an alternative means to having a standard blog like website.
Nostr is hands down the most effective means of having something that resembles a blog that’s not part of the standard http + icann setup - even setting aside nsite. User identifiers are key based10, resulting in fully user owned identifiers. The network itself is decentralized, allowing you to publish content on any relays of your choosing (well, assuming the relay allows you to), so even if a relay goes down the others you’re using will mean that people can still see your content. Finally, Nostr is a lot more flexible, which is very good when trying to use a protocol mostly focused on microblogging for longform content or a website. Regular ‘microblog’ posts have no character limit, and there’s a NIP (alternative way to parse data) which is dedicated to long form blogging (supported by many clients and some RSS readers). There’s also plenty of other capabilities like video/livestreaming, so it’s pretty flexible in that regard as well.
ActivityPub also makes it possible to have a semi alternative website setup. Usernames are ICANN domain based, and the protocol is made up of individual centralized servers that can communicate, so you don’t quite have the decentralized aspects of many of the other protocols I’m yapping about today. You can still, however, join servers specifically designed for long form content (or video content, music sharing, etc) and then publish it there. Then, of course, anybody with an Activity Pub account can fetch said content and consume on their server. There are sometimes issues with compatibility - reading longform content in a microblogging app is rather inconvenient, and some things like a PeerTube video will require you to open a link and watch it in your browser. Still, it’s a way to get content outside of the standard website + RSS fashion.
AT, Bluesky’s protocol, is lagging a bit behind in development so the options on it are a bit limited and may change soon. Profiles are identified by keys, however, they’re located on PDSs and read on Relays which are centralized - meaning you get decentralized IDs though it’s effectively hosted and consumed on two separate centralized services. You can potentially do a lot of different things on AT, as each service can set a Lexicon to determine what kind of posts are allowed. So, while standard Bluesky posts might have a char limit of 300, it’d be possible to create a blogging platform with no limits on the size of posts. However, that’s all theoretical; I’m not aware of any services on AT that aren’t either microblogging, Reddit style communities, or short form video. Lexicons also cut both ways - if two different services have two different lexicons they won’t be compatible, making something like a potential blogging platform rather isolated.
Dedicated blogging platforms
This is sort of straying away from what I’m focusing on in this post, but if you wanted a more standard website that integrates decentralized social media protocols there’s also a few ways to go about that as well. Something like WordPress with an Activity Pub or Nostr plugin enabled, a self hosted microblog.pub instance (Activity Pub), or a npub.pro site (Nostr) would allow you to have a regular website while utilizing the protocols. This post is mostly focused on non-standard server setups, not a standard server that could use ActivityPub/Nostr as an upgraded RSS, but it’s still worth bringing up.
Nostr’s nsite
Unlike publishing longform content in a blog like fashion on something like Nostr’s NIP-23 or WriteFreely (Activity Pub), the brand new nsite is a lot more along the lines of IPFS. Nsite creates simple static sites identified by your key - though it can be used with GitHub pages as well. Since you’re identified with your key it’s free of ICANN domains, and since you can use any combination of hosts it’s decentralized and doesn’t rely on a single centralized server. Unlike IPFS, however, since the content is identified by your key and not the content’s hash you can update the content whenever you wish.
Accessing an nsite is nearly identical to accessing IPFS content over a gateway (likely will also be possible in clients at some point, though I’m not aware of clients that have implemented it yet). Simply going to npub
.nsite.lol
or npub
.nostrdeploy.com
will pull up the contents of the nsite in your browser - offering a standard website served over a decentralized protocol and using a decentralized identification (albeit served over a centralized gateway atm). For example, going to me on nsite or nostrdeploy will pull up mine. Replacing my NPUB with somebody else’s will pull up theirs.
Hosting content is fairly straightforward, although it does require installing a CLI client and using a new or existing Nostr profile.
Dropdown: Creating a Nostr Profile
If you’ve never used Nostr and just want a profile to host a static site with, your best bet is to generate a keypair at nstart.me. Fill out your profile information and you’ll be provided with an NPUB (public key) and NSEC (private key). Save and backup your private key, skip having a backup emailed to you (I assume if you’ve gotten this far in a blog post about math based identifiers you know how to back up a private key), and then decide whether you want to create a bunker link or not.
A bunker is something that can sign data on behalf of other software, meaning software like the nsyte client can publish events signed by your private key, but never actually gets to read your private key itself. There are bunkers you can run yourself like Amber, and you can skip using bunkers altogether and just use a private key (or another method like a browser extension, albeit that won’t work with the nsyte client). Still, if you’re just looking to set up an nsite then I highly recommend using nstart’s frost bunker. Once it finishes generating your bunker url, copy that and back it up just like your nsec.
Once you get the bunker URL, nstart will ask if you’d like to follow anybody, listing some prominent Nostr users and allowing you to follow everyone they follow. You can if you want, but I’d recommend leaving everyone unchecked and continuing. If you’re only using it for your nsite it won’t matter anyway, and if you want to use the account later you’ll probably be better off manually following people or using a more fine tuned following list.
In order to setup your nsite itself, we’ll first need to install the nsyte client. Start by running the script on nsyte.run, running it either on your host OS or in a VM. It’ll detect what OS you’re running and install the client for you. Next, run nsyte init
to set the details of your site.
- When it asks you how you want to manage your private key, choose to use an NSEC bunker and paste in a bunker URL (use the one you got from nstart if you followed the registration guide above).
- It will then ask you to name and describe your website, which you can fill out.
- It will then ask you to choose your relays, followed by your blossom servers. If you just created an account I would recommend using all of them, but if you’re a longtime Nostr user choose your favorites.
- It will then ask you if you want to publish your profile information. This will overwrite your profile name and description with the name and description you provided. If you just registered and want to use the profile for only the nsite, choose yes. If you’re using a personal account, or using a new account you plan to use for more than the nsite, choose no and manage your profile in a standard Nostr client.
- It will then ask you if you would like to publish relay information. Again, it’ll overwrite your existing relay information every time you update your website. Choose yes on an account dedicated only to an nsite, choose no for all other accounts.
- Then it will ask you if you wish to publish your blossom servers. Again, it will overwrite your existing configuration, so choose no if you want to manage your blossom servers manually. However, I’ve personally never set any blossom servers in general, so if you don’t know what they are or do but never set any choose yes whether or not you’re on a personal profile or one dedicated to an nsite. Choose no if you want to manage your default blossom servers manually.
The initialization should be complete, and you are now set to use the client to upload a static website. Make a folder, place the contents of your static site in it, and run nsyte upload ./folder
to upload the content. Repeating the command after modifying the contents will update your site. You should now have a website, which you’ll be provided a link to by the CLI tool.
Gemini, gopher, etc
Gemini is often pushed as a good alternative to your standard web server in the indyweb/smolweb community, however, I’m actually going to trash on it a bit. Now, if it works for you that’s great, and I started this post off with an iambic-pantameter-meme-word-filled sonnet, so don’t take this post as anything more than me having fun rambling about things I like.
Anyway, Gemini’s claim to fame is that it’s intentionally bare bones; lacking javascript and modern web APIs. I get it, we’re all annoyed by javascript powered pop-ups, tracking, and ads; the goal of Gemini being to avoid all of that by hamstringing what a Gemini pod can be. However, I see it as the Luddite approach to things, thinking the problems of the present can be fixed by going from Web 2 back to Web 1. The problem with going backwards is you create a whole host of problems, problems that were solved by Web 2, and at the same time you can serve a Gemini pod style site over HTTP as well.
Some drawbacks in itself aren’t a deal breaker, but again, it doesn’t bring anything new to the table whatsoever. Of the above protocols, most have the capability of doing some or all of the following: using non-centralized identifiers, hosting content without a static IP or open port, and providing built in redundancy. But want a JavaScript free website? Serve it over Tor/I2P/IPFS/nsite and just don’t put JavaScript in it - or serve it over something like Nostr NIP-23 (markdown only) or AcitivityPub/AT-Proto (generally plain text).
I guess my philosophy here is that, if you’re looking to use something that differs from what the web is now, ideally look for the options that solve problems in novel ways, rather than just removing old solutions to already solved problems.
Conclusions
One thing you’ll probably notice is that, out of the eight different alternative hosting options, I only host my website & blog posts on two of them. I’ve got a simple splash page on three of them, and the other three are microblogging protocols which I only use for microblogging (using Nostr fairly regularly, ActivityPub occasionally, and AT fairly rarely).
My philosophy on it is mostly to try and at least dip my toes in all of them, hoping that utilizing them might show support and help their adoption - and also hopefully provide some value to people who are using them (at least if you accept the premise my content brings value). While some will likely remain forever niche (heck, I2P is almost as old as I am and it’s still fairly niche) - if one or two could hit critical mass (even just within the tech nerd sphere) I’d love to be able to contribute to it by participating and talking about them.
That said, have fun. It probably makes me weird, but playing around with this sort of stuff is fun for me. If you wanted to dip your toes into alternatives to a standard server, pick one and try something easy. Create a tiny splash page on IPFS (possibly associating it with a decentralized domain), and/or upload it to the Nostr network. Both would probably take less than five minutes in between having an html file and having a site. Or maybe try setting up an I2P site on an existing home server, or just start pasting your blog posts into Habala (Nostr) or WriteFreely (Activity Pub).
If you do wind up setting something up, or already had something setup, I’d love to hear about it. But anyway, hope you found the “Nate talks about protocols he likes” post interesting.
Footnotes:
-
Can’t have anything too high brow on my site, so signing off with “Skibbidi” fixes that. ↩︎
-
Unless you’re using a CDN. Though if your server needs to reach out to other servers, said CDN still won’t protect your existing IP. ↩︎
-
It’s easy(ish) to get a list of all Tor relays and block them, but it’s nigh impossible to block Jimbob Goober’s laptop that just turned on an hour ago and started routing traffic. I’ve seen it first hand when, behind a restrictive firewall without running a VPN, Tor fails but I2P works just fine. Tor can get around this with things like bridges, or more recently, Tor Snowflake, which takes random end user devices to use as bridges. ↩︎
-
I2P outproxies exist, which is effectively like a Tor exit node - a server that lets you retrieve clearnet data from behind I2P. Unlike Tor, however, it’s not really the focus of the network and outproxies can often be extremely slow or unreliable. ↩︎
-
Yes, this will make you more fingerprintable as opposed to the Tor browser, but I wouldn’t worry about it. We’re not looking to become criminals or undercover agents, we’re trying to read a blog on a different protocol. ↩︎
-
Quick note, often times your browser won’t detect non standard domains, even if you have them set up to be capable of resolving them. Adding a slash to the end of the domain will usually fix that, such as “example.i2p/” ↩︎ ↩︎
-
An Android phone running something like Termux would make that possible. ↩︎
-
The support for resolving them is not yet implemented in the Brave browser; it’s supported in the nightly builds and is expected to be fully implemented in the regular version in Aug. 2025. ↩︎
-
If you’re looking to try out a decentralized domain but just want to toy around with one, I highly recommend buying a relatively cheap one from Unstoppable Domains that’s yours forever. ↩︎
-
You can optionally setup a NIP05 username, which uses ICANN domains (e.g. mine is [email protected]). The domain based username, similar to DNS link in IPFS, is a way to use a domain to give you a human rememberable username that ultimately still points you to a key. ↩︎