Partie 1 Donald Buchan:
20240204deuxfreresdeuxserveursV17(Donald).pdf
Partie 2 Gordon Buchan:
A personal blog
In this post, we build a home server using Ubuntu Desktop Linux that includes a Samba network file server, an OpenVPN virtual private network (VPN), and a KVM hypervisor hosting virtual machine (VM) guests including a Linux/Apache/MySQL/PHP web server. In addition, we build an offsite backup server using Fedora Server Linux, and link the offsite backup server to the home server via a WireGuard secure network tunnel.
The home server will perform the following tasks:
As the home server will host virtual machine guests, I need a certain level of performance, so I bought a refurbished circa 2017 computer for C$403 (US$294). CPU performance can affect OpenVPN performance, so the VPN server will benefit from a stronger CPU as well.
The home server is a small form factor (SFF) desktop circa 2017:
I formatted the home server with Ubuntu Desktop 22.04 LTS.
For the home server, I wanted the option of a graphical user interface (GUI) desktop for use at console, and via remote desktop. A GUI desktop is also more convenient for the creation and management of KVM virtual machine guests using the virt-manager GUI, (and avoids the need for SSH tunnel forwarding and an X11 server to reach a headless server).
With modern hardware, I like to use UEFI mode for disk booting. Although we do not need a multiple-boot menu for this server, it is easier to construct a multiple-boot menu using grub when booting in UEFI mode. This is the default on a post-2016 motherboard, but it is worth looking at the BIOS when you first lay hands on a machine.
We need a wired Ethernet connection for the home server, as we want to create a bridge mode adapter (br0) so that virtual machine (VM) guests can have IP addresses in the host networking subnet.
https://ubuntu.com/download/desktop
If you are writing the installer to a USB using Windows, consider using Rufus:
Click on “Install Ubuntu”:
Click on “Continue”:
Click on “Continue”:
Click on “Install Now”:
Click on “Continue”:
Select a time zone. Click “Continue”:
Complete the fields as needed, then click on “Continue”:
Click on “Restart Now”:
Press the ENTER key on your keyboard:
Because we are working on an Ubuntu desktop, we will use the nmcli command to create a bridge mode adapter (br0).
Open a terminal window. Enter the following commands:
sudo su
apt install net-tools bridge-utils
ifconfig
Look at the information displayed by the ifconfig command. Identify the name of the wired Ethernet connection. The name may be “eth0” or a string such as “enp0s31f6”
Use the value you identified above and use it in place of ethernet_name.
Enter the following commands:
nmcli con add ifname br0 type bridge con-name br0
nmcli con add type ethernet ifname ethernet_name master br0
nmcli con up br0
nmcli con show
brctl show
Although the br0 adapter appears in the Gnome Settings control panel, its IP address cannot be set using this graphical user interface (GUI). We can set the IP address and other IPV4 values of a br0 adapter using the nmcli command.
Enter the following commands:
nmcli con modify br0 ipv4.addresses 192.168.56.40/24 ipv4.gateway 192.168.56.1 ipv4.method manual
nmcli con modify br0 ipv4.dns "8.8.8.8 8.8.4.4"
nmcli con down br0 && sudo nmcli con up br0
con show br0
The bridge networking device (br0) is a wrapper around the Ethernet adapter. The br0 adapter replaces the Ethernet adapter.
From the Ubuntu Desktop, Start the Settings application. Click on the search icon and search for “users”:
Click on “Unlock…”:
When prompted, enter the password for the user that owns the desktop session:
Enable “Automatic Login”:
In the Settings application, go to Privacy, then Screen. Change “Blank Screen Delay” to “Never”. Disable “Automatic Screen Lock”:
In the Settings application, go to Sharing, then go to “Remote Desktop”. Enable “Remote Desktop”. Enable “Remote Control”. Provide values for “User Name” and “Password”
Open a terminal window. Enter the following commands:
sudo su
ufw allow 3389/tcp
Use the Remmina program and select the RDP protocol. Complete the fields as necessary for your installation, then click on “Save and Connect”:
Click on the Start button. Enter the text “remote desktop”. Click on the icon for “Remote Desktop Connection”:
Enter the IP address of the home server. Click “Connect”:
Enter the username and password you specified in the Settings application on the home server under Sharing | Remote Desktop:
Check the box “Don’t ask me again for connection to this computer”. Click on “Yes”:
If you have difficulty connecting to the home server using a Windows remote desktop client, consider using VNC:
Installing x11vnc to replace broken screen sharing on Ubuntu 21.04
From the home server’s desktop, start the Files (Nautilus) program:
Right-click on “Documents”. Click on “Properties”:
Click on “Local Network Share”. Check the box “Share this folder”:
Click on “Install service”:
Click on “Install”:
Enter the password for the user that owns the desktop on the home server. Click Authenticate:
Check the box “Share this folder”. Enter a value for the “Comment” field. Click on “Create Share”:
Open a terminal window. Enter the following command:
apt install samba
Open a terminal window. Enter the following commands:
sudo su
cd /etc/samba
nano smb.conf
Use the nano text editor to modify the Samba configuration file:
[global]
workgroup = WORKGROUP
security = user
passdb backend = tdbsam
map to guest = Bad User
log file = /var/log/samba/%m.log
max log size = 50
dns proxy = no
[share01]
path = /mount2/share01
create mask = 0644
directory mask = 0755
writable = yes
browseable = yes
valid users = @share01
force group = share01
[share02]
path = /mount2/share02
create mask = 0644
directory mask = 0755
writable = yes
browseable = yes
valid users = @share02
force group = share02
Save and exit the file.
Enter the following command:
systemctl restart samba
groupadd share01
groupadd share02
usermod -aG share01 username
usermod -aG share02 username
Open a terminal window. Enter the following commands. Replace username with the user that owns the desktop on the home server. When prompted, provide a value for the password:
sudo su
smbpasswd -a username
Enter the following command:
ufw allow 137,138,139,445/tcp
In the Files (Nautilus) application, click on “+ Other Locations”:
Select “Registered User”. Provide a value for “Username”. For Domain, put “WORKGROUP”. Provide a value for “Password”. Click on “Connect”:
From the File Explorer application in Windows 11 Pro, enter the address of the server in the address bar. Prefix the address with “\\” as in “\\192.168.56.40” for the following example. Enter the IP address of your home server:
For a detailed discussion about Samba and advanced topics including Active Directory authentication, refer to Integrating open source software in the enterprise Chapter 1: Creating a network file share with Linux and Samba authenticating against Active Directory
Open a terminal window. Enter the following commands:
sudo su
apt install iptraf-ng finger wireguard virt-manager build-essential
Visit the website noip.com
Create a free account. Create a hostname. Click on “Dynamic Update Client”:
Follow the instructions provided by noip.com to install the noip dynamic update client (DUC):
Enter the following commands in the terminal window. Use the version number in place of x.xx:
cd /usr/local/src
tar xzf noip-duc-linux.tar.gz
cd no-ip-x.xx
make
make install
Open a terminal window. Enter the following commands:
sudo su
cd /etc
nano rc.local
Use the nano text editor to add the following text:
#!/usr/bin/bash
# persistent host name
/usr/local/bin/noip2
exit 0
Save and exit the file.
Enter the following commands:
chmod 755 rc.local
systemctl start rc-local
systemctl enable rc-local
If you have a registered domain name, and you have access to the DNS control panel for that domain, you can declare a CNAME record in DNS to map a subdomain to the ip address of the persistent hostname. For example, the GoDaddy DNS control panel allows the following kind of CNAME declaration:
This creates the subdomain servername.example.com, which will ping to the same IP address as persistenthostname.ddns.net
In this case we have set the time-to-live (TTL) value to 1 hour, so the IP address of the CNAME host would be updated once per hour. Many DNS providers block the option of declaring a CNAME to the apex (@) host of a domain. You can still host a subdomain, for example:
https://servername.example.com
If you need to declare the @ host of a domain as a CNAME associated with a persistent host name, consider using pobox.com as your DNS provider.
The openvpn-install.sh from Nyr automates the installation of the OpenVPN server application:
https://github.com/Nyr/openvpn-install
To download the openvpn-install.sh script, enter the following commands:
sudo su
cd /root
mkdir openvpn
cd openvpn
wget https://git.io/vpn -O openvpn-install.sh
chmod +x openvpn-install.sh
Enter the following command:
nano openvpn-install.sh
Use the nano text editor to modify the file openvpn-install.sh by using nano’s search-and-replace function:
Press Control-| for search-and-replace
search for: “10.8.”
replace with: “10.4”
(replace all occurrences)
cd /root/openvpn
./openvpn-install.sh
When prompted, choose the following options:
protocol: TCP
port: 10443
From a root shell, enter the following commands:
cd /etc/openvpn/server
nano server.conf
Locate the following line:
push "redirect-gateway def1 bypass-dhcp"
Change the line to:
push "redirect-gateway def bypass-dhcp"
Press Ctrl-X to save and exit the file.
Use a text editor to load the OpenVPN client profile. Add the following text to the bottom of the file:
Enter the following commands
cd /etc/openvpn/server
nano client-common.txt
Use the nano text editor to modify the file.
Replace the line:
remote xxx.xxx.xxx.xxx 10443
with the line:
remote persistenthostname.ddns.net 10443
Save and exit the file.
From a root shell, enter the following command:
systemctl start openvpn-server@server
systemctl enable openvpn-server@server
Enter the following commands:
sudo su
ufw allow 10443/tcp
From a root shell, enter the following commands:
cd /etc
nano sysctl.conf
Add the following text to the bottom of the file:
net.ipv4.ip_forward=1
Press Ctrl-X to save and exit the file.
Enter the following command to reload the sysctl settings:
sysctl -a
Enter the following commands:
cd /etc
nano rc.local
Add the following text. Provide a value for adaptername that matches your installation:
!/usr/bin/bash
iptables -t nat -A POSTROUTING -s 10.4.0.0/24 -o adaptername -j MASQUERADE
If you are using the no-ip.com dynamic update client (DUC), add the following text:
/usr/local/bin/noip2
Add the following text:
exit 0
Press Ctrl-X to save and exit the file.
Enter the following command
chmod 755 rc.local
Enter the following command:
systemctl restart rc-local
systemctl enable rc-local
Use the control panel of your router to forward a port from the public-facing IP address to the internal IP address of the VPN host.
As an example, for the server described in this procedure, we are using the TCP port 10443 to host the connection:
Enter the following command and follow the instructions:
./openvpn.sh
Select an IP address from the list:
Which IPv4 address should be used?
1) xxx.xxx.xxx.xxx
IPv4 address [1]: 1
Enter “2” for “2) TCP”:
Which protocol should OpenVPN use? 1) UDP (recommended) 2) TCP Protocol [1]: 2
Enter “10443”:
What port should OpenVPN listen to? Port [1194]: 10443
Use the FileZilla file transfer client to download the OpenVPN client profile:
Import the OpenVPN client profile into the OpenVPN client application.
Tip: connect a computer to your phone’s hotspot, so that you are testing a connection from outside the network.
An example of a Windows client connecting to the OpenVPN server:
For “Username” enter the username of the VPN connection. For “Password” enter the one-time password (OTP) displayed by the Google Authenticator app:
A successful connection:
For a detailed discussion about OpenVPN and advanced topics including two-factor authentication, refer to Integrating open source software in the enterprise Chapter 2: Using Linux and OpenVPN to create a virtual private network (VPN) server with two-factor authentication (2FA) enabled using Google Authenticator
We will install some programs, then run virt-manager.
Open a terminal window. Enter the following commands:
sudo su
apt install qemu-system qemu-utils python3 python3-pip git
Enter the following commands:
cd /etc/libvirt/qemu/networks/
nano default.xml
Use the nano text editor to modify the default.xml file. Change the value “122” to “162”:
<ip address='192.168.162.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.162.2' end='192.168.162.254'/>
</dhcp>
</ip>
Save and exit the file. Enter the following command:
systemctl restart libvirtd
Visit the following website:
https://ubuntu.com/download/server
Click on “Download Ubuntu Server xx.xx.x LTS”:
From the desktop of the home server, open a terminal window. Enter the following commands:
virt-manager
Click on the “i” icon on the VM. Select “NIC”:
Enter the following commands:
sudo su
apt install net-tools
ifconfig
Note the name (ie enp1so) and IP address of the first adapter:
Open a terminal window on the desktop of the home server. Enter the following command, substituting values for username and ipaddress to match your installation:
ssh username@ipaddress
As the VM is running Ubuntu Server, we will use netplan to create a static IP address.
From the SSH terminal window, enter the following commands:
sudo su
cd /etc/netplan
cp 00-installer-config.yaml 00-installer-config.yaml.b4
nano 00-installer-config.yaml
Use the nano text editor to modify the 00-installer-config.yaml file. Change the value of adaptername as needed ie “enp1s0”:
network:
version: 2
renderer: networkd
ethernets:
adaptername:
dhcp4: no
addresses:
- 192.168.56.23/24
gateway4: 192.168.56.1
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
From the VM console on the desktop of the home server, enter the following commands:
sudo su
ifconfig
cd /etc/netplan
netplan try
Verify that the new IP address has taken effect:
From the VM console on the desktop of the home server, enter the following command:
ifconfig
Enter the following commands:
apt clean
apt update
apt upgrade
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 22/tcp
apt install net-tools iptraf-ng
reboot
Open an SSH terminal window to the home server. Substitute values for username and ipaddress to match your installation:
ssh username@ipaddress
Enter the following commands:
sudo su
apt install lamp-server^
cd /etc/apache2/mods-enabled
nano dir.conf
Use the nano text editor to modify the dir.conf file. Modify the line so that index.php is the first entry in the DirectoryIndex line:
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
Save and exit the file.
Enter the following commands:
nano apache2.conf
Use the nano text editor to modify the apache2.conf file. Find the “<Directory /var/www/>” section. Change “AlllowOverride None” to “AllowOverride All”:
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Enter the following commands:
a2enmod rewrite
systemctl restart apache2
Enter the following command.
mysql_secure_installation
Answer the prompts as follows:
From the desktop of the home server, start a web browser. Visit the IP address of the VM that hosts the LAMP web server:
Using your cell phone: switch to LTE data mode. Visit the URL of your persistent hostname. If you have a CNAME declared for a subdomain host in DNS, visit that URL as well.
Open an SSH terminal window to the VM hosting the LAMP web server:
ssh desktop@192.168.56.23
Enter the following commands:
sudo su
cd /etc/apache2/sites-available
nano persistenthostname.ddns.net.conf
Use the nano text editor to edit the persistenthostname.ddns.net.conf file:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName persistenthostname.ddns.net
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Save and exit the file.
Enter the following commands
nano subdomain.example.com.conf
Use the nano text editor to edit the subdomain.example.com.conf file:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName subdomain.example.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Save and exit the file.
Enter the following commands:
a2ensite persistenthostname.ddns.net.conf
a2ensite subdomain.example.com.conf
systemctl restart apache2
Open an SSH terminal window to the VM hosting the LAMP web server. Enter the following commands:
sudo su
apt install python3-certbot-apache
certbot --apache
systemctl restart apache2
Open an SSH terminal window to the home server. Provide values for username and ipaddress to match your installation:
ssh username@ipadress
Enter the following commands:
sudo su
cd /etc/wireguard
umask 077
wg genkey > privatekey
wg pubkey < privatekey > publickey
ufw allow 55555/udp
Enter the following commands:
nano wg0.conf
Use the nano text editor to modify the wg0.conf file. Provide a value for privatekey matching the privatekey of the home server, generated above. (Provide a value for publickey of the peer system (the offsite backup server) when the value becomes available, then restart the wg-quick@wg0 service):
[Interface]
# home server
Address = 10.5.0.1/24
PrivateKey = privatekeyofhomeserver
ListenPort = 55555
[Peer]
# offsite backup server
PublicKey = publickeyofoffsitebackupserver
AllowedIPs = 10.5.0.0/24, 192.168.1.0/24
Enter the following command:
systemctl restart wg-quick@wg0
systemctl enable wg-quick@wg0
The offsite backup server will perform the following tasks
My brother donated a computer to the project, a computer that was headed for a dumpster. This is an example of a hacker living his principles.
This machine could not address more than 1.5GB RAM of the RAM we found in our junkpiles. This machine has a 20GB mechanical hard drive — we could certainly upgrade that with a 120GB SSD, but we decided to see what was possible with the mechanical drive. We will be attaching an SSD drive to the computer. Because the taskings are Samba network file sharing and a Wiregurd tunnel to the home server, it may not be necessary to upgrade the mechanical drive.
The offsite backup server is a small form factor (SFF) desktop circa 2005:
My brother formatted the offsite backup server with Fedora Server 38. This server will have a text-only console. This will allow us to conserve about 1.1GB RAM, ie 3/4 of the 1.5GB RAM we have available in the system.
For the offsite backup server, as the hardware is limited, we will use Fedora Server to conserve CPU and RAM resources.
With older, pre-2016 hardware, it is simpler to format in Legacy Mode. In this case, the system literally is legacy, this is the only mode available.
We will connect the offsite backup server using wired Ethernet. This simplifies some kinds of networking, including WireGuard, which we will use later in this procedure to create a secure tunnel to the home server.
Log in at the console of the offsite backup server. Enter the following commands:
sudo su
dnf install net-tools iptraf-ng finger wireguard
ifconfig
Examine the output of the ifconfig command. Find the name of the Ethernet adapter, it may be something like “enp0s25” or “eth0” — take note of this value.
Enter the following commands. Provide values for adaptername and ipv4.gateway that match your installation:
nmcli con modify adaptername ipv4.addresses 192.168.1.95/24 ipv4.gateway 192.168.1.1 ipv4.method manual
nmcli con modify br0 ipv4.dns "8.8.8.8 8.8.4.4"
nmcli con down br0 && sudo nmcli con up br0
con show br0
reboot
Open an SSH terminal window to the offsite backup server. Enter the following command:
dnf install samba
Refer to the section above “Creating a network file share using Samba“
Open an SSH terminal window to the offsite server. Provide values for username and ipaddress to match your installation:
ssh username@ipadress
Enter the following commands:
sudo su
cd /etc/wireguard
umask 077
wg genkey > privatekey
wg pubkey < privatekey > publickey
firewall-cmd --zone=public --add-port=55555/udp --permanent
Enter the following commands:
nano wg0.conf
Use the nano text editor to modify the wg0.conf file. Provide a value for privatekey matching the privatekey of the home server, generated above. Provide a value for publickey matching the private key of the offsite backup server:
[Interface]
# offsite backup server
Address = 10.5.0.2/24
PrivateKey = privatekeyofoffsitebackupserver
ListenPort = 55555
[Peer]
# home server
PublicKey = publickeyofhomeserver
AllowedIPs = 10.5.0.0/24, 192.168.56.0/24
Endpoint = persistenthostnameofhomeserver.ddns.net:55555
PersistentKeepalive = 25
Enter the following command:
systemctl restart wg-quick@wg0
systemctl enable wg-quick@wg0
From the offsite backup server, enter the following command:
ping 10.5.0.1
If the ping is successful, the offsite backup server has a working WireGuard connection to the home server.
From the home server, enter the following command:
ping 10.5.0.2
If the ping is successful, the home server has a working Wireguard connection to the offsite backup server.
In this procedure we install the open source program OpenVPN on a server running on Linux to create a virtual private network (VPN) authenticated against Active Directory with two-factor authentication (2FA) enabled Google Authenticator.
A Linux server running OpenVPN server software can replace a Windows server or other commercial solution for the VPN server role in the enterprise, reducing software licensing costs and improving security and stability.
The VPN server will verify client digital certificates as one of the authentication methods.
The VPN server will verify the one-time password (OTP) generated by Google Authenticator as one of the authentication methods.
To access the network, help desk clients will:
This procedure does not verify a PAM or Active Directory password to authenticate the VPN connection.
There are ways of prompting for a username, and a password, and an OTP from Google Authenticator. However, some of these are difficult to integrate with with client VPN connector software, which do not support a second password field. Some approaches ask the help desk client to enter a system password and the OTP as a combined password, but this can be confusing for help desk clients.
This procedure was tested on Ubuntu Linux 22.04 LTS.
Deploy OpenVPN on a physical Linux server or on a virtual Linux server hosted as a virtual machine (VM), using KVM on Linux, Hyper-V, VMware, or VirtualBox on Windows, or Parallels using MacOS.
For KVM, add a macvtap network adapter to the automation server. For Hyper-V, VMware, VirtualBox or Parallels, add a bridge mode network adapter. This will allow the VPN server to access the same network as the server’s hypervisor host.
Assign a static IP to the VPN server.
Most residential Internet connections have a dynamic host configuration protocol (DHCP) public-facing IP address, which can change over time. You can use a service like no-ip.com to associate a permanent host name such as permhostname.ddns.net to a host with a dynamic IP address:
Use the control panel of your router to forward a port from the public-facing IP address to the internal IP address of the VPN host.
As an example, for the server described in this procedure, we are using the TCP port 443 to host the connection:
This procedure assumes that you are logged in as the root user of the Linux server.
Escalate to the root user by entering the following commands:
sudo su
apt install libpam-google-authenticator curl oath libqrencode4
From a root shell, enter the following commands:
cd /etc
nano sysctl.conf
Add the following text to the bottom of the file:
net.ipv4.ip_forward=1
Press Ctrl-X to save and exit the file.
Enter the following command to reload the sysctl settings:
sysctl -a
Enter the following commands:
cd /etc
nano rc.local
Add the following text:
!/usr/bin/bash
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp3s0 -j MASQUERADE
If you are using the no-ip.com dynamic update client (DUC), add the following text:
/usr/local/bin/noip2
Add the following text:
exit 0
Press Ctrl-X to save and exit the file.
Enter the following command
chmod 755 rc.local
Enter the following command:
systemctl restart rc-local
The openvpn-install.sh from Angristan automates the installation of the OpenVPN server application:
https://github.com/Angristan/OpenVPN-install
To download the openvpn-install.sh script, enter the following commands:
cd /root
curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh
chmod +x openvpn-install.sh
./openvpn-install.sh
From a root shell, enter the following commands:
cd /etc/openvpn/server
nano server.conf
Locate the following line:
push "redirect-gateway def1 bypass-dhcp"
Change the line to:
push "redirect-gateway def bypass-dhcp"
Add the following text to the end of the file:
auth-user-pass-verify "/etc/openvpn/server/google-authenticator.sh" via-env
script-security 3
username-as-common-name
Press Ctrl-X to save and exit the file.
Enter the following commands:
cd /etc/openvpn/server nano google-authenticator.sh
#!/usr/bin/bash
# this script written by OpenAI ChatGPT
# see References section for prompt
# check if the user has provided a username and password
if [ -z "$username" -o -z "$password" ]; then
exit 1
fi
# get the user's secret key from the Google Authenticator app
secret_key=$(grep "^$username:" /etc/openvpn/server/google-authenticator.keys | cut -d: -f2)
# check if the user has a secret key
if [ -z "$secret_key" ]; then
exit 1
fi
# generate a six-digit code using the secret key and the current time
code=$(oathtool --totp -b "$secret_key")
# compare the generated code with the password provided by the user
if [ "$code" = "$password" ]; then
exit 0
else
exit 1
fi
Press Ctrl-X to save and exit the file.
Enter the following command:
chmod 755 google-authenticator.sh
From a root shell, enter the following command:
systemctl restart openvpn-server@server
Use the FileZilla file transfer client to download the OpenVPN client profile:
Use a text editor to load the OpenVPN client profile. Add the following text to the bottom of the file:
auth-user-pass
Save and exit the file.
Visit the Apple App Store or the Google Play Store. Search for “google authenticator” and download the app:
Click on “Get started”:
Open a terminal window as root, and make the terminal window full-screen. Enter the following command:
google-authenticator
Click on “Scan a QR code” then click on “OK” to allow the app to access the camera:
Look at the one-time code shown on the Google Authenticator app:
Enter the code in the Terminal window in the field: “Enter code from the app (-1 to skip):”
Enter “n” to the question: “Do you want me to update your “/root/.google_authenticator file? (y/n):”
Enter the following commands:
cd /etc/openvpn/server
nano google-authenticator.keys
Add an entry to the file in with the format “username: yournewsecretkey”:
client06a:NRX7VMDMIC6XSDFJNU3WVB3K2I
Press Ctrl-X to save and exit the file.
Should this process be automated further? Yes. The google-authenticator program on the server could be scripted so that the client’s username and secret code could be added to the /etc/openvpn/server/google-authenticator.keys file.
https://openvpn.net/community-downloads/
Import the OpenVPN client profile into the OpenVPN client application.
An example of a Windows client connecting to the OpenVPN server:
For “Username” enter the username of the VPN connection. For “Password” enter the one-time password (OTP) displayed by the Google Authenticator app:
A successful connection:
https://egonbraun.medium.com/using-google-authenticator-mfa-with-openvpn-on-ubuntu-16-04-774e4acc2852
https://amilstead.com/blog/openvpn-with-google-authenticator-totp/
https://github.com/evgeny-gridasov/openvpn-otp
https://www.softether.org/
https://charlesreid1.com/wiki/Ubuntu/OpenVPN_Server#Adding_MFA_to_VPN_Access
https://www.howtoforge.com/how-to-set-up-openvpn-to-authenticate-with-linotp
https://www.howtoforge.com/securing-openvpn-with-a-one-time-password-otp-on-ubuntu
https://www.digitalocean.com/community/tutorials/how-to-configure-multi-factor-authentication-on-ubuntu-18-04
https://warlord0blog.wordpress.com/2022/09/01/openvpn-mfa-and-pam/
https://binsec.wiki/en/security/howto/protect-hardening/authorization-and-authentication/openvpn-configure-2fa-google-authenticator/
https://forums.openvpn.net/viewtopic.php?t=12886
https://www.freeipa.org/page/Windows_authentication_against_FreeIPA
http://pgina.org/
https://www.ezeelogin.com/kb/article/how-to-install-google-authenticator-on-centos-ubuntu-323.html
https://askubuntu.com/questions/182498/google-authenticator-for-desktop
https://unix.stackexchange.com/questions/341226/samba-not-starting-on-ubuntu-server-16-10
https://www.linuxquestions.org/questions/linux-server-73/samba-4-5-issues-4175597252/
https://serverfault.com/questions/1026344/how-can-i-setup-nat-on-my-openvpn-server-for-the-client
https://arashmilani.com/post?id=53
https://unix.stackexchange.com/questions/283801/iptables-forward-traffic-to-vpn-tunnel-if-open
https://aranel.net/tech/raspberrypi-openvpn
https://forums.openvpn.net/viewtopic.php?t=29880
https://superuser.com/questions/168128/openvpn-can-connect-but-cant-ping-or-access-the-server
https://chat.openai.com AI prompt: “create detailed instructions for the integration of google authenticator with openvpn”
In this post, we use the server automation tools Ansible, Terraform, Docker, and Kubernetes to create and configure virtual machines (VMs) to host an on-premises Kubernetes cluster.
Infrastructure refers to computing resources used to store, transform, and exchange data. A new approach to software development called DevOps deploys applications across distributed systems consisting of multiple physical and virtual machines.
DevOps is an approach to software development and system administration that views system administration as a task to be automated, so that software developers are not dependent on the services of a system administrator when they deploy software to server infrastructure.
DevOps tools automate the creation and deployment of servers to create a distributed software infrastructure on which software can be deployed and run on multiple computers whether physical or virtual.
The term “cloud” refers to computing services that are offsite, outsourced, and virtualized. These cloud services are provided by companies including Amazon AWS, Google GCP, Microsoft Azure, and Digital Ocean.
The term “On-premises” (“onprem”) refers to computing services that are onsite, in-house, and virtualized. Onprem virtualization servers can provide the same software environment as cloud providers. Onprem server infrastructure can be used to develop and test new software before it is deployed to a public cloud.
Virtual machines require a physical machine containing processors, memory, and storage. For this exercise, we will reformat a circa 2015 laptop (i7-4712HQ, 16GB RAM, 1TB SSD) with Ubuntu Linux 22.04 LTS as an on-premises virtualization host.
KVM creates a hypervisor virtualization host on a Linux server. A KVM hypervisor can host multiple virtual machine (VM) guests.
Terraform can run scripts that automate the creation of virtual machines, on public clouds such as Amazon AWS, Google GCP, and Digital Ocean, as well as on on-premises (“onprem”) virtualization hosts including KVM.
The libvirt provider software enables Terraform to automate the creation of virtual machines on KVM hypervisor hosts.
Ansible can run scripts that automate server administration tasks. In this exercise, multiple Ansible scripts will be executed to use Terraform to create virtual machine (VM) servers, on which software will be deployed and configured, creating a Kubernetes cluster.
A virtual machine (VM) guest is a server that emulates hardware as a software image, using a subset of the hypervisor host’s processor cores, memory, and storage to create a distinct computer environment, with its own software libraries, network address, and password or key entry system.
Docker containers are software containers created by the docker-compose command. A Docker container has its own software libraries, network address, and password or key entry system, but comparisons between Docker containers and virtual machines (VMs) are discouraged.
Kubernetes is software that allows you to create a high-availability cluster consisting of a control plane server and one or more worker servers. Kubernetes allows for software to be deployed as containers stored in pods, running on clusters, running on nodes.
Software is organized within Docker containers. A Docker container is a self-contained computing environment with its own libraries, IP address, and SSH password or key.
Pods are a unit of computing that contain one or more containers. Pods execute on clusters, which are intermediate interfaces that distribute computing tasks across control plane and worker nodes, running on virtual machine servers.
A cluster is an addressable interface that allows for the execution of Kubernetes Pods across a distributed system of control plane and worker nodes.
In Kubernetes, a node is the physical or virtual machine that hosts the control plane role or worker role in a distributed Kubernetes cluster. In this exercise the nodes will be hosted on KVM virtual machines (VMs).
The automation server is a Linux server separate from the virtualization server. The automation server can be a physical or virtual machine.
Tip: avoid running operations like this from your baremetal desktop. These operations involve hosts files and SSH keys for server access, and should be isolated if possible. Consider creating a virtual machine for this role using a hypervisor such as KVM on Linux, VirtualBox on Windows, or Parallels on MacOS. Use Ubuntu Linux 22.04 LTS.
This procedure assumes that you are entering commands as root. Escalate to the root user:
sudo su
The virtualization server should be a minimal build: do a fresh format of Ubuntu Linux 22.04 LTS.
If possible, use a wired Ethernet connection for the network connection on the hypervisor. This simplifies advanced operations like iptables forwarding and makes possible the later use of macvtap adapters for connecting in the hypervisor host networking space.
Set a static IP address for the network connection of the virtualization server. Reboot.
From a root shell on the virtualization server, enter the following command:
apt install ifconfig net-tools iptraf-ng openssh-server
From a root shell on the virtualization server, enter the following commands:
cd /etc/ssh
Use the nano editor to create the following text file:
nano sshd_config
uncomment and replace the following line:
PermitRootLogin yes
sudo su
passwd
Configure a virtual machine on a different physical machine than the virtualization server. Use Ubuntu Linux 22.04 LTS.
For KVM, add a macvtap network adapter to the automation server. For VirtualBox or Parallels, add a bridge mode network adapter. This will allow the automation server to access internal subnets on the virtualization server via an ip route command.
From a root shell on the automation server, enter the following commands:
apt install ansible git openssh-server net-tools iptraf-ng
cd /root
mkdir tmpops
cd tmpops
git clone https://github.com/kubealex/libvirt-k8s-provisioner.git
cd /etc
mkdir ansible
cd ansible
Use the nano editor to create the following text file (use the IP address of the virtualization server in your setup):
nano hosts
contents:
[vm_host]
192.168.56.60
From a root shell on the automation server, enter the following command:
ssh-keygen -f /root/.ssh/id_rsa -q -N ""
When prompted for a passphrase, press Enter and provide a blank value.
From a root shell on the automation server, enter the following commands (substitute the IP address of the virtualization server in your setup):
cd /root/.ssh
rsync -e ssh -raz id_rsa.pub root@192.168.56.60:/root/.ssh/authorized_keys
From a root shell on the virtualization server, enter the following commands:
cd /root/.ssh
ls -la
Verify that the file authorized_keys is listed:
root@henderson:/home/desktop# cd /root/.ssh
root@henderson:~/.ssh# ls -la
total 20
drwx------ 2 root root 4096 Jul 29 05:51 .
drwx------ 11 root root 4096 Jul 29 06:25 ..
-rw-r--r-- 1 root root 565 Jul 28 08:18 authorized_keys
-rw------- 1 root root 978 Jul 29 05:50 known_hosts
-rw-r--r-- 1 root root 142 Jul 29 05:50 known_hosts.old
From the automation server, enter the folowing command (substitute the IP address of your virtualization server):
ssh root@192.168.56.60
Note: If you are able to login without supplying a password, you have succeeded.
Ansible can run scripts called playbooks to perform automated server administration tasks. Ansible playbook scripts will use Terraform to create and configure virtual machines (VMs) on which a Kubernetes cluster will be installed.
The libvirt-k8s-provisioner project provides a set of scripts that use Ansible and Terraform to create virtual machines (VMs) and to deploy a Kubernetes cluster.
cd /root/tmpops/libvirt-k8s-provisioner/vars
nano k8s_cluster.yml
k8s:
cluster_name: k8s-test
cluster_os: Ubuntu
cluster_version: 1.24
container_runtime: crio
master_schedulable: false
# Nodes configuration
control_plane:
vcpu: 2
mem: 2
vms: 3
disk: 30
worker_nodes:
vcpu: 2
mem: 2
vms: 1
disk: 30
# Network configuration
network:
network_cidr: 192.168.200.0/24
domain: k8s.test
additional_san: ""
pod_cidr: 10.20.0.0/16
service_cidr: 10.110.0.0/16
cni_plugin: cilium
rook_ceph:
install_rook: true
volume_size: 50
rook_cluster_size: 1
# Ingress controller configuration [nginx/haproxy]
ingress_controller:
install_ingress_controller: true
type: haproxy
node_port:
http: 31080
https: 31443
# Section for metalLB setup
metallb:
install_metallb: true
l2:
iprange: 192.168.200.210-192.168.200.250
From a root shell on the virtualization server, enter the following commands:
cd /root/tmpops/libvirt-k8s-provisioner
ansible-galaxy collection install -r requirements.yml
From a root shell on the virtualization server, enter the following commands:
ansible-playbook main.yml
The task sequence will end with this error:
fatal: [k8s-test-worker-0.k8s.test]: FAILED! => {"changed": false, "elapsed": 600, "msg": "timed out waiting for ping module test: Failed to connect to the host via ssh: ssh: Could not resolve hostname k8s-test-worker-0.k8s.test: Name or service not known"}
fatal: [k8s-test-master-0.k8s.test]: FAILED! => {"changed": false, "elapsed": 600, "msg": "timed out waiting for ping module test: Failed to connect to the host via ssh: ssh: Could not resolve hostname k8s-test-master-0.k8s.test: Name or service not known"}
Note: we will recover from this error in a later step.
From a root shell on the virtualization server, enter the following command:
virsh net-dhcp-leases k8s-test
Information about the virtual machines in the k8s-test network will be displayed:
root@henderson:/home/desktop# virsh net-dhcp-leases k8s-test
Expiry Time MAC address Protocol IP address Hostname Client ID or DUID
--------------------------------------------------------------------------------------------------------------------------------------------------------
2022-07-29 07:21:42 52:54:00:4a:20:99 ipv4 192.168.200.99/24 k8s-test-master-0 ff:b5:5e:67:ff:00:02:00:00:ab:11:28:1f:a1:fb:24:5c:f5:70
2022-07-29 07:21:42 52:54:00:86:29:8f ipv4 192.168.200.28/24 k8s-test-worker-0 ff:b5:5e:67:ff:00:02:00:00:ab:11:9e:22:e1:40:72:21:cf:9d
Take note of the IP addresses starting with 192.168.200, these values will be needed in a later configuration step.
By default, virtual machines are created with IP addresses in the 192.168.200.x subnet. This subnet is accessible within the virtualization server.
In order to make the 192.168.200.x subnet accessible to the automation server, we need to create a gateway router using iptables directives on the virtualization server.
In a later step, we will add a default route for the 192.168.200.x subnet on the automation server, allowing it to resolve IP addresses in that subnet.
From a root shell on the virtualization server, enter the following commands:
Use the nano editor to create the following text file:
cd /etc
nano sysctl.conf
Add the following line to the end of the sysctl.conf file:
net.ipv4.ip_forward = 1
Enter this command:
sysctl -p
Use the nano editor to create the following text file (substitute the wanadaptername and wanadapterip for those of the virtualization server in your setup):
nano forward.sh
contents:
#!/usr/bin/bash
# values
kvmsubnet="192.168.200.0/24"
wanadaptername="eno1"
wanadapterip="192.168.56.60"
kvmadaptername="k8s-test"
kvmadapterip="192.168.200.1"
# allow virtual adapter to accept packets from outside the host
iptables -I FORWARD -i $wanadaptername -o $kvmadaptername -d $kvmsubnet -j ACCEPT
iptables -I FORWARD -i $kvmadapterip -o $wanadaptername -s $kvmsubnet -j ACCEPT
iptables --table nat --append POSTROUTING --out-interface eth1 -j MASQUERADE
Enter the following commands:
chmod 755 forward.sh
bash forward.sh
Note: add invocation to /etc/rc.local for persistence.
From a root shell on the automation server, enter the following commands:
Use the nano editor to create the following text file:
cd /etc
nano sysctl.conf
Add the following line to the end of the sysctl.conf file:
net.ipv4.ip_forward = 1
Enter this command:
sysctl -p
Use the nano editor to modify the /etc/hosts file:
nano hosts
Add the following lines (substitute the IP addresses observed earlier in “Preparing the virtualization server 3/3”):
192.168.200.99 k8s-test-master-0.k8s.test
192.168.200.28 k8s-test-worker-0.k8s.test
From a root shell on the automation server, enter the following command (substitute the wanadaptername (dev) and wanadapterip for those of the virtualization server in your setup):
ip route add 192.168.200.0/24 via 192.168.56.60 dev enp0s3
Note: add invocation to /etc/rc.local for persistence.
Ping one of the IP addresses you observed in the preceding step “Preparing the virtualization server 3/3” (Substitute one of the IP addresses in your setup):
ping 192.168.200.99
From a root shell on the automation server, enter the following commands:
cd /root/tmpops/libvirt-k8s-provisioner
ansible-playbook main.yml
Sample output:
PLAY RECAP *******************************************************************************************************************************************************************************************************************************
192.168.56.60 : ok=76 changed=24 unreachable=0 failed=0 skipped=32 rescued=0 ignored=0
k8s-test-master-0.k8s.test : ok=49 changed=28 unreachable=0 failed=0 skipped=28 rescued=0 ignored=0
k8s-test-worker-0.k8s.test : ok=38 changed=24 unreachable=0 failed=0 skipped=28 rescued=0 ignored=0
From a root shell on the automation server, enter the following command (substitute the IP address of a VM in your setup):
ssh kube@192.168.200.99
When prompted, enter the password: “kuberocks”
From a root shell on the control plane (obsolete term “master”) VM server, enter the following command:
kubectl get pods –all-namespaces
Output:
Pending 0 113m
rook-ceph rook-ceph-mds-ceph-filesystem-a-868694c95d-85r54 1/1 Running 0 113m
rook-ceph rook-ceph-mds-ceph-filesystem-b-748dc85c96-qktmb 1/1 Running 0 113m
rook-ceph rook-ceph-mgr-a-7f6784d748-cg9v8 1/1 Running 0 115m
rook-ceph rook-ceph-mon-a-6f9d4bc99b-fgc2g 1/1 Running 0 116m
rook-ceph rook-ceph-operator-f4ccf8fc-f5rcl 1/1 Running 0 119m
rook-ceph rook-ceph-osd-0-7b6fbf8657-lktsx 0/1 CrashLoopBackOff 27 (38s ago) 114m
rook-ceph rook-ceph-osd-prepare-k8s-test-worker-0.k8s.test-j79rg 0/1 Completed 0 114m
rook-ceph rook-ceph-rgw-ceph-objectstore-a-64b5fd4d9b-77krx 0/1 Running 20 (7m43s ago) 110m
root@austin:/root/tmpops/libvirt-k8s-provisioner# ansible-playbook main.yml
[WARNING]: Collection community.general does not support Ansible version 2.10.8
PLAY [Pre-flight checklist before installing k8s] ****************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Check if distribution is supported] ************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check if target distribution is correct] *******************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check if Docker is selected on 1.24] ***********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check at least one vm for control plane is defined] ********************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check if master is schedulable in case of clusters composed by control plane VMs] **************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if Rook cluster size exceeds worker nodes.] ******************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if no container runtime is defined] **************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if no ingress controller is selected] ************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if no container plugin selected] *****************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
PLAY [This play installs needed tools to provision infrastructure VMs] *******************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Upgrade all packages] **************************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Install required packages] *********************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Install required packages] *********************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Upgrade all packages] **************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Install required packages] *********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Download and provision Terraform] **************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Virtualization services are enabled] ***********************************************************************************************************************************************************************************************
ok: [192.168.56.60]
PLAY [This play ensures environment is set up for cluster creation] **********************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [ansible.builtin.set_fact] **********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure needed pip packages are present] ********************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=PyYAML)
changed: [192.168.56.60] => (item=kubernetes)
changed: [192.168.56.60] => (item=jsonpatch)
ok: [192.168.56.60] => (item=netaddr)
TASK [Ensure workspace directory exists] *************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure cluster folder exists] ******************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure pivot tmp folder exists] ****************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Populate cluster folder with terraform files] **************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Snapshot cluster configuration for further use] ************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure helm is installed] **********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Install helm in PATH] **************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Install Helm Diff] *****************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [remove directory] ******************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Retrieve the minor version] ********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Create ssh keypair] ****************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Copy SSH keys in working directory] ************************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item=id_rsa_k8s-test)
changed: [192.168.56.60] => (item=id_rsa_k8s-test.pub)
TASK [Getting ssh private key] ***********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Getting ssh public key] ************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [ansible.builtin.set_fact] **********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Download CentOS image] *************************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Download Ubuntu image] *************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
PLAY [This play provisions libvirt resources with terraform] *****************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Use TF project to ensure pool and network are defined] *****************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure security_driver is disabled] ************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Restart libvirtd service] **********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure systemd-resolved config dir is present] *************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Enable localdns if systemd-resolved is present] ************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure NM configuration directory exists] ******************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure NM dnsmasq directory exists] ************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Configure NetworkManager for local DNS] ********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Configure NetworkManager for libvirt network] **************************************************************************************************************************************************************************************
changed: [192.168.56.60]
RUNNING HANDLER [Restart systemd-resolved] ***********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
RUNNING HANDLER [Restart NetworkManager] *************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
RUNNING HANDLER [Wait for local DNS resolver to be up] ***********************************************************************************************************************************************************************************
skipping: [192.168.56.60]
PLAY [This play provisions k8s VMs based on intial config] *******************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure control plane VMs are in place] *********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure worker VMs are in place] ****************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure Rook dedicated worker VMs are in place] *************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Add masters to given group] ********************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=0)
TASK [Add workers to given group] ********************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=0)
TASK [Ensure to clean known_hosts] *******************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=k8s-test-master-0.k8s.test)
ok: [192.168.56.60] => (item=k8s-test-worker-0.k8s.test)
PLAY [Check connection and set facts] ****************************************************************************************************************************************************************************************************
TASK [Wait 600 seconds for target connection to become reachable/usable] *****************************************************************************************************************************************************************
fatal: [k8s-test-worker-0.k8s.test]: FAILED! => {"changed": false, "elapsed": 600, "msg": "timed out waiting for ping module test: Failed to connect to the host via ssh: ssh: Could not resolve hostname k8s-test-worker-0.k8s.test: Name or service not known"}
fatal: [k8s-test-master-0.k8s.test]: FAILED! => {"changed": false, "elapsed": 600, "msg": "timed out waiting for ping module test: Failed to connect to the host via ssh: ssh: Could not resolve hostname k8s-test-master-0.k8s.test: Name or service not known"}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************
192.168.56.60 : ok=44 changed=26 unreachable=0 failed=0 skipped=14 rescued=0 ignored=0
k8s-test-master-0.k8s.test : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
k8s-test-worker-0.k8s.test : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
root@austin:/root/tmpops/libvirt-k8s-provisioner# ansible-playbook main.yml
[WARNING]: Collection community.general does not support Ansible version 2.10.8
PLAY [Pre-flight checklist before installing k8s] ****************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Check if distribution is supported] ************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check if target distribution is correct] *******************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check if Docker is selected on 1.24] ***********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check at least one vm for control plane is defined] ********************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Check if master is schedulable in case of clusters composed by control plane VMs] **************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if Rook cluster size exceeds worker nodes.] ******************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if no container runtime is defined] **************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if no ingress controller is selected] ************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Fail fast if no container plugin selected] *****************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
PLAY [This play installs needed tools to provision infrastructure VMs] *******************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Upgrade all packages] **************************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Install required packages] *********************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Install required packages] *********************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Upgrade all packages] **************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Install required packages] *********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Download and provision Terraform] **************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Virtualization services are enabled] ***********************************************************************************************************************************************************************************************
ok: [192.168.56.60]
PLAY [This play ensures environment is set up for cluster creation] **********************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [ansible.builtin.set_fact] **********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure needed pip packages are present] ********************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=PyYAML)
ok: [192.168.56.60] => (item=kubernetes)
ok: [192.168.56.60] => (item=jsonpatch)
ok: [192.168.56.60] => (item=netaddr)
TASK [Ensure workspace directory exists] *************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure cluster folder exists] ******************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure pivot tmp folder exists] ****************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Populate cluster folder with terraform files] **************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Snapshot cluster configuration for further use] ************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure helm is installed] **********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Install helm in PATH] **************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Install Helm Diff] *****************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [remove directory] ******************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Retrieve the minor version] ********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Create ssh keypair] ****************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Copy SSH keys in working directory] ************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=id_rsa_k8s-test)
ok: [192.168.56.60] => (item=id_rsa_k8s-test.pub)
TASK [Getting ssh private key] ***********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Getting ssh public key] ************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [ansible.builtin.set_fact] **********************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Download CentOS image] *************************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Download Ubuntu image] *************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
PLAY [This play provisions libvirt resources with terraform] *****************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Use TF project to ensure pool and network are defined] *****************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure security_driver is disabled] ************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Restart libvirtd service] **********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure systemd-resolved config dir is present] *************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Enable localdns if systemd-resolved is present] ************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure NM configuration directory exists] ******************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure NM dnsmasq directory exists] ************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Configure NetworkManager for local DNS] ********************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Configure NetworkManager for libvirt network] **************************************************************************************************************************************************************************************
ok: [192.168.56.60]
PLAY [This play provisions k8s VMs based on intial config] *******************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure control plane VMs are in place] *********************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure worker VMs are in place] ****************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure Rook dedicated worker VMs are in place] *************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Add masters to given group] ********************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=0)
TASK [Add workers to given group] ********************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=0)
TASK [Ensure to clean known_hosts] *******************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => (item=k8s-test-master-0.k8s.test)
ok: [192.168.56.60] => (item=k8s-test-worker-0.k8s.test)
PLAY [Check connection and set facts] ****************************************************************************************************************************************************************************************************
TASK [Wait 600 seconds for target connection to become reachable/usable] *****************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
TASK [ansible.builtin.ping] **************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
TASK [Add hosts to correct groups] *******************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Extract facts from setup] **********************************************************************************************************************************************************************************************************
ok: [k8s-test-worker-0.k8s.test]
ok: [k8s-test-master-0.k8s.test]
TASK [ansible.builtin.set_fact] **********************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
PLAY [This play provisions loadbalancer VM for control plane] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure Load Balancer VM is in place] ***********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Add loadbalancer to inventory] *****************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Ensure to clean known_hosts] *******************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
[WARNING]: Could not match supplied host pattern, ignoring: loadbalancer
PLAY [Check connection to loadbalancer] **************************************************************************************************************************************************************************************************
skipping: no hosts matched
PLAY [Loadbalancer configuration play] ***************************************************************************************************************************************************************************************************
skipping: no hosts matched
PLAY [Install container runtime] *********************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
TASK [Retrieve the minor version] ********************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
TASK [Upgrade all packages] **************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Upgrade all packages] **************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Add modules to autostart] **********************************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test]
changed: [k8s-test-master-0.k8s.test]
TASK [Enable br_netfilter] ***************************************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test] => (item=br_netfilter)
changed: [k8s-test-master-0.k8s.test] => (item=br_netfilter)
changed: [k8s-test-master-0.k8s.test] => (item=overlay)
changed: [k8s-test-worker-0.k8s.test] => (item=overlay)
TASK [Enable sysctl values] **************************************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})
changed: [k8s-test-master-0.k8s.test] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})
changed: [k8s-test-master-0.k8s.test] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
changed: [k8s-test-worker-0.k8s.test] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
changed: [k8s-test-worker-0.k8s.test] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
changed: [k8s-test-master-0.k8s.test] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
TASK [Setup sysctl] **********************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Ensure sysctl is restarted] ********************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Ensure required packages are present] **********************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Add docker repo key] ***************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure the presence of apt-repo for docker] ****************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure docker packages are installed] **********************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure required packages are present] **********************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Add docker repository] *************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure docker is installed] ********************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Create /etc/docker] ****************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Copy docker configuration in /etc/docker] ******************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Create systemd folder for Docker service] ******************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Force systemd to reread configs] ***************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure docker is enabled and started] **********************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Add crio repo key] *****************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test] => (item={'key': 'https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_22.04/Release.key', 'keyring': '/etc/apt/trusted.gpg.d/libcontainers.gpg'})
changed: [k8s-test-worker-0.k8s.test] => (item={'key': 'https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_22.04/Release.key', 'keyring': '/etc/apt/trusted.gpg.d/libcontainers.gpg'})
changed: [k8s-test-master-0.k8s.test] => (item={'key': 'https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:/1.24/xUbuntu_22.04/Release.key', 'keyring': '/etc/apt/trusted.gpg.d/libcontainers-cri-o.gpg'})
changed: [k8s-test-worker-0.k8s.test] => (item={'key': 'https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:/1.24/xUbuntu_22.04/Release.key', 'keyring': '/etc/apt/trusted.gpg.d/libcontainers-cri-o.gpg'})
TASK [Ensure the presence of apt-repo for cri-o] *****************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test] => (item={'repo': 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_22.04/ /', 'file': '/etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list'})
changed: [k8s-test-master-0.k8s.test] => (item={'repo': 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_22.04/ /', 'file': '/etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list'})
changed: [k8s-test-worker-0.k8s.test] => (item={'repo': 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.24/xUbuntu_22.04/ /', 'file': '/etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:1.24.list'})
changed: [k8s-test-master-0.k8s.test] => (item={'repo': 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.24/xUbuntu_22.04/ /', 'file': '/etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:1.24.list'})
TASK [Temporary fix for memory swap slices on 20.04] *************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Add kubic CentOS repository] *******************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test] => (item={'file': '/etc/yum.repos.d/devel:kubic:libcontainers:stable.repo', 'url': 'http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_8_Stream/devel:kubic:libcontainers:stable.repo'})
skipping: [k8s-test-master-0.k8s.test] => (item={'file': '/etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o.repo', 'url': 'http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.24/CentOS_8_Stream/devel:kubic:libcontainers:stable:cri-o:1.24.repo'})
skipping: [k8s-test-worker-0.k8s.test] => (item={'file': '/etc/yum.repos.d/devel:kubic:libcontainers:stable.repo', 'url': 'http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_8_Stream/devel:kubic:libcontainers:stable.repo'})
skipping: [k8s-test-worker-0.k8s.test] => (item={'file': '/etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o.repo', 'url': 'http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.24/CentOS_8_Stream/devel:kubic:libcontainers:stable:cri-o:1.24.repo'})
TASK [Ensure cri-o is installed - CentOS] ************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure cri-o is installed - Ubuntu] ************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure cri-o is installed - Ubuntu] ************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Fire crio-conf template] ***********************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Fire crio-conf template] ***********************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Remove example CNI configs] ********************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test] => (item=100-crio-bridge.conf)
changed: [k8s-test-worker-0.k8s.test] => (item=100-crio-bridge.conf)
changed: [k8s-test-master-0.k8s.test] => (item=200-loopback.conf)
changed: [k8s-test-worker-0.k8s.test] => (item=200-loopback.conf)
TASK [Force systemd to reread configs] ***************************************************************************************************************************************************************************************************
ok: [k8s-test-worker-0.k8s.test]
ok: [k8s-test-master-0.k8s.test]
TASK [Ensure cri-o is enabled and started] ***********************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Ensure required packages are present] **********************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Add containerd repository] *********************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure containerd is installed] ****************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure containerd is configured and installed on Ubuntu machine] *******************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Create /etc/containers] ************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Initialize config] *****************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Force systemd to reread configs] ***************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure containerd is enabled and started] ******************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Reboot nodes before proceeding] ****************************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test]
changed: [k8s-test-master-0.k8s.test]
PLAY [Ensure kube packages are installed] ************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [k8s-test-worker-0.k8s.test]
ok: [k8s-test-master-0.k8s.test]
TASK [Add Kubernetes repository] *********************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Ensure required packages for kubetools are installed] ******************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Add kube-repo key] *****************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Ensure the presence of apt-repo for kubernetes packages] ***************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Ensure Kubernetes packages are installed] ******************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Ensure kubelet, kubeadm, kubectl are on hold] **************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test] => (item=kubectl)
changed: [k8s-test-master-0.k8s.test] => (item=kubectl)
changed: [k8s-test-master-0.k8s.test] => (item=kubeadm)
changed: [k8s-test-worker-0.k8s.test] => (item=kubeadm)
changed: [k8s-test-master-0.k8s.test] => (item=kubelet)
changed: [k8s-test-worker-0.k8s.test] => (item=kubelet)
TASK [Disable swap] **********************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
changed: [k8s-test-worker-0.k8s.test]
TASK [Remove swap entry from fstab] ******************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
TASK [Disable SELinux] *******************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Install kubepackages] **************************************************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Install lvm2 for rook support and git for installing rook] *************************************************************************************************************************************************************************
skipping: [k8s-test-master-0.k8s.test]
skipping: [k8s-test-worker-0.k8s.test]
TASK [Install lvm2 for rook support and git for installing rook] *************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
TASK [Enable kubelet] ********************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
ok: [k8s-test-worker-0.k8s.test]
PLAY [Prepare kubeadm-config for cluster setup] ******************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Generate cluster token] ************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
TASK [Set generated token as fact] *******************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Generate certificate key] **********************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
TASK [Set generated token as fact] *******************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Add kubelet config for node] *******************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
PLAY [Install cluster with kubeadm] ******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Start kubeadm install] *************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
TASK [Get information on generated certificate] ******************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Set fact for certificate hash] *****************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Create kube directory] *************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
TASK [Copy kubeconfig] *******************************************************************************************************************************************************************************************************************
changed: [k8s-test-master-0.k8s.test]
TASK [Fetch kubeconfig file] *************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [Set kubeconfig as fact] ************************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
TASK [ansible.builtin.set_fact] **********************************************************************************************************************************************************************************************************
ok: [k8s-test-master-0.k8s.test]
PLAY [Verify cluster has been initialized] ***********************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Save kubeconfig as file] ***********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Wait for control-plane pods to be up and running] **********************************************************************************************************************************************************************************
skipping: [192.168.56.60]
PLAY [Play to join control plane nodes in the cluster] ***********************************************************************************************************************************************************************************
skipping: no hosts matched
PLAY [Play to join nodes in the cluster] *************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [k8s-test-worker-0.k8s.test]
TASK [Fire joinConfiguration template for worker nodes] **********************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test]
TASK [Join worker nodes in cluster] ******************************************************************************************************************************************************************************************************
changed: [k8s-test-worker-0.k8s.test]
TASK [Mark node as joined] ***************************************************************************************************************************************************************************************************************
ok: [k8s-test-worker-0.k8s.test]
PLAY [Apply network plugin] **************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Download Calico manifest.] *********************************************************************************************************************************************************************************************************
skipping: [192.168.56.60] => (item={'name': '/tmp/k8s-test/calico-operator.yaml', 'url': 'https://docs.projectcalico.org/manifests/tigera-operator.yaml'})
skipping: [192.168.56.60] => (item={'name': '/tmp/k8s-test/calico-crd.yaml', 'url': 'https://docs.projectcalico.org/manifests/custom-resources.yaml'})
TASK [Apply custom CIDR to calico installation manifest] *********************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Temporary fix for non ascii char in Calico CRD (https://github.com/projectcalico/api/pull/46)] *************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Apply calico manifests to the cluster.] ********************************************************************************************************************************************************************************************
skipping: [192.168.56.60] => (item=/tmp/k8s-test/calico-operator.yaml)
skipping: [192.168.56.60] => (item=/tmp/k8s-test/calico-crd.yaml)
TASK [Add helm chart repository for Cilium] **********************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item={'name': 'cilium', 'repo_url': 'https://helm.cilium.io/'})
TASK [Ensure Cilium helm chart is installed] *********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Download flannel manifest] *********************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Patch kube-flannel to use host-gw instead of vxlan] ********************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Apply flannel manifests to the cluster.] *******************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Wait for core-dns pods to be up and running] ***************************************************************************************************************************************************************************************
changed: [192.168.56.60]
PLAY [Complete cluster setup] ************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Prepare playbook for cluster deletion] *********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Delete image file] *****************************************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item=/tmp/OS-GenericCloud.qcow2)
TASK [Label worker nodes] ****************************************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item=k8s-test-worker-0.k8s.test)
TASK [Remove taint from master nodes] ****************************************************************************************************************************************************************************************************
skipping: [192.168.56.60] => (item=k8s-test-master-0.k8s.test)
PLAY [Save inventory to disk] ************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Gather facts from all servers] *****************************************************************************************************************************************************************************************************
ok: [192.168.56.60 -> k8s-test-master-0.k8s.test] => (item=k8s-test-master-0.k8s.test)
ok: [192.168.56.60 -> k8s-test-worker-0.k8s.test] => (item=k8s-test-worker-0.k8s.test)
ok: [192.168.56.60 -> 192.168.56.60] => (item=192.168.56.60)
TASK [Fire up inventory template] ********************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [ansible.builtin.debug] *************************************************************************************************************************************************************************************************************
ok: [192.168.56.60] => {
"msg": "Inventory is now saved as k8s-test-inventory-k8s, you can resume next steps by referencing it."
}
PLAY [Prepare cluster to install ingress controller] *************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure the needed Namespaces exist.] ***********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Add helm chart repository for Contour] *********************************************************************************************************************************************************************************************
skipping: [192.168.56.60] => (item={'name': 'bitnami', 'repo_url': 'https://charts.bitnami.com/bitnami'})
TASK [Ensure Contour helm chart is installed] ********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Ensure the needed Namespaces exist.] ***********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Add helm chart repository for haproxy] *********************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item={'name': 'haproxytech', 'repo_url': 'https://haproxytech.github.io/helm-charts'})
TASK [Ensure haproxy helm chart is installed] ********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure the needed Namespaces exist.] ***********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
TASK [Add helm chart repository for Nginx] ***********************************************************************************************************************************************************************************************
skipping: [192.168.56.60] => (item={'name': 'ingress-nginx', 'repo_url': 'https://kubernetes.github.io/ingress-nginx'})
TASK [Ensure Nginx helm chart is installed] **********************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
PLAY [Refresh facts] *********************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [k8s-test-worker-0.k8s.test]
ok: [k8s-test-master-0.k8s.test]
ok: [192.168.56.60]
PLAY [Trigger new haproxy configuration] *************************************************************************************************************************************************************************************************
skipping: no hosts matched
PLAY [Save new haproxy configuration] ****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Fire up new haproxy template] ******************************************************************************************************************************************************************************************************
skipping: [192.168.56.60]
PLAY [Prepare cluster to install rook] ***************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure the needed Namespaces exist.] ***********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Add helm chart repository for Rook] ************************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item={'name': 'rook-release', 'repo_url': 'https://charts.rook.io/release'})
ok: [192.168.56.60] => (item={'name': 'rook-release', 'repo_url': 'https://charts.rook.io/release'})
TASK [Ensure rook-operator helm chart is installed] **************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Trigger rook template] *************************************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Ensure rook-ceph-cluster helm chart is installed] **********************************************************************************************************************************************************************************
changed: [192.168.56.60]
PLAY [Prepare cluster to install metalLB] ************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Render template for L2 configuration] **********************************************************************************************************************************************************************************************
changed: [192.168.56.60]
TASK [Download metal-lb CR for later apply] **********************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item={'name': '/tmp/k8s-test/metallb-ns.yaml', 'url': 'https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml'})
changed: [192.168.56.60] => (item={'name': '/tmp/k8s-test/metallb.yaml', 'url': 'https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml'})
TASK [Ensure metal-lb namespace is present] **********************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item=/tmp/k8s-test/metallb-ns.yaml)
TASK [Ensure metal-lb is installed in your cluster] **************************************************************************************************************************************************************************************
changed: [192.168.56.60] => (item=/tmp/k8s-test/metallb.yaml)
TASK [Render template for L2 configuration] **********************************************************************************************************************************************************************************************
ok: [192.168.56.60]
TASK [Ensure metal-lb configmap is added in your cluster] ********************************************************************************************************************************************************************************
changed: [192.168.56.60]
PLAY RECAP *******************************************************************************************************************************************************************************************************************************
192.168.56.60 : ok=76 changed=24 unreachable=0 failed=0 skipped=32 rescued=0 ignored=0
k8s-test-master-0.k8s.test : ok=49 changed=28 unreachable=0 failed=0 skipped=28 rescued=0 ignored=0
k8s-test-worker-0.k8s.test : ok=38 changed=24 unreachable=0 failed=0 skipped=28 rescued=0 ignored=0
https://www.armosec.io/blog/setting-up-kubernetes-cluster/
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
https://linuxconfig.org/how-to-install-kubernetes-on-ubuntu-22-04-jammy-jellyfish-linux
https://subok-tech.com/installing-kubernetes-using-ansible-on-ubuntu-20-04/
https://projectcalico.docs.tigera.io/getting-started/kubernetes/quickstart
https://projectcalico.docs.tigera.io/getting-started/kubernetes/hardway/
https://groups.google.com/g/ansible-project/c/YTl5g317SBg?pli=1
https://www.shellhacks.com/ansible-sudo-a-password-is-required/
https://fabianlee.org/2022/05/25/kvm-kubeadm-cluster-on-kvm-using-ansible/
https://thenewstack.io/install-ansible-on-ubuntu-server-to-automate-linux-server-deployments/
In this procedure we create a network file share by integrating the open source program Samba running on Linux with Active Directory to authenticate access to the network file share.
A computer running Linux and Samba can create a network file share authenticating against a company’s Active Directory. This means that a Linux server and Samba network file share software can replace a Windows server for the network file share role in the enterprise, reducing software licensing costs and improving security and stability.
This procedure was tested on Ubuntu Linux 22.04 LTS
This procedure was tested on a network of 3 virtual machines, each running in bridge mode, on different hypervisor hosts.
sudbury | Windows Server 2019 acting as Active Directory controller for the clarkcounty.gordonbuchan.com domain. |
sandiego | Ubuntu Linux 22.04LTS desktop joined to the clarkcounty.gordonbuchan.com domain, authenticating access to a network file share enabled by Samba and Winbind against the Active Directory controller for the domain clarkcounty.gordonbuchan.com on sudbury. |
hamilton | Windows 10 Pro workstation joined to the clarkcounty.gordonbuchan.com domain. |
Active Directory is commercial software developed by Microsoft that runs primarily on Windows Server. Active Directory can authenticate users and groups of users, and can control access to resources like network file shares and “Single Sign-On” (SSO) login to computers connected to the network.
Samba is open source free software that enables a Linux server to provide a network file share that can be accessed by Windows computers.
Samba itself is able to act as an Active Directory controller and can implement a subset of Active Directory’s features. This post assumes that you are authenticating against an Active Directory controller running on Windows Server.
Winbind is software that enables Samba to integrate with Active Directory to authenticate access to a network file share.
SSSD is a technology that enables Active Directory integration for Linux workstations. In practice, it is difficult to integrate SSSD with Samba for Active Directory authentication in a stable fashion. There are some approaches to SSSD which incorporate Winbind for a hybrid approach. This procedure will focus on using Winbind, and without using SSSD.
This procedure will use Winbind to enable Samba to integrate with Active Directory to create a network file share authenticated against Active Directory.
(Single-Sign-On (SSO) and SSSD will be addressed in a later procedure.)
This procedure assumes that you are logged in as the root user of the Linux server.
Escalate to the root user:
sudo su
Please replace the sample realm/domain name clarkcounty.gordonbuchan.com with your realm/domain name.
hostnamectl set-hostname sandiego.clarkcounty.gordonbuchan.com
Associate the host name of your Linux server with its IP address:
cd /etc
nano hosts
192.168.33.110 sandiego
192.168.33.110 sandiego.clarkcounty.gordonbuchan.com
Disable systemd-resolved service:
systemctl stop systemd-resolved
systemctl disable systemd-resolved
Unlink the symbolic link /etc/resolv.conf:
cd /etc
unlink resolv.conf
Ensure that the first nameserver entry is the IP address of the Active Directory server.
nano resolv.conf
nameserver 192.168.33.80
nameserver 8.8.8.8
search clarkcounty.gordonbuchan.com
reboot
apt install acl samba winbind libnss-winbind krb5-user
The realm/domain name must be in UPPERCASE letters. This includes the long version CLARKCOUNTY.GORDONBUCHAN.COM and short version CLARKCOUNTY of the realm/domain name.
cd /etc
cp krb5.conf krb5.conf.orig
nano krb5.conf
[libdefaults]
default_realm = CLARKCOUNTY.GORDONBUCHAN.COM
dns_lookup_realm = false
dns_lookup_kdc = true
cd /etc
cp nsswitch.conf nsswitch.conf.orig
nano nsswitch.conf
passwd: files winbind
group: files winbind
hosts: files dns wins
chmod 550 nsswitch.conf
cd /etc/samba
cp smb.conf smb.conf.orig
nano smb.conf
[global]
realm = CLARKCOUNTY.GORDONBUCHAN.COM
security = ADS
workgroup = CLARKCOUNTY
idmap config SAMDOM : range = 10000 - 999999
idmap config SAMDOM : backend = rid
idmap config * : range = 3000-7999
idmap config * : backend = tdb
map acl inherit = Yes
vfs objects = acl_xattr
dedicated keytab file = /etc/krb5.keytab
kerberos method = secrets and keytab
winbind refresh tickets = Yes
kinit admingordon
klist
net ads info testjoin
net ads -v join -U admingordon
net ads info
systemctl restart smbd nmbd winbind
cd /home
mkdir example_share
chmod -R 2770 example_share
chown -R "CLARKCOUNTY\admingordon":"CLARKCOUNTY\example_group" example_share
cd /etc/samba
cp smb.conf smb.conf.orig
nano smb.conf
[Share]
acl_xattr:ignore system acl = Yes
acl allow execute always = Yes
acl group control = Yes
inherit acls = Yes
inherit owner = windows and unix
inherit permissions = Yes
path = /media/share
read only = No
systemctl restart smbd nmbd winbind
This SID must be mapped to the UNIX group nogroup:
net groupmap add sid=S-1-5-32-546 unixgroup=nogroup type=builtin
http://blog.jrg.com.br/2021/02/01/ubuntu-focal-fossa-samba-domain-member-shares-1/
https://docs.vmware.com/en/VMware-Horizon-7/7.13/linux-desktops-setup/GUID-F8F0CFCF-C4D6-4784-85FF-E7C6DF575F49.html
https://ubuntu.com/server/docs/service-sssd-ad
https://wiki.samba.org/index.php/Setting_up_Samba_as_a_Domain_Member
https://www.jurisic.org/post/2021/11/24/SAMBA-Domain-Member-as-File-Server
https://www.moderndeployment.com/windows-server-2019-active-directory-installation-beginners-guide/
https://www.reddit.com/r/Ubuntu/comments/h01i2w/cheat_sheet_on_how_to_configure_a_smb_file_server/
Previous step Chapter 17: Using subdomains to host multiple websites under a single domain name
Web presence step by step is a series of posts that show you to how to build a web presence.
This post describes how to install Linux as a virtual machine (VM) guest on a Windows computer, by installing a program called VirtualBox.
Installing Linux as a VM guest allows you to explore Linux as a desktop or server operating system from an existing Windows computer, without reformatting.
The software that enables a computer to host a virtual machine as a guest is called a hypervisor. The hypervisor we will install in this blog post is called VirtualBox, an open source application available free of charge.
A VM guest performs well in server roles likes web, database, and file sharing. VMs can be used for offline development and testing of websites and web-based applications, which are later deployed to public-facing web servers.
A VM guest can be used to deploy an internal or public-facing server with an application such as WordPress or Nextcloud.
Probably not. VirtualBox is great for testing, experiments, learning. However, if you are going into production, to run an essential task for a business, you should consider a more formal deployment using a platform like Linux KVM or Windows Server Hyper-V for an internal deployment, or to a public cloud like Digital Ocean or AWS for a public-facing deployment.
VirtualBox enables people to experiment with Linux, without making a commitment to modifying their existing Windows computer.
VirtualBox is great for students — anyone learning software development can host their own fully-functioning Linux server, allowing them to build prototype servers, containers, and software development environments.
A VM guest can function as a graphical desktop, allowing you to use the guest operating system in a sized window, or in full-screen mode. For example, you can connect to another network via VPN from a VM guest, while the host computer running Windows remains connected to its original network.
VMs have some limitations: they are not well-suited to GPU-intensive tasks like video editing software or gaming, for example. YouTube video will be choppy.
https://www.virtualbox.org/wiki/Downloads
https://ubuntu.com/download/desktop
The VM guest running under VirtualBox is a distinct and separate computer from the machine that hosts it. VirtualBox enables network communication between the VM guest and the Internet, via the network connection of the host.
VirtualBox also enables network communication between the VM guest and the host. For example, if you have a web server running on your VM guest, you can connect to it from your host’s desktop using a web browser or a terminal program like KiTTY for SSH.
By default, a VM guest is created with a network adapter configured to connect to the Internet via the Internet connection of its host.
The host and the VM guest are able to communicate with each other. Computers other than the host cannot see or initiate a network connection with the VM guest.
A VM guest can be made visible and accessible to other computers on the network via a bridge mode network connection, or via port forwarding.
The network adapter for a VM guest can be configured in “bridge mode” which permits the VM to connect directly to the same network as the host. In this mode, a VM guest can request an IP address or use an IP address in the same subnet as the host and other computers connected to the same network.
Due to the way that a bridge mode connection is configured to use the network connection of the host, the link permits communication between the VM guest and the outside world, but not between the VM guest and the host itself.
(Note: the VM must be powered down in order to add a network adapter.)
VirtualBox will offer to open a hole on the host’s firewall. Click on “Allow access”:
To enable remote desktop access, please refer to this post: Installing x11vnc to replace broken screen sharing on Ubuntu 21.04.
Previous step Chapter 17: Using subdomains to host multiple websites under a single domain name
After upgrading from Ubuntu 20.10 to Ubuntu 21.04, screen sharing (VNC server) is no longer functioning correctly.
Update 2023/11/02: on Ubuntu 22.04, in some situations, the x11vnc server will start on port 5901/tcp, rather than the default 5900/tcp, even if legacy VNC support is disabled.
This post describes how to install x11vnc, and describes how to create a script that runs at Gnome desktop login that invokes x11vnc with the necessary command line options.
Vino, the VNC server previously used by Gnome, has been deprecated. Vino has been replaced by gnome-remote-desktop, but as currently integrated, gnome-remote-desktop does not function correctly in Ubuntu 21.04.
When configured using the standard Gnome control panel settings (Settings, Sharing, Screen Sharing):
This is the error that appears when trying to connect, in both xorg and wayland:
A good suggested practice is to run LTS releases on production servers, but run recent releases on workstation laptops. This allows for issues to be identified and workarounds devised before the next LTS release, in case the problem persists in the next LTS release.
For some server tasks, it is helpful to be able to access the GUI desktop of the server via a remote viewer. For example, you may need to install a GUI operating system as a guest, and access its GUI desktop from the console of your server’s GUI desktop.
Wayland is an alternative to the xorg windows system. One day, it will be terrific. For now, it does not work with x11vnc or other important applications like TeamViewer.
sudo su
cd /etc/gdm3
nano custom.conf
# Uncomment the line below to force the login screen to use Xorg
WaylandEnable=false
reboot
From a shell window, enter the following commands:
sudo su
ufw allow 5900/tcp
ufw allow 5901/tcp
exit
Settings, Sharing, Screen Sharing:
From a shell window, enter the following commands:
sudo su
apt install x11vnc
exit
From a shell as the user that owns the Gnome desktop session, enter these commands. When prompted, supply a password:
whoami
x11vnc -storepasswd
Different situations can accept different levels of risk. The VNC protocol as implemented, sends data as cleartext over a network connection. This may be acceptable over a local area network, particularly if you have VLAN segmentation and good wifi encryption enabled on your house Local Area Network (LAN).
Do not even consider sending this kind of unencrypted traffic over the public Internet. Use a VPN, or redirect the connection via SSH tunnelling.
From a shell as the user that owns the Gnome desktop session, enter these commands. When prompted, supply a password:
whoami
x11vnc -display :0 -forever -shared -rfbauth /home/desktop/.vnc/passwd
From a shell window, enter the following commands:
sudo su
apt install net-tools
ifconfig
exit
(Note: the command:
ip a
provides an equivalent result. But ifconfig is easier to read.)
From another computer on the same local area network, connect to the IP address of the machine on which x11vnc is running. Attempt to connect using a VNC client such as RealVNC, tightvnc, or remmina:
From a shell as the user that owns the Gnome desktop session, enter these commands:
cd ~
whoami
nano x11vncstartup.sh
Enter this text. Press Control-X to save and exit:
#!/usr/bin/bash
x11vnc -display :0 -forever -shared -rfbauth /home/desktop/.vnc/passwd
Enter this command:
chmod 755 x11vncstartup.sh
From a shell as the user that owns the Gnome desktop session, enter these commands:
cd ~
./x11vncstartup.sh
Test as described earlier in the section “Testing the x11vnc screen sharing server.”
Go to Show Applications. search for “startup applications,” click on its icon:
Click Add:
Name: x11vncstartup.sh
Click the “Browse…” button. Select the file x11vncstartup.sh, Click “Open”:
Comment: x11vncstartup.sh
Click on “Add”:
Click on “Close”:
Reboot the computer. Log into the computer’s desktop.
Test as described earlier in the section “Testing the x11vnc screen sharing server.”
Ma présentation à Linux-Meetup Montréal décrivant comment héberger Windows Server 2019 en tant qu’invité virtuel sous Linux KVM, et comment configurer Samba pour respecter Active Directory pour le stockage de fichiers réseau.
https://blog.gordonbuchan.com/files/linuxkvmwindowssamba27.pdf
Previous step Chapter 16: Using a script to automate the creation of a virtual host on an Apache web server
Next step: Chapter 18: Installing VirtualBox on a computer running Windows to host Linux as a virtual machine (VM) guest
Web presence step by step is a series of posts that show you to how to build a web presence.
In this post, we learn how to declare multiple subdomain names under a single domain name for use as virtual host names, for multiple separate websites.
A shared LAMP web server can host multiple websites, or “virtual hosts,” named after domain and subdomain names.
You may wish to host a web-based application like MyBB or Nextcloud as its own website, rather than as a subdirectory of an existing website, without purchasing an additional domain name.
Multiple subdomains can be hosted on the same web server, or on different web servers.
A virtual host can be identified by a “bare” domain name like “webpresencestepbystep.com,” or by a subdomain name, like “www.webpresencestepbystep.com” — by convention, the www subdomain prefix points to the same content as the “bare” domain name.
Additional subdomain names can be declared like “community.webpresencestepbystep.com” and “media.webpresencestepbystep.com” – these subdomains can point to separate websites on the same web server, or on different web servers.
As we can see in the DNS zone for the domain, the host names “@” (“bare domain”) and “community” are A declarations associated with the IP address of web server A.
The host name “www” is a CNAME declaration associated with the host name “@” so implicitly is associated with the IP address of web server A.
The host name “media” is an A declaration associated with the IP address of web server B.
By using multiple subdomains of the same domain name, 3 separate websites can be declared, with 2 websites hosted on web server A, and 1 website hosted on web server B, without the need to purchase additional domain names.
webpresencestepbystep.com and www.webpresencestepbystep.com on web server A
the subdomain “www” host name is a canononical name (“CNAME”) of the @ host name, which identifies the “bare” domain. This means that www.webpresencestepbystep.com will resolve to the same IP address as webpresencestepbystep.com
/etc/apache2/sites-available/webpresencestepbystep.com.conf:
# generated 2021/05/18 19:42:53 EDT by addvhost.php <VirtualHost *:80> <IfModule mpm_itk_module> AssignUserID webpresencestepbystep_com webpresencestepbystep_com </IfModule> ServerName webpresencestepbystep.com ServerAlias www.webpresencestepbystep.com DocumentRoot /usr/web/webpresencestepbystep_com/webpresencestepbystep.com ServerAdmin info@yourdomain.com CustomLog /var/log/apache2/webpresencestepbystep.com-access_log combined ErrorLog /var/log/apache2/webpresencestepbystep.com-error_log RewriteEngine on RewriteCond %{SERVER_NAME} =webpresencestepbystep.com [OR] RewriteCond %{SERVER_NAME} =www.webpresencestepbystep.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost>
/etc/apache2/sites-available/webpresencestepbystep.com-le-ssl.conf:
<IfModule mod_ssl.c> <VirtualHost *:443> <IfModule mpm_itk_module> AssignUserID webpresencestepbystep_com webpresencestepbystep_com </IfModule> ServerName webpresencestepbystep.com ServerAlias www.webpresencestepbystep.com DocumentRoot /usr/web/webpresencestepbystep_com/webpresencestepbystep.com ServerAdmin info@yourdomain.com CustomLog /var/log/apache2/webpresencestepbystep.com-access_log combined ErrorLog /var/log/apache2/webpresencestepbystep.com-error_log Include /etc/letsencrypt/options-ssl-apache.conf SSLCertificateFile /etc/letsencrypt/live/linuxstepbystep.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/linuxstepbystep.com/privkey.pem </VirtualHost> </IfModule>
community.webpresencestepbystep.com on the same IP address, on web server A
/etc/apache2/sites-available/community.webpresencestepbystep.com.conf:
# generated 2021/05/29 12:45:14 EDT by addvhost.php
<VirtualHost *:80>
<IfModule mpm_itk_module>
AssignUserID community_webpresencestepbystep_ community_webpresencestepbystep_
</IfModule>
ServerName community.webpresencestepbystep.com
DocumentRoot /usr/web/community_webpresencestepbystep_/community.webpresencestepbystep.com
ServerAdmin info@yourdomain.com
CustomLog /var/log/apache2/community.webpresencestepbystep.com-access_log combined
ErrorLog /var/log/apache2/community.webpresencestepbystep.com-error_log
RewriteEngine on
RewriteCond %{SERVER_NAME} =community.webpresencestepbystep.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
/etc/apache2/sites-available/community.webpresencestepbystep.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
<IfModule mpm_itk_module>
AssignUserID community_webpresencestepbystep_ community_webpresencestepbystep_
</IfModule>
ServerName community.webpresencestepbystep.com
DocumentRoot /usr/web/community_webpresencestepbystep_/community.webpresencestepbystep.com
ServerAdmin info@yourdomain.com
CustomLog /var/log/apache2/community.webpresencestepbystep.com-access_log combined
ErrorLog /var/log/apache2/community.webpresencestepbystep.com-error_log
SSLCertificateFile /etc/letsencrypt/live/linuxstepbystep.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/linuxstepbystep.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
media.webpresencestepbystep.com on a different IP address, on web server B
/etc/apache2/sites-available/media.webpresencestepbystep.com.conf:
# generated 2021/05/29 17:12:33 UTC by addvhost.php
<VirtualHost *:80>
<IfModule mpm_itk_module>
AssignUserID media_webpresencestepbystep_com media_webpresencestepbystep_com
</IfModule>
ServerName media.webpresencestepbystep.com
DocumentRoot /usr/web/media_webpresencestepbystep_com/media.webpresencestepbystep.com
ServerAdmin info@yourdomain.com
CustomLog /var/log/apache2/media.webpresencestepbystep.com-access_log combined
ErrorLog /var/log/apache2/media.webpresencestepbystep.com-error_log
RewriteEngine on
RewriteCond %{SERVER_NAME} =media.webpresencestepbystep.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
/etc/apache2/sites-available/media.webpresencestepbystep.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
<IfModule mpm_itk_module>
AssignUserID media_webpresencestepbystep_com media_webpresencestepbystep_com
</IfModule>
ServerName media.webpresencestepbystep.com
DocumentRoot /usr/web/media_webpresencestepbystep_com/media.webpresencestepbystep.com
ServerAdmin info@yourdomain.com
CustomLog /var/log/apache2/media.webpresencestepbystep.com-access_log combined
ErrorLog /var/log/apache2/media.webpresencestepbystep.com-error_log
SSLCertificateFile /etc/letsencrypt/live/media.webpresencestepbystep.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/media.webpresencestepbystep.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
Previous step Chapter 16: Using a script to automate the creation of a virtual host on an Apache web server
Next step: Chapter 18: Installing VirtualBox on a computer running Windows to host Linux as a virtual machine (VM) guest
Previous step: Chapter 15: Using dwservice.net to provide remote technical support as an alternative to TeamViewer
Next step: Chapter 17: Using subdomains to host multiple websites under a single domain name
Web presence step by step is a series of posts that show you to how to build a web presence.
In this chapter we install and use a script to automate the creation of a virtual host on an Apache web server.
This script collects and validates inputs, then executes the commands to create a virtual host under Apache.
For formatting reasons, the text is limited to a fixed width. To fully view the text, you can scroll to the right to see the ends of lines, or use the print view for this blog post.
To view the source code in an another text editor, download and uncompress the zip file described below, or select and copy the text from the source code example below, and paste the text into a file on your computer called “addvhost.php”
Consider copying the file to your Apache web server’s /usr/bin directory with a chmod of 755 so that it can be executed from the system path. Steps to do so are included in the procedure below.
Download this zip file:
https://blog.gordonbuchan.com/files/addvhost.zip
Uncompress the zip file to extract the file “addvhost.php” then copy the file to your Apache web server.
Scroll right to see the ends of lines.
#!/usr/bin/php
<?PHP
// addvhost.php
// v0102
// updated to variable-ize vhostip as a base setting
// creates a virtual host under Apache
// Gordon Buchan 20210512 https://gordonbuchan.com
// MIT License https://mit-license.org
// tested on Ubuntu 20.04, may work on Debian
// directory structure allows for chroot jails for SFTP:
// in a jail you do not own your home directory, only your webdir
// tip: apt install finger whois
// ////////////////////////////////////////////////////////////////
// start summary
// initialize base settings in variables ie bvhwb
// ask for vhostsubdomain, vhostusername, vhostpassword
// infer vhosthomedir, vhostwebdir by convention
// create user, home directory, password
// create directory
// create index.php document
// chown vhosthomedir as root:root
// chown vhostwebdir as vhostusername:vhostusername
// chmod vhostwebdir
// create virtual host file
// enable virtual host
// echo suggestion that client restart apache, run certbot --apache, restart apache
// end summary
// ////////////////////////////////////////////////////////////////
// start base settings
$bvhostconfdir = "/etc/apache2/sites-available";
$bvhwb = "/usr/web";
$restartcommandstr = "systemctl apache2 restart";
$vhostenablecommandstr = "a2enmod";
$echoplaintextpasswords = TRUE;
$logplaintextpassword = TRUE;
$vhostserveradmin = "info@yourdomain.com";
// tip: could be "xxx.xxx.xxx.xxx"
$vhostip = "*";
// ////////////////////////////////////////////////////////////////
// end base settings
// ////////////////////////////////////////////////////////////////
// start function sink
// start polyfill
// str_contains() polyfill for pre PHP8: code for this function taken from php.net
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool
{
return '' === $needle || false !== strpos($haystack, $needle);
} // end function str_contains()
}
// ////////////////////////////////////////////////////////////////
// end polyfill
// validate functions
// We will be using the readline() function to ask questions on the command line.
// These functions allow us to do rich validation within a while statement to trap
// the readline in a loop until our conditions are satisfied.
// We will also echo text to the console with reasons for rejection to assist the client.
// For example: bad string format, vhost appears to exist already, etc.
// ////////////////////////////////////////////////////////////////
function vhostsubdomainverify($vhostsubdomainstr) {
global $bvhwb;
global $bvhostconfdir;
//assume true until proven false
$returnval = TRUE;
// is the string clean?
// note that "-" hyphen character is permitted, not part of symbol sieve
if ( preg_match('/[\'^£$%&*()}{@#~?><>,|=_+¬]/', $vhostsubdomainstr) ) {
$returnval = FALSE;
echo "string has special character that is not permitted\n";
}
// string does not contain a period symbol
if (!str_contains($vhostsubdomainstr,".") ) {
$returnval = FALSE;
echo "string does not contain a \".\" period symbol.\n";
}
// string contains two period symbols in a row
if (str_contains($vhostsubdomainstr,"..") ) {
$returnval = FALSE;
echo "string contain two \"..\" period symbols in a row.\n";
}
// string contains leading period symbol
$strlen = strlen($vhostsubdomainstr);
$begsample = substr($vhostsubdomainstr,0,1);
if ($begsample == ".") {
$returnval = FALSE;
echo "string begins with a \".\" period symbol.\n";
}
// string contains trailing period symbol
$endlen = strlen($vhostsubdomainstr);
$endsample = substr($vhostsubdomainstr,($endlen - 1),1);
if ($endsample == ".") {
$returnval = FALSE;
echo "string ends with a \".\" period symbol.\n";
}
// does the vhostsubdomain already exist?
$vhostsubdomainstrund = str_replace(".","_",$vhostsubdomainstr);
clearstatcache();
if (is_dir("$bvhwb/$vhostsubdomainstrund") ) {
$returnval = FALSE;
echo "webdir for proposed vhost already exists.\n";
} else {
} // end if (is_dir()
$grepforvhost1str = "grep -i 'ServerName $vhostsubdomainstr' $bvhostconfdir/*";
$grepforvhost2str = "grep -i 'ServerAlias $vhostsubdomainstr' $bvhostconfdir/*";
$grepforvhost1res = shell_exec($grepforvhost1str);
$grepforvhost2res = shell_exec($grepforvhost2str);
// if the string has contents something was there for the grep to find
if ($grepforvhost1res || $grepforvhost2res) {
echo "subdomain appears to be part of an existing virtual host\n";
$returnval = FALSE;
}
return $returnval;
} // end function vhostsubdomainverify()
// ////////////////////////////////////////////////////////////////
function prependverify($prependverify) {
// let us make our tests and comparisons case-insensitive
$lowerpv = strtolower($prependverify);
if ( ( $lowerpv == "n") || ($lowerpv == "no") || ($lowerpv == "y") || ($lowerpv == "yes") ) {
$returnval = TRUE;
} else {
echo "please indicate n or no, y or yes\n";
$returnval = FALSE;
}
return $returnval;
} // end function prependverify()
// ////////////////////////////////////////////////////////////////
function usernameverify($vhostusername) {
// force to lower-case
$vhostusername = strtolower($vhostusername);
// assume TRUE until proven false
$returnval = TRUE;
// is the string clean?
// note that "-" hyphen character is permitted, as is the "_" underscore character, not part of symbol sieve
if ( preg_match('/[\'^£$%&*()}{@#~?><>,|=+¬]/', $vhostusername) ) {
$returnval = FALSE;
echo "string has special character that is not permitted\n";
}
$vhunstrlen = strlen($vhostusername);
if ($vhunstrlen < 2) {
echo "username should be minimum 2 characters\n";
$returnval = FALSE;
}
if ($vhunstrlen > 32) {
echo "username should be maximum 32 characters\n";
$returnval = FALSE;
}
// what does finger return?
$fingerstr = shell_exec("finger $vhostusername 2>&1");
if (!str_contains("$fingerstr","no such user") ) {
echo "finger found this username to already be in use\n";
$returnval = FALSE;
}
return $returnval;
} // end function usernameverify()
// ////////////////////////////////////////////////////////////////
function passwordplainverify($passwordplain) {
// assume TRUE until proven false
$returnval = TRUE;
// we should do some tests here
// but mostly just for length, not all that fancy stuff.
// but: we will want to offer to auto-generate a plaintext password
$ppstrlen = strlen($passwordplain);
if ($ppstrlen < 8) {
echo "password should be at least 8 characters\n";
$returnval = FALSE;
}
return $returnval;
} // end function passwordplainverify()
// ////////////////////////////////////////////////////////////////
function genpassverify($genpassverify) {
// let us make our tests and comparisons case-insensitive
$lowergpv = strtolower($genpassverify);
if ( ( $lowergpv == "n") || ($lowergpv == "no") || ($lowergpv == "y") || ($lowergpv == "yes") ) {
$returnval = TRUE;
} else {
echo "please indicate n or no, y or yes\n";
$returnval = FALSE;
}
return $returnval;
} // end function genpassverify()
// ////////////////////////////////////////////////////////////////
function genuserverify($genuserverify) {
// let us make our tests and comparisons case-insensitive
$lowerguv = strtolower($genuserverify);
if ( ( $lowerguv == "n") || ($lowerguv == "no") || ($lowerguv == "y") || ($lowerguv == "yes") ) {
$returnval = TRUE;
} else {
echo "please indicate n or no, y or yes\n";
$returnval = FALSE;
}
return $returnval;
} // end function genuserverify()
// end function sink
// ////////////////////////////////////////////////////////////////
// start get information at command line: vhostsubdomain, vhostusername, vhostpassword
// also, generate and derive values
echo "\naddvhost.php\n";
echo "Add a virtual host to Apache\n\n";
// ask and validate inputs
// the readline is trapped in a loop until vhostsubdomainverify() is satisfied
// function will also echo text to the console with reasons for rejection to assist the client
// bad string format or vhost appears to exist already, etc.
// ////////////////////////////////////////////////////////////////
// vhostsubdomain
$vhostsubdomain = "";
while (!$vhostsubdomain || !vhostsubdomainverify($vhostsubdomain) ) {
$vhostsubdomain = readline("Enter domain xxxxxxxx.xxx or subdomain xxxxxxxx.xxxxxxxx.xxx: ");
}
// putting this here because it is right after we have the $vhostsubdomain string, and just before we need it for $genuseranswer
// will also need this later for derived values like the $vhostwebdir
$vhostsubdomainund = str_replace(".","_",$vhostsubdomain);
// should we prepend with www. as well?
$prependanswer = "";
while (!$prependanswer || !prependverify($prependanswer) ) {
$prependanswer = readline("Do you wish to prepend the subdomain www.$vhostsubdomain as well (n/y)? ");
}
$prependanswer = strtolower($prependanswer);
// ////////////////////////////////////////////////////////////////
// vhostusername
// default username
// should we offer to automatically generate a username based on the subdomain host name?
$genuseranswer = "";
while (!$genuseranswer || !genuserverify($genuseranswer) ) {
$genuseranswer = readline("Generate a username? ");
}
$genuseranswer = strtolower($genuseranswer);
if ( ($genuseranswer=="yes") || ($genuseranswer=="y") ) {
// generate a username
// we are counting on the novel construction of this name with _ modeled on subdomain
$vhostusername = $vhostsubdomainund;
$vhostusernamestrlen = strlen($vhostusername);
// the unique stuff is closer to the front
// so we will truncate to first 32 characters
if ($vhostusernamestrlen > 32) {
$vhostusername = substr($vhostusername,0,32);
}
// what does finger return?
$fingerstr2 = shell_exec("finger $vhostusername 2>&1");
if (!str_contains("$fingerstr2","no such user") ) {
echo "finger found this username to already be in use\n";
exit();
}
} else {
// the client said no to automatic generation of username so we will ask for one
$vhostusername = "";
while (!$vhostusername || !usernameverify($vhostusername) ) {
$vhostusername = readline("Enter username: ");
}
} // end if ($genuseranswer=="yes")
// ////////////////////////////////////////////////////////////////
// vhostpasswordplain
// should we offer to automatically generate a plaintext password?
$genpassanswer = "";
while (!$genpassanswer || !genpassverify($genpassanswer) ) {
$genpassanswer = readline("Generate a plaintext password? ");
}
$genpassanswer = strtolower($genpassanswer);
if ( ($genpassanswer=="yes") || ($genpassanswer=="y") ) {
// generate a random plaintext password
$vhostpasswordplain = "";
$passwordlength = "8";
$posscharsplain = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$posscharssymbols = '!@#%*?';
$posscharspstrlen = strlen($posscharsplain);
$posscharssstrlen = strlen($posscharssymbols);
// first the plain characters
for ($i=0;$i<($passwordlength-1);$i++) {
$randomint = random_int(0,$posscharspstrlen-1);
$randomchar = substr($posscharsplain,$randomint,1);
$vhostpasswordplain .= $randomchar;
} //end for $i
// now the symbol character
$randomint = random_int(0,$posscharssstrlen-1);
$randomchar = substr($posscharssymbols,$randomint,1);
$vhostpasswordplain .= $randomchar;
// now shuffle the string so the symbol position moves and as bonus the string is different
$vhostpasswordplain = str_shuffle($vhostpasswordplain);
} else {
// the client said no to automatic generation of plaintext, so we will ask for one
$vhostpasswordplain = "";
while (!$vhostpasswordplain || !passwordplainverify($vhostpasswordplain) ) {
$vhostpasswordplain = readline("Enter plaintext password: ");
}
} // end if ($genpassanswer=="yes")
// ////////////////////////////////////////////////////////////////
// vhostpasswordhashed (transformation)
// yes, i tried password_hash() -- it did not work for SHA512, this does.
// tip: apt install whois to get mkpasswd command
$vhostpasswordhashed = shell_exec("mkpasswd -m sha-512 $vhostpasswordplain");
// remove linefeed from the string
$vhostpasswordhashed = str_replace("\n","",$vhostpasswordhashed);
// ////////////////////////////////////////////////////////////////
// end get information at command line: vhostsubdomain, vhostusername, vhostpassword
// ////////////////////////////////////////////////////////////////
// start print collected values
$vhosthomedir = "$bvhwb/$vhostusername";
$vhostwebdir = "$bvhwb/$vhostusername/$vhostsubdomain";
echo "\nvalues collected, generated, and derived\n\n";
echo "vhostsubdomain: $vhostsubdomain\n";
echo "prependanswer: $prependanswer\n";
echo "vhostusername: $vhostusername\n";
echo "genpassanswer: $genpassanswer\n";
if ($echoplaintextpasswords) {
echo "vhostpasswordplain: $vhostpasswordplain\n";
}
echo "vhostpasswordhashed: $vhostpasswordhashed\n";
echo "vhosthomedir: $vhosthomedir\n";
echo "vhostwebdir: $vhostwebdir\n";
// ////////////////////////////////////////////////////////////////
// end print collected values
// ////////////////////////////////////////////////////////////////
// start engine section
// ////////////////////////////////////////////////////////////////
// create the $vhostusername with $vhosthomedir and $vhostpasswordhashed
// build the string, look at the string, then maybe do a shell_exec of the string
$shelluseraddstr = "useradd -m -d '$vhosthomedir' '$vhostusername' -s '/usr/bin/bash' -p '$vhostpasswordhashed'";
// disable for production
// echo "shelluseraddstr: $shelluseraddstr\n";
// so it will always be declared
$shelluseraddret = "";
// disable for testing other conditions without committing to this
$shelluseraddret = shell_exec($shelluseraddstr);
//echo "shelluseraddret: $shelluseraddret\n";
// non-null (non-0) exit value from shell indicates an error
if ($shelluseraddret) {
echo "ERROR: there was a problem executing the shell command to create the vhostusername $vhostusername. Stopping.\n";
exit();
} else {
//echo "SUCCESS: the vhostusername $vhostusername was created\n";
}
echo "\n";
// ////////////////////////////////////////////////////////////////
// mkdir $vhostwebdir
$mkdirvhostwebdirret = mkdir($vhostwebdir,0775,TRUE);
if (!$mkdirvhostwebdirret) {
echo "ERROR: there was a problem creating the vhostwebdir $vhostwebdir. Stopping\n";
exit();
} else {
//echo "SUCCESS: the vhostwebdir $vhostwebdir was created.\n";
}
// ////////////////////////////////////////////////////////////////
// fwrite $vhostwebdir/index.php
$indexfilecontents = "<?PHP\n\necho \"<p>$vhostsubdomain</p>\\n\";\n";
$fh1 = fopen("$vhostwebdir/index.php","w");
$filesuccess1 = fwrite($fh1,$indexfilecontents);
fclose($fh1);
if ($filesuccess1) {
//chown root $vhosthomedir
$vhosthomedirownretu1 = chown("$vhosthomedir","root");
if ($vhosthomedirownretu1) {
//echo "SUCCESS chown root $vhosthomedir\n";
} else {
echo "ERROR chown root $vhosthomedirdir not successful\n";
exit();
}
//chgrp root $vhosthomedir
$vhosthomedirownretg1 = chgrp("$vhosthomedir","root");
if ($vhosthomedirownretg1) {
//echo "SUCCESS chgrp root $vhosthomedir\n";
} else {
echo "ERROR chgrp root $vhosthomedirdir not successful\n";
exit();
}
//echo "SUCCESS indexfile written to file: $vhostwebdir/index.php\n";
// chmod the $vhostwebdir
chmod("$vhostwebdir", 0755);
$vhostwebdirperms = substr(sprintf('%o', fileperms("$vhostwebdir")), -4);
//echo "vhostwebdirperms: $vhostwebdirperms\n";
if ($vhostwebdirperms == "0755") {
//echo "SUCCESS chmod 755 $vhostwebdir\n";
} else {
echo "ERROR chmod 755 $vhostwebdir not successful. Stopping.\n";
exit();
}
// chown $vhostusername $vhostwebdir
$vhostwebdirownretu1 = chown("$vhostwebdir",$vhostusername);
if ($vhostwebdirownretu1) {
//echo "SUCCESS chown $vhostusername $vhostwebdir\n";
} else {
echo "ERROR chown $vhostusername $vhostwebdir not successful\n";
exit();
}
// chgrp $vhostusername $vhostwebdir
$vhostwebdirownretg1 = chgrp("$vhostwebdir",$vhostusername);
if ($vhostwebdirownretu1) {
//echo "SUCCESS chgrp $vhostusername $vhostwebdir\n";
} else {
echo "ERROR chgrp $vhostusername $vhostwebdir not successful\n";
exit();
}
// chmod the $vhostwebdir/index.php
chmod("$vhostwebdir/index.php", 0755);
$vhostindexperms = substr(sprintf('%o', fileperms("$vhostwebdir/index.php")), -4);
//echo "vhostindexperms: $vhostindexperms\n";
if ($vhostindexperms == "0755") {
//echo "SUCCESS chmod 755 $vhostwebdir/index.php\n";
} else {
echo "ERROR chmod 755 $vhostwebdir/index.php not successful. Stopping.\n";
exit();
}
// chown $vhostusername $vhostwebdir/index.php
$vhostindexownretu1 = chown("$vhostwebdir/index.php",$vhostusername);
if ($vhostindexownretu1) {
//echo "SUCCESS chown $vhostusername $vhostwebdir/index.php\n";
} else {
echo "ERROR chown $vhostusername $vhostwebdir/index.php not successful\n";
exit();
}
// chgrp $vhostusername $vhostwebdir/index.php
$vhostindexownretg1 = chgrp("$vhostwebdir/index.php",$vhostusername);
if ($vhostindexownretu1) {
//echo "SUCCESS chgrp $vhostusername $vhostwebdir/index.php\n";
} else {
echo "ERROR chgrp $vhostusername $vhostwebdir/index.php not successful\n";
exit();
}
} else {
echo "ERROR indexfile not written to file: $vhostwebdir/index.php\n";
exit();
}
// ////////////////////////////////////////////////////////////////
// fwrite $bvhostconfdir/$vhostsubdomain.conf
$timestring = date("Y/m/d H:i:s T");
$vhostconffilecontents = "# generated $timestring by addvhost.php\n";
$vhostconffilecontents .= "<VirtualHost $vhostip:80>\n";
$vhostconffilecontents .= "<IfModule mpm_itk_module>\n";
$vhostconffilecontents .= "\tAssignUserID $vhostusername $vhostusername\n";
$vhostconffilecontents .= "</IfModule>\n";
$vhostconffilecontents .= "ServerName $vhostsubdomain\n";
if ( ($prependanswer == "y") || ($prependanswer == "yes") ) {
$vhostconffilecontents .= "ServerAlias www.$vhostsubdomain\n";
}
$vhostconffilecontents .= "DocumentRoot $vhostwebdir\n";
$vhostconffilecontents .= "ServerAdmin $vhostserveradmin\n";
$vhostconffilecontents .= "CustomLog /var/log/apache2/$vhostsubdomain-access_log combined\n";
$vhostconffilecontents .= "ErrorLog /var/log/apache2/$vhostsubdomain-error_log\n";
$vhostconffilecontents .= "</VirtualHost>\n";
// disable in production
// echo "vhostconffilecontents = \n$vhostconffilecontents\n";
// write the text file
$fh2 = fopen("$bvhostconfdir/$vhostsubdomain.conf","w");
$filesuccess2 = fwrite($fh2,$vhostconffilecontents);
fclose($fh2);
if ($filesuccess2) {
//echo "SUCCESS virtual host config written to file: $bvhostconfdir/$vhostsubdomain.conf\n";
} else {
echo "ERROR virtual host config not written to file: $bvhostconfdir/$vhostsubdomain.conf\n";
exit();
}
// ////////////////////////////////////////////////////////////////
// shell_exec a2ensite $bvhostconfdir/$vhostsubdomain.conf
// so it will always be declared
$shella2enret = "";
// disable for testing other conditions without committing to this
$shella2enret = shell_exec("a2ensite $vhostsubdomain.conf");
//echo "shella2enret: $shella2enret\n";
// non-null (non-0) exit value from shell indicates an error
if ( str_contains($shella2enret,"ERROR") ) {
//echo "ERROR: there was a problem executing the shell command to enable the vhostsubdomain $vhostsubdomain. Stopping.\n";
exit();
} else {
echo "SUCCESS: enabled vhostsubdomain $vhostsubdomain\n";
}
// ////////////////////////////////////////////////////////////////
// echo to console suggestion that systemctl restart apache2 be executed
echo "\n";
echo "Next steps:\n";
echo "This script did not restart apache2. That is up to you.\n";
echo "systemctl restart apache2\n";
echo "validate site on port 80\n";
echo "run certbot --apache to expand ssl cert\n";
echo "systemctl restart apache2\n";
echo "validate site on port 443\n";
echo "\n";
// ////////////////////////////////////////////////////////////////
// end engine section
Declare the host name in the DNS zone file for the domain:
Use a web browser to visit the host name:
This chapter assumes that you are logged in as the root user. If you are not already root, escalate using this command:
sudo su
This script depends on the finger, whois, and unzip utilities.
Enter this command:
apt install finger whois unzip
Enter this command:
wget https://blog.gordonbuchan.com/files/addvhost.zip
Enter this command:
unzip addvhost.zip
Enter these commands:
mv addvhost.php /usr/bin
chmod 755 /usr/bin/addvhost.php
Enter this command:
addvhost.php
In this example, we decline the option to generate a username, and enter a value for the username. We also decline the option to generate a plaintext password, and enter a value for the plaintext password.
root@server01:~# addvhost.php
addvhost.php
Add a virtual host to Apache
Enter domain xxxxxxxx.xxx or subdomain xxxxxxxx.xxxxxxxx.xxx: webpresencestepbystep.ca
Do you wish to prepend the subdomain www.webpresencestepbystep.ca as well (n/y)? y
Generate a username? n
Enter username: webuserca
Generate a plaintext password? n
Enter plaintext password: password
values collected, generated, and derived
vhostsubdomain: webpresencestepbystep.ca
prependanswer: y
vhostusername: webuserca
genpassanswer: n
vhostpasswordplain: password
vhostpasswordhashed: $6$IdLp5YrW.Z3Tvnm$hlRvIBour47UcZrVm0QA2YgLp2z3C3e5W7PwiS3o.KbZz.mtFeCvWdew/eemdec3Wz9t.WEIuIm3Q2EKTuXYd1
vhosthomedir: /usr/web/webuserca
vhostwebdir: /usr/web/webuserca/webpresencestepbystep.ca
SUCCESS: enabled vhostsubdomain webpresencestepbystep.ca
Next steps:
This script did not restart apache2. That is up to you.
systemctl restart apache2
validate site on port 80
run certbot --apache to expand ssl cert
systemctl restart apache2
validate site on port 443
Enter this command:
systemctl restart apache2
Enter this command:
certbot --apache
Enter this command:
systemctl restart apache2
Use a web browser to visit the host name:
In this example, we accept the option to generate a username. We also accept the option to generate a plaintext password.
Take careful note of the plaintext password value, as shown in the “vhostpasswordplain” field.
root@server01:~# addvhost.php
addvhost.php
Add a virtual host to Apache
Enter domain xxxxxxxx.xxx or subdomain xxxxxxxx.xxxxxxxx.xxx: webpresencestepbystep.com
Do you wish to prepend the subdomain www.webpresencestepbystep.com as well (n/y)? y
Generate a username? y
Generate a plaintext password? y
values collected, generated, and derived
vhostsubdomain: webpresencestepbystep.com
prependanswer: y
vhostusername: webpresencestepbystep_com
genpassanswer: y
vhostpasswordplain: NQeQ2%VT
vhostpasswordhashed: $6$Woe9pPUwnXqUP$9RW60p6SSNfqLJSi4BeAyhe89mBpyTELk2/at7eJcKqou5Q9Y6Nti4P7EoyTV0CBfin6SxlvNHvkZjrpEGxxX0
vhosthomedir: /usr/web/webpresencestepbystep_com
vhostwebdir: /usr/web/webpresencestepbystep_com/webpresencestepbystep.com
SUCCESS: enabled vhostsubdomain webpresencestepbystep.com
Next steps:
This script did not restart apache2. That is up to you.
systemctl restart apache2
validate site on port 80
run certbot --apache to expand ssl cert
systemctl restart apache2
validate site on port 443
Enter this command:
systemctl restart apache2
Enter this command:
certbot --apache
Enter this command:
systemctl restart apache2
Use a web browser to visit the host name:
Previous step: Chapter 15: Using dwservice.net to provide remote technical support as an alternative to TeamViewer
Next step: Chapter 17: Using subdomains to host multiple websites under a single domain name