Michael McAnally

Nov 27, 2021

23 min read

Setting Up A Raspberry Pi As A Home Metaverse Server For Your VR Headset!

Raspberry Pi Model 4B 8GB installed on my home network in a 3D printed case with a Noctua NF-A4x10 5V PWM fan

After posting this article I received many questions about what is this for? Why would you want to do this? Well, these are good questions. Let me explain deeper the reasoning . . .

It’s a great development environment, and anything you build can be moved to more powerful servers in the cloud for production hosting. The Raspberry Pi has sold over 25 million machines, the best I can figure from the internet.

It has a very large “Maker Community” with a great following, and support. Also, Network-Aframe, which is a multi-user version of VR talk with WebXR, and WebRTC, enabled in a browser, allows you to communicate inside a VR headset. So setting that up with the Pi on a home network provides for “no additional cost hosting” (since you already pay for your internet connection anyway), and no latency response over wi-fi (say with an Oculus Quest 2) locally. But still, all accessible over the internet too.

I believe it to be an elegant, affordable solution for someone on a budget, or who just likes to tinker, as well as a great learning tool for those wanting to code VR for the Metaverse, OASIS, whatever.

Ultimately, this little metaverse server on a Pi has the potential of opening up and combining VR with IoT for the home, and edge computing, possibly even AI, if paired with something like a Google’s Coral, or integrate with Nvidia’s Jetson or Xavier in future articles.

I know that is a sort of the big picture answer, but that’s the best way that I can explain it. Besides, why should the big players own the Metaverse? Isn’t it for everybody? Even the little guys?! Or should I say, little Pi.

Have a slice on me.

================

This is my seminal article.

It is a long, complicated setup, and very technical. That’s just the way it has to be. Setting up this “Home Metaverse Server” for the first time is a bit of a challenge, and simply no trivial matter.

This little Pi, in the picture above, serves up virtual reality pages to a VR headset (such as my Oculus Quest 2).

Putting on your VR headset, and connecting to your router wireless (you already do this), will allow you to access VR locally on your LAN (local area network), through the internal VR browser. Latency issues will no longer be a problem. It will load VR enabled web pages fast. Faster sometimes even than across the internet.

It’s when you serve those pages to others, who access them from across the internet, then they will see loading delays. Dependent upon their internet connection speeds of course, and the number and size of the VR files you’re serving up.

Why would you want to do this? Say you might want to do this for VR Chatting -i.e. talking to each others over VR and the internet, all from inside your separate VR headsets. I have tested this half way across the world with 5 people, and there are no significant delays in audio when properly configured. This functionally can be done when we later install something called Networked A-frame, or sometimes abbreviated to NAF for short by the community of developers.

Just to be clear, slower access over the internet is not the Pi’s fault. This is because most likely your cable/internet provider is throttling your upload speeds. You can always download stuff faster than you can upload. You can check your internet speeds with a DSL speed test.

Adjusting your “upload speed” with the cable/internet provider will mitigate the delays.

What you’ll need to proceed:

A Raspberry Pi Model 4B (preferably 8 GB).

A home network in which you have access to the router for configuration of port forwarding.

Long enough Ethernet cable to plug into your router.

Power supply for the Pi (make sure you get one for a model 4B, UL Listed 18 Watts 5.25 Volts 3.5 Amps USB C Cable Power Adapter).

A good case with fan for active cooling, or a really good passive cooling heatsink case. The first time I 3D printed a case with a Noctua NF-A4x10 5V PWM fan. Now, I’m using an Argon NEO Raspberry Pi 4 Case. I just got tired of hearing the fan noise.

Read the reviews for the best Pi cases and choose a good one, because we may overclock the Pi in a future article. We don’t want the Pi underclocking downward speed while it’s serving web pages under heavy loads.

A Male Micro HDMI to Male standard size HDMI to plug into the back of a monitor or TV. I used a size converter cable, and joiner to do this, there are a number different ways. Just check the gender and sizes for the correct connection.

A keyboard and mouse connected to the Pi initially, because we are going to type a lot of Linux terminal console commands. A lot! You can copy and paste from this article to assist you.

A fast large capacity Micro SD for the 64 bit OS we are going to install and configure on the Pi. I suggest a SanDisk Extreme 64 GB (they are running about $15 at the time of this writing). You may need the extra capacity to host 360 files and videos and other VR large files. This is not a 2D webpage we will be serving up. This is 3D x-y “and” z axis VR files, along with 3D models which can be large. Besides, it’s always better to have more storage, than less.

We will eventually move it all to a SSD for more permanent serving, but for now this will more than do.

Finally, you will need a domain name ( I bought mine from https://www.namecheap.com/ ), but you can get one from many sources on the internet. This domain name will be configured (manage) to point to your LAN router IP address so that others on the internet will be able to see your VR enabled pages too when they select them from within their VR browsers headset.

PLEASE DO NOTE: I can’t take responsibility, if you get stuck, or wrongly configure your network, or zap the life out of your little Pi, or leave security holes open. Or any of the other things that could go wrong along the way. That’s my disclaimer, upfront and center, you take full responsibility for your actions while carefully following these instructions in this article. By following the steps in this article you consent to this agreement.

So, are you ready to begin?

First, I’m going to have to assume you have some experience in Linux. If not, there will be a steep learning curve, not impossible, but definitely be aware.

Now, what I can do along the way to help, is refer you to articles and videos, which will aid you in understanding the detailed setup of the software architecture we will be going through.

Step 1: Install your Pi into a case.

Watch this video, but stop at 3:47 minutes into the video. We are going to install a different 64 bit OS in the next step.

https://www.youtube.com/watch?v=KM8qWEJTXiw

Step 2: Install a 64 bit OS on the Pi.

NOTE (an update): Something has changed — I had trouble finding the OS through the Pi installer, so you can find it here (link below), just use the custom install option after the download to you PC. You are looking for the Ubuntu Server 20.04.3 LTS (64 bit) version and then after writing the OS to micro SD move on to step 3.

===

Use the Raspberry Pi Imager mentioned in the video above.

Choose OS

Other general purpose OS

Ubuntu

Go here to image the Ubuntu Server 20.04.3 LTS (RPI 3/4/400) 64-bit server version for your Pi. It’s further down and will have long term support until April 2025.

Now proceed with choosing your storage, which will be the Micro SD card mentioned above, and WRITE.

You should now have a 64 bit OS on the card. Insert into the Pi and power on. Wait for it . . . Sometimes things have to settle first before you can proceed as mentioned in the video below.

Step 3: Installing a desktop

Follow instructions in this video. You can start at 1:54 minutes into the video if you want, up to 6:47 in the video. It visually shows you Step 2 above and then installs the desktopify desktop. I chose the standard ubuntu desktop distro. You can leave the video at 6:07 minutes. You will have a Desktopify Desktop Ubuntu 64 bit Server setup on your Pi.

sudo apt updatesudo apt upgrademkdir desktopifygit clone https://github.com/wimpysworld/desktopify.gitcd desktopifysudo ./desktopify --de ubuntureboot

NOTE update: “sudo apt upgrade” now appears to be happening in the background, so you may not need to execute that command line specifically. I left it in for completeness.

Please be patient, these commands will take a long time to complete. Unfortunately, there is no preconfigured image for this at the time of this writing for the Pi. It’s probably best that you create it from scratch anyway.

Meanwhile, you are welcome to read ahead to prepare yourself by watching the videos (at the time indexes indicated), and perusing the linked articles.

Congratulations, you now have the Pi operating system setup.

Step 4: Installing Apache webserver with a LAMP stack

First the software architecture . . .

We are going to do more than just install the Apache webserver (a very well established and documented webserver). We are going to install a developer stack called the LAMP stack.

The LAMP stack means (Linux, Apache, MySQL and PHP, or Python, or Perl). It’s a well established and documented stack with loads of applications, and many examples.

There are of course other excellent stacks out there, some of them use Nginx.

This will eventually be our stack once the article is complete

However, I chose this one primarily because I’m going to want to run a database for my CMS (Content Management System) with Apache, in a future companion article building upon this one.

You may ask, why would you want to use a CMS? Because, when you are inside a VR headset, the last thing you enjoy doing is typing in a long and complex URL to visit a site. So you should put those links inside a web page for clicking/selecting on, to reduce virtual keyboard input from within the headset.

Later on, when you have many links, many pages to create, and a website to maintain for your VR metaverse server, I think you’ll thank me. Because, once you learn how to use a CMS, its so much easier to create and manage website html files, than with just a simple text editor. However, if you don’t want a CMS, that’s ok too. The CMS install will be in a future article anyway.

I’m also going to substitute MariaDB for MySQL. MariaDB is a fully compatible drop in substitute for MySQL for our purposes and uses nearly all the same commands.

Ok, I’m going to refer you to three articles and one long video, and then show you the commands I used. Don’t do any commands just yet. Just look at and study over the material first, please.

Sorry, for the long videos and reading assignments coming up, but its best to be prepared before we start typing lots of commands on the terminal. You will have a chance at understanding the commands you are typing. Which is always a good thing.

Start at 3:52 minutes into this video through 22:56 minutes to begin the install of the LAMP stack to your Pi on Ubuntu OS 64 bit server, don’t install on Raspbian or Raspberry Pi OS, as we already installed Ubuntu, because we are going to install like we are in “a production environment”.

https://www.youtube.com/watch?v=8FyqyO-k16M

https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-ubuntu-20-04#step-5-%E2%80%94-setting-up-virtual-hosts-recommended

https://www.linuxscrew.com/lamp-stack-ubuntu-raspberry-pi

https://www.tecmint.com/install-drupal-in-ubuntu-debian/

I will point out that the main difference is that we will be substituting MariaDB in our specific setup along with a configured firewall, and virtual hosts for Apache, as well as later article installing Drupal CMS.

===================

Now we are ready to actually start!

===================

COMMANDS TO BE TYPED AT THE TERMINAL

sudo apt-get install apache2

Now open a web browser on the Pi and type 127.0.0.1 in the address. You will get the Apache default web page, showing the webserver is serving webpages locally.

Good. Apache webserver is installed, and now working.

Now back to the terminal . . . for more commands. Some long ones! You can copy and paste them now from this article into the terminal.

sudo apt-get install apache2 mariadb-server-10.3 mariadb-client php  libapache2-mod-php php-cli php-fpm php-json php-common php-mysql php-zip php-gd php-intl php-mbstring php-curl php-xml php-pear php-tidy php-soap php-bcmath php-xmlrpcsudo mysql_secure_installationsudo mysql
Inside MariaDB MySQL compatible database

Set the root password and write it down so you remember it later. Remove anonymous users and disallow remote login. Remove test database. Reload privilege tables. Type

sudo mysql

Now you will be at a MariaDB (MySQL) prompt:

Congratulations, you now have a database server installed. We are not going to issue any database commands a this time.

Type

exit

To get out, and back to the terminal.

We will configure the database further in a later article for our Drupal CMS install.

sudo chown -R www-data:www-data /var/www/sudo chmod -R 777 /var/www/cd /var/www/htmlls -l

Now you have ownership of the /html directory where files from the webserver are served from to the internal network and eventually to the outside internet.

Ok, let’s install one of my favorite graphical text editors. That would be Sublime. Type at the terminal

sudo snap install sublime-text --classic

Using the Sublime graphical text editor (please use this text editor throughout this document), create the following file:

<?php
phpinfo();
?>

Save that filename as info.php into the /var/www/html directory of the webserver.

Now go to your browser on the Pi again and type 127.0.0.1/info.php

This will give you a PHP Info screen confirming you have a working PHP language.

sudo chmod -R 755 /var/www/cd /sudo service apache2 restartsudo systemctl enable apache2

We now should have all the rudiments of our LAMP stack installed. Ubuntu (Linux), Apache (Webserver), MariaDB (MySQL compatible database server), and PHP (programing language).

Good job! On to the next steps . . .

Step 5: Configuring the firewall and getting your IP address and default gateway IP address (router IP)

Let’s get our Pi’s IP address which was given to us by the internet provider most likely as a DHCP process (not important to understand for this article, but included to be complete). It’s only import for you to know that your IP address is “a leased IP address”. It’s not a static IP address.

At the terminal type

sudo hostname -I

Write it down or take a picture of it with your phone. This is the IP address assigned to your Pi at this moment.

Now lets get our router’s Default Gateway IP address. There are ways to do this on various computers.

Write down your default gateway IP address. Note it will not be the same as the Pi’s IP address.

Ok, keep those for later, and let’s now configure the firewall.

At a terminal again, type:

sudo ufw app list

We want Apache Full because we are going to configure a free SSL certificate later on. We absolutely need it for our Metaverse VR server which will primarily use A-frame for the VR part. So type

sudo ufw allow 'Apache Full'sudo ufw allow 443sudo ufw allow 3000/tcp sudo ufw allow 3000/udpsudo ufw allow OpenSSHsudo ufw allow from any to any port 3389 proto tcpsudo ufw statussudo ufw enable

We have enabled the Pi’s internal firewall along with the ability for a Remote Desktop session (say with windows remote desktop if you prefer). At this point I found it was best to logout, power off the Pi, and reboot fresh. Then, back at the terminal type:

sudo apt install xrdpsudo systemctl enable --now xrdp

We still have a lot more to configure . . . Take a break if you need to in this terribly long article (at least you didn’t have to write it), but remember where you left off at.

Step 6: Purchasing a domain name and configuring domain name records

I will not go over the basics of purchasing domain names in this article (there are already many many articles on the internet for this), only how to configure the domain name records needed to point to the Pi on your home network and the port forwarding necessary inside your router. That’s hard enough.

Some basics . . .

Network diagram of configuration with annotations

Your router is responsible for determining which incoming traffic is allowed into the network, and which device it should be sent to. In a typical home network, devices connected to the router are invisible to the outside world. Only your router can be reached from outside, using your network’s Gateway IP address (an external visible IP address).

However, if the router receives incoming traffic that is not part of an open connection (for example, when an outside device attempts to initiate a connection with an inside device, say on a specific port that is not open), it will block the incoming traffic from crossing into the network. This is an important security feature to protect your network!

So how can you connect your Pi webserver to the outside internet? The answer is port forwarding. The router must be configured to allow incoming connections on specific ports to pass through, and be sent to the correct device (in this case the Pi). The HTTP protocol uses port 80, and SSL (or HTTPS) uses port 443. We will also be allowing port 3000 pass through to the proxy Node.js process we will be setting up on the Pi later.

So armed with this information, let’s buy a cheap domain name to manage. Pointing it to the Gateway IP address of our router first. As I said earlier, I bought one on Namecheap.com I am not affiliate with Namecheap, nor do I receive any benefit by mentioning them.

To make this easy, I will give a screen shot of my managed domain records for the domain I purchased VRmetaverServer.org

Notice, I am using the Advanced DNS tab above, and the Add New Record button

After purchasing, and creating your new domain, search for the mange button. This will allow you to add records to the domain. You will need two A Records, and a CNAME Record:

A Record          @      IP Address of Gateway       TTL valueA Record         www     IP Address of Gateway       TTL valueCNAME Record      @      Domain name                 TTL Value

Creating the records does not mean they will work immediately. DNS Propagation delays exist.

Step 7: Configuring Apache with your domain name and Virtual Hosts

Virtual Hosts should be setup on Apache. Type this at the terminal:

sudo chmod -R 777 /etc/apache2/sites-available/

Open and edit the following file:

/etc/apache2/sites-available/000-default.conf

in a sublime editor.

<VirtualHost *:80>
ServerName your_domain
ServerAlias www.your_domain
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Change everywhere there is “your_domain” to the actual domain name you purchased and setup earlier. Example, if your domain name was example.com.

You would replace it with:

<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Now save the file.

Now we are going to create another virtual host for our Node.js Networked-Aframe process. Create this file in sublime editor. Replacing example.com with your domain name.

<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full

<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
</VirtualHost>

and then save it to

/etc/apache2/sites-available/

under the file name NAF.com.conf

Now, at the terminal type

sudo chmod -R 777 /etc/apache2/

Now we are going to edit the apache2.conf file. It can be found in /etc/apache2/

Open it with sublime text editor and scroll down to fine the area labeled Global configuration. Just below, on an uncommented line type

ServerName myVRserver.example.com

Replacing example.com (see image below) with your domain name, as before. Now save the modified file and close the Text Editor.

We will test for configuration errors . . . Should say OK.

sudo apache2ctl configtest

Now we will clean up and restart Apache

sudo chmod -R 755 /etc/apache2/sudo a2enmod proxy proxy_http rewrite headers expiressudo a2ensite NAF.com.confsudo systemctl restart apache2

Step 8: Port forwarding on your router

This next part is both tricky and important that you get it right. It’s all important of course, but this one especially.

My routers port forwarding configuration page

You see, it’s hard to explain because there are so many different routers out there, each with their own configuration menus and pages. But to put it simply, you will need to open/forward the following ports to your Pi’s IP address. That’s the first one I had you write down. The ports will be:

Port 80 on TCP                         to Pi IP AddressPort 53 on UDP  (forgot this one...)   to Pi IP AddressPort 443 on TCP (SSL)                  to Pi IP AddressPort 3000 on TCP                       to Pi IP AddressPort 3000 on UDP                       to Pi IP address

All these ports will pass through to the Pi’s IP address which is assigned for that computer on the router network.

Search Google for how to do port forwarding on your specific router model.

port forwarding “your router model number” 

To help, one of the most popular cable providers in the USA is Comcast. The Comcast Xfinity router configuration should be here somewhere.

I have a separate router from my cable modem, so I didn’t use that, because some are combined routers, and modems together. Having a separated router may be easier, and give you better control than you cable provider probably wants to give. Good Luck!

Testing to see if it works

Now the test to see if it works is fairly easy. Go to a computer on your LAN (that’s connected to your router or a phone that is using your router wi-fi). Open a browser and type in the IP address of your Pi. It should show you the Apache Default page above.

That means the Pi is serving locally on your router. This should work inside your VR headset’s browser as well, go ahead and test it.

Now to test on the Internet, probably use your phone again, but disable the wi-fi so it goes through the data plan on your phone instead. Type in the domain name you purchased, and setup earlier. If you see the same Apache default page then, good job. It works over the internet!

If it doesn’t work. You will need to troubleshoot. Check your Pi’s IP again from the terminal. Check your router gateway IP is correct. Have you allowed for DNS propagation delay?

hostname -I

Then compare that to the settings on your router’s port forwarding page. Does everything match as it should?

I had a problem, where when I updated the rules for port forwarding, my router rebooted, and the DCHP gave me the next IP address up, otherwise plus 1. So I knew how to fixed it. By adding 1 to the last number on the IP before the router would reboot. Tested it, all good.

I hope you don’t have this specific problem, or any other in fact, because I won’t be able to help you out; beyond what’s written down in this article. Just be patient, and trouble shoot logically, thinking through the network diagram above. Double check your domain name records as well. Maybe, getting a friend from outside your LAN, and over the internet to test can be helpful.

Step 8: Installing Node.js as a proxy from Apache with a SSL Certificate

Now we are going to install Node.js with an Apache proxy. Let’s just make sure everything is updated first.

sudo apt update && sudo apt install nodejs npmnodejs -v

That will have installed Node, npm, and given you the version number.

Now we are going to get a free SSL Certificate with Let’s Encrypt Certbot.

sudo apt install certbot python3-certbot-apache

Prior to executing Cerbot, I should let you know you’re going to be asked a number of questions . . .

However, the most important answers to the questions you will be asked are:

Enter to select both domains listed.

Yes select 2. Redirect, you want to redirect traffic to the website to HTTPS

Now, at the terminal type:

sudo certbot --apache

That should have installed your SSL Certificate for Apache. You can test your domain on the internet with https:// It will show a lock on the address bar for the Apache default page.

What you have now is a LAMP webserver on your Pi, with SSL enabled, and Node.js installed. Next we are going to load and configure NAF (Networked A-frame) for the “multi-user VR capabilities” functionality next. Good job, so far!

Step 9: Setting up Networked A-frame (NAF)

Now we are going to setup Networked A-frame. This is the magic software which will allow us to VR talk across the internet, and do more. For an example of “what is possible”, checkout Mozilla Hubs. The software for doing this is “essentially similar”, but less developed in some functional capabilities, because it is a platform of integrated components/capabilities by an organization with an established community, as compared to a single little Pi running on your home network. However, we will get into that in subsequent articles. Onward . . .

At the terminal, get the networked-aframe from GitHub

git clone https://github.com/networked-aframe/networked-aframe.git

After NAF is installed, type

cd networked-aframenpm installnpm audit fixsudo apt-get install -y webpack

Under /networked-aframe/server/ find and open the file easyrtc-server.js in sublime editor.

We are going to modify this file to read the SSL certificate configured with the Certbot earlier and reply encrypted to the reverse proxy on port 3000. Replace the entire contents of this file with this source listing then change the YourDomainName.com on lines 9 and 10 with your domain name instead. Now save the file. Https will be used instead of http. This is necessary for the a-frame VR pages to be fully functional.

// Load required modules
const https = require("https"); // https server core module
const path = require("path");
const express = require("express"); // web framework external module
const socketIo = require("socket.io"); // web socket external module
const easyrtc = require("open-easyrtc"); // EasyRTC external module
const fs = require('fs'); // file system mode
const options = {
cert: fs.readFileSync('/etc/letsencrypt/live/YourDomainName.com/cert.pem'),
key: fs.readFileSync('/etc/letsencrypt/live/YourDomainName.com/privkey.pem')
};
// Set process name
process.title = "networked-aframe-server";
// Get port or default to 3000
const port = process.env.PORT || 3000;
// Setup and configure Express http server.
const app = express();
app.use(express.static(path.resolve(__dirname, "..", "examples")));
// Serve the example and build the bundle in development.
if (process.env.NODE_ENV === "development") {
const webpackMiddleware = require("webpack-dev-middleware");
const webpack = require("webpack");
const config = require("../webpack.config");
app.use(
webpackMiddleware(webpack(config), {
publicPath: "/"
})
);
}
// Start Express https server with SSL certificate options
const webServer = https.createServer(options,app);
// Start Socket.io so it attaches itself to Express server
const socketServer = socketIo.listen(webServer, {"log level": 1});
const myIceServers = [
{"urls":"stun:stun1.l.google.com:19302"},
{"urls":"stun:stun2.l.google.com:19302"},
// {
// "urls":"turn:[ADDRESS]:[PORT]",
// "username":"[USERNAME]",
// "credential":"[CREDENTIAL]"
// },
// {
// "urls":"turn:[ADDRESS]:[PORT][?transport=tcp]",
// "username":"[USERNAME]",
// "credential":"[CREDENTIAL]"
// }
];
easyrtc.setOption("appIceServers", myIceServers);
easyrtc.setOption("logLevel", "debug");
easyrtc.setOption("demosEnable", false);
// Overriding the default easyrtcAuth listener, only so we can directly access its callback
easyrtc.events.on("easyrtcAuth", (socket, easyrtcid, msg, socketCallback, callback) => {
easyrtc.events.defaultListeners.easyrtcAuth(socket, easyrtcid, msg, socketCallback, (err, connectionObj) => {
if (err || !msg.msgData || !msg.msgData.credential || !connectionObj) {
callback(err, connectionObj);
return;
}
connectionObj.setField("credential", msg.msgData.credential, {"isShared":false});
console.log("["+easyrtcid+"] Credential saved!", connectionObj.getFieldValueSync("credential"));
callback(err, connectionObj);
});
});
// To test, lets print the credential to the console for every room join!
easyrtc.events.on("roomJoin", (connectionObj, roomName, roomParameter, callback) => {
console.log("["+connectionObj.getEasyrtcid()+"] Credential retrieved!", connectionObj.getFieldValueSync("credential"));
easyrtc.events.defaultListeners.roomJoin(connectionObj, roomName, roomParameter, callback);
});
// Start EasyRTC server
easyrtc.listen(app, socketServer, null, (err, rtcRef) => {
console.log("Initiated");
rtcRef.events.on("roomCreate", (appObj, creatorConnectionObj, roomName, roomOptions, callback) => {
console.log("roomCreate fired! Trying to create: " + roomName);
appObj.events.defaultListeners.roomCreate(appObj, creatorConnectionObj, roomName, roomOptions, callback);
});
});
// Listen on port
webServer.listen(port, () => {
console.log("listening on http://localhost:" + port);
});

Then type the following, and logout of your session.

sudo chown ubuntu -R /etc/letsencrypt

Step 10: Testing NAF

Now we should be ready to test NAF (Networked-Aframe). At the terminal while in the /networked-aframe directory, type

npm start

The node NAF process will run and initialize (assuming no errors).

Now, open a browser on your network (say from a desktop) type into the URI (address bar), substituting with your actual domain name:

https://YourDomainName.com:3000/basic-audio.html
Clicking lock on address bar shows status of allowed browser features in Chrome

Depending on which browser you use to view the web page, the “allow controls” will appear a little different. At this time the only supported browsers are Firefox, Chrome, Edge and Oculus. Safari is not a supported browser for required WebXR at this time of writing (fall 2021).

Click on the little lock next to the URL in the address bar in the upper top left of your browser screen to see the microphone and sound settings in the Chrome browser. Allow the microphone and sound. If you have troubles with the Chrome sound enable, some people do, you might want to try using the Firefox or Edge browsers instead.

In Chrome, to enable sound:
1. Click on the three dots upper right corner of Chrome browser

2. Select “Settings”

3. Select “Privacy and security” on the left.

4. Find “Site Settings” in the middle of the screen.

5. Scroll down to find “Additional Content Settings”.

6. Under sound expand and selection and click “Sites can play sound”. That should do it.

Microphone/speakers (recommend earphones to eliminate possible feedback) must be available on your computer to hear any speaking audio.

Open another tab with the + and enter the same again. Using the WASD keys on the keyboard, and holding down the left mouse button and dragging (on PC) or on Apple Mac, use command button and mouse/pad (be sure to test with Chrome, or Firefox browser for this).

This will show something like this. Meaning it is working. Say something, and if you have audio enable in the browser, you should hear an echo through the mic. As you move around the corresponding position of the other spear head will move accordingly.

NAF basic VR Multi-user page with (2) two browser tabs open to same address

If you test with a browser inside your VR headset at the same address above, you will see the same if you kept one of the tabs on your computer open.

Currently you won’t be able to move around inside the VR headset with this example, but we will fix that very soon!

Step 11: Booting A Startup Script

But first we need the start up script for the easyrtc-server.js Node.js process to occur at boot time automatically when the Pi is powered on and connected to the network, without having to be logged in.

Hold down the <CNTL> and c keys to terminate the node process. Now type these terminal commands from the /networked-aframe directory

sudo apt install build-essentialsudo npm install pm2@latest -gpm2 start npm -- startpm2 start --name=networked_aframe npm -- startpm2 savepm2 startupsudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu

Now, logout and power off, rebooting the Pi. Test that the process is starting automatically on reboot in your browser as before.

https://YourDomainName.com:3000/basic-audio.html

SETUP OF SERVER ARCHITECHTURE AND NAF IS COMPLETE

Bonus examples: Advanced Hello World, VR Office, Treasure Island VR Complex

Now for the bonus! I’m providing some more advance examples than those in the default examples folder. Future articles will build upon these.

Open Sublime

Type the following, replacing example.com with your domain name.

<html>
<head>
<meta http-equiv="refresh" content="2;url=https://example.com:3000/metaverseServer.html" />
<title>Redirect Apache</title>
</head>
</html>

Now save that file as index.html in the /var/www/html/ directory.

When it asks if you want to replace the other index.html. Go ahead. This will redirect Apache to the Node.js process which servers its files out of this directory /home/ubuntu/networked-aframe/examples/

At a terminal type

cd networked-aframe/examplescurl -o NAFmetaverse3.zip "https://rocketvirtual.com/NAFmetaverse3.zip"lsunzip NAFmetaverse3.ziprm -f NAFmetaverse3.zip

On last thing. Open in Sublime file ~/networked-aframe/examples/IslandComplex.html

On line 301, replace https://YourDomainName.com with your actual domain name. It’s a small fix to get the fountain water working. I can’t seem to make this address relative in the code, for some reason . Now save the change. Logout.

That should do it! At a browser, or in your VR headset, or on the Internet, test with your purchased domain name. Enjoy.

https://YourDomainName.com

Congratulations, you have a Raspberry Pi Metaverse Server hosting from your home network!

If you enjoyed this article, please clap me up, follow me here, and on twitter for future articles.

Here is the continuing companion article to this one. Yes, there is more! just when you thought you were done . . .

Founder, VR coder, Sci-Fi Blogger with ideas for human technological-evolution.

Love podcasts or audiobooks? Learn on the go with our new app.