feat(deploy): add a one-command production deploy in shell
Production had no orchestrator at all and its provisioning script required PowerShell 7 on the server. up.sh now does the whole thing in POSIX shell: it refuses to start until .env.prod and the origin certificate are in place, generates the stream keys, brings up the infrastructure and the edge, provisions Zitadel, applies the migrations and finally builds and starts the applications. It is idempotent, so the same command deploys a new version. provision.sh replaces provision.prod.ps1 (curl + jq) and also creates the web player client, and migrate.prod.sh moves to scripts/migrate.sh reading the env file with a parser instead of sourcing it as a shell script.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# Shared helpers for the production deploy scripts.
|
||||
|
||||
step() { printf '\n==> %s\n' "$1"; }
|
||||
fail() { printf 'error: %s\n' "$1" >&2; exit 1; }
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || fail "$1 is required but not installed."
|
||||
}
|
||||
|
||||
# env_get <file> <key> — prints the value, empty if the key is absent.
|
||||
env_get() {
|
||||
grep -E "^$2=" "$1" 2>/dev/null | tail -n 1 | cut -d= -f2-
|
||||
}
|
||||
|
||||
# env_set <file> <key> <value> — replaces the key in place, appends if missing.
|
||||
env_set() {
|
||||
_file=$1; _key=$2; _value=$3
|
||||
_tmp=$(mktemp)
|
||||
if grep -qE "^$_key=" "$_file"; then
|
||||
awk -v k="$_key" -v v="$_value" '
|
||||
index($0, k "=") == 1 { print k "=" v; next }
|
||||
{ print }
|
||||
' "$_file" >"$_tmp"
|
||||
else
|
||||
cp "$_file" "$_tmp"
|
||||
printf '%s=%s\n' "$_key" "$_value" >>"$_tmp"
|
||||
fi
|
||||
cat "$_tmp" >"$_file"
|
||||
rm -f "$_tmp"
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Applies EF Core migrations to the prod Postgres, from a throwaway SDK
|
||||
# container attached to the compose network (postgres is not published to the host).
|
||||
set -eu
|
||||
|
||||
DEPLOY_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
||||
BACKEND_DIR="$(CDPATH= cd -- "$DEPLOY_DIR/../backend" && pwd)"
|
||||
ENV_FILE="$DEPLOY_DIR/.env.prod"
|
||||
|
||||
. "$ENV_FILE"
|
||||
|
||||
NETWORK="musify-prod_default"
|
||||
CONN="Host=postgres;Port=5432;Database=${POSTGRES_DB};Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}"
|
||||
|
||||
docker run --rm \
|
||||
--network "$NETWORK" \
|
||||
-v "$BACKEND_DIR":/src \
|
||||
-w /src/Musify.Infrastructure \
|
||||
mcr.microsoft.com/dotnet/sdk:10.0 \
|
||||
sh -c "dotnet tool install --global dotnet-ef >/dev/null 2>&1 || true; \
|
||||
export PATH=\$PATH:/root/.dotnet/tools; \
|
||||
dotnet restore Musify.Infrastructure.csproj; \
|
||||
dotnet user-secrets set 'Database:ConnectionString' '$CONN' >/dev/null; \
|
||||
dotnet ef database update --context Database"
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
# Applies the EF Core migrations to the production database from a throwaway SDK
|
||||
# container attached to the compose network (Postgres is not published to the host).
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
DEPLOY_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
BACKEND_DIR=$(CDPATH= cd -- "$DEPLOY_DIR/../backend" && pwd)
|
||||
ENV_FILE="$DEPLOY_DIR/.env.prod"
|
||||
NETWORK=${MUSIFY_NETWORK:-musify-prod_default}
|
||||
|
||||
. "$SCRIPT_DIR/lib.sh"
|
||||
|
||||
CONN="Host=postgres;Port=5432;Database=$(env_get "$ENV_FILE" POSTGRES_DB);Username=$(env_get "$ENV_FILE" POSTGRES_USER);Password=$(env_get "$ENV_FILE" POSTGRES_PASSWORD)"
|
||||
|
||||
# Musify.Infrastructure is both the migrations and the startup project: it owns
|
||||
# the IDesignTimeDbContextFactory and the EFCore.Design package.
|
||||
docker run --rm \
|
||||
--network "$NETWORK" \
|
||||
-v "$BACKEND_DIR":/src \
|
||||
-w /src/Musify.Infrastructure \
|
||||
-e CONN="$CONN" \
|
||||
mcr.microsoft.com/dotnet/sdk:10.0 \
|
||||
sh -c 'dotnet tool install --global dotnet-ef >/dev/null 2>&1 || true
|
||||
export PATH=$PATH:/root/.dotnet/tools
|
||||
dotnet restore Musify.Infrastructure.csproj
|
||||
dotnet user-secrets set "Database:ConnectionString" "$CONN" >/dev/null
|
||||
dotnet ef database update --context Database'
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
# Generates the RS256 key pair used to sign (API) and verify (Gateway) stream
|
||||
# tickets. No-op if both keys already exist.
|
||||
set -eu
|
||||
|
||||
KEYS_DIR=${1:?usage: stream-keys.sh <keys-dir>}
|
||||
PRIVATE_KEY="$KEYS_DIR/stream_private.pem"
|
||||
PUBLIC_KEY="$KEYS_DIR/stream_public.pem"
|
||||
|
||||
if [ -f "$PRIVATE_KEY" ] && [ -f "$PUBLIC_KEY" ]; then
|
||||
echo "Stream-ticket keys already present in $KEYS_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$KEYS_DIR"
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "$PRIVATE_KEY" 2>/dev/null
|
||||
openssl rsa -in "$PRIVATE_KEY" -pubout -out "$PUBLIC_KEY" 2>/dev/null
|
||||
chmod 644 "$PUBLIC_KEY"
|
||||
chmod 600 "$PRIVATE_KEY"
|
||||
|
||||
echo "Generated stream-ticket keys in $KEYS_DIR"
|
||||
Reference in New Issue
Block a user