diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go
index 0d93e3252627c9155adaeca20b4ba5d505f034bb..93632856c6c2f15d3af91d434d642868fe134fed 100644
--- a/cmd/ipfs/daemon.go
+++ b/cmd/ipfs/daemon.go
@@ -11,6 +11,7 @@ import (
 	"sort"
 	"sync"
 
+	utilmain "github.com/ipfs/go-ipfs/cmd/ipfs/util"
 	"github.com/ipfs/go-ipfs/core"
 	commands "github.com/ipfs/go-ipfs/core/commands"
 	corehttp "github.com/ipfs/go-ipfs/core/corehttp"
@@ -180,8 +181,6 @@ func defaultMux(path string) corehttp.ServeOption {
 	}
 }
 
-var fileDescriptorCheck = func() error { return nil }
-
 func daemonFunc(req cmds.Request, re cmds.ResponseEmitter) {
 	// Inject metrics before we do anything
 
@@ -193,9 +192,8 @@ func daemonFunc(req cmds.Request, re cmds.ResponseEmitter) {
 	// let the user know we're going.
 	fmt.Printf("Initializing daemon...\n")
 
-	managefd, _, _ := req.Option(adjustFDLimitKwd).Bool()
-	if managefd {
-		if err := fileDescriptorCheck(); err != nil {
+	if managed, _, _ := req.Option(adjustFDLimitKwd).Bool(); managed {
+		if err := utilmain.ManageFdLimit(); err != nil {
 			log.Errorf("setting file descriptor limit: %s", err)
 		}
 	}
diff --git a/cmd/ipfs/ulimit.go b/cmd/ipfs/ulimit.go
deleted file mode 100644
index bfbd04df18537466457575da6cef142820b20b5b..0000000000000000000000000000000000000000
--- a/cmd/ipfs/ulimit.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package main
-
-import (
-	"os"
-	"strconv"
-)
-
-var ipfsFileDescNum = uint64(2048)
-
-func init() {
-	if val := os.Getenv("IPFS_FD_MAX"); val != "" {
-		n, err := strconv.Atoi(val)
-		if err != nil {
-			log.Errorf("bad value for IPFS_FD_MAX: %s", err)
-		} else {
-			ipfsFileDescNum = uint64(n)
-		}
-	}
-}
diff --git a/cmd/ipfs/ulimit_freebsd.go b/cmd/ipfs/ulimit_freebsd.go
deleted file mode 100644
index d97d05c9b9785cd8c60eda67b0473fb7a68bab57..0000000000000000000000000000000000000000
--- a/cmd/ipfs/ulimit_freebsd.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build freebsd
-
-package main
-
-import (
-	"fmt"
-
-	unix "gx/ipfs/QmPXvegq26x982cQjSfbTvSzZXn7GiaMwhhVPHkeTEhrPT/sys/unix"
-)
-
-func init() {
-	fileDescriptorCheck = checkAndSetUlimit
-}
-
-func checkAndSetUlimit() error {
-	var rLimit unix.Rlimit
-	err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rLimit)
-	if err != nil {
-		return fmt.Errorf("error getting rlimit: %s", err)
-	}
-
-	ipfsFileDescNum := int64(ipfsFileDescNum)
-
-	var setting bool
-	if rLimit.Cur < ipfsFileDescNum {
-		if rLimit.Max < ipfsFileDescNum {
-			log.Error("adjusting max")
-			rLimit.Max = ipfsFileDescNum
-		}
-		fmt.Printf("Adjusting current ulimit to %d...\n", ipfsFileDescNum)
-		rLimit.Cur = ipfsFileDescNum
-		setting = true
-	}
-
-	err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit)
-	if err != nil {
-		return fmt.Errorf("error setting ulimit: %s", err)
-	}
-
-	if setting {
-		fmt.Printf("Successfully raised file descriptor limit to %d.\n", ipfsFileDescNum)
-	}
-
-	return nil
-}
diff --git a/cmd/ipfs/ulimit_unix.go b/cmd/ipfs/ulimit_unix.go
deleted file mode 100644
index 0f541a648f8772984a97d7c240b3e2eff7cad5fa..0000000000000000000000000000000000000000
--- a/cmd/ipfs/ulimit_unix.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// +build darwin linux netbsd openbsd
-
-package main
-
-import (
-	"fmt"
-
-	unix "gx/ipfs/QmPXvegq26x982cQjSfbTvSzZXn7GiaMwhhVPHkeTEhrPT/sys/unix"
-)
-
-func init() {
-	fileDescriptorCheck = checkAndSetUlimit
-}
-
-func checkAndSetUlimit() error {
-	var rLimit unix.Rlimit
-	err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rLimit)
-	if err != nil {
-		return fmt.Errorf("error getting rlimit: %s", err)
-	}
-
-	var setting bool
-	if rLimit.Cur < ipfsFileDescNum {
-		if rLimit.Max < ipfsFileDescNum {
-			log.Error("adjusting max")
-			rLimit.Max = ipfsFileDescNum
-		}
-		fmt.Printf("Adjusting current ulimit to %d...\n", ipfsFileDescNum)
-		rLimit.Cur = ipfsFileDescNum
-		setting = true
-	}
-
-	err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit)
-	if err != nil {
-		return fmt.Errorf("error setting ulimit: %s", err)
-	}
-
-	if setting {
-		fmt.Printf("Successfully raised file descriptor limit to %d.\n", ipfsFileDescNum)
-	}
-
-	return nil
-}
diff --git a/cmd/ipfs/util/ulimit.go b/cmd/ipfs/util/ulimit.go
new file mode 100644
index 0000000000000000000000000000000000000000..742a080a36b803dfa04c58bcfa2206ef05309995
--- /dev/null
+++ b/cmd/ipfs/util/ulimit.go
@@ -0,0 +1,91 @@
+package util
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"strconv"
+	"syscall"
+
+	logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
+)
+
+var log = logging.Logger("ulimit")
+
+var (
+	supportsFDManagement = false
+
+	// getlimit returns the soft and hard limits of file descriptors counts
+	getLimit func() (int64, int64, error)
+	// set limit sets the soft and hard limits of file descriptors counts
+	setLimit func(int64, int64) error
+)
+
+// maxFds is the maximum number of file descriptors that go-ipfs
+// can use. The default value is 1024. This can be overwritten by the
+// IPFS_FD_MAX env variable
+var maxFds = uint64(2048)
+
+// setMaxFds sets the maxFds value from IPFS_FD_MAX
+// env variable if it's present on the system
+func setMaxFds() {
+	// check if the IPFS_FD_MAX is set up and if it does
+	// not have a valid fds number notify the user
+	if val := os.Getenv("IPFS_FD_MAX"); val != "" {
+
+		fds, err := strconv.ParseUint(val, 10, 64)
+		if err != nil {
+			log.Errorf("bad value for IPFS_FD_MAX: %s", err)
+			return
+		}
+
+		maxFds = fds
+	}
+}
+
+// ManageFdLimit raise the current max file descriptor count
+// of the process based on the IPFS_FD_MAX value
+func ManageFdLimit() error {
+	if !supportsFDManagement {
+		return nil
+	}
+
+	setMaxFds()
+	soft, hard, err := getLimit()
+	if err != nil {
+		return err
+	}
+
+	max := int64(maxFds)
+
+	if max <= soft {
+		return nil
+	}
+
+	// the soft limit is the value that the kernel enforces for the
+	// corresponding resource
+	// the hard limit acts as a ceiling for the soft limit
+	// an unprivileged process may only set it's soft limit to a
+	// alue in the range from 0 up to the hard limit
+	if err = setLimit(max, max); err != nil {
+		if err != syscall.EPERM {
+			return fmt.Errorf("error setting: ulimit: %s", err)
+		}
+
+		// the process does not have permission so we should only
+		// set the soft value
+		if max > hard {
+			return errors.New(
+				"cannot set rlimit, IPFS_FD_MAX is larger than the hard limit",
+			)
+		}
+
+		if err = setLimit(max, hard); err != nil {
+			return fmt.Errorf("error setting ulimit wihout hard limit: %s", err)
+		}
+	}
+
+	fmt.Printf("Successfully raised file descriptor limit to %d.\n", max)
+
+	return nil
+}
diff --git a/cmd/ipfs/util/ulimit_freebsd.go b/cmd/ipfs/util/ulimit_freebsd.go
new file mode 100644
index 0000000000000000000000000000000000000000..d8b1d5582b7e353749ec8ede8125d85978e43d70
--- /dev/null
+++ b/cmd/ipfs/util/ulimit_freebsd.go
@@ -0,0 +1,27 @@
+// +build freebsd
+
+package util
+
+import (
+	unix "gx/ipfs/QmPXvegq26x982cQjSfbTvSzZXn7GiaMwhhVPHkeTEhrPT/sys/unix"
+)
+
+func init() {
+	supportsFDManagement = true
+	getLimit = freebsdGetLimit
+	setLimit = freebdsSetLimit
+}
+
+func freebsdGetLimit() (int64, int64, error) {
+	rlimit := unix.Rlimit{}
+	err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit)
+	return rlimit.Cur, rlimit.Max, err
+}
+
+func freebdsSetLimit(soft int64, max int64) error {
+	rlimit := unix.Rlimit{
+		Cur: soft,
+		Max: max,
+	}
+	return unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit)
+}
diff --git a/cmd/ipfs/util/ulimit_test.go b/cmd/ipfs/util/ulimit_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ffba72ea819ffb790f8ef5a88dcc70097eabba03
--- /dev/null
+++ b/cmd/ipfs/util/ulimit_test.go
@@ -0,0 +1,88 @@
+package util
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"syscall"
+	"testing"
+)
+
+func TestManageFdLimit(t *testing.T) {
+	t.Log("Testing file descriptor count")
+	if err := ManageFdLimit(); err != nil {
+		t.Errorf("Cannot manage file descriptors")
+	}
+
+	if maxFds != uint64(2048) {
+		t.Errorf("Maximum file descriptors default value changed")
+	}
+}
+
+func TestManageInvalidNFds(t *testing.T) {
+	t.Logf("Testing file descriptor invalidity")
+	var err error
+	if err = os.Unsetenv("IPFS_FD_MAX"); err != nil {
+		t.Fatal("Cannot unset the IPFS_FD_MAX env variable")
+	}
+
+	rlimit := syscall.Rlimit{}
+	if err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
+		t.Fatal("Cannot get the file descriptor count")
+	}
+
+	value := rlimit.Max + rlimit.Cur
+	if err = os.Setenv("IPFS_FD_MAX", fmt.Sprintf("%d", value)); err != nil {
+		t.Fatal("Cannot set the IPFS_FD_MAX env variable")
+	}
+
+	// call to check and set the maximum file descriptor from the env
+	setMaxFds()
+
+	if err = ManageFdLimit(); err == nil {
+		t.Errorf("ManageFdLimit should return an error")
+	} else if err != nil {
+		flag := strings.Contains(err.Error(),
+			"cannot set rlimit, IPFS_FD_MAX is larger than the hard limit")
+		if !flag {
+			t.Errorf("ManageFdLimit returned unexpected error")
+		}
+	}
+
+	// unset all previous operations
+	if err = os.Unsetenv("IPFS_FD_MAX"); err != nil {
+		t.Fatal("Cannot unset the IPFS_FD_MAX env variable")
+	}
+}
+
+func TestManageFdLimitWithEnvSet(t *testing.T) {
+	t.Logf("Testing file descriptor manager with IPFS_FD_MAX set")
+	var err error
+	if err = os.Unsetenv("IPFS_FD_MAX"); err != nil {
+		t.Fatal("Cannot unset the IPFS_FD_MAX env variable")
+	}
+
+	rlimit := syscall.Rlimit{}
+	if err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
+		t.Fatal("Cannot get the file descriptor count")
+	}
+
+	value := rlimit.Max - rlimit.Cur + 1
+	if err = os.Setenv("IPFS_FD_MAX", fmt.Sprintf("%d", value)); err != nil {
+		t.Fatal("Cannot set the IPFS_FD_MAX env variable")
+	}
+
+	setMaxFds()
+	if maxFds != value {
+		t.Errorf("The maxfds is not set from IPFS_FD_MAX")
+	}
+
+	if err = ManageFdLimit(); err != nil {
+		t.Errorf("Cannot manage file descriptor count")
+	}
+
+	// unset all previous operations
+	if err = os.Unsetenv("IPFS_FD_MAX"); err != nil {
+		t.Fatal("Cannot unset the IPFS_FD_MAX env variable")
+	}
+}
diff --git a/cmd/ipfs/util/ulimit_unix.go b/cmd/ipfs/util/ulimit_unix.go
new file mode 100644
index 0000000000000000000000000000000000000000..f931034aeb0b3131aa825e7eec413e1dd040fba8
--- /dev/null
+++ b/cmd/ipfs/util/ulimit_unix.go
@@ -0,0 +1,27 @@
+// +build darwin linux netbsd openbsd
+
+package util
+
+import (
+	unix "gx/ipfs/QmPXvegq26x982cQjSfbTvSzZXn7GiaMwhhVPHkeTEhrPT/sys/unix"
+)
+
+func init() {
+	supportsFDManagement = true
+	getLimit = unixGetLimit
+	setLimit = unixSetLimit
+}
+
+func unixGetLimit() (int64, int64, error) {
+	rlimit := unix.Rlimit{}
+	err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit)
+	return int64(rlimit.Cur), int64(rlimit.Max), err
+}
+
+func unixSetLimit(soft int64, max int64) error {
+	rlimit := unix.Rlimit{
+		Cur: uint64(soft),
+		Max: uint64(max),
+	}
+	return unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit)
+}
diff --git a/cmd/ipfs/util/ulimit_windows.go b/cmd/ipfs/util/ulimit_windows.go
new file mode 100644
index 0000000000000000000000000000000000000000..3cd9908c3274f26d18821da4a0c5d5a9cd72f50c
--- /dev/null
+++ b/cmd/ipfs/util/ulimit_windows.go
@@ -0,0 +1,7 @@
+// +build windows
+
+package util
+
+func init() {
+	supportsFDManagement = false
+}