11 changed files with 652 additions and 8 deletions
@ -0,0 +1,74 @@ |
|||||||
|
# Multi-stage Dockerfile for ORLY relay with embedded web UI |
||||||
|
|
||||||
|
# Stage 1: Web UI build |
||||||
|
FROM node:20-bookworm AS web-builder |
||||||
|
|
||||||
|
WORKDIR /web |
||||||
|
|
||||||
|
# Copy web UI files |
||||||
|
COPY app/web/package.json app/web/package-lock.json* app/web/ ./ |
||||||
|
|
||||||
|
# Install dependencies and build |
||||||
|
RUN npm ci && npm run build |
||||||
|
|
||||||
|
# Stage 2: Go build stage |
||||||
|
FROM golang:1.25-bookworm AS builder |
||||||
|
|
||||||
|
# Install build dependencies |
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends git make && rm -rf /var/lib/apt/lists/* |
||||||
|
|
||||||
|
# Set working directory |
||||||
|
WORKDIR /build |
||||||
|
|
||||||
|
# Copy go mod files |
||||||
|
COPY go.mod go.sum ./ |
||||||
|
RUN go mod download |
||||||
|
|
||||||
|
# Copy source code |
||||||
|
COPY . . |
||||||
|
|
||||||
|
# Copy built web UI from web-builder stage |
||||||
|
COPY --from=web-builder /web/dist ./app/web/dist |
||||||
|
|
||||||
|
# Build the binary with CGO disabled |
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o orly -ldflags="-w -s" . |
||||||
|
|
||||||
|
# Stage 3: Runtime stage |
||||||
|
FROM debian:bookworm-slim |
||||||
|
|
||||||
|
# Install runtime dependencies |
||||||
|
RUN apt-get update && \ |
||||||
|
apt-get install -y --no-install-recommends ca-certificates curl libsecp256k1-1 && \ |
||||||
|
rm -rf /var/lib/apt/lists/* |
||||||
|
|
||||||
|
# Create app user |
||||||
|
RUN groupadd -g 1000 orly && \ |
||||||
|
useradd -m -u 1000 -g orly orly |
||||||
|
|
||||||
|
# Set working directory |
||||||
|
WORKDIR /app |
||||||
|
|
||||||
|
# Copy binary (libsecp256k1.so.1 is already installed via apt) |
||||||
|
COPY --from=builder /build/orly /app/orly |
||||||
|
|
||||||
|
# Create data directory |
||||||
|
RUN mkdir -p /data && chown -R orly:orly /data /app |
||||||
|
|
||||||
|
# Switch to app user |
||||||
|
USER orly |
||||||
|
|
||||||
|
# Expose ports |
||||||
|
EXPOSE 3334 |
||||||
|
|
||||||
|
# Health check |
||||||
|
HEALTHCHECK --interval=10s --timeout=5s --start-period=20s --retries=3 \ |
||||||
|
CMD curl -f http://localhost:3334/ || exit 1 |
||||||
|
|
||||||
|
# Set default environment variables |
||||||
|
ENV ORLY_LISTEN=0.0.0.0 \ |
||||||
|
ORLY_PORT=3334 \ |
||||||
|
ORLY_DATA_DIR=/data \ |
||||||
|
ORLY_LOG_LEVEL=info |
||||||
|
|
||||||
|
# Run the binary |
||||||
|
ENTRYPOINT ["/app/orly"] |
||||||
@ -0,0 +1,129 @@ |
|||||||
|
# Running ORLY Relay Remotely |
||||||
|
|
||||||
|
## Quick Start |
||||||
|
|
||||||
|
### 1. Pull the Image |
||||||
|
```bash |
||||||
|
docker pull silberengel/next-orly:v0.58.5 |
||||||
|
``` |
||||||
|
|
||||||
|
### 2. Run with Docker Run |
||||||
|
```bash |
||||||
|
docker run -d \ |
||||||
|
--name orly-relay \ |
||||||
|
--restart always \ |
||||||
|
-p 3334:3334 \ |
||||||
|
-v /var/lib/orly:/data \ |
||||||
|
-e ORLY_DATA_DIR=/data \ |
||||||
|
-e ORLY_LISTEN=0.0.0.0 \ |
||||||
|
-e ORLY_PORT=3334 \ |
||||||
|
-e ORLY_LOG_LEVEL=info \ |
||||||
|
silberengel/next-orly:v0.58.5 |
||||||
|
``` |
||||||
|
|
||||||
|
### 3. Or Use Docker Compose |
||||||
|
|
||||||
|
Create a `docker-compose.yml`: |
||||||
|
```yaml |
||||||
|
version: '3.8' |
||||||
|
|
||||||
|
services: |
||||||
|
orly-relay: |
||||||
|
image: silberengel/next-orly:v0.58.5 |
||||||
|
container_name: orly-relay |
||||||
|
restart: always |
||||||
|
ports: |
||||||
|
- "3334:3334" |
||||||
|
volumes: |
||||||
|
- /var/lib/orly:/data |
||||||
|
environment: |
||||||
|
- ORLY_DATA_DIR=/data |
||||||
|
- ORLY_LISTEN=0.0.0.0 |
||||||
|
- ORLY_PORT=3334 |
||||||
|
- ORLY_LOG_LEVEL=info |
||||||
|
``` |
||||||
|
|
||||||
|
Then run: |
||||||
|
```bash |
||||||
|
docker-compose up -d |
||||||
|
``` |
||||||
|
|
||||||
|
## Configuration Options |
||||||
|
|
||||||
|
### Basic Configuration |
||||||
|
- `ORLY_DATA_DIR` - Data directory (default: `/data`) |
||||||
|
- `ORLY_LISTEN` - Listen address (default: `0.0.0.0`) |
||||||
|
- `ORLY_PORT` - Port number (default: `3334`) |
||||||
|
- `ORLY_LOG_LEVEL` - Log level: `debug`, `info`, `warn`, `error` |
||||||
|
|
||||||
|
### Advanced Configuration |
||||||
|
- `ORLY_ADMINS` - Comma-separated list of admin npub keys |
||||||
|
- `ORLY_OWNERS` - Comma-separated list of owner npub keys |
||||||
|
- `ORLY_ACL_MODE` - ACL mode: `open`, `follows`, `managed` |
||||||
|
- `ORLY_SPIDER_MODE` - Spider mode: `off`, `follows`, `all` |
||||||
|
- `ORLY_RELAY_URL` - Public relay URL (for metadata) |
||||||
|
- `ORLY_MAX_CONNECTIONS` - Max concurrent connections (default: 1000) |
||||||
|
- `ORLY_MAX_EVENT_SIZE` - Max event size in bytes (default: 65536) |
||||||
|
|
||||||
|
## Useful Commands |
||||||
|
|
||||||
|
### View Logs |
||||||
|
```bash |
||||||
|
docker logs -f orly-relay |
||||||
|
``` |
||||||
|
|
||||||
|
### Stop Container |
||||||
|
```bash |
||||||
|
docker stop orly-relay |
||||||
|
``` |
||||||
|
|
||||||
|
### Start Container |
||||||
|
```bash |
||||||
|
docker start orly-relay |
||||||
|
``` |
||||||
|
|
||||||
|
### Restart Container |
||||||
|
```bash |
||||||
|
docker restart orly-relay |
||||||
|
``` |
||||||
|
|
||||||
|
### Remove Container |
||||||
|
```bash |
||||||
|
docker rm -f orly-relay |
||||||
|
``` |
||||||
|
|
||||||
|
### Update to Latest Version |
||||||
|
```bash |
||||||
|
docker pull silberengel/next-orly:v0.58.5 |
||||||
|
docker stop orly-relay |
||||||
|
docker rm orly-relay |
||||||
|
# Then run your docker run or docker-compose command again |
||||||
|
``` |
||||||
|
|
||||||
|
## Behind a Reverse Proxy |
||||||
|
|
||||||
|
If running behind nginx/Caddy/etc, bind to localhost only: |
||||||
|
```bash |
||||||
|
docker run -d \ |
||||||
|
--name orly-relay \ |
||||||
|
--restart always \ |
||||||
|
-p 127.0.0.1:3334:3334 \ |
||||||
|
-v /var/lib/orly:/data \ |
||||||
|
-e ORLY_DATA_DIR=/data \ |
||||||
|
-e ORLY_LISTEN=0.0.0.0 \ |
||||||
|
-e ORLY_PORT=3334 \ |
||||||
|
silberengel/next-orly:v0.58.5 |
||||||
|
``` |
||||||
|
|
||||||
|
## Data Persistence |
||||||
|
|
||||||
|
Data is stored in `/var/lib/orly` on the host (or whatever path you mount). |
||||||
|
To backup: |
||||||
|
```bash |
||||||
|
tar -czf orly-backup-$(date +%Y%m%d).tar.gz /var/lib/orly |
||||||
|
``` |
||||||
|
|
||||||
|
To restore: |
||||||
|
```bash |
||||||
|
tar -xzf orly-backup-YYYYMMDD.tar.gz -C / |
||||||
|
``` |
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,61 @@ |
|||||||
|
#!/bin/bash |
||||||
|
# Build script for next-orly v0.48.10 Docker image |
||||||
|
|
||||||
|
set -e |
||||||
|
|
||||||
|
# Check for Docker |
||||||
|
DOCKER_CMD="" |
||||||
|
if command -v docker >/dev/null 2>&1; then |
||||||
|
DOCKER_CMD="docker" |
||||||
|
elif command -v podman >/dev/null 2>&1; then |
||||||
|
DOCKER_CMD="podman" |
||||||
|
elif command -v docker.io >/dev/null 2>&1; then |
||||||
|
DOCKER_CMD="docker.io" |
||||||
|
else |
||||||
|
echo "Error: Docker is not installed or not in PATH." |
||||||
|
echo "" |
||||||
|
echo "To install Docker on Ubuntu/Debian:" |
||||||
|
echo " sudo apt install docker.io" |
||||||
|
echo " sudo systemctl enable --now docker" |
||||||
|
echo " sudo usermod -aG docker $USER" |
||||||
|
echo " # Then log out and back in" |
||||||
|
echo "" |
||||||
|
echo "Or install Podman (Docker alternative):" |
||||||
|
echo " sudo apt install podman" |
||||||
|
echo "" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
# Check if we're on the correct tag |
||||||
|
CURRENT_TAG=$(git describe --tags --exact-match HEAD 2>/dev/null || echo "") |
||||||
|
if [ "$CURRENT_TAG" != "v0.48.10" ]; then |
||||||
|
echo "Checking out v0.48.10..." |
||||||
|
git checkout v0.48.10 |
||||||
|
fi |
||||||
|
|
||||||
|
# Check if app/web/dist exists (web UI already built) |
||||||
|
if [ -d "app/web/dist" ]; then |
||||||
|
echo "Web UI already built, using existing Dockerfile..." |
||||||
|
DOCKERFILE="Dockerfile" |
||||||
|
else |
||||||
|
echo "Web UI not found, using Dockerfile.with-web (will build web UI in Docker)..." |
||||||
|
DOCKERFILE="Dockerfile.with-web" |
||||||
|
fi |
||||||
|
|
||||||
|
# Build the Docker image with both version and latest tags |
||||||
|
echo "Building Docker image silberengel/next-orly:v0.48.10 using $DOCKER_CMD..." |
||||||
|
$DOCKER_CMD build -t silberengel/next-orly:v0.48.10 -t silberengel/next-orly:latest -f "$DOCKERFILE" . |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "Build complete! Image tags:" |
||||||
|
echo " - silberengel/next-orly:v0.48.10" |
||||||
|
echo " - silberengel/next-orly:latest" |
||||||
|
echo "" |
||||||
|
echo "To push to Docker Hub:" |
||||||
|
echo " $DOCKER_CMD push silberengel/next-orly:v0.48.10" |
||||||
|
echo " $DOCKER_CMD push silberengel/next-orly:latest" |
||||||
|
echo "" |
||||||
|
echo "To run with Docker Compose:" |
||||||
|
echo " docker compose -f docker-compose-orly.yml up -d" |
||||||
|
echo " docker compose -f docker-compose-orly.yml logs -f" |
||||||
|
echo " docker compose -f docker-compose-orly.yml down" |
||||||
@ -0,0 +1,165 @@ |
|||||||
|
#!/bin/bash |
||||||
|
# Build script for next-orly v0.58.5 Docker image |
||||||
|
|
||||||
|
set -e |
||||||
|
|
||||||
|
# Check for Docker |
||||||
|
DOCKER_CMD="" |
||||||
|
if command -v docker >/dev/null 2>&1; then |
||||||
|
DOCKER_CMD="docker" |
||||||
|
elif command -v podman >/dev/null 2>&1; then |
||||||
|
DOCKER_CMD="podman" |
||||||
|
elif command -v docker.io >/dev/null 2>&1; then |
||||||
|
DOCKER_CMD="docker.io" |
||||||
|
else |
||||||
|
echo "Error: Docker is not installed or not in PATH." |
||||||
|
echo "" |
||||||
|
echo "To install Docker on Ubuntu/Debian:" |
||||||
|
echo " sudo apt install docker.io" |
||||||
|
echo " sudo systemctl enable --now docker" |
||||||
|
echo " sudo usermod -aG docker $USER" |
||||||
|
echo " # Then log out and back in" |
||||||
|
echo "" |
||||||
|
echo "Or install Podman (Docker alternative):" |
||||||
|
echo " sudo apt install podman" |
||||||
|
echo "" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
# Check if we're on the correct tag |
||||||
|
CURRENT_TAG=$(git describe --tags --exact-match HEAD 2>/dev/null || echo "") |
||||||
|
if [ "$CURRENT_TAG" != "v0.58.5" ]; then |
||||||
|
echo "Warning: Not on v0.58.5 tag (current: $CURRENT_TAG)" |
||||||
|
echo "Continuing anyway..." |
||||||
|
fi |
||||||
|
|
||||||
|
# Check if app/web/dist exists (web UI already built) |
||||||
|
if [ -d "app/web/dist" ]; then |
||||||
|
echo "Web UI already built, using existing Dockerfile..." |
||||||
|
DOCKERFILE="Dockerfile" |
||||||
|
else |
||||||
|
echo "Web UI not found, using Dockerfile.with-web (will build web UI in Docker)..." |
||||||
|
DOCKERFILE="Dockerfile.with-web" |
||||||
|
fi |
||||||
|
|
||||||
|
# Check if local nostr clone exists and prepare it for Docker build |
||||||
|
NOSTR_PATH="${NOSTR_PATH:-/home/firefly/Dokumente/repos/nostr}" |
||||||
|
mkdir -p .docker-build-context |
||||||
|
|
||||||
|
# Backup go.mod and go.sum before making changes |
||||||
|
cp go.mod go.mod.backup |
||||||
|
cp go.sum go.sum.backup 2>/dev/null || true |
||||||
|
|
||||||
|
if [ -d "$NOSTR_PATH" ] && [ -f "$NOSTR_PATH/go.mod" ]; then |
||||||
|
echo "Found local nostr clone at: $NOSTR_PATH" |
||||||
|
|
||||||
|
# Remove any existing replace directive |
||||||
|
sed -i '/^replace git.mleku.dev\/mleku\/nostr/d' go.mod |
||||||
|
|
||||||
|
# First, use the actual local path for vendoring (absolute path) |
||||||
|
echo "replace git.mleku.dev/mleku/nostr => $NOSTR_PATH" >> go.mod |
||||||
|
echo "Using local nostr module for vendoring" |
||||||
|
|
||||||
|
# Vendor all dependencies locally (using local network, not Docker's network) |
||||||
|
echo "Vendoring all dependencies locally..." |
||||||
|
go mod vendor || { |
||||||
|
echo "Error: Failed to vendor dependencies. Make sure you have network access." |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
# Copy nostr into build context for Docker |
||||||
|
rm -rf .docker-build-context/nostr |
||||||
|
cp -r "$NOSTR_PATH" .docker-build-context/nostr |
||||||
|
|
||||||
|
# Now update go.mod to use Docker build context path |
||||||
|
echo "Preparing for Docker build..." |
||||||
|
sed -i '/^replace git.mleku.dev\/mleku\/nostr/d' go.mod |
||||||
|
echo "replace git.mleku.dev/mleku/nostr => ./docker-build-context/nostr" >> go.mod |
||||||
|
|
||||||
|
# Update vendor/modules.txt to match the new replace path |
||||||
|
# The nostr code is already in vendor/, we just need to update the metadata |
||||||
|
if [ -f vendor/modules.txt ]; then |
||||||
|
# Replace the absolute path with the relative Docker build context path |
||||||
|
sed -i "s|=> $NOSTR_PATH|=> ./docker-build-context/nostr|g" vendor/modules.txt |
||||||
|
fi |
||||||
|
echo "Using local nostr module from build context" |
||||||
|
else |
||||||
|
echo "Local nostr clone not found at $NOSTR_PATH" |
||||||
|
echo "Will try to fetch from remote (may have DNS issues)..." |
||||||
|
# Create empty directory so COPY doesn't fail |
||||||
|
mkdir -p .docker-build-context/nostr |
||||||
|
|
||||||
|
# Remove any existing replace directive |
||||||
|
sed -i '/^replace git.mleku.dev\/mleku\/nostr/d' go.mod |
||||||
|
|
||||||
|
# Vendor all dependencies locally |
||||||
|
echo "Vendoring all dependencies locally..." |
||||||
|
go mod vendor || { |
||||||
|
echo "Error: Failed to vendor dependencies. Make sure you have network access." |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
fi |
||||||
|
|
||||||
|
# Function to restore go.mod and go.sum on exit |
||||||
|
restore_gomod() { |
||||||
|
if [ -f go.mod.backup ]; then |
||||||
|
mv go.mod.backup go.mod |
||||||
|
echo "Restored go.mod" |
||||||
|
fi |
||||||
|
if [ -f go.sum.backup ]; then |
||||||
|
mv go.sum.backup go.sum |
||||||
|
echo "Restored go.sum" |
||||||
|
fi |
||||||
|
# Clean up build context and vendor |
||||||
|
rm -rf .docker-build-context |
||||||
|
rm -rf vendor |
||||||
|
} |
||||||
|
trap restore_gomod EXIT |
||||||
|
|
||||||
|
# Build the Docker image with both version and latest tags |
||||||
|
# Local nostr clone (if found) is already copied into build context |
||||||
|
echo "Building Docker image silberengel/next-orly:v0.58.5 using $DOCKER_CMD..." |
||||||
|
if [ "$DOCKER_CMD" = "docker" ]; then |
||||||
|
# Try using host network mode first (uses host DNS) - best for DNS issues |
||||||
|
if docker build --help 2>/dev/null | grep -q "\-\-network"; then |
||||||
|
echo "Using host network mode for better DNS resolution..." |
||||||
|
$DOCKER_CMD build --network=host -t silberengel/next-orly:v0.58.5 -t silberengel/next-orly:latest -f "$DOCKERFILE" . |
||||||
|
elif docker build --help 2>/dev/null | grep -q "\-\-dns"; then |
||||||
|
# Fallback to DNS configuration |
||||||
|
echo "Using DNS configuration (8.8.8.8, 8.8.4.4)..." |
||||||
|
$DOCKER_CMD build --dns 8.8.8.8 --dns 8.8.4.4 -t silberengel/next-orly:v0.58.5 -t silberengel/next-orly:latest -f "$DOCKERFILE" . |
||||||
|
else |
||||||
|
# Last resort - no DNS config |
||||||
|
echo "Warning: No DNS configuration available, build may fail..." |
||||||
|
$DOCKER_CMD build -t silberengel/next-orly:v0.58.5 -t silberengel/next-orly:latest -f "$DOCKERFILE" . |
||||||
|
fi |
||||||
|
else |
||||||
|
# buildx or other - try DNS if available |
||||||
|
if docker buildx build --help 2>/dev/null | grep -q "\-\-dns"; then |
||||||
|
$DOCKER_CMD build --dns 8.8.8.8 --dns 8.8.4.4 -t silberengel/next-orly:v0.58.5 -t silberengel/next-orly:latest -f "$DOCKERFILE" . |
||||||
|
else |
||||||
|
$DOCKER_CMD build -t silberengel/next-orly:v0.58.5 -t silberengel/next-orly:latest -f "$DOCKERFILE" . |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "Build complete! Image tags:" |
||||||
|
echo " - silberengel/next-orly:v0.58.5" |
||||||
|
echo " - silberengel/next-orly:latest" |
||||||
|
echo "" |
||||||
|
echo "To push to Docker Hub:" |
||||||
|
echo " $DOCKER_CMD push silberengel/next-orly:v0.58.5" |
||||||
|
echo " $DOCKER_CMD push silberengel/next-orly:latest" |
||||||
|
echo "" |
||||||
|
echo "Or run this script with --push to build and push automatically:" |
||||||
|
echo " $0 --push" |
||||||
|
|
||||||
|
# Push if requested |
||||||
|
if [ "$1" == "--push" ]; then |
||||||
|
echo "" |
||||||
|
echo "Pushing images to Docker Hub..." |
||||||
|
$DOCKER_CMD push silberengel/next-orly:v0.58.5 |
||||||
|
$DOCKER_CMD push silberengel/next-orly:latest |
||||||
|
echo "" |
||||||
|
echo "✅ Images pushed successfully!" |
||||||
|
fi |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
version: '3.8' |
||||||
|
|
||||||
|
services: |
||||||
|
orly-relay: |
||||||
|
image: silberengel/next-orly:v0.48.10 |
||||||
|
container_name: orly-relay |
||||||
|
restart: always |
||||||
|
ports: |
||||||
|
- "127.0.0.1:3334:3334" |
||||||
|
- "127.0.0.1:7777:7777" |
||||||
|
volumes: |
||||||
|
# Use bind mount to host filesystem for large datasets (20GB+) |
||||||
|
# Change /var/lib/orly to your desired data directory on the host |
||||||
|
- /var/lib/orly:/data |
||||||
|
environment: |
||||||
|
# Relay Configuration |
||||||
|
- ORLY_DATA_DIR=/data |
||||||
|
- ORLY_LISTEN=0.0.0.0 |
||||||
|
- ORLY_PORT=7777 |
||||||
|
- ORLY_LOG_LEVEL=Info |
||||||
|
|
||||||
|
# Admin and Owner Configuration |
||||||
|
- ORLY_ADMINS=npub1m4ny6hjqzepn4rxknuq94c2gpqzr29ufkkw7ttcxyak7v43n6vvsajc2jl,npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx,npub12umrfdjgvdxt45g0y3ghwcyfagssjrv5qlm3t6pu2aa5vydwdmwq8q0z04,npub18cddpua960qjy3wmw7y9gmzr4h3ajlrwq3k9jnmqzlxke4qkg6gqeyaztw |
||||||
|
- ORLY_OWNERS=npub1m4ny6hjqzepn4rxknuq94c2gpqzr29ufkkw7ttcxyak7v43n6vvsajc2jl,npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx,npub12umrfdjgvdxt45g0y3ghwcyfagssjrv5qlm3t6pu2aa5vydwdmwq8q0z04,npub18cddpua960qjy3wmw7y9gmzr4h3ajlrwq3k9jnmqzlxke4qkg6gqeyaztw |
||||||
|
|
||||||
|
# ACL Configuration (follows mode for access control based on admin follow lists) |
||||||
|
- ORLY_ACL_MODE=follows |
||||||
|
|
||||||
|
# Spider Configuration (syncs events for followed pubkeys) |
||||||
|
- ORLY_SPIDER_MODE=follows |
||||||
|
|
||||||
|
# Relay URL (for dashboard and metadata) |
||||||
|
- ORLY_RELAY_URL=wss://orly-relay.imwald.eu |
||||||
|
|
||||||
|
# Sprocket Configuration (event processing plugin system) |
||||||
|
- ORLY_SPROCKET_ENABLED=false |
||||||
|
|
||||||
|
# Database Logging |
||||||
|
- ORLY_DB_LOG_LEVEL=error |
||||||
|
|
||||||
|
# Database Cache Tuning for Large Datasets (20GB+) |
||||||
|
# Increased caches for better performance with large working sets |
||||||
|
- ORLY_DB_BLOCK_CACHE_MB=2048 # 2GB block cache (default: 1024MB) |
||||||
|
- ORLY_DB_INDEX_CACHE_MB=1024 # 1GB index cache (default: 512MB) |
||||||
|
- ORLY_SERIAL_CACHE_PUBKEYS=500000 # 500k pubkeys cache (default: 100k) |
||||||
|
- ORLY_SERIAL_CACHE_EVENT_IDS=2000000 # 2M event IDs cache (default: 500k) |
||||||
|
- ORLY_DB_ZSTD_LEVEL=9 # ZSTD compression level 9 (best compression, reduces disk IO) |
||||||
|
|
||||||
|
# Storage GC Configuration for Large Archives |
||||||
|
# Enable GC with aggressive eviction to manage storage growth |
||||||
|
- ORLY_GC_ENABLED=true # Enable storage garbage collection |
||||||
|
- ORLY_GC_BATCH_SIZE=5000 # GC batch size for efficient processing |
||||||
|
- ORLY_MAX_STORAGE_BYTES=107374182400 # 100GB storage cap (adjust as needed) |
||||||
|
|
||||||
|
# Bootstrap relay for initial sync |
||||||
|
- ORLY_BOOTSTRAP_RELAYS=wss://profiles.nostr1.com,wss://purplepag.es,wss://relay.damus.io |
||||||
|
|
||||||
|
# Disable subscription/payment requirements |
||||||
|
- ORLY_SUBSCRIPTION_ENABLED=false |
||||||
|
- ORLY_MONTHLY_PRICE_SAT=0 |
||||||
|
|
||||||
|
# Performance Settings |
||||||
|
- ORLY_MAX_CONNECTIONS=1000 |
||||||
|
- ORLY_MAX_EVENT_SIZE=65536 |
||||||
|
- ORLY_MAX_SUBSCRIPTIONS=20 |
||||||
|
|
||||||
|
healthcheck: |
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:7777"] |
||||||
|
interval: 30s |
||||||
|
timeout: 10s |
||||||
|
retries: 3 |
||||||
|
start_period: 20s |
||||||
|
|
||||||
|
# Resource limits - Increased for large imports (20GB+) |
||||||
|
# Memory increased to handle Badger caches and import operations |
||||||
|
deploy: |
||||||
|
resources: |
||||||
|
limits: |
||||||
|
memory: 4096M # 4GB - increased from 1GB for large dataset imports |
||||||
|
cpus: "2.0" # Increased CPU for faster compaction during imports |
||||||
|
reservations: |
||||||
|
memory: 2048M # 2GB reservation |
||||||
|
cpus: "1.0" |
||||||
|
|
||||||
|
# Logging configuration |
||||||
|
logging: |
||||||
|
driver: "json-file" |
||||||
|
options: |
||||||
|
max-size: "10m" |
||||||
|
max-file: "3" |
||||||
|
|
||||||
|
# Note: Using bind mount instead of named volume for large datasets |
||||||
|
# Data is stored directly on host filesystem at /var/lib/orly |
||||||
|
# To use a different path, change the volume mount above |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
#!/bin/bash |
||||||
|
# Run Orly relay using docker run (alternative to docker-compose) |
||||||
|
# Optimized for large dataset imports (20GB+) |
||||||
|
|
||||||
|
set -e |
||||||
|
|
||||||
|
CONTAINER_NAME="orly-relay" |
||||||
|
IMAGE="silberengel/next-orly:v0.58.5" |
||||||
|
|
||||||
|
# Data directory on host filesystem (change this to your desired path) |
||||||
|
# Using bind mount instead of volume for better performance with large datasets |
||||||
|
DATA_DIR="${ORLY_DATA_DIR:-/var/lib/orly}" |
||||||
|
|
||||||
|
# Create data directory if it doesn't exist |
||||||
|
mkdir -p "${DATA_DIR}" |
||||||
|
# Set ownership to UID 1000 (orly user in container) and permissions |
||||||
|
chown -R 1000:1000 "${DATA_DIR}" 2>/dev/null || { |
||||||
|
echo "Warning: Could not set ownership of ${DATA_DIR} to UID 1000" |
||||||
|
echo "You may need to run: sudo chown -R 1000:1000 ${DATA_DIR}" |
||||||
|
} |
||||||
|
chmod 755 "${DATA_DIR}" |
||||||
|
|
||||||
|
# Pull the latest image |
||||||
|
echo "Pulling ${IMAGE}..." |
||||||
|
docker pull ${IMAGE} |
||||||
|
|
||||||
|
# Check if container already exists |
||||||
|
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then |
||||||
|
echo "Container ${CONTAINER_NAME} already exists." |
||||||
|
echo "Removing existing container..." |
||||||
|
docker rm -f ${CONTAINER_NAME} 2>/dev/null || true |
||||||
|
fi |
||||||
|
|
||||||
|
# Run the container |
||||||
|
echo "Starting ${CONTAINER_NAME}..." |
||||||
|
docker run -d \ |
||||||
|
--name ${CONTAINER_NAME} \ |
||||||
|
--restart always \ |
||||||
|
-p 127.0.0.1:3334:3334 \ |
||||||
|
-p 127.0.0.1:7777:7777 \ |
||||||
|
-v "${DATA_DIR}:/data" \ |
||||||
|
--memory=4096m \ |
||||||
|
--cpus="2.0" \ |
||||||
|
--health-cmd="curl -f http://localhost:7777/ || exit 1" \ |
||||||
|
--health-interval=10s \ |
||||||
|
--health-timeout=5s \ |
||||||
|
--health-start-period=20s \ |
||||||
|
--health-retries=3 \ |
||||||
|
-e ORLY_DATA_DIR=/data \ |
||||||
|
-e ORLY_LISTEN=0.0.0.0 \ |
||||||
|
-e ORLY_PORT=7777 \ |
||||||
|
-e ORLY_LOG_LEVEL=Info \ |
||||||
|
-e ORLY_ADMINS=npub1m4ny6hjqzepn4rxknuq94c2gpqzr29ufkkw7ttcxyak7v43n6vvsajc2jl,npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx,npub12umrfdjgvdxt45g0y3ghwcyfagssjrv5qlm3t6pu2aa5vydwdmwq8q0z04,npub18cddpua960qjy3wmw7y9gmzr4h3ajlrwq3k9jnmqzlxke4qkg6gqeyaztw \ |
||||||
|
-e ORLY_OWNERS=npub1m4ny6hjqzepn4rxknuq94c2gpqzr29ufkkw7ttcxyak7v43n6vvsajc2jl,npub1v30tsz9vw6ylpz63g0a702nj3xa26t3m7p5us8f2y2sd8v6cnsvq465zjx,npub12umrfdjgvdxt45g0y3ghwcyfagssjrv5qlm3t6pu2aa5vydwdmwq8q0z04,npub18cddpua960qjy3wmw7y9gmzr4h3ajlrwq3k9jnmqzlxke4qkg6gqeyaztw \ |
||||||
|
-e ORLY_ACL_MODE=follows \ |
||||||
|
-e ORLY_SPIDER_MODE=follows \ |
||||||
|
-e ORLY_RELAY_URL=wss://orly-relay.imwald.eu \ |
||||||
|
-e ORLY_SPROCKET_ENABLED=false \ |
||||||
|
-e ORLY_DB_LOG_LEVEL=error \ |
||||||
|
-e ORLY_DB_BLOCK_CACHE_MB=2048 \ |
||||||
|
-e ORLY_DB_INDEX_CACHE_MB=1024 \ |
||||||
|
-e ORLY_SERIAL_CACHE_PUBKEYS=500000 \ |
||||||
|
-e ORLY_SERIAL_CACHE_EVENT_IDS=2000000 \ |
||||||
|
-e ORLY_DB_ZSTD_LEVEL=9 \ |
||||||
|
-e ORLY_GC_ENABLED=true \ |
||||||
|
-e ORLY_GC_BATCH_SIZE=5000 \ |
||||||
|
-e ORLY_MAX_STORAGE_BYTES=107374182400 \ |
||||||
|
-e ORLY_BOOTSTRAP_RELAYS=wss://profiles.nostr1.com,wss://purplepag.es,wss://relay.nostr.band,wss://relay.damus.io \ |
||||||
|
-e ORLY_SUBSCRIPTION_ENABLED=false \ |
||||||
|
-e ORLY_MONTHLY_PRICE_SAT=0 \ |
||||||
|
-e ORLY_MAX_CONNECTIONS=1000 \ |
||||||
|
-e ORLY_MAX_EVENT_SIZE=65536 \ |
||||||
|
-e ORLY_MAX_SUBSCRIPTIONS=20 \ |
||||||
|
${IMAGE} |
||||||
|
|
||||||
|
echo "" |
||||||
|
echo "Container started!" |
||||||
|
echo "Data directory: ${DATA_DIR}" |
||||||
|
echo "View logs: docker logs -f ${CONTAINER_NAME}" |
||||||
|
echo "Stop: docker stop ${CONTAINER_NAME}" |
||||||
|
echo "Start: docker start ${CONTAINER_NAME}" |
||||||
|
echo "Remove: docker rm -f ${CONTAINER_NAME}" |
||||||
|
echo "" |
||||||
|
echo "For large imports (20GB+), use the web UI or API:" |
||||||
|
echo " curl -X POST -F 'file=@your-events.jsonl' http://localhost:7777/api/import" |
||||||
Loading…
Reference in new issue