This solution is meant to make the life of ubuntu developers a lot more convenient & secure. I hope an admin and/or others will see fit vote my original question back up as it is a pretty common question for folks who want to use Ubuntu for web development.
In any case, I recently had the software requirement for a host-only adapter for virtualbox with internet access. Meaning the widely used dual-adapter method wouldn't suffice. While solving this problem, I essentially stumbled upon a super secure, super convenient, and super efficient ubuntu/virtualbox dev environment. I am posting all of my steps below to help other web developers who are seeking a more efficient web dev environment.
First off, a quick overview:
Bridged adapter & NAT adapter Combo Method
Pros:
- Easy & quick to set up, if you are proficient with UFW
Cons:
- requires 2 network interfaces to be configure inside guest
- guest with static ip addresses might have issues changing wi-fi networks due to gateway values
- requires more advanced configuration of firewall
- encourages use of
/etc/hosts
to resolve local domain names (gets cumbersome over time)
NAT adapter & host-only adapter
Pros:
- Easy to set-up
- Minimal firewall configuration
Cons:
- requires 2 network interfaces to be configured inside guest
- some software packages utilize default ip on installation, so default 10.X.X.X addresses not suitable
(in my situation creating a custom NAT address through virtualbox preferences wouldn't help, as my software only installs on the default NAT address and NAT address isn't routeable, accessible to the host)
- requires more advanced configuration of firewall
- encourages use of
/etc/hosts
to resolve local domain names (gets cumbersome over time)
The Most Efficient Solution:
Single host-only adapter with Internet access.
host-only adapter w. internet access method
Pros:
- single adapter for all guests
- simplified firewall config
- simplified networking of guests
- guest behave more like prod servers that usually have a single network interface "eth0"
- complete elimination of
/etc/hosts
use
Cons:
- more difficult initial configuration.
With the above understood, lets get started:
I will assume:
- you have the latest version of virtualbox installed
- you have a UFW firewall with VPN KillSwitch already configured. (Pay
attention to the IP Masquerade section, we will re-visit it.)
- you have have already created a guest server in virtualbox & added an ssh pub key for your user
- A web project ready for web access inside your guest with a domain ending with ".test" (i.e. www.example.test)
Step 1
In Virtualbox > Files > Host Network Manager create a host-only adapter for your machine (i.e. vboxnet0) For this guide mine will have the IP address of 192.168.51.1
Step 2
In Virtualbox > Settings > Network, click "Enable Adapter" for Adapter 1 and for "Attached to" select the vboxnet0 name that you created in "Step 1"
Step 3
Create a static ip config for your guest server (mine is Ubuntu 20.04 server). This is necessary for ssh and domain name resolution, but you can use dynamic ip if you don't need ssh/dns.
For Ubuntu Server, I am using:
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
addresses: ['192.168.51.47/24']
gateway4: 192.168.51.1 #**NOTE** Your vboxnet0 ip address is the gateway for your static ip address.
nameservers:
addresses: [127.0.0.1, 192.168.51.1, 8.8.8.8]
Remember
Run #netplan apply
and/or #netplan --debug generate
to find your typos & errors.
Reboot your guest to be sure settings take affect.
Step Four
Create easy, minimal UFW firewall rule enable host-guest communications. This is all that is required to configure a host-only adapter to work with UFW:
$sudo ufw allow in on vboxnet0 && sudo ufw allow out on vboxnet0
At this point you should ping your guest's static ip from the host and ssh in into host.
Test with:
ssh -p 22 -i ~/.ssh/id_rsa root@your-guest's-static-ip address
ping -c 5 your-guest's-static-ip address
Step Five
Create permanent internet access for vboxnet0 by sharing host machine's primary network adapter using MASQUERADE. When you configured your vpn killswitch you had to use ip masquerading for your vpn's address by editing /etc/ufw/before.rules
, we will edit this file again.
sudo nano /etc/ufw/before.rules
In this section of the file:
#NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
Add:
-A POSTROUTING -s 192.168.51.1/24 -j MASQUERADE
#NOTEthis is the ip address of your vboxnet0 host-only adapter, which acts as the gateway for your guest's static ip address.
Close & Save the file
Now all traffic 192.168.51.1 will be sent through the host's primary network interface even if it changes (i.e. wi-fi vs lan)
You can test this by accessing your vbox guest and on the command line, running:
ping -c 5 8.8.8.8
If successful, your host-only adpater now has internet access.
Step 6
This is the final step and by far the most most complex. At this point, the only thing that needs to be done for your virtualbox web dev environment to be ready for use is to install and configure dnsmasq so that domain names from your guest server can be resolved locally.Sidebar dnsmasq can obviously be used with the combo network adapter methods mentioned above as to eliminte use of /etc/hosts
, but when using a single host-only adapter, dnsmasq is required to resolve local domain names.
Disable & stop systemd resolved
$ sudo systemctl disable systemd-resolved
$ sudo systemctl stop systemd-resolved
Remove symlink on /etc/resolv.conf
& remove the file
$ ls -lh /etc/resolv.conf
$ sudo rm /etc/resolv.conf
Create a new /etc/resolv.con
with the following values:
$ sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolv.conf' #(host machine resolution of doman names)
$ sudo bash -c 'echo "nameserver 208.67.222.222" >> /etc/resolv.conf' #(OpenDNS public dns server ip for outside internet)
$ sudo bash -c 'echo "nameserver your-guest's-static-ip address" >> /etc/resolv.conf'
Install dnsmasq
$ sudo apt install dnsmasq
Add .test to the dnsmasq config file:
$ sudo bash -c 'echo "address=/.test/your-guest's-static-ip address" >> /etc/dnsmasq.conf'
NOTE: Folks developing wordpress multisites that need wildcard domain resolution can use:
$ sudo bash -c 'echo "address=/example.test/your-guest's-static-ip address" >> /etc/dnsmasq.conf'
Create a directory resolver for the guest's static ip address:
$sudo mkdir -v /etc/resolver && sudo bash -c 'echo "nameserver your-guest's-static-ip address" > /etc/resolver/test'
Restart dnsmasq and network-manager
$ sudo systemctl restart dnsmasq
$ sudo systemctl restart network-manager
Test your dnsmasq set-up
a.) open your browser and confirm that you still have outside internet access
b.) run dig example.test
you should be able to see the static ip address of your guest server
c.) in your host machine's browser open example.test
BANG! Done.
With this web dev environment you can change wi-fi newtworks at will without ufw/guest ip address issues, you have only one host-only adapter that you use on all future guests you create, more easily network guests together, and completely stop using the /etc/hosts
file to resolve local domain names for your projects, since it is done automatically by dnsmasq.
My sources:
https://unix.stackexchange.com/questions/304050/how-to-avoid-conflicts-between-dnsmasq-and-systemd-resolved
https://brunopaz.dev/blog/setup-a-local-dns-server-for-your-projects-on-linux-with-dnsmasq/
https://www.stevenrombauts.be/2018/01/use-dnsmasq-instead-of-etc-hosts/#configure-dnsmasq
https://linuxize.com/post/how-to-setup-a-firewall-with-ufw-on-ubuntu-20-04/
https://superuser.com/questions/1237463/virtualbox-host-only-with-internet
https://www.stevenrombauts.be/2018/01/use-dnsmasq-instead-of-etc-hosts/#configure-dnsmasq
https://medium.com/soulweb-academy/docker-local-dev-stack-with-traefik-https-dnsmasq-locally-trusted-certificate-for-ubuntu-20-04-5f036c9af83d