Compare commits

..

1 Commits

Author SHA1 Message Date
Willie Zutz
92dd5db18b Merge d839769d7e into 68e151b2bd 2025-05-08 06:39:26 +00:00
5 changed files with 7 additions and 81 deletions

View File

@@ -140,37 +140,6 @@ For more details, check out the full documentation [here](https://github.com/Itz
Perplexica runs on Next.js and handles all API requests. It works right away on the same network and stays accessible even with port forwarding.
### Running Behind a Reverse Proxy
When running Perplexica behind a reverse proxy (like Nginx, Apache, or Traefik), follow these steps to ensure proper functionality:
1. **Configure the BASE_URL setting**:
- In `config.toml`, set the `BASE_URL` parameter under the `[GENERAL]` section to your public-facing URL (e.g., `https://perplexica.yourdomain.com`)
2. **Ensure proper headers forwarding**:
- Your reverse proxy should forward the following headers:
- `X-Forwarded-Host`
- `X-Forwarded-Proto`
- `X-Forwarded-Port` (if using non-standard ports)
3. **Example Nginx configuration**:
```nginx
server {
listen 80;
server_name perplexica.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
}
}
```
This ensures that OpenSearch descriptions, browser integrations, and all URLs work properly when accessing Perplexica through your reverse proxy.
## One-Click Deployment
[![Deploy to Sealos](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://usw.sealos.io/?openapp=system-template%3FtemplateName%3Dperplexica)

View File

@@ -1,7 +1,6 @@
[GENERAL]
SIMILARITY_MEASURE = "cosine" # "cosine" or "dot"
KEEP_ALIVE = "5m" # How long to keep Ollama models loaded into memory. (Instead of using -1 use "-1m")
BASE_URL = "" # Optional. When set, overrides detected URL for OpenSearch and other public URLs
[MODELS.OPENAI]
API_KEY = ""

View File

@@ -1,6 +1,5 @@
import {
getAnthropicApiKey,
getBaseUrl,
getCustomOpenaiApiKey,
getCustomOpenaiApiUrl,
getCustomOpenaiModelName,
@@ -61,7 +60,6 @@ export const GET = async (req: Request) => {
config['customOpenaiApiUrl'] = getCustomOpenaiApiUrl();
config['customOpenaiApiKey'] = getCustomOpenaiApiKey();
config['customOpenaiModelName'] = getCustomOpenaiModelName();
config['baseUrl'] = getBaseUrl();
return Response.json({ ...config }, { status: 200 });
} catch (err) {

View File

@@ -1,10 +1,11 @@
import { NextResponse } from 'next/server';
import { getBaseUrl } from '@/lib/config';
/**
* Creates an OpenSearch XML response with the given origin URL
*/
function generateOpenSearchResponse(origin: string): NextResponse {
export async function GET(request: Request) {
// Get the host from the request
const url = new URL(request.url);
const origin = url.origin;
// Create the OpenSearch XML with the correct origin
const opensearchXml = `<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>Perplexica</ShortName>
@@ -16,48 +17,10 @@ function generateOpenSearchResponse(origin: string): NextResponse {
<Url type="application/opensearchdescription+xml" rel="self" template="${origin}/api/opensearch"/>
</OpenSearchDescription>`;
// Return the XML with the correct content type
return new NextResponse(opensearchXml, {
headers: {
'Content-Type': 'application/opensearchdescription+xml',
},
});
}
export async function GET(request: Request) {
// Check if a BASE_URL is explicitly configured
const configBaseUrl = getBaseUrl();
// If BASE_URL is configured, use it, otherwise detect from request
if (configBaseUrl) {
// Remove any trailing slashes for consistency
let origin = configBaseUrl.replace(/\/+$/, '');
return generateOpenSearchResponse(origin);
}
// Detect the correct origin, taking into account reverse proxy headers
const url = new URL(request.url);
let origin = url.origin;
// Extract headers
const headers = Object.fromEntries(request.headers);
// Check for X-Forwarded-Host and related headers to handle reverse proxies
if (headers['x-forwarded-host']) {
// Determine protocol: prefer X-Forwarded-Proto, fall back to original or https
const protocol = headers['x-forwarded-proto'] || url.protocol.replace(':', '');
// Build the correct public-facing origin
origin = `${protocol}://${headers['x-forwarded-host']}`;
// Handle non-standard ports if specified in X-Forwarded-Port
if (headers['x-forwarded-port']) {
const port = headers['x-forwarded-port'];
// Don't append standard ports (80 for HTTP, 443 for HTTPS)
if (!((protocol === 'http' && port === '80') || (protocol === 'https' && port === '443'))) {
origin = `${origin}:${port}`;
}
}
}
// Generate and return the OpenSearch response
return generateOpenSearchResponse(origin);
}

View File

@@ -15,7 +15,6 @@ interface Config {
GENERAL: {
SIMILARITY_MEASURE: string;
KEEP_ALIVE: string;
BASE_URL?: string;
};
MODELS: {
OPENAI: {
@@ -71,8 +70,6 @@ export const getSimilarityMeasure = () =>
export const getKeepAlive = () => loadConfig().GENERAL.KEEP_ALIVE;
export const getBaseUrl = () => loadConfig().GENERAL.BASE_URL;
export const getOpenaiApiKey = () => loadConfig().MODELS.OPENAI.API_KEY;
export const getGroqApiKey = () => loadConfig().MODELS.GROQ.API_KEY;