diff --git a/playbooks/mail/Containerfile b/containers/postfix/Containerfile similarity index 100% rename from playbooks/mail/Containerfile rename to containers/postfix/Containerfile diff --git a/playbooks/mail/main.cf b/containers/postfix/main.cf similarity index 86% rename from playbooks/mail/main.cf rename to containers/postfix/main.cf index c6fd386..4585cac 100644 --- a/playbooks/mail/main.cf +++ b/containers/postfix/main.cf @@ -20,7 +20,9 @@ relayhost = # --- TLS (outbound) --- smtp_tls_security_level = enforce smtp_tls_loglevel = 1 -smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt +smtpd_tls_chain_files = + /etc/postfix/fullchain.pem + /etc/postfix/privkey.pem # --- Mailbox --- home_mailbox = Maildir/ diff --git a/makefile b/makefile index 63b50f4..5fdda84 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,7 @@ REGISTRY := git.secretbee.buzz INVENTORY := inventory.yml build-%: - podman build --platform linux/arm64 -t $(REGISTRY)/bee/$*:latest playbooks/$* + podman build --platform linux/arm64 -t $(REGISTRY)/bee/$*:latest containers/$* push-%: build-% podman push $(REGISTRY)/bee/$*:latest diff --git a/playbooks/letsencrypt/letsencrypt.yml b/playbooks/letsencrypt/letsencrypt.yml index 534116e..e46af14 100644 --- a/playbooks/letsencrypt/letsencrypt.yml +++ b/playbooks/letsencrypt/letsencrypt.yml @@ -27,6 +27,10 @@ changed_when: true ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains grafana.secretbee.buzz + - name: Request mail certificates + changed_when: true + ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains mail.secretbee.buzz + - name: Add post hook script ansible.builtin.copy: src: irc-post-hook.sh diff --git a/playbooks/mail/docker-compose.yml.j2 b/playbooks/mail/docker-compose.yml.j2 index 69c7d2b..ab7082f 100644 --- a/playbooks/mail/docker-compose.yml.j2 +++ b/playbooks/mail/docker-compose.yml.j2 @@ -4,44 +4,34 @@ networks: 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 + image: docker.io/dovecot/dovecot:latest + container_name: dovecot + restart: unless-stopped networks: - - gitea + - mail volumes: - - ./gitea:/data - - /etc/timezone:/etc/timezone:ro - - /etc/localtime:/etc/localtime:ro + - mail_data:/srv/vmail ports: - - "31110:31110" - - "31995:31995" - "31143:31143" - "31993:31993" + - "31110:31110" + - "31995:31995" + - "1465:1465" - "31587:31587" - "31024:31024" - depends_on: - - db + - "34190:34190" + - "8080:8080" + - "127.0.01:9110:9110" - db: - image: docker.io/library/postgres:14 - restart: always - environment: - - POSTGRES_USER=gitea - - POSTGRES_PASSWORD={{ gitea_db_password }} - - POSTGRES_DB=gitea + postfix: + image: git.secretbee.buzz/bee/postfix:latest + container_name: postfix + restart: unless-stopped networks: - - gitea + - mail volumes: - - ./postgres:/var/lib/postgresql/data \ No newline at end of file + - /etc/letsencrypt/live/mail.secretbee.buzz/fullchain.pem:/etc/postfix/fullchain.pem + - /etc/letsencrypt/live/mail.secretbee.buzz/privkey.pem:/etc/postfix/privkey.pem + +volumes: + mail-data: \ No newline at end of file diff --git a/playbooks/monitoring/config.alloy.j2 b/playbooks/monitoring/config.alloy.j2 index 1b5d77a..a00d949 100644 --- a/playbooks/monitoring/config.alloy.j2 +++ b/playbooks/monitoring/config.alloy.j2 @@ -6,8 +6,12 @@ loki.source.journal "system" { } } +local.file_match "fail2ban" { + path_targets = [{"__path__" = "/var/log/fail2ban.log", job = "fail2ban", host = "beepi"}] +} + local.file_match "varlog" { - path_targets = [{"__path__" = "/var/log/*.log", job = "varlog", host = "beepi"}] + path_targets = [{"__path__" = "/var/log/*.log", job = "varlog", "__path_exclude__" = "/var/log/fail2ban.log", host = "beepi"}] } loki.source.file "varlog" { @@ -15,6 +19,41 @@ loki.source.file "varlog" { forward_to = [loki.write.default.receiver] } +loki.source.file "fail2ban_source" { + targets = local.file_match.fail2ban.targets + forward_to = [loki.process.geoip.receiver] +} + +loki.process "geoip" { + forward_to = [loki.write.default.receiver] + stage.regex { + expression = `^.*:\s(?\w*)\s*\[(?\w*)\]\s(?\w*)\s(?(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))).*$` + labels_from_groups = true + } + + stage.geoip { + db = "/opt/database/GeoLite2-City.mmdb" + source = "ip" + db_type = "city" + } + + stage.labels { + values = { + geoip_city_name = "", + geoip_country_name = "", + geoip_country_code = "", + geoip_continent_name = "", + geoip_continent_code = "", + geoip_location_latitude = "", + geoip_location_longitude = "", + geoip_postal_code = "", + geoip_timezone = "", + geoip_subdivision_name = "", + geoip_subdivision_code = "", + } + } +} + loki.write "default" { endpoint { url = "http://loki:3100/loki/api/v1/push" diff --git a/playbooks/monitoring/docker-compose.yml.j2 b/playbooks/monitoring/docker-compose.yml.j2 index 5a2ca96..2b83322 100644 --- a/playbooks/monitoring/docker-compose.yml.j2 +++ b/playbooks/monitoring/docker-compose.yml.j2 @@ -53,6 +53,7 @@ services: - '127.0.0.1:12345:12345' volumes: - /opt/monitoring/config.alloy:/etc/alloy/config.alloy + - /opt/monitoring/database:/opt/database - /var/log:/var/log:ro - /run/log/journal:/run/log/journal:ro - /var/log/journal:/var/log/journal:ro @@ -67,7 +68,25 @@ services: networks: - monitoring + podman-exporter: + image: quay.io/navidys/prometheus-podman-exporter + container_name: podman-exporter + restart: unless-stopped + privileged: true + user: root + ports: + - '127.0.0.1:9882:9882' + volumes: + - /run/podman/podman.sock:/run/podman/podman.sock + environment: + - CONTAINER_HOST=unix:///run/podman/podman.sock + security_opt: + - label=disable + networks: + - monitoring + volumes: + prometheus-data: grafana-storage: loki-data: alloy-data: \ No newline at end of file diff --git a/playbooks/monitoring/monitoring.yml b/playbooks/monitoring/monitoring.yml index 5de6b0d..4546538 100644 --- a/playbooks/monitoring/monitoring.yml +++ b/playbooks/monitoring/monitoring.yml @@ -9,6 +9,21 @@ 36346437353963333839656163623933616662326132373036636166616538343966356361636164 3035656163616631330a663363343363643065356535356633623638376430326539363536666638 65333930613135333364383462363233386662386531323935353932373465363234 + geoip_username: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 30656365643463396265633130356339386433633331613130633134336633643637653761623962 + 3633336466326564616432373031303530376166353436610a323033353164313436613363613836 + 30303931323234306162343361643162313238313234383837323530343936343134326365666166 + 3438643238626266320a333732363461613834613833303436363534393031323333613534333534 + 3438 + geoip_license: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 32336437653435396231663666643631373638616533653538333934356339666661313439343566 + 6462303439666233316162653430363239393031633362630a323533393233633164613031646633 + 62366362383162306563383235373262326262323337303333313163653838613436316337633063 + 3630356262666338320a333137333063303534386437343762616665383034336365663732343566 + 36376463313964333834373435653564346333396538306337333762613737643363636364353139 + 3032383564333638613566633363666430356230326231633636 tasks: - name: Install podman ansible.builtin.apt: @@ -31,6 +46,18 @@ state: directory mode: '0755' + - name: Copy compose + ansible.builtin.template: + src: docker-compose.yml.j2 + dest: /opt/monitoring/docker-compose.yml + mode: '0644' + + - name: Compose down + changed_when: true + ansible.builtin.command: + cmd: podman-compose down + chdir: /opt/monitoring + - name: Copy prometheus config ansible.builtin.copy: src: prometheus_config.yml @@ -49,17 +76,50 @@ dest: /opt/monitoring/config.alloy mode: '0644' - - name: Copy compose - ansible.builtin.template: - src: docker-compose.yml.j2 - dest: /opt/monitoring/docker-compose.yml - mode: '0644' + - name: Enable podman.socket + ansible.builtin.service: + name: podman.socket + state: started + enabled: true - - name: Compose down - changed_when: true - ansible.builtin.command: - cmd: podman-compose down - chdir: /opt/monitoring + - name: Delete database directory + ansible.builtin.file: + path: /opt/monitoring/database + state: absent + mode: '0755' + + - name: Create database directory + ansible.builtin.file: + path: /opt/monitoring/database + state: directory + mode: '0755' + + - name: Download geoip database + ansible.builtin.get_url: + url: "https://download.maxmind.com/geoip/databases/GeoLite2-City/download?suffix=tar.gz" + dest: /opt/monitoring + username: "{{ geoip_username }}" + password: "{{ geoip_license }}" + mode: '0644' + tags: + - never + - geoip + + - name: Get geoip tar file + ansible.builtin.find: + paths: /opt/monitoring + file_type: file + patterns: '^GeoLite.*.tar.gz$' + use_regex: true + limit: 1 + register: found + + - name: Extract geopip database + ansible.builtin.unarchive: + remote_src: true + src: "{{ found.files[0].path }}" + dest: /opt/monitoring/database + extra_opts: ['--strip-components=1', '--show-stored-names'] - name: Compose up changed_when: true diff --git a/playbooks/monitoring/prometheus_config.yml b/playbooks/monitoring/prometheus_config.yml index b3db8ea..13ece28 100644 --- a/playbooks/monitoring/prometheus_config.yml +++ b/playbooks/monitoring/prometheus_config.yml @@ -8,4 +8,10 @@ scrape_configs: - targets: ['localhost:9090'] - job_name: node static_configs: - - targets: ['host.containers.internal:9100'] \ No newline at end of file + - targets: ['host.containers.internal:9100'] + - job_name: podman + static_configs: + - targets: ['podman-exporter:9882'] + - job_name: beepc + static_configs: + - targets: ['192.168.178.51:9100'] \ No newline at end of file diff --git a/playbooks/ufw/ufw.yml b/playbooks/ufw/ufw.yml index 3ee10b3..9f3ba40 100644 --- a/playbooks/ufw/ufw.yml +++ b/playbooks/ufw/ufw.yml @@ -66,19 +66,25 @@ proto: "udp" to_port: 53 - - name: UFW - Allow scraping + - name: UFW - Allow node exporter scraping community.general.ufw: rule: allow interface_in: podman+ proto: "tcp" to_port: 9100 + - name: UFW - Allow podman exporter scraping + community.general.ufw: + rule: allow + interface_in: podman+ + proto: "tcp" + to_port: 9882 + - 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