From 6d71e835a0206178ae58bc195e95095a77486292 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Fri, 3 Apr 2026 23:48:37 +0200 Subject: [PATCH 1/4] Add Telegram Archive, GenieACS, and LynxPrompt examples Three new self-hosted compose examples: - Telegram Archive: automated Telegram backup with web viewer (SQLite/PostgreSQL) - GenieACS: TR-069 ACS for remote ISP device management with MongoDB - LynxPrompt: AI IDE config management platform with multi-database architecture --- README.md | 3 + examples/genieacs/README.md | 9 ++ examples/genieacs/docker-compose.yml | 60 ++++++++ examples/lynxprompt/README.md | 9 ++ examples/lynxprompt/docker-compose.yml | 140 +++++++++++++++++++ examples/telegram-archive/README.md | 5 + examples/telegram-archive/docker-compose.yml | 66 +++++++++ 7 files changed, 292 insertions(+) create mode 100644 examples/genieacs/README.md create mode 100644 examples/genieacs/docker-compose.yml create mode 100644 examples/lynxprompt/README.md create mode 100644 examples/lynxprompt/docker-compose.yml create mode 100644 examples/telegram-archive/README.md create mode 100644 examples/telegram-archive/docker-compose.yml diff --git a/README.md b/README.md index 4e6db9d5f..233a9f1a4 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ A [Large Language Model (LLM)](https://en.wikipedia.org/wiki/Large_language_mode - [Ollama + Open WebUI](examples/ollama-ui) - Get up and running with Llama 3, Mistral, Gemma, and other large language models using Ollama. Using an interactive, user-friendly WebUI via Open WebUI (formerly known as Ollama WebUI). - [Serge](examples/serge) - A web interface for chatting with Alpaca through llama.cpp. Fully dockerized, with an easy to use API. +- [LynxPrompt](examples/lynxprompt) - Self-hosted platform for managing and sharing AI IDE configuration files (AGENTS.md, CLAUDE.md) with a web UI, CLI, and federation support. ### Virtual Private Network (VPN) & Remote Access @@ -199,6 +200,7 @@ Tools and software for [software project management](https://en.wikipedia.org/wi - [Watchtower](examples/watchtower) - A container-based solution for automating Docker container base image updates. - [Unify Network Application](examples/unify-network-application) - The Unifi-network-application software is a powerful, enterprise wireless software engine ideal for high-density client deployments requiring low latency and high uptime performance. - [UpSnap](examples/upsnap) - A simple wake on lan app written with SvelteKit, Go, PocketBase and nmap. +- [GenieACS](examples/genieacs) - Open-source TR-069 remote management platform for ISP customer-premises equipment (routers, ONTs, set-top boxes). ### Recipe Management @@ -255,6 +257,7 @@ Digital [archiving](https://en.wikipedia.org/wiki/Archival_science) and [preserv - [Shiori](examples/shiori) - Simple bookmark manager and website archiver built with Go. - [Readeck](examples/readeck) - Readeck is a simple web application that lets you save the precious readable content of web pages you like and want to keep forever. - [Linkwarden](examples/linkwarden) - Self-hosted collaborative bookmark manager to collect, organize, and preserve webpages, articles, and documents. +- [Telegram Archive](examples/telegram-archive) - Own your Telegram history with automated, incremental backups and a local web viewer that mirrors the Telegram UI. ### Document Management diff --git a/examples/genieacs/README.md b/examples/genieacs/README.md new file mode 100644 index 000000000..0d8e10314 --- /dev/null +++ b/examples/genieacs/README.md @@ -0,0 +1,9 @@ +# References + +- https://github.com/GeiserX/genieacs-container +- https://hub.docker.com/r/drumsergio/genieacs +- https://genieacs.com + +# Notes + +GenieACS is an open-source TR-069 remote management platform for ISP customer-premises equipment (routers, ONTs, set-top boxes). The web UI is available on port 3000. CWMP (port 7547) is where devices connect. diff --git a/examples/genieacs/docker-compose.yml b/examples/genieacs/docker-compose.yml new file mode 100644 index 000000000..cf6916dc3 --- /dev/null +++ b/examples/genieacs/docker-compose.yml @@ -0,0 +1,60 @@ +services: + + genieacs: + image: drumsergio/genieacs:1.2.16.0 + container_name: genieacs + restart: unless-stopped + depends_on: + mongo: + condition: service_healthy + ports: + - 7547:7547 + - 7557:7557 + - 7567:7567 + - 3000:3000 + expose: + - 3000 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/genieacs/ext:/opt/genieacs/ext + environment: + GENIEACS_UI_JWT_SECRET: ${GENIEACS_UI_JWT_SECRET:-ChangeMe1234} + GENIEACS_MONGODB_CONNECTION_URL: mongodb://mongo/genieacs?authSource=admin + GENIEACS_CWMP_ACCESS_LOG_FILE: /var/log/genieacs/genieacs-cwmp-access.log + GENIEACS_NBI_ACCESS_LOG_FILE: /var/log/genieacs/genieacs-nbi-access.log + GENIEACS_FS_ACCESS_LOG_FILE: /var/log/genieacs/genieacs-fs-access.log + GENIEACS_UI_ACCESS_LOG_FILE: /var/log/genieacs/genieacs-ui-access.log + GENIEACS_DEBUG_FILE: /var/log/genieacs/genieacs-debug.yaml + GENIEACS_EXT_DIR: /opt/genieacs/ext + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + #networks: + # - proxy + #labels: + # - traefik.enable=true + # - traefik.docker.network=proxy + # - traefik.http.routers.genieacs.rule=Host(`acs.example.com`) + # - traefik.http.services.genieacs.loadbalancer.server.port=3000 + + mongo: + image: mongo:8.0 + container_name: genieacs-mongo + restart: unless-stopped + expose: + - 27017 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/genieacs/mongodb:/data/db + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/genieacs/mongodb-config:/data/configdb + healthcheck: + test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 40s + +#networks: +# proxy: +# external: true diff --git a/examples/lynxprompt/README.md b/examples/lynxprompt/README.md new file mode 100644 index 000000000..4c4fe66d7 --- /dev/null +++ b/examples/lynxprompt/README.md @@ -0,0 +1,9 @@ +# References + +- https://github.com/GeiserX/LynxPrompt +- https://hub.docker.com/r/drumsergio/lynxprompt +- https://lynxprompt.com + +# Notes + +LynxPrompt uses four separate PostgreSQL databases by design (app, users, blog, support) for data isolation. Generate a `NEXTAUTH_SECRET` with `openssl rand -base64 32`. diff --git a/examples/lynxprompt/docker-compose.yml b/examples/lynxprompt/docker-compose.yml new file mode 100644 index 000000000..cfa780634 --- /dev/null +++ b/examples/lynxprompt/docker-compose.yml @@ -0,0 +1,140 @@ +services: + + lynxprompt: + image: drumsergio/lynxprompt:latest + container_name: lynxprompt + restart: unless-stopped + depends_on: + postgres-app: + condition: service_healthy + postgres-users: + condition: service_healthy + postgres-blog: + condition: service_healthy + postgres-support: + condition: service_healthy + ports: + - 3000:3000 + expose: + - 3000 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/uploads:/data/uploads + environment: + # NextAuth (required — generate with: openssl rand -base64 32) + NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} + NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:?Generate with openssl rand -base64 32} + # Databases + DB_APP_HOST: postgres-app + DB_APP_USER: lynxprompt_app + DB_APP_PASSWORD: ${POSTGRES_APP_PASSWORD:-DatabasePassword1234} + DB_APP_NAME: lynxprompt_app + DB_USERS_HOST: postgres-users + DB_USERS_USER: lynxprompt_users + DB_USERS_PASSWORD: ${POSTGRES_USERS_PASSWORD:-DatabasePassword1234} + DB_USERS_NAME: lynxprompt_users + DB_BLOG_HOST: postgres-blog + DB_BLOG_USER: lynxprompt_blog + DB_BLOG_PASSWORD: ${POSTGRES_BLOG_PASSWORD:-DatabasePassword1234} + DB_BLOG_NAME: lynxprompt_blog + DB_SUPPORT_HOST: postgres-support + DB_SUPPORT_USER: lynxprompt_support + DB_SUPPORT_PASSWORD: ${POSTGRES_SUPPORT_PASSWORD:-DatabasePassword1234} + DB_SUPPORT_NAME: lynxprompt_support + # Feature flags (all optional) + ENABLE_EMAIL_AUTH: ${ENABLE_EMAIL_AUTH:-true} + ENABLE_PASSKEYS: ${ENABLE_PASSKEYS:-true} + ENABLE_USER_REGISTRATION: ${ENABLE_USER_REGISTRATION:-true} + # OAuth (optional) + #GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-} + #GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-} + #ENABLE_GITHUB_OAUTH: ${ENABLE_GITHUB_OAUTH:-false} + # AI features (optional — requires Anthropic API key) + #ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} + #ENABLE_AI: ${ENABLE_AI:-false} + # Branding + APP_NAME: ${APP_NAME:-LynxPrompt} + APP_URL: ${APP_URL:-http://localhost:3000} + UPLOAD_DIR: /data/uploads/blog + #networks: + # - proxy + #labels: + # - traefik.enable=true + # - traefik.docker.network=proxy + # - traefik.http.routers.lynxprompt.rule=Host(`lynxprompt.example.com`) + # - traefik.http.services.lynxprompt.loadbalancer.server.port=3000 + + postgres-app: + image: postgres:18-alpine + container_name: lynxprompt-postgres-app + restart: unless-stopped + expose: + - 5432 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-app:/var/lib/postgresql/data + environment: + POSTGRES_DB: lynxprompt_app + POSTGRES_USER: lynxprompt_app + POSTGRES_PASSWORD: ${POSTGRES_APP_PASSWORD:-DatabasePassword1234} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U lynxprompt_app"] + interval: 10s + timeout: 5s + retries: 5 + + postgres-users: + image: postgres:18-alpine + container_name: lynxprompt-postgres-users + restart: unless-stopped + expose: + - 5432 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-users:/var/lib/postgresql/data + environment: + POSTGRES_DB: lynxprompt_users + POSTGRES_USER: lynxprompt_users + POSTGRES_PASSWORD: ${POSTGRES_USERS_PASSWORD:-DatabasePassword1234} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U lynxprompt_users"] + interval: 10s + timeout: 5s + retries: 5 + + postgres-blog: + image: postgres:18-alpine + container_name: lynxprompt-postgres-blog + restart: unless-stopped + expose: + - 5432 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-blog:/var/lib/postgresql/data + environment: + POSTGRES_DB: lynxprompt_blog + POSTGRES_USER: lynxprompt_blog + POSTGRES_PASSWORD: ${POSTGRES_BLOG_PASSWORD:-DatabasePassword1234} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U lynxprompt_blog"] + interval: 10s + timeout: 5s + retries: 5 + + postgres-support: + image: postgres:18-alpine + container_name: lynxprompt-postgres-support + restart: unless-stopped + expose: + - 5432 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-support:/var/lib/postgresql/data + environment: + POSTGRES_DB: lynxprompt_support + POSTGRES_USER: lynxprompt_support + POSTGRES_PASSWORD: ${POSTGRES_SUPPORT_PASSWORD:-DatabasePassword1234} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U lynxprompt_support"] + interval: 10s + timeout: 5s + retries: 5 + +#networks: +# proxy: +# external: true diff --git a/examples/telegram-archive/README.md b/examples/telegram-archive/README.md new file mode 100644 index 000000000..806687040 --- /dev/null +++ b/examples/telegram-archive/README.md @@ -0,0 +1,5 @@ +# References + +- https://github.com/GeiserX/Telegram-Archive +- https://hub.docker.com/r/drumsergio/telegram-archive +- https://hub.docker.com/r/drumsergio/telegram-archive-viewer diff --git a/examples/telegram-archive/docker-compose.yml b/examples/telegram-archive/docker-compose.yml new file mode 100644 index 000000000..2d85bae9e --- /dev/null +++ b/examples/telegram-archive/docker-compose.yml @@ -0,0 +1,66 @@ +services: + + telegram-backup: + image: drumsergio/telegram-archive:latest + container_name: telegram-backup + restart: unless-stopped + command: ["python", "-m", "src", "schedule"] + expose: + - 8000 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/telegram-archive:/data + environment: + # Telegram Credentials (required — get from https://my.telegram.org) + TELEGRAM_API_ID: ${TELEGRAM_API_ID} + TELEGRAM_API_HASH: ${TELEGRAM_API_HASH} + TELEGRAM_PHONE: ${TELEGRAM_PHONE} + SESSION_NAME: ${SESSION_NAME:-telegram_backup} + # Backup schedule (cron format) + SCHEDULE: ${SCHEDULE:-0 */6 * * *} + # Backup settings + BACKUP_PATH: /data/backups + DOWNLOAD_MEDIA: ${DOWNLOAD_MEDIA:-true} + MAX_MEDIA_SIZE_MB: ${MAX_MEDIA_SIZE_MB:-100} + # Chat filtering (comma-separated types: private, groups, channels) + CHAT_TYPES: ${CHAT_TYPES:-private,groups,channels} + # Database + DB_TYPE: ${DB_TYPE:-sqlite} + DB_PATH: /data/backups/telegram_backup.db + #networks: + # - proxy + #labels: + # - traefik.enable=true + # - traefik.docker.network=proxy + # - traefik.http.routers.telegram-backup.rule=Host(`telegram.example.com`) + # - traefik.http.services.telegram-backup.loadbalancer.server.port=8000 + + telegram-viewer: + image: drumsergio/telegram-archive-viewer:latest + container_name: telegram-viewer + restart: unless-stopped + ports: + - 8000:8000 + expose: + - 8000 + volumes: + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/telegram-archive:/data + environment: + BACKUP_PATH: /data/backups + # Authentication (recommended) + VIEWER_USERNAME: ${VIEWER_USERNAME:-admin} + VIEWER_PASSWORD: ${VIEWER_PASSWORD:-ChangeMe1234} + VIEWER_TIMEZONE: ${VIEWER_TIMEZONE:-Europe/Berlin} + # Database — must match backup service + DB_TYPE: ${DB_TYPE:-sqlite} + DB_PATH: /data/backups/telegram_backup.db + #networks: + # - proxy + #labels: + # - traefik.enable=true + # - traefik.docker.network=proxy + # - traefik.http.routers.telegram-viewer.rule=Host(`telegram.example.com`) + # - traefik.http.services.telegram-viewer.loadbalancer.server.port=8000 + +#networks: +# proxy: +# external: true From 81bc8b7a017eeebef6c5e4809c3877e2a6a33ce9 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:39:23 +0200 Subject: [PATCH 2/4] Refresh Telegram Archive and GenieACS examples to current releases --- examples/genieacs/docker-compose.yml | 2 +- examples/telegram-archive/README.md | 4 ++++ examples/telegram-archive/docker-compose.yml | 19 +++++-------------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/examples/genieacs/docker-compose.yml b/examples/genieacs/docker-compose.yml index cf6916dc3..4863b0301 100644 --- a/examples/genieacs/docker-compose.yml +++ b/examples/genieacs/docker-compose.yml @@ -1,7 +1,7 @@ services: genieacs: - image: drumsergio/genieacs:1.2.16.0 + image: drumsergio/genieacs:1.2.16.6 container_name: genieacs restart: unless-stopped depends_on: diff --git a/examples/telegram-archive/README.md b/examples/telegram-archive/README.md index 806687040..09e6e3c97 100644 --- a/examples/telegram-archive/README.md +++ b/examples/telegram-archive/README.md @@ -3,3 +3,7 @@ - https://github.com/GeiserX/Telegram-Archive - https://hub.docker.com/r/drumsergio/telegram-archive - https://hub.docker.com/r/drumsergio/telegram-archive-viewer + +# Notes + +Both containers run as uid 1000, so the data folder must belong to that user: `sudo chown -R 1000:1000 ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/telegram-archive`. Log in to Telegram once before the first start with `docker compose run --rm telegram-backup python -m telegram_archive auth`; it asks for the code Telegram sends you. The viewer is on port 8000. diff --git a/examples/telegram-archive/docker-compose.yml b/examples/telegram-archive/docker-compose.yml index 2d85bae9e..c893a3f2f 100644 --- a/examples/telegram-archive/docker-compose.yml +++ b/examples/telegram-archive/docker-compose.yml @@ -1,12 +1,10 @@ services: telegram-backup: - image: drumsergio/telegram-archive:latest + image: drumsergio/telegram-archive:9.3.2 container_name: telegram-backup restart: unless-stopped - command: ["python", "-m", "src", "schedule"] - expose: - - 8000 + command: ["python", "-m", "telegram_archive", "schedule"] volumes: - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/telegram-archive:/data environment: @@ -15,8 +13,8 @@ services: TELEGRAM_API_HASH: ${TELEGRAM_API_HASH} TELEGRAM_PHONE: ${TELEGRAM_PHONE} SESSION_NAME: ${SESSION_NAME:-telegram_backup} - # Backup schedule (cron format) - SCHEDULE: ${SCHEDULE:-0 */6 * * *} + # Full pass schedule (cron format). Empty means one pass a day; new messages are saved as they arrive. + SCHEDULE: ${SCHEDULE:-} # Backup settings BACKUP_PATH: /data/backups DOWNLOAD_MEDIA: ${DOWNLOAD_MEDIA:-true} @@ -26,16 +24,9 @@ services: # Database DB_TYPE: ${DB_TYPE:-sqlite} DB_PATH: /data/backups/telegram_backup.db - #networks: - # - proxy - #labels: - # - traefik.enable=true - # - traefik.docker.network=proxy - # - traefik.http.routers.telegram-backup.rule=Host(`telegram.example.com`) - # - traefik.http.services.telegram-backup.loadbalancer.server.port=8000 telegram-viewer: - image: drumsergio/telegram-archive-viewer:latest + image: drumsergio/telegram-archive-viewer:9.3.2 container_name: telegram-viewer restart: unless-stopped ports: From 861d30e8067de1e066c1d81e8dcc26dd7d648478 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Sat, 10 Oct 2026 21:59:12 +0200 Subject: [PATCH 3/4] LynxPrompt: fix the example so it starts and users can sign in Postgres 18 refused the mount at /var/lib/postgresql/data, the image was :latest, and no SMTP settings were passed, so nobody could get a sign-in link. One Postgres now holds the four databases, the image is pinned to 2.1.39, the SMTP settings are required, and a sample .env lets the compose check run. --- examples/lynxprompt/.env | 12 +++ examples/lynxprompt/README.md | 2 +- examples/lynxprompt/docker-compose.yml | 139 ++++++++----------------- 3 files changed, 55 insertions(+), 98 deletions(-) create mode 100644 examples/lynxprompt/.env diff --git a/examples/lynxprompt/.env b/examples/lynxprompt/.env new file mode 100644 index 000000000..abf2f2026 --- /dev/null +++ b/examples/lynxprompt/.env @@ -0,0 +1,12 @@ +# Change these settings +APP_URL=https://lynxprompt.example.com +NEXTAUTH_SECRET= +POSTGRES_PASSWORD= +SUPERADMIN_EMAIL=admin@example.com + +# Sign-in links go out by mail +SMTP_HOST=smtp.example.com +SMTP_PORT=587 +SMTP_USER=lynxprompt@example.com +SMTP_PASSWORD= +SMTP_FROM=lynxprompt@example.com diff --git a/examples/lynxprompt/README.md b/examples/lynxprompt/README.md index 4c4fe66d7..4950206af 100644 --- a/examples/lynxprompt/README.md +++ b/examples/lynxprompt/README.md @@ -6,4 +6,4 @@ # Notes -LynxPrompt uses four separate PostgreSQL databases by design (app, users, blog, support) for data isolation. Generate a `NEXTAUTH_SECRET` with `openssl rand -base64 32`. +Fill in the `.env` file: generate `NEXTAUTH_SECRET` with `openssl rand -base64 32` and `POSTGRES_PASSWORD` with `openssl rand -hex 24`. Sign-in is a link sent by mail, so set the `SMTP_*` values of a real mail server (leave `SMTP_USER` and `SMTP_PASSWORD` empty if it needs no login; port 465 uses TLS). Set `SUPERADMIN_EMAIL` to your address: the first sign-in creates the account and the second makes it superadmin. Serve it over HTTPS behind your reverse proxy and set `APP_URL` to that `https://` address: the sign-in cookies are `__Host-` and `__Secure-` cookies, which browsers refuse on any plain `http://` address, `localhost` included, and sign-in then fails without an error. The app runs as uid 1001, so avatar and logo uploads need `sudo chown -R 1001:1001 ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/uploads`. diff --git a/examples/lynxprompt/docker-compose.yml b/examples/lynxprompt/docker-compose.yml index cfa780634..4bf5d1e1a 100644 --- a/examples/lynxprompt/docker-compose.yml +++ b/examples/lynxprompt/docker-compose.yml @@ -1,17 +1,13 @@ services: lynxprompt: - image: drumsergio/lynxprompt:latest + image: drumsergio/lynxprompt:2.1.39 container_name: lynxprompt + # The image is built for amd64 only; ARM hosts run it under emulation. + platform: linux/amd64 restart: unless-stopped depends_on: - postgres-app: - condition: service_healthy - postgres-users: - condition: service_healthy - postgres-blog: - condition: service_healthy - postgres-support: + postgres: condition: service_healthy ports: - 3000:3000 @@ -20,41 +16,43 @@ services: volumes: - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/uploads:/data/uploads environment: - # NextAuth (required — generate with: openssl rand -base64 32) - NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} + # NextAuth (required, generate with: openssl rand -base64 32) + NEXTAUTH_URL: ${APP_URL:-http://localhost:3000} NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:?Generate with openssl rand -base64 32} - # Databases - DB_APP_HOST: postgres-app - DB_APP_USER: lynxprompt_app - DB_APP_PASSWORD: ${POSTGRES_APP_PASSWORD:-DatabasePassword1234} - DB_APP_NAME: lynxprompt_app - DB_USERS_HOST: postgres-users - DB_USERS_USER: lynxprompt_users - DB_USERS_PASSWORD: ${POSTGRES_USERS_PASSWORD:-DatabasePassword1234} + APP_URL: ${APP_URL:-http://localhost:3000} + # Promoted to superadmin when this address signs in + SUPERADMIN_EMAIL: ${SUPERADMIN_EMAIL:-} + # Databases: one server, one database per schema; the app creates + # lynxprompt_users, lynxprompt_blog and lynxprompt_support on first start + DB_APP_HOST: postgres + DB_APP_USER: lynxprompt + DB_APP_PASSWORD: ${POSTGRES_PASSWORD:-DatabasePassword1234} + DB_APP_NAME: lynxprompt + DB_USERS_HOST: postgres + DB_USERS_USER: lynxprompt + DB_USERS_PASSWORD: ${POSTGRES_PASSWORD:-DatabasePassword1234} DB_USERS_NAME: lynxprompt_users - DB_BLOG_HOST: postgres-blog - DB_BLOG_USER: lynxprompt_blog - DB_BLOG_PASSWORD: ${POSTGRES_BLOG_PASSWORD:-DatabasePassword1234} + DB_BLOG_HOST: postgres + DB_BLOG_USER: lynxprompt + DB_BLOG_PASSWORD: ${POSTGRES_PASSWORD:-DatabasePassword1234} DB_BLOG_NAME: lynxprompt_blog - DB_SUPPORT_HOST: postgres-support - DB_SUPPORT_USER: lynxprompt_support - DB_SUPPORT_PASSWORD: ${POSTGRES_SUPPORT_PASSWORD:-DatabasePassword1234} + DB_SUPPORT_HOST: postgres + DB_SUPPORT_USER: lynxprompt + DB_SUPPORT_PASSWORD: ${POSTGRES_PASSWORD:-DatabasePassword1234} DB_SUPPORT_NAME: lynxprompt_support - # Feature flags (all optional) - ENABLE_EMAIL_AUTH: ${ENABLE_EMAIL_AUTH:-true} - ENABLE_PASSKEYS: ${ENABLE_PASSKEYS:-true} - ENABLE_USER_REGISTRATION: ${ENABLE_USER_REGISTRATION:-true} - # OAuth (optional) + # Mail (required: sign-in is a link sent by mail) + SMTP_HOST: ${SMTP_HOST:?Set the SMTP server that sends the sign-in links} + SMTP_PORT: ${SMTP_PORT:-587} + SMTP_USER: ${SMTP_USER:-} + SMTP_PASSWORD: ${SMTP_PASSWORD:-} + SMTP_FROM: ${SMTP_FROM:?Set the sender address of the sign-in mails} + UPLOAD_DIR: /data/uploads/blog + # Optional: GitHub sign-in, AI features + #ENABLE_GITHUB_OAUTH: ${ENABLE_GITHUB_OAUTH:-false} #GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-} #GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-} - #ENABLE_GITHUB_OAUTH: ${ENABLE_GITHUB_OAUTH:-false} - # AI features (optional — requires Anthropic API key) - #ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} #ENABLE_AI: ${ENABLE_AI:-false} - # Branding - APP_NAME: ${APP_NAME:-LynxPrompt} - APP_URL: ${APP_URL:-http://localhost:3000} - UPLOAD_DIR: /data/uploads/blog + #ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} #networks: # - proxy #labels: @@ -63,74 +61,21 @@ services: # - traefik.http.routers.lynxprompt.rule=Host(`lynxprompt.example.com`) # - traefik.http.services.lynxprompt.loadbalancer.server.port=3000 - postgres-app: - image: postgres:18-alpine - container_name: lynxprompt-postgres-app - restart: unless-stopped - expose: - - 5432 - volumes: - - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-app:/var/lib/postgresql/data - environment: - POSTGRES_DB: lynxprompt_app - POSTGRES_USER: lynxprompt_app - POSTGRES_PASSWORD: ${POSTGRES_APP_PASSWORD:-DatabasePassword1234} - healthcheck: - test: ["CMD-SHELL", "pg_isready -U lynxprompt_app"] - interval: 10s - timeout: 5s - retries: 5 - - postgres-users: - image: postgres:18-alpine - container_name: lynxprompt-postgres-users - restart: unless-stopped - expose: - - 5432 - volumes: - - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-users:/var/lib/postgresql/data - environment: - POSTGRES_DB: lynxprompt_users - POSTGRES_USER: lynxprompt_users - POSTGRES_PASSWORD: ${POSTGRES_USERS_PASSWORD:-DatabasePassword1234} - healthcheck: - test: ["CMD-SHELL", "pg_isready -U lynxprompt_users"] - interval: 10s - timeout: 5s - retries: 5 - - postgres-blog: - image: postgres:18-alpine - container_name: lynxprompt-postgres-blog - restart: unless-stopped - expose: - - 5432 - volumes: - - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-blog:/var/lib/postgresql/data - environment: - POSTGRES_DB: lynxprompt_blog - POSTGRES_USER: lynxprompt_blog - POSTGRES_PASSWORD: ${POSTGRES_BLOG_PASSWORD:-DatabasePassword1234} - healthcheck: - test: ["CMD-SHELL", "pg_isready -U lynxprompt_blog"] - interval: 10s - timeout: 5s - retries: 5 - - postgres-support: + postgres: image: postgres:18-alpine - container_name: lynxprompt-postgres-support + container_name: lynxprompt-postgres restart: unless-stopped expose: - 5432 volumes: - - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/db-support:/var/lib/postgresql/data + # Postgres 18 keeps its data one level up and refuses a mount at /var/lib/postgresql/data + - ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/postgres:/var/lib/postgresql environment: - POSTGRES_DB: lynxprompt_support - POSTGRES_USER: lynxprompt_support - POSTGRES_PASSWORD: ${POSTGRES_SUPPORT_PASSWORD:-DatabasePassword1234} + POSTGRES_DB: lynxprompt + POSTGRES_USER: lynxprompt + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-DatabasePassword1234} healthcheck: - test: ["CMD-SHELL", "pg_isready -U lynxprompt_support"] + test: ["CMD-SHELL", "pg_isready -U lynxprompt -d lynxprompt"] interval: 10s timeout: 5s retries: 5 From a6eb44487267f9d64e5b367fa899129216f39df1 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Sat, 10 Oct 2026 23:12:32 +0200 Subject: [PATCH 4/4] LynxPrompt: run 2.1.40, which signs in over plain http 2.1.40 picks its auth cookies from the scheme of APP_URL, so the example works on http://localhost:3000 or a LAN address without a TLS proxy, and SUPERADMIN_EMAIL takes effect on the first sign-in. The notes drop the HTTPS-only caveat. --- examples/lynxprompt/.env | 2 +- examples/lynxprompt/README.md | 2 +- examples/lynxprompt/docker-compose.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/lynxprompt/.env b/examples/lynxprompt/.env index abf2f2026..cd86e3866 100644 --- a/examples/lynxprompt/.env +++ b/examples/lynxprompt/.env @@ -1,5 +1,5 @@ # Change these settings -APP_URL=https://lynxprompt.example.com +APP_URL=http://localhost:3000 NEXTAUTH_SECRET= POSTGRES_PASSWORD= SUPERADMIN_EMAIL=admin@example.com diff --git a/examples/lynxprompt/README.md b/examples/lynxprompt/README.md index 4950206af..e0a76ef22 100644 --- a/examples/lynxprompt/README.md +++ b/examples/lynxprompt/README.md @@ -6,4 +6,4 @@ # Notes -Fill in the `.env` file: generate `NEXTAUTH_SECRET` with `openssl rand -base64 32` and `POSTGRES_PASSWORD` with `openssl rand -hex 24`. Sign-in is a link sent by mail, so set the `SMTP_*` values of a real mail server (leave `SMTP_USER` and `SMTP_PASSWORD` empty if it needs no login; port 465 uses TLS). Set `SUPERADMIN_EMAIL` to your address: the first sign-in creates the account and the second makes it superadmin. Serve it over HTTPS behind your reverse proxy and set `APP_URL` to that `https://` address: the sign-in cookies are `__Host-` and `__Secure-` cookies, which browsers refuse on any plain `http://` address, `localhost` included, and sign-in then fails without an error. The app runs as uid 1001, so avatar and logo uploads need `sudo chown -R 1001:1001 ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/uploads`. +Fill in the `.env` file: generate `NEXTAUTH_SECRET` with `openssl rand -base64 32` and `POSTGRES_PASSWORD` with `openssl rand -hex 24`. Sign-in is a link sent by mail, so set the `SMTP_*` values of a real mail server (leave `SMTP_USER` and `SMTP_PASSWORD` empty if it needs no login; port 465 uses TLS). Set `APP_URL` to the address you open it on, `http://` or `https://`, and `SUPERADMIN_EMAIL` to your address to become superadmin on your first sign-in. The app runs as uid 1001, so avatar and logo uploads need `sudo chown -R 1001:1001 ${DOCKER_VOLUME_STORAGE:-/mnt/docker-volumes}/lynxprompt/uploads`. diff --git a/examples/lynxprompt/docker-compose.yml b/examples/lynxprompt/docker-compose.yml index 4bf5d1e1a..e7181c4e6 100644 --- a/examples/lynxprompt/docker-compose.yml +++ b/examples/lynxprompt/docker-compose.yml @@ -1,7 +1,7 @@ services: lynxprompt: - image: drumsergio/lynxprompt:2.1.39 + image: drumsergio/lynxprompt:2.1.40 container_name: lynxprompt # The image is built for amd64 only; ARM hosts run it under emulation. platform: linux/amd64