diff --git a/.zuul.yaml b/.zuul.yaml
index f02c828a..a3d4d586 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -87,20 +87,24 @@
             timeout: 6000
         - storyboard-tox-sqlite
         - tox-pep8
-        - tox-py27:
-            timeout: 6000
         - tox-py36:
             timeout: 6000
+        - tox-py37:
+            timeout: 6000
+        - tox-py38:
+            timeout: 6000
         - opendev-buildset-registry
         - storyboard-build-opendev-image
     gate:
       jobs:
         - storyboard-tox-sqlite
         - tox-pep8
-        - tox-py27:
-            timeout: 6000
         - tox-py36:
             timeout: 6000
+        - tox-py37:
+            timeout: 6000
+        - tox-py38:
+            timeout: 6000
         - opendev-buildset-registry
         - storyboard-upload-opendev-image
     post:
diff --git a/doc/source/contribute/contributing.rst b/doc/source/contribute/contributing.rst
index f6d3716d..bec2ae08 100644
--- a/doc/source/contribute/contributing.rst
+++ b/doc/source/contribute/contributing.rst
@@ -81,10 +81,10 @@ And to run the style-checker and static analysis tool::
 
   $ tox -e pep8
 
-If you would like to run the test suite with proper database backends or
-with python2 instead of python3 there is one more step to follow. Note
-that the testsuite takes quite a bit longer to run when using the MySQL
-and PostgreSQL database backends.
+If you would like to run the test suite with proper database backends
+there is one more step to follow. Note that the testsuite takes quite
+a bit longer to run when using the MySQL and PostgreSQL database
+backends.
 
 First ensure MySQL and PostgreSQL are running (you may need to start
 these services). Then run the test-setup.sh helper script::
@@ -95,18 +95,14 @@ This script needs to be run with a user that has sudo access. It will
 configure the databases as needed to run the unittests. You can then
 runt the unittests with::
 
-  $ tox -e py27
-
-or for Python 3::
-
-  $ tox -e py35
+  $ tox -e py3
 
 On slower systems, the database migrations may take longer than the
 default timeout of 120 seconds. To override the timeout, set the
 ``OS_TEST_TIMEOUT`` environment variable. For example, to set the
 timeout to 3 minutes, run::
 
-  $ OS_TEST_TIMEOUT=180 tox -e py27
+  $ OS_TEST_TIMEOUT=180 tox -e py3
 
 For More Extensive Testing...
 -------------------------------
diff --git a/requirements.txt b/requirements.txt
index 253f48c6..11ac6f2e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,8 +11,7 @@ pecan>=0.4.5
 oslo.db>=4.27.0  # Apache-2.0
 oslo.log>=1.0.0
 pika>=0.9.14
-python-openid ; python_version < '3.0'
-python3-openid ; python_version >= '3.0'
+python3-openid
 PyYAML>=3.1.0
 requests>=1.1
 six>=1.7.0
@@ -22,7 +21,6 @@ WSME>=0.6,<0.8
 SQLAlchemy-FullText-Search>=0.2.3
 stevedore>=1.3.0
 tzlocal>=1.1.2
-email>=4.0.2;python_version<'3.0'
 Jinja2>=2.7.3
 PyMySQL>=0.6.2,!=0.6.4
 apscheduler>=3.0.1,<3.1.0
diff --git a/setup.cfg b/setup.cfg
index 1f08f3cd..b0bb36dc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -12,6 +12,7 @@ project_urls =
     Bug Reporting = https://storyboard.openstack.org/#!/project/opendev/storyboard
     Documentation = https://docs.openstack.org/infra/storyboard
     Git Clone URL = https://opendev.org/opendev/storyboard
+python_requires = >=3.6
 classifier =
     Environment :: Web Environment
     Intended Audience :: Developers
@@ -21,9 +22,11 @@ classifier =
     Operating System :: OS Independent
     Operating System :: POSIX :: Linux
     Programming Language :: Python
-    Programming Language :: Python :: 2.7
     Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.5
+    Programming Language :: Python :: 3.6
+    Programming Language :: Python :: 3.7
+    Programming Language :: Python :: 3.8
+    Programming Language :: Python :: 3 :: Only
     Topic :: Software Development :: Bug Tracking
 
 [files]
@@ -49,9 +52,6 @@ storyboard.plugin.user_preferences =
 storyboard.plugin.scheduler =
     token-cleaner = storyboard.plugin.token_cleaner.cleaner:TokenCleaner
 
-[wheel]
-universal = 1
-
 [build_sphinx]
 warning-is-error = 1
 source-dir = doc/source
diff --git a/setup.py b/setup.py
index 44a94320..6ba21910 100755
--- a/setup.py
+++ b/setup.py
@@ -16,14 +16,6 @@
 # This file was pulled from the openstack global requirements repo.
 import setuptools
 
-# In python < 2.7.4, a lazy loading of package `pbr` will break
-# setuptools if some other modules registered functions in `atexit`.
-# solution from: http://bugs.python.org/issue15881#msg170215
-try:
-    import multiprocessing  # noqa
-except ImportError:
-    pass
-
 setuptools.setup(
     setup_requires=['pbr>=5'],
     pbr=True)
diff --git a/tox.ini b/tox.ini
index 4d1d81ee..d8ff4b6a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,10 @@
 [tox]
 minversion = 2.9.1
 skipsdist = True
-envlist = py35,py27,pep8
+envlist = py3,pep8
 
 [testenv]
+basepython = python3
 usedevelop = True
 install_command = pip install -U {opts} {packages}
 passenv = OS_* STORYBOARD_*
@@ -19,21 +20,17 @@ commands = stestr run {posargs}
 whitelist_externals = bash
 
 [testenv:sqlite]
-basepython = python3
 setenv =
     {[testenv]setenv}
     STORYBOARD_TEST_DB=sqlite:///{envtmpdir}
 
 [testenv:pep8]
-basepython = python3
 commands = flake8
 
 [testenv:venv]
-basepython = python3
 commands = {posargs}
 
 [testenv:docs]
-basepython = python3
 deps = -r{toxinidir}/doc/requirements.txt
 commands =
     rm -rf doc/html doc/build
@@ -42,7 +39,6 @@ commands =
 whitelist_externals = rm
 
 [testenv:cover]
-basepython = python3
 setenv =
     {[testenv]setenv}
     PYTHON=coverage run --source storyboard --parallel-mode
@@ -64,7 +60,6 @@ show-source = True
 exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
 
 [testenv:bindep]
-basepython = python3
 # Do not install any requirements. We want this to be fast and work even if
 # system dependencies are missing, since it's used to tell you what system
 # dependencies are missing! This also means that bindep must be installed
@@ -73,7 +68,6 @@ deps = bindep
 commands = bindep test
 
 [testenv:lpimport]
-basepython = python3
 # The Launchpad bug import tool uses launchpadlib, which is not a typical
 # runtime dependency of anything else in StoryBoard
 deps = launchpadlib