Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ AUTH_JWT_ALGORITHM=HS256
DATABASE_MULTITENANT_URL=postgresql://postgres:postgres@127.0.0.1:5433/postgres
DATABASE_MULTITENANT_POOL_URL=postgresql://postgres:postgres@127.0.0.1:6454/postgres
REQUEST_X_FORWARDED_HOST_REGEXP=^([a-z]{20}).local.(?:com|dev)$
SERVER_ADMIN_API_KEYS=apikey
AUTH_ENCRYPTION_KEY=encryptionkey
SERVER_ADMIN_API_KEYS=this-value-should-be-changed-to-a-random-string
AUTH_ENCRYPTION_KEY=encryptionkey_Value:shouldBe_A_long_random_string


#######################################
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ A scalable, lightweight object storage service.
cp .env.sample .env && cp .env.test.sample .env.test
```

The script at `scripts/init.sh` can be used to help generate strong values for important keys such as `SERVER_ADMIN_API_KEYS`.

**Your root directory should now have both `.env` and `.env.test` files.**

- Then run the following:
Expand Down
6 changes: 4 additions & 2 deletions docker-compose-multi-tenant.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ services:
# Auth
AUTH_JWT_SECRET: f023d3db-39dc-4ac9-87b2-b2be72e9162b
AUTH_JWT_ALGORITHM: HS256
AUTH_ENCRYPTION_KEY: encryptionkey
# change this value to a unique, strong value
AUTH_ENCRYPTION_KEY: encryptionkey_Value:shouldBe_A_long_random_string
# Multi tenant Mode
MULTI_TENANT: true
DATABASE_MULTITENANT_URL: postgresql://postgres:postgres@multitenant_db:5432/postgres
SERVER_ADMIN_API_KEYS: apikey
# change this value to a strong API key
SERVER_ADMIN_API_KEYS: this-value-should-be-changed-to-a-random-string
SERVER_ADMIN_PORT: 5001
REQUEST_X_FORWARDED_HOST_REGEXP: "^([a-z]{20}).local.(?:com|dev)$"
# Migrations
Expand Down
108 changes: 108 additions & 0 deletions scripts/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env bash

# Help initialise self hosting to change environment variables
#
# Portions of this code are derived from Inder Singh's setup.sh shell script.
# Copyright 2025 Inder Singh. Licensed under Apache License 2.0.
# Original source: https://github.com/singh-inder/supabase-automated-self-host/blob/main/setup.sh
#

set -e

gen_hex() {
openssl rand -hex "$1"
}

gen_base64() {
openssl rand -base64 "$1"
}

base64_url_encode() {
openssl enc -base64 -A | tr '+/' '-_' | tr -d '='
}

prompt() {
local var=$1 msg=$2 default=$3
read -p "$msg [$default]: " value
printf -v "$var" '%s' "${value:-$default}"
}

promptYN() {
read -p "$1 y/N: " resp
resp=$(echo "$resp" | tr '[:upper:]' '[:lower:]')
[[ "$resp" == "y" ]] && echo true || echo false
}

if ! command -v openssl >/dev/null 2>&1; then
echo "Error: openssl is required but not found."
exit 1
fi

multitenant=$(promptYN "Use multitenant?")
if $multitenant; then
prompt SERVER_ADMIN_API_KEYS "Enter SERVER_ADMIN_API_KEYS" $(gen_hex 16)
prompt DATABASE_MULTITENANT_URL "Enter DATABASE_MULTITENANT_URL" ""
prompt DATABASE_MULTITENANT_POOL_URL "Enter DATABASE_MULTITENANT_POOL_URL" ""
fi

prompt AUTH_ENCRYPTION_KEY "Enter AUTH_ENCRYPTION_KEY" $(gen_hex 16)
prompt DATABASE_URL "Enter DATABASE_URL" ""
prompt DATABASE_POOL_URL "Enter DATABASE_URL" ""

updateEnv=$(promptYN "Create .env and update?")
if $updateEnv; then
echo "Updating .env..."
cp .env.sample .env
if $multitenant; then
sed -i.old \
-e "s|^# MULTI_TENANT=true$|MULTI_TENANT=true|" \
-e "s|^SERVER_ADMIN_API_KEYS=.*$|SERVER_ADMIN_API_KEYS=${SERVER_ADMIN_API_KEYS}|" \
.env

if [[ -n "$DATABASE_MULTITENANT_URL" ]]; then
sed -i.old \
-e "s|^DATABASE_MULTITENANT_URL=.*$|DATABASE_MULTITENANT_URL=${DATABASE_MULTITENANT_URL}|" \
.env
fi
if [[ -n "$DATABASE_MULTITENANT_POOL_URL" ]]; then
sed -i.old \
-e "s|^DATABASE_MULTITENANT_POOL_URL=.*$|DATABASE_MULTITENANT_POOL_URL=${DATABASE_MULTITENANT_POOL_URL}|" \
.env
fi
fi

sed -i.old \
-e "s|^AUTH_ENCRYPTION_KEY=.*$|AUTH_ENCRYPTION_KEY=${AUTH_ENCRYPTION_KEY}|" \
.env

if [[ -n "$DATABASE_URL" ]]; then
sed -i.old \
-e "s|^DATABASE_URL=.*$|DATABASE_URL=${DATABASE_URL}|" \
.env
fi
if [[ -n "$DATABASE_POOL_URL" ]]; then
sed -i.old \
-e "s|^DATABASE_POOL_URL=.*$|DATABASE_POOL_URL=${DATABASE_POOL_URL}|" \
.env
fi
fi

echo -e "\n\n#### Initialised values:\n"

if $multitenant; then
echo "SERVER_ADMIN_API_KEYS: ${SERVER_ADMIN_API_KEYS}"
if [[ -n "$DATABASE_MULTITENANT_URL" ]]; then
echo "DATABASE_MULTITENANT_URL: ${DATABASE_MULTITENANT_URL}"
fi
if [[ -n "$DATABASE_MULTITENANT_POOL_URL" ]]; then
echo "DATABASE_MULTITENANT_POOL_URL: ${DATABASE_MULTITENANT_POOL_URL}"
fi
fi

echo "AUTH_ENCRYPTION_KEY: ${AUTH_ENCRYPTION_KEY}"
if [[ -n "$DATABASE_URL" ]]; then
echo "DATABASE_URL: ${DATABASE_URL}"
fi
if [[ -n "$DATABASE_POOL_URL" ]]; then
echo "DATABASE_POOL_URL: ${DATABASE_POOL_URL}"
fi
28 changes: 18 additions & 10 deletions src/storage/events/pgboss/move-jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class MoveJobs extends BaseEvent<MoveJobsPayload> {

try {
const sql = `
INSERT INTO ${schema}.job (
INSERT INTO :schema:.job (
id,
name,
priority,
Expand All @@ -78,9 +78,9 @@ export class MoveJobs extends BaseEvent<MoveJobsPayload> {
policy,
state
)
SELECT
SELECT
id,
'${toQueue.name}' as name,
:to_queue_name as name,
priority,
data,
retry_limit,
Expand All @@ -94,23 +94,31 @@ export class MoveJobs extends BaseEvent<MoveJobsPayload> {
created_on,
keep_until,
output,
'${toQueue.policy}' as policy,
:to_queue_policy as policy,
'created' as state
FROM ${schema}.job
WHERE name = '${fromQueueName}'
FROM :schema:.job
WHERE name = :from_queue_name
AND state IN ('created', 'active', 'retry')
ON CONFLICT DO NOTHING
`

await tnx.raw(sql)
await tnx.raw(sql, {
schema: schema,
to_queue_name: toQueue.name,
to_queue_policy: toQueue.policy,
from_queue_name: fromQueueName
})

if (job.data.deleteJobsFromOriginalQueue) {
const deleteSql = `
DELETE FROM ${schema}.job
WHERE name = '${fromQueueName}'
DELETE FROM :schema:.job
WHERE name = :from_queue_name
AND state IN ('created', 'active', 'retry')
`
await tnx.raw(deleteSql)
await tnx.raw(deleteSql, {
schema: schema,
from_queue_name: fromQueueName
})
}
} catch (error) {
logSchema.error(logger, '[PgBoss] Error while copying jobs', {
Expand Down
Loading