From cfc9718f0fe5e41ceeb68ab680c2b2b54acd4dcf Mon Sep 17 00:00:00 2001 From: cyph3rasi Date: Sat, 7 Mar 2026 17:36:41 -0800 Subject: [PATCH] Add proxyless install mode for existing reverse proxies --- README.md | 6 +++ docker-compose.proxyless.yml | 78 +++++++++++++++++++++++++++++++++++ docker/.env.example | 4 ++ docker/README.md | 51 ++++++++++++++++++++++- docker/install.sh | 80 ++++++++++++++++++++++++++++++++---- 5 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 docker-compose.proxyless.yml diff --git a/README.md b/README.md index eda3ae2..6c96e2a 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ docker compose up -d Done! Your node is live at `https://your-domain.com` with automatic SSL. No build step. No dependencies. No fuss. Database migrations run automatically on startup and during updates. +If your server already has nginx or another reverse proxy using `80/443`, use the advanced mode instead: + +```bash +curl -fsSL https://synapsis.social/install.sh | PROXY=none bash +``` + **Updating (migrations run automatically):** ```bash docker compose pull && docker compose up -d diff --git a/docker-compose.proxyless.yml b/docker-compose.proxyless.yml new file mode 100644 index 0000000..ecfec9c --- /dev/null +++ b/docker-compose.proxyless.yml @@ -0,0 +1,78 @@ +# Synapsis - Docker Compose (Production, External Reverse Proxy) +# Uses pre-built image from GitHub Container Registry +# +# Intended for hosts that already run nginx/Traefik/Caddy on 80/443. +# Synapsis binds only to localhost so your existing proxy can forward to it. + +services: + postgres: + image: postgres:16-alpine + container_name: synapsis-db + restart: unless-stopped + environment: + POSTGRES_USER: ${DB_USER:-synapsis} + POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} + POSTGRES_DB: ${DB_NAME:-synapsis} + PGDATA: /var/lib/postgresql/data/pgdata + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - synapsis-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-synapsis} -d ${DB_NAME:-synapsis}"] + interval: 10s + timeout: 5s + retries: 5 + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 256M + + app: + image: ghcr.io/gnosyslabs/synapsis:latest + container_name: synapsis-app + restart: unless-stopped + ports: + - "127.0.0.1:${APP_HOST_PORT:-3000}:3000" + environment: + DATABASE_URL: postgresql://${DB_USER:-synapsis}:${DB_PASSWORD:-changeme}@postgres:5432/${DB_NAME:-synapsis} + AUTH_SECRET: ${AUTH_SECRET} + DOMAIN: ${DOMAIN:-localhost} + NEXT_PUBLIC_NODE_DOMAIN: ${NEXT_PUBLIC_NODE_DOMAIN:-} + NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL:-} + ALLOW_LOCALHOST: ${ALLOW_LOCALHOST:-} + ADMIN_EMAILS: ${ADMIN_EMAILS} + BOT_MAX_PER_USER: ${BOT_MAX_PER_USER:-5} + PORT: "3000" + NODE_ENV: production + volumes: + - uploads_data:/app/uploads + networks: + - synapsis-network + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:3000/api/health || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 256M + +volumes: + postgres_data: + driver: local + uploads_data: + driver: local + +networks: + synapsis-network: + driver: bridge diff --git a/docker/.env.example b/docker/.env.example index 2a02910..f96ee70 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -38,6 +38,10 @@ DB_NAME=synapsis # Or set a specific port: PORT=3000 PORT=auto +# External reverse proxy mode only: +# Port on localhost to expose Synapsis for nginx/Traefik/Caddy +# APP_HOST_PORT=3000 + # Allow localhost domains in production (set only for local testing) # ALLOW_LOCALHOST=1 diff --git a/docker/README.md b/docker/README.md index 8b1e8cc..73ada1f 100644 --- a/docker/README.md +++ b/docker/README.md @@ -6,6 +6,8 @@ Production Docker deployment using pre-built images from GitHub Container Regist ## 🚀 Quick Start +This is the default install path for a fresh VPS where Synapsis should manage its own HTTPS with Caddy. + ```bash curl -fsSL https://synapsis.social/install.sh | bash nano /opt/synapsis/.env # Add your domain and admin email @@ -24,6 +26,7 @@ Your node is live at `https://your-domain.com` with automatic SSL. | **Server** | 2GB RAM, 2 CPU cores, 20GB SSD (minimum) | | **Domain** | A domain or subdomain pointing to your server | | **Docker** | Installed automatically by `install.sh` when missing on supported Linux hosts | +| **Ports** | `80` and `443` must be free for the default Caddy install | --- @@ -46,6 +49,44 @@ Optional (advanced): **Port Configuration:** - `PORT=auto` (default) — Automatically finds an available port between 3000-3020 - `PORT=3000` — Use a specific port instead +- `APP_HOST_PORT=3000` — Only used in advanced `PROXY=none` installs + +--- + +## Advanced: Existing nginx/Traefik/Caddy Host + +If your server already runs a reverse proxy on `80/443`, use the advanced mode: + +```bash +curl -fsSL https://synapsis.social/install.sh | PROXY=none bash +nano /opt/synapsis/.env +cd /opt/synapsis +docker compose up -d +``` + +This mode: +- skips the bundled Caddy service +- binds Synapsis to `127.0.0.1:${APP_HOST_PORT:-3000}` +- expects your existing reverse proxy to forward traffic there + +Example nginx site: + +```nginx +server { + server_name node.example.com; + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} +``` --- @@ -98,7 +139,15 @@ docker compose logs app --tail=50 # Check errors ``` ### Port already in use -`PORT=auto` (default) automatically finds an available port. If you set a specific port that's taken: +If the installer says `80` or `443` is already in use, another reverse proxy is already bound there. + +Use a fresh VPS for the default Caddy install, or rerun the installer in advanced mode: + +```bash +curl -fsSL https://synapsis.social/install.sh | PROXY=none bash +``` + +For the application port itself, `PORT=auto` (default) automatically finds an available port. If you set a specific port that's taken: ```bash # Check what's using the port sudo netstat -tlnp | grep :3000 diff --git a/docker/install.sh b/docker/install.sh index 9f33c73..89077d2 100644 --- a/docker/install.sh +++ b/docker/install.sh @@ -6,6 +6,7 @@ REPO="${REPO:-GnosysLabs/Synapsis}" REF="${REF:-main}" INSTALL_DIR="${1:-${INSTALL_DIR:-/opt/synapsis}}" PUBLIC_INSTALL_URL="${PUBLIC_INSTALL_URL:-https://synapsis.social/install.sh}" +PROXY="${PROXY:-caddy}" require_command() { if ! command -v "$1" >/dev/null 2>&1; then @@ -21,6 +22,53 @@ download_file() { curl -fsSL "${RAW_BASE}/${source_path}" -o "${target_path}" } +normalize_proxy_mode() { + case "$1" in + caddy|none) + printf '%s\n' "$1" + ;; + *) + echo "❌ Unsupported PROXY mode: $1" >&2 + echo " Supported values: caddy, none" >&2 + exit 1 + ;; + esac +} + +is_port_in_use() { + port="$1" + + if command -v ss >/dev/null 2>&1; then + ss -tulpn 2>/dev/null | grep -q ":${port} " + return $? + fi + + if command -v lsof >/dev/null 2>&1; then + lsof -iTCP:"${port}" -sTCP:LISTEN >/dev/null 2>&1 + return $? + fi + + if command -v netstat >/dev/null 2>&1; then + netstat -tulpn 2>/dev/null | grep -q ":${port} " + return $? + fi + + return 1 +} + +ensure_caddy_ports_available() { + for port in 80 443; do + if is_port_in_use "$port"; then + echo "❌ Port ${port} is already in use on this host." >&2 + echo " The default Synapsis install includes Caddy and needs ports 80/443." >&2 + echo " If this is a fresh VPS, free those ports and rerun the installer." >&2 + echo " If this host already runs nginx or another reverse proxy, rerun with:" >&2 + echo " curl -fsSL ${PUBLIC_INSTALL_URL} | PROXY=none bash" >&2 + exit 1 + fi + done +} + set_env_value() { file="$1" key="$2" @@ -73,6 +121,7 @@ require_command mkdir require_command cp RAW_BASE="https://raw.githubusercontent.com/${REPO}/${REF}" +PROXY="$(normalize_proxy_mode "${PROXY}")" echo "========================================" echo " Synapsis Docker Installer" @@ -80,17 +129,27 @@ echo "========================================" echo " Repo: ${REPO}" echo " Ref: ${REF}" echo " Install dir: ${INSTALL_DIR}" +echo " Proxy mode: ${PROXY}" echo "========================================" install_docker_if_needed mkdir -p "${INSTALL_DIR}" -download_file "docker-compose.yml" "${INSTALL_DIR}/docker-compose.yml" -download_file "docker/Caddyfile" "${INSTALL_DIR}/Caddyfile" -download_file "docker/caddy-entrypoint.sh" "${INSTALL_DIR}/caddy-entrypoint.sh" download_file "docker/.env.example" "${INSTALL_DIR}/.env.example" - -chmod 755 "${INSTALL_DIR}/caddy-entrypoint.sh" +case "${PROXY}" in + caddy) + ensure_caddy_ports_available + download_file "docker-compose.yml" "${INSTALL_DIR}/docker-compose.yml" + download_file "docker/Caddyfile" "${INSTALL_DIR}/Caddyfile" + download_file "docker/caddy-entrypoint.sh" "${INSTALL_DIR}/caddy-entrypoint.sh" + chmod 755 "${INSTALL_DIR}/caddy-entrypoint.sh" + rm -f "${INSTALL_DIR}/docker-compose.proxyless.yml" + ;; + none) + download_file "docker-compose.proxyless.yml" "${INSTALL_DIR}/docker-compose.yml" + rm -f "${INSTALL_DIR}/Caddyfile" "${INSTALL_DIR}/caddy-entrypoint.sh" + ;; +esac if [ ! -f "${INSTALL_DIR}/.env" ]; then cp "${INSTALL_DIR}/.env.example" "${INSTALL_DIR}/.env" @@ -120,5 +179,12 @@ fi echo "" echo "Next steps:" echo " 1. Review ${INSTALL_DIR}/.env" -echo " 2. Start Synapsis:" -echo " cd ${INSTALL_DIR} && docker compose up -d" +if [ "${PROXY}" = "caddy" ]; then + echo " 2. Start Synapsis:" + echo " cd ${INSTALL_DIR} && docker compose up -d" +else + echo " 2. Start Synapsis:" + echo " cd ${INSTALL_DIR} && docker compose up -d" + echo " 3. Configure your existing reverse proxy to forward to:" + echo " http://127.0.0.1:\${APP_HOST_PORT:-3000}" +fi