Support unified docker + k8s deployment (#58)
- adapt nginx config to work both in docker and k8s, using env vars to set urls backend: additional fixes: - use env vars with nginx config - fix settings api route - when sending e-mail, use the Host header for verification urls when available - prepare Dockerfile with full build from scratch in image, (disabled 'yarn install' for faster builds for now) - fix accept invite api for existing user to /archives/accept-invite/{token}
This commit is contained in:
parent
87c5505c43
commit
eaf8055063
@ -7,7 +7,7 @@ from datetime import datetime
|
|||||||
from typing import Dict, Union, Literal, Optional
|
from typing import Dict, Union, Literal, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||||
|
|
||||||
from db import BaseMongoModel
|
from db import BaseMongoModel
|
||||||
|
|
||||||
@ -298,18 +298,24 @@ def init_archives_api(app, mdb, user_manager, invites, user_dep: User):
|
|||||||
@router.post("/invite", tags=["invites"])
|
@router.post("/invite", tags=["invites"])
|
||||||
async def invite_user_to_archive(
|
async def invite_user_to_archive(
|
||||||
invite: InviteToArchiveRequest,
|
invite: InviteToArchiveRequest,
|
||||||
|
request: Request,
|
||||||
archive: Archive = Depends(archive_owner_dep),
|
archive: Archive = Depends(archive_owner_dep),
|
||||||
user: User = Depends(user_dep),
|
user: User = Depends(user_dep),
|
||||||
):
|
):
|
||||||
|
|
||||||
if await invites.invite_user(
|
if await invites.invite_user(
|
||||||
invite, user, user_manager, archive=archive, allow_existing=True
|
invite,
|
||||||
|
user,
|
||||||
|
user_manager,
|
||||||
|
archive=archive,
|
||||||
|
allow_existing=True,
|
||||||
|
headers=request.headers,
|
||||||
):
|
):
|
||||||
return {"invited": "new_user"}
|
return {"invited": "new_user"}
|
||||||
|
|
||||||
return {"invited": "existing_user"}
|
return {"invited": "existing_user"}
|
||||||
|
|
||||||
@app.get("/invite/accept/{token}", tags=["invites"])
|
@app.post("/archives/invite-accept/{token}", tags=["invites"])
|
||||||
async def accept_invite(token: str, user: User = Depends(user_dep)):
|
async def accept_invite(token: str, user: User = Depends(user_dep)):
|
||||||
invite = invites.accept_user_invite(user, token)
|
invite = invites.accept_user_invite(user, token)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class EmailSender:
|
|||||||
self.password = os.environ.get("EMAIL_PASSWORD")
|
self.password = os.environ.get("EMAIL_PASSWORD")
|
||||||
self.smtp_server = os.environ.get("EMAIL_SMTP_HOST")
|
self.smtp_server = os.environ.get("EMAIL_SMTP_HOST")
|
||||||
|
|
||||||
self.host = os.environ.get("APP_ORIGIN")
|
self.default_origin = os.environ.get("APP_ORIGIN")
|
||||||
|
|
||||||
def _send_encrypted(self, receiver, message):
|
def _send_encrypted(self, receiver, message):
|
||||||
"""Send Encrypted SMTP Message"""
|
"""Send Encrypted SMTP Message"""
|
||||||
@ -32,47 +32,71 @@ class EmailSender:
|
|||||||
server.login(self.sender, self.password)
|
server.login(self.sender, self.password)
|
||||||
server.sendmail(self.sender, receiver, message)
|
server.sendmail(self.sender, receiver, message)
|
||||||
|
|
||||||
def send_user_validation(self, receiver_email, token):
|
def get_origin(self, headers):
|
||||||
|
""" Return origin of the received request"""
|
||||||
|
scheme = headers.get("X-Forwarded-Proto")
|
||||||
|
if not scheme:
|
||||||
|
scheme = "http"
|
||||||
|
|
||||||
|
host = headers.get("Host")
|
||||||
|
if not host:
|
||||||
|
host = self.default_origin
|
||||||
|
|
||||||
|
return scheme + "://" + host
|
||||||
|
|
||||||
|
def send_user_validation(self, receiver_email, token, headers=None):
|
||||||
"""Send email to validate registration email address"""
|
"""Send email to validate registration email address"""
|
||||||
|
|
||||||
|
origin = self.get_origin(headers)
|
||||||
|
|
||||||
message = f"""
|
message = f"""
|
||||||
Please verify your registration for Browsertrix Cloud for {receiver_email}
|
Please verify your registration for Browsertrix Cloud for {receiver_email}
|
||||||
|
|
||||||
You can verify by clicking here: {self.host}/verify?token={token}
|
You can verify by clicking here: {origin}/verify?token={token}
|
||||||
|
|
||||||
The verification token is: {token}"""
|
The verification token is: {token}"""
|
||||||
|
|
||||||
self._send_encrypted(receiver_email, message)
|
self._send_encrypted(receiver_email, message)
|
||||||
|
|
||||||
def send_new_user_invite(self, receiver_email, sender, archive_name, token):
|
# pylint: disable=too-many-arguments
|
||||||
|
def send_new_user_invite(
|
||||||
|
self, receiver_email, sender, archive_name, token, headers=None
|
||||||
|
):
|
||||||
"""Send email to invite new user"""
|
"""Send email to invite new user"""
|
||||||
|
|
||||||
|
origin = self.get_origin(headers)
|
||||||
|
|
||||||
message = f"""
|
message = f"""
|
||||||
You are invited by {sender} to join their archive, "{archive_name}" on Browsertrix Cloud!
|
You are invited by {sender} to join their archive, "{archive_name}" on Browsertrix Cloud!
|
||||||
|
|
||||||
You can join by clicking here: {self.host}/join/{token}?email={receiver_email}
|
You can join by clicking here: {origin}/join/{token}?email={receiver_email}
|
||||||
|
|
||||||
The invite token is: {token}"""
|
The invite token is: {token}"""
|
||||||
|
|
||||||
self._send_encrypted(receiver_email, message)
|
self._send_encrypted(receiver_email, message)
|
||||||
|
|
||||||
def send_existing_user_invite(self, receiver_email, sender, archive_name, token):
|
# pylint: disable=too-many-arguments
|
||||||
|
def send_existing_user_invite(
|
||||||
|
self, receiver_email, sender, archive_name, token, headers=None
|
||||||
|
):
|
||||||
"""Send email to invite new user"""
|
"""Send email to invite new user"""
|
||||||
|
origin = self.get_origin(headers)
|
||||||
|
|
||||||
message = f"""
|
message = f"""
|
||||||
You are invited by {sender} to join their archive, "{archive_name}" on Browsertrix Cloud!
|
You are invited by {sender} to join their archive, "{archive_name}" on Browsertrix Cloud!
|
||||||
|
|
||||||
You can join by clicking here: {self.host}/invite/accept/{token}?email={receiver_email}
|
You can join by clicking here: {origin}/invite/accept/{token}?email={receiver_email}
|
||||||
|
|
||||||
The invite token is: {token}"""
|
The invite token is: {token}"""
|
||||||
|
|
||||||
self._send_encrypted(receiver_email, message)
|
self._send_encrypted(receiver_email, message)
|
||||||
|
|
||||||
|
def send_user_forgot_password(self, receiver_email, token, headers=None):
|
||||||
|
|
||||||
def send_user_forgot_password(self, receiver_email, token):
|
|
||||||
"""Send password reset email with token"""
|
"""Send password reset email with token"""
|
||||||
|
origin = self.get_origin(headers)
|
||||||
|
|
||||||
message = f"""
|
message = f"""
|
||||||
We received your password reset request. Please click here: {self.host}/reset-password?token={token}
|
We received your password reset request. Please click here: {origin}/reset-password?token={token}
|
||||||
to create a new password
|
to create a new password
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ class InviteOps:
|
|||||||
new_user_invite: NewUserInvite,
|
new_user_invite: NewUserInvite,
|
||||||
inviter_email: str,
|
inviter_email: str,
|
||||||
archive_name: Optional[str],
|
archive_name: Optional[str],
|
||||||
|
headers: Optional[dict],
|
||||||
):
|
):
|
||||||
"""Add invite for new user"""
|
"""Add invite for new user"""
|
||||||
|
|
||||||
@ -76,7 +77,11 @@ class InviteOps:
|
|||||||
await self.invites.insert_one(new_user_invite.to_dict())
|
await self.invites.insert_one(new_user_invite.to_dict())
|
||||||
|
|
||||||
self.email.send_new_user_invite(
|
self.email.send_new_user_invite(
|
||||||
new_user_invite.email, inviter_email, archive_name, new_user_invite.id
|
new_user_invite.email,
|
||||||
|
inviter_email,
|
||||||
|
archive_name,
|
||||||
|
new_user_invite.id,
|
||||||
|
headers,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def get_valid_invite(self, invite_token: str, user):
|
async def get_valid_invite(self, invite_token: str, user):
|
||||||
@ -115,6 +120,7 @@ class InviteOps:
|
|||||||
user_manager,
|
user_manager,
|
||||||
archive=None,
|
archive=None,
|
||||||
allow_existing=False,
|
allow_existing=False,
|
||||||
|
headers: dict = None,
|
||||||
):
|
):
|
||||||
"""create new invite for user to join, optionally an archive.
|
"""create new invite for user to join, optionally an archive.
|
||||||
if allow_existing is false, don't allow invites to existing users"""
|
if allow_existing is false, don't allow invites to existing users"""
|
||||||
@ -141,6 +147,7 @@ class InviteOps:
|
|||||||
),
|
),
|
||||||
user.email,
|
user.email,
|
||||||
archive_name,
|
archive_name,
|
||||||
|
headers,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -160,7 +167,7 @@ class InviteOps:
|
|||||||
await user_manager.user_db.update(other_user)
|
await user_manager.user_db.update(other_user)
|
||||||
|
|
||||||
self.email.send_existing_user_invite(
|
self.email.send_existing_user_invite(
|
||||||
other_user.email, user.name, archive_name,invite_code
|
other_user.email, user.name, archive_name, invite_code, headers
|
||||||
)
|
)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -85,7 +85,7 @@ def main():
|
|||||||
|
|
||||||
app.include_router(archive_ops.router)
|
app.include_router(archive_ops.router)
|
||||||
|
|
||||||
@app.get("/api/settings")
|
@app.get("/settings")
|
||||||
async def get_settings():
|
async def get_settings():
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
uvicorn
|
uvicorn
|
||||||
|
fastapi==0.70.0
|
||||||
fastapi-users[mongodb]==8.1.2
|
fastapi-users[mongodb]==8.1.2
|
||||||
loguru
|
loguru
|
||||||
aiofiles
|
aiofiles
|
||||||
|
@ -163,7 +163,9 @@ class UserManager(BaseUserManager[UserCreate, UserDB]):
|
|||||||
):
|
):
|
||||||
"""callback after password forgot"""
|
"""callback after password forgot"""
|
||||||
print(f"User {user.id} has forgot their password. Reset token: {token}")
|
print(f"User {user.id} has forgot their password. Reset token: {token}")
|
||||||
self.email.send_user_forgot_password(user.email, token)
|
self.email.send_user_forgot_password(
|
||||||
|
user.email, token, request and request.headers
|
||||||
|
)
|
||||||
|
|
||||||
###pylint: disable=no-self-use, unused-argument
|
###pylint: disable=no-self-use, unused-argument
|
||||||
async def on_after_request_verify(
|
async def on_after_request_verify(
|
||||||
@ -171,7 +173,7 @@ class UserManager(BaseUserManager[UserCreate, UserDB]):
|
|||||||
):
|
):
|
||||||
"""callback after verification request"""
|
"""callback after verification request"""
|
||||||
|
|
||||||
self.email.send_user_validation(user.email, token)
|
self.email.send_user_validation(user.email, token, request and request.headers)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@ -240,13 +242,19 @@ def init_users_api(app, user_manager):
|
|||||||
@users_router.post("/invite", tags=["invites"])
|
@users_router.post("/invite", tags=["invites"])
|
||||||
async def invite_user(
|
async def invite_user(
|
||||||
invite: InviteRequest,
|
invite: InviteRequest,
|
||||||
|
request: Request,
|
||||||
user: User = Depends(current_active_user),
|
user: User = Depends(current_active_user),
|
||||||
):
|
):
|
||||||
# if not user.is_superuser:
|
if not user.is_superuser:
|
||||||
# raise HTTPException(status_code=403, detail="Not Allowed")
|
raise HTTPException(status_code=403, detail="Not Allowed")
|
||||||
|
|
||||||
await user_manager.invites.invite_user(
|
await user_manager.invites.invite_user(
|
||||||
invite, user, user_manager, archive=None, allow_existing=False
|
invite,
|
||||||
|
user,
|
||||||
|
user_manager,
|
||||||
|
archive=None,
|
||||||
|
allow_existing=False,
|
||||||
|
headers=request.headers,
|
||||||
)
|
)
|
||||||
|
|
||||||
return {"invited": "new_user"}
|
return {"invited": "new_user"}
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
worker_processes 1;
|
|
||||||
error_log stderr;
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
access_log /dev/stdout;
|
|
||||||
sendfile on;
|
|
||||||
keepalive_timeout 65;
|
|
||||||
include ./resolvers/resolvers.conf;
|
|
||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
server_name _;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_buffers 16 64k;
|
|
||||||
proxy_buffer_size 64k;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
error_page 500 501 502 503 504 /50x.html;
|
|
||||||
merge_slashes off;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* /watch/([^/]+)/([^/]+)/ws {
|
|
||||||
set $archive $1;
|
|
||||||
set $crawl $2;
|
|
||||||
#auth_request /authcheck;
|
|
||||||
|
|
||||||
proxy_pass http://$2.crawlers.svc.cluster.local:9037/ws;
|
|
||||||
proxy_set_header Host "localhost";
|
|
||||||
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $http_connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* /watch/([^/]+)/([^/]+)/ {
|
|
||||||
set $archive $1;
|
|
||||||
set $crawl $2;
|
|
||||||
#auth_request /authcheck;
|
|
||||||
|
|
||||||
proxy_pass http://$2.crawlers.svc.cluster.local:9037/;
|
|
||||||
proxy_set_header Host "localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /authcheck {
|
|
||||||
internal;
|
|
||||||
proxy_pass http://localhost:8000/archives/$archive/crawls/$crawl;
|
|
||||||
proxy_pass_request_body off;
|
|
||||||
proxy_set_header Content-Length "";
|
|
||||||
}
|
|
||||||
|
|
||||||
location /healthz {
|
|
||||||
return 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
#proxy_pass http://localhost:8000/;
|
|
||||||
#proxy_set_header Host $host;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -48,6 +48,13 @@ spec:
|
|||||||
mountPath: /etc/nginx/resolvers/
|
mountPath: /etc/nginx/resolvers/
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
- name: BACKEND_HOST
|
||||||
|
value: {{ .Values.name }}-frontend
|
||||||
|
|
||||||
|
- name: BROWSER_SCREENCAST_URL
|
||||||
|
value: http://$2.crawlers.svc.cluster.local:9037
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: {{ .Values.nginx_limit_cpu }}
|
cpu: {{ .Values.nginx_limit_cpu }}
|
||||||
@ -57,7 +64,7 @@ spec:
|
|||||||
|
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -4,9 +4,6 @@ services:
|
|||||||
backend:
|
backend:
|
||||||
build: ./backend
|
build: ./backend
|
||||||
image: registry.digitalocean.com/btrix/webrecorder/browsertrix-api
|
image: registry.digitalocean.com/btrix/webrecorder/browsertrix-api
|
||||||
ports:
|
|
||||||
- 8000:8000
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
||||||
@ -17,11 +14,21 @@ services:
|
|||||||
- minio
|
- minio
|
||||||
- mongo
|
- mongo
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build: ./frontend
|
build: ./frontend
|
||||||
image: registry.digitalocean.com/btrix/webrecorder/browsertrix-frontend
|
image: registry.digitalocean.com/btrix/webrecorder/browsertrix-frontend
|
||||||
ports:
|
ports:
|
||||||
- 8010:80
|
- 9870:80
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- BACKEND_HOST=backend
|
||||||
|
- BROWSER_SCREENCAST_URL=http://$$2:9037
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis
|
image: redis
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
|
FROM node:16 as build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
# disabled to speed up build, assuming built locally
|
||||||
|
#RUN yarn
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
FROM nginx
|
FROM nginx
|
||||||
|
|
||||||
COPY ./dist/ /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
COPY --from=build /app/nginx.conf.template /etc/nginx/templates/
|
||||||
|
|
||||||
|
#COPY ./dist /usr/share/nginx/html
|
||||||
|
#COPY ./nginx.conf.template /etc/nginx/templates/
|
||||||
|
|
||||||
|
RUN rm /etc/nginx/conf.d/*
|
||||||
|
|
||||||
|
RUN mkdir -p /etc/nginx/resolvers; echo "" > /etc/nginx/resolvers/resolvers.conf
|
||||||
|
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
worker_processes 1;
|
|
||||||
error_log stderr;
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
access_log /dev/stdout;
|
|
||||||
sendfile on;
|
|
||||||
keepalive_timeout 65;
|
|
||||||
include ./resolvers/resolvers.conf;
|
|
||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
server_name _;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_buffers 16 64k;
|
|
||||||
proxy_buffer_size 64k;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
|
|
||||||
error_page 500 501 502 503 504 /50x.html;
|
|
||||||
|
|
||||||
merge_slashes off;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# fallback to index for any page
|
|
||||||
error_page 404 /index.html;
|
|
||||||
|
|
||||||
location ~* /watch/([^/]+)/([^/]+)/ws {
|
|
||||||
set $archive $1;
|
|
||||||
set $crawl $2;
|
|
||||||
#auth_request /authcheck;
|
|
||||||
|
|
||||||
proxy_pass http://$2.crawlers.svc.cluster.local:9037/ws;
|
|
||||||
proxy_set_header Host "localhost";
|
|
||||||
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $http_connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* /watch/([^/]+)/([^/]+)/ {
|
|
||||||
set $archive $1;
|
|
||||||
set $crawl $2;
|
|
||||||
#auth_request /authcheck;
|
|
||||||
|
|
||||||
proxy_pass http://$2.crawlers.svc.cluster.local:9037/;
|
|
||||||
proxy_set_header Host "localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /authcheck {
|
|
||||||
internal;
|
|
||||||
proxy_pass http://localhost:8000/archives/$archive/crawls/$crawl;
|
|
||||||
proxy_pass_request_body off;
|
|
||||||
proxy_set_header Content-Length "";
|
|
||||||
}
|
|
||||||
|
|
||||||
location /healthz {
|
|
||||||
return 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
#proxy_pass http://localhost:8000/;
|
|
||||||
#proxy_set_header Host $host;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
63
frontend/nginx.conf.template
Normal file
63
frontend/nginx.conf.template
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
include ./resolvers/resolvers.conf;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
server_name _;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_buffers 16 64k;
|
||||||
|
proxy_buffer_size 64k;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
|
||||||
|
error_page 500 501 502 503 504 /50x.html;
|
||||||
|
|
||||||
|
merge_slashes off;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# fallback to index for any page
|
||||||
|
error_page 404 /index.html;
|
||||||
|
|
||||||
|
location ~* /watch/([^/]+)/([^/]+)/ws {
|
||||||
|
set $archive $1;
|
||||||
|
set $crawl $2;
|
||||||
|
#auth_request /authcheck;
|
||||||
|
|
||||||
|
proxy_pass ${BROWSER_SCREENCAST_URL}/ws;
|
||||||
|
proxy_set_header Host "localhost";
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $http_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* /watch/([^/]+)/([^/]+)/ {
|
||||||
|
set $archive $1;
|
||||||
|
set $crawl $2;
|
||||||
|
#auth_request /authcheck;
|
||||||
|
|
||||||
|
proxy_pass ${BROWSER_SCREENCAST_URL}/;
|
||||||
|
proxy_set_header Host "localhost";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /authcheck {
|
||||||
|
internal;
|
||||||
|
proxy_pass http://localhost:8000/archives/$archive/crawls/$crawl;
|
||||||
|
proxy_pass_request_body off;
|
||||||
|
proxy_set_header Content-Length "";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
}
|
||||||
|
|
||||||
|
# used by docker only: k8s deployment handles /api directly via ingress
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://${BACKEND_HOST}:8000/;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user