diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 825ab06595e07b05fa7f3b118cdaa9f5ee73c4ef..5d5ea4ba62227d30461c2dbe1dcedab654dbf9e5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,8 +1,22 @@
 stages:
+  - lint
   - test
   - deb
   - deploy
 
+rubocop:
+  image: debian:buster
+  stage: lint
+  tags:
+    - grid5000-docker
+  script:
+    - apt-get update && apt-get -y --no-install-recommends install rubygems build-essential ruby-dev
+    - gem install rubocop
+    - rubocop -l
+  except:
+   - tags
+
+
 test-vagrant-on-g5k:
   stage: test
   tags:
@@ -11,7 +25,7 @@ test-vagrant-on-g5k:
     - /srv/ci-runner-scripts/bin/test-kadeploy-vagrant
 
 deb:
-  image: debian:jessie
+  image: debian:buster
   stage: deb
   tags:
     - grid5000-docker
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8c824378d15d573aa39ff7dcdfc203c8dea9d706
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,17 @@
+AllCops:
+  Exclude:
+    - 'vagrant-env/**/*'
+    - 'test/**/*'
+    - 'spec/**/*'
+    - 'debian/**/*'
+    - 'doc/**/*'
+    - 'addons/kaenv_migration'
+    - 'addons/deploy_env_generation/**/*'
+    - 'addons/env_migration/**'
+    - 'Rakefile'
+
+Lint/MissingSuper:
+  Exclude:
+    - 'lib/**/*'
+    - 'addons/kascade/kascade'
+
diff --git a/addons/kascade/kascade b/addons/kascade/kascade
index a1fded43869970dd08d9a1b246176e8207f52196..5e8ad9c9efef440c48f2ed0e573436565eb834f5 100755
--- a/addons/kascade/kascade
+++ b/addons/kascade/kascade
@@ -39,7 +39,6 @@
 
 require 'rubygems'
 require 'optparse'
-require 'thread'
 require 'shellwords'
 require 'timeout'
 require 'logger'
@@ -158,12 +157,12 @@ def connect_try(line)
     rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Timeout::Error => e
       $log.debug e
       raise e if retries==i
-      $log.warn("connect_try: connection refused, host unreachable or timeout on #{line}, retrying (#{i+1}/#{retries}): #{e.to_s}")
+      $log.warn("connect_try: connection refused, host unreachable or timeout on #{line}, retrying (#{i+1}/#{retries}): #{e}")
       sleep 1
-    rescue Exception => e
+    rescue StandardError => e
       $log.debug e
       raise e if retries==i
-      $log.warn("connect_try: wildcard exception on #{line}, retrying (#{i+1}/#{retries}): #{e.to_s}")
+      $log.warn("connect_try: wildcard exception on #{line}, retrying (#{i+1}/#{retries}): #{e}")
       sleep 1
     end
   end
@@ -196,15 +195,15 @@ def send_with_timeout(stream, msg)
           n_sock=connect_to(addr[2], addr[1].to_i+$config[:dec_ping_port])
           if n_sock.sysread(4) != 'pong'
             n_sock.close
-            raise ('node dead')
+            raise 'node dead'
           end
           n_sock.close
           $log.info("timeout of #{addr[2]}:#{addr[1]} ping retry")
           retry
-        rescue Exception => e
+        rescue StandardError => e
           $log.debug(e)
           $log.info "ping to #{addr[2]}:#{addr[1]} failed !"
-          raise ('node dead no ping')
+          raise 'node dead no ping'
         end
       end
     end
@@ -273,7 +272,7 @@ class Deploy
     @thread=Thread.new do
       begin
         yield arg
-      rescue Exception => e
+      rescue StandardError => e
         $log.error e
       end
     end
@@ -534,7 +533,7 @@ class Output
   attr_reader :queue
 
   #initialize with variable output. In abstract class i can define without parameter and extend it with parameter.
-  def initialize(e)
+  def initialize(_e)
     @stream=nil
     @threads=[]
   end
@@ -549,7 +548,7 @@ class Output
           @stream.write(buff)
         end
         @stream.close
-      rescue Exception => e
+      rescue StandardError => e
         $log.debug(e)
       end
     end
@@ -710,7 +709,7 @@ class Report
       file.puts(object.to_yaml)
       file.close
     rescue => e
-      $log.error "error during open file #{file_name} #{e.to_s}"
+      $log.error "error during open file #{file_name} #{e}"
     end
     $log.info("The report #{file_name} is written")
   end
@@ -743,13 +742,13 @@ class PingServer
             begin
               client.syswrite('pong')
               $log.info "pong to #{client.peeraddr[2]} #{client.peeraddr[1]}"
-            rescue Exception => e
+            rescue StandardError => e
               $log.debug(e)
             end
             client.close
           }
         end
-      rescue Exception => e
+      rescue StandardError => e
         if @running
           $log.error(e)
         else
@@ -769,7 +768,7 @@ class PingServer
   end
 end
 
-class ReadException < Exception
+class ReadException < RuntimeError
   attr_reader :byte_readed
 
   def initialize(byte_readed)
@@ -777,7 +776,7 @@ class ReadException < Exception
   end
 end
 
-class ForgetException < Exception
+class ForgetException < RuntimeError
   def initialize (ask, min)
     @ask=ask
     @min=min
@@ -815,7 +814,7 @@ class AbstractFountain
   #way 1: Connection to the next node and read GET and execute block with GET parameter or passed end end the transfer
   #way 2: We just execute the block with last parameter.
   def connexion_next
-    begin
+    loop do
       @last_node=$config[:nodeList].size==@index
       if @last_node #We are the last node
         yield nil, 0
@@ -853,17 +852,18 @@ class AbstractFountain
         rescue ReadException => ex_read
           $log.debug(ex_read)
           raise ex_read
-        rescue Exception => e
+        rescue StandardError => e
           host=$config[:nodeList][@index]
           $log.debug(e)
-          $log.error("#{e.to_s} with #{host}")
+          $log.error("#{e} with #{host}")
           @report.add_error(host, e)
           @index+=1
           @retries=$config[:retries]
           @output_stream=nil
         end
       end
-    end while  !@passed && !@last_node
+      break unless !@passed && !@last_node
+    end
   end
 end
 
@@ -910,7 +910,7 @@ class FirstFountain<AbstractFountain
           @queue.push($stdin.read(@chunk_size))
         end
         @queue.push(nil)
-      rescue Exception => e
+      rescue StandardError => e
         $log.error e
       end
     end
@@ -958,7 +958,7 @@ class FirstFountain<AbstractFountain
       end
     end
     if $config[:QUIT] #If ctrl+c is pressed send quit command
-      puts (' quit sent ...')
+      puts(' quit sent ...')
       send_cmd(output_stream, KEYWORDS[:QUIT])
     else #else send end of transfer.
       send_cmd(output_stream, KEYWORDS[:END])
@@ -999,7 +999,7 @@ class FirstFountain<AbstractFountain
     @master_server = nil
 
     #Adjust port in case of another kascade running on same node.
-    begin
+    loop do
       counter += 1
       begin
         port = get_port($config[:master],counter)
@@ -1007,7 +1007,8 @@ class FirstFountain<AbstractFountain
       rescue Errno::EADDRINUSE => ex
         raise ex if !$config[:adjust_port]
       end
-    end while @master_server==nil
+      break unless @master_server==nil
+    end
     if counter > 0
       $log.warn("Adjust master port to #{port}")
       $config[:master] = $config[:master].split(':')[0]+':'+port.to_s
@@ -1030,13 +1031,13 @@ class FirstFountain<AbstractFountain
                 else
                   $log.error("Reader has relieve unknown command #{cmd[0]}")
               end
-            rescue Exception => ex
+            rescue StandardError => ex
               $log.error(ex)
             end
             client.close
           end
         end
-      rescue Exception => ex
+      rescue StandardError => ex
         $log.error ex unless @shunting_down
         $log.info 'master server was shut down'
       end
@@ -1075,7 +1076,7 @@ class Fountain < AbstractFountain
         new_con=@server.accept
         @input_stream.shutdown if @input_stream rescue Exception
         @input_stream=new_con
-      rescue Exception => ex
+      rescue StandardError => ex
         $log.debug(ex) unless @shunting_down
       end
     }
@@ -1107,7 +1108,7 @@ class Fountain < AbstractFountain
     cyclic_buffer=CyclicBuffer.new($config[:buffer_in_memory])
     input_stream=accept
     send_cmd(input_stream, KEYWORDS[:GET], cyclic_buffer.max_byte+1)
-    begin
+    loop do
       begin
         cmd=read_cmd(input_stream)
         case cmd[0]
@@ -1126,15 +1127,16 @@ class Fountain < AbstractFountain
                   @game_over=true
                   break
                 when KEYWORDS[:DATA] #recover part
-                  begin
+                  loop do
                     chunk_transmission(master, cyclic_buffer, answer[1].to_i)
                     answer=read_cmd(master)
-                  end while answer[0]==KEYWORDS[:DATA]
+                    break unless answer[0]==KEYWORDS[:DATA]
+                  end
                   send_cmd(input_stream, KEYWORDS[:GET], cyclic_buffer.max_byte+1)
                 else
                   $log.error("Master send unknown command #{answer[0]}")
               end
-            rescue Exception => e
+            rescue StandardError => e
               $log.error('Loose part')
               $log.debug(e)
               loose
@@ -1173,15 +1175,15 @@ class Fountain < AbstractFountain
             $log.error("Reader has relieve unknown command #{cmd[0]}")
             break
         end
-      rescue Exception => ex #on error with previous wait a client.
-        $log.error("Waiting another client - #{ex.to_s}")
+      rescue StandardError => ex #on error with previous wait a client.
+        $log.error("Waiting another client - #{ex}")
         $log.debug(ex)
         input_stream.close rescue Exception {}
         input_stream=accept
         $log.error("#{input_stream.peeraddr[2]} take over")
         send_cmd(input_stream, KEYWORDS[:GET], cyclic_buffer.max_byte+1)
       end
-    end while true
+    end
   end
 
   #Transmit the chunk by a small packets.
@@ -1222,7 +1224,7 @@ class Fountain < AbstractFountain
               send_with_timeout(output_stream, buffer)
               @before_next_sender_header-=buffer.size
             end
-          rescue Exception => e #Write failure, ask new forwarder
+          rescue StandardError => e #Write failure, ask new forwarder
             file.push(buffer)
             cyclic_buffer.push(buffer)
             raise e
@@ -1299,8 +1301,8 @@ OptionParser.new do |opts|
     $config[:nodeFile]=v
     begin
       $config[:nodeList] = File.readlines(v).map { |l| l.strip }
-    rescue Exception => ex
-      fatal_error "Error: could not open #{v} file: #{ex.to_s}"
+    rescue StandardError => ex
+      fatal_error "Error: could not open #{v} file: #{ex}"
     end
   end
   opts.on('-N', '--node n1[:p1],n2[:p2],...', Array, 'list of node') { |v| $config[:nodeList]=v }
@@ -1335,7 +1337,7 @@ OptionParser.new do |opts|
   opts.separator ''
   opts.separator 'Performance & tuning options:'
   opts.on('-b', '--buffer-size SIZE', "read buffer size, in bytes (default: #{$config[:buffer_size]})") { |v| $config[:buffer_size] = v.to_i }
-  opts.on('-c', '--disable-check-master', 'disable check master in node list') { |v| $config[:check_master] = false }
+  opts.on('-c', '--disable-check-master', 'disable check master in node list') {$config[:check_master] = false }
   opts.on('-C', '--chunk-size SIZE', "size of chunks (amount of data between headers). unit: buffer size (default: #{$config[:chunk_size]})")
   opts.on('-D', '--deploy [ssh,taktuk,clush]', [:ssh, :taktuk, :clush, :none], "Choose deployment method (default: #{$config[:deploy].class.to_s.downcase})") do |v|
     case v
diff --git a/bin/kaconsole3 b/bin/kaconsole3
index 92688c52985abe02faf1151554d39cfb1be69cfa..628503205e532047c7d85ea937f991315a7798ee 100755
--- a/bin/kaconsole3
+++ b/bin/kaconsole3
@@ -43,7 +43,8 @@ class KaconsoleClient < Client
     super()
     begin
       delete(api_path()) if @wid
-    rescue Exception
+    rescue StandardError
+      # do nothing
     end
   end
 
@@ -87,7 +88,7 @@ class KaconsoleClient < Client
     params
   end
 
-  def run(options,params)
+  def run(_options,params)
     ret = post(api_path(),params)
     @wid = ret['wid']
     @resources = ret['resources']
@@ -98,8 +99,8 @@ class KaconsoleClient < Client
     begin
       sock = TCPSocket.new(uri.host,uri.port)
       sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
-    rescue Exception => e
-      error("Fail to connect to remote console #{uri.to_s} "\
+    rescue StandardError => e
+      error("Fail to connect to remote console #{uri} "\
         "(#{e.class.name}: #{e.message})")
     end
 
@@ -155,10 +156,11 @@ class KaconsoleClient < Client
         end
       end
 
-      begin
+      loop do
         sleep SLEEP_PITCH
         done = true if !done and get(api_path('resource'),params)['error']
-      end until done
+        break if done
+      end
 
       threads.each do |thr|
         thr.kill if thr.alive?
@@ -183,7 +185,7 @@ class KaconsoleClient < Client
     get(api_path('resource'),params) if @wid
   end
 
-  def result(options,ret)
+  def result(_options,ret)
     if @wid
       get(api_path('error')) if ret['error']
       delete(api_path())
diff --git a/bin/kaenv3 b/bin/kaenv3
index fd9d01c0b1a584b966efcccc2169e08effb1afa6..c66b95bc2d5eaadead7ce6d1389d930039b2762d 100755
--- a/bin/kaenv3
+++ b/bin/kaenv3
@@ -148,7 +148,7 @@ class KaenvsClient < Client
         options[:env_name] = n
         options[:operation] = :'update-postinstalls-checksum'
       }
-      add_opt(opt,"--move-files", "Move the files of the environments (for administrators only)") { |n|
+      add_opt(opt,"--move-files", "Move the files of the environments (for administrators only)") {
         options[:operation] = :'move-files'
       }
       parse_secure(opt,options)
@@ -163,7 +163,7 @@ class KaenvsClient < Client
         return false
       end
     when :list
-
+      # do nothing
     when :delete, :print, :'update-image-checksum', :'update-preinstall-checksum', :'update-postinstalls-checksum', :'toggle-destructive-tag'
       if options[:env_name].empty?
         error("You must choose an environment")
diff --git a/bin/kanodes3 b/bin/kanodes3
index 4c5a06472391e6ff9af2b51bc9624a2308375cdf..be5c7a0ebbf0c210c90362b60caee030f656041d 100755
--- a/bin/kanodes3
+++ b/bin/kanodes3
@@ -115,7 +115,7 @@ class KanodesClient < Client
     end
   end
 
-  def result(options,ret)
+  def result(_options,ret)
     debug ret if ret
   end
 end
diff --git a/bin/kapower3 b/bin/kapower3
index 30b4b66a1d00d0fd11a8def28d71202b30f87ac4..500c7df9be0340017d6094f885ccb3daedc539e1 100755
--- a/bin/kapower3
+++ b/bin/kapower3
@@ -70,6 +70,7 @@ class KapowerClient < ClientWorkflow
       params[:status] = options[:operation]
       params[:level] = options[:level] if options[:level]
     when :status
+      # do nothing
     else
       raise
     end
diff --git a/db/db_creation.sql b/db/db_creation.sql
index 24ac349b8e01f317259a50f238fd3007605b42fa..42301599258b5a64488bcc103f9a85e0dee78d2f 100644
--- a/db/db_creation.sql
+++ b/db/db_creation.sql
@@ -26,7 +26,7 @@ CREATE TABLE IF NOT EXISTS `environments` (
   `fdisk_type` varchar(2) default NULL,
   `filesystem` varchar(9) default NULL,
   `user` varchar(255) default 'nobody',
-  `allowed_users` varchar(512) NOT NULL,
+  `allowed_users` varchar(512) NOT NULL default '',
   `environment_kind` varchar(10) NOT NULL,
   `visibility` varchar(8) NOT NULL,
   `demolishing_env` boolean NOT NULL default FALSE,
diff --git a/db/update-15.1.sql b/db/update-15.1.sql
new file mode 100644
index 0000000000000000000000000000000000000000..428862cb49c715f4b2c5e720e188b176063b7057
--- /dev/null
+++ b/db/update-15.1.sql
@@ -0,0 +1,4 @@
+--
+-- Add default for allow user
+--
+ALTER TABLE `environments` ALTER `allowed_users` SET DEFAULT '';
diff --git a/debian/control b/debian/control
index b7271104f16a88c088c3449015f9b8caf01c8b58..35ed49436b14097b23c415a6b31b115e7b2f7e5f 100644
--- a/debian/control
+++ b/debian/control
@@ -41,7 +41,7 @@ XB-Ruby-Versions: ${ruby:Versions}
 
 Package: kadeploy
 Architecture: all
-Depends: ${shlibs:Depends}, ${misc:Depends}, kadeploy-common (= ${binary:Version}), ruby | ruby-interpreter, ruby-mysql | libmysql-ruby, openssh-client | ssh, taktuk
+Depends: ${shlibs:Depends}, ${misc:Depends}, kadeploy-common (= ${binary:Version}), ruby | ruby-interpreter, ruby-mysql2 , openssh-client | ssh, taktuk
 Recommends: kadeploy-client (= ${binary:Version}), tftpd-hpa | atftpd | tftpd, syslinux-common
 Description: Scalable, efficient and reliable cluster provisioning solution (server)
  Kadeploy is a scalable, efficient and reliable deployment system (cluster
diff --git a/lib/kadeploy3/client/client.rb b/lib/kadeploy3/client/client.rb
index 5d12d13dcdea11af9e5283b0fffaa442f1ec38fc..7541f409f536c4e20b870aefc397164c190bcead 100644
--- a/lib/kadeploy3/client/client.rb
+++ b/lib/kadeploy3/client/client.rb
@@ -13,7 +13,6 @@ $interactive = true
 $http_user = nil
 $http_password = nil
 
-require 'thread'
 require 'uri'
 require 'optparse'
 require 'net/http'
@@ -129,7 +128,7 @@ class Client
         tmp = nil if tmp.empty?
         servers[cp.value('name',String)] = [
           cp.value('hostname',String),
-          cp.value('port',Fixnum),
+          cp.value('port', Integer),
           cp.value('secure',[TrueClass,FalseClass],true),
           tmp
         ]
@@ -172,7 +171,6 @@ class Client
       end
       FetchFile[uri.to_s,true].grab(tmpfile.path)
       tmpfile.close
-      uri = nil
     rescue KadeployError => ke
       tmpfile.unlink
       error(ke.message)
@@ -500,7 +498,7 @@ class Client
         HTTP::Client::get(host,port,path,secure,nil,nil,nil,headers)
         return true
       end
-    rescue Exception
+    rescue StandardError
       return false
     end
   end
@@ -774,7 +772,7 @@ class Client
 
   def self.launch()
     options = nil
-    error() unless options = parse_options()
+    error() unless (options = parse_options())
     # Hack to make the --version work even if the client is not installed
     if options[:get_version] and ENV['KADEPLOY3_VERSION']
       $stdout.puts ENV['KADEPLOY3_VERSION']
@@ -908,11 +906,11 @@ class Client
   def self.check_options(options)
   end
 
-  def self.check_params(options,params)
+  def self.check_params(_options,params)
     params
   end
 
-  def run(options,params)
+  def run(_options,_params)
     raise
   end
 
@@ -954,7 +952,8 @@ class ClientWorkflow < Client
     super()
     begin
       delete(api_path()) if @wid
-    rescue Exception
+    rescue StandardError
+      # do nothing
     end
   end
 
@@ -1226,9 +1225,9 @@ class ClientWorkflow < Client
   def self.prepare(options)
     params = super(options)
     if options[:custom_operations]
-      options[:custom_operations].each_pair do |macro,micros|
-        micros.each_pair do |micro,ops|
-          ops.each_pair do |op,acts|
+      options[:custom_operations].each_value do |micros|
+        micros.each_value do |ops|
+          ops.each_value do |acts|
             acts.each do |act|
               add_localfiles(act['file']) if act['file']
             end
@@ -1278,7 +1277,7 @@ class ClientWorkflow < Client
       out = []
 
       res = nil
-      begin
+      loop do
         res = get(api_path('resource'))
 
         yield(res) if block_given?
@@ -1311,7 +1310,8 @@ class ClientWorkflow < Client
         end
 
         sleep SLEEP_PITCH
-      end until res['done']
+        break if res['done']
+      end
 
       get(api_path('error')) if res['error']
 
@@ -1360,17 +1360,17 @@ class ClientWorkflow < Client
           if status.is_a?(Hash)
             status['nodes'].each_pair do |state,nodes|
               unless nodes.empty?
-                debug "#{prefix}  [#{macro.to_s}-#{micro.to_s}] ~#{status['time']}s (#{state.to_s})"
+                debug "#{prefix}  [#{macro}-#{micro}] ~#{status['time']}s (#{state})"
                 debug "#{prefix}     #{nodes.join("\n#{prefix}     ")}"
               end
             end
           elsif status.is_a?(Array)
-            debug "#{prefix}  [#{macro.to_s}-#{micro.to_s}]"
+            debug "#{prefix}  [#{macro}-#{micro}]"
             debug "#{prefix}    #{status.join("\n#{prefix}    ")}"
           end
         end
       elsif micros.is_a?(Array)
-        debug "#{prefix}  [#{macro.to_s}]"
+        debug "#{prefix}  [#{macro}]"
         debug "#{prefix}    #{micros.join("\n#{prefix}    ")}"
       end
     end
diff --git a/lib/kadeploy3/common/compat.rb b/lib/kadeploy3/common/compat.rb
index 3d1e742044274d1cc494c2473715a88431011948..5a0ad39b6fac8310dde9b6395521e801162daa95 100644
--- a/lib/kadeploy3/common/compat.rb
+++ b/lib/kadeploy3/common/compat.rb
@@ -24,7 +24,7 @@ if RUBY_VERSION < '1.9'
 
   class Float
     alias_method :__round__, :round
-    def round(*args)
+    def round(*)
       __round__()
     end
   end
@@ -58,7 +58,7 @@ if RUBY_VERSION < '1.9'
   end
 
   module URI
-    def self.encode_www_form_component(str,*args)
+    def self.encode_www_form_component(str,*)
       encode(str.to_s)
     end
 
@@ -82,7 +82,7 @@ if RUBY_VERSION < '1.9'
       end.join('&')
     end
 
-    def self.decode_www_form_component(str,*args)
+    def self.decode_www_form_component(str,*)
       decode(str)
     end
 
@@ -131,7 +131,7 @@ if RUBY_VERSION < '1.9'
   end
 
   module Psych
-    class SyntaxError < Exception
+    class SyntaxError < RuntimeError
     end
   end
 end
diff --git a/lib/kadeploy3/common/configparser.rb b/lib/kadeploy3/common/configparser.rb
index a03f67ea8c3f93f8b2789d8196d267ada78805c9..6b0efaa53679c66d8a0fae843fd76302b3903612 100644
--- a/lib/kadeploy3/common/configparser.rb
+++ b/lib/kadeploy3/common/configparser.rb
@@ -101,6 +101,7 @@ module Configuration
         begin
           field = Integer(field)
         rescue ArgumentError
+          # do nothing
         end
 
         if ret[field]
@@ -167,7 +168,7 @@ module Configuration
       end
     end
 
-    def check_array(val, array, fieldname)
+    def check_array(val, array, _fieldname)
       unless array.include?(val)
         raise ParserError.new(
           "Invalid value '#{val}', allowed value"\
@@ -187,7 +188,7 @@ module Configuration
       check_array(val, range.entries, fieldname)
     end
 
-    def check_regexp(val, regexp, fieldname)
+    def check_regexp(val, regexp, _fieldname)
       unless val =~ regexp
         raise ParserError.new(
           "Invalid value '#{val}', the value must have the form (ruby-regexp): "\
@@ -197,7 +198,7 @@ module Configuration
     end
 
     # A file, checking if exists (creating it otherwise) and writable
-    def check_file(val, file, fieldname)
+    def check_file(val, _file, _fieldname)
       if File.exist?(val)
         unless File.file?(val)
           raise ParserError.new("The file '#{val}' is not a regular file")
@@ -208,7 +209,7 @@ module Configuration
     end
 
     # A directory, checking if exists (creating it otherwise) and writable
-    def check_dir(val, dir, fieldname)
+    def check_dir(val, _dir, _fieldname)
       if File.exist?(val)
         unless File.directory?(val)
           raise ParserError.new("'#{val}' is not a regular directory")
@@ -219,7 +220,7 @@ module Configuration
     end
 
     # A pathname, checking if exists (creating it otherwise) and writable
-    def check_pathname(val, pathname, fieldname)
+    def check_pathname(val, _pathname, _fieldname)
       begin
         Pathname.new(val)
       rescue
@@ -227,7 +228,7 @@ module Configuration
       end
     end
 
-    def check_string(val, str, fieldname)
+    def check_string(val, str, _fieldname)
       unless val == str
         raise ParserError.new(
           "Invalid value '#{val}', allowed values are: '#{str}'"
@@ -235,14 +236,15 @@ module Configuration
       end
     end
 
-    def customcheck_code(val, fieldname, args)
+    def customcheck_code(_val, _fieldname, args)
       begin
         eval("#{args[:prefix]}#{args[:code]}#{args[:suffix]}")
       rescue
         raise ParserError.new("Invalid expression '#{args[:code]}'")
       end
     end
-    def customcheck_file(val, fieldname, args)
+
+    def customcheck_file(val, _fieldname, args)
       return if args[:disable]
       if args[:command]
         val = val.split(/\s+/).first||''
@@ -298,7 +300,7 @@ module Configuration
       end
     end
 
-    def customcheck_dir(val, fieldname, args)
+    def customcheck_dir(val, _fieldname, args)
       return if args[:disable]
       val = File.join(args[:prefix],val) if args[:prefix] and !val.empty?
       val = File.join(val,args[:suffix]) if args[:suffix] and !val.empty?
diff --git a/lib/kadeploy3/common/environment.rb b/lib/kadeploy3/common/environment.rb
index 9c1994615163604e45bc1cd54d35ae6487bf34ce..6bf354731c79ace04f38e0598a13e8f46106a113 100644
--- a/lib/kadeploy3/common/environment.rb
+++ b/lib/kadeploy3/common/environment.rb
@@ -148,6 +148,7 @@ class Environment
       mandatory << :@kernel
       mandatory << :@filesystem
     when 'dd'
+      # do nothing
     end
 
     mandatory.each do |name|
@@ -175,7 +176,7 @@ class Environment
   # * user: true user
   # Output
   # * returns true if the environment can be loaded correctly, false otherwise
-  def load_from_desc(description, almighty_env_users, user, client=nil, get_checksum=true,output=nil)
+  def load_from_desc(description, _almighty_env_users, user, client=nil, get_checksum=true,output=nil)
     @recorded = false
     @user = user
     @preinstall = nil
@@ -185,7 +186,7 @@ class Environment
     begin
       cp = Configuration::Parser.new(description)
       @name = cp.value('name',String)
-      @version = cp.value('version',Fixnum,1)
+      @version = cp.value('version', Integer,1)
       @description = cp.value('description',String,'')
       @author = cp.value('author',String,'')
       @visibility = cp.value('visibility',String,'private',['public','private','shared'])
@@ -197,7 +198,7 @@ class Environment
         kind = cp.value('kind',String,nil,IMAGE_KIND)
         compress = nil
         if kind == 'fsa'
-          compress = cp.value('compression',Fixnum,0,Array(0..9)).to_s
+          compress = cp.value('compression',Integer,0,Array(0..9)).to_s
         else
           compress = cp.value('compression',String,nil,IMAGE_COMPRESSION)
         end
@@ -266,7 +267,7 @@ class Environment
       end
 
       @filesystem = cp.value('filesystem',String,'')
-      @fdisk_type = cp.value('partition_type',Fixnum,0).to_s(16) #numeric or hexa
+      @fdisk_type = cp.value('partition_type',Integer,0).to_s(16) #numeric or hexa
       @multipart = cp.value('multipart',[TrueClass,FalseClass],false)
       @options = {}
       cp.parse('options',@multipart) do |info|
@@ -275,7 +276,7 @@ class Environment
           cp.parse('partitions',true,Array) do |info2|
             unless info2[:empty]
               tmp = {
-                'id' => cp.value('id',Fixnum),
+                'id' => cp.value('id', Integer),
                 'device' => cp.value('device',String),
               }
               # Check if 'id' already defined for another partition
@@ -319,7 +320,7 @@ class Environment
         @hypervisor_params = cp.value('hypervisor_params',String,'')
         if @multipart
           @options['block_device'] = cp.value('block_device',String)
-          @options['deploy_part'] = cp.value('partition',Fixnum).to_s
+          @options['deploy_part'] = cp.value('partition',Integer).to_s
         end
       end
 
@@ -387,7 +388,7 @@ class Environment
   end
 
   def self.get_from_db(dbh, name, version, user, private_envs=false, public_envs=false)
-    version = version.to_s if version.is_a?(Fixnum)
+    version = version.to_s if version.is_a?(Integer)
     args = []
     last_version = false
     sort=''
@@ -647,7 +648,7 @@ class Environment
 
   # returns true if it worked, the already existing environments if it doesnt
   def save_to_db(dbh)
-    if envs = self.class.get_from_db(dbh,@name,@version,@user,true,false)
+    if (envs = self.class.get_from_db(dbh,@name,@version,@user,true,false))
       envs
     else
       dbh.run_query(
diff --git a/lib/kadeploy3/common/error.rb b/lib/kadeploy3/common/error.rb
index 5bb26c8417c7796c5b22f21d6d6f0ce5c3261fb4..a11cebbd0b5412eac0d764de7f7097c899ef1d8e 100644
--- a/lib/kadeploy3/common/error.rb
+++ b/lib/kadeploy3/common/error.rb
@@ -1,6 +1,6 @@
 module Kadeploy
 
-class KadeployError < Exception
+class KadeployError < RuntimeError
   attr_reader :errno, :context
   attr_writer :context
   def initialize(errno,context={},msg='')
@@ -58,9 +58,6 @@ class KadeployError < Exception
 end
 
 class KadeployHTTPError < KadeployError
-  def initialize(errno)
-    super(errno)
-  end
 end
 
 class KadeployExecuteError < KadeployError
diff --git a/lib/kadeploy3/common/execute.rb b/lib/kadeploy3/common/execute.rb
index e81dbc8cf35dcf3ea66c4e97d0ad2d47c1aa9fc4..2a5155c9f838449eb01d64065e7ef36291453142 100644
--- a/lib/kadeploy3/common/execute.rb
+++ b/lib/kadeploy3/common/execute.rb
@@ -2,7 +2,6 @@ module Kadeploy
 
   # To be used as you're using Open3.popen3 in ruby 1.9.2
   class Execute
-    require 'thread'
     require 'fcntl'
     attr_reader :command, :exec_pid, :stdout, :stderr, :status,:emptypipes
     @@forkmutex = Mutex.new
@@ -261,14 +260,14 @@ module Kadeploy
                  f_IO=IO.new(fd)
                  f_IO.close if !f_IO.closed?
               end
-            rescue Exception
+            rescue StandardError
               #Some file descriptor are reserved for the rubyVM.
               #So the function 'IO.new' raises an exception. We ignore that.
             end
           end
         end
         exec(*@command)
-      rescue SystemCallError, Exception => e
+      rescue StandardError => e
         STDERR.puts "Fork Error: #{e.message} (#{e.class.name})"
         STDERR.puts e.backtrace
       end
diff --git a/lib/kadeploy3/common/fetchfile.rb b/lib/kadeploy3/common/fetchfile.rb
index d48a8cab32067a1a83d678d9203e9c95d9219a1a..c6d7b08895057b82df4c449c48df8b11f78fb490 100644
--- a/lib/kadeploy3/common/fetchfile.rb
+++ b/lib/kadeploy3/common/fetchfile.rb
@@ -52,7 +52,7 @@ class FetchFile
     raise 'Should be reimplemented'
   end
 
-  def grab(dest,dir=nil)
+  def grab(_dest,_dir=nil)
     raise 'Should be reimplemented'
   end
 end
@@ -82,11 +82,11 @@ class ServerFetchFile < FetchFile
     end
   end
 
-  def grab(dest,dir=nil)
+  def grab(dest,_dir=nil)
     if File.readable?(@origin_uri)
       begin
         Execute['cp',@origin_uri,dest].run!.wait
-      rescue Exception => e
+      rescue StandardError => e
         error("Unable to grab the file #{@origin_uri} (#{e.message})")
       end
     else
@@ -118,7 +118,7 @@ class HTTPFetchFile < FetchFile
       error("Unable to get the size of #{@origin_uri} (connection refused)")
     rescue KadeployError => ke
       raise ke
-    rescue Exception => e
+    rescue StandardError => e
       error("Unable to grab the file #{@origin_uri} (#{e.message})")
     end
   end
@@ -130,7 +130,7 @@ class HTTPFetchFile < FetchFile
       error("Unable to get the checksum of #{@origin_uri} (http error ##{k.errno})")
     rescue KadeployError => ke
       raise ke
-    rescue Exception => e
+    rescue StandardError => e
       error("Unable to get the checksum of #{@origin_uri} (#{e.message})")
     end
   end
@@ -144,12 +144,12 @@ class HTTPFetchFile < FetchFile
       raise ke
     rescue Errno::ECONNREFUSED
       error("Unable to get the mtime of #{@origin_uri} (connection refused)")
-    rescue Exception => e
+    rescue StandardError => e
       error("Unable to grab the file #{@origin_uri} (#{e.message})")
     end
   end
 
-  def grab(dest,dir=nil)
+  def grab(dest,_dir=nil)
     begin
       HTTP.fetch_file(@origin_uri,dest)
       nil
@@ -159,7 +159,7 @@ class HTTPFetchFile < FetchFile
       raise ke
     rescue Errno::ECONNREFUSED
       error("Unable to get the mtime of #{@origin_uri} (connection refused)")
-    rescue Exception => e
+    rescue StandardError => e
       error("Unable to grab the file #{@origin_uri} (#{e.message})")
     end
   end
diff --git a/lib/kadeploy3/common/http.rb b/lib/kadeploy3/common/http.rb
index 7414de4401a21434e6c67280f57e0b2cf2bab896..5aaeb2ce13608cbcd7c94e3832c5056797f67938 100644
--- a/lib/kadeploy3/common/http.rb
+++ b/lib/kadeploy3/common/http.rb
@@ -13,7 +13,6 @@ module Kadeploy
 module HTTP
   HTTP_TIMEOUT = 120
 
-  public
   # Fetch a file over HTTP
   #
   # Arguments
@@ -47,7 +46,6 @@ module HTTP
 
   def self.check_file(uri)
     url = URI.parse(uri)
-    resp = nil
     http = Net::HTTP.new(url.host, url.port)
     http.use_ssl = url.is_a?(URI::HTTPS)
     http.verify_mode = OpenSSL::SSL::VERIFY_NONE
@@ -71,7 +69,8 @@ module HTTP
     return Time.parse(self.check_file(uri)['last-modified'][0]).to_i
   end
 
-  class ClientError < Exception
+
+  class ClientError < RuntimeError
     attr_reader :code
     def initialize(msg,code=nil)
       super(msg)
@@ -112,7 +111,7 @@ module HTTP
           request = yield(client) unless request
           raise unless request.is_a?(Net::HTTPRequest)
           response = client.request(request)
-        rescue Exception => e
+        rescue StandardError => e
           error("Invalid request on #{server}:#{port} (#{e.message})")
         end
 
@@ -131,7 +130,7 @@ module HTTP
           if parse
             begin
               tmp = response['Content-Type'].split(';').first.downcase
-            rescue Exception
+            rescue StandardError
               tmp = ''
             end
 
@@ -230,7 +229,7 @@ module HTTP
       ret
     end
 
-    def self.get(server,port,path,secure=true,content_type=nil,accept_type=nil,parse=nil,headers=nil)
+    def self.get(server,port,path,secure=true,_content_type=nil,accept_type=nil,parse=nil,headers=nil)
       request(server,port,secure,gen_request(:GET,path,nil,nil,accept_type,headers),parse)
     end
 
diff --git a/lib/kadeploy3/common/httpd.rb b/lib/kadeploy3/common/httpd.rb
index 14a5561d3bcb19dc91fa1ade3a0bd3dd281ea592..b056cfcdae7f0ab4a6cc33e36f42a2baed7094d5 100644
--- a/lib/kadeploy3/common/httpd.rb
+++ b/lib/kadeploy3/common/httpd.rb
@@ -39,7 +39,7 @@ module HTTPd
   MAX_CONTENT_SIZE = 1048576 # 1 MB
   SERVLET_TIMEOUT = 600 #10 min
 
-  class HTTPError < Exception
+  class HTTPError < RuntimeError
     attr_reader :code,:headers
     def initialize(code,name,msg=nil,headers=nil)
       super(msg)
@@ -84,7 +84,7 @@ module HTTPd
     end
   end
 
-  class ServletTimeout < Exception
+  class ServletTimeout < RuntimeError
     def set_backtrace(array)
       time=Time.now()
       $stderr.puts("[#{time}] Servlet execution is timed out")
@@ -192,7 +192,7 @@ module HTTPd
 
       unless res.is_a?(Hash)
         raise UnsupportedError.new(
-          'The content of the request\'s body must be ''a Hash')
+          'The content of the request\'s body must be a Hash')
       end
 
       # Parse HTTP request's query string
@@ -270,7 +270,7 @@ module HTTPd
       self.class.name
     end
 
-    def get_instance(server, *options)
+    def get_instance(_server, *)
       self
     end
 
@@ -376,8 +376,6 @@ module HTTPd
               request_handler.output(ret)
           end
           request_handler.free
-          request_handler = nil
-          ret = nil
         rescue HTTPError => e
           res = e.message
           response.status = e.code
@@ -396,7 +394,7 @@ module HTTPd
           $stderr.puts("[#{Time.now}] Internal Server Error  #{res}")
           $stderr.puts(ke.backtrace())
           $stderr.flush
-        rescue Exception => e
+        rescue StandardError => e
           res = "---- #{e.class.name} ----\n"\
             "#{e.message}\n"\
             "---- Stack trace ----\n"\
@@ -424,10 +422,9 @@ module HTTPd
         response['Content-Length'] = res.size
       end
       response.body = res unless get_method(request) == :HEAD
-      res = nil
     end
 
-    def handle(request, response, request_handler)
+    def handle(_request, _response, _request_handler)
       raise
     end
 
@@ -444,7 +441,7 @@ module HTTPd
       @proc = proc
     end
 
-    def handle(request, response, request_handler)
+    def handle(request, _response, _request_handler)
       @proc.call(get_method(request),request)
     end
   end
@@ -459,7 +456,7 @@ module HTTPd
       @blocks = blocks
     end
 
-    def handle(request, response, request_handler, args=nil, params={})
+    def handle(request, _response, request_handler, args=nil, params={})
       args = @args.dup if args.nil? and !@args.nil?
       args = args[get_method(request)] if args.is_a?(ContentBinding)
       args = [] if args.nil?
@@ -565,7 +562,7 @@ module HTTPd
       @content = content
     end
 
-    def handle(request, response, request_handler)
+    def handle(request, _response, _request_handler)
       if @content.is_a?(ContentBinding)
         return @content[get_method(request)]
       else
diff --git a/lib/kadeploy3/common/nodes.rb b/lib/kadeploy3/common/nodes.rb
index ba6f5a237819b8b9190d67d28341e9bfcd5628eb..3de212f4862f887b8a554f0aecc4377d53f3311e 100644
--- a/lib/kadeploy3/common/nodes.rb
+++ b/lib/kadeploy3/common/nodes.rb
@@ -1,5 +1,3 @@
-require 'thread'
-
 module Kadeploy
 
 module Nodes
@@ -265,6 +263,29 @@ module Nodes
       @set.clear()
     end
 
+    # Develop list of numbers into array of numbers
+    # eg: 5-9 => [5 6 7 8 9]
+    #
+    # Arguments
+    # * interval: list of numbers(eg: "5-16") of hostnames
+    #
+    # Output
+    # * returns array of numbers
+    def NodeSet::develop_interval(interval)
+      numbers_array =[]
+      if /(\d+)-(\d+)/ =~ interval
+        content = Regexp.last_match
+        if content[1].length == content[2].length
+          numbers_array += (content[1] .. content[2]).to_a
+        else
+          numbers_array += (content[1].to_i .. content[2].to_i).to_a
+        end
+      else
+        numbers_array += [interval]
+      end
+      return numbers_array
+    end
+
     private
 
     # Sort hostname
@@ -293,30 +314,6 @@ module Nodes
       return hosts1.sort + hosts2.sort + hosts3 + hosts4.sort
     end
 
-
-    # Develop list of numbers into array of numbers
-    # eg: 5-9 => [5 6 7 8 9]
-    #
-    # Arguments
-    # * interval: list of numbers(eg: "5-16") of hostnames
-    #
-    # Output
-    # * returns array of numbers 
-    def NodeSet::develop_interval(interval)
-      numbers_array =[]
-      if /(\d+)-(\d+)/ =~ interval
-        content = Regexp.last_match
-        if content[1].length == content[2].length
-          numbers_array += (content[1] .. content[2]).to_a
-        else
-          numbers_array += (content[1].to_i .. content[2].to_i).to_a
-        end
-      else
-        numbers_array += [interval]
-      end
-      return numbers_array
-    end
-    
     # Make an array of figures 
     # eg: 1,3,5-9 => [1 3 5 6 7 8 9]
     #
@@ -388,7 +385,6 @@ module Nodes
       similar_array = []
       diff_array = []
       head = ""
-      tail = []
       array_host1 = separate_number_letter(hostname1)
       array_host2 = separate_number_letter(hostname2)
       if array_host1.length == array_host2.length
@@ -508,6 +504,11 @@ module Nodes
       return head + "[" + list_number + "]" + tail
     end
 
+    private_class_method(:make_array_of_figures,
+                         :make_array_of_hostnames, :separate_number_letter,
+                         :diff_hosts, :cmp_hosts, :remote_host_find,
+                         :numbers_fold, :nodes_group_list_fold)
+
     public
     # Convert a string of hostnames' factorization into an array of hosts 
     #
@@ -531,12 +532,12 @@ module Nodes
         else
           puts "ips or hostnames not correct"
         end
-      end  
+      end
       array_figures = make_array_of_figures(numbers_list)
       return make_array_of_hostnames(array_figures,head,tail)
-    end  
+    end
 
-    def method_missing(method_sym, *args)
+    def method_missing(method_sym, *)
       raise "Wrong method: #{method_sym} !!!"
     end
 
@@ -815,7 +816,7 @@ module Nodes
       return out.join(delimiter)
     end
 
-    def to_h(dbg = false)
+    def to_h(_dbg = false)
       out = Hash.new
       @set.each { |node|
         out[node.hostname] = Hash["ip" => node.ip, "cluster" => node.cluster, "state" => node.state,
diff --git a/lib/kadeploy3/server/authentication.rb b/lib/kadeploy3/server/authentication.rb
index ad3da6232f25b237ac5b025998e8c7c063f2dfc2..24e00b024909fe85eb55f847fe601acf8d2782dd 100644
--- a/lib/kadeploy3/server/authentication.rb
+++ b/lib/kadeploy3/server/authentication.rb
@@ -36,6 +36,7 @@ class Authentication
               break
             end
           rescue Resolv::ResolvError
+            # do nothing
           end
         else
           raise
@@ -45,13 +46,13 @@ class Authentication
     end
   end
 
-  def auth!(source_sock,params={})
+  def auth!(_source_sock,_params={})
     raise
   end
 end
 
 class ACLAuthentication < Authentication
-  def auth!(source_sock,params={})
+  def auth!(source_sock,_params={})
     return [check_host?(source_sock),UNTRUSTED_SOURCE]
   end
 
@@ -112,7 +113,7 @@ class CertificateAuthentication < Authentication
     cert = nil
     begin
       cert = OpenSSL::X509::Certificate.new(params[:cert])
-    rescue Exception => e
+    rescue StandardError => e
       return [false,"Invalid x509 certificate (#{e.message})"]
     end
 
diff --git a/lib/kadeploy3/server/automata.rb b/lib/kadeploy3/server/automata.rb
index b2e2a40f96d17649fe3f8f9fec4c0c66237c3ee6..6d6fb4c8ccd7746316dc08caf4935daa6a2d6a2a 100644
--- a/lib/kadeploy3/server/automata.rb
+++ b/lib/kadeploy3/server/automata.rb
@@ -1,4 +1,3 @@
-require 'thread'
 require 'timeout'
 
 module Kadeploy
@@ -55,7 +54,7 @@ module Automata
       raise 'Should be reimplemented'
     end
 
-    def kill(dofree=true)
+    def kill(_dofree=true)
       raise 'Should be reimplemented'
     end
 
@@ -174,7 +173,6 @@ module Automata
         @threads_lock.synchronize do
           @threads.each_key do |task|
             task.free
-            task = nil
           end
           @threads.clear
           @threads = nil
@@ -188,7 +186,7 @@ module Automata
       @cleaner = nil
     end
 
-    def create_task(idx,subidx,nodes,nsid,context)
+    def create_task(_idx,_subidx,_nodes,_nsid,_context)
       raise 'Should be reimplemented'
     end
 
@@ -200,29 +198,29 @@ module Automata
       raise 'Should be reimplemented'
     end
 
-    def custom(task,operation)
+    def custom(_task,_operation)
       raise 'Should be reimplemented'
     end
 
-    def break!(task,nodeset)
+    def break!(_task,_nodeset)
     end
 
-    def success!(task,nodeset)
+    def success!(_task,_nodeset)
     end
 
-    def fail!(task,nodeset)
+    def fail!(_task,_nodeset)
     end
 
-    def display_fail_message(task,nodeset)
+    def display_fail_message(_task,_nodeset)
     end
 
-    def timeout!(task)
+    def timeout!(_task)
     end
 
-    def retry!(task,nodeset)
+    def retry!(_task,_nodeset)
     end
 
-    def split!(nsid0,nsid1,ns1,nsid2,ns2)
+    def split!(_nsid0,_nsid1,_ns1,_nsid2,_ns2)
     end
 
     def kill!()
@@ -325,7 +323,7 @@ module Automata
     def load_tasks
     end
 
-    def done_task(task,nodeset)
+    def done_task(_task,nodeset)
       @nodes_done.add(nodeset)
     end
 
@@ -335,13 +333,13 @@ module Automata
       break!(task,nodeset)
     end
 
-    def success_task(task,nodeset,rnsid=nil)
+    def success_task(task,nodeset,_rnsid=nil)
       done_task(task,nodeset)
       nodeset.linked_copy(nodes_ok())
       success!(task,nodeset)
     end
 
-    def fail_task(task,nodeset,rnsid=nil)
+    def fail_task(task,nodeset,_rnsid=nil)
       done_task(task,nodeset)
       nodeset.linked_copy(nodes_ko())
       fail!(task,nodeset)
@@ -689,7 +687,7 @@ module Automata
         @threads_lock.synchronize do
           @threads.each_pair do |task,threads|
             task.kill(false)
-            threads.each_pair do |key,thread|
+            threads.each_value do |thread|
               thread.kill if thread.alive?
               thread.join
             end
diff --git a/lib/kadeploy3/server/bittorrent.rb b/lib/kadeploy3/server/bittorrent.rb
index a3ac062a29b3f6fa281178a37cd7d1deaeca7a85..f7ad8fdc1c087e9384c61359c9c3a900df1ae675 100644
--- a/lib/kadeploy3/server/bittorrent.rb
+++ b/lib/kadeploy3/server/bittorrent.rb
@@ -5,7 +5,6 @@ module Kadeploy
 module Bittorrent
   DEFAULT_BITTORRENT_PORT = 6969
 
-  private
   # Get the hash reference of a torrent
   #
   # Arguments
@@ -66,8 +65,8 @@ module Bittorrent
     end
   end
 
+  private_class_method :get_downloaded, :get_torrent_hash, :get_remaining_download
 
-  public
 
   # Launch a Bittorrent tracker
   #
diff --git a/lib/kadeploy3/server/cache.rb b/lib/kadeploy3/server/cache.rb
index d1c4b6293c79d13fff45903b118a65dd5846f76c..00859d6fe0d511aad6e3369303bcdf9c8e16beb7 100644
--- a/lib/kadeploy3/server/cache.rb
+++ b/lib/kadeploy3/server/cache.rb
@@ -1,5 +1,4 @@
 require 'pathname'
-require 'thread'
 require 'fileutils'
 require 'digest'
 require 'digest/md5'
@@ -7,17 +6,15 @@ require 'uri'
 require 'yaml'
 require 'set'
 
-YAML::ENGINE.yamler = 'syck' if RUBY_VERSION >= '1.9'
-
 module Kadeploy
 
   #Used for environments
   class CacheIndexPVHash
     def self.name(params)
       if params[:tag]
-        "#{params[:tag]}-#{params[:version].to_s}-#{params[:origin_uri]}".gsub(/\W/,'_')+".data"
+        "#{params[:tag]}-#{params[:version]}-#{params[:origin_uri]}".gsub(/\W/,'_')+".data"
       else
-        "#{params[:version].to_s}-#{params[:origin_uri]}".gsub(/\W/,'_')+".data"
+        "#{params[:version]}-#{params[:origin_uri]}".gsub(/\W/,'_')+".data"
       end
     end
   end
@@ -259,7 +256,7 @@ module Kadeploy
 
     #Put file into the cache and update the data structure
     #Arguments: see the fetch function
-    def get_file(user,origin_uri,priority,version,size,md5,mtime,tag,&block)
+    def get_file(user,origin_uri,priority,version,size,md5,mtime,tag,&_block)
       begin
         @user = user
         @priority = priority
@@ -282,7 +279,7 @@ module Kadeploy
         @fetched = true
         @fetched_error = nil
         save!()
-      rescue Exception => ex
+      rescue StandardError => ex
         @fetched = false
         @fetched_error=ex
         FileUtils.rm_f(@file_in_cache) if @file_in_cache && File.exist?(@file_in_cache)
@@ -361,7 +358,7 @@ module Kadeploy
     def initialize(directory, max_size, concurrency_level, naming_meth, emptycache=true, save_meta=false)
       raise KadeployError.new(APIError::CACHE_ERROR,nil,"#{directory} is not a directory") if directory && !File.directory?(directory)
       raise KadeployError.new(APIError::CACHE_ERROR,nil,"Save meta without directory is not allowed") if save_meta && directory.nil?
-      raise KadeployError.new(APIError::CACHE_ERROR,nil,"Invalid cache size '#{max_size}'") if !(max_size.is_a?(Fixnum) or max_size.is_a?(Bignum))  or max_size <= 0
+      raise KadeployError.new(APIError::CACHE_ERROR,nil,"Invalid cache size '#{max_size}'") if !(max_size.is_a?(Integer))  or max_size <= 0
 
       @directory = directory
       @max_size = max_size     # Bytes
@@ -429,7 +426,7 @@ module Kadeploy
           end
           file.fetch(user,origin_uri,priority,version,size,md5,mtime,tag,&block)
         end
-      rescue Exception => ex
+      rescue StandardError => ex
         @lock.synchronize do
           file.release(wid)
           if !file.fetched && file.try_free
@@ -467,7 +464,7 @@ module Kadeploy
         to_del=[]
         @files.each_value do |file|
           if file.priority <= max_priority or max_priority<0
-            if fentry = file.try_free
+            if (fentry = file.try_free)
               to_del<<fentry
             end
           end
@@ -497,7 +494,6 @@ module Kadeploy
       if emptycache
         debug("Cleaning cache #{@directory} ...")
         exclude = [ '.', '..' ]
-        files = []
         Dir.entries(@directory).sort.each do |file|
           rfile = File.join(@directory,file)
           if !exclude.include?(rfile)
@@ -511,7 +507,6 @@ module Kadeploy
       else
         debug("Loading cache #{@directory} ...")
         exclude = [ '.', '..' ]
-        files = []
         @lock.synchronize do
           Dir.entries(@directory).sort.each do |file|
             rfile = File.join(@directory,file)
@@ -519,7 +514,7 @@ module Kadeploy
               begin
                 fc = CacheFile.load(rfile)
                 @files[fc.file_in_cache] = fc
-              rescue Exception => ex
+              rescue StandardError => ex
                 debug("Unable to load #{rfile}: #{ex}")
                 debug(ex.backtrace.join("\n"))
               end
@@ -587,7 +582,6 @@ module Kadeploy
       begin
       ensure
         @files.values.sort_by{|v| [v.priority,v.atime]}.each do |file|
-          return true if need_to_free <= 0
           size = file.size
           fid = file.try_free
           if fid
diff --git a/lib/kadeploy3/server/config.rb b/lib/kadeploy3/server/config.rb
index a3f2a9b48626111486bf8f83b968954084c8e94f..96fe62c06af4a663edbc5bcfa04678800e1d28c5 100644
--- a/lib/kadeploy3/server/config.rb
+++ b/lib/kadeploy3/server/config.rb
@@ -248,7 +248,7 @@ module Configuration
           config = YAML.load_file(configfile)
         rescue Errno::ENOENT
           raise ArgumentError.new("File not found '#{configfile}'")
-        rescue Exception
+        rescue StandartdError
           raise ArgumentError.new("Invalid YAML file '#{configfile}'")
         end
 
@@ -269,7 +269,7 @@ module Configuration
             'almighty_users', String, 'root'
           ).split(",").collect! { |v| v.strip }
           @purge_deployment_timer = cp.value(
-            'purge_deployment_timer', Fixnum, 900
+            'purge_deployment_timer', Integer, 900
           )
         end
 
@@ -285,16 +285,16 @@ module Configuration
 
           cp.parse('ports') do
             static[:port] = cp.value(
-              'kadeploy_server',Fixnum,KADEPLOY_PORT
+              'kadeploy_server', Integer,KADEPLOY_PORT
             )
-            @ssh_port = cp.value('ssh',Fixnum,22)
+            @ssh_port = cp.value('ssh', Integer,22)
             @test_deploy_env_port = cp.value(
-              'test_deploy_env',Fixnum,KADEPLOY_PORT
+              'test_deploy_env', Integer, KADEPLOY_PORT
             )
           end
 
           @kadeploy_tcp_buffer_size = cp.value(
-            'tcp_buffer_size',Fixnum,8192
+            'tcp_buffer_size', Integer, 8192
           )
           static[:host] = cp.value('server_hostname',String,Socket.gethostname)
         end
@@ -323,7 +323,7 @@ module Configuration
               else
                 raise
               end
-            rescue Exception => e
+            rescue StandardError => e
               raise ArgumentError.new(Parser.errmsg(inf[:path],"Unable to load #{kind} private key: #{e.message}"))
             end
           end
@@ -332,7 +332,7 @@ module Configuration
           if cert and !cert.empty?
             begin
               static[:cert] = OpenSSL::X509::Certificate.new(File.read(cert))
-            rescue Exception => e
+            rescue StandardError => e
               raise ArgumentError.new(Parser.errmsg(info[:path],"Unable to load x509 cert file: #{e.message}"))
             end
           end
@@ -376,14 +376,14 @@ module Configuration
                 addr = IPAddr.new(Resolv.getaddress(hostname))
               rescue Resolv::ResolvError
                 raise ArgumentError.new(Parser.errmsg(path,"Cannot resolv hostname #{hostname}"))
-              rescue Exception => e
+              rescue StandardError => e
                 raise ArgumentError.new(Parser.errmsg(path,"Invalid hostname #{hostname.inspect} (#{e.message})"))
               end
             end
             addr
           end
 
-          cp.parse('global',false) do |info|
+          cp.parse('global',false) do
             static[:auth_headers_prefix] = cp.value('headers_prefix',String,'X-Kadeploy-')
           end
 
@@ -417,7 +417,7 @@ module Configuration
                 else
                   raise
                 end
-              rescue Exception => e
+              rescue StandardError => e
                 raise ArgumentError.new(Parser.errmsg(nfo[:path],"Unable to load #{kind} public key: #{e.message}"))
               end
             end
@@ -431,7 +431,7 @@ module Configuration
                 begin
                   cert = OpenSSL::X509::Certificate.new(File.read(cert))
                   public_key = cert.public_key
-                rescue Exception => e
+                rescue StandardError => e
                   raise ArgumentError.new(Parser.errmsg(nfo[:path],"Unable to load x509 cert file: #{e.message}"))
                 end
               end
@@ -456,7 +456,7 @@ module Configuration
               { :type => 'file', :readable => true, :prefix => Config.dir()})
             begin
               dbfile = WEBrick::HTTPAuth::Htpasswd.new(dbfile)
-            rescue Exception => e
+            rescue StandardError => e
               raise ArgumentError.new(Parser.errmsg(inf[:path],"Unable to load htpasswd file: #{e.message}"))
             end
             static[:auth][:http_basic] = HTTPBasicAuthentication.new(dbfile,
@@ -508,11 +508,11 @@ module Configuration
         end
 
         cp.parse('verbosity') do
-          @dbg_to_file_level = cp.value('logs',Fixnum,3,(0..4))
-          @verbose_level = cp.value('clients',Fixnum,3,(0..4))
+          @dbg_to_file_level = cp.value('logs', Integer,3,(0..4))
+          @verbose_level = cp.value('clients', Integer,3,(0..4))
         end
 
-        cp.parse('cache',true) do |inf_cache|
+        cp.parse('cache',true) do
           static[:caches] = {} unless static[:caches]
           static[:caches][:global] = {}
           static[:caches][:global][:directory] = cp.value('directory',String,'/tmp',
@@ -524,18 +524,18 @@ module Configuration
               :mode => 0700
             }
           )
-          static[:caches][:global][:size] = cp.value('size', Fixnum)*1024*1024
-          static[:caches][:global][:concurrency_level] = cp.value('concurrency_level', Fixnum, 10)
+          static[:caches][:global][:size] = cp.value('size', Integer)*1024*1024
+          static[:caches][:global][:concurrency_level] = cp.value('concurrency_level', Integer, 10)
         end
 
         cp.parse('windows') do
           cp.parse('reboot') do
-            static[:reboot_window] = cp.value('size',Fixnum,50)
-            static[:reboot_window_sleep_time] = cp.value('sleep_time',Fixnum,10)
+            static[:reboot_window] = cp.value('size', Integer,50)
+            static[:reboot_window_sleep_time] = cp.value('sleep_time', Integer,10)
           end
 
           cp.parse('check') do
-            static[:nodes_check_window] = cp.value('size',Fixnum,50)
+            static[:nodes_check_window] = cp.value('size', Integer,50)
           end
         end
 
@@ -550,9 +550,9 @@ module Configuration
             )
           end
           @max_preinstall_size =
-            cp.value('max_preinstall_size',Fixnum,20) *1024 * 1024
+            cp.value('max_preinstall_size', Integer,20) *1024 * 1024
           @max_postinstall_size =
-            cp.value('max_postinstall_size',Fixnum,20) * 1024 * 1024
+            cp.value('max_postinstall_size', Integer,20) * 1024 * 1024
         end
 
         cp.parse('pxe',true) do
@@ -590,7 +590,7 @@ module Configuration
           @end_of_power_hook = nil if @end_of_power_hook.empty?
         end
 
-        @autoclean_threshold = cp.value('autoclean_threshold',Fixnum,60*6).abs * 60 # 6h by default
+        @autoclean_threshold = cp.value('autoclean_threshold', Integer,60*6).abs * 60 # 6h by default
 
         cp.parse('external') do
            @cmd_ext[:default_connector] = cp.value('default_connector',String,'ssh -A -l root -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=publickey -o BatchMode=yes')
@@ -598,11 +598,11 @@ module Configuration
             @taktuk_connector = cp.value('connector',String,'DEFAULT_CONNECTOR')
             @taktuk_connector.gsub!('DEFAULT_CONNECTOR',@cmd_ext[:default_connector])
 
-            @taktuk_tree_arity = cp.value('tree_arity',Fixnum,0)
+            @taktuk_tree_arity = cp.value('tree_arity', Integer,0)
             @taktuk_auto_propagate = cp.value(
               'auto_propagate',[TrueClass,FalseClass],true
             )
-            @taktuk_outputs_size = cp.value('outputs_size',Fixnum,20000)
+            @taktuk_outputs_size = cp.value('outputs_size', Integer,20000)
           end
 
           cp.parse('bittorrent') do |info|
@@ -610,7 +610,7 @@ module Configuration
               @bt_tracker_ip = cp.value(
                 'tracker_ip',String,nil,/\A\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\Z/
               )
-              @bt_download_timeout = cp.value('download_timeout',Fixnum)
+              @bt_download_timeout = cp.value('download_timeout', Integer)
             end
           end
 
@@ -648,7 +648,7 @@ module Configuration
     end
 
     # Parse pxe part to build NetBoot object
-    def pxemethod (name,info,cp,static,chain = nil)
+    def pxemethod(name,info,cp,static,chain = nil)
       unless info[:empty]
         args = {}
         args[:kind] = cp.value('method',String,'PXElinux',
@@ -670,15 +670,15 @@ module Configuration
         end
 
         if name == :dhcp
-            cp.parse('userfiles',true) do |info_userfiles|
+            cp.parse('userfiles',true) do
               args[:custom_dir] = cp.value('directory',String,nil,
                 {:type => 'dir', :prefix => args[:repository_dir]}
               )
               static[:caches] = {} unless static[:caches]
               static[:caches][:netboot] = {}
               static[:caches][:netboot][:directory] = File.join(args[:repository_dir],args[:custom_dir])
-              static[:caches][:netboot][:size] = cp.value('max_size',Fixnum)*1024*1024
-              static[:caches][:netboot][:concurrency_level] = cp.value('concurrency_level', Fixnum, 10)
+              static[:caches][:netboot][:size] = cp.value('max_size', Integer)*1024*1024
+              static[:caches][:netboot][:concurrency_level] = cp.value('concurrency_level', Integer, 10)
             end
         else
           args[:custom_dir] = 'PXE_CUSTOM'
@@ -729,7 +729,7 @@ module Configuration
           config = YAML.load_file(configfile)
         rescue Errno::ENOENT
           raise ArgumentError.new("File not found '#{configfile}'")
-        rescue Exception
+        rescue StandardError
           raise ArgumentError.new("Invalid YAML file '#{configfile}'")
         end
 
@@ -896,7 +896,7 @@ module Configuration
           end
         end
         obj
-      rescue Exception => ex
+      rescue StandardError => ex
         raise ArgumentError.new("error in #{conf_path}, #{ex}")
       end
     end
@@ -910,7 +910,7 @@ module Configuration
           raise ArgumentError.new(
             "Cluster configuration file not found '#{configfile}'"
           )
-        rescue Exception
+        rescue StandardError
           raise ArgumentError.new("Invalid YAML file '#{configfile}'")
         end
 
@@ -958,10 +958,10 @@ module Configuration
 
           @swap_part = cp.value('disable_swap',[TrueClass,FalseClass],false)? 'none':nil
           cp.parse('partitions',true) do
-            @swap_part = cp.value('swap',Fixnum,nil).to_s unless @swap_part
-            @prod_part = cp.value('prod',Fixnum,-1).to_s
-            @deploy_part = cp.value('deploy',Fixnum).to_s
-            @tmp_part = cp.value('tmp',Fixnum,-1).to_s
+            @swap_part = cp.value('swap', Integer,nil).to_s unless @swap_part
+            @prod_part = cp.value('prod', Integer,-1).to_s
+            @deploy_part = cp.value('deploy', Integer).to_s
+            @tmp_part = cp.value('tmp', Integer,-1).to_s
           end
           @partitioning_script = cp.value('script',String,nil,
             { :type => 'file', :readable => true, :prefix => Config.dir() })
@@ -1002,7 +1002,7 @@ module Configuration
           [:power_off,:power_on,:reboot].each do |symb|
             @cmd_ext[symb]=handle_cmd_priority(cp.value(symb.to_s,Array,[]),remoteops_info[:path],cp,cluster)
             0.upto(level_symbols.length-1)  do |idx|
-              self.instance_variable_set("@cmd_#{symb.to_s}_#{level_symbols[idx].to_s}".to_sym,@cmd_ext[symb][idx])
+              self.instance_variable_set("@cmd_#{symb}_#{level_symbols[idx]}".to_sym,@cmd_ext[symb][idx])
             end
           end
 
@@ -1068,22 +1068,22 @@ module Configuration
                 case op[:action]
                 when 'exec'
                   op[:command] = cp.value('command',String)
-                  op[:timeout] = cp.value('timeout',Fixnum,0)
-                  op[:retries] = cp.value('retries',Fixnum,0)
+                  op[:timeout] = cp.value('timeout', Integer,0)
+                  op[:retries] = cp.value('retries', Integer,0)
                   op[:scattering] = cp.value('scattering',String,:tree)
                 when 'send'
                   op[:file] = cp.value('file',String,nil,
                     { :type => 'file', :readable => true, :prefix => Config.dir() })
                   op[:destination] = cp.value('destination',String)
-                  op[:timeout] = cp.value('timeout',Fixnum,0)
-                  op[:retries] = cp.value('retries',Fixnum,0)
+                  op[:timeout] = cp.value('timeout', Integer,0)
+                  op[:retries] = cp.value('retries', Integer,0)
                   op[:scattering] = cp.value('scattering',String,:tree)
                 when 'run'
                   op[:file] = cp.value('file',String,nil,
                     { :type => 'file', :readable => true, :prefix => Config.dir() })
                   op[:params] = cp.value('params',String,'')
-                  op[:timeout] = cp.value('timeout',Fixnum,0)
-                  op[:retries] = cp.value('retries',Fixnum,0)
+                  op[:timeout] = cp.value('timeout', Integer,0)
+                  op[:retries] = cp.value('retries', Integer,0)
                   op[:scattering] = cp.value('scattering',String,:tree)
                 end
                 op[:action] = op[:action].to_sym
@@ -1124,14 +1124,14 @@ module Configuration
                       custom_post = nil if custom_post.empty?
 
                       microconf[microname.to_sym] = {
-                        :timeout => cp.value('timeout',Fixnum,0),
+                        :timeout => cp.value('timeout', Integer,0),
                         :raisable => cp.value(
                           'raisable',[TrueClass,FalseClass],true
                         ),
                         :breakpoint => cp.value(
                           'breakpoint',[TrueClass,FalseClass],false
                         ),
-                        :retries => cp.value('retries',Fixnum,0),
+                        :retries => cp.value('retries', Integer,0),
                         :custom_sub => custom_sub,
                         :custom_pre => custom_pre,
                         :custom_post => custom_post,
@@ -1141,8 +1141,8 @@ module Configuration
 
                   macroinsts << [
                     macroname + cp.value('type',String,nil,insts),
-                    cp.value('retries',Fixnum,0),
-                    cp.value('timeout',Fixnum,0),
+                    cp.value('retries', Integer,0),
+                    cp.value('timeout', Integer,0),
                     cp.value('raisable',[TrueClass,FalseClass],true),
                     cp.value('breakpoint',[TrueClass,FalseClass],false),
                     microconf,
@@ -1171,7 +1171,6 @@ module Configuration
             )
           end
 
-          n=1
           tmptime = eval(code)
           @workflow_steps[0].to_a.each do |macroinst|
             if [
@@ -1211,7 +1210,6 @@ module Configuration
             )
           end
 
-          n=1
           tmptime = eval(code)
           @workflow_steps[0].to_a.each do |macroinst|
             if macroinst[0] == 'SetDeploymentEnvKexec' and tmptime > macroinst[2]
@@ -1277,7 +1275,7 @@ module Configuration
     # * cluster: cluster concerned
     # Output
     # * return true if the group has been added correctly, false otherwise
-    def add_group_of_nodes(command, file, cluster)
+    def add_group_of_nodes(command, file, _cluster)
       if File.readable?(file) then
         @group_of_nodes[command] = Array.new
         IO.readlines(file).each do |line|
@@ -1307,7 +1305,7 @@ module Configuration
         config = YAML.load_file(configfile)
       rescue Errno::ENOENT
         return true
-      rescue Exception
+      rescue StandardError
         $stderr.puts "Invalid YAML file '#{configfile}'"
         return false
       end
@@ -1365,20 +1363,20 @@ module Configuration
     case ret[:action]
     when 'exec'
       ret[:command] = cp.value('command',String)
-      ret[:timeout] = cp.value('timeout',Fixnum,0)
-      ret[:retries] = cp.value('retries',Fixnum,0)
+      ret[:timeout] = cp.value('timeout', Integer,0)
+      ret[:retries] = cp.value('retries', Integer,0)
       ret[:scattering] = cp.value('scattering',String,:tree)
     when 'send'
       ret[:file] = cp.value('file',String,nil,fileopts)
       ret[:destination] = cp.value('destination',String)
-      ret[:timeout] = cp.value('timeout',Fixnum,0)
-      ret[:retries] = cp.value('retries',Fixnum,0)
+      ret[:timeout] = cp.value('timeout', Integer,0)
+      ret[:retries] = cp.value('retries', Integer,0)
       ret[:scattering] = cp.value('scattering',String,:tree)
     when 'run'
       ret[:file] = cp.value('file',String,nil,fileopts)
       ret[:params] = cp.value('params',String,'')
-      ret[:timeout] = cp.value('timeout',Fixnum,0)
-      ret[:retries] = cp.value('retries',Fixnum,0)
+      ret[:timeout] = cp.value('timeout', Integer,0)
+      ret[:retries] = cp.value('retries', Integer,0)
       ret[:scattering] = cp.value('scattering',String,:tree)
     end
     ret[:action] = ret[:action].to_sym
@@ -1421,17 +1419,17 @@ module Configuration
     ret
   end
 
-  def self.parse_custom_macrostep(cp,macrobase,opts={})
+  def self.parse_custom_macrostep(cp,macrobase,_opts={})
     ret = []
 
-    cp.parse(macrobase,true,Array) do |info|
+    cp.parse(macrobase,true,Array) do
       name = cp.value('name',String)
       raise ArgumentError.new("Unknown macrostep name '#{name}'") \
         unless check_macrostep_instance(name,:deploy)
       ret << [
         name,
-        cp.value('retries',Fixnum,0),
-        cp.value('timeout',Fixnum,0),
+        cp.value('retries', Integer,0),
+        cp.value('timeout', Integer,0),
       ]
     end
 
diff --git a/lib/kadeploy3/server/db.rb b/lib/kadeploy3/server/db.rb
index 20ea4215b5a7ee50856c19d1bcf8ed19f84edece..00e84050b0b7375d21cbdef2ccf68809d3a68b4c 100644
--- a/lib/kadeploy3/server/db.rb
+++ b/lib/kadeploy3/server/db.rb
@@ -1,4 +1,4 @@
-require 'mysql'
+require 'mysql2'
 require 'timeout'
 
 module Kadeploy
@@ -115,7 +115,6 @@ module Database
     def to_hash
       unless @cache_hash
         @cache_hash = []
-
         @content.each do |row|
           @cache_hash << Hash[*(@fields.zip(row).flatten)]
         end
@@ -150,16 +149,17 @@ module Database
       ret = true
       begin
         Timeout.timeout(60) do
-          @dbh = Mysql.init
-          @dbh.options(Mysql::SET_CHARSET_NAME,'utf8')
-          @dbh.real_connect(host, user, passwd, base)
-          @dbh.reconnect = true
+          @dbh = Mysql2::Client.new(
+            host: host,
+            username: user,
+            password: passwd,
+            database: base)
         end
       rescue Timeout::Error
         $stderr.puts "[#{Time.now}] MySQL error: Timeout when connecting to DB (#{user}@#{host}/#{base})"
         $stderr.flush
         ret = false
-      rescue Mysql::Error => e
+      rescue Mysql2::Error => e
         $stderr.puts "[#{Time.now}] MySQL error (code): #{e.errno}"
         $stderr.puts "[#{Time.now}] MySQL error (message): #{e.error}"
         $stderr.puts "[#{Time.now}] Kadeploy server cannot connect to DB #{user}@#{host}/#{base}"
@@ -180,21 +180,23 @@ module Database
       res = nil
       begin
         st = @dbh.prepare(query)
-        st.execute(*args)
-
+        res = st.execute(*args)
         content = nil
-        fields = nil
-        if st.result_metadata
+        fields = st.fields
+        unless res.nil?
           content = []
-          fields = st.result_metadata.fetch_fields.collect{ |f| f.name }
-          st.each do |row|
-            content << row
+          res.each do |r|
+            rescontent = []
+            r.each do |_,row|
+              rescontent << row
+            end
+            content << rescontent
           end
         end
-        res = DbResult.new(fields,content,st.affected_rows)
+        result = DbResult.new(fields,content,st.affected_rows)
 
         st.close
-      rescue Mysql::Error => e
+      rescue Mysql2::Error => e
         $stderr.puts "MySQL query: #{query.gsub(/\s+/," ").strip}" if query
         $stderr.puts "MySQL args: #{args.inspect}" if args
         $stderr.puts "MySQL error (code): #{e.errno}"
@@ -203,7 +205,7 @@ module Database
         raise KadeployError.new(APIError::DATABASE_ERROR,nil,
           "MySQL error ##{e.errno}: #{e.error.gsub(/\s+/," ").strip}")
       end
-      return res
+      return result
     end
   end
 end
diff --git a/lib/kadeploy3/server/debug.rb b/lib/kadeploy3/server/debug.rb
index 18741a12238a0efa8a2700d31cee85db611c4097..22226f7375652f57f6810f5fbfbe704c4acf96ad 100644
--- a/lib/kadeploy3/server/debug.rb
+++ b/lib/kadeploy3/server/debug.rb
@@ -1,5 +1,3 @@
-require 'thread'
-
 module Kadeploy
 
 module Debug
@@ -184,7 +182,7 @@ module Debug
     def empty?()
       ret = true
       @lock.synchronize do
-        @debug.each_pair do |node,v|
+        @debug.each_value do |v|
           if v and !v.empty?
             ret = false
             break
@@ -407,7 +405,7 @@ end
 
 
 module Printer
-  def debug(level,msg,nodesetid=nil,opts={})
+  def debug(level,msg,nodesetid=nil,_opts={})
     return unless output()
     output().push(level,msg,nodesetid)
   end
diff --git a/lib/kadeploy3/server/dump.rb b/lib/kadeploy3/server/dump.rb
index c960e9b60d6e730e434d33ad7b43b88fc11f7067..c5496719daef4ed1577a303fc381193414c690b0 100644
--- a/lib/kadeploy3/server/dump.rb
+++ b/lib/kadeploy3/server/dump.rb
@@ -1,5 +1,4 @@
 require 'pp'
-require 'thread'
 
 # Hacks that allow better dump of internal structures
 class Mutex
@@ -18,10 +17,10 @@ module Kadeploy
     objects[Object] = total
 
     file.puts("--- Objects by number ---")
-    PP.pp(Hash[objects.select{|k,v| v > 4}.sort_by{|k,v| -v}],file,width)
+    PP.pp(Hash[objects.select{|_,v| v > 4}.sort_by{|_,v| -v}],file,width)
 
     file.puts("\n--- Objects by name ---")
-    PP.pp(Hash[objects.sort_by{|k,v| k.name || ''}],file,width)
+    PP.pp(Hash[objects.sort_by{|k,_| k.name || ''}],file,width)
     objects = nil
 
     if ObjectSpace.respond_to?(:count_objects)
diff --git a/lib/kadeploy3/server/grabfile.rb b/lib/kadeploy3/server/grabfile.rb
index 9f8705f0ec913472a0a4918da97d4046d86595db..58ca3043b64310c0398e397ee08c50516d06c479 100644
--- a/lib/kadeploy3/server/grabfile.rb
+++ b/lib/kadeploy3/server/grabfile.rb
@@ -1,4 +1,3 @@
-require 'thread'
 require 'uri'
 require 'fileutils'
 require 'tempfile'
@@ -54,7 +53,7 @@ class GrabFile
     cf = @cache.cache(
             origin_uri,version,user,priority,tag,fetcher.size,
             wid,opts[:file],fchecksum,fmtime
-            ) do |source,destination,size,md5|
+            ) do |source,destination,_size,md5|
 
       if md5 && fetcher.checksum && md5 != fetcher.checksum # fetcher provides the checksum
         error(APIError::INVALID_FILE,"Checksum of the file '#{source}' does not match "\
@@ -137,14 +136,14 @@ class GrabFile
     #Grab tarball, Preinstall and Postinstall archive if only inside deploy kind
     if kind == :deploy
       # Env tarball
-      if env and tmp = env.tarball
+      if env and (tmp = env.tarball)
         grab(gfm,context,tmp['file'],envprio,'tarball',
           :md5=>tmp['md5'], :env => env
         )
       end
 
       # Preinstall archive
-      if env and tmp = env.preinstall
+      if env and (tmp = env.preinstall)
         grab(gfm,context,tmp['file'],envprio,'preinstall',
           :md5 => tmp['md5'], :env => env,
           :maxsize => context[:common].max_preinstall_size
@@ -164,8 +163,8 @@ class GrabFile
 
     # Custom files
     if cexec.custom_operations
-      cexec.custom_operations[:operations].each_pair do |macro,micros|
-        micros.each_pair do |micro,entries|
+      cexec.custom_operations[:operations].each_pair do |_macro,micros|
+        micros.each_value do |entries|
           entries.each do |entry|
             if entry[:action] == :send
               entry[:filename] = File.basename(entry[:file].dup)
diff --git a/lib/kadeploy3/server/ident.rb b/lib/kadeploy3/server/ident.rb
index 57a13fa306a8c971db5d04599b533c9bb308f9d1..8f5edf794519c36a938fe592432dc4b5895e67fd 100644
--- a/lib/kadeploy3/server/ident.rb
+++ b/lib/kadeploy3/server/ident.rb
@@ -2,7 +2,7 @@ require 'socket'
 
 module Kadeploy
 
-class IdentError < Exception
+class IdentError < RuntimeError
 end
 
 class Ident
@@ -21,7 +21,7 @@ class Ident
       raise IdentError, 'Connection to ident service timed out'
     rescue Errno::ECONNREFUSED
       raise IdentError, 'Connection to ident service was refused'
-    rescue Exception => e
+    rescue StandardError => e
       raise IdentError, "Connection to ident service failed (#{e.class.name}: #{e.message})"
     end
 
diff --git a/lib/kadeploy3/server/kaconsole.rb b/lib/kadeploy3/server/kaconsole.rb
index c9b05fd5e445be2f220bdddefe6a88676c50141b..e7794e706fdba35760bb8c8e061c3743c2ac472a 100644
--- a/lib/kadeploy3/server/kaconsole.rb
+++ b/lib/kadeploy3/server/kaconsole.rb
@@ -60,7 +60,9 @@ module Kaconsole
       kaerror(APIError::INVALID_RIGHTS) \
         unless context.rights.granted?(context.user,context.node,'')
     when :get
+      # do nithing
     when :delete
+      # do nothing
     else
       raise
     end
@@ -74,9 +76,10 @@ module Kaconsole
     context
   end
 
-  def console_rights?(cexec,operation,names,wid=nil,*args)
+  def console_rights?(cexec,operation,names,wid=nil,*)
     case operation
     when :create
+       # do nothing
     when :get
       if wid and names
         workflow_get(:console,wid) do |info|
@@ -175,7 +178,7 @@ module Kaconsole
     end
   end
 
-  def console_delete!(cexec,info)
+  def console_delete!(_cexec,info)
     console_kill(info)
     console_free(info)
 
@@ -203,13 +206,13 @@ module Kaconsole
     end
   end
 
-  def console_get_error(cexec,wid)
+  def console_get_error(_cexec,wid)
     workflow_get(:console,wid) do |info|
       break if info[:thread].alive?
       begin
         info[:thread].join
         nil
-      rescue Exception => e
+      rescue StandardError => e
         console_free(info)
         raise e
       end
@@ -269,6 +272,7 @@ module Kaconsole
                 begin
                   Execute.kill_recursive(pid)
                 rescue Errno::ESRCH
+                  # do nothing
                 end
                 PTY.check(pid)
                 Thread.current[:pid] = nil
@@ -303,6 +307,7 @@ module Kaconsole
         begin
           client[:sock].syswrite("\n[Kaconsole] client killed\n")
         rescue
+          # do nothing
         end
       end
 
@@ -313,6 +318,7 @@ module Kaconsole
           begin
             Execute.kill_recursive(client[:pid])
           rescue Errno::ESRCH
+            # do nothing
           end
           sleep 2 # wait for the thread to clean itself
           if client[:pid]
diff --git a/lib/kadeploy3/server/kadeploy.rb b/lib/kadeploy3/server/kadeploy.rb
index b12d3e912a27a34ce6fbc5d745639f3d52f84c69..8867616d084d0449b75cf07a5932862db370dbae 100644
--- a/lib/kadeploy3/server/kadeploy.rb
+++ b/lib/kadeploy3/server/kadeploy.rb
@@ -60,7 +60,7 @@ module Kadeploy
         end
 
         # Check the boot partition
-        context.boot_part = p.parse('boot_partition',Fixnum)
+        context.boot_part = p.parse('boot_partition',Integer)
 
         # Check disable options
         context.disable_bootloader_install = p.parse('disable_bootloader_install',nil,:toggle=>true)
diff --git a/lib/kadeploy3/server/kaenvs.rb b/lib/kadeploy3/server/kaenvs.rb
index fb3fa9a04d015788b719c34a6a854fe4c5c85283..7738f10b77912d63171cbedc0bcdb4f02c05851f 100644
--- a/lib/kadeploy3/server/kaenvs.rb
+++ b/lib/kadeploy3/server/kaenvs.rb
@@ -100,7 +100,7 @@ module Kaenvs
     context
   end
 
-  def envs_rights?(cexec,operation,names,user=nil,name=nil,version=nil)
+  def envs_rights?(cexec,operation,_names,user=nil,_name=nil,_version=nil)
     # check if env is private and cexec != user on GET
     # check if cexec == user on DELETE
     case operation
@@ -109,6 +109,7 @@ module Kaenvs
         return [false,'Only administrators can use the "public" tag']
       end
     when :get
+      # do nothing
     when :modify
       unless cexec.almighty_users.include?(cexec.user)
         return [false,'Only administrators are allowed to modify other user\'s environment'] if cexec.user != user
@@ -143,7 +144,6 @@ module Kaenvs
   end
 
   def envs_get(cexec)
-    envs = nil
     envs = Environment.get_from_db_context(
           cexec.database,
           cexec.env_name,
diff --git a/lib/kadeploy3/server/kanodes.rb b/lib/kadeploy3/server/kanodes.rb
index 18089d449b1358c26e952188a68431474f1f1f3b..a87e9d2599fa6efc92600261d521bd267a916782 100644
--- a/lib/kadeploy3/server/kanodes.rb
+++ b/lib/kadeploy3/server/kanodes.rb
@@ -7,9 +7,8 @@ module Kanodes
     ret
   end
 
-  def nodes_prepare(params,operation,context)
+  def nodes_prepare(params,_operation,context)
     context = nodes_init_exec_context(context)
-    operation ||= :get
 
     parse_params(params) do |p|
       # Check nodelist
diff --git a/lib/kadeploy3/server/kareboot.rb b/lib/kadeploy3/server/kareboot.rb
index 961d62a8f2269b46523a29f493b778755439ec7f..9fe18cc94efaca28484da5753b51633f356a728e 100644
--- a/lib/kadeploy3/server/kareboot.rb
+++ b/lib/kadeploy3/server/kareboot.rb
@@ -43,6 +43,7 @@ module Kareboot
         end
       end
     when :get
+      # do nothing
     end
 
     context
diff --git a/lib/kadeploy3/server/karights.rb b/lib/kadeploy3/server/karights.rb
index b3d7690e045a0a250bb1168582e434edb16b5171..fe75a4b0fd46f6b5d1adef34e022da5e0bdf0649 100644
--- a/lib/kadeploy3/server/karights.rb
+++ b/lib/kadeploy3/server/karights.rb
@@ -26,7 +26,9 @@ module Karights
         context.overwrite = p.parse('overwrite',nil,:toggle=>true)
 
       when :get
+        # do nothing
       when :delete
+        # do nothing
       else
         raise
       end
@@ -35,7 +37,7 @@ module Karights
     context
   end
 
-  def rights_rights?(cexec,operation,names,*args)
+  def rights_rights?(cexec,_operation,_names,*)
     # check almighty
     unless cexec.almighty_users.include?(cexec.user)
       return [ false, 'Only administrators are allowed to manage rights' ]
@@ -106,11 +108,10 @@ module Karights
         raise
       end
     end
-    res = nil
     ret
   end
 
-  def rights_modify(cexec,user,nodes=nil)
+  def rights_modify(_cexec,_user,_nodes=nil)
     error_invalid!
   end
 
@@ -122,7 +123,7 @@ module Karights
 
     existing = nil
     # nothing to delete
-    kaerror(APIError::NOTHING_MODIFIED) unless existing = cexec.rights.get(user,nodes)
+    kaerror(APIError::NOTHING_MODIFIED) unless (existing = cexec.rights.get(user,nodes))
     existing = existing[user]
 
     partitions = cexec.partitions
diff --git a/lib/kadeploy3/server/kastats.rb b/lib/kadeploy3/server/kastats.rb
index 438706443f5c6a95240c33323970b3305df715f7..63c2bddd5ae8962d40db971839f1802f2a435239 100644
--- a/lib/kadeploy3/server/kastats.rb
+++ b/lib/kadeploy3/server/kastats.rb
@@ -10,9 +10,8 @@ module Kastats
     ret
   end
 
-  def stats_prepare(params,operation,context)
+  def stats_prepare(params,_operation,context)
     context = stats_init_exec_context(context)
-    operation ||= :get
 
     parse_params(params) do |p|
       # Check nodelist
@@ -21,7 +20,6 @@ module Kastats
       if nodes
         tmp = nodes.make_array_of_hostname
         nodes.free
-        nodes = nil
         context.filters[:nodes] = tmp
       end
 
diff --git a/lib/kadeploy3/server/kaworkflow.rb b/lib/kadeploy3/server/kaworkflow.rb
index 91462554278b8dc585275b9b47430b7d481294b2..a74450cd2db2c173b938309203c02503975c7417 100644
--- a/lib/kadeploy3/server/kaworkflow.rb
+++ b/lib/kadeploy3/server/kaworkflow.rb
@@ -72,7 +72,7 @@ module Kaworkflow
     hook = nil
     nodes = Nodes::NodeSet.new(0)
     cexec.nodes.duplicate(nodes)
-    hook = cexec.config.common.send(:"end_of_#{kind.to_s}_hook").dup if cexec.hook
+    hook = cexec.config.common.send(:"end_of_#{kind}_hook").dup if cexec.hook
     {
       :wid => uuid(API.wid_prefix(kind)),
       :user => cexec.user,
@@ -151,7 +151,7 @@ module Kaworkflow
         context.force = p.parse('force',nil,:toggle=>true)
 
         # Check verbose level
-        context.verbose_level = p.parse('verbose_level',Fixnum,:range=>(1..5))
+        context.verbose_level = p.parse('verbose_level',Integer,:range=>(1..5))
 
         # Check debug
         context.debug = p.parse('debug',nil,:toggle=>true)
@@ -247,7 +247,7 @@ module Kaworkflow
           p.parse('timeout_reboot_classical',String) do |timeout|
             begin
               eval("n=1; #{timeout}")
-            rescue Exception => e
+            rescue StandardError => e
               kaerror(APIError::INVALID_OPTION,
                 "the timeout is not a valid expression (#{e.message})")
             end
@@ -267,9 +267,10 @@ module Kaworkflow
     context
   end
 
-  def work_rights?(kind,cexec,operation,names,wid=nil,*args)
+  def work_rights?(kind,cexec,operation,names,wid=nil,*)
     case operation
     when :create,:modify
+      nil
     when :get
       if wid and names
         workflow_get(kind,wid) do |info|
@@ -367,7 +368,7 @@ module Kaworkflow
               info[:user],
               context[:wid],
               Time.now,
-              (info[:environment] ? "#{info[:environment].name}:#{info[:environment].version.to_s}" : nil),
+              (info[:environment] ? "#{info[:environment].name}:#{info[:environment].version}" : nil),
               (info[:environment] and info[:environment].id < 0),
               info[:loggerfile],
               (info[:config].common.log_to_db ? context[:database] : nil)
@@ -450,7 +451,7 @@ module Kaworkflow
           run_wmethod(kind,:free,info)
         end
 
-      rescue Exception => e
+      rescue StandardError => e
         info[:lock].synchronize do
           info[:error] = true
           run_wmethod(kind,:kill,info)
@@ -466,7 +467,7 @@ module Kaworkflow
   end
 
   # TODO: implement it
-  def work_modify(*args)
+  def work_modify(*)
     error_invalid!
   end
 
@@ -576,7 +577,7 @@ module Kaworkflow
     end
   end
 
-  def work_delete!(kind,cexec,info)
+  def work_delete!(kind,_cexec,info)
     run_wmethod(kind,:kill,info)
     run_wmethod(kind,:free,info)
     info[:output].free if info[:output]
@@ -593,7 +594,7 @@ module Kaworkflow
   end
 
 
-  def work_kill(kind,info)
+  def work_kill(_kind,info)
     unless info[:freed]
       info[:thread].kill if info[:thread] and info[:thread].alive? and info[:thread] != Thread.current
       info[:threads].each_value{|thread| thread.kill} if info[:threads]
@@ -602,6 +603,7 @@ module Kaworkflow
           begin
             workflow.kill
           rescue KadeployError
+            #do nothing
           end
         end
       end
@@ -622,7 +624,7 @@ module Kaworkflow
     end
   end
 
-  def work_free(kind,info)
+  def work_free(_kind,info)
     unless info[:freed]
       info[:freed] = true
       info[:nodes].free if info[:nodes]
@@ -661,7 +663,7 @@ module Kaworkflow
     end
   end
 
-  def work_get_logs(kind,cexec,wid,cluster=nil)
+  def work_get_logs(kind,_cexec,wid,cluster=nil)
     workflow_get(kind,wid) do |info|
       # check if already done
       break if info[:error]
@@ -682,7 +684,7 @@ module Kaworkflow
     end
   end
 
-  def work_get_debugs(kind,cexec,wid,node=nil)
+  def work_get_debugs(kind,_cexec,wid,node=nil)
     workflow_get(kind,wid) do |info|
       break if info[:error]
       error_not_found! if (node and !info[:nodelist].include?(node)) or !info[:debugger]
@@ -691,14 +693,14 @@ module Kaworkflow
     end
   end
 
-  def work_get_state(kind,cexec,wid)
+  def work_get_state(kind,_cexec,wid)
     workflow_get(kind,wid) do |info|
       break if info[:error]
       info[:state].states
     end
   end
 
-  def work_get_status(kind,cexec,wid)
+  def work_get_status(kind,_cexec,wid)
     workflow_get(kind,wid) do |info|
       break if info[:error]
       ret = {}
@@ -711,21 +713,21 @@ module Kaworkflow
     end
   end
 
-  def work_get_error(kind,cexec,wid)
+  def work_get_error(kind,_cexec,wid)
     workflow_get(kind,wid) do |info|
       break if !info[:error]
       begin
         info[:thread].join
         info[:threads].each_value{|thr| thr.join unless thr.alive?} if info[:threads]
         nil
-      rescue Exception => e
+      rescue StandardError => e
         run_wmethod(kind,:free,info)
         raise e
       end
     end
   end
 
-  def work_end_hook(kind,info)
+  def work_end_hook(_kind,info)
     if info[:hook]
       cmd = info[:hook].gsub('WORKFLOW_ID',info[:wid])
       run = Execute[cmd]
@@ -741,7 +743,7 @@ module Kaworkflow
       rescue Timeout::Error
         STDERR.puts("[#{Time.now}] The hook command has expired (#{cmd})")
         STDERR.flush
-      rescue Exception => ex
+      rescue StandardError => ex
         STDERR.puts "[#{Time.now}] #{ex}"
         STDERR.puts ex.backtrace
         STDERR.flush
diff --git a/lib/kadeploy3/server/macrostep.rb b/lib/kadeploy3/server/macrostep.rb
index f6fd0ea58341415e771fd7f1ffb320eb3996e3de..a3be51e1b80bf4b4b1a59cb085fdae53411b9041 100644
--- a/lib/kadeploy3/server/macrostep.rb
+++ b/lib/kadeploy3/server/macrostep.rb
@@ -45,7 +45,7 @@ module Macrostep
 
       addcustoms = Proc.new do |op, operations, subst, pre, post|
         operations.each do |operation|
-          opname = "#{op.to_s}_#{operation[:name]}".to_sym
+          opname = "#{op}_#{operation[:name]}".to_sym
           timeout = 0
           timeout = operation.delete(:timeout) if operation[:timeout]
           retries = 0
@@ -126,7 +126,7 @@ module Macrostep
       delete = lambda do |arr,index|
         if arr[index][0] == taskname
           to_delete << [arr,index]
-          debug(5, " * Bypassing the step #{macroname}-#{taskname.to_s}",nsid)
+          debug(5, " * Bypassing the step #{macroname}-#{taskname}",nsid)
         end
       end
 
@@ -170,7 +170,7 @@ module Macrostep
     end
 
     def break!(task,nodeset)
-      debug(2,"*** Breakpoint on #{task.name.to_s} reached for #{nodeset.to_s_fold}",task.nsid)
+      debug(2,"*** Breakpoint on #{task.name} reached for #{nodeset.to_s_fold}",task.nsid)
       debug(1,"Step #{macroname} breakpointed",task.nsid)
       log("step#{idx+1}_duration",(Time.now.to_i-@start_time),nodeset)
     end
@@ -184,7 +184,7 @@ module Macrostep
     end
 
     def display_fail_message(task,nodeset)
-      debug(2,"!!! The nodes #{nodeset.to_s_fold} failed on step #{task.name.to_s}",task.nsid)
+      debug(2,"!!! The nodes #{nodeset.to_s_fold} failed on step #{task.name}",task.nsid)
       debug(1,
         "Step #{macroname} failed for #{nodeset.to_s_fold} "\
         "after #{Time.now.to_i - @start_time}s",
@@ -192,7 +192,7 @@ module Macrostep
       )
     end
 
-    def fail!(task,nodeset)
+    def fail!(_task,nodeset)
       log("step#{idx+1}_duration",(Time.now.to_i-@start_time),nodeset)
     end
 
diff --git a/lib/kadeploy3/server/microsteps.rb b/lib/kadeploy3/server/microsteps.rb
index 6cd42510731435320a3b28ac8cfcc267a249b076..b5fee568b06d731d5007cea00efecf254d2cbaab 100644
--- a/lib/kadeploy3/server/microsteps.rb
+++ b/lib/kadeploy3/server/microsteps.rb
@@ -60,10 +60,10 @@ class Microstep < Automata::QueueTask
           debug(3,"#{@name.to_s.sub(/^custom_post_/,'')}",false)
           ret = ret && send(:custom,*@params)
         else
-          debug(3,"#{@name.to_s}",false)
-          ret = ret && send("ms_#{@name.to_s}".to_sym,*@params)
+          debug(3,"#{@name}",false)
+          ret = ret && send("ms_#{@name}".to_sym,*@params)
         end
-        debug(4, " ~ Time in #{@name.to_s}: #{Time.now.to_i - @timestart}s",false)
+        debug(4, " ~ Time in #{@name}: #{Time.now.to_i - @timestart}s",false)
       end
     rescue KadeployError => ke
       ke.context = context() unless ke.context
@@ -123,6 +123,7 @@ class Microstep < Automata::QueueTask
           begin
             @runthread.join
           rescue SignalException
+            # do nothing
           end
         end
       end
@@ -186,7 +187,7 @@ class Microstep < Automata::QueueTask
   end
 
   def failed_microstep(msg)
-    debug(0, "Error[#{@name.to_s}] #{msg}")
+    debug(0, "Error[#{@name}] #{msg}")
     @nodes.set_error_msg(msg)
     @nodes.linked_copy(@nodes_ko)
     @nodes_ko.set.each do |n|
@@ -240,9 +241,8 @@ class Microstep < Automata::QueueTask
     end
   end
 
-  def command(cmd,opts={},&block)
+  def command(cmd,opts={},_block)
     raise '@current_operation should not be set' if @current_operation
-    res = nil
     @lock.synchronize{ @current_operation = Execute[cmd] }
     @current_operation.run(opts)
     res = @current_operation.wait(opts)
@@ -622,10 +622,7 @@ class Microstep < Automata::QueueTask
     end
 
     map.clear
-    map = nil
     node_set.free(false)
-    node_set = nil
-    initial_node_set = nil
   end
 
   # Test if the given symlink is an absolute link
@@ -918,13 +915,13 @@ class Microstep < Automata::QueueTask
           fsmap = ''
           if context[:execution].environment.multipart
             context[:execution].environment.options['partitions'].each do |part|
-              fsmap += "id=#{part['id'].to_s},dest=#{part['device']} "
+              fsmap += "id=#{part['id']},dest=#{part['device']} "
             end
           else
             if partition
               if context[:execution].environment.options['partitions']
                 part = context[:execution].environment.options['partitions'][0]
-                fsmap += "id=#{part['id'].to_s},dest=#{partition} "
+                fsmap += "id=#{part['id']},dest=#{partition} "
               else
                 fsmap += "id=0,dest=#{partition}"
               end
@@ -1137,7 +1134,6 @@ class Microstep < Automata::QueueTask
         oknodes = []
         tmp = node_set.make_sorted_array_of_nodes.collect{|n| get_nodeid(n)}
         konodes = Hash[tmp.zip [err]*tmp.size]
-        tmp = nil
       end
 
       node_set.set.each do |node|
@@ -1214,6 +1210,7 @@ class Microstep < Automata::QueueTask
       begin
         Execute.kill_recursive(seed_pid)
       rescue Errno::ESRCH
+        # do nothing
       end
       return false
     end
@@ -1223,6 +1220,7 @@ class Microstep < Automata::QueueTask
       debug(3, "Shutdown the tracker for #{torrent}")
       Execute.kill_recursive(tracker_pid)
     rescue Errno::ESRCH
+      # do nothing
     end
     command("rm -f #{btdownload_state}")
 
@@ -1284,6 +1282,8 @@ class Microstep < Automata::QueueTask
     return path
   end
 
+  public
+
   def self.load_deploy_context(vals={:env=>{},:parts=>{}})
     ret = {
       'KADEPLOY_CLUSTER' => vals[:cluster],
@@ -1361,7 +1361,7 @@ class Microstep < Automata::QueueTask
   def set_env
     ret = ''
     deploy_context().each_pair do |key,val|
-      ret += "#{key.to_s}=\"#{val}\" "
+      ret += "#{key}=\"#{val}\" "
     end
     ret
   end
@@ -1423,8 +1423,6 @@ class Microstep < Automata::QueueTask
     )
   end
 
-  public
-
   def ms_dummy()
     sleep((200+rand(800)) / 1000.0)
     true
diff --git a/lib/kadeploy3/server/netboot.rb b/lib/kadeploy3/server/netboot.rb
index a79045cfdffa53802586824c7ef057e8723a5c3f..11a73f9b37ff443d0345ccb590f2ef6fbb3b0a7f 100644
--- a/lib/kadeploy3/server/netboot.rb
+++ b/lib/kadeploy3/server/netboot.rb
@@ -25,13 +25,13 @@ module NetBoot
     )
   end
 
-  class NetBoot::Exception < Exception
+  class NetBoot::Exception < RuntimeError
   end
 
   class PXE
     class Export
       def initialize(kind, server)
-        raise NetBoot::Exception.new("#{self.class.name} do not support '#{kind.to_s}' (supported values: #{kinds().join(', ')})") unless kinds().include?(kind)
+        raise NetBoot::Exception.new("#{self.class.name} do not support '#{kind}' (supported values: #{kinds().join(', ')})") unless kinds().include?(kind)
         @kind = kind
         @server = server
       end
@@ -40,7 +40,7 @@ module NetBoot
         raise 'Should be reimplemented'
       end
 
-      def path(path)
+      def path(_path)
         raise 'Should be reimplemented'
       end
     end
@@ -72,7 +72,7 @@ module NetBoot
         @chain.boot(:chain,nodes,headers,@binary)
       end
 
-      profile, meth = send("boot_#{kind.to_s}".to_sym,*args)
+      profile, meth = send("boot_#{kind}".to_sym,*args)
 
       unless kind == :custom
         header = headers[kind].to_s
@@ -84,23 +84,23 @@ module NetBoot
     end
 
     protected
-    def labelize(header,kind,profile,args)
+    def labelize(_header,_kind,_profile,*)
       raise 'Should be reimplemented'
     end
 
-    def boot_chain(pxebin)
+    def boot_chain(_pxebin)
       raise 'Should be reimplemented'
     end
 
-    def boot_local(env, diskname, device_id, partition_id, default_params='')
+    def boot_local(_env, _diskname, _device_id, _partition_id, _default_params='')
       raise 'Should be reimplemented'
     end
 
-    def boot_network(kernel, initrd, params)
+    def boot_network(_kernel, _initrd, _params)
       raise 'Should be reimplemented'
     end
 
-    def boot_custom(profile, user, id, singularities=nil)
+    def boot_custom(profile, user, _id, singularities=nil)
       [
         profile,
         lambda do |prof,node|
@@ -178,7 +178,7 @@ module NetBoot
       end
     end
 
-    def labelize(header,kind,profile,args=[])
+    def labelize(header,kind,profile,*)
       header+
       "DEFAULT #{kind}\n"\
       "LABEL #{kind}\n"\
@@ -192,7 +192,7 @@ module NetBoot
       ]]
     end
 
-    def boot_local(env, diskname, device_id, partition_id, default_params='')
+    def boot_local(_env, _diskname, device_id, partition_id, _default_params='')
       [[
         "COM32 #{export_path('chain.c32')}",
         "APPEND hd#{device_id} #{partition_id}",
@@ -234,9 +234,9 @@ module NetBoot
           end
         when :http,:ftp
           if path
-            File.join("#{@kind.to_s}://",@server,path)
+            File.join("#{@kind}://",@server,path)
           else
-            File.join("#{@kind.to_s}://",@server)
+            File.join("#{@kind}://",@server)
           end
         end
       end
@@ -264,15 +264,15 @@ module NetBoot
           end
         when :http,:ftp
           if path
-            File.join("#{@kind.to_s}://",@server,path)
+            File.join("#{@kind}://",@server,path)
           else
-            File.join("#{@kind.to_s}://",@server)
+            File.join("#{@kind}://",@server)
           end
         end
       end
     end
 
-    def labelize(header,kind,profile,args=[])
+    def labelize(header,_kind,profile,*)
       "#!ipxe\n#{header}#{profile.join("\n")}"
     end
 
@@ -282,7 +282,7 @@ module NetBoot
       ]]
     end
 
-    def boot_local(env, diskname, device_id, partition_id, default_params='')
+    def boot_local(_env, _diskname, device_id, partition_id, _default_params='')
       [[
         "chain #{export_path('chain.c32')} hd#{device_id} #{partition_id}",
       ]]
@@ -318,15 +318,15 @@ module NetBoot
           end
         when :http
           if path
-            File.join("(#{@kind.to_s},#{@server})",path)
+            File.join("(#{@kind},#{@server})",path)
           else
-            "(#{@kind.to_s},#{@server})"
+            "(#{@kind},#{@server})"
           end
         end
       end
     end
 
-    def labelize(header,kind,profile,args=[])
+    def labelize(header,kind,profile,*)
       header += "\ntimeout=0\n" unless header.include?("timeout")
       header +
       "default=0\n"\
diff --git a/lib/kadeploy3/server/parallel_ops.rb b/lib/kadeploy3/server/parallel_ops.rb
index bd7524db9da4e0d1b0a1846c884b5e7e3e00b7fa..a9c19e9ee31c51e0dfd91e5fa7a343957af6be09 100644
--- a/lib/kadeploy3/server/parallel_ops.rb
+++ b/lib/kadeploy3/server/parallel_ops.rb
@@ -90,7 +90,7 @@ module Kadeploy
     # * expects: Hash of expectations, will be used to sort nodes in OK and KO sets: :stdout, :stderr, :status, ...
     # Output
     # * returns an array that contains two arrays ([0] is the nodes OK and [1] is the nodes KO)
-    def taktuk_sendfile(src,dst,opts={},expects={})
+    def taktuk_sendfile(src,dst,_opts={},expects={})
       nodes_init(:stdout => '', :stderr => '', :status => '0')
 
       res = nil
@@ -164,7 +164,7 @@ module Kadeploy
     # Set information about a Taktuk command execution
     def nodes_update(result, fieldkey = nil, fieldval = :line)
       if fieldkey
-        result.each_pair do |host,pids|
+        result.each_value do |pids|
           pids.each_value do |value|
             value[fieldkey].each_index do |i|
               node = node_get(value[fieldkey][i])
diff --git a/lib/kadeploy3/server/parallel_runner.rb b/lib/kadeploy3/server/parallel_runner.rb
index 799df12fb18c6d62badf89fd9e76fdbdf114ee86..51f1b9354276701eb27d52a547f99a4c944663fa 100644
--- a/lib/kadeploy3/server/parallel_runner.rb
+++ b/lib/kadeploy3/server/parallel_runner.rb
@@ -1,5 +1,3 @@
-require 'thread'
-
 module Kadeploy
   class ParallelRunner
     @execs = nil
@@ -109,6 +107,7 @@ module Kadeploy
           begin
             thr.join
           rescue SignalException
+            # do nothing
           end
         end
       end
@@ -142,7 +141,6 @@ module Kadeploy
         nodeset.id = @nodesetid
         nodeset.push(node)
         @output.push(exec.command, nodeset) if @output
-        nodeset = nil
       end
 
       [good, bad]
diff --git a/lib/kadeploy3/server/paramsparser.rb b/lib/kadeploy3/server/paramsparser.rb
index 8bd15b07ae5657bc3e0849f002dec8d96c8aaed5..c2b9c85482c0e0d773452a04f3db4ad4a3233676 100644
--- a/lib/kadeploy3/server/paramsparser.rb
+++ b/lib/kadeploy3/server/paramsparser.rb
@@ -98,14 +98,14 @@ class ParamsParser
     end
 
     if opts[:range] and !opts[:range].include?(param)
-      error(errno,"must be in the range #{opts[:range].to_s}")
+      error(errno,"must be in the range #{opts[:range]}")
     end
 
     case opts[:type]
     when :uri
       begin
         param = URI.parse(param)
-      rescue Exception => e
+      rescue StandardError => e
         error(errno,"invalid URI (#{e.message})")
       end
 
@@ -120,7 +120,7 @@ class ParamsParser
       # Get the node
       param = param.strip
       error(APIError::INVALID_NODELIST,"Empty node name") if param.empty?
-      unless param = @nodes.get_node(param)
+      unless (param = @nodes.get_node(param))
         error(APIError::INVALID_NODELIST,"The node #{param} does not exist")
       end
     when :nodeset
diff --git a/lib/kadeploy3/server/port_scanner.rb b/lib/kadeploy3/server/port_scanner.rb
index 614b326f3863ba130a6e253a438a9e89ae95fc0e..b8855000ae02e6478f44c70a38f897f52b9c2103 100644
--- a/lib/kadeploy3/server/port_scanner.rb
+++ b/lib/kadeploy3/server/port_scanner.rb
@@ -1,5 +1,4 @@
 require 'socket'
-require 'thread'
 
 module Kadeploy
 
@@ -61,12 +60,15 @@ module PortScanner
   def self.ping(hostname, timeout, port)
     ret = true
     begin
-      timeout(timeout) do
-	      s = TCPSocket.new(hostname, port)
-	      s.close
+      Timeout.timeout(timeout) do
+        s = TCPSocket.new(hostname, port)
+        s.close
       end
     rescue Errno::ECONNREFUSED
-    rescue Timeout::Error, StandardError
+      # do nothing
+    rescue Timeout::Error
+      ret = false
+    rescue StandardError
       ret = false
     end
     ret
diff --git a/lib/kadeploy3/server/rights.rb b/lib/kadeploy3/server/rights.rb
index b66a2d68317e3d55c604630d0aa9c0d3d26a54fa..c64d996aa27b4f4407b26d26f7855feaf9390b9c 100644
--- a/lib/kadeploy3/server/rights.rb
+++ b/lib/kadeploy3/server/rights.rb
@@ -15,19 +15,19 @@ module Rights
   end
 
   class Rights
-    def add(user,nodes=nil,parts=nil)
+    def add(_user, _nodes=nil, _parts=nil)
       true
     end
 
-    def get(user,nodes=nil)
+    def get(_user, _nodes=nil)
       true
     end
 
-    def delete(user,nodes=nil)
+    def delete(_user,_nodes=nil)
       true
     end
 
-    def granted?(user,nodes,parts=nil)
+    def granted?(_user,_nodes,_parts=nil)
       true
     end
 
@@ -59,7 +59,7 @@ module Rights
 
   class RightsDummy < Rights
     def get(user,nodes=nil)
-      user,nodes = prepare(user,nodes)
+      _,nodes = prepare(user,nodes)
       if nodes and !nodes.empty?
         nodes.uniq! if nodes.is_a?(Array)
         nodes.inject({}){|h,n| h[n] = '*'; h}
@@ -105,7 +105,7 @@ module Rights
       to_add = {}
       if nodes
         if existing.is_a?(Array) # User have rights on every nodes
-          nodes.each do |n|
+          nodes.each do
             treatment.call(to_add,node,existing)
           end
         elsif existing.is_a?(Hash)
@@ -185,7 +185,6 @@ module Rights
             ret[usr] = nods
           end
         end
-        res = nil
         ret
       else
         nil
@@ -254,7 +253,7 @@ module Rights
       elsif rights.is_a?(Hash)
         if nodes.sort == rights.keys.sort
           unless parts[0].empty?
-            rights.each do |n,p|
+            rights.each do |_,p|
               return false if p[0] != '*' and !(parts.sort-p.sort).empty?
             end
           end
@@ -277,7 +276,6 @@ module Rights
           h[v['user']][v['node']] << v['part']
           h
         end
-        res = nil
         ret
       else
         nil
diff --git a/lib/kadeploy3/server/server.rb b/lib/kadeploy3/server/server.rb
index c55b1970600006f3047ab8c9c06871fd922efa46..a3598b8ab648fd800a2664f4fa30f5e53c2259f6 100644
--- a/lib/kadeploy3/server/server.rb
+++ b/lib/kadeploy3/server/server.rb
@@ -1,4 +1,3 @@
-require 'thread'
 require 'securerandom'
 require 'ostruct'
 require 'base64'
@@ -355,7 +354,7 @@ class KadeployServer
     end
   end
 
-  def prepare(request,kind,query,*args)
+  def prepare(_request,_kind,_query,*)
     options
   end
 
@@ -476,7 +475,6 @@ class KadeployServer
           free_exec_context(options)
           wipe_exec_context(options)
         end
-        options = nil
       end
     end
   end
@@ -644,15 +642,15 @@ class KadeployServer
     nil
   end
 
-  def get_nodes(*args)
+  def get_nodes(*)
     Nodes::sort_list(cfg.common.nodes.make_array_of_hostname)
   end
 
-  def get_clusters(*args)
+  def get_clusters(*)
     cfg.clusters.keys.dup
   end
 
-  def get_users_info(*args)
+  def get_users_info(*)
     ret = {}
 
     ret[:pxe] = cfg.common.pxe[:dhcp].class.name.split('::').last
diff --git a/lib/kadeploy3/server/stats.rb b/lib/kadeploy3/server/stats.rb
index 5ed0ec7d44957158b3dce6e996d96cab28be603e..d89b193dd9afbb2ed1e1dccba0b785b3fcb60015 100644
--- a/lib/kadeploy3/server/stats.rb
+++ b/lib/kadeploy3/server/stats.rb
@@ -3,7 +3,7 @@ module Kadeploy
 module Stats
   MAX_RESULTS_PER_REQUEST=50000
 
-  def self.list_failure_rates(db,operation,filters={},options={},fields=nil)
+  def self.list_failure_rates(db,operation,filters={},options={},_fields=nil)
     where,args = db_filters(operation,filters)
     op,args = db_options(options,args)
     query = "SELECT hostname,COUNT(*) FROM log"
@@ -84,8 +84,6 @@ module Stats
     ret
   end
 
-  private
-
   def self.db_field(table,name,expr)
     "#{table && (table+'.'+name) || name} #{expr}"
   end
@@ -158,6 +156,8 @@ module Stats
 
     return [ret,args]
   end
+
+  private_class_method :db_field, :db_filters, :db_options
 end
 
 end
diff --git a/lib/kadeploy3/server/stepdeploy.rb b/lib/kadeploy3/server/stepdeploy.rb
index 3715e5878cbfe5a19b9cb39f441b015a09576480..14e641a922f1b82e7ad9349d734f277a6af107c7 100644
--- a/lib/kadeploy3/server/stepdeploy.rb
+++ b/lib/kadeploy3/server/stepdeploy.rb
@@ -7,9 +7,6 @@ module Macrostep
 ########################
 
   class DeploySetDeploymentEnv < Deploy
-    def load_config()
-      super()
-    end
   end
 
   class DeploySetDeploymentEnvUntrusted < DeploySetDeploymentEnv
@@ -109,9 +106,6 @@ module Macrostep
 ####################
 
   class DeployBroadcastEnv < Deploy
-    def load_config()
-      super()
-    end
   end
 
   class DeployBroadcastEnvChain < DeployBroadcastEnv
@@ -222,9 +216,6 @@ module Macrostep
 ##################
 
   class DeployBootNewEnv < Deploy
-    def load_config()
-      super()
-    end
   end
 
   class DeployBootNewEnvKexec < DeployBootNewEnv
diff --git a/lib/kadeploy3/server/taktuk.rb b/lib/kadeploy3/server/taktuk.rb
index ddc3d09441574f35331fdbe1fbe03085437b6cb5..74519ecfba64e69b3826bf55c39c228a76db23c4 100644
--- a/lib/kadeploy3/server/taktuk.rb
+++ b/lib/kadeploy3/server/taktuk.rb
@@ -45,7 +45,7 @@ module TakTuk
     end
 
     def free()
-      self.each_pair do |host,pids|
+      self.each_value do |pids|
         pids.each_value do |val|
           val.clear if val.is_a?(Array) or val.is_a?(Hash)
         end
@@ -100,7 +100,7 @@ module TakTuk
     def parse(string)
       ret = Result.new
       if @template and string and !string.empty?
-        regexp = /^#{@type.to_s}#{SEPESCAPED}(\d+)#{SEPESCAPED}(#{HOSTNAME_REGEXP})#{SEPESCAPED}(.+)$/
+        regexp = /^#{@type}#{SEPESCAPED}(\d+)#{SEPESCAPED}(#{HOSTNAME_REGEXP})#{SEPESCAPED}(.+)$/
         string.each_line do |line|
           if regexp =~ line
             ret.add(
@@ -241,7 +241,7 @@ module TakTuk
 
     def to_cmd
       @fields.inject('') do |ret,field|
-        ret + ".length(\"$#{field.to_s}\").\"#{SEPARATOR}$#{field.to_s}\""
+        ret + ".length(\"$#{field}\").\"#{SEPARATOR}$#{field}\""
       end
     end
 
@@ -370,9 +370,9 @@ module TakTuk
     def to_cmd
       self.inject([]) do |ret,val|
         if val =~ /^\[(.*)\]$/
-          ret += ['[',Regexp.last_match(1).strip,']']
+          ret + ['[',Regexp.last_match(1).strip,']']
         else
-          ret += val.split(' ')
+          ret + val.split(' ')
         end
       end
     end
@@ -420,7 +420,7 @@ module TakTuk
       @streams.each_pair do |name,stream|
         temp = (stream.is_a?(Stream) ? "=#{stream.to_cmd}" : '')
         @args << '-o'
-        @args << "#{name.to_s}#{temp}"
+        @args << "#{name}#{temp}"
       end
       @args += @hostlist.to_cmd
       @args += @commands.to_cmd
@@ -473,7 +473,6 @@ module TakTuk
       if @streams
         @streams.each_value do |stream|
           stream.free if stream
-          stream = nil
         end
       end
       @hostlist.free if @hostlist
diff --git a/lib/kadeploy3/server/window.rb b/lib/kadeploy3/server/window.rb
index 40769c9381b06047bfabd5ff4ee00e5318b3b3bc..8fd4610e8d3265635ee8f545ed39afdb10298a9d 100644
--- a/lib/kadeploy3/server/window.rb
+++ b/lib/kadeploy3/server/window.rb
@@ -1,4 +1,3 @@
-require 'thread'
 require 'uri'
 require 'tempfile'
 
diff --git a/lib/kadeploy3/server/workflow.rb b/lib/kadeploy3/server/workflow.rb
index 872f0e3d27b324a3a89fae43ce7e4bb608e18744..c1e4000710af8f07c1be430a4776809c137a353c 100644
--- a/lib/kadeploy3/server/workflow.rb
+++ b/lib/kadeploy3/server/workflow.rb
@@ -1,4 +1,3 @@
-require 'thread'
 require 'uri'
 require 'tempfile'
 
@@ -62,6 +61,7 @@ module Workflow
         begin
           kind = URI.parse(path).scheme
         rescue URI::InvalidURIError
+          # do nothing
         end
 
         if kind.nil?
@@ -80,7 +80,7 @@ module Workflow
         check_file(cexec.env.tarball['file']) if cexec.env.tarball
         check_file(cexec.env.preinstall['file']) if cexec.env.preinstall
         if cexec.env.postinstall and !cexec.env.postinstall.empty?
-          cexec.env.postinstall.each do |postinstall|
+          cexec.env.postinstall.each do
             check_file(cexec.env.postinstall['file'])
           end
         end
@@ -89,8 +89,8 @@ module Workflow
       check_file(cexec.key) if cexec.key
 
       if cexec.custom_operations
-        cexec.custom_operations[:operations].each_pair do |macro,micros|
-          micros.each_pair do |micro,entries|
+        cexec.custom_operations[:operations].each_value do |micros|
+          micros.each_value do |entries|
             entries.each do |entry|
               if entry[:action] == :send or entry[:action] == :run
                 check_file(entry[:file])
@@ -250,7 +250,7 @@ module Workflow
       )
     end
 
-    def fail!(task,nodeset)
+    def fail!(_task,nodeset)
       @nodes_ko.set_state(self.class.operation('_failed'),nil,
         context[:database],context[:user])
       @nodes_ko.set.each do |node|
@@ -385,17 +385,19 @@ module Workflow
     def check_config()
     end
 
-    def self.operation(suffix='')
+    def self.operation(_suffix='')
       raise
     end
 
+    private_class_method :operation
+
     def load_tasks()
       raise
     end
   end
 
   class Deploy < Workflow
-    def self.opname(suffix='')
+    def self.opname(_suffix='')
       "deployment"
     end
 
@@ -437,7 +439,7 @@ module Workflow
       # BroadcastEnv step
       macrosteps[1].to_a.each do |instance|
         if context[:execution].disable_kexec and instance[0] == 'SetDeploymentEnvKexec'
-	        instance[0] = 'SetDeploymentEnvUntrusted'
+          instance[0] = 'SetDeploymentEnvUntrusted'
           # Should not be hardcoded
           instance[1] = 0
           instance[2] = eval("(#{context[:cluster].timeout_reboot_classical})+200").to_i
@@ -447,7 +449,6 @@ module Workflow
       end
 
       # BootNewEnv step
-      n = n = @nodes.length
       setclassical = lambda do |inst,msg|
         if inst[0] == 'BootNewEnvKexec'
           inst[0] = 'BootNewEnvClassical'
@@ -482,7 +483,7 @@ module Workflow
       end
 
       @tasks.each do |macro|
-        macro = macro[0] if macro.size == 1
+        macro[0] if macro.size == 1
       end
 
       # Some extra debugs
@@ -532,7 +533,7 @@ module Workflow
   end
 
   class Power < Workflow
-    def self.opname(suffix='')
+    def self.opname(_suffix='')
       "power operation"
     end
 
@@ -565,7 +566,7 @@ module Workflow
   end
 
   class Reboot < Workflow
-    def self.opname(suffix='')
+    def self.opname(_suffix='')
       "reboot"
     end
 
diff --git a/sbin/kadeploy3d b/sbin/kadeploy3d
index afe38df7def4be15436e68269a6efa0f7c167921..6cde6890ef5925779353e24f883fdda54e1b3ad8 100755
--- a/sbin/kadeploy3d
+++ b/sbin/kadeploy3d
@@ -80,8 +80,8 @@ Signal::trap("HUP") do
 #      STDOUT.puts "[#{Time.now.to_s}] Reloading configuration files"
 #      $kadeploy.reload_config()
 #      file.puts '0'
-    rescue Exception => e
-      STDERR.puts "[#{Time.now.to_s}] Failed to reload configuration files !"
+    rescue StandardError => e
+      STDERR.puts "[#{Time.now}] Failed to reload configuration files !"
       if e.is_a?(Kadeploy::KadeployError)
         file.puts '1'
         error("#{Kadeploy::KadeployError.to_msg(e.errno)}"\
@@ -106,9 +106,9 @@ Signal::trap("USR1") do
   Thread.new do
     begin
       require 'kadeploy3/server/dump'
-      STDERR.puts "[#{Time.now.to_s}] Dump internal structures"
+      STDERR.puts "[#{Time.now}] Dump internal structures"
       Kadeploy.dump
-    rescue Exception => e
+    rescue StandardError => e
       STDERR.puts e.class.name
       STDERR.puts e.message
       STDERR.puts e.backtrace
@@ -116,8 +116,6 @@ Signal::trap("USR1") do
   end
 end
 
-require 'thread'
-
 # code snippet coming from
 # http://itreallymatters.net/post/29549982905/generating-thread-dumps-for-ruby-scripts
 Signal::trap('USR2') do
@@ -127,7 +125,7 @@ Signal::trap('USR2') do
   else
     Thread.list.each do |thread|
       t=Time.now
-      STDERR.puts "[#{t}]========= Thread #{thread.object_id.to_s} =========="
+      STDERR.puts "[#{t}]========= Thread #{thread.object_id} =========="
       bt = thread.backtrace
       STDERR.puts "[#{t}] #{bt ? bt.join("\n[#{t}]    \\_ ") : "Thread has no backtrace, its status is: #{thread.status}"}"
       STDERR.puts "[#{t}]================= END ================="
@@ -147,7 +145,8 @@ def clean()
   begin
     File.delete($pidfile) if $pidfile
     $pidfile = nil
-  rescue Exception
+  rescue StandardError
+    # do nothing
   end
 
   if $ssh_key
@@ -334,14 +333,14 @@ $stderr = STDERR
 begin
   File.open($pidfile,'w'){|f| f.puts Process::pid} if $pidfile
 
-  $stdout.puts "[#{Time.now.to_s}] Launching service"
+  $stdout.puts "[#{Time.now}] Launching service"
 
   # Launch autoclean thread
   $autoclean = Thread.new do
-    begin
+    loop do
       sleep AUTOCLEAN_PITCH
       $kadeploy.workflows_clean()
-    end while true
+    end
   end
 
   GC.start
diff --git a/vagrant-env/README.md b/vagrant-env/README.md
index 619ad027394a55fad7f4ad8b725e3da890cc32d5..91a1083d3bfb22a72b3fd4145e337930aa2b5d2c 100644
--- a/vagrant-env/README.md
+++ b/vagrant-env/README.md
@@ -17,6 +17,7 @@ You will need ncat from nmap. (apt install ncat)
 * vagrant up kadeploy
 * vagrant up knode-1 #Fail to connect ssh is expected
 * vagrant ssh kadeploy
+* You may need to start ident2 on kadeploy (`sudo ident2`)
 ```
 vagrant@kadeploy> kadeploy3d -d
 vagrant@kadeploy> karights3 -o -a -m node-1 -u vagrant
diff --git a/vagrant-env/Vagrantfile b/vagrant-env/Vagrantfile
index 08ed8cc7f63368360dc4007e9b95951f06af57a5..89ba1ff0a8cc9efc2628c5c22e64fbc6bb4d76a4 100644
--- a/vagrant-env/Vagrantfile
+++ b/vagrant-env/Vagrantfile
@@ -3,7 +3,7 @@ require 'yaml'
 
 Vagrant.configure("2") do |config|
   config.vm.define :kadeploy do |server|
-    server.vm.box = 'debian/contrib-jessie64'
+    server.vm.box = 'debian/contrib-buster64'
     server.vm.hostname = 'kadeploy'
     server.vm.synced_folder '.', '/vagrant'
     server.vm.synced_folder '..', '/kadeploy'
diff --git a/vagrant-env/db_creation.sql b/vagrant-env/db_creation.sql
deleted file mode 100644
index 24ac349b8e01f317259a50f238fd3007605b42fa..0000000000000000000000000000000000000000
--- a/vagrant-env/db_creation.sql
+++ /dev/null
@@ -1,97 +0,0 @@
--- Kadeploy 3.1
--- Copyright (c) by INRIA, Emmanuel Jeanvoine - 2008-2010
--- CECILL License V2 - http://www.cecill.info
--- For details on use and redistribution please refer to License.txt
-
-
--- 
--- Table `environments`
--- 
-
-DROP TABLE IF EXISTS `environments`;
-CREATE TABLE IF NOT EXISTS `environments` (
-  `id` int(10) unsigned NOT NULL auto_increment,
-  `name` varchar(255) NOT NULL default '',
-  `version` int(10) unsigned NOT NULL default '0',
-  `description` text,
-  `author` varchar(56) NOT NULL default '',
-  `tarball` varchar(512) NOT NULL,
-  `preinstall` varchar(512) NOT NULL,
-  `postinstall` varchar(512) NOT NULL,
-  `hypervisor` varchar(255) NOT NULL,
-  `hypervisor_params` varchar(255) NOT NULL,
-  `initrd` varchar(255) NOT NULL,
-  `kernel` varchar(255) NOT NULL,
-  `kernel_params` varchar(255) NOT NULL,
-  `fdisk_type` varchar(2) default NULL,
-  `filesystem` varchar(9) default NULL,
-  `user` varchar(255) default 'nobody',
-  `allowed_users` varchar(512) NOT NULL,
-  `environment_kind` varchar(10) NOT NULL,
-  `visibility` varchar(8) NOT NULL,
-  `demolishing_env` boolean NOT NULL default FALSE,
-  `multipart` boolean NOT NULL default FALSE,
-  `options` text NULL default NULL,
-  PRIMARY KEY  (`id`)
-) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
--- 
--- Table `log`
--- 
-
-DROP TABLE IF EXISTS `log`;
-CREATE TABLE IF NOT EXISTS `log` (
-  `wid` varchar(41) NOT NULL,
-  `hostname` varchar(256) NOT NULL,
-  `step1` varchar(45) NOT NULL,
-  `step2` varchar(45) NOT NULL,
-  `step3` varchar(45) NOT NULL,
-  `timeout_step1` smallint(5) unsigned NOT NULL,
-  `timeout_step2` smallint(5) unsigned NOT NULL,
-  `timeout_step3` smallint(5) unsigned NOT NULL,
-  `retry_step1` tinyint(1) unsigned NOT NULL,
-  `retry_step2` tinyint(1) unsigned NOT NULL,
-  `retry_step3` tinyint(1) unsigned NOT NULL,
-  `start` int(10) unsigned NOT NULL,
-  `step1_duration` int(10) unsigned NOT NULL,
-  `step2_duration` int(10) unsigned NOT NULL,
-  `step3_duration` int(10) unsigned NOT NULL,
-  `env` varchar(64) NOT NULL,
-  `anonymous_env` varchar(6) NOT NULL,
-  `md5` varchar(35) NOT NULL,
-  `success` varchar(6) NOT NULL,
-  `error` varchar(255) NOT NULL,
-  `user` varchar(16) NOT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
--- 
--- Table `nodes`
--- 
-
-DROP TABLE IF EXISTS `nodes`;
-CREATE TABLE IF NOT EXISTS `nodes` (
-  `hostname` varchar(256) NOT NULL,
-  `state` varchar(16) NOT NULL,
-  `env_id` int(10) NOT NULL,
-  `date` int(10) unsigned NOT NULL,
-  `user` varchar(16) NOT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-
-
--- --------------------------------------------------------
-
--- 
--- Table `rights`
--- 
-
-DROP TABLE IF EXISTS `rights`;
-CREATE TABLE IF NOT EXISTS `rights` (
-  `user` varchar(30) NOT NULL,
-  `node` varchar(256) NOT NULL,
-  `part` varchar(50) NOT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-
diff --git a/vagrant-env/kadeploy_conf/server.conf b/vagrant-env/kadeploy_conf/server.conf
index b2326bb022e6370f9a7e3d3b77ee916ff62e58b7..5aff61160759e2c19d8788a2a363d199aab4d1c4 100644
--- a/vagrant-env/kadeploy_conf/server.conf
+++ b/vagrant-env/kadeploy_conf/server.conf
@@ -24,10 +24,10 @@ authentication:
     - 127.0.0.1
 security:
   secure_server: true
-  certificate: /vagrant/ssl/test2.cert
+  certificate: /vagrant/ssl/certificate.crt
   private_key:
     algorithm: RSA
-    file: /vagrant/ssl/test2.key
+    file: /vagrant/ssl/privateKey.key
 logs:
   database: true
   logfile: /var/log/kadeploy3/kadeploy.log
@@ -43,7 +43,7 @@ network:
   vlan:
     hostname_suffix: -kavlan-VLAN_ID
     set_cmd: kavlan NODES -s -i VLAN_ID -u USER
-  server_hostname: wheezy_mock
+  server_hostname: vagrant_machine
   ports:
     test_deploy_env: 25300
     kadeploy_server: 25301
diff --git a/vagrant-env/kadeploy_provision.sh b/vagrant-env/kadeploy_provision.sh
index 3c29cb3588a4f5338402a07e509f13ed67d9291a..2e71df465fd7ce400423f890d73937b76cd4446e 100644
--- a/vagrant-env/kadeploy_provision.sh
+++ b/vagrant-env/kadeploy_provision.sh
@@ -6,13 +6,14 @@ wget http://packages.grid5000.fr/grid5000-archive-key.asc -q -O- | apt-key add -
 echo deb http://packages.grid5000.fr/deb/g5k-postinstall/ ./ > /etc/apt/sources.list.d/postinstall.list
 echo deb http://packages.grid5000.fr/deb/kadeploy-kernels/ ./ > /etc/apt/sources.list.d/kadeploykernel.list
 DEBIAN_FRONTEND=noninteractive apt-get update
-DEBIAN_FRONTEND=noninteractive apt-get install -y ruby rubygems lsb-release git taktuk rake help2man mysql-server ruby-dev libmysqlclient-dev ident2 syslinux nmap dnsmasq isc-dhcp-server tftpd-hpa pxelinux
+DEBIAN_FRONTEND=noninteractive apt-get install -y ruby rubygems lsb-release git taktuk rake help2man mariadb-server libmariadbclient-dev ruby-dev ident2 syslinux ncat dnsmasq isc-dhcp-server tftpd-hpa pxelinux
 DEBIAN_FRONTEND=noninteractive apt-get install -y g5k-postinstall kadeploy3-deploy-kernel-buster
 # Not necessary:
 DEBIAN_FRONTEND=noninteractive apt-get install -y vim tcpdump
-gem install --conservative --no-ri --no-rdoc mysql
+gem install --conservative --no-ri --no-rdoc mysql2
 gem install --conservative --no-ri --no-rdoc net-ssh -v 4.2.0
-gem install --conservative --no-ri --no-rdoc net-ssh-multi
+gem install --conservative --no-ri --no-rdoc byebug -v 9.0.6
+gem install --conservative --no-ri --no-rdoc rspec
 }
 
 setup_tftp() {
@@ -42,7 +43,7 @@ systemctl restart dnsmasq
 }
 
 setup_kadeploy() {
-mysql <<< "DROP DATABASE IF EXISTS deploy3;\nCREATE DATABASE deploy3;\nGRANT select, insert, update, delete, create, drop, alter,  create temporary tables, lock tables ON deploy3.*  TO 'deploy'@'localhost';\nSET PASSWORD FOR  'deploy'@'localhost' = PASSWORD('deploy-password');\nuse deploy3;\nsource /vagrant/db_creation.sql;"
+mysql <<< "DROP DATABASE IF EXISTS deploy3;\nCREATE DATABASE deploy3;\nCREATE USER IF NOT EXISTS 'deploy'@'localhost';\nGRANT select, insert, update, delete, create, drop, alter, create temporary tables, lock tables ON deploy3.*  TO 'deploy'@'localhost';\nSET PASSWORD FOR  'deploy'@'localhost' = PASSWORD('deploy-password');\nuse deploy3;\nsource /kadeploy/db/db_creation.sql;"
 cp /vagrant/keys/id_deploy /home/vagrant/.ssh/deploy_id_rsa
 chown vagrant /home/vagrant/.ssh/deploy_id_rsa
 chmod og-r /home/vagrant/.ssh/deploy_id_rsa
diff --git a/vagrant-env/ssl/certificate.crt b/vagrant-env/ssl/certificate.crt
new file mode 100644
index 0000000000000000000000000000000000000000..234a665f1e8e8f2505efcb350f770d3a7bd36fd3
--- /dev/null
+++ b/vagrant-env/ssl/certificate.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIURV+F7KeGrX+G/jgRAb5f1UMGzikwDQYJKoZIhvcNAQEL
+BQAwMzELMAkGA1UEBhMCRlIxETAPBgNVBAgMCEthZGVwbG95MREwDwYDVQQKDAhH
+cmlkNTAwMDAeFw0yMDExMDQxNDQzMjdaFw0yMDEyMDQxNDQzMjdaMDMxCzAJBgNV
+BAYTAkZSMREwDwYDVQQIDAhLYWRlcGxveTERMA8GA1UECgwIR3JpZDUwMDAwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5HmYk6J+BZSp89HEtJQ0hiud9
+3EPyOxkmBFQUG/Ci6dFEqiGngKhN6yJ8Cz8uMr5WKr/j9mO7OwAUCDJrJ2XfcJDJ
+aO3jfNELbcR6fdGRmXV+LL3zB9IFau9YVomdqQupY6ifTwYlQQKjrTLbYYzMlClP
+H79CIyMiWu8mJ/pgtEZ9TL8fxCB7XUITNx1ofR4bjGDujGhnb6A6BAv7nz5PURh1
+DNd2HhupAW3dpVJYgorOeOt8tavGTtjdiDO0mNVDho3upsauQFV3nWLfxiY6cMXY
+pRJBx14Kuc9dBgULKZfztb25fOw6RMeMYae/pI/7b06Pye8t1iCYBi4wKweVAgMB
+AAGjUzBRMB0GA1UdDgQWBBQSgvJ/10cu3UTyfw9FzJxP3Y40UDAfBgNVHSMEGDAW
+gBQSgvJ/10cu3UTyfw9FzJxP3Y40UDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQB6L5dIwpe1ZU2lTPeZXcg6HoAj7UNN1Pw0jGIbWwVrjzpk3m1v
+gNm11D2vbUyajIy7YfQ3zBWqp/Lz0GT9QoEgFrF6L1rxAWG98py9mQ1/0X/q2NeX
+o+2n1PyrTzuKwNbWunYECz1OhOz8a7GiZKJApudSDtQsB0iOXtJ9qC8ap/QX/vHs
+ipQbbDcX7J1XfGJwnFYSr8kjy9nowns9XvwKYVEWsBmR+eZUv2aFItwC87iWSoGT
+XYSg5YGOpWGhF8y0hNMxfWFVgahaljfRprcmIKSbt+EKOibt1hR+Zhwtf63BFUcn
+fTfMVnQpZlMZ49cceo/WS0ioqI/sRd2HEN8f
+-----END CERTIFICATE-----
diff --git a/vagrant-env/ssl/privateKey.key b/vagrant-env/ssl/privateKey.key
new file mode 100644
index 0000000000000000000000000000000000000000..302df4760f158995f859e7d8874e8243b2dca0ca
--- /dev/null
+++ b/vagrant-env/ssl/privateKey.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5HmYk6J+BZSp8
+9HEtJQ0hiud93EPyOxkmBFQUG/Ci6dFEqiGngKhN6yJ8Cz8uMr5WKr/j9mO7OwAU
+CDJrJ2XfcJDJaO3jfNELbcR6fdGRmXV+LL3zB9IFau9YVomdqQupY6ifTwYlQQKj
+rTLbYYzMlClPH79CIyMiWu8mJ/pgtEZ9TL8fxCB7XUITNx1ofR4bjGDujGhnb6A6
+BAv7nz5PURh1DNd2HhupAW3dpVJYgorOeOt8tavGTtjdiDO0mNVDho3upsauQFV3
+nWLfxiY6cMXYpRJBx14Kuc9dBgULKZfztb25fOw6RMeMYae/pI/7b06Pye8t1iCY
+Bi4wKweVAgMBAAECggEABhkxRj//mTSq/KjU3abd0uAPlj7eYil+P5le57av674G
+Ldvo9eqwILkBTtLUBwKW8KHB5pGkYXOlIgPPHWaT3ZOIwYnaZGclP9oi4eIpOEG0
+9C4nJ813JsSKE//t0qrR/oeQ84aX7jxBCQFYro99IvQylC+4jkY4Dxat0DT685qO
+asFKbEO17k5mz3meVn4sedBIhfU+BhcqGak+WtVLuMtnOM9qX2Q3zrRx7Vs6hb34
+P6GZMTu0xdYdBo5nvA6RkFL2DFJqN4rn7SPeUrYUrJw5uK36d+p1wzQwL3Ss6RTI
+0NSeNpiaCtsNJQi2EUde0refL1uPOBpc4BWiWjcawQKBgQDfjGcBH4uGvlqx2HPt
+b/ZNn/mM7Vs5T0EsqdxYP7HFepkpReAebH3Y/DNeY/E2IfDpJLn2pgrao6iXQ44k
+6RJXibDEBVN+lesUKvbvCaHv9+klJtsy4mwpITB3S4y/rg1Umn8BDt/pComJVFFi
+5FVw11Ry5ZKgTqDEL5iKqHM0UQKBgQDT/dtJYJr+SVyL+bu9TA9qJ8VM68IVNLw+
+G3AmB55vsKhH2hT8h1zEwlr4I9aCyFsWvgpFfQmsyZ1C041o+X7yiJCdxL/zFTxM
+jvUDASK+TNuJ0jHYCJGrhoiWH9ZtHVqlGUBWEzeOdLrjJP2Ft69kI+7/W6HWUqFD
+7cNQyKRiBQKBgQC9QQU3KziZY3Au3lwOqNnxj7zadVvkoddAc7GKuKnM0OT3zyNV
+Pm4wlBr9D0l3lbZ5+tDBIoNP5HvnS5b8YqFXoMcYvJWaNlulYFZbumDxYoVsIYAz
+jQMasvFwHXLUGAtLE9zvzWL8zSHxNIQOX9aByJrDBt5ifw6V6OGQidm2cQKBgQCh
+B3YpON7DRgqssRiw5DPZWTiAA5276gEL1F/OI39wK+rIGZpTcKdBNrlPQDnTwkme
+7uByhFZzD/sLJhOGp+6MYLwpe6irB3h0Vys6CwTPNSaWfDosdeXhOyJJlwmUfPW7
+74B1YceTyIuluxVxG2R5VupWws4eNUoWhWcV2DM12QKBgFbibcCvwd1y+d3QhZXP
+5E7OvMj7n8zg6kjQvL2ByB/UGt65c/89NZrxxapysgDZ+krvAMICDN+JvUeds85e
+f4W3SC5dQySDQm2iF0jpv7llC1ILDyt5B7YqqZ3WuHhgE9uHqKaT6wA9pxwyz9VP
+wROykymMcL11NBRNelfgAE/U
+-----END PRIVATE KEY-----