diff --git a/lib/facter/fw_builder_is_docker.rb b/lib/facter/fw_builder_is_docker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6388b74e49a41b2117f45a65f52a6bd9316270d5
--- /dev/null
+++ b/lib/facter/fw_builder_is_docker.rb
@@ -0,0 +1,9 @@
+Facter.add(:fw_builder_is_docker) do
+  setcode do
+    if Facter::Util::Resolution.which('docker')
+      true
+    else
+      false
+    end
+  end
+end
diff --git a/manifests/chains.pp b/manifests/chains.pp
new file mode 100644
index 0000000000000000000000000000000000000000..4b21c21abfa27068a675275d920e13400ffee7cb
--- /dev/null
+++ b/manifests/chains.pp
@@ -0,0 +1,112 @@
+# == Class: fw_builder::chains
+#
+# Pre IPtables allows several icmp type, loopback connection
+# either on IPv6 and IPv4
+#
+# This class opens the firewall to Geant specific servers
+#
+# === Parameters
+#
+# === Requires
+#
+# === Examples
+#
+class fw_builder::chains (
+  $ipv4_enable,
+  $ipv6_enable
+) {
+
+  assert_private()
+
+  if ($ipv4_enable) {
+    ['udp', 'tcp', 'trust', 'public'].each | $chain | {
+      firewallchain { "INPUT_${chain}:filter:IPv4":
+        ensure  => present;
+      }
+    }
+    firewall {
+      default:
+        chain    => 'INPUT',
+        action   => accept,
+        provider => 'iptables';
+      '010 accept all icmp for provider iptables':
+        proto    => 'icmp';
+      '003 accept inbound related established rules for provider iptables':
+        proto => all,
+        state => ['RELATED', 'ESTABLISHED'];
+    }
+    firewall {
+      default:
+        chain    => 'INPUT',
+        jump     => 'INPUT_public',
+        state    => ['NEW'],
+        provider => 'ip6tables';
+      '090 IPv4 UDP INPUT_public for all public services':
+        proto    => 'udp';
+      '090 IPv4 TCP INPUT_public for all public services':
+        proto    => 'tcp';
+    }
+    firewall { '095 IPv4 INPUT_trust this is for all ip ranges (mostly internal)':
+      chain    => 'INPUT',
+      proto    => all,
+      state    => ['NEW'],
+      jump     => 'INPUT_trust',
+      ipset    => 'trusted_networks_v4 src',
+      provider => 'iptables';
+    }
+    firewall { '001 IPv4 accept all inbound to localhost':
+      chain    => 'INPUT',
+      proto    => all,
+      iniface  => 'lo',
+      action   => accept,
+      provider => 'iptables';
+    }
+  }
+
+  if ($ipv6_enable) {
+    ['udp', 'tcp', 'trust', 'public'].each | $chain | {
+      firewallchain { "INPUT_${chain}:filter:IPv6":
+        ensure  => present,
+      }
+    }
+    firewall {
+      default:
+        chain    => 'INPUT',
+        action   => accept,
+        provider => 'ip6tables';
+      '010 accept all icmp for provider ip6tables':
+        proto    => 'ipv6-icmp';
+      '003 accept inbound related established rules for provider ip6tables':
+        proto => all,
+        state => ['RELATED', 'ESTABLISHED'];
+    }
+    firewall {
+      default:
+        chain    => 'INPUT',
+        jump     => 'INPUT_public',
+        state    => ['NEW'],
+        provider => 'ip6tables';
+      '090 IPv6 UDP INPUT_public for all public services':
+        proto    => 'udp';
+      '090 IPv6 TCP INPUT_public for all public services':
+        proto    => 'tcp';
+    }
+    firewall { '095 IPv6 INPUT_trust this is for all ip ranges (mostly internal)':
+      chain    => 'INPUT',
+      proto    => all,
+      state    => ['NEW'],
+      jump     => 'INPUT_trust',
+      ipset    => 'trusted_networks_v6 src',
+      provider => 'ip6tables';
+    }
+    firewall { '001 IPv6 accept all inbound to localhost6':
+      chain    => 'INPUT',
+      proto    => all,
+      iniface  => 'lo',
+      action   => accept,
+      provider => 'ip6tables';
+    }
+  }
+
+}
+# vim:ts=2:sw=2
diff --git a/manifests/docker.pp b/manifests/docker.pp
new file mode 100644
index 0000000000000000000000000000000000000000..0ba5dc2c1e7141da52202a6be758df7c5fb3ee11
--- /dev/null
+++ b/manifests/docker.pp
@@ -0,0 +1,64 @@
+# == Class: fw_builder::docker
+#
+# Pre IPtables allows several icmp type, loopback connection
+# either on IPv6 and IPv4
+#
+# This class opens the firewall to Geant specific servers
+#
+# === Parameters
+#
+# === Requires
+#
+# === Examples
+#
+class fw_builder::docker (
+  $manage_docker,
+  $ipv4_enable,
+  $ipv6_enable
+) {
+
+  assert_private()
+
+  # IPv6 IS STILL MISSING
+
+  firewallchain { ['INPUT:filter:IPv4', 'OUTPUT:filter:IPv4']:
+    purge  => true,
+    ignore => ['docker', 'br-', 'cali-', 'KUBE'],
+  }
+
+  firewallchain { 'FORWARD:filter:IPv4':
+    purge  => true,
+    ignore => ['docker', 'br-', 'cali-', 'KUBE'],
+  }
+
+  firewallchain { ['DOCKER:nat:IPv4', 'DOCKER:filter:IPv4']:
+    purge  => false,
+  }
+
+  firewallchain { 'POSTROUTING:nat:IPv4':
+    purge  => false,
+  }
+
+  firewallchain { [
+    'INPUT:nat:IPv4', 'PREROUTING:nat:IPv4',
+    'OUTPUT:nat:IPv4', 'PREROUTING:mangle:IPv4',
+    'POSTROUTING:mangle:IPv4', 'INPUT:mangle:IPv4',
+    'FORWARD:mangle:IPv4', 'OUTPUT:mangle:IPv4',
+    'OUTPUT:raw:IPv4', 'PREROUTING:raw:IPv4'
+    ]:
+    purge  => true,
+    ignore => ['DOCKER', 'cali-', 'KUBE'],
+  }
+
+  # this is is for kube / cali
+  firewallchain { [
+    'cali-PREROUTING:mangle:IPv4', 'cali-failsafe-in:mangle:IPv4',
+    'cali-from-host-endpoint:mangle:IPv4', 'cali-failsafe-in:raw:IPv4',
+    'cali-failsafe-out:raw:IPv4', 'cali-from-host-endpoint:raw:IPv4',
+    'cali-to-host-endpoint:raw:IPv4', 'KUBE-SERVICES:filter:IPv4'
+    ]:
+    purge  => false,
+  }
+
+}
+# vim:ts=2:sw=2
diff --git a/manifests/init.pp b/manifests/init.pp
index dad27e829e53f357322e69b9b619afaa253c3896..a2ec1d65ccc34ada6d5fafeab9f29208a980868b 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -5,6 +5,84 @@
 #   Pete Pedersen<pete.pedersen@geant.org>
 #   Massimiliano Adamo<massimiliano.adamo@geant.org>
 #
-class fw_builder {
-  # resources
+class fw_builder (
+  Array $trusted_networks,
+  Boolean $manage_docker     = false,
+  Boolean $ipv4_enable       = true,
+  Boolean $ipv6_enable       = true,
+  Boolean $logging           = true,
+  Boolean $purge_rules       = true,
+  Integer $log_rotation_days = '7',
+  $ipset_package_ensure      = 'present',
+  $limit                     = '1000/sec'
+) {
+
+  if ! ($purge_rules) and ($manage_docker) {
+    fail('cannot set purge_rules to false and manage_docker to true')
+  }
+
+  if ! ($ipv4_enable) and ! ($ipv6_enable) {
+    fail('you cannot disable ipv4 and ipv6 at the same time')
+  }
+
+  if ($ipv4_enable) and ($ipv6_enable) {
+    $ip_proto_array = ['ip6tables', 'iptables']
+  } elsif ($ipv4_enable) and ! ($ipv6_enable) {
+    $ip_proto_array = ['iptables']
+  } elsif ! ($ipv4_enable) and ($ipv6_enable) {
+    $ip_proto_array = ['iptables']
+  }
+
+  class {
+    'fw_builder::ipset':
+      ipset_package_ensure => $ipset_package_ensure,
+      trusted_networks     => $trusted_networks,
+      ipv4_enable          => $ipv4_enable,
+      ipv6_enable          => $ipv6_enable,
+      before               => Class['fw_builder::chains', 'fw_builder::docker'];
+    'fw_builder::chains':
+      ipv4_enable => $ipv4_enable,
+      ipv6_enable => $ipv6_enable;
+    'fw_builder::post':
+      ipv4_enable => $ipv4_enable,
+      ipv6_enable => $ipv6_enable,
+      limit       => $limit;
+    'fw_builder::logrotate':
+      logging           => $logging,
+      log_rotation_days => $log_rotation_days,
+  }
+
+  if ($purge_rules) {
+    if ($facts['fw_builder_is_docker']) and ($manage_docker) {
+      echo { 'Docker detected':
+        message => 'not purging iptables rules set by docker';
+      }
+      resources { 'firewallchain':
+        purge => false;
+      }
+      class { 'fw_builder::docker':
+        ipv4_enable => $ipv4_enable,
+        ipv6_enable => $ipv6_enable;
+      }
+    } else {
+      if ($ipv4_enable) {
+        firewallchain { 'FORWARD:filter:IPv4':
+          ensure => present,
+          policy => drop,
+          purge  => true;
+        }
+      }
+      if ($ipv6_enable) {
+        firewallchain { 'FORWARD:filter:IPv6':
+          ensure => present,
+          policy => drop,
+          purge  => true;
+        }
+      }
+      resources { 'firewall':
+        purge => true;
+      }
+    }
+  }
+
 }
diff --git a/manifests/ipset.pp b/manifests/ipset.pp
new file mode 100644
index 0000000000000000000000000000000000000000..23f4459867917dd53e85d70671402dd608d2757b
--- /dev/null
+++ b/manifests/ipset.pp
@@ -0,0 +1,49 @@
+# Class: fw_builder::ipset
+#
+#
+class fw_builder::ipset (
+  $trusted_networks,
+  $ipset_package_ensure,
+  $ipv4_enable,
+  $ipv6_enable
+) {
+
+  assert_private()
+
+  $firewall_service = $facts['os']['family'] ? {
+    'Debian' => 'netfilter-persistent.service',
+    default => undef
+  }
+
+  $packages = "${facts['os']['family']}_${facts['os']['release']['major']}" ? {
+    'RedHat_6' => ['ipset'],
+    default => undef
+  }
+
+  class { 'ipset':
+    packages         => $packages,
+    package_ensure   => $ipset_package_ensure,
+    firewall_service => $firewall_service
+  }
+
+  if ($ipv4_enable) {
+    $trusted_networks_v4 = $trusted_networks.filter |$ip_range| { $ip_range =~ Stdlib::IP::Address::V4 }
+    ipset::set { 'trusted_networks_v4':
+      ensure => 'present',
+      type   => 'hash:net',
+      set    => $trusted_networks_v4;
+    }
+  }
+
+  if ($ipv6_enable) {
+    $trusted_networks_v6 = $trusted_networks.filter |$ip_range| { $ip_range =~ Stdlib::IP::Address::V6 }
+    ipset::set { 'trusted_networks_v6':
+      ensure  => 'present',
+      type    => 'hash:net',
+      set     => $trusted_networks_v6,
+      options => {'family' => 'inet6'}
+    }
+  }
+
+}
+# vim:ts=2:sw=2
diff --git a/manifests/logrotate.pp b/manifests/logrotate.pp
new file mode 100644
index 0000000000000000000000000000000000000000..168916319f950783c7a9b63d5a38dc83add14452
--- /dev/null
+++ b/manifests/logrotate.pp
@@ -0,0 +1,29 @@
+# == Class: fw_builder
+#
+# == Authors:
+#
+#   Pete Pedersen<pete.pedersen@geant.org>
+#   Massimiliano Adamo<massimiliano.adamo@geant.org>
+#
+class fw_builder::logrotate (
+  $logging,
+  $log_rotation_days,
+) {
+
+  assert_private()
+
+  file { ['/var/log/iptables.log', '/var/log/ip6tables.log']: ensure => file; }
+
+  if ($logging) {
+    logrotate::rule { 'iptables':
+      rotate       => $log_rotation_days,
+      dateext      => true,
+      copytruncate => true,
+      missingok    => true,
+      compress     => true,
+      ifempty      => false,
+      path         => '/var/log/ip*tables.log';
+    }
+  }
+
+}
diff --git a/manifests/post.pp b/manifests/post.pp
new file mode 100644
index 0000000000000000000000000000000000000000..08b5d43b301fed39309aaeec65bb5b6f5ac56514
--- /dev/null
+++ b/manifests/post.pp
@@ -0,0 +1,46 @@
+# == Class: fw_builder::post
+#
+class fw_builder::post (
+  $ipv4_enable,
+  $ipv6_enable,
+  $logging,
+  $limit
+) {
+
+  assert_private()
+
+  if ($logging) {
+    $fw_builder::ip_proto_array.each | String $provider | {
+      firewall {
+        default:
+          chain     => 'INPUT',
+          provider  => $provider,
+          jump      => 'LOG',
+          limit     => $limit,
+          log_level => '4';
+        "889 log RST dropped inbound chain for provider ${provider}":
+          log_prefix => "[${provider.upcase()} RST RST] dropped";
+        "900 log dropped inbound chain for provider ${provider}":
+          proto      => all,
+          log_prefix => "[${provider.upcase()} INPUT] dropped ",
+      }
+    }
+  }
+
+  $fw_builder::ip_proto_array.each | String $provider | {
+    firewall {
+      default:
+        chain    => 'INPUT',
+        provider => $provider;
+      "910 deny all other inbound requests for provider ${provider}":
+        before => undef,
+        proto  => all,
+        action => 'drop';
+      "890 drop RST RST connections for provider ${provider}":
+        tcp_flags => 'RST RST',
+        action    => 'drop';
+    }
+  }
+
+}
+# vim:ts=2:sw=2