From 5558ed473a37c1165d418646f810d8538080980d Mon Sep 17 00:00:00 2001 From: bee Date: Tue, 28 Apr 2026 11:00:23 +0200 Subject: [PATCH] logging stack and firewall --- playbooks/fail2ban/fail2ban.yml | 24 +++++++ playbooks/fail2ban/jail.local.j2 | 15 +++++ playbooks/{postfix => mail}/Containerfile | 0 playbooks/mail/docker-compose.yml.j2 | 47 +++++++++++++ playbooks/{postfix => mail}/main.cf | 0 playbooks/monitoring/config.alloy.j2 | 22 +++++++ playbooks/monitoring/docker-compose.yml.j2 | 42 +++++++++++- playbooks/monitoring/local-config.yml.j2 | 77 ++++++++++++++++++++++ playbooks/monitoring/monitoring.yml | 16 ++++- playbooks/ufw/ufw.yml | 40 +++++++++++ 10 files changed, 280 insertions(+), 3 deletions(-) create mode 100644 playbooks/fail2ban/fail2ban.yml create mode 100644 playbooks/fail2ban/jail.local.j2 rename playbooks/{postfix => mail}/Containerfile (100%) create mode 100644 playbooks/mail/docker-compose.yml.j2 rename playbooks/{postfix => mail}/main.cf (100%) create mode 100644 playbooks/monitoring/config.alloy.j2 create mode 100644 playbooks/monitoring/local-config.yml.j2 diff --git a/playbooks/fail2ban/fail2ban.yml b/playbooks/fail2ban/fail2ban.yml new file mode 100644 index 0000000..2527a11 --- /dev/null +++ b/playbooks/fail2ban/fail2ban.yml @@ -0,0 +1,24 @@ +- name: fail2ban + hosts: pi + become: true + + tasks: + - name: Install fail2ban + ansible.builtin.apt: + name: fail2ban + state: present + + - name: Copy jail.local + ansible.builtin.template: + src: jail.local.j2 + dest: /etc/fail2ban/jail.local + owner: root + group: root + mode: '0644' + notify: Restart fail2ban + + handlers: + - name: Restart fail2ban + ansible.builtin.service: + name: fail2ban + state: restarted diff --git a/playbooks/fail2ban/jail.local.j2 b/playbooks/fail2ban/jail.local.j2 new file mode 100644 index 0000000..eaeb831 --- /dev/null +++ b/playbooks/fail2ban/jail.local.j2 @@ -0,0 +1,15 @@ +[DEFAULT] +bantime = 24h +findtime = 10m +maxretry = 5 +banaction = ufw + +[sshd] +enabled = true +port = ssh,2222 + +[nginx-http-auth] +enabled = true + +[nginx-limit-req] +enabled = true diff --git a/playbooks/postfix/Containerfile b/playbooks/mail/Containerfile similarity index 100% rename from playbooks/postfix/Containerfile rename to playbooks/mail/Containerfile diff --git a/playbooks/mail/docker-compose.yml.j2 b/playbooks/mail/docker-compose.yml.j2 new file mode 100644 index 0000000..69c7d2b --- /dev/null +++ b/playbooks/mail/docker-compose.yml.j2 @@ -0,0 +1,47 @@ +networks: + mail: + external: false + +services: + dovecot: + image: docker.gitea.com/gitea:1.26.0 + container_name: gitea + environment: + - USER_UID=1000 + - USER_GID=1000 + - GITEA__database__DB_TYPE=postgres + - GITEA__database__HOST=db:5432 + - GITEA__database__NAME=gitea + - GITEA__database__USER=gitea + - GITEA__database__PASSWD={{ gitea_db_password }} + - GITEA__server__SSH_LISTEN_PORT=2222 + - GITEA__server__SSH_PORT=2222 + - SSH_LISTEN_PORT=2222 + restart: always + networks: + - gitea + volumes: + - ./gitea:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "31110:31110" + - "31995:31995" + - "31143:31143" + - "31993:31993" + - "31587:31587" + - "31024:31024" + depends_on: + - db + + db: + image: docker.io/library/postgres:14 + restart: always + environment: + - POSTGRES_USER=gitea + - POSTGRES_PASSWORD={{ gitea_db_password }} + - POSTGRES_DB=gitea + networks: + - gitea + volumes: + - ./postgres:/var/lib/postgresql/data \ No newline at end of file diff --git a/playbooks/postfix/main.cf b/playbooks/mail/main.cf similarity index 100% rename from playbooks/postfix/main.cf rename to playbooks/mail/main.cf diff --git a/playbooks/monitoring/config.alloy.j2 b/playbooks/monitoring/config.alloy.j2 new file mode 100644 index 0000000..1b5d77a --- /dev/null +++ b/playbooks/monitoring/config.alloy.j2 @@ -0,0 +1,22 @@ +loki.source.journal "system" { + forward_to = [loki.write.default.receiver] + labels = { + job = "systemd-journal", + host = "beepi", + } +} + +local.file_match "varlog" { + path_targets = [{"__path__" = "/var/log/*.log", job = "varlog", host = "beepi"}] +} + +loki.source.file "varlog" { + targets = local.file_match.varlog.targets + forward_to = [loki.write.default.receiver] +} + +loki.write "default" { + endpoint { + url = "http://loki:3100/loki/api/v1/push" + } +} \ No newline at end of file diff --git a/playbooks/monitoring/docker-compose.yml.j2 b/playbooks/monitoring/docker-compose.yml.j2 index 911002e..5a2ca96 100644 --- a/playbooks/monitoring/docker-compose.yml.j2 +++ b/playbooks/monitoring/docker-compose.yml.j2 @@ -30,4 +30,44 @@ services: - GF_SERVER_HTTP_PORT=4000 - GF_SERVER_PROTOCOL=HTTP networks: - - monitoring \ No newline at end of file + - monitoring + + loki: + image: docker.io/grafana/loki + container_name: loki + ports: + - '127.0.0.1:3100:3100' + - '127.0.0.1:9096:9096' + volumes: + - loki-data:/loki + - /opt/monitoring/local-config.yml:/etc/loki/local-config.yaml + command: -config.file=/etc/loki/local-config.yaml + restart: unless-stopped + networks: + - monitoring + + alloy: + image: docker.io/grafana/alloy + container_name: alloy + ports: + - '127.0.0.1:12345:12345' + volumes: + - /opt/monitoring/config.alloy:/etc/alloy/config.alloy + - /var/log:/var/log:ro + - /run/log/journal:/run/log/journal:ro + - /var/log/journal:/var/log/journal:ro + - /etc/machine-id:/etc/machine-id:ro + - alloy-data:/var/lib/alloy/data + command: + - run + - /etc/alloy/config.alloy + - --storage.path=/var/lib/alloy/data + - --server.http.listen-addr=0.0.0.0:12345 + - --stability.level=experimental + networks: + - monitoring + +volumes: + grafana-storage: + loki-data: + alloy-data: \ No newline at end of file diff --git a/playbooks/monitoring/local-config.yml.j2 b/playbooks/monitoring/local-config.yml.j2 new file mode 100644 index 0000000..46fd6ff --- /dev/null +++ b/playbooks/monitoring/local-config.yml.j2 @@ -0,0 +1,77 @@ +auth_enabled: false + +server: + http_listen_port: 3100 + grpc_listen_port: 9096 + log_level: info + +common: + instance_addr: 127.0.0.1 + path_prefix: /loki + storage: + filesystem: + chunks_directory: /loki/chunks + rules_directory: /loki/rules + replication_factor: 1 + ring: + kvstore: + store: inmemory + +query_range: + results_cache: + cache: + embedded_cache: + enabled: true + max_size_mb: 100 + +schema_config: + configs: + - from: 2020-10-24 + store: tsdb + object_store: filesystem + schema: v13 + index: + prefix: index_ + period: 24h + +ruler: + alertmanager_url: http://localhost:9093 + +ingester: + wal: + enabled: true + dir: /loki/wal + lifecycler: + ring: + replication_factor: 1 + +limits_config: + reject_old_samples: true + reject_old_samples_max_age: 168h + ingestion_rate_mb: 16 + ingestion_burst_size_mb: 24 + max_streams_per_user: 10000 + max_line_size: 256kb + +chunk_store_config: + chunk_cache_config: + embedded_cache: + enabled: true + max_size_mb: 100 + +storage_config: + tsdb_shipper: + active_index_directory: /loki/tsdb-index + cache_location: /loki/tsdb-cache + +compactor: + working_directory: /loki/compactor + compaction_interval: 10m + retention_enabled: true + retention_delete_delay: 2h + retention_delete_worker_count: 150 + delete_request_store: filesystem + +table_manager: + retention_deletes_enabled: true + retention_period: 720h \ No newline at end of file diff --git a/playbooks/monitoring/monitoring.yml b/playbooks/monitoring/monitoring.yml index 3a3d9db..5de6b0d 100644 --- a/playbooks/monitoring/monitoring.yml +++ b/playbooks/monitoring/monitoring.yml @@ -25,18 +25,30 @@ name: prometheus-node-exporter state: present - - name: Create prometheus config directory + - name: Create monitoring config directory ansible.builtin.file: path: /opt/monitoring state: directory mode: '0755' - - name: Copy config + - name: Copy prometheus config ansible.builtin.copy: src: prometheus_config.yml dest: /opt/monitoring/prometheus.yml mode: '0644' + - name: Copy loki config + ansible.builtin.template: + src: local-config.yml.j2 + dest: /opt/monitoring/local-config.yml + mode: '0644' + + - name: Copy alloy config + ansible.builtin.template: + src: config.alloy.j2 + dest: /opt/monitoring/config.alloy + mode: '0644' + - name: Copy compose ansible.builtin.template: src: docker-compose.yml.j2 diff --git a/playbooks/ufw/ufw.yml b/playbooks/ufw/ufw.yml index 00fa836..3ee10b3 100644 --- a/playbooks/ufw/ufw.yml +++ b/playbooks/ufw/ufw.yml @@ -7,6 +7,10 @@ name: ufw state: present + - name: Logging + community.general.ufw: + logging: "low" + - name: Allow SSH community.general.ufw: rule: allow @@ -34,11 +38,47 @@ proto: tcp route: true + - name: UFW - Allow podman forwarding + community.general.ufw: + rule: allow + interface_in: podman+ + interface_out: podman+ + route: true + + - name: UFW - Allow podman forwarding 2 + community.general.ufw: + rule: allow + interface_in: eth0 + interface_out: podman+ + route: true + + - name: UFW - Allow podman forwarding 3 + community.general.ufw: + rule: allow + interface_in: podman+ + interface_out: eth0 + route: true + + - name: UFW - Enable DNS + community.general.ufw: + rule: allow + interface_in: podman+ + proto: "udp" + to_port: 53 + + - name: UFW - Allow scraping + community.general.ufw: + rule: allow + interface_in: podman+ + proto: "tcp" + to_port: 9100 + - name: UFW - Enable and deny by default community.general.ufw: state: enabled default: deny + - name: UFW - Reload firewall changed_when: true ansible.builtin.command: ufw reload