add plattform services
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
---
|
||||
# - name: AUTHENTIK | Verzeichnisse erstellen und Berechtigungen setzen
|
||||
# ansible.builtin.file:
|
||||
# path: "/mnt/cephfs/authentik/data/{{ item }}"
|
||||
# state: directory
|
||||
# owner: 1000
|
||||
# group: 1000
|
||||
# mode: '0755'
|
||||
# loop:
|
||||
# - cache
|
||||
# - certs
|
||||
# - db
|
||||
# - media
|
||||
# - templates
|
||||
# run_once: true
|
||||
# delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: AUTHENTIK | Generate Compose file
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: /mnt/cephfs/authentik/authentik.yml
|
||||
mode: 0644
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: AUTHENTIK | Deploy app stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: authentik
|
||||
compose:
|
||||
- /mnt/cephfs/authentik/authentik.yml
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
networks:
|
||||
traefik_public:
|
||||
external: true
|
||||
internal:
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $POSTGRES_DB -U $POSTGRES_USER"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 5s
|
||||
volumes:
|
||||
- /mnt/cephfs/authentik/data/db:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: "{{ pg_pass }}"
|
||||
POSTGRES_USER: "{{ pg_user | default('authentik') }}"
|
||||
POSTGRES_DB: "{{ pg_db | default('authentik') }}"
|
||||
networks:
|
||||
- internal
|
||||
|
||||
redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
command: --save 60 1 --loglevel warning
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 3s
|
||||
volumes:
|
||||
- /mnt/cephfs/authentik/data/cache:/data
|
||||
networks:
|
||||
- internal
|
||||
|
||||
server:
|
||||
image: "{{ authentik_image | default('ghcr.io/goauthentik/server') }}:{{ authentik_tag | default('2025.6.3') }}"
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: "{{ authentik_secret_key }}"
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__USER: "{{ pg_user | default('authentik') }}"
|
||||
AUTHENTIK_POSTGRESQL__NAME: "{{ pg_db | default('authentik') }}"
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: "{{ pg_pass }}"
|
||||
AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
|
||||
volumes:
|
||||
- /mnt/cephfs/authentik/data/media:/media
|
||||
- /mnt/cephfs/authentik/data/templates:/templates
|
||||
networks:
|
||||
- traefik_public
|
||||
- internal
|
||||
deploy:
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.swarm.network: {{ traefik_net }}
|
||||
traefik.http.routers.authentik.rule: Host(`{{ traefik_route }}`) || HostRegexp(`{subdomain:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?}.genius.ceo`) && PathPrefix(`/outpost.goauthentik.io/`)
|
||||
traefik.http.routers.authentik.entrypoints: https
|
||||
traefik.http.routers.authentik.tls: "true"
|
||||
traefik.http.routers.authentik.tls.certresolver: main
|
||||
traefik.http.services.authentik.loadbalancer.server.port: 9000
|
||||
# - "traefik.enable=true"
|
||||
# - "traefik.swarm.network={{ traefik_net }}"
|
||||
# - "traefik.http.routers.authentik.rule=Host(`{{ traefik_route }}`) || HostRegexp(`{subdomain:[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?}.genius.ceo`) && PathPrefix(`/outpost.goauthentik.io/`)"
|
||||
# - "traefik.http.routers.authentik.entrypoints=https"
|
||||
# - "traefik.http.routers.authentik.tls=true"
|
||||
# - "traefik.http.routers.authentik.tls.certresolver=main"
|
||||
# - "traefik.http.services.authentik.loadbalancer.server.port=9000"
|
||||
|
||||
worker:
|
||||
image: "{{ authentik_image | default('ghcr.io/goauthentik/server') }}:{{ authentik_tag | default('2025.6.3') }}"
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: "{{ authentik_secret_key }}"
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__USER: "{{ pg_user | default('authentik') }}"
|
||||
AUTHENTIK_POSTGRESQL__NAME: "{{ pg_db | default('authentik') }}"
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: "{{ pg_pass }}"
|
||||
# `user: root` and the docker socket volume are optional.
|
||||
# See more for the docker socket integration here:
|
||||
# https://goauthentik.io/docs/outposts/integrations/docker
|
||||
# Removing `user: root` also prevents the worker from fixing the permissions
|
||||
# on the mounted folders, so when removing this make sure the folders have the correct UID/GID
|
||||
# (1000:1000 by default)
|
||||
user: root
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /mnt/cephfs/authentik/data/media:/media
|
||||
- /mnt/cephfs/authentik/data/certs:/certs
|
||||
- /mnt/cephfs/authentik/data/templates:/templates
|
||||
networks:
|
||||
- internal
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
authentik_image: "ghcr.io/goauthentik/server"
|
||||
authentik_tag: "2025.6.3"
|
||||
authentik_secret_key: ""
|
||||
|
||||
pg_user: "authentik"
|
||||
pg_pass: ""
|
||||
pg_db: "authentik"
|
||||
|
||||
traefik_net: "traefik_public"
|
||||
traefik_route: "auth.genius.ceo"
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
- name: CEPH | Private IP des ersten Managers ermitteln
|
||||
ansible.builtin.set_fact:
|
||||
ceph_bootstrap_ip: "{{ hostvars[inventory_hostname]['ansible_' + private_interface]['ipv4']['address'] }}"
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: CEPH | Cluster auf dem ersten Manager initialisieren (Bootstrap)
|
||||
ansible.builtin.command:
|
||||
cmd: "cephadm bootstrap --mon-ip {{ ceph_bootstrap_ip }}"
|
||||
creates: /etc/ceph/ceph.conf
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: CEPH | Öffentlichen SSH-Schlüssel von cephadm abrufen
|
||||
ansible.builtin.command: "cephadm shell -- ceph cephadm get-pub-key"
|
||||
register: cephadm_pub_key
|
||||
changed_when: false
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: CEPH | Öffentlichen Schlüssel von cephadm auf allen Knoten für root verteilen
|
||||
ansible.posix.authorized_key:
|
||||
user: root
|
||||
key: "{{ hostvars[groups['managers'][0]]['cephadm_pub_key'].stdout }}"
|
||||
state: present
|
||||
key_options: 'no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty'
|
||||
|
||||
- name: CEPH | Andere Knoten zum Ceph-Cluster hinzufügen
|
||||
ansible.builtin.command:
|
||||
cmd: "ceph orch host add {{ item }} {{ hostvars[item]['ansible_' + private_interface]['ipv4']['address'] }}"
|
||||
loop: "{{ groups['all'] }}"
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: CEPH | Prüfen, ob bereits OSDs (Speichergeräte) vorhanden sind
|
||||
ansible.builtin.command: "ceph osd ls"
|
||||
register: existing_osds
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: CEPH | Spezifische Festplatte ({{ ceph_osd_device }}) auf jedem Knoten als OSD hinzufügen
|
||||
ansible.builtin.command: "ceph orch daemon add osd {{ item }}:{{ ceph_osd_device }}"
|
||||
loop: "{{ groups['all'] }}"
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
when: existing_osds.stdout | length == 0
|
||||
|
||||
- name: CEPH | Prüfen, ob CephFS bereits existiert
|
||||
ansible.builtin.command: "ceph fs ls -f json"
|
||||
register: cephfs_list
|
||||
changed_when: false
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: CEPH | CephFS Pools und Dateisystem erstellen, falls nicht vorhanden
|
||||
block:
|
||||
- name: Metadaten-Pool für CephFS erstellen
|
||||
ansible.builtin.command: "ceph osd pool create {{ cephfs_name }}_metadata"
|
||||
- name: Daten-Pool für CephFS erstellen
|
||||
ansible.builtin.command: "ceph osd pool create {{ cephfs_name }}_data"
|
||||
- name: CephFS-Dateisystem erstellen
|
||||
ansible.builtin.command: "ceph fs new {{ cephfs_name }} {{ cephfs_name }}_metadata {{ cephfs_name }}_data"
|
||||
when: cephfs_list.stdout | from_json | length == 0
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: CEPH | Metadaten-Server (MDS) für CephFS starten
|
||||
ansible.builtin.command: "ceph orch apply mds {{ cephfs_name }} --placement=2"
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
when: cephfs_list.stdout | from_json | length == 0
|
||||
|
||||
- name: CEPH | Ceph Admin-Schlüssel für das Mounten abrufen
|
||||
ansible.builtin.command: "ceph auth get-key client.admin"
|
||||
register: ceph_admin_key
|
||||
changed_when: false
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: CEPH | Mount-Punkt für CephFS erstellen
|
||||
ansible.builtin.file:
|
||||
path: /mnt/cephfs
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: CEPH | CephFS auf allen Knoten mounten (und in /etc/fstab eintragen)
|
||||
ansible.posix.mount:
|
||||
path: /mnt/cephfs
|
||||
src: "{{ hostvars[groups['managers'][0]]['ceph_bootstrap_ip'] }}:/"
|
||||
fstype: ceph
|
||||
opts: "name=admin,secret={{ ceph_admin_key.stdout }}"
|
||||
state: mounted
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
- name: COMMON | Systempakete aktualisieren und upgraden
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
autoclean: true
|
||||
|
||||
- name: COMMON | Notwendige Pakete installieren
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- ufw
|
||||
- fail2ban
|
||||
- unattended-upgrades
|
||||
- apt-listchanges
|
||||
- docker-ce
|
||||
- python3-pip
|
||||
- chrony
|
||||
- lvm2
|
||||
- cephadm
|
||||
- ceph-common
|
||||
state: present
|
||||
|
||||
- name: COMMON | Chrony Dienst starten und aktivieren
|
||||
ansible.builtin.service:
|
||||
name: chronyd
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: COMMON | Docker Dienst starten und aktivieren
|
||||
ansible.builtin.service:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: COMMON | Einen dedizierten Admin-Benutzer erstellen
|
||||
ansible.builtin.user:
|
||||
name: "{{ admin_user }}"
|
||||
password: "{{ admin_password}}"
|
||||
shell: /bin/bash
|
||||
groups: sudo,docker
|
||||
append: true
|
||||
state: present
|
||||
|
||||
- name: COMMON | SSH-Schlüssel für den Admin-Benutzer einrichten
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ admin_user }}"
|
||||
key: "{{ item }}"
|
||||
state: present
|
||||
with_items: "{{ authorized_keys }}"
|
||||
|
||||
- name: COMMON | cephadm-Benutzer erstellen
|
||||
ansible.builtin.user:
|
||||
name: "cephadm"
|
||||
password: "{{ cephadm_password }}"
|
||||
shell: /bin/bash
|
||||
groups: sudo,docker
|
||||
append: yes
|
||||
state: present
|
||||
|
||||
- name: COMMON | .ssh Verzeichnis für cephadm-Benutzer erstellen
|
||||
ansible.builtin.file:
|
||||
path: /home/cephadm/.ssh
|
||||
state: directory
|
||||
|
||||
- name: COMMON | Passwortloses Sudo für cephadm-Benutzer erlauben
|
||||
ansible.builtin.copy:
|
||||
dest: "/etc/sudoers.d/91-cephadm-nopasswd"
|
||||
content: "cephadm ALL=(ALL) NOPASSWD: ALL"
|
||||
mode: '0440'
|
||||
validate: 'visudo -cf %s'
|
||||
|
||||
- name: COMMON | ed25519 SSH-Schlüssel für cephadm-Benutzer generieren (nur auf dem ersten Manager)
|
||||
community.crypto.openssh_keypair:
|
||||
path: /home/cephadm/.ssh/id_ed25519
|
||||
type: ed25519
|
||||
owner: cephadm
|
||||
group: cephadm
|
||||
mode: '0600'
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: COMMON | Öffentlichen SSH-Schlüssel von cephadm abrufen
|
||||
ansible.builtin.slurp:
|
||||
src: /home/cephadm/.ssh/id_ed25519.pub
|
||||
register: cephadm_ssh_pub_key
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: COMMON | Öffentlichen SSH-Schlüssel von cephadm auf allen Knoten verteilen
|
||||
ansible.posix.authorized_key:
|
||||
user: cephadm
|
||||
key: "{{ hostvars[groups['managers'][0]]['cephadm_ssh_pub_key']['content'] | b64decode }}"
|
||||
state: present
|
||||
|
||||
- name: COMMON | Automatische Sicherheitsupdates konfigurieren
|
||||
ansible.builtin.copy:
|
||||
src: assets/50unattended-upgrades
|
||||
dest: /etc/apt/apt.conf.d/50unattended-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: COMMON | Periodische Auto-Updates aktivieren
|
||||
ansible.builtin.copy:
|
||||
src: assets/20auto-upgrades
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
- name: SWARM | Ensure Docker SDK for Python is installed
|
||||
ansible.builtin.apt:
|
||||
name: python3-docker
|
||||
state: present
|
||||
|
||||
- name: SWARM | Get interface IP address for the manager
|
||||
ansible.builtin.set_fact:
|
||||
manager_ip: "{{ hostvars[inventory_hostname]['ansible_' + private_interface]['ipv4']['address'] }}"
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: SWARM | Initialize the Docker Swarm
|
||||
community.docker.docker_swarm:
|
||||
state: present
|
||||
advertise_addr: "{{ manager_ip }}"
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
register: swarm_init_result
|
||||
|
||||
- name: SWARM | Get the join tokens
|
||||
community.docker.docker_swarm_info:
|
||||
register: swarm_info
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: SWARM | Verify that join tokens were fetched
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- swarm_info is defined
|
||||
- swarm_info.swarm_facts is defined
|
||||
- swarm_info.swarm_facts.JoinTokens.Manager is defined
|
||||
- swarm_info.swarm_facts.JoinTokens.Worker is defined
|
||||
fail_msg: "Konnte die Join-Tokens vom Swarm Manager nicht abrufen. Ist der Swarm korrekt initialisiert?"
|
||||
success_msg: "Join-Tokens erfolgreich abgerufen."
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: SWARM | Join manager nodes to the Swarm
|
||||
community.docker.docker_swarm:
|
||||
state: join
|
||||
remote_addrs: [ "{{ hostvars[groups['managers'][0]]['manager_ip'] }}:2377" ]
|
||||
join_token: "{{ hostvars[groups['managers'][0]]['swarm_info']['swarm_facts']['JoinTokens']['Manager'] }}"
|
||||
when: inventory_hostname in groups['managers']
|
||||
|
||||
- name: SWARM | Join worker nodes to the Swarm
|
||||
community.docker.docker_swarm:
|
||||
state: join
|
||||
remote_addrs: [ "{{ hostvars[groups['managers'][0]]['manager_ip'] }}:2377" ]
|
||||
join_token: "{{ hostvars[groups['managers'][0]]['swarm_info']['swarm_facts']['JoinTokens']['Worker'] }}"
|
||||
when: inventory_hostname in groups['workers']
|
||||
|
||||
- name: SWARM | Verify Swarm Cluster State (run on manager)
|
||||
ansible.builtin.command: docker node ls
|
||||
register: swarm_nodes
|
||||
changed_when: false
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
|
||||
- name: SWARM | Display cluster state
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ swarm_nodes.stdout_lines }}"
|
||||
when: inventory_hostname == groups['managers'][0]
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
dockge_stacks_dir: /mnt/cephfs/dockge/stacks
|
||||
dockge_data_dir: /mnt/cephfs/dockge/data
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
- name: DOCKGE | Copy Stack Files
|
||||
copy:
|
||||
directory_mode: true
|
||||
src: /Users/d3r0/dev/repositories/active/gc/iac/ansible/resources/dockge
|
||||
dest: /mnt/cephfs
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
# - name: DOCKGE | Sicherstellen, dass das Verzeichnis für die Anwendungs Daten existiert
|
||||
# ansible.builtin.file:
|
||||
# path: "{{ dockge_data_dir }}"
|
||||
# state: directory
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0755'
|
||||
# become: true
|
||||
|
||||
# - name: DOCKGE | Sicherstellen, dass das Verzeichnis für die Stacks existiert
|
||||
# ansible.builtin.file:
|
||||
# path: "{{ dockge_stacks_dir }}"
|
||||
# state: directory
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0755'
|
||||
# become: true
|
||||
|
||||
# - name: DOCKGE | Stack aus der Template-Datei bereitstellen
|
||||
# community.docker.docker_stack:
|
||||
# state: present
|
||||
# name: dockge
|
||||
# compose:
|
||||
# - "{{ lookup('template', '../../../resources/dockge/dockge.yml') }}"
|
||||
# delegate_to: "{{ groups['managers'][0] }}"
|
||||
# run_once: true
|
||||
- name: DOCKGE | Deploy app stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: dockge
|
||||
compose:
|
||||
- /mnt/cephfs/dockge/dockge.yml
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: FAIL2BAN | Eine lokale Jail-Konfiguration erstellen
|
||||
ansible.builtin.template:
|
||||
src: jail.local.j2
|
||||
dest: /etc/fail2ban/jail.local
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: restart fail2ban
|
||||
@@ -0,0 +1,8 @@
|
||||
[DEFAULT]
|
||||
bantime = 1h
|
||||
findtime = 10m
|
||||
maxretry = 5
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = {{ ssh_port }}
|
||||
@@ -0,0 +1,14 @@
|
||||
postgres_version: 16-alpine
|
||||
gitea_version: "1.21"
|
||||
gitea_domain: "{{ subdomain }}.{{ main_domain }}"
|
||||
gitea_http_port: 3000
|
||||
gitea_ssh_port: 2222
|
||||
|
||||
data_dir: "{{ ceph_volume }}/gitea"
|
||||
subdomain: git
|
||||
|
||||
gitea_db_type: "postgres"
|
||||
gitea_db_host: db:5432
|
||||
gitea_db_name: "gitea"
|
||||
gitea_db_user: "gitea"
|
||||
gitea_db_password: ""
|
||||
@@ -0,0 +1,38 @@
|
||||
- name: GITEA | Ensure data directories
|
||||
ansible.builtin.file:
|
||||
path: '{{ data_dir }}/data'
|
||||
state: directory
|
||||
owner: 1000
|
||||
group: 1000
|
||||
mode: '0750'
|
||||
recurse: yes
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: GITEA | Ensure DB data directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ data_dir }}/data/db"
|
||||
state: directory
|
||||
# Postgres Alpine nutzt UID 70 (postgres).
|
||||
# Bei Debian-Images wäre es 999.
|
||||
owner: 70
|
||||
group: 70
|
||||
mode: '0700'
|
||||
recurse: yes
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: GITEA | Generate Compose file
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: '{{ data_dir }}/gitea.yml'
|
||||
mode: 0644
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: GITEA | Deploy stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: gitea
|
||||
compose:
|
||||
- '{{ data_dir }}/gitea.yml'
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,62 @@
|
||||
networks:
|
||||
{{ traefik_public_net }}:
|
||||
external: true
|
||||
internal:
|
||||
|
||||
services:
|
||||
server:
|
||||
image: gitea/gitea:{{ gitea_version }}
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- GITEA__database__DB_TYPE={{ gitea_db_type }}
|
||||
- GITEA__database__HOST={{ gitea_db_host }}
|
||||
- GITEA__database__NAME={{ gitea_db_name }}
|
||||
- GITEA__database__USER={{ gitea_db_user }}
|
||||
- GITEA__database__PASSWD={{ gitea_db_password }}
|
||||
- GITEA__server__DOMAIN={{ gitea_domain }}
|
||||
- GITEA__server__SSH_DOMAIN={{ gitea_domain }}
|
||||
- GITEA__server__SSH_PORT={{ gitea_ssh_port }}
|
||||
- GITEA__server__ROOT_URL=https://{{ gitea_domain }}/
|
||||
volumes:
|
||||
- {{ data_dir }}/data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
networks:
|
||||
- internal
|
||||
- {{ traefik_public_net }}
|
||||
ports:
|
||||
- "{{ gitea_ssh_port }}:22"
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network={{ traefik_public_net }}"
|
||||
- "traefik.http.routers.gitea.rule=Host(`{{ gitea_domain }}`)"
|
||||
- "traefik.http.routers.gitea.entrypoints=https"
|
||||
- "traefik.http.routers.gitea.tls.certresolver=main"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
|
||||
db:
|
||||
image: postgres:{{ postgres_version }}
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_USER={{ gitea_db_user }}
|
||||
- POSTGRES_PASSWORD={{ gitea_db_password }}
|
||||
- POSTGRES_DB={{ gitea_db_name }}
|
||||
networks:
|
||||
- internal
|
||||
volumes:
|
||||
- {{ data_dir }}/data/db:/var/lib/postgresql/data
|
||||
command:
|
||||
- "postgres"
|
||||
- "-c"
|
||||
- "fsync=on"
|
||||
- "-c"
|
||||
- "full_page_writes=on"
|
||||
- "-c"
|
||||
- "synchronous_commit=on"
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
- name: KESTRA | Ensure data directory
|
||||
ansible.builtin.file:
|
||||
path: '{{ data_dir }}/data/data'
|
||||
state: directory
|
||||
mode: '0755'
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: KESTRA | Ensure db directory
|
||||
ansible.builtin.file:
|
||||
path: '{{ data_dir }}/data/db'
|
||||
state: directory
|
||||
mode: '0755'
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: KESTRA | Konfigurationsdatei für tmpfiles.d erstellen
|
||||
ansible.builtin.copy:
|
||||
content: "d /tmp/kestra-wd 0755 root root -"
|
||||
dest: /etc/tmpfiles.d/kestra-wd.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: KESTRA | Create Kestra working directory
|
||||
ansible.builtin.file:
|
||||
path: /tmp/kestra-wd
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: KESTRA | Generate Compose file
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: '{{ data_dir }}/kestra.yml'
|
||||
mode: 0644
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: KESTRA | Deploy stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: kestra
|
||||
compose:
|
||||
- /mnt/cephfs/kestra/kestra.yml
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,92 @@
|
||||
networks:
|
||||
internal:
|
||||
{{ traefik_public_net }}:
|
||||
external: true
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
volumes:
|
||||
- {{ data_dir }}/data/db:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: {{ kestra.db.name }}
|
||||
POSTGRES_USER: {{ kestra.db.user }}
|
||||
POSTGRES_PASSWORD: "{{ kestra.db.pass }}"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d '$${POSTGRES_DB}' -U $${POSTGRES_USER}"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
networks:
|
||||
- internal
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
|
||||
kestra:
|
||||
image: kestra/kestra:v0.24.2
|
||||
entrypoint: /bin/bash
|
||||
# Note that this is meant for development only. Refer to the documentation for production deployments of Kestra which runs without a root user.
|
||||
user: "root"
|
||||
command:
|
||||
- -c
|
||||
- /app/kestra server standalone --worker-thread=128
|
||||
volumes:
|
||||
- {{ data_dir }}/data/data:/app/storage
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /tmp/kestra-wd:/tmp/kestra-wd
|
||||
environment:
|
||||
KESTRA_CONFIGURATION: |
|
||||
datasources:
|
||||
postgres:
|
||||
url: jdbc:postgresql://postgres:5432/kestra
|
||||
driverClassName: org.postgresql.Driver
|
||||
username: {{ kestra.db.user }}
|
||||
password: {{ kestra.db.pass }}
|
||||
kestra:
|
||||
tutorialFlows:
|
||||
enabled: false
|
||||
traces:
|
||||
root: DEFAULT
|
||||
micronaut:
|
||||
metrics:
|
||||
export:
|
||||
otlp:
|
||||
enabled: true
|
||||
url: http://signoz_otel-collector:4318/v1/metrics
|
||||
otel:
|
||||
traces:
|
||||
exporter: otlp
|
||||
exporter:
|
||||
otlp:
|
||||
endpoint: http://signoz_otel-collector:4318
|
||||
server:
|
||||
basic-auth:
|
||||
username: {{ kestra.basic_auth.user }}
|
||||
password: {{ kestra.basic_auth.pass }}
|
||||
repository:
|
||||
type: postgres
|
||||
storage:
|
||||
type: local
|
||||
local:
|
||||
base-path: "/app/storage"
|
||||
queue:
|
||||
type: postgres
|
||||
tasks:
|
||||
tmp-dir:
|
||||
path: /tmp/kestra-wd/tmp
|
||||
url: http://localhost:8080/
|
||||
networks:
|
||||
- {{ traefik_public_net }}
|
||||
- internal
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network={{ traefik_public_net }}"
|
||||
- "traefik.http.routers.kestra.rule=Host(`{{ subdomain }}.{{ main_domain }}`)"
|
||||
- "traefik.http.routers.kestra.entrypoints=https"
|
||||
- "traefik.http.routers.kestra.tls=true"
|
||||
- "traefik.http.routers.kestra.tls.certresolver=main"
|
||||
- "traefik.http.services.kestra.loadbalancer.server.port=8080"
|
||||
@@ -0,0 +1,11 @@
|
||||
subdomain: kestra
|
||||
data_dir: "{{ ceph_volume }}/kestra"
|
||||
|
||||
kestra:
|
||||
basic_auth:
|
||||
user: "ma@coachhamburg.com"
|
||||
pass: "igyozi9B87yTeiQ6z2sbe8Y4aQLJV58jdaCNu"
|
||||
db:
|
||||
name: kestra
|
||||
user: kestra
|
||||
pass: ""
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Copy Stack Files
|
||||
copy:
|
||||
directory_mode: true
|
||||
src: /Users/d3r0/dev/repositories/active/gc/iac/ansible/resources/monitoring
|
||||
dest: /srv
|
||||
- block:
|
||||
- name: Deploy Monitoring stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: monitoring
|
||||
compose:
|
||||
- /srv/monitoring/observability.yml
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
- name: PORTAINER | Ensure data directories
|
||||
ansible.builtin.file:
|
||||
path: '{{ data_dir }}/data'
|
||||
state: directory
|
||||
mode: '0755'
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: PORTAINER | Generate Compose file
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: '{{ data_dir }}/portainer.yml'
|
||||
mode: 0644
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: PORTAINER | Deploy stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: portainer
|
||||
compose:
|
||||
- '{{ data_dir }}/portainer.yml'
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,37 @@
|
||||
version: '3.2'
|
||||
|
||||
services:
|
||||
agent:
|
||||
image: portainer/agent:{{ portainer_version }}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /var/lib/docker/volumes:/var/lib/docker/volumes
|
||||
networks:
|
||||
- {{ traefik_public_net }}
|
||||
deploy:
|
||||
mode: global
|
||||
placement:
|
||||
constraints: [node.platform.os == linux]
|
||||
|
||||
portainer:
|
||||
image: portainer/portainer-ce:{{ portainer_version }}
|
||||
command: -H tcp://portainer_agent:9001 --tlsskipverify
|
||||
volumes:
|
||||
- {{ data_dir }}/data:/data
|
||||
networks:
|
||||
- {{ traefik_public_net }}
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network={{ traefik_public_net }}"
|
||||
- "traefik.http.routers.portainer.rule=Host(`{{ subdomain }}.{{ main_domain }}`)"
|
||||
- "traefik.http.routers.portainer.entrypoints=https"
|
||||
- "traefik.http.routers.portainer.tls=true"
|
||||
- "traefik.http.routers.portainer.tls.certresolver=main"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
|
||||
|
||||
networks:
|
||||
{{ traefik_public_net }}:
|
||||
external: true
|
||||
@@ -0,0 +1,4 @@
|
||||
subdomain: port
|
||||
data_dir: "{{ ceph_volume }}/portainer"
|
||||
|
||||
portainer_version: 2.33.5
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: Copy Stack Files
|
||||
copy:
|
||||
directory_mode: true
|
||||
src: /Users/d3r0/dev/repositories/active/gc/iac/ansible/resources/signoz-infra
|
||||
dest: /mnt/cephfs
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: Deploy Signoz Infra stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: signoz-infra
|
||||
prune: true
|
||||
compose:
|
||||
- /mnt/cephfs/signoz-infra/signoz-infra.yml
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: Copy Stack Files
|
||||
copy:
|
||||
directory_mode: true
|
||||
src: /Users/d3r0/dev/repositories/active/gc/iac/ansible/resources/signoz
|
||||
dest: /mnt/cephfs
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
|
||||
- name: Deploy Signoz stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: signoz
|
||||
prune: true
|
||||
compose:
|
||||
- /mnt/cephfs/signoz/signoz.yml
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
- name: SSH | Ensure privilege separation directory exists
|
||||
ansible.builtin.file:
|
||||
path: /run/sshd
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: SSH | Root-Login nur mit Schlüssel erlauben
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitRootLogin'
|
||||
line: 'PermitRootLogin prohibit-password'
|
||||
validate: 'sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
|
||||
- name: SSH | Passwort-Authentifizierung deaktivieren
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PasswordAuthentication'
|
||||
line: 'PasswordAuthentication no'
|
||||
validate: 'sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
|
||||
- name: SSH | Leere Passwörter verbieten
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitEmptyPasswords'
|
||||
line: 'PermitEmptyPasswords no'
|
||||
validate: 'sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
[http]
|
||||
[http.middlewares]
|
||||
[http.middlewares.authentik.forwardAuth]
|
||||
address = "http://authentik_server:9000/outpost.goauthentik.io/auth/traefik"
|
||||
trustForwardHeader = true
|
||||
authResponseHeaders = [
|
||||
"X-authentik-username",
|
||||
"X-authentik-groups",
|
||||
"X-authentik-email",
|
||||
"X-authentik-name",
|
||||
"X-authentik-uid",
|
||||
"X-authentik-jwt",
|
||||
"X-authentik-meta-jwks",
|
||||
"X-authentik-meta-outpost",
|
||||
"X-authentik-meta-provider",
|
||||
"X-authentik-meta-app",
|
||||
"X-authentik-meta-version"
|
||||
]
|
||||
@@ -0,0 +1,80 @@
|
||||
[global]
|
||||
checkNewVersion = true
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[experimental]
|
||||
otlpLogs = true
|
||||
|
||||
[core]
|
||||
defaultRuleSyntax = "v2"
|
||||
|
||||
[accessLog]
|
||||
filePath = "/logs/access.log"
|
||||
format = "json"
|
||||
|
||||
# Enable the Dashboard
|
||||
[api]
|
||||
dashboard = true
|
||||
|
||||
# Write out Traefik logs
|
||||
[log]
|
||||
level = "INFO"
|
||||
format = "json"
|
||||
filePath = "/logs/traefik.log"
|
||||
# [log.otlp.http]
|
||||
# endpoint = "http://signoz_otel-collector:4318/v1/logs"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.http]
|
||||
address = ":80"
|
||||
[entryPoints.http.http.redirections.entryPoint]
|
||||
to = "https"
|
||||
scheme = "https"
|
||||
|
||||
[entryPoints.https]
|
||||
address = ":443"
|
||||
# [entryPoints.https.http.tls]
|
||||
# certResolver = "main"
|
||||
|
||||
# OTel
|
||||
# [tracing]
|
||||
# serviceName = "traefik"
|
||||
# [tracing.otlp.http]
|
||||
# endpoint = "http://signoz_otel-collector:4318/v1/traces"
|
||||
# [tracing.otlp.http.tls]
|
||||
# insecureSkipVerify = true
|
||||
|
||||
# # Metrics
|
||||
# [metrics]
|
||||
# addInternals = false
|
||||
# [metrics.otlp]
|
||||
# serviceName = "traefik"
|
||||
# addEntryPointsLabels = true
|
||||
# addRoutersLabels = true
|
||||
# addServicesLabels = true
|
||||
# [metrics.otlp.http]
|
||||
# endpoint = "http://signoz_otel-collector:4318/v1/metrics"
|
||||
# [metrics.otlp.grpc]
|
||||
# endpoint = "monitoring_alloy:4317"
|
||||
# insecure = true
|
||||
|
||||
# Let's Encrypt
|
||||
[certificatesResolvers.main.acme]
|
||||
email = "ma@coachhamburg.com"
|
||||
storage = "acme.json"
|
||||
# uncomment to use staging CA for testing
|
||||
# caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
# [certificatesResolvers.main.acme.tlsChallenge]
|
||||
[certificatesResolvers.main.acme.dnsChallenge]
|
||||
provider = "digitalocean"
|
||||
# Uncomment to use HTTP validation, like a caveman!
|
||||
# [certificatesResolvers.main.acme.httpChallenge]
|
||||
# entryPoint = "http"
|
||||
|
||||
[providers]
|
||||
[providers.swarm]
|
||||
endpoint = "unix:///var/run/docker.sock"
|
||||
exposedByDefault = false
|
||||
[providers.file]
|
||||
directory = "/etc/traefik/dynamic"
|
||||
watch = true
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
- name: TRAEFIK | Copy Stack Files
|
||||
copy:
|
||||
directory_mode: true
|
||||
src: traefik
|
||||
dest: "{{ ceph_volume }}"
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: TRAEFIK | Generate Compose file
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ data_dir }}/traefik.yml"
|
||||
mode: 0644
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: TRAEFIK | Ensure permissions on acme.json
|
||||
ansible.builtin.file:
|
||||
path: "{{ data_dir }}/data/acme.json"
|
||||
mode: '0600'
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: TRAEFIK | traefik_public Netzwerk erstellen
|
||||
community.docker.docker_network:
|
||||
name: traefik_public
|
||||
driver: overlay
|
||||
state: present
|
||||
attachable: yes
|
||||
ipam_config:
|
||||
- subnet: '172.16.200.0/24'
|
||||
gateway: '172.16.200.1'
|
||||
run_once: true
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
|
||||
- name: TRAEFIK | Deploy app stack
|
||||
community.docker.docker_stack:
|
||||
state: present
|
||||
name: traefik
|
||||
compose:
|
||||
- "{{ data_dir }}/traefik.yml"
|
||||
delegate_to: "{{ groups['managers'][0] }}"
|
||||
run_once: true
|
||||
@@ -0,0 +1,55 @@
|
||||
services:
|
||||
app:
|
||||
image: traefik:{{ traefik_version }}
|
||||
ports:
|
||||
- target: 80
|
||||
published: 80
|
||||
protocol: tcp
|
||||
mode: host
|
||||
- target: 443
|
||||
published: 443
|
||||
protocol: tcp
|
||||
mode: host
|
||||
- target: 8080
|
||||
published: 8080
|
||||
protocol: tcp
|
||||
environment:
|
||||
# - HETZNER_API_TOKEN={{ hetzner_api_key }}
|
||||
- DO_AUTH_TOKEN={{ do_api_key }}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- {{ data_dir }}/config:/etc/traefik
|
||||
- {{ data_dir }}/data/logs:/logs
|
||||
- {{ data_dir }}/data/acme.json:/acme.json
|
||||
# healthcheck:
|
||||
# test: ["CMD", "traefik", "healthcheck", "--ping"]
|
||||
# timeout: 1s
|
||||
# interval: 10s
|
||||
# retries: 3
|
||||
# start_period: 10s
|
||||
networks:
|
||||
- {{ traefik_public_net }}
|
||||
# Global mode makes an instance of traefik listen on _every_ node, so that regardless of which
|
||||
# node the request arrives on, it'll be forwarded to the correct backend service.
|
||||
deploy:
|
||||
mode: global
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.swarm.network={{ traefik_public_net }}"
|
||||
- "traefik.http.routers.api.rule=Host(`{{ subdomain }}.{{ main_domain }}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
|
||||
- "traefik.http.routers.api.entrypoints=https"
|
||||
{% if use_authentik %}
|
||||
- "traefik.http.routers.api.middlewares=authentik@file"
|
||||
{% endif %}
|
||||
- "traefik.http.routers.api.tls.domains[0].main={{ main_domain }}"
|
||||
- "traefik.http.routers.api.tls.domains[0].sans=*.{{ main_domain }}"
|
||||
- "traefik.http.routers.api.tls=true"
|
||||
- "traefik.http.routers.api.tls.certresolver=main"
|
||||
- "traefik.http.routers.api.service=api@internal"
|
||||
- "traefik.http.services.dummy.loadbalancer.server.port=9999"
|
||||
placement:
|
||||
constraints: [node.role == manager]
|
||||
|
||||
networks:
|
||||
{{ traefik_public_net }}:
|
||||
external: true
|
||||
@@ -0,0 +1,5 @@
|
||||
subdomain: router
|
||||
use_authentik: true
|
||||
data_dir: "{{ ceph_volume }}/traefik"
|
||||
|
||||
traefik_version: v3.6.2
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
- name: FIREWALL | UFW auf Standardeinstellungen zurücksetzen
|
||||
community.general.ufw:
|
||||
state: reset
|
||||
|
||||
- name: FIREWALL | Standardmäßig allen ausgehenden Traffic erlauben
|
||||
community.general.ufw:
|
||||
direction: outgoing
|
||||
policy: allow
|
||||
|
||||
- name: FIREWALL | Standardmäßig allen eingehenden Traffic blockieren
|
||||
community.general.ufw:
|
||||
direction: incoming
|
||||
policy: deny
|
||||
|
||||
- name: FIREWALL | Eingehenden SSH-Traffic auf öffentlichem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
interface: "{{ public_interface }}"
|
||||
direction: in
|
||||
|
||||
- name: FIREWALL | Eingehenden SSH-Traffic auf privatem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
interface: "{{ private_interface }}"
|
||||
direction: in
|
||||
|
||||
- name: FIREWALL | Eingehenden HTTP/HTTPS-Traffic auf öffentlichem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item.port }}"
|
||||
proto: "{{ item.proto }}"
|
||||
interface: "{{ public_interface }}"
|
||||
direction: in
|
||||
with_items:
|
||||
- { port: '80', proto: 'tcp' }
|
||||
- { port: '443', proto: 'tcp' }
|
||||
|
||||
- name: FIREWALL | Ceph Monitor Ports auf privatem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
interface: "{{ private_interface }}"
|
||||
direction: in
|
||||
with_items:
|
||||
- '3300'
|
||||
- '6789'
|
||||
|
||||
- name: FIREWALL | Ceph OSD/MGR Port-Range auf öffentlichem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "6800:7568"
|
||||
proto: tcp
|
||||
interface: "{{ private_interface }}"
|
||||
direction: in
|
||||
|
||||
- name: FIREWALL | Docker Swarm Management Ports auf privatem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "2377"
|
||||
proto: tcp
|
||||
interface: "{{ private_interface }}"
|
||||
direction: in
|
||||
|
||||
- name: FIREWALL | Docker Swarm Discovery/Network Ports auf privatem Interface erlauben
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ item.port }}"
|
||||
proto: "{{ item.proto }}"
|
||||
interface: "{{ private_interface }}"
|
||||
direction: in
|
||||
with_items:
|
||||
- { port: '7946', proto: 'tcp' }
|
||||
- { port: '7946', proto: 'udp' }
|
||||
- { port: '4789', proto: 'udp' }
|
||||
|
||||
- name: FIREWALL | UFW aktivieren
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
Reference in New Issue
Block a user