chore: remove setup-railway-stack.sh script and update self-hosting documentation with PUBLIC_IS_SELFHOSTED variable
This commit is contained in:
@@ -190,6 +190,7 @@ BETTER_AUTH_SECRET="random-secure-key"
|
||||
AUTH_BEARER_TOKEN="some-key"
|
||||
AUTH_COOKIE_DOMAIN="yourdomain.com"
|
||||
PRIVATE_SERVER_KEY="same-key-for-api-and-dashboard"
|
||||
PUBLIC_IS_SELFHOSTED="true"
|
||||
|
||||
# Email (configure one)
|
||||
SMTP_HOST=
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
API_SERVICE_NAME="${API_SERVICE_NAME:-cio-api}"
|
||||
DASHBOARD_SERVICE_NAME="${DASHBOARD_SERVICE_NAME:-cio-dashboard}"
|
||||
POSTGRES_SERVICE_NAME="${POSTGRES_SERVICE_NAME:-Postgres}"
|
||||
REDIS_SERVICE_NAME="${REDIS_SERVICE_NAME:-Redis}"
|
||||
|
||||
BUCKET_REGION="${BUCKET_REGION:-iad}"
|
||||
BUCKET_PREFIX="${BUCKET_PREFIX:-classroomio}"
|
||||
VIDEOS_BUCKET_NAME="${VIDEOS_BUCKET_NAME:-${BUCKET_PREFIX}-videos}"
|
||||
DOCUMENTS_BUCKET_NAME="${DOCUMENTS_BUCKET_NAME:-${BUCKET_PREFIX}-documents}"
|
||||
MEDIA_BUCKET_NAME="${MEDIA_BUCKET_NAME:-${BUCKET_PREFIX}-media}"
|
||||
|
||||
require_command() {
|
||||
local command_name="$1"
|
||||
if ! command -v "${command_name}" >/dev/null 2>&1; then
|
||||
echo "Error: ${command_name} is required but not installed."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
json_has_name() {
|
||||
local json_payload="$1"
|
||||
local target_name="$2"
|
||||
|
||||
printf '%s' "${json_payload}" | jq -e --arg target "${target_name}" '
|
||||
[
|
||||
.. | objects | (
|
||||
.name? //
|
||||
.serviceName? //
|
||||
.service?.name? //
|
||||
empty
|
||||
)
|
||||
] | index($target) != null
|
||||
' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
service_exists() {
|
||||
local service_name="$1"
|
||||
local service_json
|
||||
|
||||
service_json="$(railway service status --all --json 2>/dev/null || true)"
|
||||
if [[ -z "${service_json}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
json_has_name "${service_json}" "${service_name}"
|
||||
}
|
||||
|
||||
bucket_exists() {
|
||||
local bucket_name="$1"
|
||||
local bucket_json
|
||||
|
||||
bucket_json="$(railway bucket list --json 2>/dev/null || true)"
|
||||
if [[ -z "${bucket_json}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
json_has_name "${bucket_json}" "${bucket_name}"
|
||||
}
|
||||
|
||||
ensure_database_service() {
|
||||
local database_kind="$1"
|
||||
local service_name="$2"
|
||||
local output
|
||||
|
||||
if service_exists "${service_name}"; then
|
||||
echo "Service '${service_name}' already exists."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Creating ${database_kind} service '${service_name}'..."
|
||||
if output="$(railway add --database "${database_kind}" --service "${service_name}" --json 2>&1)"; then
|
||||
echo "Created '${service_name}'."
|
||||
return
|
||||
fi
|
||||
|
||||
if service_exists "${service_name}"; then
|
||||
echo "Service '${service_name}' already exists (detected after create attempt)."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "${output}"
|
||||
echo "Error: failed to provision '${service_name}'."
|
||||
exit 1
|
||||
}
|
||||
|
||||
ensure_bucket() {
|
||||
local bucket_name="$1"
|
||||
local output
|
||||
|
||||
if bucket_exists "${bucket_name}"; then
|
||||
echo "Bucket '${bucket_name}' already exists."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Creating bucket '${bucket_name}' in region '${BUCKET_REGION}'..."
|
||||
if output="$(railway bucket create "${bucket_name}" --region "${BUCKET_REGION}" --json 2>&1)"; then
|
||||
echo "Created bucket '${bucket_name}'."
|
||||
return
|
||||
fi
|
||||
|
||||
if bucket_exists "${bucket_name}"; then
|
||||
echo "Bucket '${bucket_name}' already exists (detected after create attempt)."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "${output}"
|
||||
echo "Error: failed to create bucket '${bucket_name}'."
|
||||
exit 1
|
||||
}
|
||||
|
||||
ensure_application_service() {
|
||||
local service_name="$1"
|
||||
|
||||
if service_exists "${service_name}"; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Error: app service '${service_name}' was not found."
|
||||
echo "Create/link it first, then rerun this script:"
|
||||
echo " railway add --service \"${service_name}\""
|
||||
exit 1
|
||||
}
|
||||
|
||||
build_media_public_base_url() {
|
||||
local endpoint="$1"
|
||||
local bucket_name="$2"
|
||||
local force_path_style="$3"
|
||||
local url
|
||||
|
||||
url="${endpoint%/}"
|
||||
if [[ "${force_path_style}" == "true" ]]; then
|
||||
printf '%s/%s\n' "${url}" "${bucket_name}"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${url}" =~ ^(https?)://(.+)$ ]]; then
|
||||
printf '%s://%s.%s\n' "${BASH_REMATCH[1]}" "${bucket_name}" "${BASH_REMATCH[2]}"
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s/%s\n' "${url}" "${bucket_name}"
|
||||
}
|
||||
|
||||
require_command railway
|
||||
require_command jq
|
||||
|
||||
if ! railway status --json >/dev/null 2>&1; then
|
||||
echo "Error: no linked Railway project in this directory."
|
||||
echo "Run 'railway link --project <project-name-or-id>' and retry."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ensure_application_service "${API_SERVICE_NAME}"
|
||||
ensure_application_service "${DASHBOARD_SERVICE_NAME}"
|
||||
|
||||
ensure_database_service postgres "${POSTGRES_SERVICE_NAME}"
|
||||
ensure_database_service redis "${REDIS_SERVICE_NAME}"
|
||||
|
||||
ensure_bucket "${VIDEOS_BUCKET_NAME}"
|
||||
ensure_bucket "${DOCUMENTS_BUCKET_NAME}"
|
||||
ensure_bucket "${MEDIA_BUCKET_NAME}"
|
||||
|
||||
echo "Fetching credentials for bucket '${MEDIA_BUCKET_NAME}'..."
|
||||
MEDIA_BUCKET_CREDS_JSON="$(railway bucket credentials --bucket "${MEDIA_BUCKET_NAME}" --json)"
|
||||
|
||||
OBJECT_STORAGE_ENDPOINT="$(printf '%s' "${MEDIA_BUCKET_CREDS_JSON}" | jq -r '.endpoint // empty')"
|
||||
OBJECT_STORAGE_ACCESS_KEY_ID="$(printf '%s' "${MEDIA_BUCKET_CREDS_JSON}" | jq -r '.accessKeyId // empty')"
|
||||
OBJECT_STORAGE_SECRET_ACCESS_KEY="$(printf '%s' "${MEDIA_BUCKET_CREDS_JSON}" | jq -r '.secretAccessKey // empty')"
|
||||
OBJECT_STORAGE_REGION="${BUCKET_REGION}"
|
||||
OBJECT_STORAGE_URL_STYLE="$(printf '%s' "${MEDIA_BUCKET_CREDS_JSON}" | jq -r '(.urlStyle // "") | ascii_downcase')"
|
||||
|
||||
if [[ -z "${OBJECT_STORAGE_ENDPOINT}" || -z "${OBJECT_STORAGE_ACCESS_KEY_ID}" || -z "${OBJECT_STORAGE_SECRET_ACCESS_KEY}" ]]; then
|
||||
echo "Error: could not parse bucket credentials JSON."
|
||||
echo "Response:"
|
||||
echo "${MEDIA_BUCKET_CREDS_JSON}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OBJECT_STORAGE_FORCE_PATH_STYLE="false"
|
||||
if [[ "${OBJECT_STORAGE_URL_STYLE}" == *path* ]]; then
|
||||
OBJECT_STORAGE_FORCE_PATH_STYLE="true"
|
||||
fi
|
||||
|
||||
OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL="$(
|
||||
build_media_public_base_url "${OBJECT_STORAGE_ENDPOINT}" "${MEDIA_BUCKET_NAME}" "${OBJECT_STORAGE_FORCE_PATH_STYLE}"
|
||||
)"
|
||||
|
||||
POSTGRES_DATABASE_URL_REF="\${{${POSTGRES_SERVICE_NAME}.DATABASE_URL}}"
|
||||
REDIS_URL_REF="\${{${REDIS_SERVICE_NAME}.REDIS_URL}}"
|
||||
|
||||
echo "Setting API variables on '${API_SERVICE_NAME}'..."
|
||||
railway variable set --service "${API_SERVICE_NAME}" \
|
||||
"SERVICE_TARGET=api" \
|
||||
"PORT=3081" \
|
||||
"DATABASE_URL=${POSTGRES_DATABASE_URL_REF}" \
|
||||
"PRIVATE_DATABASE_URL=${POSTGRES_DATABASE_URL_REF}" \
|
||||
"REDIS_URL=${REDIS_URL_REF}" \
|
||||
"OBJECT_STORAGE_ENDPOINT=${OBJECT_STORAGE_ENDPOINT%/}" \
|
||||
"OBJECT_STORAGE_PUBLIC_ENDPOINT=${OBJECT_STORAGE_ENDPOINT%/}" \
|
||||
"OBJECT_STORAGE_ACCESS_KEY_ID=${OBJECT_STORAGE_ACCESS_KEY_ID}" \
|
||||
"OBJECT_STORAGE_SECRET_ACCESS_KEY=${OBJECT_STORAGE_SECRET_ACCESS_KEY}" \
|
||||
"OBJECT_STORAGE_REGION=${OBJECT_STORAGE_REGION}" \
|
||||
"OBJECT_STORAGE_FORCE_PATH_STYLE=${OBJECT_STORAGE_FORCE_PATH_STYLE}" \
|
||||
"OBJECT_STORAGE_BUCKET_VIDEOS=${VIDEOS_BUCKET_NAME}" \
|
||||
"OBJECT_STORAGE_BUCKET_DOCUMENTS=${DOCUMENTS_BUCKET_NAME}" \
|
||||
"OBJECT_STORAGE_BUCKET_MEDIA=${MEDIA_BUCKET_NAME}" \
|
||||
"OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL=${OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL}"
|
||||
|
||||
echo "Setting dashboard variables on '${DASHBOARD_SERVICE_NAME}'..."
|
||||
railway variable set --service "${DASHBOARD_SERVICE_NAME}" \
|
||||
"SERVICE_TARGET=dashboard" \
|
||||
"PORT=3082" \
|
||||
"PUBLIC_IS_SELFHOSTED=true"
|
||||
|
||||
echo
|
||||
echo "Railway infrastructure is provisioned and wired:"
|
||||
echo "- Postgres service: ${POSTGRES_SERVICE_NAME}"
|
||||
echo "- Redis service: ${REDIS_SERVICE_NAME}"
|
||||
echo "- Buckets: ${VIDEOS_BUCKET_NAME}, ${DOCUMENTS_BUCKET_NAME}, ${MEDIA_BUCKET_NAME}"
|
||||
echo "- API service updated: ${API_SERVICE_NAME}"
|
||||
echo "- Dashboard service updated: ${DASHBOARD_SERVICE_NAME}"
|
||||
echo
|
||||
echo "Next: set domain/auth/smtp variables, then deploy with:"
|
||||
echo " railway up --service \"${API_SERVICE_NAME}\" --detach -m \"deploy api\""
|
||||
echo " railway up --service \"${DASHBOARD_SERVICE_NAME}\" --detach -m \"deploy dashboard\""
|
||||
Reference in New Issue
Block a user