chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,44 @@
---
# Standardwerte für die App-Rolle
# Standardwerte für die App-Rolle
# Deployment-Verzeichnisse
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"
# Quellverzeichnis für Dateisynchronisation
project_source: "{{ playbook_dir | dirname | dirname }}"
# Domain
app_domain: "localhost"
---
# Standardwerte für die App-Rolle
---
# Standardwerte für die App-Rolle
# Deployment-Verzeichnisse
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"
# Deployment-Variablen
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
deploy_user: deploy
# Anwendungsvariablen
app_domain: "{{ hostvars[inventory_hostname]['ansible_host'] | default(inventory_hostname) }}"
project_source: "{{ playbook_dir }}/../.."
project_root: "{{ playbook_dir }}/../.."
# Docker-Compose-Pfad
docker_compose_project_path: "{{ deploy_root }}"
# Diese Werte werden nur verwendet, wenn sie nicht anderweitig definiert sind
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
deploy_user: "{{ ansible_user | default('deploy') }}"
app_domain: "localhost"
project_root: "{{ playbook_dir | dirname }}"

View File

@@ -0,0 +1,622 @@
---
- name: Prüfe erforderliche Variablen
assert:
that:
- deploy_root is defined
- deploy_user is defined
fail_msg: "Erforderliche Variablen fehlen: deploy_root und/oder deploy_user nicht definiert"
success_msg: "Alle erforderlichen Variablen sind korrekt definiert"
tags: [always]
- name: Projektverzeichnisse erstellen
file:
path: "{{ item }}"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
loop:
- "{{ deploy_root }}"
- "{{ deploy_root }}/ssl"
- "{{ deploy_root }}/public"
- "{{ deploy_root }}/src"
- "{{ deploy_root }}/docker"
- name: SSL-Zertifikate prüfen
stat:
path: "/etc/letsencrypt/live/{{ app_domain }}/fullchain.pem"
register: ssl_certs
- name: SSL-Zertifikate kopieren (falls vorhanden)
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
remote_src: yes
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
loop:
- { src: "/etc/letsencrypt/live/{{ app_domain }}/fullchain.pem", dest: "{{ deploy_root }}/ssl/fullchain.pem" }
- { src: "/etc/letsencrypt/live/{{ app_domain }}/privkey.pem", dest: "{{ deploy_root }}/ssl/privkey.pem" }
when: ssl_certs.stat.exists
- name: Lokales public-Verzeichnis prüfen
stat:
path: "{{ playbook_dir }}/../../public"
register: public_dir
delegate_to: localhost
become: false
- name: public-Verzeichnis synchronisieren
synchronize:
src: "{{ playbook_dir }}/../../public/"
dest: "{{ deploy_public }}/"
delete: yes
recursive: yes
when: public_dir.stat.exists and public_dir.stat.isdir
- name: Lokale docker-compose.yml Datei prüfen
stat:
path: "{{ playbook_dir }}/../../docker-compose.yml"
register: docker_compose_file
delegate_to: localhost
become: false
- name: Projekt-Stammdaten kopieren
copy:
src: "{{ playbook_dir }}/../../docker-compose.yml"
dest: "{{ deploy_root }}/docker-compose.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
when: docker_compose_file.stat.exists
- name: .env-Datei prüfen
stat:
path: "{{ project_root }}/.env"
register: env_file
delegate_to: localhost
become: false
- name: .env kopieren (falls vorhanden)
copy:
src: "{{ project_root }}/.env"
dest: "{{ deploy_root }}/.env"
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
when: env_file.stat.exists
- name: Erstelle Standard-.env-Datei, wenn keine existiert
copy:
dest: "{{ deploy_root }}/.env"
content: |
COMPOSE_PROJECT_NAME=michaelschiemer
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
when: not env_file.stat.exists
- name: Lokales src-Verzeichnis prüfen
stat:
path: "{{ playbook_dir }}/../../src"
register: src_dir
delegate_to: localhost
become: false
- name: Quellcode synchronisieren
synchronize:
src: "{{ playbook_dir }}/../../src/"
dest: "{{ deploy_root }}/src/"
delete: yes
recursive: yes
when: src_dir.stat.exists and src_dir.stat.isdir
- name: Docker-Verzeichnis prüfen
stat:
path: "{{ project_root }}/docker"
register: docker_dir
delegate_to: localhost
become: false
- name: Docker-Configs synchronisieren (falls vorhanden)
synchronize:
src: "{{ project_root }}/docker/"
dest: "{{ deploy_root }}/docker/"
delete: yes
recursive: yes
when: docker_dir.stat.exists
- name: Rechte im Zielverzeichnis korrigieren
file:
path: "{{ deploy_root }}"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
recurse: yes
# Cache-Verzeichnis für UID/GID 1000 (z.B. appuser im Container)
- name: Stelle Schreibrechte für Cache-Verzeichnis her
file:
path: "{{ deploy_root }}/cache"
state: directory
owner: 1000
group: 1000
mode: '0775'
recurse: yes
- name: Erstelle .env-Datei für Docker Compose
copy:
dest: "{{ deploy_root }}/.env"
content: |
COMPOSE_PROJECT_NAME=michaelschiemer
APP_ENV=production
APP_PORT=80
APP_SSL_PORT=443
COMPOSER_INSTALL_FLAGS=--no-dev --optimize-autoloader
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
when: not env_file.stat.exists
- name: Prüfe docker-compose.yml im project_root
stat:
path: "{{ project_root }}/docker-compose.yml"
register: compose_file
delegate_to: localhost
become: false
- name: Docker-Compose-Konfiguration für Deployment anpassen
copy:
dest: "{{ deploy_root }}/docker-compose-deploy.yml"
content: |
version: '3.8'
services:
php:
build:
context: {{ deploy_root }}/docker/php
dockerfile: Dockerfile-simple
volumes:
- {{ deploy_root }}/src:/var/www/html/src:rw
- {{ deploy_root }}/public:/var/www/html/public:rw
networks:
- backend
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- {{ deploy_root }}/public:/var/www/html/public:ro
- {{ deploy_root }}/docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- {{ deploy_root }}/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
networks:
- frontend
- backend
redis:
image: redis:alpine
networks:
- cache
networks:
frontend:
backend:
cache:
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
- name: Stelle sicher, dass die Nginx-Verzeichnisstruktur korrekt ist
file:
path: "{{ deploy_root }}/docker/nginx"
state: directory
mode: '0755'
- name: Bereinige nginx.conf Verzeichnis falls es existiert
shell: |
if [ -d "{{ deploy_root }}/docker/nginx/nginx.conf" ]; then
rm -rf "{{ deploy_root }}/docker/nginx/nginx.conf"
fi
args:
executable: /bin/bash
ignore_errors: yes
- name: Erstelle Dockerfile für Nginx
copy:
dest: "{{ deploy_root }}/docker/nginx/Dockerfile"
content: |
FROM nginx:alpine
# Konfigurationen kopieren
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
# Erstelle Verzeichnis für SSL
RUN mkdir -p /etc/nginx/ssl
# Starte nginx im Vordergrund
CMD ["nginx", "-g", "daemon off;"]
mode: '0644'
- name: Docker-Compose-Datei für Deployment anpassen (PHP Dockerfile)
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: 'dockerfile: docker/php/Dockerfile'
replace: 'dockerfile: {{ deploy_root }}/docker/php/Dockerfile'
---
# App Deployment Tasks
- name: Prüfe erforderliche Variablen
assert:
that:
- deploy_root is defined
- deploy_user is defined
fail_msg: "Erforderliche Variablen fehlen: deploy_root und/oder deploy_user nicht definiert"
success_msg: "Alle erforderlichen Variablen sind korrekt definiert"
tags: [always]
- name: Projektverzeichnisse erstellen
file:
path: "{{ item }}"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
loop:
- "{{ deploy_root }}"
- "{{ deploy_root }}/ssl"
- "{{ deploy_root }}/public"
- "{{ deploy_root }}/src"
- "{{ deploy_root }}/docker"
- name: Erstelle einfache Test-HTML-Datei
copy:
dest: "{{ deploy_root }}/public/index.html"
content: |
<!DOCTYPE html>
<html>
<head>
<title>App ist aktiv</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
h1 { color: #3273dc; }
.container { max-width: 800px; margin: 0 auto; padding: 20px; border: 1px solid #eee; border-radius: 5px; }
</style>
</head>
<body>
<div class="container">
<h1>Anwendung ist aktiv!</h1>
<p>Diese Seite bestätigt, dass das App-Deployment erfolgreich war.</p>
<p>Server: {{ inventory_hostname }}</p>
</div>
</body>
</html>
mode: '0644'
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
- name: Docker-Compose-Datei für Deployment anpassen (Nginx Context)
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: 'context: docker/nginx'
replace: 'context: {{ deploy_root }}/docker/nginx'
- name: Docker-Volumes in docker-compose.yml anpassen (korrigiert)
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: '(\s+-)?\s+\./(.+?)(?::cached|:delegated)?(?::rw|:ro)?$'
replace: '\1 {{ deploy_root }}/\2'
with_items:
- volumes
- volume
- name: Docker-Volumes für Redis anpassen
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: '\./docker/redis/redis.conf'
replace: '{{ deploy_root }}/docker/redis/redis.conf'
- name: Korrigiere spezielle Volume-Optionen (cached, delegated)
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: '{{ deploy_root }}/([^:]+):cached'
replace: '{{ deploy_root }}/\1:rw'
- name: Korrigiere spezielle Volume-Optionen (delegated)
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: '{{ deploy_root }}/([^:]+):delegated'
replace: '{{ deploy_root }}/\1:rw'
- name: Finde und korrigiere ungültige Volume-Spezifikationen
shell: |
sed -i 's|{{ deploy_root }}/var/www/html:|{{ deploy_root }}:|g' {{ deploy_root }}/docker-compose-deploy.yml
sed -i 's|:cached:rw|:rw|g' {{ deploy_root }}/docker-compose-deploy.yml
sed -i 's|:delegated:rw|:rw|g' {{ deploy_root }}/docker-compose-deploy.yml
cat {{ deploy_root }}/docker-compose-deploy.yml | grep -A 20 volumes
args:
chdir: "{{ deploy_root }}"
register: volume_debug
- name: Erstelle einfache Docker Compose-Datei als Fallback
copy:
dest: "{{ deploy_root }}/docker-compose-simple.yml"
content: |
version: '3.8'
services:
php:
build:
context: {{ deploy_root }}/docker/php
dockerfile: Dockerfile-simple
volumes:
- {{ deploy_root }}/src:/var/www/html/src:rw
- {{ deploy_root }}/public:/var/www/html/public:rw
networks:
- backend
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- {{ deploy_root }}/public:/var/www/html/public:ro
- {{ deploy_root }}/docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- php
networks:
- frontend
- backend
redis:
image: redis:alpine
networks:
- cache
networks:
frontend:
backend:
cache:
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
- name: Erstelle composer.lock-Datei wenn diese nicht existiert
file:
path: "{{ deploy_root }}/composer.lock"
state: touch
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
register: composer_lock_created
- name: Prüfe ob Dockerfile existiert
stat:
path: "{{ project_root }}/docker/php/Dockerfile"
register: dockerfile_exists
delegate_to: localhost
become: false
- name: Erstelle angepasste Dockerfile für PHP
copy:
dest: "{{ deploy_root }}/docker/php/Dockerfile-deploy"
content: |
FROM php:8.4-fpm
RUN apt-get update && apt-get install -y \
git \
unzip \
libzip-dev \
zip \
&& docker-php-ext-install zip pdo pdo_mysql \
&& docker-php-ext-install opcache \
&& docker-php-ext-install pcntl posix shmop \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html
# Kopiere Projektdateien
COPY . /var/www/html/
# Stelle sicher, dass der Webserver Zugriff auf Dateien hat
RUN chown -R www-data:www-data /var/www/html
CMD ["php-fpm"]
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
# Task entfernt, da wir jetzt direkt eine vollständige Dockerfile erstellen
# und nicht mehr eine vorhandene Datei anpassen müssen
- name: Erstelle vereinfachte Dockerfile für PHP
copy:
dest: "{{ deploy_root }}/docker/php/Dockerfile-simple"
content: |
FROM php:8.4-fpm
RUN apt-get update && apt-get install -y \
git \
unzip \
libzip-dev \
zip \
&& docker-php-ext-install zip pdo pdo_mysql \
&& docker-php-ext-install opcache \
&& docker-php-ext-install pcntl posix shmop \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html
# Kein Composer-Befehl hier
CMD ["php-fpm"]
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
- name: Docker-Compose-Datei anpassen um die modifizierte Dockerfile zu verwenden
replace:
path: "{{ deploy_root }}/docker-compose-deploy.yml"
regexp: 'dockerfile: {{ deploy_root }}/docker/php/Dockerfile'
replace: 'dockerfile: {{ deploy_root }}/docker/php/Dockerfile-simple'
- name: Erstelle composer.json für Docker-Build
copy:
dest: "{{ deploy_root }}/composer.json"
content: |
{
"name": "michaelschiemer/website",
"description": "Michael Schiemer Website",
"type": "project",
"require": {
"php": "^8.1"
},
"minimum-stability": "stable"
}
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
- name: Debug-Info für Docker Compose
debug:
msg: "Versuche, Container zu starten mit Docker Compose-Datei: {{ deploy_root }}/docker-compose-simple.yml"
- name: Zeige Docker Images
shell: docker images
register: docker_images
ignore_errors: yes
- name: Docker Images anzeigen
debug:
var: docker_images.stdout_lines
- name: Zeige laufende Docker Container
shell: docker ps -a
register: docker_containers
ignore_errors: yes
- name: Docker Container anzeigen
debug:
var: docker_containers.stdout_lines
- name: Docker Compose Container stoppen
shell: |
cd {{ deploy_root }} && \
docker-compose -f {{ deploy_root }}/docker-compose-simple.yml -p michaelschiemer down --remove-orphans || true
args:
chdir: "{{ deploy_root }}"
environment:
COMPOSE_IGNORE_ORPHANS: "True"
- name: Prüfe ob docker-compose-simple.yml existiert
stat:
path: "{{ deploy_root }}/docker-compose-simple.yml"
register: simple_compose_file
- name: Anzeigen des Inhalts der docker-compose-simple.yml Datei
shell: cat {{ deploy_root }}/docker-compose-simple.yml
register: compose_content
when: simple_compose_file.stat.exists
- name: Anzeigen des Inhalts der docker-compose-simple.yml Datei
debug:
var: compose_content.stdout_lines
when: compose_content is defined
- name: Verzeichnisse in nginx Docker Verzeichnis anzeigen
shell: "ls -la {{ deploy_root }}/docker/nginx"
register: nginx_dir_content
- name: Nginx Verzeichnisinhalt anzeigen
debug:
var: nginx_dir_content.stdout_lines
- name: Stoppe alle Docker Container
shell: |
cd {{ deploy_root }} && \
docker-compose -f {{ deploy_root }}/docker-compose-simple.yml -p michaelschiemer down --remove-orphans
args:
chdir: "{{ deploy_root }}"
ignore_errors: yes
environment:
COMPOSE_IGNORE_ORPHANS: "True"
- name: Bereinige Docker-Systemressourcen
shell: docker system prune -f
ignore_errors: yes
- name: Docker Compose neu bauen und starten (vereinfachte Version)
shell: |
cd {{ deploy_root }} && \
export DOCKER_BUILDKIT=0 && \
docker-compose -f {{ deploy_root }}/docker-compose-simple.yml -p michaelschiemer up -d --build
args:
chdir: "{{ deploy_root }}"
ignore_errors: yes
environment:
COMPOSE_IGNORE_ORPHANS: "True"
- name: Warte kurz bis Docker-Container gestartet sind
pause:
seconds: 5
- name: Prüfe welche Prozesse an Port 80 gebunden sind
shell: |
netstat -tulpn | grep LISTEN | grep ':80' || echo "Kein Prozess an Port 80 gebunden"
register: port_80_check
ignore_errors: yes
- name: Zeige Port 80 Bindung
debug:
var: port_80_check.stdout_lines
- name: Prüfe Docker-Container Netzwerkeinstellungen
shell: |
docker inspect michaelschiemer-nginx-1 | grep -A 20 "NetworkSettings" || echo "Container nicht gefunden"
register: container_network
ignore_errors: yes
- name: Zeige Container-Netzwerkeinstellungen
debug:
var: container_network.stdout_lines
- name: PHP-Container für Composer starten
shell: docker-compose -f {{ deploy_root }}/docker-compose-simple.yml -p michaelschiemer up -d php
args:
chdir: "{{ deploy_root }}"
- name: Kurze Wartezeit bis PHP-Container bereit
wait_for:
timeout: 5
- name: Composer Abhängigkeiten installieren (deaktiviert)
debug:
msg: "Composer-Installation übersprungen - keine PHP-Anwendung vorhanden"
register: composer_result
- name: Composer-Ergebnis anzeigen
debug:
var: composer_result.stdout_lines
when: composer_result.stdout is defined
- name: Composer-Fehler anzeigen
debug:
var: composer_result.stderr_lines
when: composer_result.stderr is defined

View File

@@ -0,0 +1,12 @@
---
# Standardwerte für die Common-Rolle
# Verzeichnisse
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"
# Domain
app_domain: "localhost"

View File

@@ -0,0 +1,101 @@
---
# Common-Rolle für grundlegende Systemeinstellungen
- name: Setze globale Variablen
set_fact:
deploy_root: "{{ deploy_root | default('/var/www/michaelschiemer') }}"
deploy_user: "{{ deploy_user | default(ansible_user) }}"
app_domain: "{{ app_domain | default('localhost') }}"
tags: [always]
- name: Aktualisiere Paketindex
apt:
update_cache: yes
cache_valid_time: 3600
tags: [always]
- name: Installiere grundlegende Pakete
apt:
name:
- sudo
- vim
- htop
- git
- zip
- unzip
- curl
- wget
- net-tools
- rsync
- python3-pip
- ufw
- fail2ban
state: present
tags: [system, packages]
- name: Setze Zeitzone auf Europe/Berlin
timezone:
name: Europe/Berlin
tags: [system, timezone]
# Benutzer und Berechtigungen
- name: Stelle sicher, dass Deploy-Benutzer existiert
user:
name: "{{ deploy_user }}"
shell: /bin/bash
groups: sudo
append: yes
createhome: yes
state: present
when: deploy_user != 'root' and ansible_connection != 'local'
tags: [system, user]
- name: Stelle sicher, dass SSH-Verzeichnis existiert
file:
path: "/home/{{ deploy_user }}/.ssh"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0700'
when: deploy_user != 'root' and ansible_connection != 'local'
tags: [system, user]
- name: Konfiguriere passwordless sudo für deploy-Benutzer
lineinfile:
path: "/etc/sudoers.d/{{ deploy_user }}"
line: "{{ deploy_user }} ALL=(ALL) NOPASSWD: ALL"
state: present
create: yes
mode: '0440'
validate: 'visudo -cf %s'
become: true
when: deploy_user != 'root' and ansible_connection != 'local'
tags: [system, user]
# Firewall
- name: Öffne Ports in Firewall
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- '22' # SSH
- '80' # HTTP
- '443' # HTTPS
tags: [system, firewall]
- name: Aktiviere Firewall
ufw:
state: enabled
policy: deny
tags: [system, firewall]
# Verzeichnisse
- name: Erstelle deploy_root-Verzeichnis
file:
path: "{{ deploy_root }}"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
tags: [system, directories]

View File

@@ -0,0 +1,9 @@
- name: Füge Funktion für ms (mit Argumenten) hinzu
blockinfile:
path: "/home/{{ ansible_user }}/.bashrc"
marker: "# {mark} ms docker alias"
block: |
ms() {
docker compose exec php php ms "$@"
}
become: false

View File

@@ -0,0 +1,14 @@
- name: Stoppe laufende Container
command: docker compose down
args:
chdir: "{{ playbook_dir }}/../"
- name: Baue Images neu (ohne Cache)
command: docker compose build --no-cache
args:
chdir: "{{ playbook_dir }}/../"
- name: Starte Container neu
command: docker compose up -d
args:
chdir: "{{ playbook_dir }}/../"

View File

@@ -0,0 +1,36 @@
# Automatisch generierte .env-Datei
# Generiert durch Ansible am {{ ansible_date_time.date }}
COMPOSE_PROJECT_NAME={{ compose_project_name | default('michaelschiemer') }}
# Allgemeine Einstellungen
APP_NAME={{ app_name | default('michaelschiemer') }}
APP_ENV={{ env_vars.APP_ENV | default('production') }}
APP_DEBUG={{ env_vars.APP_DEBUG | default('false') }}
APP_PORT={{ env_vars.APP_PORT | default(80) }}
APP_SSL_PORT={{ env_vars.APP_SSL_PORT | default(443) }}
# Server-Konfiguration
APP_URL={{ 'https' if ssl_enabled | default(false) else 'http' }}://{{ app_domain }}
# Datenbank-Einstellungen
{% if lookup('vars', 'database_host', default=false) %}
DB_CONNECTION=mysql
DB_HOST={{ database_host }}
DB_PORT=3306
DB_DATABASE={{ database_name }}
DB_USERNAME={{ database_user }}
DB_PASSWORD={{ database_password | default('') }}
{% endif %}
# Redis-Konfiguration
{% if lookup('vars', 'redis_host', default=false) %}
REDIS_HOST={{ redis_host }}
REDIS_PASSWORD={{ redis_password | default(null) }}
REDIS_PORT={{ redis_port | default(6379) }}
{% endif %}
# Weitere Umgebungsspezifische Einstellungen
{% for key, value in env_vars.items() if key not in ['APP_ENV', 'APP_DEBUG', 'APP_PORT', 'APP_SSL_PORT'] %}
{{ key }}={{ value }}
{% endfor %}

View File

@@ -0,0 +1,9 @@
# Rolle: Docker
Diese Rolle installiert Docker Engine, CLI, Compose-Plugin sowie (optional) Docker Compose V1 als Fallback.
- Fügt den gewünschten User zur Docker-Gruppe hinzu.
- Startet und aktiviert den Docker-Dienst.
## Variablen
- `docker_compose_version`: Version von Docker Compose V1 für Fallback (Standard: 1.29.2).
- `docker_user`: Benutzer, der in die Gruppe `docker` aufgenommen werden soll (Standard: aktueller Ansible-User).

View File

@@ -0,0 +1,16 @@
# Standardwerte für die Docker-Rolle
# Docker-Version
docker_version: "20.10"
docker_compose_version: "2.24.5"
# Docker-Einstellungen
docker_install_compose: true
docker_user: "{{ ansible_user | default('michael') }}"
# Deployment-Verzeichnisse
deploy_root: /var/www/michaelschiemer
docker_compose_project_path: "{{ deploy_root }}"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"

View File

@@ -0,0 +1,4 @@
- name: restart docker
ansible.builtin.service:
name: docker
state: restarted

View File

@@ -0,0 +1,191 @@
- name: Prüfe erforderliche Variablen
assert:
that:
- deploy_root is defined
- deploy_user is defined
fail_msg: "Erforderliche Variablen fehlen: deploy_root und/oder deploy_user nicht definiert"
success_msg: "Alle erforderlichen Variablen sind korrekt definiert"
tags: [always]
- name: Docker-Abhängigkeiten installieren
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
state: present
update_cache: yes
---
# Docker-Installation und -Konfiguration
- name: Docker-Abhängigkeiten installieren
apt:
name:
- ca-certificates
- curl
- gnupg
- apt-transport-https
- software-properties-common
state: present
update_cache: yes
---
# Tasks für Docker-Installation
- name: Docker-Abhängigkeiten installieren
apt:
name:
- apt-transport-https
- ca-certificates
- gnupg
- lsb-release
state: present
- name: Docker GPG-Schlüssel hinzufügen
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Docker Repository hinzufügen
apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable
state: present
- name: Docker installieren
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
update_cache: yes
- name: Docker-Gruppe erstellen
group:
name: docker
state: present
- name: Benutzer zur Docker-Gruppe hinzufügen
user:
name: "{{ deploy_user }}"
groups: docker
append: yes
- name: Docker-Dienst aktivieren und starten
service:
name: docker
state: started
enabled: yes
- name: Prüfen, ob Docker funktioniert
shell: docker --version
register: docker_version
changed_when: false
- name: Docker-Version anzeigen
debug:
var: docker_version.stdout
- name: Docker GPG-Schlüssel hinzufügen
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Docker-Repository hinzufügen
apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable
state: present
- name: Docker installieren
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
state: present
update_cache: yes
- name: Docker-Gruppe erstellen
group:
name: docker
state: present
- name: Deploy-Benutzer zur Docker-Gruppe hinzufügen
user:
name: "{{ deploy_user }}"
groups: docker
append: yes
- name: Docker-Service aktivieren und starten
systemd:
name: docker
state: started
enabled: yes
- name: Docker Compose herunterladen
get_url:
url: "https://github.com/docker/compose/releases/download/v{{ docker_compose_version }}/docker-compose-Linux-x86_64"
dest: /usr/local/bin/docker-compose
mode: '0755'
- name: Docker-Verzeichnisse und -Dateien kopieren
copy:
src: "{{ playbook_dir }}/../docker/"
dest: "{{ deploy_root }}/docker/"
directory_mode: '0755'
mode: '0644'
- name: Docker Compose-Datei kopieren
copy:
src: "{{ playbook_dir }}/../docker-compose.yml"
dest: "{{ deploy_root }}/docker-compose.yml"
mode: '0644'
- name: Docker GPG-Schlüssel hinzufügen
apt_key:
url: https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg
state: present
- name: Docker Repository hinzufügen
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
state: present
- name: Docker Engine installieren
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
update_cache: yes
- name: Docker Compose installieren (V1 als Fallback)
get_url:
url: "https://github.com/docker/compose/releases/download/v{{ docker_compose_version }}/docker-compose-linux-x86_64"
dest: /usr/local/bin/docker-compose
mode: '0755'
- name: Benutzer zur Docker-Gruppe hinzufügen
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
- name: Docker-Service starten und aktivieren
service:
name: docker
state: started
enabled: yes
notify: restart docker
- name: Starte Docker-Container via Compose
community.docker.docker_compose_v2:
#project_src: "{{ playbook_dir | dirname }}/../" # ggf. anpassen auf deinen Compose-Pfad!
project_src: "{{ deploy_root }}"
build: always
recreate: always
when: false

View File

@@ -0,0 +1,22 @@
---
# Standardwerte für die Nginx-Rolle
# Nginx-Konfiguration
nginx_worker_processes: auto
nginx_worker_connections: 1024
# Nginx-Verzeichnisse
nginx_target_dir: "{{ deploy_root }}/docker/nginx"
# SSL-Verzeichnisse
nginx_ssl_dest_dir: "{{ deploy_root }}/ssl"
# Deployment-Verzeichnisse
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"
# Domain
app_domain: "localhost"

View File

@@ -0,0 +1,14 @@
- name: reload nginx
ansible.builtin.shell: |
# Versuche unterschiedliche Container-Namen und Methoden
CONTAINER_ID=$(docker ps -q --filter name=michaelschiemer_nginx || docker ps -q --filter name=nginx)
if [ -n "$CONTAINER_ID" ]; then
docker exec $CONTAINER_ID nginx -s reload || true
else
# Wenn Container nicht gefunden, versuche Neustart über Docker Compose
cd {{ deploy_root }} && \
docker-compose -f {{ deploy_root }}/docker-compose-simple.yml restart nginx || true
fi
args:
executable: /bin/bash
ignore_errors: yes

View File

@@ -0,0 +1,299 @@
---
- name: Stelle sicher, dass Nginx-Verzeichnisse existieren
ansible.builtin.file:
path: "{{ nginx_target_dir }}"
state: directory
recurse: yes
mode: '0755'
- name: Kopiere Nginx-Konfigurationsdateien
ansible.builtin.copy:
src: "{{ playbook_dir }}/../docker/nginx/{{ item }}"
dest: "{{ nginx_target_dir }}/{{ item }}"
mode: '0644'
loop:
- nginx.conf
- default.conf
notify: reload nginx
- name: Erstelle nginx.conf
ansible.builtin.copy:
dest: "{{ nginx_target_dir }}/nginx.conf"
content: |
user nginx;
worker_processes {{ nginx_worker_processes }};
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
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" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
mode: '0644'
- name: Überprüfe ob default.conf ein Verzeichnis ist
stat:
path: "{{ nginx_target_dir }}/default.conf"
register: default_conf_stat
- name: Entferne default.conf Verzeichnis falls es existiert
file:
path: "{{ nginx_target_dir }}/default.conf"
state: absent
when: default_conf_stat.stat.exists and default_conf_stat.stat.isdir
- name: Erstelle default.conf
ansible.builtin.copy:
dest: "{{ nginx_target_dir }}/default.conf"
content: |
server {
listen 80;
listen [::]:80;
server_name {{ app_domain }};
# Weiterleitung auf HTTPS, wenn verfügbar
# location / {
# return 301 https://$host$request_uri;
# }
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Vite Dev Server Proxy (deaktiviert)
# include /etc/nginx/vite-proxy.inc;
}
# HTTPS Server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ app_domain }};
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Vite Dev Server Proxy (deaktiviert)
# include /etc/nginx/vite-proxy.inc;
}
mode: '0644'
- name: Prüfe ob vite-proxy.inc existiert
stat:
path: "{{ nginx_vite_proxy_src }}"
register: vite_proxy_exists
delegate_to: localhost
become: false
---
# Tasks für Nginx-Konfiguration
- name: Nginx-Konfigurationsverzeichnis erstellen
file:
path: "{{ deploy_root }}/docker/nginx"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
- name: Erstelle Nginx-Hauptkonfiguration
copy:
dest: "{{ deploy_root }}/docker/nginx/nginx.conf"
content: |
user nginx;
worker_processes {{ nginx_worker_processes }};
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
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" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
notify: reload nginx
- name: Erstelle Nginx-Default-Konfiguration
copy:
dest: "{{ deploy_root }}/docker/nginx/default.conf"
content: |
server {
listen 80;
server_name {{ app_domain }} localhost;
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'
notify: reload nginx
- name: Kopiere richtige vite-proxy.inc je nach Umgebung (falls vorhanden)
ansible.builtin.copy:
src: "{{ nginx_vite_proxy_src }}"
dest: "{{ nginx_target_dir }}/vite-proxy.inc"
mode: '0644'
notify: reload nginx
when: vite_proxy_exists.stat.exists
- name: Überprüfe ob vite-proxy.inc ein Verzeichnis ist
stat:
path: "{{ nginx_target_dir }}/vite-proxy.inc"
register: vite_proxy_stat
- name: Entferne vite-proxy.inc Verzeichnis falls es existiert
file:
path: "{{ nginx_target_dir }}/vite-proxy.inc"
state: absent
when: vite_proxy_stat.stat.exists and vite_proxy_stat.stat.isdir
- name: Erstelle Standard vite-proxy.inc Datei (falls nicht vorhanden)
ansible.builtin.copy:
dest: "{{ nginx_target_dir }}/vite-proxy.inc"
content: |
# Standard Vite Proxy Konfiguration
location /@vite/ {
proxy_pass http://localhost:5173/;
proxy_set_header Host $host;
}
location /@fs/ {
proxy_pass http://localhost:5173/;
proxy_set_header Host $host;
}
location /node_modules/ {
proxy_pass http://localhost:5173/node_modules/;
proxy_set_header Host $host;
}
mode: '0644'
notify: reload nginx
when: not vite_proxy_exists.stat.exists
- name: Überprüfe ob docker-entrypoint.sh ein Verzeichnis ist
stat:
path: "{{ nginx_target_dir }}/docker-entrypoint.sh"
register: entrypoint_stat
- name: Entferne docker-entrypoint.sh Verzeichnis falls es existiert
file:
path: "{{ nginx_target_dir }}/docker-entrypoint.sh"
state: absent
when: entrypoint_stat.stat.exists and entrypoint_stat.stat.isdir
- name: Erstelle docker-entrypoint Skript
ansible.builtin.copy:
dest: "{{ nginx_target_dir }}/docker-entrypoint.sh"
content: |
#!/bin/sh
# Überprüfe SSL-Zertifikate und erstelle selbstsignierte, wenn keine vorhanden sind
if [ ! -f /etc/nginx/ssl/fullchain.pem ] || [ ! -f /etc/nginx/ssl/privkey.pem ]; then
echo "Keine SSL-Zertifikate gefunden, erstelle selbstsignierte Zertifikate..."
mkdir -p /etc/nginx/ssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/privkey.pem \
-out /etc/nginx/ssl/fullchain.pem \
-subj "/CN=localhost"
fi
# Starte Nginx im Vordergrund
echo "Starte Nginx..."
exec nginx -g 'daemon off;'
mode: '0755'
- name: Baue und starte Nginx-Container (optional, wenn Compose separat genutzt wird, dann hier nicht nötig)
ansible.builtin.shell: |
export DOCKER_BUILDKIT=0
docker-compose -f "{{ deploy_root }}/docker-compose-simple.yml" up -d --build nginx
args:
chdir: "{{ deploy_root }}"
executable: /bin/bash
when: nginx_target_dir is defined and deploy_root is defined
register: nginx_compose_result
ignore_errors: true
environment:
COMPOSE_IGNORE_ORPHANS: "True"
PATH: "/usr/local/bin:/usr/bin:/bin"
- name: Zeige Compose-Resultat
ansible.builtin.debug:
var: nginx_compose_result.stdout_lines
when: nginx_compose_result is defined

View File

@@ -0,0 +1,23 @@
---
# Standardwerte für die PHP-Rolle
---
# Standardwerte für die PHP-Rolle
# PHP-Version
php_version: "8.1"
# PHP-Erweiterungen
php_extensions:
- zip
- pdo
- pdo_mysql
- opcache
# PHP-Version
php_version: "8.4"
# Deployment-Verzeichnisse
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"

View File

@@ -0,0 +1,33 @@
---
# PHP Installation und Konfiguration
- name: Stelle sicher, dass das PHP-Docker-Verzeichnis existiert
file:
path: "{{ deploy_root }}/docker/php"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
- name: Erstelle einfache PHP-Dockerfile
copy:
dest: "{{ deploy_root }}/docker/php/Dockerfile-simple"
content: |
FROM php:8.1-fpm
RUN apt-get update && apt-get install -y \
git \
unzip \
libzip-dev \
zip \
&& docker-php-ext-install zip pdo pdo_mysql \
&& docker-php-ext-install opcache \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html
CMD ["php-fpm"]
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'

View File

@@ -0,0 +1,19 @@
---
# Standardwerte für die Redis-Rolle
---
# Standardwerte für die Redis-Rolle
# Redis-Speicherlimit
redis_maxmemory: "128mb"
# Redis-Port
redis_port: 6379
# Deployment-Verzeichnisse
deploy_root: /var/www/michaelschiemer
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"
# Redis-Konfiguration
redis_maxmemory: "256mb"
redis_port: 6379

View File

@@ -0,0 +1,72 @@
---
# Redis Installation und Konfiguration
- name: Stelle sicher, dass das Redis-Docker-Verzeichnis existiert
file:
path: "{{ deploy_root }}/docker/redis"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0755'
- name: Erstelle Redis-Konfiguration
copy:
dest: "{{ deploy_root }}/docker/redis/redis.conf"
content: |
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
maxmemory {{ redis_maxmemory | default('128mb') }}
maxmemory-policy allkeys-lru
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: '0644'

View File

@@ -0,0 +1,12 @@
---
# Standardwerte für die Setup-Rolle
# Verzeichnisse
deploy_root: /var/www/michaelschiemer
deploy_public: "{{ deploy_root }}/public"
# Benutzer
deploy_user: "{{ ansible_user | default('deploy') }}"
# Domain
app_domain: "localhost"

View File

@@ -0,0 +1,4 @@
- name: Reload nginx
service:
name: nginx
state: reloaded

View File

@@ -0,0 +1,47 @@
- name: Docker installieren
apt:
name:
- docker.io
- docker-compose
state: present
update_cache: yes
- name: Certbot + Plugin installieren
apt:
name:
- certbot
- python3-certbot-nginx
state: present
update_cache: yes
- name: Challenge-Verzeichnis für Let's Encrypt anlegen
file:
path: /var/www/html/.well-known/acme-challenge
state: directory
owner: www-data
group: www-data
mode: '0755'
recurse: yes
- name: Füge Let's Encrypt Challenge-Pfad in den Nginx-Vhost ein
blockinfile:
path: /etc/nginx/sites-available/default
marker: "# {mark} ANSIBLE LETSENCRYPT"
insertafter: "^\\s*server\\s*{"
block: |
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
allow all;
default_type "text/plain";
}
notify: Reload nginx
- name: Let's Encrypt Zertifikat anfordern
command: >
certbot --nginx -n --agree-tos --redirect
-m kontakt@michaelschiemer.de
-d test.michaelschiemer.de
args:
creates: /etc/letsencrypt/live/test.michaelschiemer.de/fullchain.pem

View File

@@ -0,0 +1,18 @@
- name: Systempakete aktualisieren
apt:
update_cache: yes
upgrade: safe
autoremove: yes
autoclean: yes
register: upgrade_result
become: true
- name: Zeige ggf. Anzahl aktualisierter Pakete
debug:
msg: "Anzahl aktualisierter Pakete: {{ upgrade_result.stdout_lines | default([]) | length }}"
- name: Reboot durchführen, wenn notwendig
reboot:
msg: "Reboot wegen Kernel-/System-Update erforderlich"
pre_reboot_delay: 30
when: upgrade_result.changed

View File

@@ -0,0 +1,50 @@
- name: Certbot + Plugin installieren
apt:
name:
- certbot
- python3-certbot-nginx
state: present
update_cache: yes
when: letsencrypt_enabled
- name: Challenge-Verzeichnis für Let's Encrypt anlegen
file:
path: "{{ app_public }}/.well-known/acme-challenge"
state: directory
owner: www-data
group: www-data
mode: '0755'
recurse: yes
when: letsencrypt_enabled and letsencrypt_certbot_method == 'webroot'
- name: Stoppe Nginx für Standalone-Methode
service:
name: nginx
state: stopped
when: letsencrypt_enabled and letsencrypt_certbot_method == 'standalone'
- name: Let's Encrypt Zertifikat anfordern (Standalone)
command: >
certbot certonly --standalone -n --agree-tos
-m {{ app_email }}
-d {{ app_domain }}
args:
creates: /etc/letsencrypt/live/{{ app_domain }}/fullchain.pem
when: letsencrypt_enabled and letsencrypt_certbot_method == 'standalone'
- name: Let's Encrypt Zertifikat anfordern (Webroot)
command: >
certbot certonly --webroot -w {{ app_public }} -n --agree-tos
-m {{ app_email }}
-d {{ app_domain }}
args:
creates: /etc/letsencrypt/live/{{ app_domain }}/fullchain.pem
when: letsencrypt_enabled and letsencrypt_certbot_method == 'webroot'
- name: Kopiere SSL-Zertifikate für Docker
copy:
src: "/etc/letsencrypt/live/{{ app_domain }}/"
dest: "{{ app_root }}/ssl/"
remote_src: yes
mode: '0644'
when: letsencrypt_enabled