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
31 changes: 25 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@
# All defaults here work with `docker compose up` out of the box.
#
# Service ports (defaults):
# Postgres → localhost:5432
# Redis → localhost:6379
# Typesense → localhost:8108
# Adminer → localhost:8082 (DB browser UI)
# Postgres → localhost:5432
# Redis → localhost:6379
# Typesense → localhost:8108
# Adminer → localhost:8082 (DB browser UI)
# Keycloak → localhost:8180 (OAuth/OIDC testing)
# MinIO API → localhost:9000
# MinIO console → localhost:9001
# Prometheus → localhost:9090
#
# Note: If port 8082 conflicts, change the adminer port in docker-compose.yml
# Change host ports here; Docker Compose keeps the service ports inside the
# dev network unchanged.
# =============================================================================

# -----------------------------------------------------------------------------
# Database (Postgres 17)
# -----------------------------------------------------------------------------
# Keep DATABASE_URL aligned with PGHOST and PGPORT.
# Compose uses PGPORT as the published host port.
DATABASE_URL=postgres://buzz:buzz_dev@localhost:5432/buzz
# Optional read-replica URL; unset/blank keeps all reads on the writer.
# READ_DATABASE_URL=postgres://buzz:buzz_dev@localhost:5433/buzz
Expand All @@ -31,6 +38,8 @@ PGDATABASE=buzz
# Redis 7
# -----------------------------------------------------------------------------
REDIS_URL=redis://localhost:6379
# Host port published by Docker Compose. Keep it aligned with REDIS_URL.
REDIS_PORT=6379
# Max connections in the relay's shared Redis pool (default 16).
# BUZZ_REDIS_POOL_SIZE=16

Expand All @@ -44,6 +53,15 @@ REDIS_URL=redis://localhost:6379
TYPESENSE_API_KEY=buzz_dev_key
TYPESENSE_URL=http://localhost:8108

# -----------------------------------------------------------------------------
# Auxiliary local service ports
# -----------------------------------------------------------------------------
ADMINER_PORT=8082
KEYCLOAK_PORT=8180
MINIO_API_PORT=9000
MINIO_CONSOLE_PORT=9001
PROMETHEUS_PORT=9090

# -----------------------------------------------------------------------------
# Relay (WebSocket server)
# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -85,7 +103,8 @@ RELAY_URL=ws://localhost:3000
# -----------------------------------------------------------------------------
# S3-Compatible Object Storage (media + Git/CAS)
# -----------------------------------------------------------------------------
# The local MinIO container is reachable from host processes at localhost:9000.
# The local MinIO container is reachable from host processes at the port in
# MINIO_API_PORT. Keep BUZZ_S3_ENDPOINT aligned if that port changes.
# Path style keeps the bucket in the URL path and is required by this local DNS
# setup. Use `virtual` only when the provider requires bucket-as-subdomain URLs.
BUZZ_S3_ENDPOINT=http://localhost:9000
Expand Down
8 changes: 6 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,12 @@ it is safe to re-run.

`just setup` then starts Docker services (Postgres on `:5432`, Redis on `:6379`,
Adminer on `:8082`, Keycloak on `:8180` for local OAuth/OIDC testing, MinIO on
`:9000` for media storage, and Prometheus on `:9090` for metrics) and runs all
pending database migrations.
`:9000`/`:9001` for media storage and its console, and Prometheus on `:9090` for
metrics) and runs all pending database migrations. These are host-port defaults;
override `PGPORT`, `REDIS_PORT`, `ADMINER_PORT`, `KEYCLOAK_PORT`,
`MINIO_API_PORT`, `MINIO_CONSOLE_PORT`, or `PROMETHEUS_PORT` in `.env` when a
port is already occupied. Keep `DATABASE_URL`, `REDIS_URL`, and
`BUZZ_S3_ENDPOINT` aligned with their corresponding host-port overrides.

### Running the Relay and Desktop App

Expand Down
16 changes: 7 additions & 9 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,8 @@ _ensure-sidecar-stubs:
_ensure-services:
#!/usr/bin/env bash
set -euo pipefail
pg=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' buzz-postgres 2>/dev/null || echo "not_found")
redis=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' buzz-redis 2>/dev/null || echo "not_found")
if [[ "$pg" == "healthy" && "$redis" == "healthy" ]]; then
echo "Services already healthy"
exit 0
fi
echo "Starting services..."
docker compose up -d || true
echo "Starting or reconciling services..."
docker compose up -d
echo -n "Waiting for services"
for i in $(seq 1 40); do
pg=$(docker inspect --format '{{"{{"}}.State.Health.Status{{"}}"}}' buzz-postgres 2>/dev/null || echo "not_found")
Expand Down Expand Up @@ -286,10 +280,14 @@ desktop-e2e-pre-push: _ensure-migrations
cd {{desktop_dir}} && pnpm build:e2e && pnpm exec playwright test --only-changed=origin/main

# Run all checks suitable for CI / pre-push (no infra needed)
ci: check test-unit desktop-test desktop-build desktop-tauri-check desktop-tauri-test web-build mobile-test
ci: check test-dev-service-ports test-unit desktop-test desktop-build desktop-tauri-check desktop-tauri-test web-build mobile-test

# ─── Test ─────────────────────────────────────────────────────────────────────

# Verify default/custom host-port mappings and service reconciliation behavior
test-dev-service-ports:
./scripts/test-dev-service-ports.sh

# Run all tests (unit + integration)
test:
./scripts/run-tests.sh all
Expand Down
16 changes: 11 additions & 5 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ just setup # start Docker services, run migrations

> **Already running Buzz Desktop?** Desktop uses the same Docker container
> names (`buzz-postgres`, `buzz-redis`) and the same
> default ports (`:5432`, `:6379`). `just setup` will reuse those
> services, so **your test relay writes into Desktop's database**. That's
> fine for read/write smoke tests, but: `just reset` wipes Desktop's data
> along with yours. If you need isolation, stop Desktop first or run the
> dev stack on a different Compose project
> default ports (`:5432`, `:6379`). Host ports can be overridden in `.env`;
> keep `DATABASE_URL`/`PGPORT` and `REDIS_URL`/`REDIS_PORT` aligned. Changing
> an override reconciles the shared Compose stack, so a running Desktop or
> relay using the old ports will lose its service connections. `just setup`
> will reuse those services, so **your test relay writes into Desktop's
> database**. That's fine for read/write smoke tests, but: `just reset` wipes
> Desktop's data along with yours. If you need isolation, stop Desktop first
> or run the dev stack on a different Compose project
> (`COMPOSE_PROJECT_NAME=buzz-dev docker compose …`).

`just reset` wipes all local data and starts over — **including Buzz
Expand Down Expand Up @@ -314,7 +317,10 @@ out of the box with `just setup` or `just relay`. Common overrides:
| `BUZZ_METRICS_PORT` | `9102` | Prometheus `/metrics` |
| `RELAY_URL` | `ws://localhost:3000` | Advertised in NIP-11 / NIP-42 challenges. **Note: no `BUZZ_` prefix.** |
| `DATABASE_URL` | `postgres://buzz:buzz_dev@localhost:5432/buzz` | |
| `PGPORT` | `5432` | Postgres host port published by the root dev Compose stack; keep aligned with `DATABASE_URL` |
| `REDIS_URL` | `redis://localhost:6379` | |
| `REDIS_PORT` | `6379` | Redis host port published by the root dev Compose stack; keep aligned with `REDIS_URL` |
| `MINIO_API_PORT` | `9000` | MinIO API host port; keep aligned with `BUZZ_S3_ENDPOINT` |
| `BUZZ_REQUIRE_AUTH_TOKEN` | `false` | When true, REST requires NIP-98 (no `X-Pubkey` fallback) |
| `BUZZ_REQUIRE_RELAY_MEMBERSHIP` | `false` | When true, only pubkeys in `relay_members` can connect |
| `BUZZ_DRAIN_JITTER_MS` | `0` (off) | Per-connection upper bound, in ms, for the random delay before each live WebSocket gets its `1012 Service Restart` close on graceful shutdown. `0` closes every socket at once (the previous behavior). A positive value spreads closes uniformly over `[1, value]` ms to avoid a reconnect thundering herd on rolling deploys. Values above `20000` are capped to `20000` (`MAX_DRAIN_JITTER_MS`) to leave close-frame delivery headroom under the relay's 30s hard-drain timeout. Empty or whitespace-only is treated as unset (off); a non-integer fails startup loudly. |
Expand Down
14 changes: 7 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ services:
POSTGRES_DB: buzz
PGDATA: /var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432"
- "127.0.0.1:${PGPORT:-5432}:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
Expand All @@ -34,7 +34,7 @@ services:
image: redis:7-alpine
container_name: buzz-redis
ports:
- "127.0.0.1:6379:6379"
- "127.0.0.1:${REDIS_PORT:-6379}:6379"
networks:
- buzz-net
healthcheck:
Expand All @@ -56,7 +56,7 @@ services:
image: adminer:latest
container_name: buzz-adminer
ports:
- "127.0.0.1:8082:8080"
- "127.0.0.1:${ADMINER_PORT:-8082}:8080"
networks:
- buzz-net
depends_on:
Expand All @@ -82,7 +82,7 @@ services:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
ports:
- "127.0.0.1:8180:8080"
- "127.0.0.1:${KEYCLOAK_PORT:-8180}:8080"
networks:
- buzz-net
healthcheck:
Expand All @@ -108,8 +108,8 @@ services:
MINIO_ROOT_USER: buzz_dev
MINIO_ROOT_PASSWORD: buzz_dev_secret
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9001:9001"
- "127.0.0.1:${MINIO_API_PORT:-9000}:9000"
- "127.0.0.1:${MINIO_CONSOLE_PORT:-9001}:9001"
volumes:
- minio-data:/data
networks:
Expand Down Expand Up @@ -152,7 +152,7 @@ services:
image: prom/prometheus:latest
container_name: buzz-prometheus
ports:
- "127.0.0.1:9090:9090"
- "127.0.0.1:${PROMETHEUS_PORT:-9090}:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
Expand Down
30 changes: 22 additions & 8 deletions scripts/dev-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

# `just setup` runs `bootstrap` in a separate recipe. Keep this script
# self-contained when it validates URLs with the Hermit-provided node shim.
export PATH="${REPO_ROOT}/bin:${PATH}"

# shellcheck disable=SC1091
source "${SCRIPT_DIR}/lib/dev-service-env.sh"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
Expand Down Expand Up @@ -67,6 +74,15 @@ load_env() {
export PGPASSWORD="${PGPASSWORD:-buzz_dev}"
export PGDATABASE="${PGDATABASE:-buzz}"
export REDIS_URL="${REDIS_URL:-redis://localhost:6379}"
export REDIS_PORT="${REDIS_PORT:-6379}"
export MINIO_API_PORT="${MINIO_API_PORT:-9000}"
export BUZZ_S3_ENDPOINT="${BUZZ_S3_ENDPOINT:-http://localhost:9000}"
}

validate_env() {
validate_local_service_port "DATABASE_URL" "${DATABASE_URL}" "${PGPORT}" "5432"
validate_local_service_port "REDIS_URL" "${REDIS_URL}" "${REDIS_PORT}" "6379"
validate_local_service_port "BUZZ_S3_ENDPOINT" "${BUZZ_S3_ENDPOINT}" "${MINIO_API_PORT}" "80"
}

cleanup_legacy_sprout_containers() {
Expand All @@ -76,7 +92,7 @@ cleanup_legacy_sprout_containers() {
return
fi

warn "Stopping/removing legacy sprout-* dev containers so buzz-* containers can bind the standard ports"
warn "Stopping/removing legacy sprout-* dev containers so buzz-* containers can bind the configured ports"
echo "${legacy_containers}" | xargs docker stop >/dev/null 2>&1 || true
echo "${legacy_containers}" | xargs docker rm >/dev/null 2>&1 || true
success "Legacy sprout-* containers removed (volumes preserved)"
Expand All @@ -86,14 +102,11 @@ fail_if_local_redis_blocks_compose() {
if ! command -v lsof >/dev/null 2>&1; then
return
fi
if docker ps --format '{{.Names}}' | grep -qx 'buzz-redis'; then
return
fi
local redis_pids
redis_pids=$(lsof -nP -iTCP:6379 -sTCP:LISTEN 2>/dev/null | awk 'NR > 1 && $1 == "redis-ser" {print $2}' | sort -u | tr '
redis_pids=$(lsof -nP -iTCP:"${REDIS_PORT}" -sTCP:LISTEN 2>/dev/null | awk 'NR > 1 && $1 == "redis-ser" {print $2}' | sort -u | tr '
' ' ' || true)
if [[ -n "${redis_pids}" ]]; then
error "Local Redis is already listening on port 6379 (pid(s): ${redis_pids}). Stop it before running setup: brew services stop redis"
error "Local Redis is already listening on port ${REDIS_PORT} (pid(s): ${redis_pids}). Stop it before running setup: brew services stop redis"
exit 1
fi
}
Expand All @@ -105,6 +118,7 @@ postgres_accepting_connections() {
}

load_env
validate_env
cleanup_legacy_sprout_containers
fail_if_local_redis_blocks_compose

Expand Down Expand Up @@ -187,8 +201,8 @@ echo -e "${GREEN}=======================================================${NC}"
echo ""
echo -e " ${BLUE}Postgres${NC} ${DATABASE_URL}"
echo -e " ${BLUE}Redis${NC} ${REDIS_URL}"
echo -e " ${BLUE}Adminer${NC} http://localhost:8082 (DB browser)"
echo -e " ${BLUE}Keycloak${NC} http://localhost:8180 (admin / admin — local OAuth testing)"
echo -e " ${BLUE}Adminer${NC} http://localhost:${ADMINER_PORT:-8082} (DB browser)"
echo -e " ${BLUE}Keycloak${NC} http://localhost:${KEYCLOAK_PORT:-8180} (admin / admin — local OAuth testing)"
echo ""
echo -e " ${YELLOW}Next steps:${NC}"
echo -e " just relay # start the relay (terminal 1)"
Expand Down
Loading
Loading