From 709362b1c0b6af7ca226ccb05eeaac4b1ed99e4b Mon Sep 17 00:00:00 2001 From: Yuri Lima Date: Mon, 17 Feb 2025 09:09:51 +0000 Subject: [PATCH] Refactor Docker Compose for PostgreSQL and Redis services --- docker-compose.yaml | 49 ++++++++++++++++++++++---- fail2ban/data/db/fail2ban.sqlite3 | Bin 0 -> 73728 bytes https_portal/config/custom_nginx.conf | 41 +++++++++++++++++++++ redis.conf | 4 +++ server_custom/config.ts | 21 +++-------- 5 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 fail2ban/data/db/fail2ban.sqlite3 create mode 100644 https_portal/config/custom_nginx.conf create mode 100644 redis.conf diff --git a/docker-compose.yaml b/docker-compose.yaml index c0e9eb8..de0cc37 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -16,6 +16,8 @@ services: - "POSTGRES_PASSWORD=${POSTGRES_PASSWORD}" volumes: - "./database:/var/lib/postgresql/data" + - "./database/pg_hba.conf:/etc/postgresql/pg_hba.conf" # Correct location + command: ["postgres", "-c", "hba_file=/etc/postgresql/pg_hba.conf"] # ✅ Tell PostgreSQL where to find it healthcheck: test: - CMD-SHELL @@ -128,8 +130,8 @@ services: phoenix-redis: image: 'bitnami/redis:latest' container_name: redis - command: /opt/bitnami/scripts/redis/run.sh --maxmemory 100mb - user: root + command: /opt/bitnami/scripts/redis/run.sh --maxmemory 100mb --dir /bitnami/redis/data + user: 1001:1001 # Non-root user in Bitnami images The /bitnami/redis/data directory inside the container is already owned by 1001, avoiding permission issues. networks: - backend restart: always @@ -139,13 +141,22 @@ services: 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 volumes: - "./redis/data:/bitnami/redis/data" + - /opt/phx/redis/tmp:/opt/bitnami/redis/tmp # ✅ Fix permission issue + - /opt/phx/redis/logs:/opt/bitnami/redis/logs # ✅ Fix logs permission issue + - ./redis.conf:/opt/bitnami/redis/etc/redis.conf # ✅ Use a writable redis.conf + depends_on: + postgres: + condition: service_healthy node_exporter: image: quay.io/prometheus/node-exporter:latest container_name: node_exporter - network_mode: host - pid: host + networks: + - metrics restart: unless-stopped ports: - "9100:9100" @@ -162,7 +173,6 @@ services: container_name: https_portal image: "steveltn/https-portal:1.21" restart: unless-stopped - user: "root" networks: - frontend # [ PgAdmin, Phoenix-App ] - external # [ Outside of the World] @@ -181,25 +191,50 @@ services: 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: - phoenix-app - phoenix-system - pgadmin - phoenix-redis - postgres - + 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 external: driver: bridge - external: true + external: false + + metrics: + driver: bridge + external: false + ipam: + config: + - subnet: 172.22.0.0/16 volumes: pgadmin: null diff --git a/fail2ban/data/db/fail2ban.sqlite3 b/fail2ban/data/db/fail2ban.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..8164bae465d88f70242d4ad6cad1457439ec5028 GIT binary patch literal 73728 zcmeI)&u-&H9KdnAf1I{yl6IxYLL8WtK&>Uil3maWp_K@YTgs*>nyZ|>i@*3Q@@*rH8nIuk}P+%oa*4L_Id&d4{=JOl79i{ErvuYRxqSL>* z_9OAg*fC7g_(%xDF!FM}C)eqclRInE1GzQl_V3!w8}EE~o-6!f>~8*K6n-tdR(P5J zJ@;e&=lu7%&vV)B_p-lbf5@I}y`6n?^AC9n3jzorfB*srAb@}tc)V-buNTdeu-6X0 zy$A=xRya_bdk1x|-0;M4t>QfwlL~QK)4TiOz^U$7wo^32*@aPf9rQaFeovjfyL^3I zABTxcoKcj|*u|px@@eE>bORMZt%XUHM)~8aH+^f-@SZnB?NqMKYSk5A`eApmERHNY z(D07D`rP@lg{u1RYcBh@y=bXQw1bX++l@rY6>UHA#iwVdHCKFAKRzkf&&5;kT#}4i z;<)1QwC)`r)pW6HoFnSqp;z~62i}=(?Qp;6Uk8qG_6nB$VbL@+;_&OP{DHaU-$s3X z+|ueL^}6#oH=icIr_&@i`6TnWLi@^Hm8PR@%YLh9UXIhG>Q#$WlI4DG`RYk+96}wt zLI%3bX6z4&=4gE(QY<}*xqU~>`STW{$5qa#u{9nB+3_%tZB*^dCWnD6*;nmaOnNxb zC9a4AE+x_x|6lh1dzw!+^}X_yrt9{!Etx*t7oi#F9EOQ(m*|`?h(m?bRS0w$#0>_tq2ovr5IUkH)wC)k?;;ZFBTM z^Xm%zvYJT1?1E$lCJwF$dg@8pj+v(qL#n1Xj%zb4|_v<%j+(2q1s}0tg_000IagfB*srAdq5#E!8*X|0&KeT|)o? z1Q0*~0R#|0009ILK)^7V|1$~@KmY**5I_I{1Q0*~0R#|8zW~4gpZ*-vLj({&009IL zKmY**5I_I{1o-@)F@OL92q1s}0tg_000IagfI#{MnE$6g$Mg^Z1Q0*~0R#|0009IL zKmY;e|BL|y5I_I{1Q0*~0R#|0009KjFTngi{W+$G2q1s}0tg_000IagfB*sr@c;i9 z0|+3100IagfB*srAbwd400IagfB*srAb#n d1(^S*KgaYC0R#|0009ILKmY**5I_KdzX0LI5jFq- literal 0 HcmV?d00001 diff --git a/https_portal/config/custom_nginx.conf b/https_portal/config/custom_nginx.conf new file mode 100644 index 0000000..56800e5 --- /dev/null +++ b/https_portal/config/custom_nginx.conf @@ -0,0 +1,41 @@ +# /https_portal/config/custom_nginx.conf +server { + listen 80; + server_name yuri.phx-erp.de; + + # Rate limiting + limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m; + + # Global security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; + + # Enable DDoS protection + client_body_timeout 10s; + client_header_timeout 10s; + keepalive_timeout 5s 5s; + send_timeout 10s; + + # IP blocking for repeated failed attempts + geo $bad_user { + default 0; + include /etc/nginx/conf.d/blocked_ips.conf; + } + + # Block suspicious requests + map $http_user_agent $bad_bot { + default 0; + ~*(curl|wget|python|nikto|sqlmap) 1; + } + + location / { + proxy_pass http://phoenix-app; + 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; + } +} \ No newline at end of file diff --git a/redis.conf b/redis.conf new file mode 100644 index 0000000..6ec37a6 --- /dev/null +++ b/redis.conf @@ -0,0 +1,4 @@ + +rename-command FLUSHDB "" +rename-command FLUSHALL "" +rename-command CONFIG "" diff --git a/server_custom/config.ts b/server_custom/config.ts index e3cb748..ff99a53 100644 --- a/server_custom/config.ts +++ b/server_custom/config.ts @@ -9,8 +9,6 @@ import { EmailPlugin, FileBasedTemplateLoader, defaultEmailHandlers } from '@pho import { BillBeePlugin } from "@phoenix/bill-bee-plugin"; import { ChannelPilotProPlugin } from "@phoenix/channel-pilot-pro-plugin"; import { ShopifyPlugin } from '@phoenix/shopify-plugin'; -//import { BonnAPIPlugin } from '../plugins/bonn-api-plugin/bonn-api-plugin.module'; -// import { DefaultJobQueuePlugin } from '@phoenix/system_service'; /** * Config settings used during development @@ -89,7 +87,9 @@ export const customConfig: SystemConfig = { port: 5002, assetUrlPrefix: "\\remote-assets\\" // to make it relative for client }), - DefaultJobQueuePlugin.init({}), + DefaultJobQueuePlugin.init({ + useDatabaseForBuffer: true + }), EmailPlugin.init({ sendRealEmails: true, route: 'mailbox', @@ -128,20 +128,7 @@ export const customConfig: SystemConfig = { } }), ShopifyPlugin.init({ - active: process.env.SHOPIFY_ACTIVE === 'true', - connectionInfo: { - url: process.env.SHOPIFY_HOST_NAME, - apiKey: process.env.SHOPIFY_API_KEY, - apiSecretKey: process.env.SHOPIFY_API_SECRET, - token: process.env.SHOPIFY_TOKEN, - // scopes: process.env.SHOPIFY_SCOPES.split(','), - hostName: process.env.SHOPIFY_HOST_NAME, - hostScheme: process.env.SHOPIFY_HOST_SCHEME === 'https' ? 'https' : 'http', - isEmbeddedApp: process.env.SHOPIFY_IS_EMBEDDED_APP === 'true', - header: { - 'X-Shopify-Access-Token': process.env.SHOPIFY_TOKEN, - } - } + active: process.env.SHOPIFY_ACTIVE === 'true' }), // DefaultStoragePlaceRankPlugin.init({}) // new DefaultSearchPlugin(),