diff --git a/cincoconfig/config.py b/cincoconfig/config.py
index 119738e..2657aa7 100644
--- a/cincoconfig/config.py
+++ b/cincoconfig/config.py
@@ -5,6 +5,7 @@
 # this source code package.
 #
 
+import os
 import sys
 from typing import Union, Any, Iterator, Tuple, Callable, List
 from argparse import Namespace
@@ -498,6 +499,7 @@ class Config(BaseConfig):
         :param format: output format
         '''
         content = self.dumps(format)
+        filename = os.path.expanduser(filename)
         with open(filename, 'wb') as file:
             file.write(content)
 
@@ -508,7 +510,7 @@ class Config(BaseConfig):
         :param filename: source filename
         :param format: source format
         '''
-
+        filename = os.path.expanduser(filename)
         with open(filename, 'rb') as file:
             content = file.read()
 
diff --git a/cincoconfig/encryption.py b/cincoconfig/encryption.py
index e404c8e..0a5405e 100644
--- a/cincoconfig/encryption.py
+++ b/cincoconfig/encryption.py
@@ -104,8 +104,9 @@ class KeyFile:
         '''
         INTERNAL METHOD. Load configuration key.
         '''
+        filename = os.path.expanduser(self.filename)
         try:
-            with open(self.filename, 'rb') as fp:
+            with open(filename, 'rb') as fp:
                 self.__key = fp.read()
         except OSError:
             self.__key = self.__generate_key()
@@ -119,7 +120,8 @@ class KeyFile:
         :returns: the generated key
         '''
         key = os.urandom(32)
-        with open(self.filename, 'wb') as fp:
+        filename = os.path.expanduser(self.filename)
+        with open(filename, 'wb') as fp:
             fp.write(key)
         return key
 
diff --git a/cincoconfig/fields.py b/cincoconfig/fields.py
index bf64778..3ecdc31 100644
--- a/cincoconfig/fields.py
+++ b/cincoconfig/fields.py
@@ -286,6 +286,15 @@ class IPv4NetworkField(StringField):
     '''
     storage_type = str
 
+    def __init__(self, min_prefix_len: int = None, max_prefix_len: int = None, **kwargs):
+        '''
+        :param min_prefix_len: minimum subnet prefix length (/X), in bits
+        :param max_prefix_len: maximum subnet prefix length (/X), in bits
+        '''
+        super().__init__(**kwargs)
+        self.min_prefix_len = min_prefix_len
+        self.max_prefix_len = max_prefix_len
+
     def _validate(self, cfg: BaseConfig, value: str) -> str:
         '''
         Validate a value.
@@ -299,6 +308,13 @@ class IPv4NetworkField(StringField):
             net = IPv4Network(value)
         except ValueError as err:
             raise ValueError('value is not a valid IPv4 Network (CIDR)') from err
+
+        if self.min_prefix_len and net.prefixlen < self.min_prefix_len:
+            raise ValueError('value must be at least a /%d subnet' % self.min_prefix_len)
+
+        if self.max_prefix_len and net.prefixlen > self.max_prefix_len:
+            raise ValueError('value must be smaller than a /%d subnet' % self.max_prefix_len)
+
         return str(net)
 
 
@@ -398,7 +414,7 @@ class FilenameField(StringField):
             return value
 
         if not os.path.isabs(value) and self.startdir:
-            value = os.path.abspath(os.path.join(self.startdir, value))
+            value = os.path.abspath(os.path.expanduser(os.path.join(self.startdir, value)))
 
         if os.path.sep == '\\':
             value = value.replace('/', '\\')
@@ -1217,7 +1233,7 @@ class IncludeField(FilenameField):
         :returns: the new basic value tree containing the base tree and the included tree
         '''
         filename = self.validate(config, filename)
-        with open(filename, 'rb') as fp:
+        with open(os.path.expanduser(filename), 'rb') as fp:
             content = fp.read()
 
         child = fmt.loads(config, content)

diff --git a/tests/test_config.py b/tests/test_config.py
index c3b45ec..255e8c3 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -483,3 +483,23 @@ class TestConfig:
 
             mock_validate.assert_called_once_with(config, 2)
             assert excinfo.value is orig_exc
+
+    @patch('cincoconfig.config.open', new_callable=mock_open)
+    @patch('cincoconfig.config.os.path.expanduser')
+    def test_save_expanduser(self, expanduser, mop):
+        expanduser.return_value = 'path/to/blah.txt'
+        config = Config(Schema())
+        config.save('~/blah.txt', format='json')
+
+        expanduser.assert_called_once_with('~/blah.txt')
+        mop.assert_called_once_with('path/to/blah.txt', 'wb')
+
+    @patch('cincoconfig.config.open', new_callable=mock_open, read_data=b'{}')
+    @patch('cincoconfig.config.os.path.expanduser')
+    def test_load_expanduser(self, expanduser, mop):
+        expanduser.return_value = 'path/to/blah.txt'
+        config = Config(Schema())
+
+        config.load('~/blah.txt', format='json')
+        expanduser.assert_called_once_with('~/blah.txt')
+        mop.assert_called_once_with('path/to/blah.txt', 'rb')
diff --git a/tests/test_fields/test_include.py b/tests/test_fields/test_include.py
index b9ec29f..414bc05 100644
--- a/tests/test_fields/test_include.py
+++ b/tests/test_fields/test_include.py
@@ -49,7 +49,17 @@ class TestIncludeField:
         field.combine_trees.assert_called_once_with(base, fmt.retval)
         fmt.loads.assert_called_once_with(cfg, b'hello')
 
+    @patch('cincoconfig.fields.open', new_callable=mock_open, read_data=b'{}')
+    @patch('cincoconfig.config.os.path.expanduser')
+    def test_include_expanduser(self, expanduser, mop):
+        field = IncludeField()
+        fmt = MockConfigFormat()
+        cfg = MockConfig()
+        expanduser.return_value = '/home/asdf/blah.txt'
+        base = {'b': 2}
 
-
-
-
+        field.combine_trees = MagicMock(return_value={'a': 1})
+        field.validate = MagicMock(return_value='blah.txt')
+        field.include(cfg, fmt, 'blah.txt', base)
+        mop.assert_called_once_with('/home/asdf/blah.txt', 'rb')
+        expanduser.assert_called_once_with('blah.txt')
diff --git a/tests/test_fields/test_net.py b/tests/test_fields/test_net.py
index 97720a2..7cebfe0 100644
--- a/tests/test_fields/test_net.py
+++ b/tests/test_fields/test_net.py
@@ -41,6 +41,24 @@ class TestIPv4NetworkField:
         with pytest.raises(ValueError):
             field.validate(MockConfig(), '300.1.2.a/42')
 
+    def test_min_prefix_good(self):
+        field = IPv4NetworkField(min_prefix_len=8)
+        assert field._validate(MockConfig(), '192.168.0.0/16') == '192.168.0.0/16'
+
+    def test_min_prefix_bad(self):
+        field = IPv4NetworkField(min_prefix_len=16)
+        with pytest.raises(ValueError):
+            field._validate(MockConfig(), '10.0.0.0/8')
+
+    def test_max_prefix_good(self):
+        field = IPv4NetworkField(max_prefix_len=16)
+        assert field._validate(MockConfig(), '10.0.0.0/8') == '10.0.0.0/8'
+
+    def test_max_prefix_bad(self):
+        field = IPv4NetworkField(max_prefix_len=31)
+        with pytest.raises(ValueError):
+            field._validate(MockConfig(), '10.10.10.1/32')
+
 
 class TestHostnameField:
 

IPv4Network min/max prefix length
Implement options for validating an IPv4 network with a minimum and maximum prefix length. For example, these options could be used to filter out single IP addresses (`max_prefix_length = 31`) and filter out class A networks (`min_prefix_length = 9`).
tests/test_config.py::TestConfig::test_save_expanduser tests/test_config.py::TestConfig::test_load_expanduser tests/test_fields/test_include.py::TestIncludeField::test_include_expanduser tests/test_fields/test_net.py::TestIPv4NetworkField::test_min_prefix_good tests/test_fields/test_net.py::TestIPv4NetworkField::test_min_prefix_bad tests/test_fields/test_net.py::TestIPv4NetworkField::test_max_prefix_good tests/test_fields/test_net.py::TestIPv4NetworkField::test_max_prefix_bad
tests/test_config.py::TestConfig::test_setdefault tests/test_config.py::TestConfig::test_subschema tests/test_config.py::TestConfig::test_setattr_field tests/test_config.py::TestConfig::test_setattr_dynamic tests/test_config.py::TestConfig::test_setattr_non_dynamic tests/test_config.py::TestConfig::test_setattr_config_dict tests/test_config.py::TestConfig::test_setattr_value tests/test_config.py::TestConfig::test_setattr_config_no_dict tests/test_config.py::TestConfig::test_getitem tests/test_config.py::TestConfig::test_to_tree tests/test_config.py::TestConfig::test_to_tree_include_virtual tests/test_config.py::TestConfig::test_to_tree_exclude_virtual tests/test_config.py::TestConfig::test_to_tree_empty_mask_secure tests/test_config.py::TestConfig::test_to_tree_sensitive_mask_single tests/test_config.py::TestConfig::test_to_tree_sensitive_mask_multi tests/test_config.py::TestConfig::test_to_tree_sensitive_mask_empty tests/test_config.py::TestConfig::test_dumps_to_tree_args tests/test_config.py::TestConfig::test_iter tests/test_config.py::TestConfig::test_getattr_error tests/test_config.py::TestConfig::test_getattr_dynamic tests/test_config.py::TestConfig::test_setitem tests/test_config.py::TestConfig::test_dumps tests/test_config.py::TestConfig::test_loads tests/test_config.py::TestConfig::test_load tests/test_config.py::TestConfig::test_save tests/test_config.py::TestConfig::test_version tests/test_config.py::TestConfig::test_getitem_nested tests/test_config.py::TestConfig::test_setitem_nested tests/test_config.py::TestConfig::test_include_field tests/test_config.py::TestConfig::test_nested_include tests/test_config.py::TestConfig::test_set_config tests/test_config.py::TestConfig::test_validate tests/test_config.py::TestConfig::test_load_tree_validate tests/test_config.py::TestConfig::test_validator tests/test_config.py::TestConfig::test_cmdline_args_override tests/test_config.py::TestConfig::test_cmdline_args_ocverride_single_ignore tests/test_config.py::TestConfig::test_in_flat tests/test_config.py::TestConfig::test_in_nested tests/test_config.py::TestConfig::test_not_in tests/test_config.py::TestConfig::test_in_not_config tests/test_config.py::TestConfig::test_wrap_validation_error tests/test_config.py::TestConfig::test_validation_error_str tests/test_config.py::TestConfig::test_setattr_validation_error_reraise tests/test_config.py::TestConfig::test_valdiate_wrap_validation_error tests/test_config.py::TestConfig::test_validate_reraise_validation_error tests/test_fields/test_include.py::TestIncludeField::test_combine_trees tests/test_fields/test_include.py::TestIncludeField::test_include tests/test_fields/test_net.py::TestIPv4AddressField::test_invalid_ipv4 tests/test_fields/test_net.py::TestIPv4NetworkField::test_invalid_net tests/test_fields/test_net.py::TestHostnameField::test_no_ipv4 tests/test_fields/test_net.py::TestHostnameField::test_valid_hostname_resolve tests/test_fields/test_net.py::TestHostnameField::test_valid_dnsname tests/test_fields/test_net.py::TestHostnameField::test_valid_netbios tests/test_fields/test_net.py::TestHostnameField::test_invalid_dnsname tests/test_fields/test_net.py::TestHostnameField::test_resolve_failed tests/test_fields/test_net.py::TestPortField::test_port_valid