mirror of https://github.com/buster-so/buster.git
buster start, stop, restart handled well
This commit is contained in:
parent
c62d09536c
commit
87fcc41e2d
|
@ -94,48 +94,50 @@ pub async fn auth(mut req: Request, next: Next) -> Result<Response, StatusCode>
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Payment Required Check START ---
|
// --- Payment Required Check START ---
|
||||||
if let Some(org_membership) = user.organizations.get(0) {
|
if env::var("ENVIRONMENT").unwrap_or_default() == "production" {
|
||||||
let org_id = org_membership.id;
|
if let Some(org_membership) = user.organizations.get(0) {
|
||||||
let pg_pool = get_pg_pool();
|
let org_id = org_membership.id;
|
||||||
let mut conn = match pg_pool.get().await {
|
let pg_pool = get_pg_pool();
|
||||||
Ok(conn) => conn,
|
let mut conn = match pg_pool.get().await {
|
||||||
Err(e) => {
|
Ok(conn) => conn,
|
||||||
tracing::error!("Failed to get DB connection for payment check: {}", e);
|
Err(e) => {
|
||||||
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
tracing::error!("Failed to get DB connection for payment check: {}", e);
|
||||||
}
|
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match database::schema::organizations::table
|
match database::schema::organizations::table
|
||||||
.filter(database::schema::organizations::id.eq(org_id))
|
.filter(database::schema::organizations::id.eq(org_id))
|
||||||
.select(database::schema::organizations::payment_required)
|
.select(database::schema::organizations::payment_required)
|
||||||
.first::<bool>(&mut conn)
|
.first::<bool>(&mut conn)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(payment_required) => {
|
Ok(payment_required) => {
|
||||||
if payment_required {
|
if payment_required {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
|
user_id = %user.id,
|
||||||
|
org_id = %org_id,
|
||||||
|
"Access denied due to payment requirement for organization."
|
||||||
|
);
|
||||||
|
return Err(StatusCode::PAYMENT_REQUIRED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(diesel::NotFound) => {
|
||||||
|
tracing::error!(
|
||||||
user_id = %user.id,
|
user_id = %user.id,
|
||||||
org_id = %org_id,
|
org_id = %org_id,
|
||||||
"Access denied due to payment requirement for organization."
|
"Organization not found during payment check."
|
||||||
);
|
);
|
||||||
return Err(StatusCode::PAYMENT_REQUIRED);
|
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(
|
||||||
|
user_id = %user.id,
|
||||||
|
org_id = %org_id,
|
||||||
|
"Database error during payment check: {}", e
|
||||||
|
);
|
||||||
|
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(diesel::NotFound) => {
|
|
||||||
tracing::error!(
|
|
||||||
user_id = %user.id,
|
|
||||||
org_id = %org_id,
|
|
||||||
"Organization not found during payment check."
|
|
||||||
);
|
|
||||||
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!(
|
|
||||||
user_id = %user.id,
|
|
||||||
org_id = %org_id,
|
|
||||||
"Database error during payment check: {}", e
|
|
||||||
);
|
|
||||||
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::io::{self, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use crate::error::BusterError;
|
use crate::error::BusterError;
|
||||||
|
@ -10,6 +11,7 @@ use dirs;
|
||||||
#[derive(RustEmbed)]
|
#[derive(RustEmbed)]
|
||||||
#[folder = "../../"]
|
#[folder = "../../"]
|
||||||
#[include = "docker-compose.yml"]
|
#[include = "docker-compose.yml"]
|
||||||
|
#[include = "supabase/.env.example"]
|
||||||
#[include = "supabase/**/*"]
|
#[include = "supabase/**/*"]
|
||||||
#[exclude = "supabase/volumes/db/data/**/*"]
|
#[exclude = "supabase/volumes/db/data/**/*"]
|
||||||
#[exclude = "supabase/volumes/storage/**/*"]
|
#[exclude = "supabase/volumes/storage/**/*"]
|
||||||
|
@ -60,20 +62,32 @@ async fn setup_persistent_app_environment() -> Result<PathBuf, BusterError> {
|
||||||
let supabase_volumes_functions_path = app_base_dir.join("supabase/volumes/functions");
|
let supabase_volumes_functions_path = app_base_dir.join("supabase/volumes/functions");
|
||||||
fs::create_dir_all(supabase_volumes_functions_path).map_err(|e| BusterError::CommandError(format!("Failed to create supabase/volumes/functions in persistent app dir: {}", e)))?;
|
fs::create_dir_all(supabase_volumes_functions_path).map_err(|e| BusterError::CommandError(format!("Failed to create supabase/volumes/functions in persistent app dir: {}", e)))?;
|
||||||
|
|
||||||
let local_dotenv_path = PathBuf::from("/Users/dallin/buster/buster/.env");
|
let target_dotenv_path = app_base_dir.join(".env");
|
||||||
if local_dotenv_path.exists() {
|
|
||||||
let target_dotenv_path = app_base_dir.join(".env");
|
// Always use .env.example from embedded assets
|
||||||
fs::copy(&local_dotenv_path, &target_dotenv_path).map_err(|e| {
|
let example_env_filename = "supabase/.env.example";
|
||||||
BusterError::CommandError(format!(
|
let asset = StaticAssets::get(example_env_filename)
|
||||||
"Failed to copy local .env from {} to {}: {}",
|
.ok_or_else(|| BusterError::CommandError(format!("Failed to get embedded asset: {}", example_env_filename)))?;
|
||||||
local_dotenv_path.display(),
|
|
||||||
target_dotenv_path.display(),
|
fs::write(&target_dotenv_path, asset.data).map_err(|e| {
|
||||||
e
|
BusterError::CommandError(format!(
|
||||||
))
|
"Failed to write {} to {}: {}",
|
||||||
})?;
|
example_env_filename,
|
||||||
} else {
|
target_dotenv_path.display(),
|
||||||
println!("Warning: Specified .env file not found at {}. Services might not configure correctly if .env is required by docker-compose.yml.", local_dotenv_path.display());
|
e
|
||||||
}
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Additionally copy the .env to the supabase subdirectory
|
||||||
|
let supabase_dotenv_path = app_base_dir.join("supabase/.env");
|
||||||
|
fs::copy(&target_dotenv_path, &supabase_dotenv_path).map_err(|e| {
|
||||||
|
BusterError::CommandError(format!(
|
||||||
|
"Failed to copy .env from {} to {}: {}",
|
||||||
|
target_dotenv_path.display(),
|
||||||
|
supabase_dotenv_path.display(),
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(app_base_dir)
|
Ok(app_base_dir)
|
||||||
}
|
}
|
||||||
|
@ -143,4 +157,155 @@ pub async fn start() -> Result<(), BusterError> {
|
||||||
|
|
||||||
pub async fn stop() -> Result<(), BusterError> {
|
pub async fn stop() -> Result<(), BusterError> {
|
||||||
run_docker_compose_command(&["down"], "Stopping").await
|
run_docker_compose_command(&["down"], "Stopping").await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn restart() -> Result<(), BusterError> {
|
||||||
|
println!("WARNING: This command will stop all Buster services, attempt to remove their current images, and then restart them.");
|
||||||
|
println!("This can lead to a complete wipe of the Buster database and any other local service data.");
|
||||||
|
println!("This action is irreversible.");
|
||||||
|
print!("Are you sure you want to proceed? (yes/No): ");
|
||||||
|
io::stdout().flush().map_err(|e| BusterError::CommandError(format!("Failed to flush stdout: {}", e)))?;
|
||||||
|
|
||||||
|
let mut confirmation = String::new();
|
||||||
|
io::stdin().read_line(&mut confirmation).map_err(|e| BusterError::CommandError(format!("Failed to read user input: {}", e)))?;
|
||||||
|
|
||||||
|
if confirmation.trim().to_lowercase() != "yes" {
|
||||||
|
println!("Restart cancelled by user.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let persistent_app_dir = setup_persistent_app_environment().await?;
|
||||||
|
|
||||||
|
let pb = ProgressBar::new_spinner();
|
||||||
|
pb.enable_steady_tick(Duration::from_millis(120));
|
||||||
|
pb.set_style(
|
||||||
|
ProgressStyle::default_spinner()
|
||||||
|
.tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸", "✔"])
|
||||||
|
.template("{spinner:.blue} {msg}")
|
||||||
|
.expect("Failed to set progress bar style"),
|
||||||
|
);
|
||||||
|
|
||||||
|
pb.set_message("Rebuilding Buster services (step 1/4): Stopping services...");
|
||||||
|
|
||||||
|
let mut down_cmd = Command::new("docker");
|
||||||
|
down_cmd.current_dir(&persistent_app_dir)
|
||||||
|
.arg("compose")
|
||||||
|
.arg("-p")
|
||||||
|
.arg("buster")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("docker-compose.yml")
|
||||||
|
.arg("down");
|
||||||
|
|
||||||
|
let down_output = down_cmd.output().map_err(|e| BusterError::CommandError(format!("Failed to execute docker compose down: {}", e)))?;
|
||||||
|
if !down_output.status.success() {
|
||||||
|
let err_msg = format!(
|
||||||
|
"docker compose down failed (status: {}). Logs:
|
||||||
|
Working directory: {}
|
||||||
|
Stdout:
|
||||||
|
{}
|
||||||
|
Stderr:
|
||||||
|
{}",
|
||||||
|
down_output.status,
|
||||||
|
persistent_app_dir.display(),
|
||||||
|
String::from_utf8_lossy(&down_output.stdout),
|
||||||
|
String::from_utf8_lossy(&down_output.stderr)
|
||||||
|
);
|
||||||
|
pb.abandon_with_message("Error: docker compose down failed. See console for details.");
|
||||||
|
println!("\nDocker Compose Down Error Details:\n{}", err_msg);
|
||||||
|
return Err(BusterError::CommandError(err_msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pb.set_message("Rebuilding Buster services (step 2/4): Identifying service images...");
|
||||||
|
let mut config_images_cmd = Command::new("docker");
|
||||||
|
config_images_cmd.current_dir(&persistent_app_dir)
|
||||||
|
.arg("compose")
|
||||||
|
.arg("-p")
|
||||||
|
.arg("buster")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("docker-compose.yml")
|
||||||
|
.arg("config")
|
||||||
|
.arg("--images");
|
||||||
|
|
||||||
|
let config_images_output = config_images_cmd.output().map_err(|e| BusterError::CommandError(format!("Failed to execute docker compose config --images: {}", e)))?;
|
||||||
|
if !config_images_output.status.success() {
|
||||||
|
let err_msg = format!(
|
||||||
|
"docker compose config --images failed (status: {}). Logs:
|
||||||
|
Working directory: {}
|
||||||
|
Stdout:
|
||||||
|
{}
|
||||||
|
Stderr:
|
||||||
|
{}",
|
||||||
|
config_images_output.status,
|
||||||
|
persistent_app_dir.display(),
|
||||||
|
String::from_utf8_lossy(&config_images_output.stdout),
|
||||||
|
String::from_utf8_lossy(&config_images_output.stderr)
|
||||||
|
);
|
||||||
|
pb.abandon_with_message("Error: Failed to identify service images. See console for details.");
|
||||||
|
println!("\nDocker Compose Config --images Error Details:\n{}", err_msg);
|
||||||
|
return Err(BusterError::CommandError(err_msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let image_list_str = String::from_utf8_lossy(&config_images_output.stdout);
|
||||||
|
let image_names: Vec<&str> = image_list_str.lines().filter(|line| !line.trim().is_empty()).collect();
|
||||||
|
|
||||||
|
if image_names.is_empty() {
|
||||||
|
pb.println("No images identified by docker-compose config --images. Skipping image removal.");
|
||||||
|
} else {
|
||||||
|
pb.set_message(format!("Rebuilding Buster services (step 3/4): Removing {} service image(s)...", image_names.len()));
|
||||||
|
for (index, image_name) in image_names.iter().enumerate() {
|
||||||
|
let current_image_name = image_name.trim();
|
||||||
|
if current_image_name.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pb.set_message(format!(
|
||||||
|
"Rebuilding Buster services (step 3/4): Removing image {}/{} ('{}')...",
|
||||||
|
index + 1,
|
||||||
|
image_names.len(),
|
||||||
|
current_image_name
|
||||||
|
));
|
||||||
|
let mut rmi_cmd = Command::new("docker");
|
||||||
|
rmi_cmd.arg("image").arg("rm").arg(current_image_name);
|
||||||
|
|
||||||
|
let rmi_output = rmi_cmd.output().map_err(|e| BusterError::CommandError(format!("Failed to execute docker image rm {}: {}", current_image_name, e)))?;
|
||||||
|
|
||||||
|
// Log warning on failure but continue, as image might not exist or be in use by other non-project containers
|
||||||
|
if !rmi_output.status.success() {
|
||||||
|
let rmi_stderr = String::from_utf8_lossy(&rmi_output.stderr);
|
||||||
|
if !rmi_stderr.trim().is_empty() && !rmi_stderr.contains("No such image") { // Don't warn if image was already gone
|
||||||
|
pb.println(format!("Warning: Could not remove image '{}'. It might be in use or already removed. Stderr: {}", current_image_name, rmi_stderr.trim()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pb.set_message("Rebuilding Buster services (step 4/4): Starting services (pulling images if needed)...");
|
||||||
|
let mut up_cmd = Command::new("docker");
|
||||||
|
up_cmd.current_dir(&persistent_app_dir)
|
||||||
|
.arg("compose")
|
||||||
|
.arg("-p")
|
||||||
|
.arg("buster")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("docker-compose.yml")
|
||||||
|
.arg("up")
|
||||||
|
.arg("-d")
|
||||||
|
.arg("--pull") // Ensure latest images are pulled
|
||||||
|
.arg("--force-recreate"); // Recreate containers even if config hasn't changed
|
||||||
|
|
||||||
|
let up_output = up_cmd.output().map_err(|e| BusterError::CommandError(format!("Failed to execute docker compose up: {}", e)))?;
|
||||||
|
|
||||||
|
if up_output.status.success() {
|
||||||
|
pb.finish_with_message("Buster services rebuilt and started successfully.");
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let err_msg = format!(
|
||||||
|
"docker compose up failed after image purge (status: {}). Logs:\nWorking directory: {}\nStdout:\n{}\nStderr:\n{}",
|
||||||
|
up_output.status,
|
||||||
|
persistent_app_dir.display(),
|
||||||
|
String::from_utf8_lossy(&up_output.stdout),
|
||||||
|
String::from_utf8_lossy(&up_output.stderr)
|
||||||
|
);
|
||||||
|
pb.abandon_with_message("Error: docker compose up failed after image purge. See console for details.");
|
||||||
|
println!("\nDocker Compose Up Error Details:\n{}", err_msg);
|
||||||
|
Err(BusterError::CommandError(err_msg))
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -80,8 +80,12 @@ pub enum Commands {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
},
|
},
|
||||||
|
/// Start the Buster services
|
||||||
Start,
|
Start,
|
||||||
|
/// Stop the Buster services
|
||||||
Stop,
|
Stop,
|
||||||
|
/// Restart the Buster services
|
||||||
|
Restart,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -140,6 +144,7 @@ async fn main() {
|
||||||
Commands::Parse { path } => commands::parse::parse_models_command(path).await,
|
Commands::Parse { path } => commands::parse::parse_models_command(path).await,
|
||||||
Commands::Start => run::start().await.map_err(anyhow::Error::from),
|
Commands::Start => run::start().await.map_err(anyhow::Error::from),
|
||||||
Commands::Stop => run::stop().await.map_err(anyhow::Error::from),
|
Commands::Stop => run::stop().await.map_err(anyhow::Error::from),
|
||||||
|
Commands::Restart => run::restart().await.map_err(anyhow::Error::from),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
|
|
|
@ -32,6 +32,7 @@ services:
|
||||||
- EMBEDDING_PROVIDER=${EMBEDDING_PROVIDER}
|
- EMBEDDING_PROVIDER=${EMBEDDING_PROVIDER}
|
||||||
- EMBEDDING_MODEL=${EMBEDDING_MODEL}
|
- EMBEDDING_MODEL=${EMBEDDING_MODEL}
|
||||||
- COHERE_API_KEY=${COHERE_API_KEY}
|
- COHERE_API_KEY=${COHERE_API_KEY}
|
||||||
|
- ENVIRONMENT=${ENVIRONMENT}
|
||||||
ports:
|
ports:
|
||||||
- "3001:3001"
|
- "3001:3001"
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
# General Application Settings
|
||||||
|
ENVIRONMENT="development"
|
||||||
|
BUSTER_URL="http://localhost:3000"
|
||||||
|
BUSTER_WH_TOKEN="buster-wh-token"
|
||||||
|
|
||||||
|
# --- API Service Specific ---
|
||||||
|
# Direct Database Connection (for API service and potentially others)
|
||||||
|
DATABASE_URL="postgresql://postgres.your-tenant-id:your-super-secret-and-long-postgres-password@supavisor:5432/postgres"
|
||||||
|
# Pooled Database Connection (for API service, uses Supavisor)
|
||||||
|
POOLER_URL="postgresql://postgres.your-tenant-id:your-super-secret-and-long-postgres-password@supavisor:5432/postgres"
|
||||||
|
# Redis Connection
|
||||||
|
REDIS_URL="redis://buster-redis:6379"
|
||||||
|
# Supabase Connection for API service
|
||||||
|
SUPABASE_URL="http://kong:8000"
|
||||||
|
SUPABASE_SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey AgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||||
|
|
||||||
|
# --- LLM / AI Services ---
|
||||||
|
EMBEDDING_PROVIDER="ollama"
|
||||||
|
EMBEDDING_MODEL="mxbai-embed-large"
|
||||||
|
COHERE_API_KEY=""
|
||||||
|
OPENAI_API_KEY="" # For OpenAI models or Supabase Studio assistant
|
||||||
|
LLM_API_KEY="test-key"
|
||||||
|
LLM_BASE_URL="http://litellm:4001"
|
||||||
|
|
||||||
|
# --- Web Client (Next.js) Specific ---
|
||||||
|
NEXT_PUBLIC_API_URL="http://localhost:3001" # External URL for the API service (buster-api)
|
||||||
|
NEXT_PUBLIC_URL="http://localhost:3000" # External URL for the Web service (buster-web)
|
||||||
|
NEXT_PUBLIC_SUPABASE_URL="http://kong:8000" # External URL for Supabase (Kong proxy)
|
||||||
|
NEXT_PUBLIC_WS_URL="ws://localhost:3001"
|
||||||
|
NEXT_PUBLIC_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey AgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"
|
||||||
|
NEXT_PRIVATE_SUPABASE_SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey AgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# Supabase Stack Configuration Variables
|
||||||
|
# These are primarily used by the Supabase services themselves
|
||||||
|
# (defined in supabase/docker-compose.yml)
|
||||||
|
# and are sourced from this .env file when `docker compose up` is run.
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
############
|
||||||
|
# Secrets
|
||||||
|
############
|
||||||
|
POSTGRES_PASSWORD="your-super-secret-and-long-postgres-password"
|
||||||
|
JWT_SECRET="your-super-secret-jwt-token-with-at-least-32-characters-long"
|
||||||
|
ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey AgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"
|
||||||
|
SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey AgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||||
|
DASHBOARD_USERNAME="supabase"
|
||||||
|
DASHBOARD_PASSWORD="this_password_is_insecure_and_should_be_updated"
|
||||||
|
|
||||||
|
############
|
||||||
|
# Database
|
||||||
|
############
|
||||||
|
POSTGRES_HOST="db"
|
||||||
|
POSTGRES_DB="postgres"
|
||||||
|
POSTGRES_PORT="5432"
|
||||||
|
|
||||||
|
############
|
||||||
|
# Supavisor -- Database pooler
|
||||||
|
############
|
||||||
|
POOLER_PROXY_PORT_TRANSACTION="6543"
|
||||||
|
POOLER_DEFAULT_POOL_SIZE="20"
|
||||||
|
POOLER_MAX_CLIENT_CONN="100"
|
||||||
|
POOLER_TENANT_ID="your-tenant-id"
|
||||||
|
|
||||||
|
############
|
||||||
|
# API Proxy - Kong
|
||||||
|
############
|
||||||
|
KONG_HTTP_PORT="8000"
|
||||||
|
KONG_HTTPS_PORT="8443"
|
||||||
|
|
||||||
|
############
|
||||||
|
# API - PostgREST
|
||||||
|
############
|
||||||
|
PGRST_DB_SCHEMAS="public,storage,graphql_public"
|
||||||
|
|
||||||
|
############
|
||||||
|
# Auth - GoTrue
|
||||||
|
############
|
||||||
|
SITE_URL="http://localhost:3000" # Default base URL for the site (used in emails, etc.)
|
||||||
|
ADDITIONAL_REDIRECT_URLS=""
|
||||||
|
JWT_EXPIRY="3600"
|
||||||
|
DISABLE_SIGNUP="false"
|
||||||
|
API_EXTERNAL_URL="http://localhost:8000" # Publicly accessible URL for the Supabase API (via Kong)
|
||||||
|
|
||||||
|
## Mailer Config
|
||||||
|
MAILER_URLPATHS_CONFIRMATION="/auth/v1/verify"
|
||||||
|
MAILER_URLPATHS_INVITE="/auth/v1/verify"
|
||||||
|
MAILER_URLPATHS_RECOVERY="/auth/v1/verify"
|
||||||
|
MAILER_URLPATHS_EMAIL_CHANGE="/auth/v1/verify"
|
||||||
|
|
||||||
|
## Email auth
|
||||||
|
ENABLE_EMAIL_SIGNUP="true"
|
||||||
|
ENABLE_EMAIL_AUTOCONFIRM="true"
|
||||||
|
SMTP_ADMIN_EMAIL="admin@buster.so"
|
||||||
|
SMTP_HOST="supabase-mail"
|
||||||
|
SMTP_PORT="2500"
|
||||||
|
SMTP_USER=""
|
||||||
|
SMTP_PASS=""
|
||||||
|
SMTP_SENDER_NAME="Buster"
|
||||||
|
ENABLE_ANONYMOUS_USERS="true"
|
||||||
|
|
||||||
|
## Phone auth
|
||||||
|
ENABLE_PHONE_SIGNUP="true"
|
||||||
|
ENABLE_PHONE_AUTOCONFIRM="true"
|
||||||
|
|
||||||
|
############
|
||||||
|
# Studio - Supabase Dashboard
|
||||||
|
############
|
||||||
|
STUDIO_DEFAULT_ORGANIZATION="Default Organization"
|
||||||
|
STUDIO_DEFAULT_PROJECT="Default Project"
|
||||||
|
STUDIO_PORT="3003"
|
||||||
|
SUPABASE_PUBLIC_URL="http://localhost:8000" # Public URL for Supabase (Kong), used by Studio
|
||||||
|
|
||||||
|
# Image Proxy
|
||||||
|
IMGPROXY_ENABLE_WEBP_DETECTION="true"
|
||||||
|
|
||||||
|
############
|
||||||
|
# Functions - Supabase Edge Functions
|
||||||
|
############
|
||||||
|
FUNCTIONS_VERIFY_JWT="false"
|
||||||
|
|
||||||
|
############
|
||||||
|
# Logs - Logflare
|
||||||
|
############
|
||||||
|
LOGFLARE_LOGGER_BACKEND_API_KEY="your-super-secret-and-long-logflare-key"
|
||||||
|
LOGFLARE_API_KEY="your-super-secret-and-long-logflare-key"
|
||||||
|
DOCKER_SOCKET_LOCATION="/var/run/docker.sock"
|
||||||
|
GOOGLE_PROJECT_ID="GOOGLE_PROJECT_ID"
|
||||||
|
GOOGLE_PROJECT_NUMBER="GOOGLE_PROJECT_NUMBER"
|
Loading…
Reference in New Issue