diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3732bd736de5c83f8043b402a430e6418dc905a0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.*.swp
+
+__pycache__
+dist
+rbinstall.egg-info
diff --git a/.reviewboardrc b/.reviewboardrc
new file mode 100644
index 0000000000000000000000000000000000000000..d30b895d3bd1fe1b39dd8ac10eff9a5d75aa86f0
--- /dev/null
+++ b/.reviewboardrc
@@ -0,0 +1,6 @@
+REVIEWBOARD_URL = 'https://reviews.reviewboard.org'
+REPOSITORY = 'rbinstall'
+REPOSITORY_TYPE = 'git'
+BRANCH = 'master'
+TRACKING_BRANCH = 'origin/%s' % BRANCH
+LAND_DEST_BRANCH = BRANCH
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..fda1848eede87cd83caa6fb473daeed7f5ffa945
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Lead Developers:
+
+* Beanbag, Inc <https://www.beanbaginc.com>
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000000000000000000000000000000000000..e045008b771a17aeb604eef66aa5d50958d59343
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,5 @@
+We welcome contributions for improving the installer!
+
+Please note that we do *not* accept pull requests! Instead, every patch must go
+through a code review process on our own Review Board server at
+https://reviews.reviewboard.org/.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..bceffd3db48d566f7b81c4eb4ac87eee23e92ba4
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 2023  Beanbag, Inc.
+
+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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e3807f251ed0a4bcc8f3c5d5c1cd8c9ee42ea2ba
--- /dev/null
+++ b/README.md
@@ -0,0 +1,142 @@
+Review Board Installer
+======================
+
+The Review Board Installer, rbinstall, is designed to simplify installing
+[Review Board](https://www.reviewboard.org/) on a wide variety of Linux
+distributions.
+
+Installation can be performed with a single command:
+
+```shell
+$ curl https://install.reviewboard.org | python3
+```
+
+
+Compatibility
+-------------
+
+rbinstall requires a supported Linux system with Python 3.7 or higher.
+
+The following Linux distributions are directly supported on a default install:
+
+* Amazon Linux 2023
+* Arch Linux
+* CentOS 9 Stream
+* Debian 11 (Buster)
+* Debian 12 (Bullseye)
+* Debian 13 (Bookworm)
+* Fedora 36
+* Fedora 37
+* Fedora 39
+* Fedora 39
+* Fedora 40
+* openSUSE Tumbleweed
+* Red Hat Enterprise Linux 9
+* Rocky Linux 9
+* Ubuntu 20.04
+* Ubuntu 22.04
+* Ubuntu 23.10
+
+
+The following are known to work if you install a newer version of Python
+(see below):
+
+* Amazon Linux 2
+* openSUSE Leap 15
+* Red Hat Enterprise Linux 8
+* Rocky Linux 8
+* Ubuntu 18.04
+
+**NOTE:** If you're using a non-default version of Python, you will need to use
+a web server such as [gunicorn](https://gunicorn.org/),
+[uwsgi](https://uwsgi-docs.readthedocs.io/en/latest/), or build an Apache
+`mod_wsgi` for your server using
+[mod_wsgi-express](https://pypi.org/project/mod-wsgi/).
+
+
+Legacy Distro Notes
+-------------------
+
+### Amazon Linux 2
+
+Before installing on Amazon Linux 2, you will need to install a newer version
+of Python:
+
+```shell
+sudo amazon-linux-extras install python3.8
+sudo yum install python38-devel
+```
+
+Then run the installation script with `python3.8`.
+
+Please note that Python 3.8 reaches end-of-life on October 14, 2024. Versions
+of Review Board after this date may no longer support Python 3.8.
+
+
+### openSUSE Leap 15
+
+Before installing on openSUSE Leap 15, you will need to install a newer version
+of Python:
+
+```shell
+sudo zypper install python39 python39-devel
+```
+
+Then run the installation script with `python3.9`.
+
+
+### Red Hat Enterprise Linux 8
+
+Before installing on Red Hat Enterprise Linux 8, you will need to install a newer version
+of Python:
+
+```shell
+sudo yum install -y python38 python38-devel
+```
+
+Then run the installation script with `python3.8`.
+
+Note that due to missing packages, Single Sign-On is not available on
+Red Hat Enterprise Linux 8.
+
+Please note that Python 3.8 reaches end-of-life on October 14, 2024. Versions
+of Review Board after this date may no longer support Python 3.8.
+
+
+### Rocky Linux 8
+
+Before installing on Rocky Linux 8, you will need to install a newer version
+of Python:
+
+```shell
+sudo dnf module install python38
+sudo dnf install python38-devel
+```
+
+Then run the installation script with `python3.8`.
+
+Note that due to missing packages, Single Sign-On is not available on
+Rocky Linux 8.
+
+Please note that Python 3.8 reaches end-of-life on October 14, 2024. Versions
+of Review Board after this date may no longer support Python 3.8.
+
+
+### Ubuntu 18.04
+
+Before installing on Ubuntu 18.04, you will need to install a newer version
+of Python:
+
+```shell
+sudo apt-get install software-properties-common
+sudo add-apt-repository ppa:deadsnakes/ppa
+sudo apt-get install python3.8 python3.8-dev python3.8-venv
+```
+
+Then run the installation script with `python3.8`.
+
+Note that due to missing packages, Single Sign-On is not available on
+Ubuntu 18.04.
+
+Please note that Python 3.8 reaches end-of-life on October 14, 2024. Versions
+of Review Board after this date may no longer support Python 3.8.
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..b175162abe757a6ebcbff100a7a421a7a1e325e7
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,61 @@
+[build-system]
+requires = ['setuptools>=61.0']
+build-backend = 'setuptools.build_meta'
+
+[project]
+name = 'rbinstall'
+description = 'Official installer for Review Board code/document review.'
+authors = [
+    {name='Beanbag, Inc.', email='questions@beanbaginc.com'},
+]
+license = {file='LICENSE'}
+readme = {file='README.md', content-type='text/markdown'}
+
+dynamic = ['version']
+
+requires-python = '>=3.7'
+dependencies = [
+    'typing_extensions>=4.3.0',
+    'virtualenv',
+]
+
+classifiers = [
+    'Development Status :: 5 - Production/Stable',
+    'Environment :: Console',
+    'Intended Audience :: Developers',
+    'Intended Audience :: System Administrators',
+    'License :: OSI Approved :: MIT License',
+    'Operating System :: MacOS',
+    'Operating System :: MacOS :: MacOS X',
+    'Operating System :: POSIX :: Linux',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 3',
+    'Programming Language :: Python :: 3.7',
+    'Programming Language :: Python :: 3.8',
+    'Programming Language :: Python :: 3.9',
+    'Programming Language :: Python :: 3.10',
+    'Programming Language :: Python :: 3.11',
+    'Programming Language :: Python :: 3.12',
+    'Topic :: System',
+    'Topic :: System :: Installation/Setup',
+    'Topic :: System :: Software Distribution',
+    'Topic :: System :: System Administration',
+]
+
+
+[project.urls]
+homepage = 'https://github.com/reviewboard/rbinstall'
+documentation = 'https://github.com/reviewboard/rbinstall'
+repository = 'https://github.com/reviewboard/rbinstall'
+
+
+[project.scripts]
+rbinstall = 'rbinstall.main:main'
+
+
+[tool.setuptools]
+packages = ['rbinstall']
+
+
+[tool.setuptools.dynamic]
+version = {attr = 'rbinstall.__version__'}
diff --git a/rbinstall/__init__.py b/rbinstall/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1b93dcccf9bc9374db7d2c9467c85b99b6d184df
--- /dev/null
+++ b/rbinstall/__init__.py
@@ -0,0 +1,84 @@
+"""Review Board Installer version and package information.
+
+These variables and functions can be used to identify the version of the
+Review Board Installer. They're largely used for packaging purposes.
+"""
+
+#: The version of the Review Board installer.
+#:
+#: This is in the format of:
+#:
+#: (Major, Minor, Micro, Patch, alpha/beta/rc/final, Release Number, Released)
+#:
+VERSION = (1, 0, 0, 0, 'alpha', 0, False)
+
+
+def get_version_string() -> str:
+    """Return the version as a human-readable string.
+
+    Returns:
+        str:
+        The installer version.
+    """
+    major, minor, micro, patch, tag, relnum, is_release = VERSION
+
+    version = f'{major}.{minor}'
+
+    if micro or patch:
+        version = f'{version}.{micro}'
+
+        if patch:
+            version = f'{version}.{patch}'
+
+    if tag != 'final':
+        if tag == 'rc':
+            version = f'{version} RC{relnum}'
+        else:
+            version = f'{version} {tag} {relnum}'
+
+    if not is_release:
+        version = f'{version} (dev)'
+
+    return version
+
+
+def get_package_version() -> str:
+    """Return the version as a Python package version string.
+
+    Returns:
+        str:
+        The version number as used in a Python package.
+    """
+    major, minor, micro, patch, tag, relnum = __version_info__
+
+    version = f'{major}.{minor}'
+
+    if micro or patch:
+        version = f'{version}.{micro}'
+
+        if patch:
+            version = f'{version}.{patch}'
+
+    if tag != 'final':
+        norm_tag = {
+            'alpha': 'a',
+            'beta': 'b',
+        }.get(tag, tag)
+        version = f'{version}{norm_tag}{relnum}'
+
+    return version
+
+
+def is_release() -> bool:
+    """Return whether this is a released version.
+
+    Returns:
+        bool:
+        ``True`` if this is a released version of the package.
+        ``False`` if it is a development version.
+    """
+    return VERSION[-1]
+
+
+__version_info__ = VERSION[:-1]
+__version__ = get_package_version()
diff --git a/rbinstall/main.py b/rbinstall/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..b0381a40bfdf616ab79bf041dc6dd2cb87d100ea
--- /dev/null
+++ b/rbinstall/main.py
@@ -0,0 +1,9 @@
+# NOTE: This file must be syntactically compatible with Python 3.7+.
+from __future__ import annotations
+
+import sys
+
+
+def main() -> None:
+    """Main entry point for the installer."""
+    sys.exit(1)
