diff --git a/pygeoapi/api.py b/pygeoapi/api.py
index 250e21e..1915472 100644
--- a/pygeoapi/api.py
+++ b/pygeoapi/api.py
@@ -997,7 +997,7 @@ def to_json(dict_):
     :returns: JSON string representation
     """
 
-    return json.dumps(dict_, default=json_serial)
+    return json.dumps(dict_)
 
 
 def _render_j2_template(config, template, data):
diff --git a/pygeoapi/util.py b/pygeoapi/util.py
index fe37953..7d8b331 100644
--- a/pygeoapi/util.py
+++ b/pygeoapi/util.py
@@ -2,7 +2,7 @@
 #
 # Authors: Tom Kralidis <tomkralidis@gmail.com>
 #
-# Copyright (c) 2018 Tom Kralidis
+# Copyright (c) 2019 Tom Kralidis
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -32,27 +32,34 @@
 from datetime import date, datetime, time
 from decimal import Decimal
 import logging
+import os
+import re
 
 import yaml
 
 LOGGER = logging.getLogger(__name__)
 
 
-def get_url(scheme, host, port, basepath):
+def get_typed_value(value):
     """
-    Provides URL of instance
+    Derive true type from data value
 
-    :returns: string of complete baseurl
-    """
-
-    url = '{}://{}'.format(scheme, host)
+    :param value: value
 
-    if port not in [80, 443]:
-        url = '{}:{}'.format(url, port)
+    :returns: value as a native Python data type
+    """
 
-    url = '{}{}'.format(url, basepath)
+    try:
+        if '.' in value:  # float?
+            value2 = float(value)
+        elif len(value) > 1 and value.startswith('0'):
+            value2 = value
+        else:  # int?
+            value2 = int(value)
+    except ValueError:  # string (default)?
+        value2 = value
 
-    return url
+    return value2
 
 
 def yaml_load(fh):
@@ -64,11 +71,23 @@ def yaml_load(fh):
     :returns: `dict` representation of YAML
     """
 
-    try:
-        return yaml.load(fh, Loader=yaml.FullLoader)
-    except AttributeError as err:
-        LOGGER.warning('YAML loading error: {}'.format(err))
-        return yaml.load(fh)
+    # support environment variables in config
+    # https://stackoverflow.com/a/55301129
+    path_matcher = re.compile(r'.*\$\{([^}^{]+)\}.*')
+
+    def path_constructor(loader, node):
+        env_var = path_matcher.match(node.value).group(1)
+        if env_var not in os.environ:
+            raise EnvironmentError('Undefined environment variable in config')
+        return get_typed_value(os.path.expandvars(node.value))
+
+    class EnvVarLoader(yaml.SafeLoader):
+        pass
+
+    EnvVarLoader.add_implicit_resolver('!path', path_matcher, None)
+    EnvVarLoader.add_constructor('!path', path_constructor)
+
+    return yaml.load(fh, Loader=EnvVarLoader)
 
 
 def str2bool(value):
@@ -100,8 +119,7 @@ def json_serial(obj):
     """
 
     if isinstance(obj, (datetime, date, time)):
-        serial = obj.isoformat()
-        return serial
+        return obj.isoformat()
     elif isinstance(obj, Decimal):
         return float(obj)
 

implement env variables inside PYGEOAPI_CONFIG file
**Is your feature request related to a problem? Please describe.**

devop systems (docker, k8) use enviroment variable to set parameters like database connections of  set passwords inside containers. 

For example running pygeopai in openshift and we want to connect to a database that has a secret password. Currentely we would have to set the password on the yaml configuration file and this could  be a security problem, while openshift can set the secret env inside the pod from a secure source  

**Describe the solution you'd like**
Parse the PYGEOAPI_CONFIG yaml file with python module envyaml
(https://github.com/thesimj/envyaml). The current default module yaml should be replaced by envyaml as parser allowing for env variables to be injected into the yaml file

**Describe alternatives you've considered**
The dataprovider would get the env variables by it self, IMHO this is less elegant and we may need the described solutions for other configurations

**Additional context**
Add any other context or screenshots about the feature request here.
![image](https://user-images.githubusercontent.com/1275400/65626708-2cd62700-dfce-11e9-9926-ae7e1a193b31.png)


diff --git a/tests/pygeoapi-test-config-envvars.yml b/tests/pygeoapi-test-config-envvars.yml
new file mode 100644
index 0000000..717f94f
--- /dev/null
+++ b/tests/pygeoapi-test-config-envvars.yml
@@ -0,0 +1,120 @@
+# =================================================================
+#
+# Authors: Tom Kralidis <tomkralidis@gmail.com>
+#
+# Copyright (c) 2019 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+server:
+    bind:
+        host: 0.0.0.0
+        port: ${PYGEOAPI_PORT}
+    url: http://localhost:5000/
+    mimetype: application/json; charset=UTF-8
+    encoding: utf-8
+    language: en-US
+    cors: true
+    pretty_print: true
+    limit: 10
+    # templates: /path/to/templates
+    map:
+        url: https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png
+        attribution: '<a href="https://wikimediafoundation.org/wiki/Maps_Terms_of_Use">Wikimedia maps</a> | Map data &copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
+
+logging:
+    level: ERROR
+    #logfile: /tmp/pygeoapi.log
+
+metadata:
+    identification:
+        title: pygeoapi default instance ${PYGEOAPI_TITLE}
+        description: pygeoapi provides an API to geospatial data
+        keywords:
+            - geospatial
+            - data
+            - api
+        keywords_type: theme
+        terms_of_service: None
+        url: http://example.org
+    license:
+        name: CC-BY 4.0 license
+        url: https://creativecommons.org/licenses/by/4.0/
+    provider:
+        name: Organization Name
+        url: https://pygeoapi.io
+    contact:
+        name: Lastname, Firstname
+        position: Position Title
+        address: Mailing Address
+        city: City
+        stateorprovince: Administrative Area
+        postalcode: Zip or Postal Code
+        country: Country
+        phone: +xx-xxx-xxx-xxxx
+        fax: +xx-xxx-xxx-xxxx
+        email: you@example.org
+        url: Contact URL
+        hours: Hours of Service
+        instructions: During hours of service.  Off on weekends.
+        role: pointOfContact
+
+datasets:
+    obs:
+        title: Observations
+        description: My cool observations
+        keywords:
+            - observations
+            - monitoring
+        links:
+            - type: text/csv
+              rel: canonical
+              title: data
+              href: https://github.com/mapserver/mapserver/blob/branch-7-0/msautotest/wxs/data/obs.csv
+              hreflang: en-US
+            - type: text/csv
+              rel: alternate
+              title: data
+              href: https://raw.githubusercontent.com/mapserver/mapserver/branch-7-0/msautotest/wxs/data/obs.csv
+              hreflang: en-US
+        extents:
+            spatial:
+                bbox: [-180,-90,180,90]
+                crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+            temporal:
+                begin: 2000-10-30T18:24:39Z
+                end: 2007-10-30T08:57:29Z
+                trs: http://www.opengis.net/def/uom/ISO-8601/0/Gregorian
+        provider:
+            name: CSV
+            data: tests/data/obs.csv
+            id_field: id
+            geometry:
+                x_field: long
+                y_field: lat
+
+processes:
+    hello-world:
+        processor:
+            name: HelloWorld
diff --git a/tests/test_config.py b/tests/test_config.py
new file mode 100644
index 0000000..7d2b455
--- /dev/null
+++ b/tests/test_config.py
@@ -0,0 +1,62 @@
+# =================================================================
+#
+# Authors: Tom Kralidis <tomkralidis@gmail.com>
+#
+# Copyright (c) 2019 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+import os
+
+import pytest
+
+from pygeoapi.util import yaml_load
+
+
+def get_test_file_path(filename):
+    """helper function to open test file safely"""
+
+    if os.path.isfile(filename):
+        return filename
+    else:
+        return 'tests/{}'.format(filename)
+
+
+def test_config_envvars():
+    os.environ['PYGEOAPI_PORT'] = '5001'
+    os.environ['PYGEOAPI_TITLE'] = 'my title'
+
+    with open(get_test_file_path('pygeoapi-test-config-envvars.yml')) as fh:
+        config = yaml_load(fh)
+
+    assert isinstance(config, dict)
+    assert config['server']['bind']['port'] == 5001
+    assert config['metadata']['identification']['title'] == \
+        'pygeoapi default instance my title'
+
+    os.environ.pop('PYGEOAPI_PORT')
+
+    with pytest.raises(EnvironmentError):
+        with open(get_test_file_path('pygeoapi-test-config-envvars.yml')) as fh:  # noqa
+            config = yaml_load(fh)
diff --git a/tests/test_util.py b/tests/test_util.py
new file mode 100644
index 0000000..f4b8aca
--- /dev/null
+++ b/tests/test_util.py
@@ -0,0 +1,98 @@
+# =================================================================
+#
+# Authors: Tom Kralidis <tomkralidis@gmail.com>
+#
+# Copyright (c) 2019 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+from datetime import datetime, date, time
+from decimal import Decimal
+import os
+
+import pytest
+
+from pygeoapi import util
+
+
+def get_test_file_path(filename):
+    """helper function to open test file safely"""
+
+    if os.path.isfile(filename):
+        return filename
+    else:
+        return 'tests/{}'.format(filename)
+
+
+def test_get_typed_value():
+    value = util.get_typed_value('2')
+    assert isinstance(value, int)
+
+    value = util.get_typed_value('1.2')
+    assert isinstance(value, float)
+
+    value = util.get_typed_value('1.c2')
+    assert isinstance(value, str)
+
+
+def test_yaml_load():
+    with open(get_test_file_path('pygeoapi-test-config.yml')) as fh:
+        d = util.yaml_load(fh)
+        assert isinstance(d, dict)
+    with pytest.raises(FileNotFoundError):
+        with open(get_test_file_path('404.yml')) as fh:
+            d = util.yaml_load(fh)
+
+
+def test_str2bool():
+    assert util.str2bool(False) is False
+    assert util.str2bool('0') is False
+    assert util.str2bool('no') is False
+    assert util.str2bool('yes') is True
+    assert util.str2bool('1') is True
+    assert util.str2bool(True) is True
+    assert util.str2bool('true') is True
+    assert util.str2bool('True') is True
+    assert util.str2bool('TRUE') is True
+    assert util.str2bool('tRuE') is True
+    assert util.str2bool('on') is True
+    assert util.str2bool('On') is True
+    assert util.str2bool('off') is False
+
+
+def test_json_serial():
+    d = datetime(1972, 10, 30)
+    assert util.json_serial(d) == '1972-10-30T00:00:00'
+
+    d = date(2010, 7, 31)
+    assert util.json_serial(d) == '2010-07-31'
+
+    d = time(11)
+    assert util.json_serial(d) == '11:00:00'
+
+    d = Decimal(1.0)
+    assert util.json_serial(d) == 1.0
+
+    with pytest.raises(TypeError):
+        util.json_serial('foo')

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.7
requirements.txt requirements-dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
Babel==2.14.0
bleach==6.0.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
charset-normalizer==3.4.1
click==8.1.8
coverage==7.2.7
cryptography==44.0.2
docutils==0.17.1
exceptiongroup==1.2.2
flake8==5.0.4
Flask==2.2.5
Flask-Cors==5.0.0
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==2.0.0
itsdangerous==2.1.2
jaraco.classes==3.2.3
jeepney==0.9.0
Jinja2==3.1.6
keyring==23.9.3
markdown-it-py==2.2.0
MarkupSafe==2.1.5
mccabe==0.7.0
mdurl==0.1.2
more-itertools==9.1.0
ndg-httpsclient==0.5.1
packaging==24.0
pkginfo==1.10.0
pluggy==1.2.0
pyasn1==0.5.1
pycodestyle==2.9.1
pycparser==2.21
pyflakes==2.5.0
-e git+https://github.com/geopython/pygeoapi.git@c8d0f1b5128d13306bf2db147faaea120a53ae16#egg=pygeoapi
Pygments==2.17.2
pyOpenSSL==25.0.0
pytest==7.4.4
pytest-cov==4.1.0
pytest-env==1.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.1
readme-renderer==37.3
requests==2.31.0
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==13.8.1
SecretStorage==3.3.3
six==1.17.0
snowballstemmer==2.2.0
Sphinx==4.3.2
sphinx-rtd-theme==1.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==2.0.1
twine==4.0.2
typing_extensions==4.7.1
unicodecsv==0.14.1
urllib3==2.0.7
webencodings==0.5.1
Werkzeug==2.2.3
zipp==3.15.0

name: pygeoapi
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - babel==2.14.0
      - bleach==6.0.0
      - cffi==1.15.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - coverage==7.2.7
      - cryptography==44.0.2
      - docutils==0.17.1
      - exceptiongroup==1.2.2
      - flake8==5.0.4
      - flask==2.2.5
      - flask-cors==5.0.0
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - itsdangerous==2.1.2
      - jaraco-classes==3.2.3
      - jeepney==0.9.0
      - jinja2==3.1.6
      - keyring==23.9.3
      - markdown-it-py==2.2.0
      - markupsafe==2.1.5
      - mccabe==0.7.0
      - mdurl==0.1.2
      - more-itertools==9.1.0
      - ndg-httpsclient==0.5.1
      - packaging==24.0
      - pkginfo==1.10.0
      - pluggy==1.2.0
      - pyasn1==0.5.1
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pyopenssl==25.0.0
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-env==1.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.1
      - readme-renderer==37.3
      - requests==2.31.0
      - requests-toolbelt==1.0.0
      - rfc3986==2.0.0
      - rich==13.8.1
      - secretstorage==3.3.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==4.3.2
      - sphinx-rtd-theme==1.3.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==2.0.1
      - twine==4.0.2
      - typing-extensions==4.7.1
      - unicodecsv==0.14.1
      - urllib3==2.0.7
      - webencodings==0.5.1
      - werkzeug==2.2.3
      - zipp==3.15.0
prefix: /opt/conda/envs/pygeoapi

tests/test_config.py::test_config_envvars tests/test_util.py::test_get_typed_value
tests/test_util.py::test_yaml_load tests/test_util.py::test_str2bool tests/test_util.py::test_json_serial
pygeoapi/api.py pygeoapi/util.py
pygeoapi/api.py pygeoapi/util.py