mirror of
https://github.com/Eugeny/tabby-web.git
synced 2025-06-08 05:29:52 +00:00
.
This commit is contained in:
parent
e541269392
commit
eac64152b8
51
README.md
51
README.md
@ -1,3 +1,19 @@
|
|||||||
|
# Tabby Web
|
||||||
|
|
||||||
|
This is the exact code that runs at https://tabby.sh. In fact, it's being deployed straight out of this repository.
|
||||||
|
|
||||||
|
You can use this to deploy your own copy or to make improvements - pull requests are welcome!
|
||||||
|
|
||||||
|
# How it works
|
||||||
|
|
||||||
|
Tabby Web serves the Tabby Terminal as a web application while managing multiple config files, authentication, and providing TCP connections via a [separate gateway service](https://github.com/Eugeny/tabby-connection-gateway).
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
* Python 3.7+
|
||||||
|
* A database server supported by Django (MariaDB, Postgres, SQLite, etc.)
|
||||||
|
* Storage for distribution files - local, S3, GCS or others supported by `fsspec`
|
||||||
|
|
||||||
# Using Docker images
|
# Using Docker images
|
||||||
|
|
||||||
Tabby Web consists of two Docker images - `backend` and `frontend`. See an example set up in `docker-compose.yml`
|
Tabby Web consists of two Docker images - `backend` and `frontend`. See an example set up in `docker-compose.yml`
|
||||||
@ -6,7 +22,7 @@ Tabby Web consists of two Docker images - `backend` and `frontend`. See an examp
|
|||||||
|
|
||||||
### Frontend
|
### Frontend
|
||||||
|
|
||||||
* `BACKEND_URL`
|
* `BACKEND_URL` (required if running the backend in a separate Docker container).
|
||||||
* `WEB_CONCURRENCY`
|
* `WEB_CONCURRENCY`
|
||||||
|
|
||||||
### Backend
|
### Backend
|
||||||
@ -15,8 +31,35 @@ Tabby Web consists of two Docker images - `backend` and `frontend`. See an examp
|
|||||||
* `FRONTEND_URL`
|
* `FRONTEND_URL`
|
||||||
* `APP_DIST_STORAGE`: a `file://`, `s3://`, or `gcs://` URL to store app distros in.
|
* `APP_DIST_STORAGE`: a `file://`, `s3://`, or `gcs://` URL to store app distros in.
|
||||||
* `SOCIAL_AUTH_*_KEY` & `SOCIAL_AUTH_*_SECRET`: social login credentials, supported providers are `GITHUB`, `GITLAB`, `MICROSOFT_GRAPH` and `GOOGLE_OAUTH2`.
|
* `SOCIAL_AUTH_*_KEY` & `SOCIAL_AUTH_*_SECRET`: social login credentials, supported providers are `GITHUB`, `GITLAB`, `MICROSOFT_GRAPH` and `GOOGLE_OAUTH2`.
|
||||||
* `ENABLE_HOMEPAGE`: set to `False` to disable the homepage and always redirect to the app.
|
|
||||||
|
|
||||||
## Installing Tabby app versions
|
## Adding Tabby app versions
|
||||||
|
|
||||||
* `docker-compose run backend ./manage.py add_version 1.0.156-nightly.1`
|
* `docker-compose run backend ./manage.py add_version 1.0.156-nightly.2`
|
||||||
|
|
||||||
|
# Development setup
|
||||||
|
|
||||||
|
Put your environment vars (`DATABASE_URL`, etc.) in the `.env` file in the root of the repo.
|
||||||
|
|
||||||
|
For the frontend:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd frontend
|
||||||
|
yarn
|
||||||
|
yarn run build # or yarn run watch
|
||||||
|
```
|
||||||
|
|
||||||
|
For the backend:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd backend
|
||||||
|
poetry install
|
||||||
|
./manage.py migrate # set up the database
|
||||||
|
./manage.py add_version 1.0.156-nightly.2 # install an app distribution
|
||||||
|
PORT=9000 poetry run gunicorn # optionally with --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# Security
|
||||||
|
|
||||||
|
* When using Tabby Web for SSH/Telnet connectivity, your traffic will pass through a hosted gateway service. It's encrypted in transit (HTTPS) and the gateway servers authenticate themselves with a certificate before connections are made. However there's a non-zero risk of a MITM if a gateway service is compromised and the attacker gains access to the service's private key.
|
||||||
|
* You can alleviate this risk by [hosting your own gateway service](https://github.com/Eugeny/tabby-connection-gateway), or your own copy of Tabby Web altogether.
|
||||||
|
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
|
public
|
||||||
|
17
backend/poetry.lock
generated
17
backend/poetry.lock
generated
@ -602,6 +602,17 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6.1"
|
python-versions = ">=3.6.1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "whitenoise"
|
||||||
|
version = "5.3.0"
|
||||||
|
description = "Radically simplified static file serving for WSGI applications"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5, <4"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
brotli = ["brotli"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zipp"
|
name = "zipp"
|
||||||
version = "3.4.1"
|
version = "3.4.1"
|
||||||
@ -630,7 +641,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.7"
|
python-versions = "^3.7"
|
||||||
content-hash = "a855859b9c8eb70c722c6e1ce320e3b4a8b554b8eeb12e42cfaea4dce857855d"
|
content-hash = "bb7f88af57c4e8e37ff32e12d3f8627cd64aef874617d88c68fa0f16be8a6de1"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
asgiref = [
|
asgiref = [
|
||||||
@ -949,6 +960,10 @@ websockets = [
|
|||||||
{file = "websockets-9.1-cp39-cp39-win_amd64.whl", hash = "sha256:85db8090ba94e22d964498a47fdd933b8875a1add6ebc514c7ac8703eb97bbf0"},
|
{file = "websockets-9.1-cp39-cp39-win_amd64.whl", hash = "sha256:85db8090ba94e22d964498a47fdd933b8875a1add6ebc514c7ac8703eb97bbf0"},
|
||||||
{file = "websockets-9.1.tar.gz", hash = "sha256:276d2339ebf0df4f45df453923ebd2270b87900eda5dfd4a6b0cfa15f82111c3"},
|
{file = "websockets-9.1.tar.gz", hash = "sha256:276d2339ebf0df4f45df453923ebd2270b87900eda5dfd4a6b0cfa15f82111c3"},
|
||||||
]
|
]
|
||||||
|
whitenoise = [
|
||||||
|
{file = "whitenoise-5.3.0-py2.py3-none-any.whl", hash = "sha256:d963ef25639d1417e8a247be36e6aedd8c7c6f0a08adcb5a89146980a96b577c"},
|
||||||
|
{file = "whitenoise-5.3.0.tar.gz", hash = "sha256:d234b871b52271ae7ed6d9da47ffe857c76568f11dd30e28e18c5869dbd11e12"},
|
||||||
|
]
|
||||||
zipp = [
|
zipp = [
|
||||||
{file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"},
|
{file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"},
|
||||||
{file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"},
|
{file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"},
|
||||||
|
0
backend/public/.gitkeep
Normal file
0
backend/public/.gitkeep
Normal file
@ -23,6 +23,7 @@ pyga = "^2.6.2"
|
|||||||
django-cors-headers = "^3.7.0"
|
django-cors-headers = "^3.7.0"
|
||||||
cryptography = "3.0"
|
cryptography = "3.0"
|
||||||
fsspec = "^2021.7.0"
|
fsspec = "^2021.7.0"
|
||||||
|
whitenoise = "^5.3.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
flake8 = "^3.9.2"
|
flake8 = "^3.9.2"
|
||||||
|
@ -42,6 +42,7 @@ INSTALLED_APPS = [
|
|||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
@ -145,6 +146,7 @@ LOGGING = {
|
|||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATICFILES_DIRS = [FRONTEND_BUILD_DIR]
|
STATICFILES_DIRS = [FRONTEND_BUILD_DIR]
|
||||||
|
STATIC_ROOT = BASE_DIR / 'public'
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
from django.conf import settings
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from django.views.static import serve
|
|
||||||
from .app.urls import urlpatterns as app_urlpatterns
|
from .app.urls import urlpatterns as app_urlpatterns
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(app_urlpatterns)),
|
path('', include(app_urlpatterns)),
|
||||||
path('api/1/auth/social/', include('social_django.urls', namespace='social')),
|
path('api/1/auth/social/', include('social_django.urls', namespace='social')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
# path(f'{settings.STATIC_URL.strip("/")}/<path:path>', serve, kwargs={
|
]
|
||||||
# 'document_root': settings.STATIC_ROOT,
|
|
||||||
# }),
|
|
||||||
] + staticfiles_urlpatterns(settings.STATIC_URL)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user