diff --git a/.gitignore b/.gitignore
index ad21e45bc3f..dac19098747 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,3 +101,7 @@ typings/
.vscode
.vercel
+
+#include template .env file for docker-compose
+!docker/supabase/.env
+!docker/supabase-traefik/.env
diff --git a/docker/config/pgadmin/config.py b/docker/config/pgadmin/config.py
new file mode 100644
index 00000000000..97cc61a3f17
--- /dev/null
+++ b/docker/config/pgadmin/config.py
@@ -0,0 +1,675 @@
+# -*- coding: utf-8 -*-
+
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2021, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# config.py - Core application configuration settings
+#
+##########################################################################
+
+import builtins
+import logging
+import os
+import sys
+
+# We need to include the root directory in sys.path to ensure that we can
+# find everything we need when running in the standalone runtime.
+root = os.path.dirname(os.path.realpath(__file__))
+if sys.path[0] != root:
+ sys.path.insert(0, root)
+
+from pgadmin.utils import env, IS_WIN, fs_short_path
+
+##########################################################################
+# Application settings
+##########################################################################
+
+# Name of the application to display in the UI
+APP_NAME = 'pgAdmin 4'
+APP_ICON = 'pg-icon'
+
+##########################################################################
+# Application settings
+##########################################################################
+
+# NOTE!!!
+# If you change any of APP_RELEASE, APP_REVISION or APP_SUFFIX, then you
+# must also change APP_VERSION_INT to match.
+#
+
+# Application version number components
+APP_RELEASE = 5
+APP_REVISION = 2
+
+# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
+# for GA releases.
+APP_SUFFIX = ''
+
+# Numeric application version for upgrade checks. Should be in the format:
+# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
+# zero if needed, and Z represents the suffix, with a leading zero if needed
+APP_VERSION_INT = 50200
+
+# DO NOT CHANGE!
+# The application version string, constructed from the components
+if not APP_SUFFIX:
+ APP_VERSION = '%s.%s' % (APP_RELEASE, APP_REVISION)
+else:
+ APP_VERSION = '%s.%s-%s' % (APP_RELEASE, APP_REVISION, APP_SUFFIX)
+
+# Copyright string for display in the app
+APP_COPYRIGHT = 'Copyright (C) 2013 - 2021, The pgAdmin Development Team'
+
+##########################################################################
+# Misc stuff
+##########################################################################
+
+# Path to the online help.
+HELP_PATH = '../../../docs/en_US/_build/html/'
+
+# Languages we support in the UI
+LANGUAGES = {
+ 'en': 'English',
+ 'zh': 'Chinese (Simplified)',
+ 'cs': 'Czech',
+ 'fr': 'French',
+ 'de': 'German',
+ 'it': 'Italian',
+ 'ja': 'Japanese',
+ 'ko': 'Korean',
+ 'pl': 'Polish',
+ 'ru': 'Russian',
+ 'es': 'Spanish',
+}
+
+# DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING!
+# List of modules to skip when dynamically loading
+MODULE_BLACKLIST = ['test']
+
+# DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING!
+# List of treeview browser nodes to skip when dynamically loading
+NODE_BLACKLIST = []
+
+##########################################################################
+# Server settings
+##########################################################################
+
+# The server mode determines whether or not we're running on a web server
+# requiring user authentication, or desktop mode which uses an automatic
+# default login.
+#
+# DO NOT DISABLE SERVER MODE IF RUNNING ON A WEBSERVER!!
+#
+# We only set SERVER_MODE if it's not already set. That's to allow the
+# runtime to force it to False.
+#
+# NOTE: If you change the value of SERVER_MODE in an included config file,
+# you may also need to redefine any values below that are derived
+# from it, notably various paths such as LOG_FILE and anything
+# using DATA_DIR.
+
+if (not hasattr(builtins, 'SERVER_MODE')) or builtins.SERVER_MODE is None:
+ SERVER_MODE = True
+else:
+ SERVER_MODE = builtins.SERVER_MODE
+
+# HTTP headers to search for CSRF token when it is not provided in the form.
+# Default is ['X-CSRFToken', 'X-CSRF-Token']
+WTF_CSRF_HEADERS = ['X-pgA-CSRFToken']
+
+# User ID (email address) to use for the default user in desktop mode.
+# The default should be fine here, as it's not exposed in the app.
+DESKTOP_USER = 'pgadmin4@pgadmin.org'
+
+# This option allows the user to host the application on a LAN
+# Default hosting is on localhost (DEFAULT_SERVER='localhost').
+# To host pgAdmin4 over LAN set DEFAULT_SERVER='0.0.0.0' (or a specific
+# adaptor address.
+#
+# NOTE: This is NOT recommended for production use, only for debugging
+# or testing. Production installations should be run as a WSGI application
+# behind Apache HTTPD.
+DEFAULT_SERVER = '127.0.0.1'
+
+# The default port on which the app server will listen if not set in the
+# environment by the runtime
+DEFAULT_SERVER_PORT = 5050
+
+# This param is used to override the default web server information about
+# the web technology and the frameworks being used in the application
+# An attacker could use this information to fingerprint underlying operating
+# system and research known exploits for the specific version of
+# software in use
+WEB_SERVER = 'Python'
+
+# Enable X-Frame-Option protection.
+# Set to one of "SAMEORIGIN", "ALLOW-FROM origin" or "" to disable.
+# Note that "DENY" is NOT supported (and will be silently ignored).
+# See https://tools.ietf.org/html/rfc7034 for more info.
+X_FRAME_OPTIONS = "SAMEORIGIN"
+
+# The Content-Security-Policy header allows you to restrict how resources
+# such as JavaScript, CSS, or pretty much anything that the browser loads.
+# see https://content-security-policy.com/#source_list for more info
+# e.g. "default-src https: data: 'unsafe-inline' 'unsafe-eval';"
+CONTENT_SECURITY_POLICY = "default-src http: data: blob: 'unsafe-inline' " \
+ "'unsafe-eval';"
+
+# STRICT_TRANSPORT_SECURITY_ENABLED when set to True will set the
+# Strict-Transport-Security header
+STRICT_TRANSPORT_SECURITY_ENABLED = False
+
+# The Strict-Transport-Security header tells the browser to convert all HTTP
+# requests to HTTPS, preventing man-in-the-middle (MITM) attacks.
+# e.g. 'max-age=31536000; includeSubDomains'
+STRICT_TRANSPORT_SECURITY = "max-age=31536000; includeSubDomains"
+
+# The X-Content-Type-Options header forces the browser to honor the response
+# content type instead of trying to detect it, which can be abused to
+# generate a cross-site scripting (XSS) attack.
+# e.g. nosniff
+X_CONTENT_TYPE_OPTIONS = "nosniff"
+
+# The browser will try to prevent reflected XSS attacks by not loading the
+# page if the request contains something that looks like JavaScript and the
+# response contains the same data. e.g. '1; mode=block'
+X_XSS_PROTECTION = "1; mode=block"
+
+# This param is used to validate ALLOWED_HOSTS for the application
+# This will be used to avoid Host Header Injection attack
+# ALLOWED_HOSTS = ['225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6']
+# ALLOWED_HOSTS = ['127.0.0.1', '192.168.0.1']
+# if ALLOWED_HOSTS= [] then it will accept all ips (and application will be
+# vulnerable to Host Header Injection attack)
+ALLOWED_HOSTS = []
+
+# Hashing algorithm used for password storage
+SECURITY_PASSWORD_HASH = 'pbkdf2_sha512'
+
+# Reverse Proxy parameters
+# You must tell the middleware how many proxies set each header
+# so it knows what values to trust.
+# See https://tinyurl.com/yyg7r9av
+# for more information.
+
+# Number of values to trust for X-Forwarded-For
+PROXY_X_FOR_COUNT = 1
+
+# Number of values to trust for X-Forwarded-Proto.
+PROXY_X_PROTO_COUNT = 1
+
+# Number of values to trust for X-Forwarded-Host.
+PROXY_X_HOST_COUNT = 0
+
+# Number of values to trust for X-Forwarded-Port.
+PROXY_X_PORT_COUNT = 1
+
+# Number of values to trust for X-Forwarded-Prefix.
+PROXY_X_PREFIX_COUNT = 0
+
+# NOTE: CSRF_SESSION_KEY, SECRET_KEY and SECURITY_PASSWORD_SALT are no
+# longer part of the main configuration, but are stored in the
+# configuration databases 'keys' table and are auto-generated.
+
+# COMPRESSION
+COMPRESS_MIMETYPES = [
+ 'text/html', 'text/css', 'text/xml', 'application/json',
+ 'application/javascript'
+]
+COMPRESS_LEVEL = 9
+COMPRESS_MIN_SIZE = 500
+
+# Set the cache control max age for static files in flask to 1 year
+SEND_FILE_MAX_AGE_DEFAULT = 31556952
+
+# This will be added to static urls as url parameter with value as
+# APP_VERSION_INT for cache busting on version upgrade. If the value is set as
+# None or empty string then it will not be added.
+# eg - http:localhost:5050/pgadmin.css?intver=3.13
+APP_VERSION_PARAM = 'ver'
+
+# Add the internal version param to below extensions only
+APP_VERSION_EXTN = ('.css', '.js', '.html', '.svg', '.png', '.gif', '.ico')
+
+# Data directory for storage of config settings etc. This shouldn't normally
+# need to be changed - it's here as various other settings depend on it.
+# On Windows, we always store data in %APPDATA%\pgAdmin. On other platforms,
+# if we're in server mode we use /var/lib/pgadmin, otherwise ~/.pgadmin
+if IS_WIN:
+ # Use the short path on windows
+ DATA_DIR = os.path.realpath(
+ os.path.join(fs_short_path(env('APPDATA')), "pgAdmin")
+ )
+else:
+ if SERVER_MODE:
+ DATA_DIR = '/var/lib/pgadmin'
+ else:
+ DATA_DIR = os.path.realpath(os.path.expanduser('~/.pgadmin/'))
+
+# An optional login banner to show security warnings/disclaimers etc. at
+# login and password recovery etc. HTML may be included for basic formatting,
+# For example:
+# LOGIN_BANNER = "
Authorised Users Only!
" \
+# "Unauthorised use is strictly forbidden."
+LOGIN_BANNER = ""
+
+##########################################################################
+# Log settings
+##########################################################################
+
+# Debug mode?
+DEBUG = False
+
+# Application log level - one of:
+# CRITICAL 50
+# ERROR 40
+# WARNING 30
+# SQL 25
+# INFO 20
+# DEBUG 10
+# NOTSET 0
+CONSOLE_LOG_LEVEL = logging.WARNING
+FILE_LOG_LEVEL = logging.WARNING
+
+# Log format.
+CONSOLE_LOG_FORMAT = '%(asctime)s: %(levelname)s\t%(name)s:\t%(message)s'
+FILE_LOG_FORMAT = '%(asctime)s: %(levelname)s\t%(name)s:\t%(message)s'
+
+# Log file name. This goes in the data directory, except on non-Windows
+# platforms in server mode.
+if SERVER_MODE and not IS_WIN:
+ LOG_FILE = '/var/log/pgadmin/pgadmin4.log'
+else:
+ LOG_FILE = os.path.join(DATA_DIR, 'pgadmin4.log')
+
+##########################################################################
+# Server Connection Driver Settings
+##########################################################################
+
+# The default driver used for making connection with PostgreSQL
+PG_DEFAULT_DRIVER = 'psycopg2'
+
+# Maximum allowed idle time in minutes before which releasing the connection
+# for the particular session. (in minutes)
+MAX_SESSION_IDLE_TIME = 60
+
+##########################################################################
+# User account and settings storage
+##########################################################################
+
+# The default path to the SQLite database used to store user accounts and
+# settings. This default places the file in the same directory as this
+# config file, but generates an absolute path for use througout the app.
+SQLITE_PATH = env('SQLITE_PATH') or os.path.join(DATA_DIR, 'pgadmin4.db')
+
+# SQLITE_TIMEOUT will define how long to wait before throwing the error -
+# OperationError due to database lock. On slower system, you may need to change
+# this to some higher value.
+# (Default: 500 milliseconds)
+SQLITE_TIMEOUT = 500
+
+# Allow database connection passwords to be saved if the user chooses.
+# Set to False to disable password saving.
+ALLOW_SAVE_PASSWORD = True
+
+# Maximum number of history queries stored per user/server/database
+MAX_QUERY_HIST_STORED = 20
+
+##########################################################################
+# Server-side session storage path
+#
+# SESSION_DB_PATH (Default: $HOME/.pgadmin4/sessions)
+##########################################################################
+#
+# We use SQLite for server-side session storage. There will be one
+# SQLite database object per session created.
+#
+# Specify the path used to store your session objects.
+#
+# If the specified directory does not exist, the setup script will create
+# it with permission mode 700 to keep the session database secure.
+#
+# On certain systems, you can use shared memory (tmpfs) for maximum
+# scalability, for example, on Ubuntu:
+#
+# SESSION_DB_PATH = '/run/shm/pgAdmin4_session'
+#
+##########################################################################
+SESSION_DB_PATH = os.path.join(DATA_DIR, 'sessions')
+
+SESSION_COOKIE_NAME = 'pga4_session'
+
+##########################################################################
+# Mail server settings
+##########################################################################
+
+# These settings are used when running in web server mode for confirming
+# and resetting passwords etc.
+# See: http://pythonhosted.org/Flask-Mail/ for more info
+MAIL_SERVER = 'localhost'
+MAIL_PORT = 25
+MAIL_USE_SSL = False
+MAIL_USE_TLS = False
+MAIL_USERNAME = ''
+MAIL_PASSWORD = ''
+MAIL_DEBUG = False
+
+# Flask-Security overrides Flask-Mail's MAIL_DEFAULT_SENDER setting, so
+# that should be set as such:
+SECURITY_EMAIL_SENDER = 'no-reply@localhost'
+
+##########################################################################
+# Mail content settings
+##########################################################################
+
+# These settings define the content of password reset emails
+SECURITY_EMAIL_SUBJECT_PASSWORD_RESET = "Password reset instructions for %s" \
+ % APP_NAME
+SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Your %s password has been reset" \
+ % APP_NAME
+SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = \
+ "Your password for %s has been changed" % APP_NAME
+
+##########################################################################
+# Upgrade checks
+##########################################################################
+
+# Check for new versions of the application?
+UPGRADE_CHECK_ENABLED = True
+
+# Where should we get the data from?
+UPGRADE_CHECK_URL = 'https://www.pgadmin.org/versions.json'
+
+# What key should we look at in the upgrade data file?
+UPGRADE_CHECK_KEY = 'pgadmin4'
+
+# Which CA file should we use?
+# Default to cacert.pem in the same directory as config.py et al.
+CA_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ "cacert.pem")
+
+# Check if the detected browser is supported
+CHECK_SUPPORTED_BROWSER = True
+
+##########################################################################
+# Storage Manager storage url config settings
+# If user sets STORAGE_DIR to empty it will show all volumes if platform
+# is Windows, '/' if it is Linux, Mac or any other unix type system.
+
+# For example:
+# 1. STORAGE_DIR = get_drive("C") or get_drive() # return C:/ by default
+# where C can be any drive character such as "D", "E", "G" etc
+# 2. Set path manually like
+# STORAGE_DIR = "/path/to/directory/"
+##########################################################################
+STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
+
+##########################################################################
+# Default locations for binary utilities (pg_dump, pg_restore etc)
+#
+# These are intentionally left empty in the main config file, but are
+# expected to be overridden by packagers in config_distro.py.
+#
+# A default location can be specified for each database driver ID, in
+# a dictionary. Either an absolute or relative path can be specified.
+# In cases where it may be difficult to know what the working directory
+# is, "$DIR" can be specified. This will be replaced with the path to the
+# top-level pgAdmin4.py file. For example, on macOS we might use:
+#
+# $DIR/../../SharedSupport
+#
+##########################################################################
+DEFAULT_BINARY_PATHS = {
+ "pg": "",
+ "ppas": "",
+ "gpdb": ""
+}
+
+##########################################################################
+# Test settings - used primarily by the regression suite, not for users
+##########################################################################
+
+# The default path for SQLite database for testing
+TEST_SQLITE_PATH = os.path.join(DATA_DIR, 'test_pgadmin4.db')
+
+##########################################################################
+# Allows flask application to response to the each request asynchronously
+##########################################################################
+THREADED_MODE = True
+
+##########################################################################
+# Do not allow SQLALCHEMY to track modification as it is going to be
+# deprecated in future
+##########################################################################
+SQLALCHEMY_TRACK_MODIFICATIONS = False
+
+##########################################################################
+# Number of records to fetch in one batch in query tool when query result
+# set is large.
+##########################################################################
+ON_DEMAND_RECORD_COUNT = 1000
+
+##########################################################################
+# Allow users to display Gravatar image for their username in Server mode
+##########################################################################
+SHOW_GRAVATAR_IMAGE = False
+
+##########################################################################
+# Set cookie path and options
+##########################################################################
+COOKIE_DEFAULT_PATH = '/'
+COOKIE_DEFAULT_DOMAIN = None
+SESSION_COOKIE_DOMAIN = None
+SESSION_COOKIE_SAMESITE = 'Lax'
+SESSION_COOKIE_SECURE = False
+SESSION_COOKIE_HTTPONLY = True
+
+#########################################################################
+# Skip storing session in files and cache for specific paths
+#########################################################################
+SESSION_SKIP_PATHS = [
+ '/misc/ping'
+]
+
+##########################################################################
+# Session expiration support
+##########################################################################
+# SESSION_EXPIRATION_TIME is the interval in Days. Session will be
+# expire after the specified number of *days*.
+SESSION_EXPIRATION_TIME = 1
+
+# CHECK_SESSION_FILES_INTERVAL is interval in Hours. Application will check
+# the session files for cleanup after specified number of *hours*.
+CHECK_SESSION_FILES_INTERVAL = 24
+
+# USER_INACTIVITY_TIMEOUT is interval in Seconds. If the pgAdmin screen is left
+# unattended for seconds then the user will
+# be logged out. When set to 0, the timeout will be disabled.
+# If pgAdmin doesn't detect any activity in the time specified (in seconds),
+# the user will be forcibly logged out from pgAdmin. Set to zero to disable
+# the timeout.
+# Note: This is applicable only for SERVER_MODE=True.
+USER_INACTIVITY_TIMEOUT = 0
+
+# OVERRIDE_USER_INACTIVITY_TIMEOUT when set to True will override
+# USER_INACTIVITY_TIMEOUT when long running queries in the Query Tool
+# or Debugger are running. When the queries complete, the inactivity timer
+# will restart in this case. If set to False, user inactivity may cause
+# transactions or in-process debugging sessions to be aborted.
+OVERRIDE_USER_INACTIVITY_TIMEOUT = True
+
+##########################################################################
+# SSH Tunneling supports only for Python 2.7 and 3.4+
+##########################################################################
+SUPPORT_SSH_TUNNEL = True
+# Allow SSH Tunnel passwords to be saved if the user chooses.
+# Set to False to disable password saving.
+ALLOW_SAVE_TUNNEL_PASSWORD = False
+
+##########################################################################
+# Master password is used to encrypt/decrypt saved server passwords
+# Applicable for desktop mode only
+##########################################################################
+MASTER_PASSWORD_REQUIRED = True
+
+##########################################################################
+# Allows pgAdmin4 to create session cookies based on IP address, so even
+# if a cookie is stolen, the attacker will not be able to connect to the
+# server using that stolen cookie.
+# Note: This can cause problems when the server is deployed in dynamic IP
+# address hosting environments, such as Kubernetes or behind load
+# balancers. In such cases, this option should be set to False.
+##########################################################################
+ENHANCED_COOKIE_PROTECTION = True
+
+##########################################################################
+# External Authentication Sources
+##########################################################################
+
+# Default setting is internal
+# External Supported Sources: ldap, kerberos
+# Multiple authentication can be achieved by setting this parameter to
+# ['ldap', 'internal']. pgAdmin will authenticate the user with ldap first,
+# in case of failure internal authentication will be done.
+
+AUTHENTICATION_SOURCES = ['internal']
+
+##########################################################################
+# LDAP Configuration
+##########################################################################
+
+# After ldap authentication, user will be added into the SQLite database
+# automatically, if set to True.
+# Set it to False, if user should not be added automatically,
+# in this case Admin has to add the user manually in the SQLite database.
+LDAP_AUTO_CREATE_USER = True
+
+# Connection timeout
+LDAP_CONNECTION_TIMEOUT = 10
+
+# Server connection details (REQUIRED)
+# example: ldap://: or ldap://:
+LDAP_SERVER_URI = 'ldap://:'
+
+# The LDAP attribute containing user names. In OpenLDAP, this may be 'uid'
+# whilst in AD, 'sAMAccountName' might be appropriate. (REQUIRED)
+LDAP_USERNAME_ATTRIBUTE = ''
+
+##########################################################################
+# 3 ways to configure LDAP as follows (Choose anyone):
+
+# 1. Dedicated User binding
+
+# LDAP Bind User DN Example: cn=username,dc=example,dc=com
+# Set this parameter to allow the connection to bind using a dedicated user.
+# After the connection is made, the pgadmin login user will be further
+# authenticated by the username and password provided
+# at the login screen.
+LDAP_BIND_USER = None
+
+# LDAP Bind User Password
+LDAP_BIND_PASSWORD = None
+
+# OR ####################
+# 2. Anonymous Binding
+
+# Set this parameter to allow the anonymous bind.
+# After the connection is made, the pgadmin login user will be further
+# authenticated by the username and password provided
+
+LDAP_ANONYMOUS_BIND = False
+
+# OR ####################
+# 3. Bind as pgAdmin user
+
+# BaseDN (REQUIRED)
+# AD example:
+# (&(objectClass=user)(memberof=CN=MYGROUP,CN=Users,dc=example,dc=com))
+# OpenLDAP example: CN=Users,dc=example,dc=com
+LDAP_BASE_DN = ''
+
+##########################################################################
+
+# Search ldap for further authentication (REQUIRED)
+# It can be optional while bind as pgAdmin user
+LDAP_SEARCH_BASE_DN = ''
+
+# Filter string for the user search.
+# For OpenLDAP, '(cn=*)' may well be enough.
+# For AD, you might use '(objectClass=user)' (REQUIRED)
+LDAP_SEARCH_FILTER = '(objectclass=*)'
+
+# Search scope for users (one of BASE, LEVEL or SUBTREE)
+LDAP_SEARCH_SCOPE = 'SUBTREE'
+
+# Use TLS? If the URI scheme is ldaps://, this is ignored.
+LDAP_USE_STARTTLS = False
+
+# TLS/SSL certificates. Specify if required, otherwise leave empty
+LDAP_CA_CERT_FILE = ''
+LDAP_CERT_FILE = ''
+LDAP_KEY_FILE = ''
+
+
+##########################################################################
+# Kerberos Configuration
+##########################################################################
+
+KRB_APP_HOST_NAME = DEFAULT_SERVER
+
+# If the default_keytab_name is not set in krb5.conf or
+# the KRB_KTNAME environment variable is not set then, explicitly set
+# the Keytab file
+
+KRB_KTNAME = ''
+
+# After kerberos authentication, user will be added into the SQLite database
+# automatically, if set to True.
+# Set it to False, if user should not be added automatically,
+# in this case Admin has to add the user manually in the SQLite database.
+
+KRB_AUTO_CREATE_USER = True
+
+##########################################################################
+# Local config settings
+##########################################################################
+
+# Load distribution-specific config overrides
+try:
+ from config_distro import *
+except ImportError:
+ pass
+
+# Load local config overrides
+try:
+ from config_local import *
+except ImportError:
+ pass
+
+# Load system config overrides. We do this last, so that the sysadmin can
+# override anything they want from a config file that's in a protected system
+# directory and away from pgAdmin to avoid invalidating signatures.
+system_config_dir = '/etc/pgadmin'
+if sys.platform.startswith('win32'):
+ system_config_dir = os.environ['CommonProgramFiles'] + '/pgadmin'
+elif sys.platform.startswith('darwin'):
+ system_config_dir = '/Library/Preferences/pgadmin'
+
+if os.path.exists(system_config_dir + '/config_system.py'):
+ try:
+ sys.path.insert(0, system_config_dir)
+ from config_system import *
+ except ImportError:
+ pass
+
+# Override DEFAULT_SERVER value from environment variable.
+if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ:
+ DEFAULT_SERVER = os.environ['PGADMIN_CONFIG_DEFAULT_SERVER']
+
+# Disable USER_INACTIVITY_TIMEOUT when SERVER_MODE=False
+if not SERVER_MODE:
+ USER_INACTIVITY_TIMEOUT = 0
diff --git a/docker/config/pgadmin/servers.json b/docker/config/pgadmin/servers.json
new file mode 100644
index 00000000000..c487011b7b2
--- /dev/null
+++ b/docker/config/pgadmin/servers.json
@@ -0,0 +1,13 @@
+{
+ "Servers": {
+ "1": {
+ "Name": "Supabase",
+ "Group": "Servers",
+ "Port": 5432,
+ "Username": "postgres",
+ "Host": "db",
+ "SSLMode": "disable",
+ "MaintenanceDB": "postgres"
+ }
+ }
+}
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
deleted file mode 100644
index 5ad4e7f1814..00000000000
--- a/docker/docker-compose.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-version: '3.6'
-services:
- kong:
- container_name: supabase-kong
- build:
- context: ./kong
- environment:
- KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml
- KONG_PLUGINS: request-transformer,cors,key-auth,http-log
- ports:
- - 8000:8000/tcp
- - 8443:8443/tcp
- auth:
- container_name: supabase-auth
- image: supabase/gotrue:latest
- ports:
- - '9999:9999'
- environment:
- GOTRUE_JWT_SECRET: super-secret-jwt-token-with-at-least-32-characters-long
- GOTRUE_JWT_EXP: 3600
- GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
- GOTRUE_DB_DRIVER: postgres
- DB_NAMESPACE: auth
- API_EXTERNAL_URL: localhost
- GOTRUE_API_HOST: 0.0.0.0
- PORT: 9999
- GOTRUE_DISABLE_SIGNUP: "false"
- GOTRUE_SITE_URL: localhost
- GOTRUE_MAILER_AUTOCONFIRM: "true"
- GOTRUE_LOG_LEVEL: DEBUG
- GOTRUE_OPERATOR_TOKEN: super-secret-operator-token
- DATABASE_URL: "postgres://postgres:postgres@db:5432/postgres?sslmode=disable"
- depends_on:
- - db
- rest:
- container_name: supabase-rest
- image: postgrest/postgrest:latest
- ports:
- - '3000:3000'
- depends_on:
- - db
- restart: always
- environment:
- PGRST_DB_URI: postgres://postgres:postgres@db:5432/postgres
- PGRST_DB_SCHEMA: public
- PGRST_DB_ANON_ROLE: postgres
- PGRST_JWT_SECRET: super-secret-jwt-token-with-at-least-32-characters-long
- realtime:
- container_name: supabase-realtime
- image: supabase/realtime:latest
- ports:
- - '4000:4000'
- depends_on:
- - db
- restart: on-failure
- environment:
- DB_HOST: db
- DB_NAME: postgres
- DB_USER: postgres
- DB_PASSWORD: postgres
- DB_PORT: 5432
- PORT: 4000
- HOSTNAME: localhost
- # Disable JWT Auth locally. The JWT_SECRET will be ignored.
- SECURE_CHANNELS: 'false'
- JWT_SECRET: super-secret-jwt-token-with-at-least-32-characters-long
- db:
- container_name: supabase-db
- build:
- context: ./postgres
- ports:
- - 5432:5432
- command:
- - postgres
- - -c
- - wal_level=logical
- environment:
- POSTGRES_DB: postgres
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- POSTGRES_PORT: 5432
diff --git a/docker/kong/Dockerfile b/docker/dockerfiles/kong/Dockerfile
similarity index 100%
rename from docker/kong/Dockerfile
rename to docker/dockerfiles/kong/Dockerfile
diff --git a/docker/kong/kong.yml b/docker/dockerfiles/kong/kong.yml
similarity index 100%
rename from docker/kong/kong.yml
rename to docker/dockerfiles/kong/kong.yml
diff --git a/docker/postgres/00-initial-schema.sql b/docker/dockerfiles/postgres/00-initial-schema.sql
similarity index 100%
rename from docker/postgres/00-initial-schema.sql
rename to docker/dockerfiles/postgres/00-initial-schema.sql
diff --git a/docker/postgres/Dockerfile b/docker/dockerfiles/postgres/Dockerfile
similarity index 100%
rename from docker/postgres/Dockerfile
rename to docker/dockerfiles/postgres/Dockerfile
diff --git a/docker/postgres/auth-schema.sql b/docker/dockerfiles/postgres/auth-schema.sql
similarity index 100%
rename from docker/postgres/auth-schema.sql
rename to docker/dockerfiles/postgres/auth-schema.sql
diff --git a/docker/supabase-traefik/.env b/docker/supabase-traefik/.env
new file mode 100644
index 00000000000..14356159fe2
--- /dev/null
+++ b/docker/supabase-traefik/.env
@@ -0,0 +1,32 @@
+#fill with random passwords
+OPERATOR_TOKEN=
+
+JWT_SECRET=
+
+#string length 100 didnt work as password for me; length 50 did it
+POSTGRES_PASSWORD=
+# some smtp server to send your auth-mails with
+SMTP_HOST=mail.example.com
+SMTP_PORT=
+SMTP_USER=
+SMTP_PASS=
+
+#traefik
+TRAEFIK_SECURE_ENTRYPOINT=websecure
+TRAEFIK_NETWORK=your_docker_network
+SUPABASE_HOSTNAME=supabase.example.com
+
+#pgadmin
+PGADMIN_DEFAULT_PASSWORD=
+PGADMIN_DEFAULT_EMAIL=
+
+
+#predefined; dont change these
+POSTGRES_PORT=5432
+AUTH_PORT=9999
+REST_PORT=3000
+REALTIME_PORT=4000
+KONG_PORT=8000
+KONG_PORT_TLS=8443
+PGADMIN_PORT=80
+
diff --git a/docker/supabase-traefik/README.md b/docker/supabase-traefik/README.md
new file mode 100644
index 00000000000..3dbae9ee86e
--- /dev/null
+++ b/docker/supabase-traefik/README.md
@@ -0,0 +1,36 @@
+# use supabase with existing traefik setup
+
+## fill the .env file and reach the endpoints at
+
+### **pgadmin**
+```
+supabase.example.com/pgadmin/
+```
+
+
+### **auth**
+
+```
+supabase.example.com/auth/
+```
+you can test auth with
+
+```
+supabase.example.com/auth/settings
+```
+as the default path returns 404
+
+### **realtime**
+```
+supabase.example.com/realtime/
+```
+
+### **rest**
+```
+supabase.example.com/rest/
+```
+
+### **kong**
+```
+supabase.example.com/kong/
+```
\ No newline at end of file
diff --git a/docker/supabase-traefik/docker-compose.yml b/docker/supabase-traefik/docker-compose.yml
new file mode 100644
index 00000000000..2bc1030bd5a
--- /dev/null
+++ b/docker/supabase-traefik/docker-compose.yml
@@ -0,0 +1,161 @@
+version: '3.6'
+services:
+ kong:
+ container_name: supabase-kong
+ build:
+ context: ../dockerfiles/kong
+ environment:
+ KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml
+ KONG_PLUGINS: request-transformer,cors,key-auth,http-log
+ labels:
+ traefik.enable: 'true'
+ traefik.http.routers.supabase-kong.entrypoints: ${TRAEFIK_SECURE_ENTRYPOINT}
+ traefik.http.routers.supabase-kong.tls: 'true'
+ traefik.http.services.supabase-kong.loadbalancer.server.port: ${KONG_PORT}
+ traefik.docker.network: ${TRAEFIK_NETWORK}
+ traefik.http.routers.supabase-kong.rule: 'Host(`${SUPABASE_HOSTNAME}`) && PathPrefix(`/kong/`)'
+ traefik.http.routers.supabase-kong.middlewares: repl-supabase-kong@docker
+ traefik.http.middlewares.repl-supabase-kong.replacepathregex.regex: ^/kong/(.*)
+ traefik.http.middlewares.repl-supabase-kong.replacepathregex.replacement: /$$1
+ networks:
+ - rp
+ - db
+ auth:
+ container_name: supabase-auth
+ image: supabase/gotrue:latest
+ depends_on:
+ - db
+ ports:
+ - ${AUTH_PORT}
+ environment:
+ GOTRUE_JWT_SECRET: ${JWT_SECRET}
+ GOTRUE_JWT_EXP: 3600
+ GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
+ GOTRUE_DB_DRIVER: postgres
+ DB_NAMESPACE: auth
+ API_EXTERNAL_URL: ${SUPABASE_HOSTNAME}
+ GOTRUE_API_HOST: 0.0.0.0
+ PORT: ${AUTH_PORT}
+
+ GOTRUE_DISABLE_SIGNUP: 'false'
+ GOTRUE_SITE_URL: ${SUPABASE_HOSTNAME}
+ GOTRUE_MAILER_AUTOCONFIRM: 'true'
+ GOTRUE_LOG_LEVEL: DEBUG
+ GOTRUE_OPERATOR_TOKEN: ${OPERATOR_TOKEN}
+ DATABASE_URL: 'postgres://postgres:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/postgres?sslmode=disable'
+
+ GOTRUE_SMTP_HOST: ${SMTP_HOST}
+ GOTRUE_SMTP_PORT: ${SMTP_PORT}
+ GOTRUE_SMTP_USER: ${SMTP_USER}
+ GOTRUE_SMTP_PASS: ${SMTP_PASS}
+ labels:
+ traefik.enable: 'true'
+ traefik.http.routers.supabase-auth.entrypoints: ${TRAEFIK_SECURE_ENTRYPOINT}
+ traefik.http.services.supabase-auth.loadbalancer.server.port: ${AUTH_PORT}
+ traefik.http.routers.supabase-auth.tls: 'true'
+ traefik.docker.network: ${TRAEFIK_NETWORK}
+ traefik.http.routers.supabase-auth.rule: 'Host(`${SUPABASE_HOSTNAME}`) && PathPrefix(`/auth/`)'
+ traefik.http.routers.supabase-auth.middlewares: repl-supabase-auth@docker
+ traefik.http.middlewares.repl-supabase-auth.replacepathregex.regex: ^/auth/(.*)
+ traefik.http.middlewares.repl-supabase-auth.replacepathregex.replacement: /$$1
+ networks:
+ - rp
+ - db
+ rest:
+ container_name: supabase-rest
+ image: postgrest/postgrest:latest
+ depends_on:
+ - db
+ restart: always
+ environment:
+ PGRST_DB_URI: postgres://postgres:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/postgres
+ PGRST_DB_SCHEMA: public
+ PGRST_DB_ANON_ROLE: postgres
+ PGRST_JWT_SECRET: ${JWT_SECRET}
+ labels:
+ traefik.enable: 'true'
+ traefik.http.routers.supabase-rest.entrypoints: ${TRAEFIK_SECURE_ENTRYPOINT}
+ traefik.http.services.supabase-rest.loadbalancer.server.port: ${REST_PORT}
+ traefik.http.routers.supabase-rest.tls: 'true'
+ traefik.docker.network: ${TRAEFIK_NETWORK}
+ traefik.http.routers.supabase-rest.rule: 'Host(`${SUPABASE_HOSTNAME}`) && PathPrefix(`/rest/`)'
+ traefik.http.routers.supabase-rest.middlewares: repl-supabase-rest@docker
+ traefik.http.middlewares.repl-supabase-rest.replacepathregex.regex: ^/rest/(.*)
+ traefik.http.middlewares.repl-supabase-rest.replacepathregex.replacement: /$$1
+ networks:
+ - rp
+ - db
+ realtime:
+ container_name: supabase-realtime
+ image: supabase/realtime:latest
+ depends_on:
+ - db
+ restart: on-failure
+ environment:
+ DB_HOST: db
+ DB_NAME: postgres
+ DB_USER: postgres
+ DB_PASSWORD: ${POSTGRES_PASSWORD}
+ DB_PORT: ${POSTGRES_PORT}
+ PORT: ${REALTIME_PORT}
+ HOSTNAME: localhost
+ # Disable JWT Auth locally. The JWT_SECRET will be ignored.
+ SECURE_CHANNELS: 'false'
+ JWT_SECRET: ${JWT_SECRET}
+ labels:
+ traefik.enable: 'true'
+ traefik.http.routers.supabase-realtime.entrypoints: ${TRAEFIK_SECURE_ENTRYPOINT}
+ traefik.http.services.supabase-realtime.loadbalancer.server.port: ${REALTIME_PORT}
+ traefik.http.routers.supabase-realtime.tls: 'true'
+ traefik.docker.network: ${TRAEFIK_NETWORK}
+ traefik.http.routers.supabase-realtime.rule: 'Host(`${SUPABASE_HOSTNAME}`) && PathPrefix(`/realtime/`)'
+ traefik.http.routers.supabase-realtime.middlewares: repl-supabase-realtime@docker
+ traefik.http.middlewares.repl-supabase-realtime.replacepathregex.regex: ^/realtime/(.*)
+ traefik.http.middlewares.repl-supabase-realtime.replacepathregex.replacement: /$$1
+ networks:
+ - rp
+ - db
+ db:
+ container_name: supabase-db
+ build:
+ context: ../dockerfiles/postgres
+ ports:
+ - ${POSTGRES_PORT}
+ command:
+ - postgres
+ - -c
+ - wal_level=logical
+ environment:
+ POSTGRES_DB: postgres
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+ POSTGRES_PORT: ${POSTGRES_PORT}
+ networks:
+ - db
+ pgadmin:
+ container_name: supabase-pgadmin
+ image: dpage/pgadmin4
+ restart: always
+ environment:
+ PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
+ PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
+ SCRIPT_NAME: /pgadmin
+ PGADMIN_SERVER_JSON_FILE: /pgadmin4/servers.json
+ volumes:
+ - ../config/pgadmin/servers.json:/pgadmin4/servers.json
+ - ../config/pgadmin/config.py:/pgadmin4/config.py
+ networks:
+ - db
+ - rp
+ labels:
+ traefik.enable: 'true'
+ traefik.http.routers.supabase-pgadmin.entrypoints: ${TRAEFIK_SECURE_ENTRYPOINT}
+ traefik.http.services.supabase-pgadmin.loadbalancer.server.port: ${PGADMIN_PORT}
+ traefik.http.routers.supabase-pgadmin.tls: 'true'
+ traefik.docker.network: ${TRAEFIK_NETWORK}
+ traefik.http.routers.supabase-pgadmin.rule: 'Host(`${SUPABASE_HOSTNAME}`) && PathPrefix(`/pgadmin`)'
+
+networks:
+ rp:
+ name: ${TRAEFIK_NETWORK}
+ db:
diff --git a/docker/supabase/.env b/docker/supabase/.env
new file mode 100644
index 00000000000..d406128c932
--- /dev/null
+++ b/docker/supabase/.env
@@ -0,0 +1,22 @@
+#fill with random passwords
+OPERATOR_TOKEN=
+
+JWT_SECRET=
+
+#string length 100 didnt work as password for me; length 50 did it
+POSTGRES_PASSWORD=
+
+# some smtp server to send your auth-mails with
+SMTP_HOST=mail.example.com
+SMTP_PORT=
+SMTP_USER=
+SMTP_PASS=
+
+
+#predefined; dont change these
+POSTGRES_PORT=5432
+AUTH_PORT=9999
+REST_PORT=3000
+REALTIME_PORT=4000
+KONG_PORT=8000
+KONG_PORT_TLS=8443
\ No newline at end of file
diff --git a/docker/README.md b/docker/supabase/README.md
similarity index 96%
rename from docker/README.md
rename to docker/supabase/README.md
index 7ccc78a287b..695e8242706 100644
--- a/docker/README.md
+++ b/docker/supabase/README.md
@@ -3,6 +3,8 @@
You can run Supabase on your local machine using `docker-compose`:
+- Add passwords to the .env file
+
- Starting all services: `docker-compose up -d`
- Stopping all services: `docker-compose down`
diff --git a/docker/supabase/docker-compose.yml b/docker/supabase/docker-compose.yml
new file mode 100644
index 00000000000..db8bffb0d73
--- /dev/null
+++ b/docker/supabase/docker-compose.yml
@@ -0,0 +1,88 @@
+version: '3.6'
+services:
+ kong:
+ container_name: supabase-kong
+ build:
+ context: ../dockerfiles/kong
+ environment:
+ KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml
+ KONG_PLUGINS: request-transformer,cors,key-auth,http-log
+ ports:
+ - ${KONG_PORT}:8000/tcp
+ - ${KONG_PORT_TLS}:8443/tcp
+ auth:
+ container_name: supabase-auth
+ image: supabase/gotrue:latest
+ ports:
+ - ${AUTH_PORT}
+ depends_on:
+ - db
+ environment:
+ GOTRUE_JWT_SECRET: ${JWT_SECRET}
+ GOTRUE_JWT_EXP: 3600
+ GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
+ GOTRUE_DB_DRIVER: postgres
+ DB_NAMESPACE: auth
+ API_EXTERNAL_URL: localhost
+ GOTRUE_API_HOST: 0.0.0.0
+ PORT: ${AUTH_PORT}
+
+ GOTRUE_SMTP_HOST: ${SMTP_HOST}
+ GOTRUE_SMTP_PORT: ${SMTP_PORT}
+ GOTRUE_SMTP_USER: ${SMTP_USER}
+ GOTRUE_SMTP_PASS: ${SMTP_PASS}
+
+ GOTRUE_DISABLE_SIGNUP: 'false'
+ GOTRUE_SITE_URL: localhost
+ GOTRUE_MAILER_AUTOCONFIRM: 'true'
+ GOTRUE_LOG_LEVEL: DEBUG
+ GOTRUE_OPERATOR_TOKEN: ${OPERATOR_TOKEN}
+ DATABASE_URL: 'postgres://postgres:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/postgres?sslmode=disable'
+
+ rest:
+ container_name: supabase-rest
+ image: postgrest/postgrest:latest
+ ports:
+ - ${REST_PORT}:3000
+ depends_on:
+ - db
+ restart: always
+ environment:
+ PGRST_DB_URI: postgres://postgres:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/postgres
+ PGRST_DB_SCHEMA: public
+ PGRST_DB_ANON_ROLE: postgres
+ PGRST_JWT_SECRET: ${JWT_SECRET}
+ realtime:
+ container_name: supabase-realtime
+ image: supabase/realtime:latest
+ ports:
+ - ${REALTIME_PORT}
+ depends_on:
+ - db
+ restart: on-failure
+ environment:
+ DB_HOST: db
+ DB_NAME: postgres
+ DB_USER: postgres
+ DB_PASSWORD: ${POSTGRES_PASSWORD}
+ DB_PORT: ${POSTGRES_PORT}
+ PORT: ${REALTIME_PORT}
+ HOSTNAME: localhost
+ # Disable JWT Auth locally. The JWT_SECRET will be ignored.
+ SECURE_CHANNELS: 'false'
+ JWT_SECRET: ${JWT_SECRET}
+ db:
+ container_name: supabase-db
+ build:
+ context: ../dockerfiles/postgres
+ ports:
+ - ${POSTGRES_PORT}:${POSTGRES_PORT}
+ command:
+ - postgres
+ - -c
+ - wal_level=logical
+ environment:
+ POSTGRES_DB: postgres
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+ POSTGRES_PORT: ${POSTGRES_PORT}