├── .editorconfig ├── .env.example ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── deploy ├── local-ingress │ ├── cert │ │ └── .gitkeep │ ├── docker-compose.yml │ └── traefik │ │ ├── fileConfig.yml │ │ ├── htpasswd.example │ │ └── traefik.yml └── supabase │ └── .gitkeep ├── scripts ├── create-local-certs.sh ├── supabase-amend-docker-compose.sh └── supabase-docker-update.sh ├── setup-repo.sh ├── start-local-infra.sh ├── stop-local-infra.sh └── wipe-supabase-data.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.yml] 12 | indent_size = 2 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping. 2 | # To create a user:password pair without prompt, the following command can be used: 3 | # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g 4 | # -> user:$$apr1$$CIAMshBq$$/ZoVtz9bXygfE9lnmhvof1 5 | TRAEFIK_DASHBOARD_USER=user 6 | TRAEFIK_DASHBOARD_PWD="$$apr1$$CIAMshBq$$/ZoVtz9bXygfE9lnmhvof1" 7 | 8 | ############ 9 | # Secrets 10 | # YOU MUST CHANGE THESE BEFORE GOING INTO PRODUCTION 11 | ############ 12 | 13 | POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password 14 | JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long 15 | ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE 16 | SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q 17 | DASHBOARD_USERNAME=supabase 18 | DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated 19 | 20 | ############ 21 | # Database - You can change these to any PostgreSQL database that has logical replication enabled. 22 | ############ 23 | 24 | POSTGRES_HOST=db 25 | POSTGRES_DB=postgres 26 | POSTGRES_PORT=5432 27 | # default user is postgres 28 | 29 | ############ 30 | # API Proxy - Configuration for the Kong Reverse proxy. 31 | ############ 32 | 33 | KONG_HTTP_PORT=8000 34 | KONG_HTTPS_PORT=8443 35 | 36 | 37 | ############ 38 | # API - Configuration for PostgREST. 39 | ############ 40 | 41 | PGRST_DB_SCHEMAS=public,storage,graphql_public 42 | 43 | 44 | ############ 45 | # Auth - Configuration for the GoTrue authentication server. 46 | ############ 47 | 48 | ## General 49 | SITE_URL=http://localhost:3000 50 | ADDITIONAL_REDIRECT_URLS= 51 | JWT_EXPIRY=3600 52 | DISABLE_SIGNUP=false 53 | API_EXTERNAL_URL=http://localhost:8000 54 | 55 | ## Mailer Config 56 | MAILER_URLPATHS_CONFIRMATION="/auth/v1/verify" 57 | MAILER_URLPATHS_INVITE="/auth/v1/verify" 58 | MAILER_URLPATHS_RECOVERY="/auth/v1/verify" 59 | MAILER_URLPATHS_EMAIL_CHANGE="/auth/v1/verify" 60 | 61 | ## Email auth 62 | ENABLE_EMAIL_SIGNUP=true 63 | ENABLE_EMAIL_AUTOCONFIRM=false 64 | SMTP_ADMIN_EMAIL=admin@example.com 65 | SMTP_HOST=supabase-mail 66 | SMTP_PORT=2500 67 | SMTP_USER=fake_mail_user 68 | SMTP_PASS=fake_mail_password 69 | SMTP_SENDER_NAME=fake_sender 70 | ENABLE_ANONYMOUS_USERS=false 71 | 72 | ## Phone auth 73 | ENABLE_PHONE_SIGNUP=true 74 | ENABLE_PHONE_AUTOCONFIRM=true 75 | 76 | 77 | ############ 78 | # Studio - Configuration for the Dashboard 79 | ############ 80 | 81 | STUDIO_DEFAULT_ORGANIZATION=acme 82 | STUDIO_DEFAULT_PROJECT=ACT 83 | 84 | STUDIO_PORT=3000 85 | # replace if you intend to use Studio outside of localhost 86 | SUPABASE_PUBLIC_URL=http://localhost:8000 87 | 88 | # Enable webp support 89 | IMGPROXY_ENABLE_WEBP_DETECTION=true 90 | 91 | ############ 92 | # Functions - Configuration for Functions 93 | ############ 94 | # NOTE: VERIFY_JWT applies to all functions. Per-function VERIFY_JWT is not supported yet. 95 | FUNCTIONS_VERIFY_JWT=false 96 | 97 | ############ 98 | # Logs - Configuration for Logflare 99 | # Please refer to https://supabase.com/docs/reference/self-hosting-analytics/introduction 100 | ############ 101 | 102 | LOGFLARE_LOGGER_BACKEND_API_KEY=your-super-secret-and-long-logflare-key 103 | 104 | # Change vector.toml sinks to reflect this change 105 | LOGFLARE_API_KEY=your-super-secret-and-long-logflare-key 106 | 107 | # Docker socket location - this value will differ depending on your OS 108 | DOCKER_SOCKET_LOCATION=/var/run/docker.sock 109 | 110 | # Google Cloud Project details 111 | GOOGLE_PROJECT_ID=GOOGLE_PROJECT_ID 112 | GOOGLE_PROJECT_NUMBER=GOOGLE_PROJECT_NUMBER 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE's 2 | .idea 3 | .idea/ 4 | .vscode/* 5 | !.vscode/extensions.json 6 | !.vscode/settings.json 7 | 8 | # dependencies 9 | node_modules 10 | node_modules/ 11 | 12 | # testing 13 | coverage 14 | 15 | # misc 16 | .DS_Store 17 | *.pem 18 | tsconfig.tsbuildinfo 19 | 20 | # debug 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | .pnpm-debug.log* 25 | 26 | # env files 27 | env* 28 | .env 29 | .env* 30 | !.env.example 31 | .env.local 32 | .env.development.local 33 | .env.test.local 34 | .env.production.local 35 | 36 | # Buildables 37 | .turbo 38 | .cache 39 | .bin/ 40 | dist 41 | dist/ 42 | build 43 | build/ 44 | build/Release 45 | public/build/ 46 | server/dist/ 47 | public/dist/ 48 | storybook-static/ 49 | deploy/supabase/volumes/db/data/ 50 | deploy/supabase/volumes/storage/ 51 | 52 | 53 | # TS 54 | typings/ 55 | 56 | # Specific Configurations and IDE Settings: 57 | .eslintcache 58 | .npm 59 | .yarn-integrity 60 | .yarn/* 61 | !.yarn/patches 62 | !.yarn/plugins 63 | !.yarn/releases 64 | !.yarn/sdks 65 | !.yarn/versions 66 | .terraform 67 | .env.bkp 68 | *.lock.hcl 69 | terraform.tfvars 70 | *.tfstate* 71 | supabase.auto.pkrvars.hcl 72 | sender-verification.sh 73 | .tsbuildinfo 74 | htpasswd 75 | !htpasswd.example 76 | 77 | # Logs and Debug Files: 78 | *.log 79 | 80 | # Temporary and Runtime Files: 81 | tmp 82 | *.swp 83 | pids 84 | *.pid 85 | *.seed 86 | *.pid.lock 87 | 88 | # Build and Dependency Folders: 89 | lib-cov 90 | *.lcov 91 | 92 | # Archives and Package Files: 93 | *.tgz 94 | 95 | # Miscellaneous Patterns: 96 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 97 | test.http 98 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-vscode-remote.remote-containers", 4 | "redhat.vscode-yaml", 5 | "ms-kubernetes-tools.vscode-kubernetes-tools", 6 | "ms-azuretools.vscode-docker", 7 | "googlecloudtools.cloudcode", 8 | "dbaeumer.vscode-eslint", 9 | "denoland.vscode-deno", 10 | "esbenp.prettier-vscode", 11 | "wayou.vscode-todo-highlight", 12 | "firsttris.vscode-jest-runner", 13 | "streetsidesoftware.code-spell-checker", 14 | "github.vscode-github-actions", 15 | "donjayamanne.githistory", 16 | "eamodio.gitlens", 17 | "ms-vscode.remote-explorer", 18 | "ms-vscode-remote.remote-ssh-edit", 19 | "ms-vscode-remote.remote-ssh", 20 | "formulahendry.code-runner", 21 | "chrmarti.regex", 22 | "vscode-icons-team.vscode-icons", 23 | "aaron-bond.better-comments", 24 | "chakrounanas.turbo-console-log", 25 | "oderwat.indent-rainbow", 26 | "formulahendry.auto-rename-tag", 27 | "pranaygp.vscode-css-peek", 28 | "kamikillerto.vscode-colorize", 29 | "yzhang.markdown-all-in-one", 30 | "idleberg.icon-fonts" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["berbix", "Firestore", "Idenfy", "oliu"], 3 | "search.exclude": { 4 | "**/node_modules": true, 5 | "**/yarn.lock": true 6 | }, 7 | "typescript.preferences.importModuleSpecifier": "non-relative", 8 | "javascript.preferences.importModuleSpecifier": "non-relative", 9 | "eslint.workingDirectories": ["apps", "packages"], 10 | "editor.defaultFormatter": "esbenp.prettier-vscode", 11 | "editor.formatOnSave": true, 12 | "editor.formatOnPaste": true, 13 | "editor.codeActionsOnSave": { 14 | "source.fixAll.eslint": "explicit", 15 | "source.organizeImports": "explicit" 16 | }, 17 | "[typescript]": { 18 | "editor.defaultFormatter": "denoland.vscode-deno" 19 | }, 20 | "deno.enablePaths": ["supabase/functions"], 21 | "deno.lint": true, 22 | "deno.unstable": true 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023 DigitalOcean 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fully Dockerized Web Stack with Supabase Docker & Traefik + localhost ssl certs 2 | 3 | ## Introduction 4 | 5 | This is a self-hosting Supabase + Traefik with localhost ssl certs. 6 | 7 | Note: this setup is unofficial. 8 | 9 | It aims at fully automating self-hosted Supabase setup with [Traefik](https://github.com/traefik/traefik) as a reverse proxy for local development. 10 | 11 | WIP - Automating deployment to Digital Ocean. 12 | 13 | Please make sure you read the [self-hosting guide](https://supabase.io/docs/guides/self-hosting#running-supabase). 14 | 15 | ## Requirements 16 | 17 | To imitate a deployed environment this implementation leverages `mkcert`to enable local development with https 18 | Please install it using brew: 19 | 20 | `brew install mkcert` 21 | 22 | ## Setup 23 | 24 | Please run this command: 25 | `./setup-repo.sh` 26 | 27 | ## Run 28 | 29 | Execute the following command: 30 | `./start-local-infra.sh` 31 | 32 | You will be able to access traefik proxy at: 33 | `https://traefik.acme.localhost` 34 | with credentials: 35 | `user:password` 36 | 37 | You will be able to access traefik proxy at: 38 | `https://studio.acme.localhost` 39 | with credentials: 40 | `supabase:this_password_is_insecure_and_should_be_updated` 41 | 42 | ## Stop 43 | 44 | Execute the following command: 45 | `./stop-local-infra.sh` 46 | 47 | ## Existing Commands 48 | 49 | `./setup-repo.sh` - Updates Supabase docker files & creates localhost ssl certs using `mkcert`. 50 | 51 | `./start-local-infra.sh` - Starts Supabase & Traefik with localhost ssl certs service. 52 | 53 | `./stop-local-infra.sh` - Stops Supabase & Traefik service. 54 | 55 | `./wipe-supabase-data.sh` - Clears the supabase postgres data and wipes it clean. 56 | 57 | ### localhost certs generation 58 | 59 | > Please note that this step is automated for you when you use `./setup-repo.sh` command. 60 | 61 | The local operation of this repo, requires use of `mkcert` to generate local certs. 62 | We leverage brew to install it: 63 | `brew install mkcert` 64 | then inside `cert` folder in order to create cert for acme.test and _.acme.test execute: 65 | `mkcert -key-file key.pem -cert-file cert.pem "acme.localhost" "_.acme.localhost"` 66 | -------------------------------------------------------------------------------- /deploy/local-ingress/cert/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartekus/self-host-supabase-local-dev/469487d28adfc418350bd77c2e5f4cde00cd9c4d/deploy/local-ingress/cert/.gitkeep -------------------------------------------------------------------------------- /deploy/local-ingress/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | reverse-proxy: 3 | image: traefik:v2.11.2 4 | container_name: traefik 5 | hostname: traefik 6 | # security_opt: 7 | # - no-new-privileges:true 8 | ports: 9 | - 80:80 10 | - 443:443 11 | restart: unless-stopped 12 | environment: 13 | TRAEFIK_DASHBOARD_USER: "${TRAEFIK_DASHBOARD_USER}" 14 | TRAEFIK_DASHBOARD_PWD: "${TRAEFIK_DASHBOARD_PWD}" 15 | depends_on: 16 | - dockersocket 17 | volumes: 18 | - /var/run/docker.sock:/var/run/docker.sock:ro 19 | - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro 20 | - ./traefik/fileConfig.yml:/etc/traefik/fileConfig.yml:ro 21 | - ./traefik/htpasswd:/etc/traefik/htpasswd:ro 22 | - certs:/etc/ssl/traefik 23 | networks: 24 | - supabase 25 | 26 | dockersocket: 27 | container_name: dockersocket 28 | image: tecnativa/docker-socket-proxy 29 | volumes: 30 | - /var/run/docker.sock:/var/run/docker.sock 31 | networks: 32 | - supabase 33 | environment: 34 | CONTAINERS: 1 35 | POST: 0 36 | privileged: true 37 | restart: unless-stopped 38 | 39 | volumes: 40 | certs: 41 | driver: local 42 | driver_opts: 43 | type: none 44 | device: ${PWD}/cert 45 | o: bind 46 | 47 | networks: 48 | supabase: 49 | driver: bridge 50 | external: true 51 | proxy: 52 | external: true 53 | -------------------------------------------------------------------------------- /deploy/local-ingress/traefik/fileConfig.yml: -------------------------------------------------------------------------------- 1 | tls: 2 | stores: 3 | default: 4 | defaultCertificate: 5 | certFile: /etc/ssl/traefik/cert.pem 6 | keyFile: /etc/ssl/traefik/key.pem 7 | certificates: 8 | - certFile: /etc/ssl/traefik/cert.pem 9 | keyFile: /etc/ssl/traefik/key.pem 10 | 11 | http: 12 | routers: 13 | ############################################################################################################################################################################### 14 | 15 | ## EXTERNAL ROUTING ## 16 | traefik: 17 | rule: "Host(`traefik.acme.localhost`)" 18 | service: "api@internal" 19 | entryPoints: 20 | - https 21 | middlewares: 22 | - "traefikDashboardAuth" 23 | - "securityHeaders" 24 | tls: 25 | domains: 26 | - main: "acme.localhost" 27 | sans: 28 | - "*.acme.localhost" 29 | 30 | #Supabase Kong routing 31 | supabase-kong: 32 | service: supabase-kong 33 | entryPoints: 34 | - https 35 | rule: "Host(`studio.acme.localhost`)" 36 | tls: {} 37 | middlewares: 38 | - "securityHeaders" 39 | 40 | #Supabase Analytics routing 41 | supabase-analytics: 42 | service: supabase-analytics 43 | entryPoints: 44 | - https 45 | rule: "Host(`analytics.acme.localhost`)" 46 | tls: {} 47 | middlewares: 48 | - "securityHeaders" 49 | 50 | 51 | ######################################################################################################################################################################## 52 | 53 | ## SERVICES ## 54 | services: 55 | # Traefik service 56 | traefik: 57 | loadBalancer: 58 | servers: 59 | - url: "http://traefik:8080" 60 | 61 | # Supabase Kong service 62 | supabase-kong: 63 | loadbalancer: 64 | servers: 65 | - url: "http://kong:8000" 66 | 67 | # Supabase Analytics service 68 | supabase-analytics: 69 | loadbalancer: 70 | servers: 71 | - url: "http://analytics:4000" 72 | 73 | 74 | ############################################################################################################################################################################### 75 | 76 | ## MIDDLEWARES ## 77 | middlewares: 78 | # Traefik 79 | traefikDashboardAuth: 80 | basicAuth: 81 | usersFile: "/etc/traefik/htpasswd" 82 | users: 83 | - "{{env "TRAEFIK_DASHBOARD_USER"}}:{{env "TRAEFIK_DASHBOARD_PWD"}}" 84 | 85 | 86 | # Security headers 87 | securityHeaders: 88 | headers: 89 | customResponseHeaders: 90 | X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex" 91 | server: "" 92 | sslProxyHeaders: 93 | X-Forwarded-Proto: https 94 | referrerPolicy: "same-origin" 95 | hostsProxyHeaders: 96 | - "X-Forwarded-Host" 97 | customRequestHeaders: 98 | X-Forwarded-Proto: "https" 99 | contentTypeNosniff: true 100 | browserXssFilter: true 101 | forceSTSHeader: true 102 | stsIncludeSubdomains: true 103 | stsSeconds: 63072000 104 | stsPreload: true 105 | -------------------------------------------------------------------------------- /deploy/local-ingress/traefik/htpasswd.example: -------------------------------------------------------------------------------- 1 | test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/ 2 | test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 3 | -------------------------------------------------------------------------------- /deploy/local-ingress/traefik/traefik.yml: -------------------------------------------------------------------------------- 1 | global: 2 | checkNewVersion: true 3 | sendAnonymousUsage: false 4 | 5 | serversTransport: 6 | insecureSkipVerify: false 7 | 8 | ping: {} 9 | 10 | api: 11 | dashboard: true 12 | 13 | providers: 14 | providersThrottleDuration: 30s 15 | 16 | docker: 17 | endpoint: unix:///var/run/docker.sock 18 | watch: true 19 | network: supabase 20 | # Default host rule to container_name.domain.example 21 | defaultRule: "Host(`{{ lower (trimPrefix `/` .Name )}}.acme.localhost`)" 22 | swarmModeRefreshSeconds: 15s 23 | exposedByDefault: false 24 | 25 | file: 26 | filename: /etc/traefik/fileConfig.yml 27 | watch: true 28 | 29 | accessLog: 30 | bufferingSize: 100 31 | # filePath: log/traefik.log | "os.Stdout" (Default) 32 | # format: "json" | "common" (Default) 33 | 34 | log: 35 | level: INFO 36 | # filePath: log/traefik.log | "os.Stdout" (Default) 37 | # format: "json" | "common" (Default) 38 | 39 | entryPoints: 40 | # Not used in apps, but redirect everything from HTTP to HTTPS 41 | http: 42 | address: ':80' 43 | http: 44 | redirections: 45 | entryPoint: 46 | permanent: true 47 | to: https 48 | scheme: https 49 | 50 | # HTTPS endpoint, with domain wildcard 51 | https: 52 | address: ':443' 53 | -------------------------------------------------------------------------------- /deploy/supabase/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartekus/self-host-supabase-local-dev/469487d28adfc418350bd77c2e5f4cde00cd9c4d/deploy/supabase/.gitkeep -------------------------------------------------------------------------------- /scripts/create-local-certs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Navigate to the directory local ingress directory and start it 4 | cd ./deploy/local-ingress/cert && mkcert -key-file key.pem -cert-file cert.pem "acme.localhost" "*.acme.localhost" && cd - || exit 5 | -------------------------------------------------------------------------------- /scripts/supabase-amend-docker-compose.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Path to the docker-compose.yml file 4 | file_path="deploy/supabase/docker-compose.yml" 5 | 6 | # Services to update with the network configuration 7 | services=("studio" "kong" "auth" "rest" "realtime" "storage" "imgproxy" "meta" "functions" "analytics" "db" "vector") 8 | 9 | # Loop over each service and insert the network configuration 10 | for service in "${services[@]}"; do 11 | sed -i '' -e "/^ $service:/s/$/\\ 12 | networks:\ 13 | \\n - supabase/" "$file_path" 14 | done 15 | 16 | # Add global network configuration at the end of the file 17 | echo -e "\nnetworks:\n supabase:\n driver: bridge\n external: true" >> "$file_path" 18 | -------------------------------------------------------------------------------- /scripts/supabase-docker-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Target directory 4 | TARGET_DIR="./deploy/supabase" 5 | mkdir -p $TARGET_DIR # Ensure the target directory exists 6 | 7 | # Base URL for raw files 8 | BASE_URL="https://raw.githubusercontent.com/supabase/supabase/master/docker" 9 | 10 | # An array of relative file paths 11 | declare -a files=( 12 | "dev/data.sql" 13 | "dev/docker-compose.dev.yml" 14 | "volumes/api/kong.yml" 15 | "volumes/db/init/data.sql" 16 | "volumes/db/jwt.sql" 17 | "volumes/db/logs.sql" 18 | "volumes/db/realtime.sql" 19 | "volumes/db/roles.sql" 20 | "volumes/db/webhooks.sql" 21 | "volumes/functions/hello/index.ts" 22 | "volumes/functions/main/index.ts" 23 | "volumes/logs/vector.yml" 24 | "docker-compose.s3.yml" 25 | "docker-compose.yml" 26 | ) 27 | 28 | # Loop through the array, downloading each file 29 | for file in "${files[@]}"; do 30 | # Create the directory structure in the target directory 31 | mkdir -p "$TARGET_DIR/$(dirname $file)" 32 | 33 | # Construct the full local path for the file 34 | local_path="$TARGET_DIR/$file" 35 | 36 | echo "Downloading $file to $local_path..." 37 | curl -o "$local_path" "$BASE_URL/$file" 38 | done 39 | 40 | echo "All files have been downloaded successfully to $TARGET_DIR." 41 | -------------------------------------------------------------------------------- /setup-repo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cp .env.example .env 4 | cp ./deploy/local-ingress/traefik/htpasswd.example ./deploy/local-ingress/traefik/htpasswd 5 | 6 | ./scripts/create-local-certs.sh 7 | ./scripts/supabase-docker-update.sh 8 | ./scripts/supabase-amend-docker-compose.sh 9 | -------------------------------------------------------------------------------- /start-local-infra.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # .env file at the root 4 | ENV_FILE="${PWD}/.env" 5 | 6 | # Create supabase network 7 | docker network create supabase 8 | 9 | # Navigate to the directory local ingress directory and start it 10 | cd ./deploy/local-ingress && docker compose -f docker-compose.yml --env-file "$ENV_FILE" up --build --force-recreate -d --renew-anon-volumes && cd - || exit 11 | 12 | # Navigate to the directory supabase directory and start it 13 | cd ./deploy/supabase && docker compose -f docker-compose.yml --env-file "$ENV_FILE" up --build --force-recreate -d --renew-anon-volumes && cd - || exit 14 | -------------------------------------------------------------------------------- /stop-local-infra.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # .env file at the root 4 | ENV_FILE="${PWD}/.env" 5 | 6 | # Navigate to the directory local ingress directory and start it 7 | cd ./deploy/local-ingress && docker compose -f docker-compose.yml --env-file "$ENV_FILE" down --rmi local --volumes --remove-orphans -t 1 && cd - || exit 8 | 9 | # Navigate to the directory supabase directory and start it 10 | cd ./deploy/supabase && docker compose -f docker-compose.yml --env-file "$ENV_FILE" down --rmi local --volumes --remove-orphans -t 1 && cd - || exit 11 | 12 | # Destroy supabase network 13 | docker network rm supabase 14 | -------------------------------------------------------------------------------- /wipe-supabase-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf ./deploy/supabase/volumes/db/data 4 | rm -rf ./deploy/supabase/volumes/storage 5 | --------------------------------------------------------------------------------