diff --git a/_modules/node.py b/_modules/node.py
--- a/_modules/node.py
+++ b/_modules/node.py
@@ -11,6 +11,7 @@
 
 
 from salt.exceptions import CommandExecutionError, SaltCloudConfigError
+from salt._compat import ipaddress
 
 
 def _get_all_nodes():
@@ -218,3 +219,43 @@
     ipv6 = __grains__.get("ipv6")
 
     return " ".join(["[" + ip + "]" for ip in ipv6])
+
+
+def resolve_network():
+    """
+    A function to determine canonical properties of networks
+    from the nodes pillar.
+
+    CLI Example:
+        salt * node.resolve_network
+    """
+    network = {
+        "ipv4_address": "",
+        "ipv4_gateway": "",
+    }
+    private_network = network.copy()
+
+    interfaces = _get_property("network:interfaces", __grains__["id"], {})
+    for interface_name, interface in interfaces.items():
+        if "ipv4" not in interface:
+            continue
+
+        ipv4 = interface["ipv4"]["address"]
+        if ipaddress.ip_address(ipv4).is_private:
+            target = private_network
+        else:
+            target = network
+
+        if target["ipv4_address"] != "":
+            continue
+
+        target["ipv4_address"] = ipv4
+        try:
+            target["ipv4_gateway"] = interface["ipv4"]["gateway"]
+        except KeyError:
+            pass
+
+    if network["ipv4_address"] == "":
+        return private_network
+
+    return network
diff --git a/_tests/data/forests.yaml b/_tests/data/forests.yaml
--- a/_tests/data/forests.yaml
+++ b/_tests/data/forests.yaml
@@ -9,11 +9,28 @@
     hostname: egladil.lothlorien.forest
     roles:
       - treecity
+    network:
+      interfaces:
+        net01:
+          ipv4:
+            address: 1.2.3.4 #public
+            gateway: 1.2.3.254
+        net02:
+          ipv4:
+            address: 10.100.0.4 #private
+            gateway: 10.100.0.1
+
   entwash:
     forest: fangorn
     hostname: entwash.node
     roles:
       - border
+    network:
+      interfaces:
+        net02:
+          ipv4:
+            address: 10.100.0.5 #private
+            gateway: 10.100.0.1
 
 items_by_role:
   treecity:
diff --git a/_tests/modules/test_node.py b/_tests/modules/test_node.py
--- a/_tests/modules/test_node.py
+++ b/_tests/modules/test_node.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 
 from importlib.machinery import SourceFileLoader
+from unittest_data_provider import data_provider
 import unittest
 
 
@@ -104,6 +105,52 @@
             node.get_ipv6_list(),
         )
 
+    resolved_networks = lambda: (
+        (
+            "egladil",
+            {
+                "ipv4_address": "1.2.3.4",
+                "ipv4_gateway": "1.2.3.254",
+            },
+        ),
+        (
+            "entwash",
+            {
+                "ipv4_address": "10.100.0.5",
+                "ipv4_gateway": "10.100.0.1",
+            },
+        ),
+    )
+
+    @data_provider(resolved_networks)
+    def test_resolve_network(self, id, expected):
+        self.grains["id"] = id
+        self.assertEqual(expected, node.resolve_network())
+
+    def test_resolve_network_without_gateway(self):
+        expected = {
+            "ipv4_address": "10.100.0.5",
+            "ipv4_gateway": "",
+        }
+
+        self.grains["id"] = "entwash"
+        del self.pillar["nodes"]["entwash"]["network"]["interfaces"]["net02"]["ipv4"][
+            "gateway"
+        ]
+
+        self.assertEqual(expected, node.resolve_network())
+
+    def test_resolve_network_without_any_network(self):
+        expected = {
+            "ipv4_address": "",
+            "ipv4_gateway": "",
+        }
+
+        self.grains["id"] = "entwash"
+        del self.pillar["nodes"]["entwash"]["network"]
+
+        self.assertEqual(expected, node.resolve_network())
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/pillar/nodes/nodes.sls b/pillar/nodes/nodes.sls
--- a/pillar/nodes/nodes.sls
+++ b/pillar/nodes/nodes.sls
@@ -19,18 +19,23 @@
     roles:
       - opensearch
     network:
-      ipv4_interface: eno1
-      ipv4_address: 188.165.200.229
-      ipv4_gateway: 188.165.200.254
-
-      ipv6_interface: eno1
-      ipv6_address: fe80::ec4:7aff:fe6a:36e8
-      ipv6_gateway: fe80::ee30:91ff:fee0:df80
-      ipv6_prefix: 64
       ipv6_native: True
-
       ipv6_tunnel: False
 
+      canonical_public_ipv4: 188.165.200.229
+
+      interfaces:
+        eno1:
+          device: eno1
+          ipv4:
+            address: 188.165.200.229
+            gateway: 188.165.200.254
+          ipv6:
+            address: fe80::ec4:7aff:fe6a:36e8
+            prefix: 64
+            gateway: fe80::ee30:91ff:fee0:df80
+
+
   dwellers:
     forest: nasqueron-infra
     hostname: dwellers.nasqueron.org
@@ -41,16 +46,25 @@
     flags:
       install_docker_devel_tools: True
     network:
-      ipv4_address: 51.255.124.11
-      ipv4_gateway: 91.121.86.254
+      ipv6_tunnel: True
 
-      private_interface:
-        uuid: 8e8ca793-b2eb-46d8-9266-125aba6d06c4
-        device: ens224
-        address: 172.27.27.4
-        netmask: 255.255.255.0
+      canonical_public_ipv4: 51.255.124.11
 
-      ipv6_tunnel: True
+      interfaces:
+        ens192:
+          device: ens192
+          uuid: 6e05ebea-f2fd-4ca1-a21f-78a778664d8c
+          ipv4:
+            address: 51.255.124.11
+            gateway: 91.121.86.254
+
+        ens224:
+          device: ens224
+          uuid: 8e8ca793-b2eb-46d8-9266-125aba6d06c4
+          ipv4:
+            address: 172.27.27.4
+            netmask: &drake_netmask 255.255.255.0
+            gateway: 172.27.27.1
 
   docker-001:
     forest: nasqueron-infra
@@ -58,16 +72,25 @@
     roles:
       - paas-docker
     network:
-      ipv4_address: 51.255.124.9
-      ipv4_gateway: 91.121.86.254
+      ipv6_tunnel: False
 
-      private_interface:
-        uuid: 3fd0b9f8-ecc3-400d-bc61-3ba21d0b6337
-        device: ens224
-        address: 172.27.27.6
-        netmask: 255.255.255.0
+      canonical_public_ipv4: 51.255.124.9
 
-      ipv6_tunnel: False
+      interfaces:
+        ens192:
+          device: ens192
+          uuid: ef7370c5-5060-4d89-82bb-dbeabf4a35f6
+          ipv4:
+            address: 51.255.124.9
+            gateway: 91.121.86.254
+
+        ens224:
+          device: ens224
+          uuid: 3fd0b9f8-ecc3-400d-bc61-3ba21d0b6337
+          ipv4:
+            address: 172.27.27.6
+            netmask: *drake_netmask
+            gateway: 172.27.27.1
 
   router-001:
     forest: nasqueron-infra
@@ -75,18 +98,24 @@
     roles:
       - router
     network:
-      ipv4_interface: vmx0
-      ipv4_address: 51.255.124.8
-      ipv4_netmask: 255.255.255.255
-      ipv4_gateway: 91.121.86.254
       ipv4_ovh_failover: True
+      ipv6_tunnel: False
 
-      private_interface:
-        device: vmx1
-        address: 172.27.27.1
-        netmask: 255.255.255.0
+      canonical_public_ipv4: 51.255.124.8
 
-      ipv6_tunnel: False
+      interfaces:
+        vmx0:
+          device: vmx0
+          ipv4:
+            address: 51.255.124.8
+            netmask: 255.255.255.255
+            gateway: 91.121.86.254
+
+        vmx1:
+          device: vmx1
+          ipv4:
+            address: 172.27.27.1
+            netmask: &intranought_netmask 255.255.255.240
 
   ysul:
     forest: nasqueron-dev
@@ -99,15 +128,20 @@
     zfs:
       pool: arcology
     network:
-      ipv4_interface: igb0
-      ipv4_address: 163.172.49.16
-      ipv4_gateway: 163.172.49.1
-      ipv4_aliases:
-        - 212.83.187.132
-
       ipv6_tunnel: True
       ipv6_gateway: 2001:470:1f12:9e1::1
 
+      canonical_public_ipv4: 212.83.187.132
+
+      interfaces:
+        igb0:
+          device: igb0
+          ipv4:
+            address: 163.172.49.16
+            gateway: 163.172.49.1
+            aliases:
+              - 212.83.187.132
+
   windriver:
     forest: nasqueron-dev
     hostname: windriver.nasqueron.org
@@ -119,18 +153,22 @@
     zfs:
       pool: arcology
     network:
-      ipv4_interface: igb0
-      ipv4_address: 51.159.18.59
-      ipv4_gateway: 51.159.18.1
-
-      ipv6_interface: igb0
-      ipv6_address: 2001:0bc8:6005:0005:aa1e:84ff:fef3:5d9c
-      ipv6_gateway: fe80::a293:51ff:feb7:5073
-      ipv6_prefix: 128
       ipv6_native: True
-
       ipv6_tunnel: False
 
+      canonical_public_ipv4: 51.159.18.59
+
+      interfaces:
+        igb0:
+          device: igb0
+          ipv4:
+            address: 51.159.18.59
+            gateway: 51.159.18.1
+          ipv6:
+            address: 2001:0bc8:6005:0005:aa1e:84ff:fef3:5d9c
+            gateway: fe80::a293:51ff:feb7:5073
+            prefix: 128
+
   ##
   ## Forest:         Eglide
   ## Semantic field: ? (P27 used for "Eglide" too)
@@ -145,10 +183,19 @@
     roles:
       - shellserver
     network:
-      ipv4_interface: ens2
-      ipv4_address: 51.159.150.221
-      ipv4_gateway: ""
-
       ipv6_tunnel: True
+
+      canonical_public_ipv4: 51.159.150.221
+
+      interfaces:
+        ens2:
+          device: ens2
+          ipv4:
+            address: 51.159.150.221
+            gateway: ""
+          flags:
+            # This interface is configured by cloud-init
+            - skip_interface_configuration
+
     fixes:
       rsyslog_xconsole: True
diff --git a/roles/core/motd/init.sls b/roles/core/motd/init.sls
--- a/roles/core/motd/init.sls
+++ b/roles/core/motd/init.sls
@@ -7,7 +7,7 @@
 #   -------------------------------------------------------------
 
 {% set motd_path = salt['motd.get_path']() %}
-{% set network = salt['node.get']('network') %}
+{% set network = salt['node.resolve_network()'] %}
 
 motd:
   file.managed:
diff --git a/roles/core/network/files/FreeBSD/netif_ipv4.rc b/roles/core/network/files/Debian/10-net.jinja
copy from roles/core/network/files/FreeBSD/netif_ipv4.rc
copy to roles/core/network/files/Debian/10-net.jinja
--- a/roles/core/network/files/FreeBSD/netif_ipv4.rc
+++ b/roles/core/network/files/Debian/10-net.jinja
@@ -1,9 +1,9 @@
 #   -------------------------------------------------------------
-#   Network — rc configuration
+#   Network — interfaces configuration
 #   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #   Project:        Nasqueron
 #   License:        Trivial work, not eligible to copyright
-#   Source file:    roles/core/network/files/FreeBSD/netif_ipv4.rc
+#   Source file:    roles/core/network/files/Debian/10-net.jinja
 #   -------------------------------------------------------------
 #
 #   <auto-generated>
@@ -13,7 +13,10 @@
 #       and will be lost if the state is redeployed.
 #   </auto-generated>
 
-ifconfig_{{ interface }}="inet {{ ipv4_address }} netmask {{ ipv4_netmask }}"
-{%- for ip in ipv4_aliases %}
-ifconfig_{{ interface }}_alias{{ loop.index0 }}="inet {{ ip }} netmask 255.255.255.255"
-{% endfor -%}
+auto {{ interface.device }}
+iface {{ interface.device }} inet static
+    address {{ interface.ipv4.address }}
+    netmask {{ interface.ipv4.netmask }}
+    {% if "gateway" in interface.ipv4 %}
+    gateway {{ interface.ipv4.gateway }}
+    {% endif %}
diff --git a/roles/core/network/files/FreeBSD/netif_ipv4.rc b/roles/core/network/files/FreeBSD/netif_ipv4.rc
--- a/roles/core/network/files/FreeBSD/netif_ipv4.rc
+++ b/roles/core/network/files/FreeBSD/netif_ipv4.rc
@@ -13,7 +13,7 @@
 #       and will be lost if the state is redeployed.
 #   </auto-generated>
 
-ifconfig_{{ interface }}="inet {{ ipv4_address }} netmask {{ ipv4_netmask }}"
-{%- for ip in ipv4_aliases %}
-ifconfig_{{ interface }}_alias{{ loop.index0 }}="inet {{ ip }} netmask 255.255.255.255"
+ifconfig_{{ interface.device }}="inet {{ interface.address }} netmask {{ interface.netmask }}"
+{%- for ip in interface.get("aliases", []) %}
+ifconfig_{{ interface.device }}_alias{{ loop.index0 }}="inet {{ ip }} netmask 255.255.255.255"
 {% endfor -%}
diff --git a/roles/core/network/files/RedHat/ifcfg-private b/roles/core/network/files/RedHat/ifcfg
rename from roles/core/network/files/RedHat/ifcfg-private
rename to roles/core/network/files/RedHat/ifcfg
--- a/roles/core/network/files/RedHat/ifcfg-private
+++ b/roles/core/network/files/RedHat/ifcfg
@@ -3,7 +3,7 @@
 #   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #   Project:        Nasqueron
 #   License:        Trivial work, not eligible to copyright
-#   Source file:    roles/core/network/files/RedHat/ifcfg-private
+#   Source file:    roles/core/network/files/RedHat/ifcfg
 #   -------------------------------------------------------------
 #
 #   <auto-generated>
@@ -18,7 +18,7 @@
 BROWSER_ONLY=no
 BOOTPROTO=none
 DEFROUTE=yes
-IPV4_FAILURE_FATAL=no
+IPV4_FAILURE_FATAL=yes
 IPV6INIT=yes
 IPV6_AUTOCONF=yes
 IPV6_DEFROUTE=yes
@@ -28,5 +28,5 @@
 UUID={{ interface.uuid }}
 DEVICE={{ interface.device }}
 ONBOOT=yes
+IPADDR={{ interface.ipv4.address }}
 PREFIX={{ prefix }}
-IPADDR={{ interface.address }}
diff --git a/roles/core/network/init.sls b/roles/core/network/init.sls
--- a/roles/core/network/init.sls
+++ b/roles/core/network/init.sls
@@ -9,12 +9,11 @@
 include:
   - .ipv4
   - .ipv6
-  - .private
   - .gre
 
 # Drake can be configured as:
 #
-#   - private (e.g. IntraNought network cards on EXSi hypervisor VMs)
+#   - ipv4    (e.g. IntraNought network cards on EXSi hypervisor VMs)
 #   - gre     (e.g. isolated servers needing a tunnel)
 #
 # Both are needed for servers with router role.
diff --git a/roles/core/network/ipv4.sls b/roles/core/network/ipv4.sls
--- a/roles/core/network/ipv4.sls
+++ b/roles/core/network/ipv4.sls
@@ -6,24 +6,34 @@
 #   License:        Trivial work, not eligible to copyright
 #   -------------------------------------------------------------
 
+{% from "roles/core/network/map.jinja" import interface_config with context %}
 {% set network = salt['node.get']('network') %}
 
 #   -------------------------------------------------------------
 #   Interface
 #   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-{% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/ipv4_{{ network['ipv4_interface'] }}:
+{% for interface_name, interface in network["interfaces"] %}
+
+{% if "skip_interface_configuration" not in interface.get("flags", []) %}
+network_ipv4_{{ interface_name }}:
   file.managed:
-    - source: salt://roles/core/network/files/FreeBSD/netif_ipv4.rc
+    {% if interface_config["suffix"] == "interface" %}
+    - name : {{ interface_config["config_path"] }}{{ interface_name }}
+    {% else %}
+    - name : {{ interface_config["config_path"] }}{{ interface["device"] }}
+    {% endif %}
+    - source: salt://roles/core/network/files/{{ interface_config["source_path"] }}
     - makedirs: True
     - template: jinja
-    - context:
-        interface: {{ network['ipv4_interface'] }}
-        ipv4_address: {{ network['ipv4_address'] }}
-        ipv4_netmask: {{ network['ipv4_netmask'] | default('255.255.255.0') }}
-        ipv4_aliases: {{ salt['node.get_list']('network:ipv4_aliases') }}
+    - defaults:
+        interface: {{ interface }}
+{% if grains['os_family'] == 'RedHat' %}
+        prefix: {{ salt['network_utils.netmask_to_cidr_prefix'](interface['netmask']) }}
 {% endif %}
+{% endif %}
+
+{% endfor %}
 
 #   -------------------------------------------------------------
 #   Routes
diff --git a/roles/core/network/ipv6.sls b/roles/core/network/ipv6.sls
--- a/roles/core/network/ipv6.sls
+++ b/roles/core/network/ipv6.sls
@@ -26,19 +26,27 @@
 
 {% if salt['node.has']('network:ipv6_native') %}
 
+{% for interface_name, interface in network["interfaces"] %}
+
+{% if "gateway" in interface["ipv6"] %}
+{% set ipv6_gateway = interface["ipv6"]["gateway"] %}
+{% endif %}
+
 {% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/ipv6_{{ network['ipv6_interface'] }}:
+/etc/rc.conf.d/netif/ipv6_{{ interface['device'] }}:
   file.managed:
     - source: salt://roles/core/network/files/FreeBSD/netif_ipv6.rc
     - makedirs: True
     - template: jinja
     - context:
-        interface: {{ network['ipv6_interface'] }}
-        ipv6_address: {{ network['ipv6_address'] }}
-        ipv6_prefix: {{ network['ipv6_prefix'] | default(64) }}
+        interface: {{ interface['device'] }}
+        ipv6_address: {{ interface['ipv6']['address'] }}
+        ipv6_prefix: {{ interface['ipv6']['prefix'] | default(64) }}
         has_native_ipv6: True
 {% endif %}
 
+{% endfor %}
+
 {% endif %}
 
 #   -------------------------------------------------------------
@@ -67,7 +75,7 @@
     - makedirs: True
     - template: jinja
     - context:
-        ipv6_gateway: {{ network['ipv6_gateway'] }}
+        ipv6_gateway: {{ ipv6_gateway }}
 {% endif %}
 
 {% endif %}
diff --git a/roles/core/network/map.jinja b/roles/core/network/map.jinja
new file mode 100644
--- /dev/null
+++ b/roles/core/network/map.jinja
@@ -0,0 +1,34 @@
+#   -------------------------------------------------------------
+#   Salt — Network
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#   Project:        Nasqueron
+#   License:        Trivial work, not eligible to copyright
+#   -------------------------------------------------------------
+
+#   -------------------------------------------------------------
+#   Interface configuration by OS/distro
+#
+#   config_path:   the configuration file to write in OS
+#   source_path:   in this repo, roles/core/network/files/<source_path>
+#
+#   Don't set default value, so we MUST define them
+#   for EACH os/distro.
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{% set interface_config = salt['grains.filter_by']({
+  'FreeBSD': {
+    "config_path": "/etc/rc.conf.d/netif/ipv4_",
+    "source_path": "FreeBSD/netif_ipv4.rc",
+    "suffix": "interface",
+  },
+  'RedHat': {
+    "config_path": "/etc/sysconfig/network-scripts/ifcfg-",
+    "source_path": "RedHat/ifcfg",
+    "suffix": "device",
+  },
+  'Debian': {
+    "config_path": "/etc/network/interfaces.d/10-net-",
+    "source_path": "Debian/10-net.jinja",
+    "suffix": "device",
+  },
+}) %}
diff --git a/roles/core/network/private.sls b/roles/core/network/private.sls
deleted file mode 100644
--- a/roles/core/network/private.sls
+++ /dev/null
@@ -1,41 +0,0 @@
-#   -------------------------------------------------------------
-#   Salt — Network
-#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#   Project:        Nasqueron
-#   Created:        2020-09-24
-#   License:        Trivial work, not eligible to copyright
-#   -------------------------------------------------------------
-
-{% set network = salt['node.get']('network') %}
-
-#   -------------------------------------------------------------
-#   Interface
-#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-{% if salt['node.has']('network:private_interface') %}
-{% set interface = network['private_interface'] %}
-
-{% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/ipv4_{{ network['private_interface'] }}:
-  file.managed:
-    - source: salt://roles/core/network/files/FreeBSD/netif_ipv4.rc
-    - makedirs: True
-    - template: jinja
-    - context:
-        interface: {{ interface['device'] }}
-        ipv4_address: {{ interface['address'] }}
-        ipv4_netmask: {{ interface['netmask'] | default('255.255.255.0') }}
-        ipv4_aliases: {{ salt['node.get_list']('network:private_interface:aliases') }}
-{% endif %}
-
-{% if grains['os_family'] == 'RedHat' %}
-/etc/sysconfig/network-scripts/ifcfg-{{ interface['device'] }}:
-  file.managed:
-    - source: salt://roles/core/network/files/RedHat/ifcfg-private
-    - template: jinja
-    - context:
-        interface: {{ interface }}
-        prefix: {{ salt['network_utils.netmask_to_cidr_prefix'](interface['netmask']) }}
-{% endif %}
-
-{% endif %}