Connect Servers with Virtual Network
Before, we deployed one project on a single server. One server works well for most simple SaaS projects until you reach a few thousand active daily users because you can scale your server on almost any cloud provider by increasing the number of vCPUs and up to 64-128 GB of RAM. However, at some point (perhaps even before going to production), you might decide to deploy your project across multiple servers or even use servers from different cloud providers and your own machines. In this case, you'll need to send requests between different services hosted (deployed) on separate servers. To simplify multi-cloud and multi-server communication, you can connect all servers using an overlay network, a virtual private network (VPN), or a "Virtual Private Cloud" (VPC). These approaches essentially do the same thing: set up end-to-end encrypted connections between the servers you add to the network. This may sound complicated, but we'll explore how it works with a real example below.
How a Virtual Private Network Works
We'll use the Nebula Overlay Network to connect our servers. The main difference between a virtual private network and a private network, which most cloud providers use to connect servers within a data center, is that a virtual network offers end-to-end encryption and can connect servers from different locations. In contrast, a cloud provider's private network only works within a data center, as it is a physical private network, and often does not encrypt data between servers unless you configure encryption yourself.
Let's look at the common steps for how Nebula (and other VPNs) work:
- You install a Nebula agent (a service that runs while the system is up) and a Nebula certificate tool to create certificates on one server, which we'll call "Server A." Nebula creates a private IP address for this server that works only inside your private network.
- On Server A, you generate certificates (which are just text files) for each server you want to add to the network, then download them.
- When you create certificates, you also get a random private IP address for the server you’re adding, which you can use for communication.
- You SSH into another server (let's call it "Server B"), install the Nebula agent, and start the Nebula agent with the certificates you created on Server A.
- Now, Server A and Server B are connected through a private network. To use this private network, send a request to the private IP (for example, instead of sending a request to
localhost:6000
, you'd send it toprivate_ip_address_server_b:6000
to reach a service on Server B). - Repeat these steps to add as many servers, laptops, or single-board computers as you need.
To have Nebula working, you need at least one server with a public IP address, and all other machines in the network can function without public IP addresses. For example, you can set up a public server with your cloud provider, configure a load balancer on it (we'll discuss this in the next chapter), and forward all requests to older laptops or on-premise servers in your office. These servers can handle tasks and return responses to users. This setup works particularly well when you need heavy, non-real-time media processing that can be done more efficiently and cost-effectively on your own hardware, or if you need to complete tasks periodically and want to avoid paying for a server when it's not in use.
How to Set Up a VPN on Multiple Servers
In this example, we'll connect two servers.
Prerequisites
- Two servers with public IP addresses, running Ubuntu 22.04, and SSH access. You can use servers from different data centers and cloud providers. Let's assume you have Server A with public IP address
151.115.51.131
and Server B with public IP168.119.101.23
. Server A will act as the "lighthouse" in our network, and we’ll connect Server B to the same network. Later, we'll also connect your local machine (e.g., a laptop). - A domain or subdomain with an A record pointing to Server A's IPv4 address. In this example, we’ll use
join.turbocloud.dev
.
Steps to Set Up
- SSH into Server A (replace
151.115.51.131
with your IP address):
ssh root@151.115.51.131
-
Install Caddy Server (a proxy server) to enable certificate downloads when adding new servers/local machines to the network.
-
Download and Install Nebula Agent and Nebula Certificate Tool:
wget https://github.com/slackhq/nebula/releases/download/v1.9.4/nebula-linux-amd64.tar.gz
tar -xzf nebula-linux-amd64.tar.gz
rm nebula-linux-amd64.tar.gz
sudo chmod +x nebula
sudo chmod +x nebula-cert
mv nebula /usr/local/bin/nebula
mv nebula-cert /usr/local/bin/nebula-cert
sudo mkdir /etc/nebula
sudo nebula-cert ca -name "lighthouse" -duration 34531h
sudo nebula-cert sign -name "lighthouse" -ip "192.168.202.1/24"
wget turbo_cloud_repo/nebula_lighthouse_config.yaml
sed -i -e "s/{{lighthouse_ip}}/$(curl https://localcloud.dev/ip)/g" nebula_lighthouse_config.yaml
sudo mv lighthouse_config.yaml /etc/nebula/config.yaml
sudo mv ca.crt /etc/nebula/ca.crt
sudo mv ca.key /etc/nebula/ca.key
sudo mv lighthouse.crt /etc/nebula/host.crt
sudo mv lighthouse.key /etc/nebula/host.key
- Start Nebula:
sudo echo -e "[Unit]\nDescription=Nebula overlay networking tool\nWants=basic.target network-online.target nss-lookup.target time-sync.target\nAfter=basic.target network.target network-online.target\nBefore=sshd.service" >> /etc/systemd/system/turbocloud-nebula.service
sudo echo -e "[Service]\nSyslogIdentifier=nebula\nExecReload=/bin/kill -HUP $MAINPID\nExecStart=/usr/local/bin/nebula -config /etc/nebula/config.yaml\nRestart=always" >> /etc/systemd/system/turbocloud-nebula.service
sudo echo -e "[Install]\nWantedBy=multi-user.target" >> /etc/systemd/system/turbocloud-nebula.service
sudo systemctl enable turbocloud-nebula.service
sudo systemctl start turbocloud-nebula.service
Great! We’ve just started a virtual private network. Now, we’ll add new servers to the network.
- Generate Certificates for a New Server:
cd ~/certs
wget turbo_cloud_repo/nebula_lighthouse_config.yaml
sed -i -e "s/{{lighthouse_ip}}/$server_ip/g" nebula_lighthouse_config.yaml
nebula-cert sign -ca-crt /etc/nebula/ca.crt -ca-key /etc/nebula/ca.key -name "srv_1" -ip "192.168.202.2/24" -groups "devs"
- SSH into Server B and install Nebula:
wget https://github.com/slackhq/nebula/releases/download/v1.9.4/nebula-linux-amd64.tar.gz
tar -xzf nebula-linux-amd64.tar.gz
rm nebula-linux-amd64.tar.gz
sudo chmod +x nebula
sudo chmod +x nebula-cert
mv nebula /usr/local/bin/nebula
mv nebula-cert /usr/local/bin/nebula-cert
sudo mkdir /etc/nebula
# Download required files to join the network created on Server A
wget url_from_server_A_with_zip -O turbocloud-join-vpn.zip
unzip -o turbocloud-join-vpn.zip
sudo mv config.yaml /etc/nebula/config.yaml
sudo mv ca.crt /etc/nebula/ca.crt
sudo mv host.crt /etc/nebula/host.crt
sudo mv host.key /etc/nebula/host.key
sudo rm turbocloud-join-vpn.zip
# Start Nebula
sudo echo -e "[Unit]\nDescription=Nebula overlay networking tool\nWants=basic.target network-online.target nss-lookup.target time-sync.target\nAfter=basic.target network.target network-online.target\nBefore=sshd.service" >> /etc/systemd/system/turbocloud-nebula.service
sudo echo -e "[Service]\nSyslogIdentifier=nebula\nExecReload=/bin/kill -HUP $MAINPID\nExecStart=/usr/local/bin/nebula -config /etc/nebula/config.yaml\nRestart=always" >> /etc/systemd/system/turbocloud-nebula.service
sudo echo -e "[Install]\nWantedBy=multi-user.target" >> /etc/systemd/system/turbocloud-nebula.service
sudo systemctl enable turbocloud-nebula.service
sudo systemctl start turbocloud-nebula.service
- If no errors occur, Server B should now be connected to Server A over an encrypted