From e7128e86528cf7e4eb434e378299c07a4c64cbe1 Mon Sep 17 00:00:00 2001 From: anorien90 Date: Wed, 3 Dec 2025 15:42:58 +0000 Subject: [PATCH] Initial commit --- .gitignore | 15 +++++++ README.md | 0 bin/init-letsencrypt.sh | 25 +++++++++++ config/fail2ban/filter.d/gitea.local | 4 ++ config/fail2ban/jail.d/gitea.local | 8 ++++ config/fail2ban/jail.d/nginx-bots.local | 9 ++++ config/fail2ban/jail.d/nginx-log.local | 19 ++++++++ config/nginx/conf.d/README.md | 0 config/nginx/nginx.conf | 24 ++++++++++ data/fail2ban/db/README.md | 0 data/www/html/README.md | 0 docker-compose.yml | 58 +++++++++++++++++++++++++ setup.sh | 0 13 files changed, 162 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 bin/init-letsencrypt.sh create mode 100644 config/fail2ban/filter.d/gitea.local create mode 100644 config/fail2ban/jail.d/gitea.local create mode 100644 config/fail2ban/jail.d/nginx-bots.local create mode 100644 config/fail2ban/jail.d/nginx-log.local create mode 100644 config/nginx/conf.d/README.md create mode 100644 config/nginx/nginx.conf create mode 100644 data/fail2ban/db/README.md create mode 100644 data/www/html/README.md create mode 100644 docker-compose.yml create mode 100644 setup.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f35e83f --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ + +logs/*.log + +config/nginx/conf.d/*.conf + +# Sensitive data +data/.htpasswd + +# Fail2ban database files +data/fail2ban/db/*.db + +# Certbot subdirectories +data/certbot/** + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/bin/init-letsencrypt.sh b/bin/init-letsencrypt.sh new file mode 100755 index 0000000..c799ff1 --- /dev/null +++ b/bin/init-letsencrypt.sh @@ -0,0 +1,25 @@ +#!/bin/bash +DOMAIN="apidocs.nxs.solutions" +EMAIL="info@nxs.solutions" +STAGING=0 # Set to 1 for testing (to avoid rate limits) + +# Ensure required directories exist +if [ ! -d "data/certbot/conf" ]; then + mkdir -p data/certbot/conf +fi +if [ ! -d "data/certbot/www" ]; then + mkdir -p data/certbot/www +fi + +# Run Certbot to get initial certificate +docker compose run --rm certbot certonly --webroot \ + --webroot-path=/var/www/certbot \ + --email "$EMAIL" \ + -d "$DOMAIN" -d "www.$DOMAIN" \ + --rsa-key-size 4096 \ + --agree-tos \ + --noninteractive \ + $([ "$STAGING" -eq 1 ] && echo "--staging") + +# Reload Nginx to use the new certificate +docker compose exec nginx nginx -s reload diff --git a/config/fail2ban/filter.d/gitea.local b/config/fail2ban/filter.d/gitea.local new file mode 100644 index 0000000..8450f9d --- /dev/null +++ b/config/fail2ban/filter.d/gitea.local @@ -0,0 +1,4 @@ +# gitea.local +[Definition] +failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from +ignoreregex = diff --git a/config/fail2ban/jail.d/gitea.local b/config/fail2ban/jail.d/gitea.local new file mode 100644 index 0000000..bb67ab5 --- /dev/null +++ b/config/fail2ban/jail.d/gitea.local @@ -0,0 +1,8 @@ +[gitea-docker] +enabled = true +filter = gitea +logpath = /var/log/gitea/access.log +maxretry = 10 +findtime = 3600 +bantime = 900 +action = iptables-allports[chain="FORWARD"] diff --git a/config/fail2ban/jail.d/nginx-bots.local b/config/fail2ban/jail.d/nginx-bots.local new file mode 100644 index 0000000..64b2d43 --- /dev/null +++ b/config/fail2ban/jail.d/nginx-bots.local @@ -0,0 +1,9 @@ +[nginx-badbots] +enabled = true +port = http,https +filter = nginx-error-common +logpath = /var/log/nginx/access.log +maxretry = 10 +findtime = 60 +bantime = 3600 +chain = DOCKER-USER diff --git a/config/fail2ban/jail.d/nginx-log.local b/config/fail2ban/jail.d/nginx-log.local new file mode 100644 index 0000000..c25bb07 --- /dev/null +++ b/config/fail2ban/jail.d/nginx-log.local @@ -0,0 +1,19 @@ +[nginx-http-auth] +enabled = true +port = http,https +filter = nginx-http-auth +logpath = /var/log/nginx/error.log +maxretry = 3 +findtime = 600 +bantime = 86400 +chain = DOCKER-USER + + + + + + + + + + diff --git a/config/nginx/conf.d/README.md b/config/nginx/conf.d/README.md new file mode 100644 index 0000000..e69de29 diff --git a/config/nginx/nginx.conf b/config/nginx/nginx.conf new file mode 100644 index 0000000..f1e4924 --- /dev/null +++ b/config/nginx/nginx.conf @@ -0,0 +1,24 @@ +# 1. Main global section +user nginx; +worker_processes auto; + +# 2. **REQUIRED EVENTS BLOCK** +events { + # Define how Nginx handles connections + worker_connections 1024; +} + +# 3. HTTP context (where your server blocks go) +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent"'; + sendfile on; + keepalive_timeout 65; + + resolver 127.0.0.11 valid=5s ipv6=off; + # Include your server configuration files (like develop.conf) + include /etc/nginx/conf.d/*.conf; +} diff --git a/data/fail2ban/db/README.md b/data/fail2ban/db/README.md new file mode 100644 index 0000000..e69de29 diff --git a/data/www/html/README.md b/data/www/html/README.md new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dddbce5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,58 @@ +services: + nginx: + image: nginx:latest + container_name: nginx-main + ports: + - "80:80" + - "443:443" + volumes: + - ./data/nginx.conf/:/etc/nginx/nginx.conf:ro # Nginx should only read its config + - ./data/.htpasswd:/etc/nginx/.htpasswd:ro + - ./data/conf.d/:/etc/nginx/conf.d/:ro + - ./data/certbot/www:/var/www/certbot/:ro + - ./data/certbot/conf:/etc/letsencrypt/:ro + - /prod/data/docs/:/var/www/html/docs.nxs.solutions/:ro + - ./logs/:/var/log/nginx/:rw + networks: + - fast-services + restart: always + + certbot: + image: certbot/certbot + container_name: certbot + # The container will not run automatically; it's used for one-off commands + entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $!; done;'" + volumes: + # Must be read-write for certbot to place challenge files + - ./data/certbot/www:/var/www/certbot/:rw + # Must be read-write for certbot to store and renew certificates + - ./data/certbot/conf:/etc/letsencrypt/:rw + # Only runs when explicitly called or for renewal cronjob + restart: unless-stopped + networks: + - fast-services + + fail2ban: + image: crazymax/fail2ban:latest + container_name: fail2ban + # Required for Fail2Ban to modify host firewall rules + network_mode: host + cap_add: + - NET_ADMIN + - NET_RAW + # Ensure it always restarts + restart: always + volumes: + # 1. Mount the Nginx logs from the host (Read-Only) + - ./logs:/var/log/nginx:ro + # 2. Persist Fail2Ban's configuration and database + - /var/log/auth.log:/var/log/auth.log:ro + - /prod/gitea/logs/access.log:/var/log/gitea/access.log:ro + - ./data/fail2ban:/data + environment: + # Optional: set timezone + - TZ=Europe/Berlin + +networks: + fast-services: + external: true diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..e69de29