add deploy script, fix production paths, use port 3006
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
DATABASE_URL=postgresql://localhost:5433/celebrate_esc
|
DATABASE_URL=postgresql://localhost:5433/celebrate_esc
|
||||||
PORT=3001
|
PORT=3006
|
||||||
|
|||||||
113
deploy.sh
Executable file
113
deploy.sh
Executable file
@@ -0,0 +1,113 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# celebrate-esc deploy script — idempotent, can be re-run safely
|
||||||
|
# Target: Uberspace 8 (serve.uber.space)
|
||||||
|
|
||||||
|
HOST="serve"
|
||||||
|
SERVICE_DIR="services/celebrate-esc"
|
||||||
|
STATIC_DIR="/var/www/virtual/serve/html/celebrate-esc"
|
||||||
|
DB_NAME="celebrate_esc"
|
||||||
|
PORT=3006
|
||||||
|
|
||||||
|
echo "=== celebrate-esc deploy ==="
|
||||||
|
|
||||||
|
# ── 1. Create database if needed ─────────────────────────────────────
|
||||||
|
echo "→ ensuring database exists..."
|
||||||
|
ssh "$HOST" "createdb -h localhost -p 5433 $DB_NAME 2>/dev/null || true"
|
||||||
|
|
||||||
|
# ── 2. Build client locally ──────────────────────────────────────────
|
||||||
|
echo "→ building client..."
|
||||||
|
cd packages/client
|
||||||
|
VITE_BASE="/celebrate-esc/" bun run build
|
||||||
|
cd ../..
|
||||||
|
|
||||||
|
# ── 3. Sync server code ─────────────────────────────────────────────
|
||||||
|
echo "→ syncing server to $HOST:~/$SERVICE_DIR/..."
|
||||||
|
ssh "$HOST" "mkdir -p ~/$SERVICE_DIR"
|
||||||
|
rsync -az --delete \
|
||||||
|
--exclude='node_modules' \
|
||||||
|
--exclude='.env' \
|
||||||
|
packages/server/ "$HOST:~/$SERVICE_DIR/server/"
|
||||||
|
rsync -az --delete \
|
||||||
|
--exclude='node_modules' \
|
||||||
|
packages/shared/ "$HOST:~/$SERVICE_DIR/shared/"
|
||||||
|
|
||||||
|
# Copy root workspace files needed for bun install
|
||||||
|
scp package.json "$HOST:~/$SERVICE_DIR/"
|
||||||
|
scp tsconfig.json "$HOST:~/$SERVICE_DIR/"
|
||||||
|
scp bun.lock "$HOST:~/$SERVICE_DIR/"
|
||||||
|
|
||||||
|
# ── 4. Install server dependencies on remote ─────────────────────────
|
||||||
|
echo "→ installing server dependencies..."
|
||||||
|
ssh "$HOST" "cd ~/$SERVICE_DIR && cat > package.json << 'PKGJSON'
|
||||||
|
{
|
||||||
|
\"name\": \"celebrate-esc\",
|
||||||
|
\"private\": true,
|
||||||
|
\"workspaces\": [
|
||||||
|
\"shared\",
|
||||||
|
\"server\"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PKGJSON
|
||||||
|
bun install --frozen-lockfile 2>/dev/null || bun install"
|
||||||
|
|
||||||
|
# ── 5. Create .env on remote if missing ──────────────────────────────
|
||||||
|
echo "→ ensuring .env exists..."
|
||||||
|
ssh "$HOST" "test -f ~/$SERVICE_DIR/.env || cat > ~/$SERVICE_DIR/.env << 'ENVFILE'
|
||||||
|
DATABASE_URL=postgresql://localhost:5433/$DB_NAME
|
||||||
|
PORT=$PORT
|
||||||
|
ENVFILE"
|
||||||
|
|
||||||
|
# ── 6. Run migrations ────────────────────────────────────────────────
|
||||||
|
echo "→ running database migrations..."
|
||||||
|
ssh "$HOST" "cd ~/$SERVICE_DIR/server && DATABASE_URL=postgresql://localhost:5433/$DB_NAME bun drizzle-kit migrate"
|
||||||
|
|
||||||
|
# ── 7. Deploy static client files ────────────────────────────────────
|
||||||
|
echo "→ deploying client static files..."
|
||||||
|
ssh "$HOST" "mkdir -p $STATIC_DIR"
|
||||||
|
rsync -az --delete packages/client/dist/ "$HOST:$STATIC_DIR/"
|
||||||
|
|
||||||
|
# Create .htaccess for SPA routing
|
||||||
|
ssh "$HOST" "cat > $STATIC_DIR/.htaccess << 'HTACCESS'
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteBase /celebrate-esc/
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule . index.html [L]
|
||||||
|
HTACCESS"
|
||||||
|
|
||||||
|
# ── 8. Create systemd service ────────────────────────────────────────
|
||||||
|
echo "→ setting up systemd service..."
|
||||||
|
ssh "$HOST" "cat > ~/.config/systemd/user/celebrate-esc.service << 'UNIT'
|
||||||
|
[Unit]
|
||||||
|
Description=celebrate-esc API server
|
||||||
|
After=postgresql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=%h/services/celebrate-esc/server
|
||||||
|
ExecStart=/home/serve/.local/share/mise/installs/bun/1.3.0/bin/bun run --env-file=../.env src/index.ts
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
UNIT
|
||||||
|
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable celebrate-esc.service
|
||||||
|
systemctl --user restart celebrate-esc.service"
|
||||||
|
|
||||||
|
# ── 9. Set up web backend routing ────────────────────────────────────
|
||||||
|
echo "→ configuring web backend routing..."
|
||||||
|
ssh "$HOST" "uberspace web backend set /celebrate-esc/api --http --port $PORT --remove-prefix 2>/dev/null || true"
|
||||||
|
|
||||||
|
# ── 10. Verify ────────────────────────────────────────────────────────
|
||||||
|
echo "→ verifying deployment..."
|
||||||
|
sleep 2
|
||||||
|
ssh "$HOST" "systemctl --user status celebrate-esc.service --no-pager | head -5"
|
||||||
|
echo ""
|
||||||
|
echo "=== deploy complete ==="
|
||||||
|
echo "Frontend: https://serve.uber.space/celebrate-esc/"
|
||||||
|
echo "API: https://serve.uber.space/celebrate-esc/api/health"
|
||||||
@@ -41,9 +41,10 @@ export function useWebSocket(roomCode: string) {
|
|||||||
const sessionId = stored?.roomCode === roomCode ? stored.sessionId : null
|
const sessionId = stored?.roomCode === roomCode ? stored.sessionId : null
|
||||||
|
|
||||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"
|
||||||
|
const base = import.meta.env.BASE_URL.replace(/\/$/, "")
|
||||||
const wsUrl = sessionId
|
const wsUrl = sessionId
|
||||||
? `${protocol}//${window.location.host}/api/ws/${roomCode}?sessionId=${sessionId}`
|
? `${protocol}//${window.location.host}${base}/api/ws/${roomCode}?sessionId=${sessionId}`
|
||||||
: `${protocol}//${window.location.host}/api/ws/${roomCode}`
|
: `${protocol}//${window.location.host}${base}/api/ws/${roomCode}`
|
||||||
|
|
||||||
setConnectionStatus("connecting")
|
setConnectionStatus("connecting")
|
||||||
const ws = new WebSocket(wsUrl)
|
const ws = new WebSocket(wsUrl)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function CreateRoomCard() {
|
|||||||
setError("")
|
setError("")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/rooms", {
|
const res = await fetch(`${import.meta.env.BASE_URL}api/rooms`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ displayName: displayName.trim() }),
|
body: JSON.stringify({ displayName: displayName.trim() }),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import react from "@vitejs/plugin-react"
|
|||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
base: process.env.VITE_BASE ?? "/",
|
||||||
plugins: [TanStackRouterVite(), react(), tailwindcss()],
|
plugins: [TanStackRouterVite(), react(), tailwindcss()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@@ -14,8 +15,9 @@ export default defineConfig({
|
|||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api": {
|
"/api": {
|
||||||
target: "http://localhost:3001",
|
target: "http://localhost:3006",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||||
ws: true,
|
ws: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
const envSchema = z.object({
|
const envSchema = z.object({
|
||||||
DATABASE_URL: z.string().url(),
|
DATABASE_URL: z.string().url(),
|
||||||
PORT: z.coerce.number().default(3001),
|
PORT: z.coerce.number().default(3006),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const env = envSchema.parse(process.env)
|
export const env = envSchema.parse(process.env)
|
||||||
|
|||||||
Reference in New Issue
Block a user