diff --git a/.env b/.env index 0b84298..9a2ad92 100644 --- a/.env +++ b/.env @@ -7,6 +7,10 @@ DB_NAME="phoenix" DB_HOST="phoenixDB" DB_PORT=5432 DB_USERNAME="postgres" +PHX_SYSTEM_CONNECTION_POOL_MAX=5 +PHX_WORKER_CONNECTION_POOL_MAX=2 +# ===== PGADMIN CONFIGURATION ===== +PGADMIN_DEFAULT_EMAIL="info@phx-erp.de" PGADMIN_DEFAULT_EMAIL="info@phx-erp.de" MAIL_SERVER="mail.phx-erp.de" MAIL_PORT=465 @@ -38,3 +42,4 @@ BILL_BEE_ACTIVE='true' CHANNEL_PILOT_PRO_ACTIVE='true' # Shopify SHOPIFY_ACTIVE='true' +PHX_HOST_NAME='yuri.phx-erp.de' diff --git a/docker-compose.yaml b/docker-compose.yaml index c2b09fb..a008399 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -25,8 +25,9 @@ services: timeout: 2s # Number of failures before marking as unhealthy retries: 5 # Grace period before health checks start pgadmin: + restart: always image: dpage/pgadmin4 - container_name: pgAdmin4_Ui + container_name: pgAdmin4-ui user: "5050:5050" # logging: # driver: loki @@ -90,7 +91,7 @@ services: phoenix-app: restart: always image: "yurimatoslima/phoenix-frontend:alpha" - container_name: phoenixApp + container_name: phoenix-app ports: - "3000:3000" # Restrict to only allow access from Grafana Server IP # logging: @@ -111,7 +112,7 @@ services: pgadmin: condition: service_healthy healthcheck: - test: ["CMD", "wget", "--spider", "-q", "http://phoenixApp/login"] # localhost checks that the NGINX server inside the container is serving something at the root + test: ["CMD", "wget", "--spider", "-q", "http://phoenix-app/login"] # localhost checks that the NGINX server inside the container is serving something at the root interval: 10s # check every 10 seconds timeout: 5s # allow 5 seconds per check retries: 5 # mark as unhealthy after 5 failures @@ -135,6 +136,7 @@ services: - "REDIS_PASSWORD=${REDIS_PASSWORD}" - RUN_JOB_QUEUE=${RUN_JOB_QUEUE} - NODE_ENV=${NODE_ENV} + - PHX_HOST_NAME=${PHX_HOST_NAME} command: ["npm", "run", "start:server"] deploy: replicas: ${PHOENIX_SYSTEM_REPLICAS} #change here if u want to have more replicas. Cant find a way to set via variable right now @@ -180,6 +182,8 @@ services: - "SUPER_ADMIN_USER_PASSWORD=${SUPER_ADMIN_USER_PASSWORD}" - REDIS_PASSWORD=${REDIS_PASSWORD} - NODE_ENV=${NODE_ENV} + - PHX_HOST_NAME=${PHX_HOST_NAME} + command: ['npm', 'run', 'start:worker'] depends_on: phoenix-system: condition: service_healthy @@ -318,7 +322,7 @@ services: # ports: # - "9113:9113" # Restrict to only allow access from Grafana Server IP # command: - # - '--nginx.scrape-uri=http://phoenixApp/stub_status' + # - '--nginx.scrape-uri=http://phoenix-app/stub_status' # security_opt: # - no-new-privileges:true # deploy: diff --git a/docker-compose.yaml.bak b/docker-compose.yaml.bak new file mode 100644 index 0000000..876982c --- /dev/null +++ b/docker-compose.yaml.bak @@ -0,0 +1,430 @@ +--- +services: + postgres-auto-upgrade: + image: alpine:3.19 + container_name: postgres_auto_upgrade + working_dir: /opt/phx + volumes: + - .:/opt/phx:rw + - /var/run/docker.sock:/var/run/docker.sock + entrypoint: > + sh -c " + apk add --no-cache bash coreutils grep sed findutils curl docker-cli dos2unix && + mkdir -p ~/.docker/cli-plugins && + curl -SL https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose && + chmod +x ~/.docker/cli-plugins/docker-compose && + chmod +x ./postgres_upgrade.sh && + ./postgres_upgrade.sh" + restart: "no" + depends_on: [] + network_mode: bridge + postgres: + restart: always + image: "postgres:18beta1-bookworm" + container_name: phoenixDB # Hostname + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-postgres,env=prod" + networks: + - backend + environment: + DEBUG: true + POSTGRES_DB: ${DB_NAME} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - "./database:/var/lib/postgresql/data" + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U postgres" ] + interval: 5s # Time between each health check + timeout: 2s # Number of failures before marking as unhealthy + retries: 5 # Grace period before health checks start + pgadmin: + restart: always + image: dpage/pgadmin4 + container_name: pgAdmin4-ui + user: "5050:5050" + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-pgadmin,env=prod" + networks: + - backend + - frontend + environment: + PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL} + PGADMIN_DEFAULT_PASSWORD: ${SUPER_ADMIN_USER_PASSWORD} + PGADMIN_CONFIG_SERVER_MODE: 'True' + PGADMIN_CONFIG_WSGI_SCRIPT_NAME: "'/pgadmin4'" + PGADMIN_CONFIG_PROXY_X_PROTO_COUNT: 1 + PGADMIN_SERVER_JSON_FILE: '/var/lib/pgadmin/servers.json' + PGADMIN_REPLACE_SERVERS_ON_STARTUP: 'True' + PGADMIN_CONFIG_DATA_DIR: "'/var/lib/pgadmin'" + PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False' + + # pgpass dynamic vars + PGPASSFILE: /var/lib/pgadmin/pgpass + PGPASS_HOST: ${DB_HOST} + PGPASS_PORT: ${DB_PORT} + PGPASS_DB: ${DB_NAME} + PGPASS_USER: ${DB_USERNAME} + PGPASS_PASSWORD: ${POSTGRES_PASSWORD} + + # Other config + ALLOW_SAVE_PASSWORD: 'False' + MFA_ENABLED: 'True' + MFA_FORCE_REGISTRATION: 'False' + MFA_SUPPORTED_METHODS: 'email' + MFA_EMAIL_SUBJECT: 'Your MFA code by PHX-ERP' + MAX_LOGIN_ATTEMPTS: 5 + ENHANCED_COOKIE_PROTECTION: 'True' + SHOW_GRAVATAR_IMAGE: 'True' + SECURITY_EMAIL_SENDER: ${SECURITY_EMAIL_SENDER} + MAIL_SERVER: ${MAIL_SERVER} + MAIL_PORT: ${MAIL_PORT} + MAIL_USE_SSL: 'False' + MAIL_USE_TLS: 'False' + MAIL_USERNAME: ${MAIL_USERNAME} + MAIL_PASSWORD: ${MAIL_PASSWORD} + MAIL_DEBUG: 'False' + volumes: + - ./pgadmin/data:/var/lib/pgadmin + - ./pgadmin/pgadmin-entrypoint.sh:/docker-entrypoint.sh:ro + entrypoint: ["/bin/sh", "/docker-entrypoint.sh"] + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "-O", "-", "http://localhost:80/misc/ping"] + interval: 15s + timeout: 10s + retries: 5 + start_period: 60s + phoenix-app: + restart: always + image: "yurimatoslima/phoenix-frontend:alpha" + container_name: phoenix-app + ports: + - "3000:3000" # Restrict to only allow access from Grafana Server IP + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-app,env=prod,project=phoenix" + volumes: + - ./app_custom:/usr/share/nginx/html/assets/custom + - ./nginx/nginx.conf:/etc/nginx/nginx.conf + - ./nginx/includes:/etc/nginx/includes:ro + networks: + - backend + - frontend + depends_on: + pgadmin: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://phoenix-app/login"] # localhost checks that the NGINX server inside the container is serving something at the root + interval: 10s # check every 10 seconds + timeout: 5s # allow 5 seconds per check + retries: 5 # mark as unhealthy after 5 failures + start_period: 15s # wait 15 seconds after container start before checking + phoenix-system: + restart: always + image: "yurimatoslima/phoenix-backend:alpha" + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phoenix-system,env=prod" + environment: + - "DB_HOST=phoenixDB" + - "DB_NAME=${DB_NAME}" + - "DB_PASSWORD=${POSTGRES_PASSWORD}" + - "DB_USERNAME=postgres" + - "SUPER_ADMIN_USER_PASSWORD=${SUPER_ADMIN_USER_PASSWORD}" + - "REDIS_PASSWORD=${REDIS_PASSWORD}" + - RUN_JOB_QUEUE=${RUN_JOB_QUEUE} + - NODE_ENV=${NODE_ENV} + - PHX_HOST_NAME=${PHX_HOST_NAME} + command: ["npm", "run", "start:server"] + deploy: + replicas: ${PHOENIX_SYSTEM_REPLICAS} #change here if u want to have more replicas. Cant find a way to set via variable right now + networks: + backend: + aliases: + - phoenix-system + depends_on: + postgres: + condition: service_healthy + phoenix-redis: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -s http://phoenix-system:3000/health | grep -q '\"admin-api\":{\"status\":\"up\"}' && curl -s http://phoenix-system:3000/health | grep -q '\"database\":{\"status\":\"up\"}'"] # Checks both admin-api and database status + interval: 10s # Time between each health check + timeout: 6s # Max time to wait for each check + retries: 10 # Number of failures before marking as unhealthy + start_period: 40s # Grace period before health checks start + volumes: + - "./assets:/usr/src/app/packages/dev-server/assets" + - "./server_custom:/usr/src/app/packages/dev-server/custom" + # - "./logs:/usr/src/app/packages/dev-server/logs" + phoenix-worker: + restart: always + image: "yurimatoslima/phoenix-backend:alpha" + container_name: "phoenix-worker" + ports: + - "3001:3001" # Restrict to only allow access from Grafana Server IP + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-worker,env=prod" + networks: + - backend + environment: + - DB_HOST=phoenixDB + - "DB_NAME=${DB_NAME}" + - "DB_PASSWORD=${POSTGRES_PASSWORD}" + - DB_USERNAME=postgres + - "SUPER_ADMIN_USER_PASSWORD=${SUPER_ADMIN_USER_PASSWORD}" + - REDIS_PASSWORD=${REDIS_PASSWORD} + - NODE_ENV=${NODE_ENV} + - PHX_HOST_NAME=${PHX_HOST_NAME} + depends_on: + phoenix-system: + condition: service_healthy + postgres: + condition: service_healthy + healthcheck: + test: [ "CMD-SHELL", "curl -s http://phoenix-worker:3001/health | grep -q '\"status\":\"ok\"'" ] # Check if worker responds with status ok + interval: 10s # Time between each health check + timeout: 6s # Max time to wait for each check + retries: 20 # Grace period before health checks start + start_period: 30s # Grace period before health checks start + volumes: + - "./assets:/usr/src/app/packages/dev-server/assets" + - "./server_custom:/usr/src/app/packages/dev-server/custom" + # - "./logs:/usr/src/app/packages/dev-server/logs" + phoenix-redis: + image: 'bitnami/redis:latest' + container_name: redis + command: /opt/bitnami/scripts/redis/run.sh --maxmemory 100mb + user: root + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-redis,env=prod" + networks: + - backend + restart: always + environment: + ALLOW_EMPTY_PASSWORD: "no" + REDIS_PASSWORD: ${REDIS_PASSWORD} + healthcheck: + test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ] + interval: 5s + retries: 10 # Increase retries if Redis takes a while to start + timeout: 5s # Increase timeout if needed + depends_on: + postgres: + condition: service_healthy + volumes: + - "./redis/data:/bitnami/redis/data" + phoenix-health-exporter: + image: phxerp/phoenix-health-exporter:alpha + container_name: health_exporter + restart: unless-stopped + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-health-exporter,env=prod" + ports: + - "9800:9800" + environment: + DB_HOST: ${DB_HOST} + DB_NAME: ${DB_NAME} + DB_PASSWORD: ${POSTGRES_PASSWORD} + DB_USERNAME: ${DB_USERNAME} + networks: + - frontend + - backend + volumes: + - /etc/hostname:/etc/host_hostname:ro # This ensures the container always uses the real machine hostname, even if restarted or recreated. + security_opt: + - no-new-privileges:true + deploy: + resources: + limits: + cpus: '0.25' + memory: 128M + depends_on: + phoenix-system: + condition: service_healthy + phoenix-worker: + condition: service_healthy + postgres: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:9800/healthz || exit 1"] + interval: 1m + timeout: 5s + retries: 3 + start_period: 15s + node-exporter: + image: quay.io/prometheus/node-exporter:latest + container_name: node_exporter + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-node-exporter,env=prod" + networks: + - metrics + - frontend + restart: unless-stopped + ports: + - "9100:9100" # Restrict to only allow access from Grafana Server IP + command: + - "--path.procfs=/host/proc" + - "--path.sysfs=/host/sys" + - "--path.rootfs=/host" + - "--collector.filesystem.ignored-mount-points=^/(sys|proc|dev)($$|/)" + volumes: + - "/proc:/host/proc:ro" + - "/sys:/host/sys:ro" + - "/:/host:ro,rslave" + security_opt: + - no-new-privileges:true + deploy: + resources: + limits: + cpus: '0.25' + memory: 128M + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:9100/metrics"] + interval: 15s + timeout: 5s + retries: 3 + start_period: 20s + # nginx-exporter: + # image: nginx/nginx-prometheus-exporter:1.4.2 + # container_name: nginx_exporter + # restart: unless-stopped + # # logging: + # # driver: loki + # # options: + # # loki-url: "${LOKI_URL}" + # # loki-retries: "${LOKI_RETRIES}" + # # loki-batch-size: "${LOKI_BATCH_SIZE}" + # # loki-external-labels: "service=phx-nginx-exporter,env=prod" + # ports: + # - "9113:9113" # Restrict to only allow access from Grafana Server IP + # command: + # - '--nginx.scrape-uri=http://phoenix-app/stub_status' + # security_opt: + # - no-new-privileges:true + # deploy: + # resources: + # limits: + # cpus: '0.25' + # memory: 128M + # depends_on: + # phoenix-app: + # condition: service_healthy + # networks: + # - frontend + # - metrics + # healthcheck: + # test: ["CMD", "wget", "-qO-", "http://localhost:9113/metrics"] # Not working as expected + # interval: 15s + # timeout: 5s + # retries: 3 + # start_period: 10s + https_portal: + container_name: https_portal + image: "steveltn/https-portal:1.21" + restart: unless-stopped + # logging: + # driver: loki + # options: + # loki-url: "${LOKI_URL}" + # loki-retries: "${LOKI_RETRIES}" + # loki-batch-size: "${LOKI_BATCH_SIZE}" + # loki-external-labels: "service=phx-https-portal,env=prod" + networks: + - frontend # [ PgAdmin, Phoenix-App ] + ports: + - "80:80" + - "443:443" + # - host:container + environment: + STAGE: "production" # Use Let's Encrypt production server + WEBSOCKET: "true" # Enable websocket support + DEBUG: "true" + RENEW_MARGIN_DAYS: 30 + CLIENT_MAX_BODY_SIZE: 0 + SERVER_NAMES_HASH_BUCKET_SIZE: 128 # Increase hash bucket size for server names - good for bigger domains names, if not set correctly, it will throw an error, break the container. + # FORCE_RENEW: 'true' + DOMAINS: "${HTTPS_PORTAL_DOMAINS}" + volumes: + - ./https_portal/data:/var/lib/https-portal # ssl_certs, vhost.d, htdocs + - ./https_portal/log:/var/log/nginx # nginx logs + # - ./https_portal/config/custom_nginx.conf:/opt/custom_nginx.conf:ro # ✅ Mount file in a safe path + depends_on: + pgadmin: + condition: service_healthy + postgres: + condition: service_healthy + fail2ban: + image: crazymax/fail2ban:latest + container_name: fail2ban + network_mode: 'host' + cap_add: + - NET_ADMIN + - NET_RAW + volumes: + - ./fail2ban/data:/data + - ./fail2ban/jail.d:/etc/fail2ban/jail.d + - /var/log:/var/log:ro + restart: always + +networks: + backend: + driver: bridge + external: false + ipam: + config: + - subnet: 172.19.0.0/16 + + frontend: + driver: bridge + external: false + ipam: + config: + - subnet: 172.20.0.0/16 + + metrics: + driver: bridge + external: false + ipam: + config: + - subnet: 172.22.0.0/16 diff --git a/helper.md b/helper.md index cb4046e..b9f5f2e 100644 --- a/helper.md +++ b/helper.md @@ -1 +1,5 @@ -docker exec -it phx-phoenix-system-1 sh \ No newline at end of file +docker exec -it phx-phoenix-system-1 sh + +rm -rf https_portal/data https_portal/log + +docker exec -i phoenixDB psql -U postgres -d phoenix < migration.sql \ No newline at end of file diff --git a/migration.sql b/migration.sql new file mode 100644 index 0000000..e69de29 diff --git a/nginx/includes/pgadmin.conf b/nginx/includes/pgadmin.conf index 8a83459..9a73011 100644 --- a/nginx/includes/pgadmin.conf +++ b/nginx/includes/pgadmin.conf @@ -1,6 +1,6 @@ # pgAdmin reverse proxy (under subpath) location /pgadmin4 { - proxy_pass http://pgAdmin4_Ui/; + proxy_pass http://pgadmin4-ui/; proxy_set_header X-Script-Name /pgadmin4; proxy_set_header X-Scheme $scheme; proxy_set_header X-Forwarded-Proto $forwarded_proto; @@ -12,4 +12,7 @@ location /pgadmin4 { proxy_set_header X-Forwarded-Proto $forwarded_proto; # End of headers proxy_redirect off; + + # ⚠️ Rewrite required to remove /pgadmin4 from the path + rewrite ^/pgadmin4(/.*)$ $1 break; } \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf index c7b219b..d2b45a6 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -140,6 +140,11 @@ http { proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $forwarded_proto; # End of headers + # Increase timeout settings for file uploads + proxy_connect_timeout 600; + proxy_send_timeout 600; + proxy_read_timeout 600; + send_timeout 600; } location /admin-api { @@ -298,6 +303,11 @@ http { proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $forwarded_proto; # End of headers + # Increase timeout settings for file uploads + proxy_connect_timeout 600; + proxy_send_timeout 600; + proxy_read_timeout 600; + send_timeout 600; } location /admin-api {