mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-05-30 17:50:27 +02:00
Add arbitrary domain support + website hosting to onebox setup
This commit is contained in:
parent
e20179048d
commit
5aabc5abe6
@ -1,5 +0,0 @@
|
||||
This serves as an example for how to deploy everything in a single box. This is far
|
||||
from optimal, but can get you started easily and cheaply. To run:
|
||||
|
||||
1. Set up a `.env` file in this directory with relevant environment variables (TODO: document)
|
||||
2. `docker compose up -d --build`
|
1
deployment/.gitignore
vendored
Normal file
1
deployment/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.env*
|
7
deployment/README.md
Normal file
7
deployment/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
This serves as an example for how to deploy everything on a single machine. This is
|
||||
not optimal, but can get you started easily and cheaply. To run:
|
||||
|
||||
1. Set up a `.env` + `.env.nginx` file in this directory with relevant environment variables
|
||||
a. TODO: add description of required variables
|
||||
2. `chmod +x init-letsencrypt.sh` + `./init-letsencrypt.sh` to setup https certificate
|
||||
2. `docker compose up -d --build` to start nginx, postgres, web/api servers, and the background indexing job
|
@ -6,14 +6,20 @@ upstream app_server {
|
||||
#server unix:/tmp/gunicorn.sock fail_timeout=0;
|
||||
|
||||
# for a TCP configuration
|
||||
# TODO: use gunicorn to manage multiple processes
|
||||
server api:8080 fail_timeout=0;
|
||||
}
|
||||
|
||||
upstream web_server {
|
||||
server web:3000 fail_timeout=0;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.danswer.dev;
|
||||
server_name ${DOMAIN};
|
||||
|
||||
location / {
|
||||
location ~ ^/api(.*)$ {
|
||||
rewrite ^/api(/.*)$ $1 break;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $http_host;
|
||||
@ -23,6 +29,14 @@ server {
|
||||
proxy_pass http://app_server;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
proxy_pass http://web_server;
|
||||
}
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
@ -30,14 +44,14 @@ server {
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name api.danswer.dev;
|
||||
server_name ${DOMAIN};
|
||||
|
||||
location / {
|
||||
proxy_pass http://api.danswer.dev;
|
||||
proxy_pass http://${DOMAIN};
|
||||
}
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/api.danswer.dev/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/api.danswer.dev/privkey.pem;
|
||||
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
}
|
@ -3,13 +3,13 @@ version: '3'
|
||||
services:
|
||||
api:
|
||||
build:
|
||||
context: ..
|
||||
context: ../backend
|
||||
dockerfile: Dockerfile
|
||||
depends_on:
|
||||
- db
|
||||
# just for local testing
|
||||
ports:
|
||||
- "8080:8080"
|
||||
# uncomment for local testing
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
@ -18,7 +18,7 @@ services:
|
||||
- local_dynamic_storage:/home/storage
|
||||
background:
|
||||
build:
|
||||
context: ..
|
||||
context: ../backend
|
||||
dockerfile: Dockerfile.background
|
||||
depends_on:
|
||||
- db
|
||||
@ -28,6 +28,14 @@ services:
|
||||
- POSTGRES_HOST=db
|
||||
volumes:
|
||||
- local_dynamic_storage:/home/storage
|
||||
web:
|
||||
build:
|
||||
context: ../web
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
NEXT_PUBLIC_API_URL: /api
|
||||
depends_on:
|
||||
- api
|
||||
db:
|
||||
image: postgres:15.2-alpine
|
||||
restart: always
|
||||
@ -47,7 +55,11 @@ services:
|
||||
- ./data/nginx:/etc/nginx/conf.d
|
||||
- ./data/certbot/conf:/etc/letsencrypt
|
||||
- ./data/certbot/www:/var/www/certbot
|
||||
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
|
||||
command: >
|
||||
/bin/sh -c "envsubst '$$\{DOMAIN\}' < /etc/nginx/conf.d/app.conf.template > /etc/nginx/conf.d/app.conf
|
||||
&& while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\""
|
||||
env_file:
|
||||
- .env.nginx
|
||||
depends_on:
|
||||
- api
|
||||
certbot:
|
@ -1,14 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
# .env.nginx file must be present in the same directory as this script and
|
||||
# must set DOMAIN (and optionally EMAIL)
|
||||
set -o allexport
|
||||
source .env.nginx
|
||||
set +o allexport
|
||||
|
||||
if ! [ -x "$(command -v docker compose)" ]; then
|
||||
echo 'Error: docker compose is not installed.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
domains=(api.danswer.dev www.api.danswer.dev)
|
||||
domains=("$DOMAIN" "www.$DOMAIN")
|
||||
rsa_key_size=4096
|
||||
data_path="./data/certbot"
|
||||
email="" # Adding a valid address is strongly recommended
|
||||
email="$EMAIL" # Adding a valid address is strongly recommended
|
||||
staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits
|
||||
|
||||
if [ -d "$data_path" ]; then
|
55
web/Dockerfile
Normal file
55
web/Dockerfile
Normal file
@ -0,0 +1,55 @@
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# Step 1. Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# Step 2. Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Disable automatic telemetry collection
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# Step 3. Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
# Disable automatic telemetry collection
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
# Don't run production as root
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
USER nextjs
|
||||
|
||||
# Add back in if we add anything to `public`
|
||||
# COPY --from=builder /app/public ./public
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
# Note: Don't expose ports here, Compose will handle that for us if necessary.
|
||||
# If you want to run this without compose, specify the ports to
|
||||
# expose via cli
|
||||
|
||||
CMD ["node", "server.js"]
|
@ -3,6 +3,23 @@ const nextConfig = {
|
||||
experimental: {
|
||||
appDir: true,
|
||||
},
|
||||
output: "standalone",
|
||||
redirects: async () => {
|
||||
// In production, something else (nginx in the one box setup) takes care
|
||||
// of this redirect
|
||||
// NOTE: this may get adjusted later if we want to support hosting of the
|
||||
// API server on a different domain without requring some kind of proxy
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
return [
|
||||
{
|
||||
source: "/api/:path*",
|
||||
destination: "http://localhost:8080/:path*", // Proxy to Backend
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
|
@ -6,11 +6,8 @@ import "tailwindcss/tailwind.css";
|
||||
import { SearchResultsDisplay } from "./SearchResultsDisplay";
|
||||
import { SearchResponse } from "./types";
|
||||
|
||||
const BACKEND_URL =
|
||||
process.env.NEXT_PUBLIC_BACKEND_URL || "http://localhost:8080"; // "http://servi-lb8a1-jhqpsz92kbm2-1605938866.us-east-2.elb.amazonaws.com/direct-qa";
|
||||
|
||||
const searchRequest = async (query: string): Promise<SearchResponse> => {
|
||||
const response = await fetch(BACKEND_URL + "/direct-qa", {
|
||||
const response = await fetch("/api/direct-qa", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Formik, Form, Field, ErrorMessage, FormikHelpers } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import { BACKEND_URL } from "@/lib/constants";
|
||||
import { Popup } from "./Popup";
|
||||
|
||||
interface FormData {
|
||||
@ -18,7 +17,7 @@ const validationSchema = Yup.object().shape({
|
||||
});
|
||||
|
||||
const getConfig = async (): Promise<FormData> => {
|
||||
const response = await fetch(BACKEND_URL + "/admin/slack_connector_config");
|
||||
const response = await fetch("/api/admin/slack_connector_config");
|
||||
return response.json();
|
||||
};
|
||||
|
||||
@ -31,17 +30,13 @@ const handleSubmit = async (
|
||||
) => {
|
||||
setSubmitting(true);
|
||||
try {
|
||||
// Replace this with your actual API call
|
||||
const response = await fetch(
|
||||
BACKEND_URL + "/admin/slack_connector_config",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(values),
|
||||
}
|
||||
);
|
||||
const response = await fetch("/api/admin/slack_connector_config", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(values),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setPopup({ message: "Success!", type: "success" });
|
||||
|
@ -1,2 +0,0 @@
|
||||
export const BACKEND_URL =
|
||||
process.env.NEXT_PUBLIC_BACKEND_URL || "http://localhost:8080"; // "http://servi-lb8a1-jhqpsz92kbm2-1605938866.us-east-2.elb.amazonaws.com/direct-qa";
|
Loading…
x
Reference in New Issue
Block a user