diff --git a/blueprints/cloudflared/template.toml b/blueprints/cloudflared/template.toml index 7d2557cc..2b4d5239 100644 --- a/blueprints/cloudflared/template.toml +++ b/blueprints/cloudflared/template.toml @@ -1,6 +1,7 @@ variables = {} [config] +isolated = false domains = [] mounts = [] diff --git a/blueprints/cyberchef/cyberchef.png b/blueprints/cyberchef/cyberchef.png new file mode 100644 index 00000000..4a3dfc32 Binary files /dev/null and b/blueprints/cyberchef/cyberchef.png differ diff --git a/blueprints/cyberchef/cyberchef.svg b/blueprints/cyberchef/cyberchef.svg deleted file mode 100644 index 84258252..00000000 Binary files a/blueprints/cyberchef/cyberchef.svg and /dev/null differ diff --git a/blueprints/frappe-lending/docker-compose.yml b/blueprints/frappe-lending/docker-compose.yml new file mode 100644 index 00000000..60972a3b --- /dev/null +++ b/blueprints/frappe-lending/docker-compose.yml @@ -0,0 +1,550 @@ +x-custom-image: &custom_image + image: ${IMAGE_NAME:-frappe/erpnext}:${VERSION:-v15} + pull_policy: ${PULL_POLICY:-always} + deploy: + restart_policy: + condition: always + +services: + backend: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + echo "Waiting for site to be ready..."; + export start=`date +%s`; + while [ ! -f "sites/sites.txt" ] || [ ! -d "sites/${SITE_NAME}" ] || [ ! -f "sites/${SITE_NAME}/site_config.json" ]; do + echo "Waiting for site ${SITE_NAME} to be created and ready..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for site to be ready"; + echo "Checking sites directory:"; + ls -la sites/ || echo "sites directory not found"; + echo "Checking sites.txt:"; + cat sites/sites.txt 2>/dev/null || echo "sites.txt not found"; + break; + fi + done; + if [ -f "sites/sites.txt" ] && [ -d "sites/${SITE_NAME}" ] && [ -f "sites/${SITE_NAME}/site_config.json" ]; then + echo "Site ${SITE_NAME} is ready!"; + echo "sites.txt contents:"; + cat sites/sites.txt; + echo "Verifying site is accessible via bench..."; + bench --site ${SITE_NAME} list-apps > /dev/null 2>&1 && echo "Site is accessible via bench" || echo "Warning: Site accessibility check via bench failed"; + echo "Site directory structure:"; + ls -la sites/${SITE_NAME}/ | head -10; + if [ -n "${MAIN_DOMAIN}" ]; then + echo "Updating host_name and SSL settings to https://${MAIN_DOMAIN} (ensuring correct domain for emails)..."; + bench --site ${SITE_NAME} set-config host_name "https://${MAIN_DOMAIN}" || echo "Warning: Could not update host_name"; + bench --site ${SITE_NAME} set-config host_url "https://${MAIN_DOMAIN}" || echo "Warning: Could not update host_url"; + bench --site ${SITE_NAME} set-config use_ssl 1 || echo "Warning: Could not set use_ssl"; + echo "Verifying configuration..."; + bench --site ${SITE_NAME} get-config host_name 2>/dev/null || echo "Could not read host_name (this is OK if site is not fully initialized)"; + echo "Clearing cache to apply new domain settings..."; + bench --site ${SITE_NAME} clear-cache || echo "Warning: Could not clear cache"; + bench --site ${SITE_NAME} clear-website-cache || echo "Warning: Could not clear website cache"; + fi; + else + echo "Warning: Site may not be fully ready, but starting backend anyway"; + fi; + echo "Starting bench serve (production-ready)"; + export PYTHONUNBUFFERED=1; + bench serve --port 8000 2>&1 | awk '!/127\.0\.0\.1.*400/ {print}' || bench serve --port 8000; + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + environment: + SITE_NAME: ${SITE_NAME} + FRAPPE_SITE_NAME_HEADER: "" + MAIN_DOMAIN: ${MAIN_DOMAIN} + depends_on: + configurator: + condition: service_completed_successfully + required: true + create-site: + condition: service_completed_successfully + required: true + healthcheck: + test: + - CMD + - wait-for-it + - '0.0.0.0:8000' + interval: 2s + timeout: 10s + retries: 30 + + frontend: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + echo "Starting Nginx with port_in_redirect fix..."; + nginx-entrypoint.sh & + NGINX_PID=$!; + sleep 3; + if [ -f /etc/nginx/conf.d/frappe.conf ]; then + if ! grep -q "port_in_redirect off" /etc/nginx/conf.d/frappe.conf; then + echo "Applying port_in_redirect fix to prevent :8080 in URLs..."; + sed -i 's/listen 8080;/listen 8080;\n port_in_redirect off;\n absolute_redirect off;/' /etc/nginx/conf.d/frappe.conf; + echo "Nginx config updated - reloading..."; + sleep 1; + nginx -s reload 2>/dev/null || echo "Nginx will use updated config on next reload"; + else + echo "Nginx config already has port_in_redirect settings"; + fi + else + echo "Warning: frappe.conf not found yet, will check again"; + sleep 2; + if [ -f /etc/nginx/conf.d/frappe.conf ]; then + if ! grep -q "port_in_redirect off" /etc/nginx/conf.d/frappe.conf; then + sed -i 's/listen 8080;/listen 8080;\n port_in_redirect off;\n absolute_redirect off;/' /etc/nginx/conf.d/frappe.conf; + nginx -s reload 2>/dev/null || true; + fi + fi + fi; + wait $NGINX_PID + depends_on: + backend: + condition: service_started + required: true + websocket: + condition: service_started + required: true + environment: + BACKEND: backend:8000 + FRAPPE_SITE_NAME_HEADER: "" + SOCKETIO: websocket:9000 + UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1 + UPSTREAM_REAL_IP_HEADER: X-Forwarded-For + UPSTREAM_REAL_IP_RECURSIVE: "off" + USE_X_FORWARDED_HOST: "1" + PROXY_FIX: "1" + X_FORWARDED_PROTO: "https" + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + healthcheck: + test: + - CMD-SHELL + - curl -fsS http://127.0.0.1:8080/login || exit 1 + interval: 30s + timeout: 5s + retries: 3 + + queue-default: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench worker --queue default + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + + queue-long: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench worker --queue long + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + + queue-short: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench worker --queue short + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + + scheduler: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench schedule + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + websocket: + <<: *custom_image + healthcheck: + test: + - CMD + - wait-for-it + - '0.0.0.0:9000' + interval: 2s + timeout: 10s + retries: 30 + command: + - node + - /home/frappe/frappe-bench/apps/frappe/socketio.js + depends_on: + configurator: + condition: service_completed_successfully + required: true + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + configurator: + <<: *custom_image + deploy: + mode: replicated + replicas: ${CONFIGURE:-0} + restart_policy: + condition: none + entrypoint: ["bash", "-c"] + command: + - > + [[ $${REGENERATE_APPS_TXT} == "1" ]] && ls -1 apps > sites/apps.txt; + [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && exit 0; + bench set-config -g db_host $$DB_HOST; + bench set-config -gp db_port $$DB_PORT; + bench set-config -g redis_cache "redis://$$REDIS_CACHE"; + bench set-config -g redis_queue "redis://$$REDIS_QUEUE"; + bench set-config -g redis_socketio "redis://$$REDIS_QUEUE"; + bench set-config -gp socketio_port $$SOCKETIO_PORT; + environment: + DB_HOST: "${DB_HOST:-db}" + DB_PORT: "3306" + REDIS_CACHE: redis-cache:6379 + REDIS_QUEUE: redis-queue:6379 + SOCKETIO_PORT: "9000" + REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}" + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + create-site: + <<: *custom_image + deploy: + mode: replicated + replicas: ${CREATE_SITE:-0} + restart_policy: + condition: none + entrypoint: ["bash", "-c"] + command: + - > + wait-for-it -t 120 $$DB_HOST:$$DB_PORT; + wait-for-it -t 120 redis-cache:6379; + wait-for-it -t 120 redis-queue:6379; + export start=`date +%s`; + until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \ + [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \ + [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]]; + do + echo "Waiting for sites/common_site_config.json to be created"; + sleep 5; + if (( `date +%s`-start > 120 )); then + echo "could not find sites/common_site_config.json with required keys"; + exit 1 + fi + done; + echo "sites/common_site_config.json found"; + cd /home/frappe/frappe-bench; + if [ -d "sites/${SITE_NAME}" ] && [ -f "sites/${SITE_NAME}/site_config.json" ]; then + echo "Site ${SITE_NAME} already exists, skipping creation"; + bench use $${SITE_NAME} || echo "Warning: Could not set current site"; + echo "$${SITE_NAME}" > sites/sites.txt || echo "Warning: Could not update sites.txt"; + bench set-config -g default_site $${SITE_NAME} || echo "Warning: Could not set default site"; + if [ -n "$${ADMIN_PASSWORD}" ]; then + echo "Updating admin password for existing site..."; + bench --site $${SITE_NAME} set-admin-password $${ADMIN_PASSWORD} || echo "Warning: Could not update admin password (may need to be done manually)"; + fi; + if [ -n "$${MAIN_DOMAIN}" ]; then + echo "Setting host_name and SSL settings to https://${MAIN_DOMAIN} (with HTTPS)..."; + bench --site $${SITE_NAME} set-config host_name "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_name"; + bench --site $${SITE_NAME} set-config host_url "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_url"; + bench --site $${SITE_NAME} set-config use_ssl 1 || echo "Warning: Could not set use_ssl"; + echo "Clearing cache to apply new domain settings..."; + bench --site $${SITE_NAME} clear-cache || echo "Warning: Could not clear cache"; + bench --site $${SITE_NAME} clear-website-cache || echo "Warning: Could not clear website cache"; + fi; + echo "Verifying existing site is accessible..."; + bench --site $${SITE_NAME} list-apps > /dev/null 2>&1 && echo "Existing site is accessible and working" || echo "Warning: Site accessibility check failed"; + exit 0; + fi; + if [ ! -d "apps/lending" ]; then + echo "Cloning lending app..."; + git clone https://github.com/frappe/lending.git apps/lending || echo "Failed to clone lending app"; + fi; + if [ -d "apps/lending" ]; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending app"; + fi; + echo "Regenerating apps.txt to include all apps..."; + ls -1 apps > sites/apps.txt || (echo "frappe" > sites/apps.txt && echo "lending" >> sites/apps.txt); + echo "apps.txt contents:"; + cat sites/apps.txt; + bench set-mariadb-host $${DB_HOST:-db}; + bench new-site --mariadb-user-host-login-scope='%' --admin-password=$${ADMIN_PASSWORD} --db-root-username=root --db-root-password=$${DB_ROOT_PASSWORD} $${INSTALL_APP_ARGS} $${SITE_NAME}; + if [ ! -d "sites/${SITE_NAME}" ]; then + echo "ERROR: Site ${SITE_NAME} was not created successfully"; + exit 1; + fi; + echo "Site ${SITE_NAME} created successfully"; + bench use $${SITE_NAME}; + echo "Current site set to: $${SITE_NAME}"; + if [ -d "apps/lending" ]; then + echo "Installing lending app on site..."; + bench --site $${SITE_NAME} install-app lending || echo "Lending app may already be installed or failed to install"; + fi; + echo "Building assets for all apps (this ensures lending JS is available)..."; + bench build --apps lending || echo "Asset build completed"; + echo "Clearing all caches..."; + bench --site $${SITE_NAME} clear-cache || echo "Cache cleared"; + bench --site $${SITE_NAME} clear-website-cache || echo "Website cache cleared"; + echo "Creating sites.txt for site resolution..."; + echo "$${SITE_NAME}" > sites/sites.txt || echo "Warning: Could not create sites.txt"; + echo "Site registered in sites.txt:"; + cat sites/sites.txt || echo "sites.txt not found"; + echo "Verifying site directory and config exist..."; + if [ -d "sites/${SITE_NAME}" ] && [ -f "sites/${SITE_NAME}/site_config.json" ]; then + echo "Site directory and config verified successfully"; + else + echo "Warning: Site directory or config file missing"; + ls -la sites/${SITE_NAME}/ 2>/dev/null || echo "Site directory listing failed"; + fi; + echo "Setting default site in common_site_config.json..."; + bench set-config -g default_site $${SITE_NAME} || echo "Warning: Could not set default site"; + if [ -n "$${MAIN_DOMAIN}" ]; then + echo "Setting host_name and SSL settings to https://${MAIN_DOMAIN} (with HTTPS)..."; + bench --site $${SITE_NAME} set-config host_name "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_name"; + bench --site $${SITE_NAME} set-config host_url "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_url"; + bench --site $${SITE_NAME} set-config use_ssl 1 || echo "Warning: Could not set use_ssl"; + echo "Clearing cache to apply new domain settings..."; + bench --site $${SITE_NAME} clear-cache || echo "Warning: Could not clear cache"; + bench --site $${SITE_NAME} clear-website-cache || echo "Warning: Could not clear website cache"; + fi; + echo "Verifying site is accessible..."; + bench --site $${SITE_NAME} list-apps > /dev/null 2>&1 && echo "Site is accessible and working" || echo "Warning: Site accessibility check failed"; + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + environment: + SITE_NAME: ${SITE_NAME} + MAIN_DOMAIN: ${main_domain} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + DB_HOST: ${DB_HOST:-db} + DB_PORT: "${DB_PORT:-3306}" + DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + INSTALL_APP_ARGS: ${INSTALL_APP_ARGS} + + migration: + <<: *custom_image + deploy: + mode: replicated + replicas: ${MIGRATE:-0} + restart_policy: + condition: none + entrypoint: ["bash", "-c"] + command: + - > + curl -f http://${SITE_NAME}:8080/api/method/ping || echo "Site busy" && exit 0; + bench --site all set-config -p maintenance_mode 1; + bench --site all set-config -p pause_scheduler 1; + bench --site all migrate; + bench --site all set-config -p maintenance_mode 0; + bench --site all set-config -p pause_scheduler 0; + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + db: + image: mariadb:10.6 + deploy: + mode: replicated + replicas: ${ENABLE_DB:-0} + restart_policy: + condition: always + healthcheck: + test: mysqladmin ping -h localhost --password=${DB_ROOT_PASSWORD} + interval: 1s + retries: 20 + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --skip-character-set-client-handshake + - --skip-innodb-read-only-compressed + environment: + - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + volumes: + - db-data:/var/lib/mysql + + redis-cache: + deploy: + restart_policy: + condition: always + image: redis:6.2-alpine + volumes: + - redis-cache-data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 5s + retries: 3 + + redis-queue: + deploy: + restart_policy: + condition: always + image: redis:6.2-alpine + volumes: + - redis-queue-data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 5s + retries: 3 + + redis-socketio: + deploy: + restart_policy: + condition: always + image: redis:6.2-alpine + volumes: + - redis-socketio-data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 5s + retries: 3 + +volumes: + db-data: + redis-cache-data: + redis-queue-data: + redis-socketio-data: + sites: + driver_opts: + type: "${SITE_VOLUME_TYPE}" + o: "${SITE_VOLUME_OPTS}" + device: "${SITE_VOLUME_DEV}" + apps: + diff --git a/blueprints/frappe-lending/frappe-lending.png b/blueprints/frappe-lending/frappe-lending.png new file mode 100644 index 00000000..e94e65a6 Binary files /dev/null and b/blueprints/frappe-lending/frappe-lending.png differ diff --git a/blueprints/frappe-lending/template.toml b/blueprints/frappe-lending/template.toml new file mode 100644 index 00000000..71612960 --- /dev/null +++ b/blueprints/frappe-lending/template.toml @@ -0,0 +1,29 @@ +[variables] +main_domain = "${domain}" +site_name = "frappe.lending" +db_root_password = "${password:32}" +admin_password = "${password:32}" + +[config] +env = [ + "SITE_NAME=${site_name}", + "ADMIN_PASSWORD=${admin_password}", + "DB_ROOT_PASSWORD=${db_root_password}", + "MIGRATE=1", + "ENABLE_DB=1", + "DB_HOST=db", + "CREATE_SITE=1", + "CONFIGURE=1", + "REGENERATE_APPS_TXT=1", + "INSTALL_APP_ARGS=--install-app erpnext --install-app lending", + "IMAGE_NAME=frappe/erpnext", + "VERSION=latest", + "FRAPPE_SITE_NAME_HEADER=", + "MAIN_DOMAIN=${main_domain}", +] +mounts = [] + +[[config.domains]] +serviceName = "frontend" +port = 8_080 +host = "${main_domain}" diff --git a/blueprints/go2rtc/docker-compose.yml b/blueprints/go2rtc/docker-compose.yml new file mode 100644 index 00000000..947c0feb --- /dev/null +++ b/blueprints/go2rtc/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.8" + +services: + go2rtc: + image: alexxit/go2rtc:1.9.14 + restart: unless-stopped + + # To use a local webcam, add the device to the service: + # devices: + # - /dev/video0:/dev/video0 # Adjust path if your device is at /dev/video1, etc. + + expose: + - 1984 # Web UI + - 8554 # RTSP + - 8555 # WebRTC + + environment: + - TZ=${TZ} + + volumes: + - go2rtc-config:/config + +volumes: + go2rtc-config: {} diff --git a/blueprints/go2rtc/go2rtc.png b/blueprints/go2rtc/go2rtc.png new file mode 100644 index 00000000..a9a81a3c Binary files /dev/null and b/blueprints/go2rtc/go2rtc.png differ diff --git a/blueprints/go2rtc/template.toml b/blueprints/go2rtc/template.toml new file mode 100644 index 00000000..f650f2fc --- /dev/null +++ b/blueprints/go2rtc/template.toml @@ -0,0 +1,13 @@ +[variables] +main_domain = "${domain}" + +[config] +[[config.domains]] +serviceName = "go2rtc" +port = 1984 +host = "${main_domain}" + +env = [ + "TZ=${TZ}" +] + diff --git a/blueprints/meilisearch/docker-compose.yml b/blueprints/meilisearch/docker-compose.yml index ae5ebcb1..db87310f 100644 --- a/blueprints/meilisearch/docker-compose.yml +++ b/blueprints/meilisearch/docker-compose.yml @@ -2,12 +2,11 @@ version: "3.8" services: meilisearch: - image: getmeili/meilisearch:v1.8.3 + image: getmeili/meilisearch:v1.35.1 volumes: - meili_data:/meili_data environment: MEILI_MASTER_KEY: ${MEILI_MASTER_KEY} - MEILI_ENV: ${MEILI_ENV} volumes: meili_data: diff --git a/blueprints/meilisearch/template.toml b/blueprints/meilisearch/template.toml index b1bdb5f9..5b1b94eb 100644 --- a/blueprints/meilisearch/template.toml +++ b/blueprints/meilisearch/template.toml @@ -11,5 +11,4 @@ port = 7_700 host = "${main_domain}" [config.env] -MEILI_ENV = "development" -MEILI_MASTER_KEY = "${master_key}" +MEILI_MASTER_KEY = "${master_key}" \ No newline at end of file diff --git a/blueprints/plunk/docker-compose.yml b/blueprints/plunk/docker-compose.yml index 914001cf..9991d855 100644 --- a/blueprints/plunk/docker-compose.yml +++ b/blueprints/plunk/docker-compose.yml @@ -1,58 +1,166 @@ -# IMPORTANT: Plunk requires HTTPS to work properly -# go to the "Domains" tab and enable HTTPS for your domain +# Plunk Self-Hosting Docker Compose for Dokploy +# This setup runs all Plunk services with nginx reverse proxy +# +# IMPORTANT: This template requires multiple subdomains: +# - api.yourdomain.com -> API Server +# - app.yourdomain.com -> Web Dashboard +# - www.yourdomain.com -> Landing Page +# - docs.yourdomain.com -> Documentation +# - minio.yourdomain.com -> Minio Console (optional) +# +# All domains will be automatically configured in Dokploy services: - plunk: - image: driaug/plunk - expose: - - "3000" - depends_on: - db: - condition: service_healthy - redis: - condition: service_started - environment: - REDIS_URL: ${REDIS_URL} - DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} - JWT_SECRET: ${JWT_SECRET} - AWS_REGION: ${AWS_REGION} - AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} - AWS_SES_CONFIGURATION_SET: ${AWS_SES_CONFIGURATION_SET} - APP_URI: ${APP_URI} - NEXT_PUBLIC_API_URI: ${APP_URI}/api - API_URI: ${APP_URI}/api - DISABLE_SIGNUPS: ${DISABLE_SIGNUPS} - entrypoint: ["/app/entry.sh"] - restart: unless-stopped + # ============================================ + # Infrastructure Services + # ============================================ - db: - image: postgres:alpine + postgres: + image: postgres:16-alpine + restart: unless-stopped environment: - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_DB: plunk + POSTGRES_USER: plunk + POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + test: ["CMD-SHELL", "pg_isready -U plunk"] interval: 10s + timeout: 5s retries: 5 - timeout: 10s - restart: unless-stopped - expose: - - 5432 redis: - image: redis:alpine + image: redis:7-alpine restart: unless-stopped - expose: - - 6379 + command: redis-server --appendonly yes volumes: - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + minio: + image: minio/minio:latest + restart: unless-stopped + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: ${MINIO_ROOT_USER} + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} + volumes: + - minio_data:/data + ports: + - 9000 + - 9001 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 30s + timeout: 20s + retries: 3 + + # ============================================ + # Plunk Application + # ============================================ + + plunk: + image: ghcr.io/useplunk/plunk:latest + restart: unless-stopped + environment: + # Service mode - runs all services in one container + SERVICE: all + NODE_ENV: production + + # Database + DATABASE_URL: postgresql://plunk:${DB_PASSWORD}@postgres:5432/plunk + DIRECT_DATABASE_URL: postgresql://plunk:${DB_PASSWORD}@postgres:5432/plunk + + # Redis + REDIS_URL: ${REDIS_URL} + + # Security + JWT_SECRET: ${JWT_SECRET} + + # Nginx configuration + NGINX_PORT: ${NGINX_PORT} + + # Domain configuration (subdomain-based routing) + API_DOMAIN: ${API_DOMAIN} + DASHBOARD_DOMAIN: ${DASHBOARD_DOMAIN} + LANDING_DOMAIN: ${LANDING_DOMAIN} + WIKI_DOMAIN: ${WIKI_DOMAIN} + USE_HTTPS: ${USE_HTTPS} + + # AWS SES (for sending emails) - REQUIRED + AWS_SES_REGION: ${AWS_SES_REGION} + AWS_SES_ACCESS_KEY_ID: ${AWS_SES_ACCESS_KEY_ID} + AWS_SES_SECRET_ACCESS_KEY: ${AWS_SES_SECRET_ACCESS_KEY} + SES_CONFIGURATION_SET: ${SES_CONFIGURATION_SET} + SES_CONFIGURATION_SET_NO_TRACKING: ${SES_CONFIGURATION_SET_NO_TRACKING} + + # Optional: OAuth + GITHUB_OAUTH_CLIENT: ${GITHUB_OAUTH_CLIENT} + GITHUB_OAUTH_SECRET: ${GITHUB_OAUTH_SECRET} + GOOGLE_OAUTH_CLIENT: ${GOOGLE_OAUTH_CLIENT} + GOOGLE_OAUTH_SECRET: ${GOOGLE_OAUTH_SECRET} + + # Optional: Stripe + STRIPE_SK: ${STRIPE_SK} + STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET} + STRIPE_PRICE_ONBOARDING: ${STRIPE_PRICE_ONBOARDING} + STRIPE_PRICE_EMAIL_USAGE: ${STRIPE_PRICE_EMAIL_USAGE} + STRIPE_METER_EVENT_NAME: ${STRIPE_METER_EVENT_NAME} + + # S3-compatible storage (Minio) + S3_ENDPOINT: ${S3_ENDPOINT} + S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID} + S3_ACCESS_KEY_SECRET: ${S3_ACCESS_KEY_SECRET} + S3_BUCKET: ${S3_BUCKET} + S3_PUBLIC_URL: ${S3_PUBLIC_URL} + S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE} + + # SMTP Server (for sending emails via SMTP) + SMTP_DOMAIN: ${SMTP_DOMAIN} + PORT_SECURE: ${PORT_SECURE} + PORT_SUBMISSION: ${PORT_SUBMISSION} + + # Internal + PLUNK_API_KEY: ${PLUNK_API_KEY} + PLUNK_FROM_ADDRESS: ${PLUNK_FROM_ADDRESS} + + volumes: + # Mount Traefik certificates for SSL + - /etc/dokploy/traefik/dynamic/acme.json:/certs/acme.json:ro + + ports: + # Main nginx port (handles all subdomain routing) + - 80 + # SMTP ports (for email relay) + - 465 + - 587 + + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + minio: + condition: service_healthy + + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:80/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s volumes: postgres_data: driver: local redis_data: - driver: local \ No newline at end of file + driver: local + minio_data: + driver: local + plunk_data: + driver: local diff --git a/blueprints/plunk/template.toml b/blueprints/plunk/template.toml index 831f2c47..ce92c1fe 100644 --- a/blueprints/plunk/template.toml +++ b/blueprints/plunk/template.toml @@ -1,30 +1,120 @@ [variables] -main_domain = "${domain}" -postgres_user = "plunk" -postgres_db = "plunk" +# Generate unique domains for each service +api_domain = "${domain}" +dashboard_domain = "${domain}" +landing_domain = "${domain}" +wiki_domain = "${domain}" +minio_domain = "${domain}" + +# Database credentials +postgres_password = "${password:32}" + +# Security +jwt_secret = "${password:64}" + +# Minio credentials +minio_root_user = "plunk" +minio_root_password = "${password:32}" [config] isolated = true +# API Domain [[config.domains]] serviceName = "plunk" -port = 3000 -host = "${main_domain}" +port = 80 +host = "${api_domain}" +path = "/" + +# Dashboard Domain +[[config.domains]] +serviceName = "plunk" +port = 80 +host = "${dashboard_domain}" +path = "/" + +# Landing Page Domain +[[config.domains]] +serviceName = "plunk" +port = 80 +host = "${landing_domain}" +path = "/" + +# Documentation Domain +[[config.domains]] +serviceName = "plunk" +port = 80 +host = "${wiki_domain}" +path = "/" + +# Minio Console Domain (optional) +[[config.domains]] +serviceName = "minio" +port = 9001 +host = "${minio_domain}" path = "/" [config.env] -POSTGRES_USER = "${postgres_user}" -POSTGRES_DB = "${postgres_db}" -POSTGRES_PASSWORD = "${password:32}" +# Database +DB_PASSWORD = "${postgres_password}" +# Redis REDIS_URL = "redis://redis:6379" -JWT_SECRET = "${password:64}" -APP_URI = "https://${main_domain}" +# Security +JWT_SECRET = "${jwt_secret}" -AWS_REGION = "" -AWS_ACCESS_KEY_ID = "" -AWS_SECRET_ACCESS_KEY = "" -AWS_SES_CONFIGURATION_SET = "" +# Nginx configuration +NGINX_PORT = "80" -DISABLE_SIGNUPS = "False" \ No newline at end of file +# Domain configuration (subdomain-based routing) +API_DOMAIN = "${api_domain}" +DASHBOARD_DOMAIN = "${dashboard_domain}" +LANDING_DOMAIN = "${landing_domain}" +WIKI_DOMAIN = "${wiki_domain}" +USE_HTTPS = "true" + +# AWS SES (Required - users must configure these for email to work) +AWS_SES_REGION = "us-east-1" +AWS_SES_ACCESS_KEY_ID = "" +AWS_SES_SECRET_ACCESS_KEY = "" +SES_CONFIGURATION_SET = "" + +# S3-compatible storage (Minio) +MINIO_ROOT_USER = "${minio_root_user}" +MINIO_ROOT_PASSWORD = "${minio_root_password}" +S3_ENDPOINT = "http://minio:9000" +S3_ACCESS_KEY_ID = "${minio_root_user}" +S3_ACCESS_KEY_SECRET = "${minio_root_password}" +S3_BUCKET = "uploads" +S3_PUBLIC_URL = "https://${minio_domain}/uploads" +S3_FORCE_PATH_STYLE = "true" + +# Minio ports +MINIO_API_PORT = "9000" +MINIO_CONSOLE_PORT = "9001" + +# SMTP Server ports +PORT_SECURE = "465" +PORT_SUBMISSION = "587" + +# Notifications (ntfy.sh) +NTFY_URL = "http://ntfy/plunk-notifications" + +# Optional: OAuth (leave empty if not using) +GITHUB_OAUTH_CLIENT = "" +GITHUB_OAUTH_SECRET = "" +GOOGLE_OAUTH_CLIENT = "" +GOOGLE_OAUTH_SECRET = "" + +# Optional: Stripe (leave empty if not using) +STRIPE_SK = "" +STRIPE_WEBHOOK_SECRET = "" +STRIPE_PRICE_ONBOARDING = "" +STRIPE_PRICE_EMAIL_USAGE = "" +STRIPE_METER_EVENT_NAME = "emails" + +# Internal +PLUNK_API_KEY = "" +PLUNK_FROM_ADDRESS = "" +SMTP_DOMAIN = "" \ No newline at end of file diff --git a/meta.json b/meta.json index 3ae0cb5e..8be7825d 100644 --- a/meta.json +++ b/meta.json @@ -1685,7 +1685,7 @@ "name": "CyberChef", "version": "latest", "description": "CyberChef is a web application for encryption, encoding, compression, and data analysis, developed by GCHQ.", - "logo": "cyberchef.svg", + "logo": "cyberchef.png", "links": { "github": "https://github.com/gchq/CyberChef", "website": "https://gchq.github.io/CyberChef/", @@ -2543,6 +2543,26 @@ "performace" ] }, + { + "id": "frappe-lending", + "name": "Frappe Lending", + "version": "latest", + "description": "A comprehensive loan management system built on Frappe Framework. 100% open source and customizable for managing loans, repayments, and lending operations.", + "logo": "frappe-lending.png", + "links": { + "github": "https://github.com/frappe/lending", + "docs": "https://docs.frappe.io/lending", + "website": "https://frappe.io" + }, + "tags": [ + "lending", + "finance", + "loans", + "payments", + "accounting", + "self-hosted" + ] + }, { "id": "freescout", "name": "FreeScout", @@ -2810,6 +2830,24 @@ "api" ] }, + { + "id": "go2rtc", + "name": "go2rtc", + "version": "latest", + "description": "Ultimate camera streaming application with support for dozens formats and protocols.", + "logo": "go2rtc.png", + "links": { + "github": "https://github.com/AlexxIT/go2rtc", + "website": "https://go2rtc.org/", + "docs": "https://go2rtc.org/" + }, + "tags": [ + "streaming", + "webrtc", + "video", + "home assistant" + ] + }, { "id": "gotenberg", "name": "Gotenberg", @@ -3968,7 +4006,7 @@ { "id": "meilisearch", "name": "Meilisearch", - "version": "v1.8.3", + "version": "v1.35.1", "description": "Meilisearch is a free and open-source search engine that allows you to easily add search functionality to your web applications.", "logo": "meilisearch.png", "links": { @@ -5952,24 +5990,6 @@ "media" ] }, - { - "id": "strapi", - "name": "Strapi", - "version": "v5.33.0", - "description": "Open-source headless CMS to build powerful APIs with built-in content management.", - "logo": "strapi.svg", - "links": { - "github": "https://github.com/strapi/strapi", - "discord": "https://discord.com/invite/strapi", - "docs": "https://docs.strapi.io", - "website": "https://strapi.io" - }, - "tags": [ - "headless", - "cms", - "content-management" - ] - }, { "id": "supabase", "name": "SupaBase",