# Enabling Secondary IPs and/or VLANs on the WAN interface MetalSoft supports configuring secondary IPs and VLANs on the WAN interface. This enables complex setups such as the one pictured below (as an example) where the primary IP is a private (non-routable IP) and a secondary IP is configured on a VLAN interface that is bridged to the primary interface. Note that this is only supported on certain switch vendors (such as Cumulus 4.x+) and certain provisioners (such as the VLAN provisioner). The untagged traffic is handled by the default VLAN (automatically allocated by MetalSoft in this case) whereas the secondary VLAN is allowed by the switch port configuration. ![](/assets/advanced/enabling_secondary_ips_and_vlans_on_the_wan_interface_01.svg) To enable this scenario follow the following: 1. From the **Admin panel**, in the **Subnets** section click **Add subnet pool** button. Register a **Subnet Pool** that will be used to allocate IPs on primary or secondary interfaces. Make sure to set the **Infrastructure Allocation** option to **Manual**. ![](/assets/advanced/enabling_secondary_ips_and_vlans_on_the_wan_interface_01.png) 2. From the **Infrastructure Editor**, select the **InstanceArray**, click the **Advanced** tab and configure the desired primary and secondary IP configuration. - A setting (on either the primary IP or secondary IPs) of **Subnet Pool: Automatic** will instruct the system to use IPs from Subnets created from Subnet Pools that are marked as **Infrastructure Allocation: Automatic** (the default)" - A setting of **Use custom VLAN: disabled** will instruct the system to use the automatically allocated VLAN from the range configured in the Datacenter's **ToRWANVLANRange** option (defaults to 100-399 for VLAN provisioner). - A setting other than **Default** on the VLAN for the *primary* IPs will also instruct the system to configure the switch port to map all UNTAGGED traffic to the respective switch-side VLAN. - A setting other than **Default** on the VLAN for the *secondary* IPs will also instruct the system to configure the switch port to allow traffic TAGGED with the respective VLAN. ![](/assets/advanced/enabling_secondary_ips_and_vlans_on_the_wan_interface_02.png) Note that this does not automatically configure the server side interface. The template must be configured to perform this setup. The **`{{wan_interface_ipv4_vlan_id_INDEX}}`** variable can be used to in the template to retrieve the VLAN id of the respective interface. ## Configuring the secondary interface in the kickstart file of the template The last step is to configure the template to create a vlan interface and assign the ip. Edit the template's kickstart file to include something like this: This example is for VMWare ESXI: ``` if [ {{wan_interface_0_ipv4_ip_count}} -ge 2 ]; then esxcli network vswitch standard portgroup add --portgroup-name="Internet Network" --vswitch-name=vSwitch0 esxcli network vswitch standard portgroup set --portgroup-name "Internet Network" --vlan-id {{wan_interface_0_ipv4_ip_1_vlan_id}} esxcli network ip interface add --interface-name=vmk1 --portgroup-name="Internet Network" esxcli network ip interface ipv4 set --interface-name "vmk1" --ipv4={{wan_interface_0_ipv4_ip_1_address}} --netmask={{wan_interface_0_ipv4_ip_1_subnet_pool_mask}} --gateway={{wan_interface_1_ipv4_ip_0_gateway}} --type=static esxcli network ip route ipv4 add -n 0.0.0.0/0 -g {{wan_interface_0_ipv4_ip_1_gateway}} else esxcli network ip route ipv4 add -n 0.0.0.0/0 -g {{wan_interface_0_ipv4_ip_0_gateway}} fi ``` This is for ubuntu 20.04: ``` getInterfaceNameFromMAC() { interfaceName=$(ip -o link | awk '$(NF-2) == "'$1'" {print $2}') if [ -z "$interfaceName" ] then echo "Did not find interface name for given MAC: $1." exit 1 fi echo ${interfaceName::-1} } # Helper Network Device ConfigFile bondNetworkDeviceConfigFile() { cat <> /etc/systemd/network/10-bond0.link # Specify the Mac address for bond0 [Match] OriginalName=bond0 [Link] MACAddressPolicy=none MACAddress={{wan_interface_0_mac_address}} EOT } export wanInterfaceCount={{wan_interface_count}} # Generate Netplan Configiguration for bonded setups if [ {{wan_interface_count}} -gt 1 ]; then case $wanInterfaceCount in 2) wan1Name="$(getInterfaceNameFromMAC "{{wan_interface_0_mac_address}}")" wan2Name="$(getInterfaceNameFromMAC "{{wan_interface_1_mac_address}}")" read -r -d '' NETPLANETHERNETS<< EOM { "$wan1Name": { "dhcp4": false }, "$wan2Name": { "dhcp4": false } } EOM read -r -d '' NETPLANBONDINTERFACES<< EOM [ "$wan1Name", "$wan2Name" ] EOM ;; 3) wan1Name="$(getInterfaceNameFromMAC "{{wan_interface_0_mac_address}}")" wan2Name="$(getInterfaceNameFromMAC "{{wan_interface_1_mac_address}}")" wan3Name="$(getInterfaceNameFromMAC "{{wan_interface_2_mac_address}}")" read -r -d '' NETPLANETHERNETS<< EOM { "$wan1Name": { "dhcp4": false }, "$wan2Name": { "dhcp4": false }, "$wan3Name": { "dhcp4": false } } EOM read -r -d '' NETPLANBONDINTERFACES<< EOM [ "$wan1Name", "$wan2Name", "$wan3Name" ] EOM ;; 4) wan1Name="$(getInterfaceNameFromMAC "{{wan_interface_0_mac_address}}")" wan2Name="$(getInterfaceNameFromMAC "{{wan_interface_1_mac_address}}")" wan3Name="$(getInterfaceNameFromMAC "{{wan_interface_2_mac_address}}")" wan4Name="$(getInterfaceNameFromMAC "{{wan_interface_3_mac_address}}")" read -r -d '' NETPLANETHERNETS<< EOM { "$wan1Name": { "dhcp4": false }, "$wan2Name": { "dhcp4": false }, "$wan3Name": { "dhcp4": false }, "$wan4Name": { "dhcp4": false } } EOM read -r -d '' NETPLANBONDINTERFACES<< EOM [ "$wan1Name", "$wan2Name", "$wan3Name", "$wan4Name" ] EOM ;; *) exit ;; esac bondNetworkDeviceConfigFile read -r -d '' TEMPNETPLANCFG<< EOM { "network": { "version": 2, "renderer": "networkd", "ethernets": $NETPLANETHERNETS, "bonds": { "bond0": { "dhcp4": false, "addresses": [ "{{wan_interface_0_ipv4_ip_0_cidr}}" ], "routes": [ { "to": "default", "via": "{{wan_interface_0_ipv4_ip_0_gateway}}" } ], "nameservers": { "addresses": [ "{{dns_server_ip_0}}" ] }, "interfaces": $NETPLANBONDINTERFACES, "parameters": { "mode": "802.3ad", "lacp-rate": "fast", "mii-monitor-interval": 100, "transmit-hash-policy": "layer3+4" } } } } } EOM echo "$TEMPNETPLANCFG" > /var/log/01-netcfg.json # Convert to yaml python -c 'import sys, yaml, json; yaml.safe_dump(json.load(sys.stdin), sys.stdout, default_flow_style=False)' < /var/log/01-netcfg.json > /etc/netplan/01-netcfg.yaml fi # Generate Netplan Configuration for single wan interface setups if [ {{wan_interface_count}} -eq 1 ]; then wan1Name="$(getInterfaceNameFromMAC "{{wan_interface_0_mac_address}}")" read -r -d '' TEMPNETPLANCFG<< EOM { "network": { "version": 2, "renderer": "networkd", "ethernets": { "$wan1Name": { "dhcp4": false, "addresses": [ "{{wan_interface_0_ipv4_ip_0_cidr}}" ], "routes": [ { "to": "default", "via": "{{wan_interface_0_ipv4_ip_0_gateway}}" } ], "nameservers": { "addresses": [ "{{dns_server_ip_0}}" ] } } } } } EOM echo "$TEMPNETPLANCFG" > /var/log/01-netcfg.json # Convert to yaml python -c 'import sys, yaml, json; yaml.safe_dump(json.load(sys.stdin), sys.stdout, default_flow_style=False)' < /var/log/01-netcfg.json > /etc/netplan/01-netcfg.yaml fi ```