diff --git a/.dockerignore b/.dockerignore index 82b74cf8..e1d3549c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ data -nginx node_modules .env.* .turbo diff --git a/README.md b/README.md index 593d2134..5fa3286b 100644 --- a/README.md +++ b/README.md @@ -73,20 +73,18 @@ Alternatively, you can also run Briefer using Docker directly: # Run Briefer using Docker docker run -d \ -p 3000:3000 \ - -p 8080:8080 \ -v briefer_psql_data:/var/lib/postgresql/data \ -v briefer_jupyter_data:/home/jupyteruser \ -v briefer_briefer_data:/home/briefer \ briefercloud/briefer ``` -When running on Windows' PowerShell, it might be necessary to add an extra ``` ` ``` to the end of each line instead of the `\`, like this: +When running on Windows' PowerShell, it might be necessary to add an extra `` ` `` to the end of each line instead of the `\`, like this: ```bash # Run Briefer using Docker docker run -d ` -p 3000:3000 ` - -p 8080:8080 ` -v briefer_psql_data:/var/lib/postgresql/data ` -v briefer_jupyter_data:/home/jupyteruser ` -v briefer_briefer_data:/home/briefer ` diff --git a/apps/api/src/websocket/index.ts b/apps/api/src/websocket/index.ts index d9d819c1..51bcbdc2 100644 --- a/apps/api/src/websocket/index.ts +++ b/apps/api/src/websocket/index.ts @@ -53,6 +53,7 @@ type Server = { export function createSocketServer(server: http.Server): Server { const io: IOServer = new BaseServer(server, { cors: { credentials: true, origin: config().FRONTEND_URL }, + transports: ['websocket'], }) io.use(async (socket: Socket, next) => { @@ -68,6 +69,13 @@ export function createSocketServer(server: http.Server): Server { next(new Error('Unauthorized')) } } catch (err) { + logger.error( + { + err, + socketId: socket.id, + }, + 'Error authenticating socket connection' + ) next(new Error('Internal Server Error')) } }) @@ -75,8 +83,17 @@ export function createSocketServer(server: http.Server): Server { let workInProgress: Map> = new Map() io.on('connection', (socket: Socket) => { + logger.info({ socketId: socket.id }, 'Client connected to socket server') + const session = socket.session if (!session) { + logger.error( + { + socketId: socket.id, + }, + 'Socket connection did not have a session' + ) + socket.disconnect(true) return } @@ -104,6 +121,20 @@ export function createSocketServer(server: http.Server): Server { trackWork(handleRestartEnvironment(socket, session)) ) socket.on('complete-python', trackWork(completePython(io, socket, session))) + + socket.on('disconnect', (reason) => { + logger.info( + { socketId: socket.id, reason }, + 'Client disconnected from socket server' + ) + }) + + socket.on('error', (error) => { + logger.error( + { socketId: socket.id, error }, + 'Socket server error occurred' + ) + }) }) return { diff --git a/apps/api/src/yjs/v2/index.ts b/apps/api/src/yjs/v2/index.ts index b090c66f..a210f8ad 100644 --- a/apps/api/src/yjs/v2/index.ts +++ b/apps/api/src/yjs/v2/index.ts @@ -68,8 +68,7 @@ async function getRequestData(req: http.IncomingMessage): Promise<{ } | null> { const cookiesHeader = req.headers.cookie const cookies = cookie.parse(cookiesHeader ?? '') - const url = new URL(req.url ?? '', config().API_URL) - const query = qs.parse(url.search.slice(1)) + const query = qs.parse(req.url?.split('?')[1] ?? '') const docId = query['documentId'] const clock = parseInt((query['clock'] ?? '').toString()) const isDataApp = query['isDataApp'] === 'true' diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 5f1383c4..5411284e 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -66,6 +66,6 @@ COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/we COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public COPY --from=installer --chown=nextjs:nodejs /app/apps/web/start.sh ./apps/web/start.sh -EXPOSE 3000 +EXPOSE 4000 CMD ./apps/web/start.sh diff --git a/apps/web/package.json b/apps/web/package.json index 5ac992ef..8102013e 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -3,7 +3,7 @@ "version": "0.0.8", "private": true, "scripts": { - "dev": "next dev --experimental-https && local-ssl-proxy --key", + "dev": "next dev -p 4000 --experimental-https && local-ssl-proxy --key", "build": "next build", "start": "node dist/server.js", "lint": "next lint", diff --git a/apps/web/src/hooks/useWebsocket.tsx b/apps/web/src/hooks/useWebsocket.tsx index b1f9645d..24c6d764 100644 --- a/apps/web/src/hooks/useWebsocket.tsx +++ b/apps/web/src/hooks/useWebsocket.tsx @@ -16,8 +16,12 @@ export function WebsocketProvider({ children }: Props) { const workspaceId = useStringQuery('workspaceId') useEffect(() => { if (session.data) { - const socket = io(NEXT_PUBLIC_API_URL(), { + const url = new URL(NEXT_PUBLIC_API_URL()) + const withoutPathname = url.origin + const socket = io(withoutPathname, { withCredentials: true, + path: url.pathname + '/socket.io', + transports: ['websocket'], }) setSocket(socket) diff --git a/apps/web/src/utils/env.ts b/apps/web/src/utils/env.ts index 2704b11d..b47fe196 100644 --- a/apps/web/src/utils/env.ts +++ b/apps/web/src/utils/env.ts @@ -11,14 +11,24 @@ function getFromWindow(key: string, or?: string): string { } } +function currentUrl() { + return `${window.location.protocol}//${window.location.host}` +} + export const NEXT_PUBLIC_API_URL = () => - process.env.NEXT_PUBLIC_API_URL || getFromWindow('NEXT_PUBLIC_API_URL') + process.env.NEXT_PUBLIC_API_URL || + getFromWindow('NEXT_PUBLIC_API_URL') || + `${currentUrl()}/api` export const NEXT_PUBLIC_API_WS_URL = () => - process.env.NEXT_PUBLIC_API_WS_URL || getFromWindow('NEXT_PUBLIC_API_WS_URL') + process.env.NEXT_PUBLIC_API_WS_URL || + getFromWindow('NEXT_PUBLIC_API_WS_URL') || + `${currentUrl().replace('http', 'ws')}/api` export const NEXT_PUBLIC_PUBLIC_URL = () => - process.env.NEXT_PUBLIC_PUBLIC_URL || getFromWindow('NEXT_PUBLIC_PUBLIC_URL') + process.env.NEXT_PUBLIC_PUBLIC_URL || + getFromWindow('NEXT_PUBLIC_PUBLIC_URL') || + currentUrl() export const NEXT_PUBLIC_GATEWAY_IP = () => process.env.NEXT_PUBLIC_GATEWAY_IP || diff --git a/apps/web/start.sh b/apps/web/start.sh index c7ff66e5..f7ba0249 100755 --- a/apps/web/start.sh +++ b/apps/web/start.sh @@ -7,4 +7,4 @@ echo "window.env.NEXT_PUBLIC_API_URL = '$NEXT_PUBLIC_API_URL'" >> $SCRIPT_DIR/pu echo "window.env.NEXT_PUBLIC_API_WS_URL = '$NEXT_PUBLIC_API_WS_URL'" >> $SCRIPT_DIR/public/env.js echo "window.env.NEXT_PUBLIC_PUBLIC_URL = '$NEXT_PUBLIC_PUBLIC_URL'" >> $SCRIPT_DIR/public/env.js -node $SCRIPT_DIR/server.js +HOSTNAME=0.0.0.0 PORT=4000 node $SCRIPT_DIR/server.js diff --git a/docker-compose.yaml b/docker-compose.yaml index 5afdbec0..9592c173 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -76,18 +76,8 @@ services: build: context: '.' dockerfile: 'apps/web/Dockerfile' - args: - NODE_ENV: 'production' - NEXT_PUBLIC_API_URL: 'https://api.${TLD:?error}' - NEXT_PUBLIC_API_WS_URL: 'wss://api.${TLD:?error}' - NEXT_PUBLIC_PUBLIC_URL: 'https://app.${TLD:?error}' environment: NODE_ENV: 'production' - NEXT_PUBLIC_API_URL: 'https://api.${TLD:?error}' - NEXT_PUBLIC_API_WS_URL: 'wss://api.${TLD:?error}' - NEXT_PUBLIC_PUBLIC_URL: 'https://app.${TLD:?error}' - ports: - - '3000:3000' depends_on: api: condition: service_healthy @@ -97,14 +87,11 @@ services: build: context: '.' dockerfile: 'apps/api/Dockerfile' - ports: - - '8080:8080' environment: NODE_ENV: 'production' - LOG_LEVEL: 'info' - API_URL: 'https://api.${TLD:?error}' - FRONTEND_URL: 'https://app.${TLD:?error}' - TLD: ${TLD:?error} + LOG_LEVEL: 'debug' + API_URL: '/api' + FRONTEND_URL: '/' LOGIN_JWT_SECRET: ${LOGIN_JWT_SECRET:?error} AUTH_JWT_SECRET: ${AUTH_JWT_SECRET:?error} AI_API_URL: 'http://ai:8000' @@ -138,6 +125,17 @@ services: ai: condition: service_healthy + nginx: + image: nginx:1.27 + depends_on: + - web + - api + ports: + - '3000:3000' + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + restart: always + volumes: jupyter: postgres_data: diff --git a/docker/Dockerfile b/docker/Dockerfile index 3801ffaf..7f5d09a8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -141,6 +141,13 @@ COPY --from=web-installer --chown=briefer:briefer /app/apps/web/public ./apps/we COPY --from=web-installer --chown=briefer:briefer /app/apps/web/start.sh ./apps/web/start.sh ##### END OF COPY API AND WEB BUILDS #### +# NGINX +RUN mkdir -p /var/log/nginx /etc/nginx /etc/nginx/conf.d +COPY ./nginx/nginx.conf /etc/nginx/nginx.conf +COPY ./docker/start-nginx.sh /app/start-nginx.sh +RUN chmod +x /app/start-nginx.sh + + USER postgres RUN mkdir -p /var/lib/postgresql/data \ && chown -R postgres:postgres /var/lib/postgresql \ diff --git a/docker/setup/api.py b/docker/setup/api.py index aa86729d..9428e6ec 100644 --- a/docker/setup/api.py +++ b/docker/setup/api.py @@ -35,9 +35,8 @@ def run_api(cfg): default_env = { "NODE_ENV": "production", "LOG_LEVEL": "info", - "API_URL": cfg["API_URL"], - "FRONTEND_URL": cfg["FRONTEND_URL"], - "TLD": cfg["TLD"], + "API_URL": "/api", + "FRONTEND_URL": "/", "LOGIN_JWT_SECRET": cfg["LOGIN_JWT_SECRET"], "AUTH_JWT_SECRET": cfg["AUTH_JWT_SECRET"], "AI_API_URL": "http://localhost:8000", diff --git a/docker/setup/setup.py b/docker/setup/setup.py index 6c1e8a44..9189e259 100644 --- a/docker/setup/setup.py +++ b/docker/setup/setup.py @@ -31,13 +31,9 @@ def get_config(dir): def generate_apps_config(): fpath = get_config_path(APPS_CONFIG_DIR) - tld = os.getenv("TLD", "localhost") cfg = { "NODE_ENV": "production", "LOG_LEVEL": "info", - "TLD": tld, - "API_URL": f"https://api.{tld}" if tld != "localhost" else "http://localhost:8080", - "FRONTEND_URL": f"https://app.{tld}" if tld != "localhost" else "http://localhost:3000", "POSTGRES_USERNAME": "briefer", "POSTGRES_PASSWORD": get_random_secret(8), "JUPYTER_TOKEN": get_random_secret(32), diff --git a/docker/setup/web.py b/docker/setup/web.py index 981b5645..86951da9 100644 --- a/docker/setup/web.py +++ b/docker/setup/web.py @@ -1,12 +1,10 @@ import time import subprocess from pathlib import Path -import json import logging import os CONFIG_DIR = Path(Path.home(), ".config", "briefer") -CONFIG_FILE_PATH = Path(CONFIG_DIR, "briefer.json") SETUP_FILE_PATH = Path(CONFIG_DIR, "setup") def wait_setup(): @@ -14,31 +12,12 @@ def wait_setup(): logging.info("Waiting for setup to finish") time.sleep(0.3) -def get_config(): - while not CONFIG_FILE_PATH.exists(): - logging.info("Waiting for config file") - time.sleep(0.3) - - logging.info("Reading config file") - with open(CONFIG_FILE_PATH, "r") as f: - cfg = json.load(f) - - # override config with env vars - for k, _ in cfg.items(): - if k in os.environ: - cfg[k] = os.environ[k] - - return cfg - -def run_web(cfg): +def run_web(): logging.info("Running Web") default_env = { "NODE_ENV": "production", - "NEXT_PUBLIC_API_URL": cfg["API_URL"], - "NEXT_PUBLIC_API_WS_URL": cfg["API_URL"].replace('http', 'ws'), - "NEXT_PUBLIC_PUBLIC_URL": cfg["FRONTEND_URL"], } env = os.environ.copy() for k, v in default_env.items(): @@ -51,8 +30,7 @@ def run_web(cfg): def main(): wait_setup() - cfg = get_config() - run_web(cfg) + run_web() if __name__ == '__main__': diff --git a/docker/start-nginx.sh b/docker/start-nginx.sh new file mode 100644 index 00000000..9d6b30ff --- /dev/null +++ b/docker/start-nginx.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Function to ensure web and api are in /etc/hosts +update_hosts() { + if ! grep -q "127.0.0.1 web" /etc/hosts; then + echo "127.0.0.1 web" >> /etc/hosts + fi + if ! grep -q "127.0.0.1 api" /etc/hosts; then + echo "127.0.0.1 api" >> /etc/hosts + fi +} + +# Loop until both web and api services are reachable +while true; do + update_hosts + + # Check if the web and api services are reachable + if curl --output /dev/null --silent --head --fail http://web:4000 && curl --output /dev/null --silent --head --fail http://api:8080/readyz; then + echo "Web and API services are reachable, starting Nginx..." + break + else + echo "Waiting for Web and API services to be reachable..." + sleep 2 + fi +done + +# Start Nginx +nginx -g 'daemon off;' diff --git a/docker/supervisord.conf b/docker/supervisord.conf index 586eb9eb..0272c94f 100644 --- a/docker/supervisord.conf +++ b/docker/supervisord.conf @@ -77,3 +77,13 @@ stdout_logfile=/dev/stdout stderr_logfile=/dev/stderr stdout_logfile_maxbytes=0 stderr_logfile_maxbytes=0 + +[program:nginx] +command=/app/start-nginx.sh +autostart=true +autorestart=true +stdout_logfile=/dev/stdout +stderr_logfile=/dev/stderr +stdout_logfile_maxbytes=0 +stderr_logfile_maxbytes=0 +priority=7 diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 0c057a77..9e6bb344 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -54,7 +54,7 @@ If you're not sure which option to choose, we recommend starting with the first This is the simplest way to deploy Briefer. You'll only need to install Docker on your server and run a single command to start the application. -Then, you'll have to make sure that this server is accessible to all the people who will use Briefer, and use the necessary DNS records to access the web application and the API. +Then, you'll have to make sure that this server is accessible to all the people who will use Briefer. Here's a step-by-step guide to deploy Briefer as a single container: @@ -69,28 +69,19 @@ Here's a step-by-step guide to deploy Briefer as a single container: 3. Pull and run the all-in-one Docker image for Briefer. ```bash - # if using an IP set API_URL to https://your-ip:3000 and FRONTEND_URL to https://your-ip:8080 docker run -d \ -p 3000:3000 \ - -p 8080:8080 \ -v briefer_psql_data:/var/lib/postgresql/data \ -v briefer_jupyter_data:/home/jupyteruser \ -v briefer_briefer_data:/home/briefer \ - --env API_URL="https://your_api_address" \ - --env FRONTEND_URL="https://your_frontend_address" \ briefercloud/briefer ``` - ℹ️ The most crucial part of this step is to make sure that `API_URL` and `FRONTEND_URL` point to the host's address. For example, if you're running Briefer on a machine whose IP is `192.168.0.1`, you should set the `API_URL` to `https://192.168.0.1:8080` (considering API is running on port 8080) and `FRONTEND_URL` to `https://192.168.0.1:3000` (considering the front-end is running on port 3000). - ℹ️ If you want to serve Briefer over HTTP (usually because you're using an IP directly) you should consider setting `--env ALLOW_HTTP="true"` in the above command. 4. Expose your server to the internet or your local network. - Make sure that you allow traffic on ports 3000 and 8080. The first one is for the Briefer web application (the one you'll access in your browser), and the second one is for the API that the web application talks to. -5. If you want to use a domain name rather than an IP, create the necessary DNS records to access ports 3000 and 8080. Otherwise, skip this step. - Use `app.briefer.your_domain_here.com` as the name for the web application bound to port 3000, and `api.briefer.your_domain_here.com` as the name for the API bound to port 8080. - -Now you should be able to access the Briefer web application at `app.briefer.your_domain_here.com` and the API at `api.briefer.your_domain_here.com`. + Make sure that you allow traffic on port 3000. +5. (Optional) If you want to use a domain name rather than an IP, create the necessary DNS records to access port 3000. Otherwise, skip this step.
@@ -98,7 +89,7 @@ Now you should be able to access the Briefer web application at `app.briefer.you Besides deploying Briefer as a single container, you can also deploy it as multiple containers. That way, you'll have separate containers for the web application, the API, the AI service, the database, and the Jupyter notebook server. -This approach is more complex than the previous one, but it allows you to use configure each container separately. +This approach is more complex than the previous one, but it allows you to configure each container separately. That way, you can scale each part of the application independently or just change the configuration of one part without affecting the others. If you want to use an RDS instance for the database, for example, you can do that by changing the configuration of the database container. @@ -112,15 +103,13 @@ Here's a step-by-step guide to deploy Briefer as multiple containers: sudo yum install docker -y sudo systemctl start docker ``` -3. Run the `start.sh` script and enter Briefer's TLD to start all the containers. - We recommend using `briefer.your_domain_here.com` as the TLD. +3. Run `start.sh` to start all the containers. ```bash ./start.sh ``` 4. Expose your server to the internet or your local network. - Make sure that you allow traffic on ports 3000 and 8080. The first one is for the Briefer web application (the one you'll access in your browser), and the second one is for the API that the web application talks to. -5. Create the necessary DNS records to access ports 3000 and 8080. - Use `app.briefer.your_domain_here.com` as the name for the web application bound to port 3000, and `api.briefer.your_domain_here.com` as the name for the API bound to port 8080. + Make sure that you allow traffic on port 3000. +5. (Optional) Create DNS records to make it easier to access Briefer. If you want to use an RDS instance for the database, you will need to: @@ -160,21 +149,19 @@ To check if Briefer is running, SSH into your server and run `docker ps`. You sh If Briefer is running, have a look at its logs and see if there are any errors. You can do that by running `docker logs `, where `` is the ID of the Briefer container. -Finally, make sure that you've exposed your server to the internet or your local network. You can do that by allowing traffic on ports 3000 and 8080 and creating the necessary DNS records to access these ports, which should be `app.briefer.your_domain_here.com` and `api.briefer.your_domain_here.com`. - -If you want to change the domains that Briefer uses, you can do that by changing the `TLD` environment variable in your root `.env` file and restarting the Briefer container. +Finally, make sure that you've exposed your server to the internet or your local network. You can do that by allowing traffic on port 3000 and creating the necessary DNS records to access the host.
I can access the web application, but it can't talk to the API -In this case, it's likely that the API is not available on `api.briefer.your_domain_here.com`, so double check that you've created the necessary DNS records using the correct values. +In this case, it's likely that the web process is running, but the API is not. -If you do have the correct DNS records, check if the API is running by SSHing into your server and running `docker ps`. You should see a container using the image `briefercloud/briefer` or `briefercloud/briefer-api` and exposing port 8080. +If the API is running, have a look at its logs and see if there are any errors. You can do that by running `docker logs `, where `` is the ID of the API container or the monolithic Briefer container in case that's what you're using. -If the container is running, check its logs by running `docker logs `, where `` is the ID of the API container. Look for any errors that might indicate why the API is not working. +Check if it complains about any missing environment variables or if there's any other straightforward error that you can solve. -Also, see if you can `cURL` the API from your server. You can do that by running `curl api.briefer.your_domain_here.com` in your terminal. If you can cURL the API from the server but the web application can't talk to it, it's likely that there's a network issue at play. +If you can't figure out what's happening, please [open an issue here](https://github.com/briefercloud/briefer/issues).
diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 00000000..c96397d8 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,71 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + + upstream web { + server web:4000; + } + + upstream api { + server api:8080; + } + + server { + listen 3000; + + # Handle WebSocket connections for /api/socket.io + location /api/socket.io/ { + proxy_pass http://api/socket.io/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 60m; + proxy_send_timeout 60m; + proxy_buffering off; # Disable buffering for WebSocket + } + + location /api/v2/yjs/ { + proxy_pass http://api/v2/yjs/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 60m; + proxy_send_timeout 60m; + proxy_buffering off; # Disable buffering for WebSocket + } + + # Proxy regular HTTP requests to /api (non-WebSocket) to the API service + location /api/ { + proxy_pass http://api/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Proxy everything else to the frontend service + location / { + proxy_pass http://web/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} diff --git a/pypi/src/briefer/main.py b/pypi/src/briefer/main.py index 9ee28cbd..013edb02 100644 --- a/pypi/src/briefer/main.py +++ b/pypi/src/briefer/main.py @@ -11,24 +11,15 @@ ENV_VARS = [ "LOG_LEVEL", - "API_URL", - "FRONTEND_URL", "ALLOW_HTTP", - "TLD", - "LOGIN_JWT_SECRET", - "AUTH_JWT_SECRET", - "AI_API_URL", - "AI_API_USERNAME", - "AI_API_PASSWORD", - "PYTHON_ALLOWED_LIBRARIES", "POSTGRES_USERNAME", "POSTGRES_PASSWORD", "POSTGRES_HOSTNAME", "POSTGRES_PORT", "POSTGRES_DATABASE", - "ENVIRONMENT_VARIABLES_ENCRYPTION_KEY", - "WORKSPACE_SECRETS_ENCRYPTION_KEY", - "DATASOURCES_ENCRYPTION_KEY", + "AI_API_URL", + "AI_API_USERNAME", + "AI_API_PASSWORD", "JUPYTER_HOST", "JUPYTER_PORT", "JUPYTER_TOKEN" @@ -108,8 +99,7 @@ def start_or_run_container(client, container_name, image, detach): if ":" not in image and "/" in image: image += ":latest" - web_port = find_free_port(3000) - api_port = find_free_port(8080) + port = find_free_port(3000) if "/" in image and "latest" in image or not client.images.list(name=image): pull_image(client, image) @@ -132,24 +122,18 @@ def start_or_run_container(client, container_name, image, detach): if var in os.environ: env[var] = os.environ[var] - if "API_URL" not in env: - env["API_URL"] = f"http://localhost:{api_port}" - - if "FRONTEND_URL" not in env: - env["FRONTEND_URL"] = f"http://localhost:{web_port}" - # Run a new container with the updated ports and environment container = client.containers.run( image, detach=True, - ports={f"3000/tcp": web_port, f"8080/tcp": api_port}, + ports={f"3000/tcp": port}, name=container_name, volumes=volumes, environment=env ) - api_url = env["API_URL"] - web_url = env["FRONTEND_URL"] + api_url = f"http://localhost:{port}/api" + web_url = f"http://localhost:{port}" def check_reachability(): while True: diff --git a/start-dev.sh b/start-dev.sh index 4ea98095..102c1894 100755 --- a/start-dev.sh +++ b/start-dev.sh @@ -6,7 +6,7 @@ if [ ! -f ./apps/api/.env ]; then echo "NODE_ENV=development" > ./apps/api/.env echo "LOG_LEVEL=debug" >> ./apps/api/.env echo "API_URL='https://localhost:8080'" >> ./apps/api/.env - echo "FRONTEND_URL='https://localhost:3000'" >> ./apps/api/.env + echo "FRONTEND_URL='https://localhost:4000'" >> ./apps/api/.env echo "TLD=localhost" >> ./apps/api/.env echo "LOGIN_JWT_SECRET=$(openssl rand -hex 24)" >> ./apps/api/.env echo "AUTH_JWT_SECRET=$(openssl rand -hex 24)" >> ./apps/api/.env @@ -36,7 +36,7 @@ if [ ! -f ./apps/web/.env ]; then echo "NODE_ENV=development" > ./apps/web/.env echo "NEXT_PUBLIC_API_URL='https://localhost:8080'" >> ./apps/web/.env echo "NEXT_PUBLIC_API_WS_URL='wss://localhost:8080'" >> ./apps/web/.env - echo "NEXT_PUBLIC_PUBLIC_URL='https://localhost:3000'" >> ./apps/web/.env + echo "NEXT_PUBLIC_PUBLIC_URL='https://localhost:4000'" >> ./apps/web/.env echo "Generated a new ./apps/eb/.env file with default values" fi diff --git a/start.sh b/start.sh index cb73429c..2d2afc4a 100755 --- a/start.sh +++ b/start.sh @@ -3,10 +3,6 @@ set -e # if there is no .env file, create one if [ ! -f .env ]; then - echo "Enter the top level domain (e.g. example.com):" - read TLD - - echo "TLD=$TLD" > .env echo "POSTGRES_USERNAME=$(openssl rand -hex 12)" >> .env echo "POSTGRES_PASSWORD=$(openssl rand -hex 12)" >> .env echo "JUPYTER_TOKEN=$(openssl rand -hex 24)" >> .env @@ -19,14 +15,6 @@ if [ ! -f .env ]; then echo "WORKSPACE_SECRETS_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env echo "DATASOURCES_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env echo "ENABLE_CUSTOM_OAI_KEY=true" >> .env - - echo - echo "Here are the URLs you should use to access Briefer:" - echo "APP: https://app.${TLD}" - echo "API: https://api.${TLD}" - echo - - read -p "Press enter to continue" fi # Check if docker compose exists, if it does use it @@ -42,3 +30,4 @@ fi # Running docker compose up $COMPOSE_CMD up -d +echo "Briefer is now running at port 3000"