Initial commit
This commit is contained in:
91
install.sh
Executable file
91
install.sh
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
source "$SCRIPT_DIR/libsupabase.sh"
|
||||
setup_traps
|
||||
|
||||
########################################
|
||||
# Defaults
|
||||
########################################
|
||||
|
||||
cores=2
|
||||
memory=4096
|
||||
swap=512
|
||||
disk=50
|
||||
bridge="vmbr0"
|
||||
storage="local-zfs"
|
||||
ip="dhcp"
|
||||
unpriv=1
|
||||
ctid=""
|
||||
|
||||
########################################
|
||||
# Args
|
||||
########################################
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--cores) cores="$2"; shift 2 ;;
|
||||
--memory) memory="$2"; shift 2 ;;
|
||||
--swap) swap="$2"; shift 2 ;;
|
||||
--disk) disk="$2"; shift 2 ;;
|
||||
--bridge) bridge="$2"; shift 2 ;;
|
||||
--storage) storage="$2"; shift 2 ;;
|
||||
--ip) ip="$2"; shift 2 ;;
|
||||
--ctid) ctid="$2"; shift 2 ;;
|
||||
--help)
|
||||
echo "Usage: bash install.sh [options]"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
die "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
info "Argument-Parsing OK"
|
||||
|
||||
########################################
|
||||
# Checks
|
||||
########################################
|
||||
|
||||
need_cmd pct pvesm pveam pvesh awk grep sort
|
||||
|
||||
pve_bridge_exists "$bridge" || die "Bridge $bridge not found"
|
||||
pve_storage_exists "$storage" || die "Storage $storage not found"
|
||||
|
||||
template="$(pve_template_ensure_debian12 "$storage")"
|
||||
info "Template OK: $template"
|
||||
|
||||
if [[ -z "$ctid" ]]; then
|
||||
ctid="$(pve_next_free_ctid)"
|
||||
fi
|
||||
|
||||
[[ -n "$ctid" ]] || die "CTID empty"
|
||||
|
||||
hostname="sb-$(date +%s)"
|
||||
|
||||
info "Using CTID=$ctid Hostname=$hostname"
|
||||
|
||||
########################################
|
||||
# Create CT
|
||||
########################################
|
||||
|
||||
net0="$(pve_build_net0 "$bridge" "$ip")"
|
||||
rootfs="$storage:$disk"
|
||||
features="nesting=1,keyctl=1,fuse=1"
|
||||
|
||||
info "Creating CT $ctid"
|
||||
|
||||
pct create "$ctid" "$template" \
|
||||
--hostname "$hostname" \
|
||||
--cores "$cores" \
|
||||
--memory "$memory" \
|
||||
--swap "$swap" \
|
||||
--net0 "$net0" \
|
||||
--rootfs "$rootfs" \
|
||||
--unprivileged "$unpriv" \
|
||||
--features "$features" \
|
||||
--start 0
|
||||
|
||||
info "CT created successfully"
|
||||
97
libsupabase.sh
Executable file
97
libsupabase.sh
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
########################################
|
||||
# Logging / Errors
|
||||
########################################
|
||||
|
||||
_ts() { date '+%F %T'; }
|
||||
|
||||
log() { echo "[$(_ts)] $*"; }
|
||||
info() { log "INFO: $*"; }
|
||||
warn() { log "WARN: $*"; }
|
||||
die() { log "ERROR: $*"; exit 1; }
|
||||
|
||||
on_error() {
|
||||
die "Failed at line $1: $2 (exit=$3)"
|
||||
}
|
||||
setup_traps() {
|
||||
trap 'on_error $LINENO "$BASH_COMMAND" "$?"' ERR
|
||||
}
|
||||
|
||||
########################################
|
||||
# Preconditions
|
||||
########################################
|
||||
|
||||
need_cmd() {
|
||||
for c in "$@"; do
|
||||
command -v "$c" >/dev/null 2>&1 || die "Missing command: $c"
|
||||
done
|
||||
}
|
||||
|
||||
########################################
|
||||
# Proxmox helpers
|
||||
########################################
|
||||
|
||||
pve_bridge_exists() {
|
||||
[[ -d "/sys/class/net/$1/bridge" ]]
|
||||
}
|
||||
|
||||
pve_storage_exists() {
|
||||
pvesm status --storage "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
########################################
|
||||
# Template handling
|
||||
########################################
|
||||
|
||||
pve_template_ensure_debian12() {
|
||||
local tpl="debian-12-standard_12.12-1_amd64.tar.zst"
|
||||
local store="$1"
|
||||
|
||||
if ! pveam list "$store" >/dev/null 2>&1; then
|
||||
warn "pveam storage '$store' not available for templates; falling back to 'local'"
|
||||
store="local"
|
||||
fi
|
||||
|
||||
if ! pveam list "$store" | awk '{print $2}' | grep -qx "$tpl"; then
|
||||
info "Downloading CT template to $store: $tpl"
|
||||
pveam update
|
||||
pveam download "$store" "$tpl"
|
||||
fi
|
||||
|
||||
echo "$store:vztmpl/$tpl"
|
||||
}
|
||||
|
||||
########################################
|
||||
# Cluster-wide CTID
|
||||
########################################
|
||||
|
||||
pve_next_free_ctid() {
|
||||
local used
|
||||
used="$(pvesh get /cluster/resources --type vm | awk 'NR>1 {print $1}' | sort -n)"
|
||||
|
||||
for id in $(seq 100 9999); do
|
||||
if ! echo "$used" | grep -qx "$id"; then
|
||||
echo "$id"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
die "No free CTID found"
|
||||
}
|
||||
|
||||
########################################
|
||||
# Networking
|
||||
########################################
|
||||
|
||||
pve_build_net0() {
|
||||
local bridge="$1"
|
||||
local ip="$2"
|
||||
|
||||
if [[ "$ip" == "dhcp" ]]; then
|
||||
echo "name=eth0,bridge=$bridge,ip=dhcp"
|
||||
else
|
||||
echo "name=eth0,bridge=$bridge,ip=$ip"
|
||||
fi
|
||||
}
|
||||
5
sql/init_pgvector.sql
Normal file
5
sql/init_pgvector.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
-- Optional, aber hilfreich:
|
||||
-- CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
95
templates/docker-compose.yml
Normal file
95
templates/docker-compose.yml
Normal file
@@ -0,0 +1,95 @@
|
||||
services:
|
||||
# --- Vectorstore DB (pgvector) ---
|
||||
supabase-db:
|
||||
image: pgvector/pgvector:pg15
|
||||
container_name: supabase-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${SB_DB_NAME}
|
||||
POSTGRES_USER: ${SB_DB_USER}
|
||||
POSTGRES_PASSWORD: ${SB_DB_PASS}
|
||||
volumes:
|
||||
- ./volumes/supabase-db:/var/lib/postgresql/data
|
||||
- ./init:/docker-entrypoint-initdb.d:ro
|
||||
ports:
|
||||
- "5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${SB_DB_USER} -d ${SB_DB_NAME}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 15
|
||||
|
||||
# Optional: REST API auf die Vector-DB (wenn du es brauchst)
|
||||
# Wenn du "von außen keinen DB-Zugriff" willst: später im Reverse Proxy sperren oder Port entfernen.
|
||||
postgrest:
|
||||
image: postgrest/postgrest:v12.2.8
|
||||
container_name: postgrest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
supabase-db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
PGRST_DB_URI: postgres://${SB_DB_USER}:${SB_DB_PASS}@supabase-db:5432/${SB_DB_NAME}
|
||||
PGRST_DB_SCHEMA: public
|
||||
PGRST_DB_ANON_ROLE: anon
|
||||
PGRST_SERVER_PORT: 3000
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
# --- n8n DB (separat, sauber getrennt) ---
|
||||
n8n-db:
|
||||
image: postgres:15-alpine
|
||||
container_name: n8n-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${N8N_DB_NAME}
|
||||
POSTGRES_USER: ${N8N_DB_USER}
|
||||
POSTGRES_PASSWORD: ${N8N_DB_PASS}
|
||||
volumes:
|
||||
- ./volumes/n8n-db:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${N8N_DB_USER} -d ${N8N_DB_NAME}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 15
|
||||
|
||||
# --- n8n ---
|
||||
n8n:
|
||||
image: docker.n8n.io/n8nio/n8n:latest
|
||||
container_name: n8n
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
n8n-db:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "5678:5678"
|
||||
environment:
|
||||
DB_TYPE: postgresdb
|
||||
DB_POSTGRESDB_HOST: n8n-db
|
||||
DB_POSTGRESDB_PORT: 5432
|
||||
DB_POSTGRESDB_DATABASE: ${N8N_DB_NAME}
|
||||
DB_POSTGRESDB_USER: ${N8N_DB_USER}
|
||||
DB_POSTGRESDB_PASSWORD: ${N8N_DB_PASS}
|
||||
|
||||
GENERIC_TIMEZONE: Europe/Berlin
|
||||
NODE_ENV: production
|
||||
|
||||
N8N_HOST: ${N8N_HOST}
|
||||
N8N_PORT: 5678
|
||||
WEBHOOK_URL: ${N8N_WEBHOOK_URL}
|
||||
|
||||
N8N_BASIC_AUTH_ACTIVE: "true"
|
||||
N8N_BASIC_AUTH_USER: ${N8N_BASIC_AUTH_USER}
|
||||
N8N_BASIC_AUTH_PASSWORD: ${N8N_BASIC_AUTH_PASS}
|
||||
|
||||
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
|
||||
|
||||
# Solange du KEIN HTTPS hast, sonst bekommst du genau die "secure cookie"-Meldung:
|
||||
N8N_SECURE_COOKIE: "false"
|
||||
|
||||
# Optional: wenn du später Community Nodes brauchst
|
||||
N8N_COMMUNITY_PACKAGES_ENABLED: "true"
|
||||
|
||||
volumes:
|
||||
- ./volumes/n8n-data:/home/node/.n8n
|
||||
|
||||
Reference in New Issue
Block a user