start
This commit is contained in:
42
.env
Normal file
42
.env
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
LOCAL_TIMEZONE="America/Argentina/Buenos_Aires"
|
||||||
|
STORAGE_VOLUME="/storage"
|
||||||
|
APPS_VOLUME="/containers"
|
||||||
|
GID="${UID}"
|
||||||
|
PUBLIC_IP="181.14.212.99"
|
||||||
|
LOCAL_IP="192.168.1.239"
|
||||||
|
OLLAMA_SERVER="192.168.1.135:11434"
|
||||||
|
DOMAIN_NAME="sudestec.ar"
|
||||||
|
PROXY_HTTP_PORT="7700"
|
||||||
|
PROXY_HTTPS_PORT="7701"
|
||||||
|
PROXY_PORT="7702"
|
||||||
|
NEXTCLOUD_PORT="7710"
|
||||||
|
ONLYOFFICE_PORT="7711"
|
||||||
|
POCKETBASE_PORT="7720"
|
||||||
|
GITEA_PORT="7730"
|
||||||
|
GITEA_PORT2="7731"
|
||||||
|
FLATNOTE_PORT="7740"
|
||||||
|
FLATNOTE_NAME="flatnote"
|
||||||
|
SUPABASE_DATABASE_PASSWORD="facU8990"
|
||||||
|
SUPABASE_DATABASE="supabase-db"
|
||||||
|
NEXTCLOUD_TRUSTED_DOMAINS="${LOCAL_IP} ${DOMAIN_NAME}"
|
||||||
|
NEXTCLOUD_REDIS_ENABLED=""
|
||||||
|
NEXTCLOUD_VERSION="stable"
|
||||||
|
OPENWEBUI_PORT=""
|
||||||
|
VIRTMANAGER_PORT=""
|
||||||
|
WIREGUARD_PORT=""
|
||||||
|
GITEA_NAME="git-sudeste"
|
||||||
|
WIREGUARD_PEERS="10"
|
||||||
|
WIREGUARD_SUBNET="7.7.7.0"
|
||||||
|
ADMIN_EMAIL="facu.vdp@gmail.com"
|
||||||
|
ADMIN_USERNAME="sudeste"
|
||||||
|
ADMIN_PASSWORD="facU8990!$"
|
||||||
|
POCKETBASE_VERSION="latest"
|
||||||
|
POCKETBASE_NAME="pocketbase"
|
||||||
|
POCKETBASE_TRUSTED_DOMAINS="127.0.0.1,localhost,server-sudestec,192.168.1.239,own.sudestec.ar"
|
||||||
|
SPEEDTEST_SCHEDULE="*/30 * * * *"
|
||||||
|
SPEEDTEST_SERVERS="13449,54503"
|
||||||
|
PHP_MEMORY_LIMIT="1024M"
|
||||||
|
PHP_UPLOAD_LIMIT="10240M"
|
||||||
|
JWT_SECRET="100847038046ae5cb373204d405da78c0817285b17e3212a8a2970bf4605cfc2"
|
||||||
|
ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzY4ODg2OTQ4LCJleHAiOjE3Njg4OTA1NDh9.HlpsCqlfMYmHH8ZO-X-Q099awds6o71CEq0qwpbGUSY"
|
||||||
|
SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UiLCJpYXQiOjE3Njg4ODY5NDgsImV4cCI6MjA4NDI0Njk0OH0.MW_D_r9FBh9EC-DR8G1mJedXC8EaZyTZNYkGafDE3fU"
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,3 +10,5 @@ test-servers/
|
|||||||
.bundle
|
.bundle
|
||||||
vendor
|
vendor
|
||||||
|
|
||||||
|
test
|
||||||
|
secret
|
||||||
2
.gitignore copy
Normal file
2
.gitignore copy
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
test
|
||||||
|
secret
|
||||||
33
commands/01-start-proxy_server.sh
Executable file
33
commands/01-start-proxy_server.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
source .env
|
||||||
|
|
||||||
|
proxy_path=${APPS_VOLUME}/proxy
|
||||||
|
proxy_data=${proxy_path}/data
|
||||||
|
proxy_letsencrypt=${proxy_path}/letsencrypt
|
||||||
|
|
||||||
|
for p in "${proxy_data}" "${proxy_letsencrypt}"; do
|
||||||
|
if ! ls ${p} >/dev/null 2>&1; then
|
||||||
|
echo "Creating ${p} directory..."
|
||||||
|
mkdir -p ${p}
|
||||||
|
else
|
||||||
|
echo "directory exists ${p}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
podman run -d --replace \
|
||||||
|
--name proxy_server \
|
||||||
|
--hostname proxy_server \
|
||||||
|
--network container-bridge \
|
||||||
|
--tz=local \
|
||||||
|
-p ${PROXY_PORT}:81 \
|
||||||
|
-p ${PROXY_HTTP_PORT}:80 \
|
||||||
|
-p ${PROXY_HTTPS_PORT}:443 \
|
||||||
|
-v ${proxy_data}:/data \
|
||||||
|
-v ${proxy_letsencrypt}:/etc/letsencrypt \
|
||||||
|
--health-cmd="/usr/bin/check-health" \
|
||||||
|
--health-interval=10s \
|
||||||
|
--health-timeout=3s \
|
||||||
|
-e DISABLE_IPV6=true \
|
||||||
|
-e INITIAL_ADMIN_EMAIL=${ADMIN_EMAIL} \
|
||||||
|
-e INITIAL_ADMIN_PASSWORD=${ADMIN_PASSWORD} \
|
||||||
|
docker.io/jc21/nginx-proxy-manager:latest
|
||||||
28
commands/02-start-redis.sh
Executable file
28
commands/02-start-redis.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
source .env
|
||||||
|
|
||||||
|
redis_path=${APPS_VOLUME}/redis
|
||||||
|
|
||||||
|
for p in "${redis_path}"; do
|
||||||
|
if ! ls ${p} >/dev/null 2>&1; then
|
||||||
|
echo "Creating ${p} directory..."
|
||||||
|
mkdir -p ${p}
|
||||||
|
else
|
||||||
|
echo "directory exists ${p}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
podman run -d --replace \
|
||||||
|
--name redis \
|
||||||
|
--hostname redis \
|
||||||
|
--network container-bridge \
|
||||||
|
--tz=local \
|
||||||
|
-v ${redis_path}:/data \
|
||||||
|
--health-cmd="redis-cli ping" \
|
||||||
|
--health-interval=10s \
|
||||||
|
--health-timeout=5s \
|
||||||
|
--health-retries=5 \
|
||||||
|
docker.io/redis:6 \
|
||||||
|
--databases 1
|
||||||
|
|
||||||
|
podman generate systemd --new --files --name redis
|
||||||
40
commands/03-start-nextcloud.sh
Executable file
40
commands/03-start-nextcloud.sh
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Create container directories
|
||||||
|
nc_app=${APPS_VOLUME}/nextcloud
|
||||||
|
nc_data=${STORAGE_VOLUME}/nextcloud
|
||||||
|
|
||||||
|
for p in "${nc_app} ${nc_data}"; do
|
||||||
|
if ! ls ${p} >/dev/null 2>&1; then
|
||||||
|
echo "Creating ${p} directory..."
|
||||||
|
mkdir -p ${p}
|
||||||
|
else
|
||||||
|
echo "directory exists ${p}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
podman run -d --replace \
|
||||||
|
--name nextcloud_server \
|
||||||
|
--hostname nextcloud_server \
|
||||||
|
--restart=always \
|
||||||
|
--network container-bridge \
|
||||||
|
--tz=local \
|
||||||
|
-p ${NEXTCLOUD_PORT}:80 \
|
||||||
|
-e NEXTCLOUD_ADMIN_USER=${ADMIN_USERNAME} \
|
||||||
|
-e NEXTCLOUD_ADMIN_PASSWORD=${ADMIN_PASSWORD} \
|
||||||
|
-e NEXTCLOUD_TRUSTED_DOMAINS="cloud.${DOMAIN_NAME} ${LOCAL_IP} ${PUBLIC_IP}" \
|
||||||
|
-e TRUSTED_PROXIES=proxy_server \
|
||||||
|
-e TRUSTED_PROXIES=${LOCAL_IP}:${HTTPS_PORT} \
|
||||||
|
-e OVERWRITECLIURL=https://cloud.${DOMAIN_NAME} \
|
||||||
|
-e SQLITE_DATABASE=nextcloud_db \
|
||||||
|
-e REDIS_HOST=redis \
|
||||||
|
-e PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT} \
|
||||||
|
-e PHP_UPLOAD_LIMIT=${PHP_UPLOAD_LIMIT} \
|
||||||
|
-v ${nc_app}:/var/www/html \
|
||||||
|
-v ${nc_data}:/var/www/html/data \
|
||||||
|
--health-interval=30s \
|
||||||
|
--health-timeout=10s \
|
||||||
|
--health-retries=5 \
|
||||||
|
--health-cmd="curl -f ${LOCAL_IP}:${NEXTCLOUD_PORT}" \
|
||||||
|
docker.io/nextcloud:${NEXTCLOUD_VERSION}
|
||||||
30
commands/04-start-pocketbase.sh
Executable file
30
commands/04-start-pocketbase.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
source .env
|
||||||
|
|
||||||
|
pb_ap=${STORAGE_VOLUME}/${POCKETBASE_NAME}
|
||||||
|
|
||||||
|
for p in "${pb_ap}/data ${pb_ap}/public"; do
|
||||||
|
if ! ls ${p} >/dev/null 2>&1; then
|
||||||
|
echo "Creating ${p} directory..."
|
||||||
|
mkdir -p ${p}
|
||||||
|
else
|
||||||
|
echo "directory exists ${p}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
podman run -d --replace \
|
||||||
|
--name ${POCKETBASE_NAME} \
|
||||||
|
--hostname ${POCKETBASE_NAME} \
|
||||||
|
--restart=always \
|
||||||
|
--network container-bridge \
|
||||||
|
-p ${POCKETBASE_PORT}:${POCKETBASE_PORT} \
|
||||||
|
-e PB_PORT=${POCKETBASE_PORT} \
|
||||||
|
-e PB_ADMIN_EMAIL=${ADMIN_EMAIL} \
|
||||||
|
-e PB_ADMIN_PASSWORD=${ADMIN_PASSWORD} \
|
||||||
|
-v ${pb_ap}/data:/pb_data \
|
||||||
|
-v ${pb_ap}/public:/public \
|
||||||
|
--health-cmd="wget --no-verbose --tries=1 --spider ${LOCAL_IP}:${POCKETBASE_PORT}/api/health" \
|
||||||
|
--health-interval=30s \
|
||||||
|
--health-timeout=10s \
|
||||||
|
--health-retries=5 \
|
||||||
|
ghcr.io/muchobien/pocketbase:latest
|
||||||
31
commands/05-start-gitea.sh
Executable file
31
commands/05-start-gitea.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
source .env
|
||||||
|
|
||||||
|
git_data=${STORAGE_VOLUME}/${GITEA_NAME}
|
||||||
|
|
||||||
|
for p in "${git_data}"; do
|
||||||
|
if ! ls ${p} >/dev/null 2>&1; then
|
||||||
|
echo "Creating ${p} directory..."
|
||||||
|
mkdir -p ${p}
|
||||||
|
else
|
||||||
|
echo "directory exists ${p}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
podman run -d --replace \
|
||||||
|
--name ${GITEA_NAME} \
|
||||||
|
--hostname ${GITEA_NAME} \
|
||||||
|
--restart=always \
|
||||||
|
--network container-bridge \
|
||||||
|
-p ${GITEA_PORT}:3000 \
|
||||||
|
-p ${GITEA_PORT2}:2222 \
|
||||||
|
-v ${git_data}:/data \
|
||||||
|
-v /etc/timezone:/etc/timezone:ro \
|
||||||
|
-v /etc/localtime:/etc/localtime:ro \
|
||||||
|
-e USER_UID=1000 \
|
||||||
|
-e USER_GID=1000 \
|
||||||
|
--health-cmd="curl -f ${LOCAL_IP}:${GITEA_PORT}/api/healthz" \
|
||||||
|
--health-interval=30s \
|
||||||
|
--health-timeout=10s \
|
||||||
|
--health-retries=5 \
|
||||||
|
docker.gitea.com/gitea:latest
|
||||||
33
commands/06-start-flatnotes.sh
Executable file
33
commands/06-start-flatnotes.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
source .env
|
||||||
|
|
||||||
|
git_data=${STORAGE_VOLUME}/${FLATNOTE_NAME}
|
||||||
|
|
||||||
|
for p in "${git_data}"; do
|
||||||
|
if ! ls ${p} >/dev/null 2>&1; then
|
||||||
|
echo "Creating ${p} directory..."
|
||||||
|
mkdir -p ${p}
|
||||||
|
else
|
||||||
|
echo "directory exists ${p}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
podman run -d --replace \
|
||||||
|
--name ${FLATNOTE_NAME} \
|
||||||
|
--hostname ${FLATNOTE_NAME} \
|
||||||
|
--restart=always \
|
||||||
|
--network container-bridge \
|
||||||
|
-p ${FLATNOTE_PORT}:8080 \
|
||||||
|
-v ${git_data}:/data \
|
||||||
|
--userns=keep-id:uid=1000,gid=1000 \
|
||||||
|
-e PUID=1000 \
|
||||||
|
-e PGID=1000 \
|
||||||
|
-e FLATNOTES_AUTH_TYPE=password \
|
||||||
|
-e FLATNOTES_USERNAME=${ADMIN_USERNAME} \
|
||||||
|
-e FLATNOTES_PASSWORD=${ADMIN_PASSWORD} \
|
||||||
|
-e FLATNOTES_SECRET_KEY=${ANON_KEY} \
|
||||||
|
--health-cmd="curl -f ${LOCAL_IP}:${FLATNOTE_PORT}/health" \
|
||||||
|
--health-interval=30s \
|
||||||
|
--health-timeout=10s \
|
||||||
|
--health-retries=5 \
|
||||||
|
docker.io/dullage/flatnotes:latest
|
||||||
20
commands/DELETE.sh
Executable file
20
commands/DELETE.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
echo "⚠️ WARNING: This will permanently delete data."
|
||||||
|
|
||||||
|
select choice in "Abort" "Continue"; do
|
||||||
|
case "$choice" in
|
||||||
|
"Abort")
|
||||||
|
echo "Aborted."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
"Continue")
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
podman container stop --all
|
||||||
|
|
||||||
|
podman system prune --all
|
||||||
|
|
||||||
|
sudo rm -rdf /storage/flatnote
|
||||||
55
commands/generate-keys.sh
Executable file
55
commands/generate-keys.sh
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# === config ===
|
||||||
|
JWT_EXP_ANON=3600
|
||||||
|
JWT_EXP_SERVICE=315360000 # 10 years
|
||||||
|
JWT_ISSUER="supabase"
|
||||||
|
|
||||||
|
# === helpers ===
|
||||||
|
b64url() {
|
||||||
|
openssl base64 -A | tr '+/' '-_' | tr -d '='
|
||||||
|
}
|
||||||
|
|
||||||
|
jwt_sign() {
|
||||||
|
header=$1
|
||||||
|
payload=$2
|
||||||
|
secret=$3
|
||||||
|
|
||||||
|
header_b64=$(printf '%s' "$header" | b64url)
|
||||||
|
payload_b64=$(printf '%s' "$payload" | b64url)
|
||||||
|
|
||||||
|
sig=$(printf '%s.%s' "$header_b64" "$payload_b64" |
|
||||||
|
openssl dgst -binary -sha256 -hmac "$secret" | b64url)
|
||||||
|
|
||||||
|
printf '%s.%s.%s\n' "$header_b64" "$payload_b64" "$sig"
|
||||||
|
}
|
||||||
|
|
||||||
|
# === generate JWT secret ===
|
||||||
|
JWT_SECRET=$(openssl rand -hex 32)
|
||||||
|
|
||||||
|
NOW=$(date +%s)
|
||||||
|
|
||||||
|
JWT_HEADER='{"alg":"HS256","typ":"JWT"}'
|
||||||
|
|
||||||
|
ANON_PAYLOAD=$(
|
||||||
|
cat <<EOF
|
||||||
|
{"role":"anon","iss":"$JWT_ISSUER","iat":$NOW,"exp":$((NOW + JWT_EXP_ANON))}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
SERVICE_PAYLOAD=$(
|
||||||
|
cat <<EOF
|
||||||
|
{"role":"service_role","iss":"$JWT_ISSUER","iat":$NOW,"exp":$((NOW + JWT_EXP_SERVICE))}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
ANON_KEY=$(jwt_sign "$JWT_HEADER" "$ANON_PAYLOAD" "$JWT_SECRET")
|
||||||
|
SERVICE_ROLE_KEY=$(jwt_sign "$JWT_HEADER" "$SERVICE_PAYLOAD" "$JWT_SECRET")
|
||||||
|
|
||||||
|
# === output .env-compatible ===
|
||||||
|
cat <<EOF
|
||||||
|
JWT_SECRET=$JWT_SECRET
|
||||||
|
ANON_KEY=$ANON_KEY
|
||||||
|
SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY
|
||||||
|
EOF
|
||||||
63
commands/init.sh
Executable file
63
commands/init.sh
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR" || exit 1
|
||||||
|
|
||||||
|
# write new secret:
|
||||||
|
if [[ -f "secret" ]]; then
|
||||||
|
echo "Secret found..." >&2
|
||||||
|
else
|
||||||
|
echo "Secret created..." >&2
|
||||||
|
openssl rand -hex 32 >./secret
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create network
|
||||||
|
if ! podman network inspect container-bridge >/dev/null 2>&1; then
|
||||||
|
echo "Creating container-bridge network..."
|
||||||
|
podman network create container-bridge
|
||||||
|
else
|
||||||
|
echo "container-bridge network already exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get podman start scripts
|
||||||
|
shopt -s nullglob
|
||||||
|
# start_files=( *-start-*.sh )
|
||||||
|
containers=()
|
||||||
|
|
||||||
|
# Run every start stcript
|
||||||
|
for f in *-start-*.sh; do
|
||||||
|
trim="${f%.sh}"
|
||||||
|
container="${trim#*start-}"
|
||||||
|
containers+=("$container")
|
||||||
|
echo "Running $container"
|
||||||
|
chmod +x "$f"
|
||||||
|
./"$f"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Generate systemd Units
|
||||||
|
|
||||||
|
# mkdir -p ~/.config/systemd/user
|
||||||
|
# for f in "${containers[@]}"; do
|
||||||
|
# echo "Generating systemd Unit for $f"
|
||||||
|
# podman generate systemd --files --name $f
|
||||||
|
# if ! [ -e "patch-${f}-service.sh" ]; then
|
||||||
|
# echo "No patch for container-${f}.service"
|
||||||
|
# else
|
||||||
|
# echo "Patching container-${f}.service..."
|
||||||
|
#
|
||||||
|
# fi
|
||||||
|
# mv container-$f.service ~/.config/systemd/user/
|
||||||
|
# done
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# Add to container-owncloud_server.service
|
||||||
|
# Requires=container-owncloud_mariadb.service
|
||||||
|
# Requires=container-owncloud_redis.service
|
||||||
|
# After=container-owncloud_mariadb.service
|
||||||
|
# After=container-owncloud_redis.service
|
||||||
|
|
||||||
|
# Add to container-proxy_server.service
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
283
commands/kong.yml
Normal file
283
commands/kong.yml
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
_format_version: '2.1'
|
||||||
|
_transform: true
|
||||||
|
|
||||||
|
###
|
||||||
|
### Consumers / Users
|
||||||
|
###
|
||||||
|
consumers:
|
||||||
|
- username: DASHBOARD
|
||||||
|
- username: anon
|
||||||
|
keyauth_credentials:
|
||||||
|
- key: $SUPABASE_ANON_KEY
|
||||||
|
- username: service_role
|
||||||
|
keyauth_credentials:
|
||||||
|
- key: $SUPABASE_SERVICE_KEY
|
||||||
|
|
||||||
|
###
|
||||||
|
### Access Control List
|
||||||
|
###
|
||||||
|
acls:
|
||||||
|
- consumer: anon
|
||||||
|
group: anon
|
||||||
|
- consumer: service_role
|
||||||
|
group: admin
|
||||||
|
|
||||||
|
###
|
||||||
|
### Dashboard credentials
|
||||||
|
###
|
||||||
|
basicauth_credentials:
|
||||||
|
- consumer: DASHBOARD
|
||||||
|
username: $DASHBOARD_USERNAME
|
||||||
|
password: $DASHBOARD_PASSWORD
|
||||||
|
|
||||||
|
###
|
||||||
|
### API Routes
|
||||||
|
###
|
||||||
|
services:
|
||||||
|
## Open Auth routes
|
||||||
|
- name: auth-v1-open
|
||||||
|
url: http://auth:9999/verify
|
||||||
|
routes:
|
||||||
|
- name: auth-v1-open
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /auth/v1/verify
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: auth-v1-open-callback
|
||||||
|
url: http://auth:9999/callback
|
||||||
|
routes:
|
||||||
|
- name: auth-v1-open-callback
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /auth/v1/callback
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: auth-v1-open-authorize
|
||||||
|
url: http://auth:9999/authorize
|
||||||
|
routes:
|
||||||
|
- name: auth-v1-open-authorize
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /auth/v1/authorize
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
|
||||||
|
## Secure Auth routes
|
||||||
|
- name: auth-v1
|
||||||
|
_comment: 'GoTrue: /auth/v1/* -> http://auth:9999/*'
|
||||||
|
url: http://auth:9999/
|
||||||
|
routes:
|
||||||
|
- name: auth-v1-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /auth/v1/
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: false
|
||||||
|
- name: acl
|
||||||
|
config:
|
||||||
|
hide_groups_header: true
|
||||||
|
allow:
|
||||||
|
- admin
|
||||||
|
- anon
|
||||||
|
|
||||||
|
## Secure REST routes
|
||||||
|
- name: rest-v1
|
||||||
|
_comment: 'PostgREST: /rest/v1/* -> http://rest:3000/*'
|
||||||
|
url: http://rest:3000/
|
||||||
|
routes:
|
||||||
|
- name: rest-v1-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /rest/v1/
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: true
|
||||||
|
- name: acl
|
||||||
|
config:
|
||||||
|
hide_groups_header: true
|
||||||
|
allow:
|
||||||
|
- admin
|
||||||
|
- anon
|
||||||
|
|
||||||
|
## Secure GraphQL routes
|
||||||
|
- name: graphql-v1
|
||||||
|
_comment: 'PostgREST: /graphql/v1/* -> http://rest:3000/rpc/graphql'
|
||||||
|
url: http://rest:3000/rpc/graphql
|
||||||
|
routes:
|
||||||
|
- name: graphql-v1-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /graphql/v1
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: true
|
||||||
|
- name: request-transformer
|
||||||
|
config:
|
||||||
|
add:
|
||||||
|
headers:
|
||||||
|
- Content-Profile:graphql_public
|
||||||
|
- name: acl
|
||||||
|
config:
|
||||||
|
hide_groups_header: true
|
||||||
|
allow:
|
||||||
|
- admin
|
||||||
|
- anon
|
||||||
|
|
||||||
|
## Secure Realtime routes
|
||||||
|
- name: realtime-v1-ws
|
||||||
|
_comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*'
|
||||||
|
url: http://realtime-dev.supabase-realtime:4000/socket
|
||||||
|
protocol: ws
|
||||||
|
routes:
|
||||||
|
- name: realtime-v1-ws
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /realtime/v1/
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: false
|
||||||
|
- name: acl
|
||||||
|
config:
|
||||||
|
hide_groups_header: true
|
||||||
|
allow:
|
||||||
|
- admin
|
||||||
|
- anon
|
||||||
|
- name: realtime-v1-rest
|
||||||
|
_comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*'
|
||||||
|
url: http://realtime-dev.supabase-realtime:4000/api
|
||||||
|
protocol: http
|
||||||
|
routes:
|
||||||
|
- name: realtime-v1-rest
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /realtime/v1/api
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: false
|
||||||
|
- name: acl
|
||||||
|
config:
|
||||||
|
hide_groups_header: true
|
||||||
|
allow:
|
||||||
|
- admin
|
||||||
|
- anon
|
||||||
|
## Storage routes: the storage server manages its own auth
|
||||||
|
- name: storage-v1
|
||||||
|
_comment: 'Storage: /storage/v1/* -> http://storage:5000/*'
|
||||||
|
url: http://storage:5000/
|
||||||
|
routes:
|
||||||
|
- name: storage-v1-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /storage/v1/
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
|
||||||
|
## Edge Functions routes
|
||||||
|
- name: functions-v1
|
||||||
|
_comment: 'Edge Functions: /functions/v1/* -> http://functions:9000/*'
|
||||||
|
url: http://functions:9000/
|
||||||
|
routes:
|
||||||
|
- name: functions-v1-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /functions/v1/
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
|
||||||
|
## Analytics routes
|
||||||
|
- name: analytics-v1
|
||||||
|
_comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*'
|
||||||
|
url: http://analytics:4000/
|
||||||
|
routes:
|
||||||
|
- name: analytics-v1-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /analytics/v1/
|
||||||
|
|
||||||
|
## Secure Database routes
|
||||||
|
- name: meta
|
||||||
|
_comment: 'pg-meta: /pg/* -> http://pg-meta:8080/*'
|
||||||
|
url: http://meta:8080/
|
||||||
|
routes:
|
||||||
|
- name: meta-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /pg/
|
||||||
|
plugins:
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: false
|
||||||
|
- name: acl
|
||||||
|
config:
|
||||||
|
hide_groups_header: true
|
||||||
|
allow:
|
||||||
|
- admin
|
||||||
|
|
||||||
|
## Block access to /api/mcp
|
||||||
|
- name: mcp-blocker
|
||||||
|
_comment: 'Block direct access to /api/mcp'
|
||||||
|
url: http://studio:3000/api/mcp
|
||||||
|
routes:
|
||||||
|
- name: mcp-blocker-route
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /api/mcp
|
||||||
|
plugins:
|
||||||
|
- name: request-termination
|
||||||
|
config:
|
||||||
|
status_code: 403
|
||||||
|
message: "Access is forbidden."
|
||||||
|
|
||||||
|
## MCP endpoint - local access
|
||||||
|
- name: mcp
|
||||||
|
_comment: 'MCP: /mcp -> http://studio:3000/api/mcp (local access)'
|
||||||
|
url: http://studio:3000/api/mcp
|
||||||
|
routes:
|
||||||
|
- name: mcp
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /mcp
|
||||||
|
plugins:
|
||||||
|
# Block access to /mcp by default
|
||||||
|
- name: request-termination
|
||||||
|
config:
|
||||||
|
status_code: 403
|
||||||
|
message: "Access is forbidden."
|
||||||
|
# Enable local access (danger zone!)
|
||||||
|
# 1. Comment out the 'request-termination' section above
|
||||||
|
# 2. Uncomment the entire section below, including 'deny'
|
||||||
|
# 3. Add your local IPs to the 'allow' list
|
||||||
|
#- name: cors
|
||||||
|
#- name: ip-restriction
|
||||||
|
# config:
|
||||||
|
# allow:
|
||||||
|
# - 127.0.0.1
|
||||||
|
# - ::1
|
||||||
|
# deny: []
|
||||||
|
|
||||||
|
## Protected Dashboard - catch all remaining routes
|
||||||
|
- name: dashboard
|
||||||
|
_comment: 'Studio: /* -> http://studio:3000/*'
|
||||||
|
url: http://studio:3000/
|
||||||
|
routes:
|
||||||
|
- name: dashboard-all
|
||||||
|
strip_path: true
|
||||||
|
paths:
|
||||||
|
- /
|
||||||
|
plugins:
|
||||||
|
- name: cors
|
||||||
|
- name: basic-auth
|
||||||
|
config:
|
||||||
|
hide_credentials: true
|
||||||
10
commands/secret.sh
Executable file
10
commands/secret.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
if [[ -f "secret" ]]; then
|
||||||
|
echo "Found a SECRET! Shhhhh..." >&2
|
||||||
|
SECRET=$(<secret)
|
||||||
|
else
|
||||||
|
echo "Creating New SECRET! Shhhhh..." >&2
|
||||||
|
openssl rand -hex 32 >./secret
|
||||||
|
SECRET=$(<secret)
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user