This commit is contained in:
Eugene Pankov
2021-08-25 01:25:49 +02:00
parent f0497a081a
commit e541269392
12 changed files with 123 additions and 14 deletions

22
README.md Normal file
View File

@@ -0,0 +1,22 @@
# Using Docker images
Tabby Web consists of two Docker images - `backend` and `frontend`. See an example set up in `docker-compose.yml`
## Environment variables
### Frontend
* `BACKEND_URL`
* `WEB_CONCURRENCY`
### Backend
* `DATABASE_URL` (required).
* `FRONTEND_URL`
* `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`.
* `ENABLE_HOMEPAGE`: set to `False` to disable the homepage and always redirect to the app.
## Installing Tabby app versions
* `docker-compose run backend ./manage.py add_version 1.0.156-nightly.1`

0
app-dist/.gitkeep Normal file
View File

View File

@@ -81,6 +81,7 @@ class AppVersionViewSet(ListModelMixin, GenericViewSet):
return [
self._get_version(x['name'])
for x in fs.listdir(settings.APP_DIST_STORAGE)
if x['type'] == 'directory'
]
def _get_version(self, dir):

View File

@@ -1,6 +1,8 @@
import fsspec
import os
from fsspec.implementations.local import LocalFileSystem
from django.conf import settings
from django.http.response import HttpResponseRedirect
from django.http.response import FileResponse, HttpResponseNotFound, HttpResponseRedirect
from django.views import static
from rest_framework.views import APIView
from urllib.parse import urlparse
@@ -24,4 +26,9 @@ class AppDistView(APIView):
def get(self, request, version=None, path=None, format=None):
fs = fsspec.filesystem(urlparse(settings.APP_DIST_STORAGE).scheme)
url = f'{settings.APP_DIST_STORAGE}/{version}/{path}'
return HttpResponseRedirect(fs.url(url))
if isinstance(fs, LocalFileSystem):
if not fs.exists(url):
return HttpResponseNotFound()
return FileResponse(fs.open(url), filename=os.path.basename(url))
else:
return HttpResponseRedirect(fs.url(url))

View File

@@ -1,5 +1,6 @@
from django.conf import settings
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path, include
from django.views.static import serve
from .app.urls import urlpatterns as app_urlpatterns
@@ -8,7 +9,7 @@ urlpatterns = [
path('', include(app_urlpatterns)),
path('api/1/auth/social/', include('social_django.urls', namespace='social')),
path('admin/', admin.site.urls),
path(f'{settings.STATIC_URL.strip("/")}/<path:path>', serve, kwargs={
'document_root': settings.STATIC_ROOT,
}),
]
# path(f'{settings.STATIC_URL.strip("/")}/<path:path>', serve, kwargs={
# 'document_root': settings.STATIC_ROOT,
# }),
] + staticfiles_urlpatterns(settings.STATIC_URL)

21
docker-compose.yml Normal file
View File

@@ -0,0 +1,21 @@
services:
frontend:
build: frontend
ports:
- 9090:80
environment:
- PORT=80
- BACKEND_URL=http://localhost:9091
backend:
build: backend
ports:
- 9091:80
volumes:
- ./app-dist:/app-dist
environment:
- DATABASE_URL
- PORT=80
- FRONTEND_URL=http://localhost:9090
- ENABLE_HOMEPAGE=False
- DEBUG=False
- APP_DIST_STORAGE=file:///app-dist

View File

@@ -7,8 +7,6 @@ steps:
- '${_DOCKER_TAG}'
- '--cache-from'
- '${_DOCKER_TAG}'
- '--build-arg'
- 'BACKEND_URL=${_BACKEND_URL}'
- '.'
images: ['${_DOCKER_TAG}']

View File

@@ -21,6 +21,8 @@
<meta property="twitter:title" content="Tabby - a terminal for a more modern age">
<meta property="twitter:description" content="Tabby is a free and open source SSH, local and Telnet terminal with everything you'll ever need.">
<meta property="twitter:image" content="https://user-images.githubusercontent.com/161476/126016449-a053012a-e322-48ed-a2ab-3ed4f3281465.png">
<meta property="x-tabby-web-backend-url" content="{{backendURL}}">
</head>
<body>
<app></app>

View File

@@ -8,6 +8,7 @@ import { enableProdMode } from '@angular/core'
import { ngExpressEngine } from '@nguniversal/express-engine'
import * as express from 'express'
import { join } from 'path'
@@ -42,7 +43,19 @@ function start () {
}))
app.get(['/', '/app', '/login'], (req, res) => {
res.render('index', { req })
res.render(
'index',
{
req,
providers: [
{ provide: 'BACKEND_URL', useValue: process.env.BACKEND_URL ?? '' },
],
},
(err: Error, html: string) => {
html = html.replace('{{backendURL}}', process.env.BACKEND_URL ?? '')
res.status(err ? 500 : 200).send(html || err.message)
},
)
})
app.get(['/terminal'], (req, res) => {

View File

@@ -1,12 +1,23 @@
import { Injectable } from '@angular/core'
declare const BACKEND_URL: any
import { Inject, Injectable, Optional } from '@angular/core'
@Injectable({ providedIn: 'root' })
export class CommonService {
backendURL: string = BACKEND_URL
backendURL: string
constructor () {
constructor (@Inject('BACKEND_URL') @Optional() ssrBackendURL: string) {
const tag = (document.querySelector('meta[property=x-tabby-web-backend-url]') as HTMLMetaElement)
if (ssrBackendURL) {
this.backendURL = ssrBackendURL
tag.content = ssrBackendURL
} else {
if (tag.content && !tag.content.startsWith('{{')) {
this.backendURL = tag.content
} else {
this.backendURL = ''
}
}
console.log(this.backendURL)
if (this.backendURL.endsWith('/')) {
this.backendURL = this.backendURL.slice(0, -1)
}

View File

@@ -1,6 +1,8 @@
import './terminal-styles.scss'
async function start () {
window['__filename'] = ''
await new Promise<void>(resolve => {
window.addEventListener('message', event => {
if (event.data === 'connector-ready') {

View File

@@ -953,6 +953,11 @@ async-foreach@^0.1.3:
resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=
async@~3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8"
integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -2898,6 +2903,13 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
lru-cache@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
dependencies:
yallist "^3.0.2"
magic-string@^0.25.0:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
@@ -3064,6 +3076,20 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
mustache-express@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mustache-express/-/mustache-express-1.3.1.tgz#b5144513ab79a503c87aa8cb16fe019d2f61d9f9"
integrity sha512-RSSzrvM+CVAk9217dkWSNYyl6c2JnesNn6zaZ8+FvZSn8aLxY9l4kTnYqIoiE8GxdLyVQL2ak7XlMZS6t/l8YA==
dependencies:
async "~3.2.0"
lru-cache "~5.1.1"
mustache "^4.2.0"
mustache@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64"
integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==
nan@^2.13.2:
version "2.14.2"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
@@ -4950,6 +4976,11 @@ y18n@^5.0.5:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yallist@^3.0.2:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"