From d2304173f1b221f9727ffea55a8d923befe402ae Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Mon, 12 May 2025 07:58:10 +0200 Subject: [PATCH] corrections and improvements --- .gitignore | 2 + docu/70_postgresql.md | 49 +++++++ .../10_einrichten_ansible_auf_workstation.md | 13 +- docu/de/50_neues_ansknife_projekt.md | 8 +- docu/{ => de}/60_neue_webapplikation.md | 19 ++- playbooks.templates/i_10_basic.yaml | 6 +- playbooks.templates/i_40_php8.2.yaml | 2 +- playbooks.templates/i_51_seafile.yaml | 124 ++++++++++++++++++ playbooks.templates/i_70_webapps.yaml | 22 ---- ...i_21_nginx_sites.yaml => nginx_sites.yaml} | 0 playbooks.templates/pg_databases.yaml | 0 playbooks.templates/pg_users.yaml | 71 ++++++++++ playbooks/create_project.yaml | 7 + templates.vars/common.yaml | 5 +- templates.vars/mysql.yaml | 9 +- templates.vars/mysql_vault.yaml | 5 +- templates.vars/php.yaml | 38 +++--- templates.vars/webapps.yaml | 3 + 18 files changed, 318 insertions(+), 65 deletions(-) create mode 100644 .gitignore create mode 100644 docu/70_postgresql.md rename docu/{ => de}/60_neue_webapplikation.md (79%) create mode 100644 playbooks.templates/i_51_seafile.yaml delete mode 100644 playbooks.templates/i_70_webapps.yaml rename playbooks.templates/{i_21_nginx_sites.yaml => nginx_sites.yaml} (100%) create mode 100644 playbooks.templates/pg_databases.yaml create mode 100644 playbooks.templates/pg_users.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b4f614 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/ +.stdusr diff --git a/docu/70_postgresql.md b/docu/70_postgresql.md new file mode 100644 index 0000000..af540d6 --- /dev/null +++ b/docu/70_postgresql.md @@ -0,0 +1,49 @@ +# POSTGRESQL + +## Zielsetzung +Hier wird beschrieben, wie die Datenbank- und Rechteverwaltung unter PostGreSQL funktioniert. + +## Eigenheiten von PostGreSQL +### Root-Zugriff (automatisch eingerichter Superuser) +Die Rechteverwaltung findet in der DB postgres statt. + +Man erhält Zugriff auf alles, wenn man mit dem (Linux-)Benutzer "postgres" auf die zugreift: +``` +sudo -u postgres psql postgres +``` + +## Rollen, Gruppen, Benutzer + +- Für die Rechteverwaltung gibt es nur ein Objekt, die Rolle. +- Eine Rolle kann ein Benutzer sein: Dann hat sie normalerweise das Attribut LOGIN, darf sich also anmelden. Eine Rolle mit LOGIN braucht ein Passwort. +- Eine Rolle kann eine Gruppe sein: Dann hat sie normalerweise das Attribut NOLOGIN und kein Passwort. +- Eine Rolle kann mehreren anderen Rollen zugeordent werden (Gruppeneigenschaft), die dann die Rechte dieser Rolle übernehmen + +``` +# Anlegen einer Gruppe admins: +CREATE ROLE admins WITH CREATEDB CREATEROLE NOLOGIN; +# Anlegen eines Benutzers dba: +CREATE ROLE dba LOGIN PASSWORD 'NoOneKnows'; +# Anlegen weiteren Benutzers admbackup: +CREATE ROLE admbackup LOGIN PASSWORD 'ForgetAtOnce'; +# Zuordnen zur Gruppe: +GRANT admins TO dba, admbackup; +``` + +## Datenbanken +- Es gibt keinen globalen Zugriff auf alle Datenbanken (Superuser): Jede berechtigte Rolle muss explizit zugewiesen werden. +- Eine DB braucht einen Besitzer (Rolle) + +Konvention: +- Jede Datenbank hat eine gleichnamige Gruppe (Rolle), die Besitzer der DB ist +- Über Gruppenzugehörigkeit wird der Zugriff auf andere Benutzer gewährt + +### Anlegen der Datenbank mydb +``` +# Anlegen der Rolle +CREATE ROLE mydb WITH CREATEDB CREATEROLE NOLOGIN; +# Anlegen der DB: +CREATE DATABASE mydb OWNER = mydb; +# Zugriff von Benutzer Jonny auf mydb: +GRANT mydb TO jonny; +``` \ No newline at end of file diff --git a/docu/de/10_einrichten_ansible_auf_workstation.md b/docu/de/10_einrichten_ansible_auf_workstation.md index 2ea8f11..b96c14d 100644 --- a/docu/de/10_einrichten_ansible_auf_workstation.md +++ b/docu/de/10_einrichten_ansible_auf_workstation.md @@ -5,7 +5,7 @@ Diese Beschreibung bezieht sich auf eine Linuxumgebung eines Debian-Systems. ## Paketinstallation ``` -apt install ansible openssh +apt install ansible openssh-server ``` ## Installation Entwicklungsumgebung Es ist sinnvoll, die Entwicklungsumgebung "Microsoft Visual Code" zu verwenden. @@ -27,6 +27,15 @@ Es wird ein Passwort abgefragt, mit dem dann das Zertifikat geschützt ist. '''Wichtig''': Unbedingt ein Passwort vergeben, da der Zugriff auf den entfernten Server mit Root-Rechten erfolgt, also wirklich alles offenlegt. +### Zugriff auf localhost per ssh ermöglichen +Um die Konfiguration zu ändern muss ssh auf die lokale Workstation per ssh zugreifen können: +``` +DIR=/home/ansadm/.ssh +cat $DIR/id_rsa.pub >>$DIR/authorized_keys +chmod 600 $DIR/authorized_keys +chown ansadm $DIR/authorized_keys +``` + ## Verwendung von ssh-agent Damit das Passwort des Zertifikats nur einmal pro Session eingeben werden muss, kann das Programm ssh-agent verwendet werden. Dieses wird normalerweise automatisch gestartet. @@ -59,5 +68,3 @@ Für ansadm muss "sudo" erlaubt sein: In die Datei /etc/sudoers nach "root" am Z ``` ansadm: ALL=NOPASSWD: ALL ``` - - diff --git a/docu/de/50_neues_ansknife_projekt.md b/docu/de/50_neues_ansknife_projekt.md index fb1a900..7ea43ee 100644 --- a/docu/de/50_neues_ansknife_projekt.md +++ b/docu/de/50_neues_ansknife_projekt.md @@ -18,10 +18,10 @@ Dieses Projekt muss '''immer''' als Nachbarverzeichnis zu $BASE/ansknife sein, w ``` BASE=/home/ws/ansible cd $BASE/ansknife -ansible-playbook playbook/create_project \ +ansible-playbook playbooks/create_project.yaml \ -e project=rocket \ -e postfix_mode=send_only \ - -e ansible_base=$BASE + -e base_ansible=$BASE ``` Hier wird die einfachste Variante der postfix-Installation gewählt. Weitere Varianten siehe 60_postfix_varianten.md @@ -46,9 +46,9 @@ Es müssen alle Dateien angeschaut werden und projektspezifische Anpassungen vor Unbedingt überprüfen/anpassen: - remote_www_directory: "/home/www" - Das ist das Verzeichnis, das dann mit /srv/www erreicht wird. -- postfix_host: "hero.infeos.it" +- postfix_host: "mail.example.com" - Das muss eine gültige DNS-Adresse sein -- postfix_domain: "infeos.it" +- postfix_domain: "example.com" - postfix_receipient_email: "mail.rocket@example.com" - Das wird als Absenderadresse für Mails von postfix benutzt, z.B. für "Post kann nicht zugestellt werden". webmaster_email: "web.hero@hamatoma.de" diff --git a/docu/60_neue_webapplikation.md b/docu/de/60_neue_webapplikation.md similarity index 79% rename from docu/60_neue_webapplikation.md rename to docu/de/60_neue_webapplikation.md index 912b973..e48f344 100644 --- a/docu/60_neue_webapplikation.md +++ b/docu/de/60_neue_webapplikation.md @@ -29,7 +29,7 @@ ansible-playbook playbooks/nginx_create_site.yaml -e domain=$DOMAIN Jetzt muss die NGINX-Datei (/etc/nginx/sites-available/huber.de) angepasst werden und unter templates.local/nginx/sites abgelegt werden. '''Wichtig:''' Das Zertifikat in der Konfiguration muss das SSL-Zertifikat sein, nicht das Letsencrypt-Zertifikat, -da dieses noch existiert: +da dieses noch nicht existiert: ``` ... #ssl_certificate /etc/letsencrypt/live/huber.de/fullchain.pem; @@ -41,10 +41,21 @@ da dieses noch existiert: Die NGINX-Konfiguration aktivieren: ``` ansible-playbook playbooks/i_21_nginx_sites.yaml +# Jetzt kann das Letsencrypt-Zertifikat erstellt werden: +ansible-playbook playbooks/lets_create.yaml -e domain=huber.de ``` -Jetzt kann das Letsencrypt-Zertifikat erstellt werden: +Jetzt auf das Letsencrypt-Zertifikat in templates.local/nginx/sites/huber.de umstellen: ``` -ansible-playbook playbooks/lets_create.yaml -e domain=huber.de + ... + ssl_certificate /etc/letsencrypt/live/huber.de/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/huber.de/privkey.pem; + #ssl_certificate /etc/ssl/certs/huber.de.pem; + #ssl_certificate_key /etc/ssl/private/huber.de.key; + ... +``` +und aktivieren: +``` +ansible-playbook playbooks/i_21_nginx_sites.yaml ``` ### Fehlersuche @@ -56,5 +67,5 @@ Als Antwort muss "Hi 2!" erscheinen. Auf dem Server: ``` -certbot certonly --dry -a webroot --webroot-path=/srv/www/letsencrypt -d $DOMAIN --email web.hero@hamatoma.de +certbot certonly --dry -a webroot --webroot-path=/srv/www/letsencrypt -d $DOMAIN ``` \ No newline at end of file diff --git a/playbooks.templates/i_10_basic.yaml b/playbooks.templates/i_10_basic.yaml index f063cf4..c7ef6d9 100644 --- a/playbooks.templates/i_10_basic.yaml +++ b/playbooks.templates/i_10_basic.yaml @@ -21,11 +21,11 @@ - name: Symbolic link to local directory ansible.builtin.file: src=/usr/local/bin/local dest=/usr/local/bin/{{hostname}} state=link - name: Unpack a tar into /usr/local/bin/local - unarchive: src=../resources/needed.tgz dest=/usr/local/bin + ansible.builtin.unarchive: src=../resources/needed.tgz dest=/usr/local/bin - name: Symbolic link to /p ansible.builtin.file: src=/usr/local/bin/std.profile dest=/p state=link - name: Unpack a tar into /usr/share/pyrshell - unarchive: src=../resources/rsh.tgz dest=/usr/share/pyrshell + ansible.builtin.unarchive: src=../resources/rsh.tgz dest=/usr/share/pyrshell - name: Create configuration directory ansible.builtin.file: path=/etc/config state=directory mode=0700 - name: Create webapp.d @@ -34,7 +34,7 @@ ansible.builtin.file: path=/media/{{ item }} state=directory mode=0700 with_items: [src, tmp, trg] - name: install standard packages - apt: + ansible.builtin.apt: name: "{{ item }}" state: present update_cache: true diff --git a/playbooks.templates/i_40_php8.2.yaml b/playbooks.templates/i_40_php8.2.yaml index 5ae3231..e3e23aa 100644 --- a/playbooks.templates/i_40_php8.2.yaml +++ b/playbooks.templates/i_40_php8.2.yaml @@ -44,7 +44,7 @@ "{{ php_ini_settings }}" - name: Ensure PHP-FPM is running ansible.builtin.systemd: - name: php{{php_version}}-fpm + name: php {{php_ version }}-fpm state: started enabled: yes - name: Ensure Redis is running diff --git a/playbooks.templates/i_51_seafile.yaml b/playbooks.templates/i_51_seafile.yaml new file mode 100644 index 0000000..28cf0ab --- /dev/null +++ b/playbooks.templates/i_51_seafile.yaml @@ -0,0 +1,124 @@ +- name: Playbook to install and configure the seafile server + hosts: all + vars_files: + - ../vars/common.yaml + - ../vars/seafile.yaml + # needed facts: seafile_version = "12.0", seafile_user + tasks: + - name: create seafile user + ansible.builtin.user: + name: "{{ seafile_user }}" + state: present + shell: /usr/bin/bash + home: /home/seafile + uid: "{{ seafile_user_id }}" + - name: install packages + ansible.builtin.apt: + name: "{{ item }}" + state: present + with_items: [ memcached, libmemcached-dev, python3-dev, python3-setuptools, python3-pip, python3.11-venv] + - name: create directories for seafile + ansible.builtin.file: + path: "{{ item }}" + state: directory + group: "{{ seafile_user }}" + owner: "{{ seafile_user }}" + mode: "0755" + recurse: yes + # Trick: we use a subdirectory "install" to ensure not destoying possible symbolic links in /opt/seafile ... + with_items: ["/opt/seafile/install", "/opt/seafile-mysql/install", "/opt/seafile-data/install"] + + - name: file check for .env + ansible.builtin.stat: + path: /opt/seafile/.env + register: file_check + - name: download the docker .env file for seafile + ansible.builtin.get_url: + url: "https://manual.seafile.com/{{ seafile_version }}/repo/docker/ce/env" + dest: /opt/seafile/.env + mode: "0644" + when: file_check.stat.exists == false + + - name: file check for seadoc.yml + ansible.builtin.stat: + path: /opt/seafile/seadoc.yml + register: file_check + - name: download seadoc.yml for seafile + ansible.builtin.get_url: + url: "https://manual.seafile.com/{{ seafile_version }}/repo/docker/seadoc.yml" + dest: "/opt/seafile/seadoc.yml" + mode: "0644" + when: not file_check.stat.exists + + - name: file check for cadd.yml + ansible.builtin.stat: + path: /opt/seafile/caddy.yml + register: file_check + - name: download caddy.yml for seafile + ansible.builtin.get_url: + url: "https://manual.seafile.com/{{ seafile_version }}/repo/docker/caddy.yml" + dest: "/opt/seafile/caddy.yml" + mode: "0644" + when: not file_check.stat.exists + + - name: create a virtual enviroment + ansible.builtin.command: + cmd: python3 -m venv venv + chdir: /opt/seafile + args: + creates: venv + register: result + changed_when: result.rc == 0 + - name: install modules in venv + pip: + name: "{{ item }}" + virtualenv: venv + chdir: /opt/seafile + state: present + with_items: + - django==4.2.* + - future==1.0.* + - mysqlclient==2.2.* + - pymysql + - pillow==10.4.* + - pylibmc + - captcha==0.6.* + - markupsafe==2.0.1 + - jinja2 + - sqlalchemy==2.0.* + - psd-tools + - django-pylibmc + - django_simple_captcha==0.6.* + - djangosaml2==1.9.* + - pysaml2==7.3.* + - pycryptodome==3.20.* + - cffi==1.17.0 + - lxml + - python-ldap==3.4.* + - gevent==24.2.* + + - name: file check for seafile_server_current + ansible.builtin.stat: + path: /opt/seafile/seafile_server_current + register: file_check + + - name: download tar file + ansible.builtin.get_url: + url: "{{ seafile_download_tar }}" + dest: /opt/seafile/install/seafile-server.tar.gz + mode: "0644" + when: file_check.stat.exists == false + + - name: Unpack a tar + ansible.builtin.unarchive: + remote_src: install/seafile-server.tar.gz + dest: /opt/seafile + when: file_check.stat.exists == false + + - name: build symbolic link to seafile_server + ansible.builtin.file: + src: "{{ item }}" + dest: /opt/seafile/seafile_server_current + state: link + force: yes + with_fileglob: "seafile-server-*" diff --git a/playbooks.templates/i_70_webapps.yaml b/playbooks.templates/i_70_webapps.yaml deleted file mode 100644 index 1244cb3..0000000 --- a/playbooks.templates/i_70_webapps.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -- name: Install and configure web applications - hosts: all - vars_files: - - ../vars/common.yaml - - ../vars/ssl-certificate.yaml - - ../vars/webapps_vault.yaml - tasks: - - name: Prepare state.infeos.net - ansible.builtin.set_fact: - webapp_name: "state.infeos.net" - domain: "{{ webapp_name }}" - shortname: state_infeos - mysql_vault.yaml: swstateinfeos - db_type: mysql - db_host: localhost - db_user: swstateinfeos - db_password: "{{ vault_db_password }}" - php_version: "8.3" - - debug: - - name: create web application for {{ webapp_name }} - include_tasks: ../tasks/t_webapp_create.yaml diff --git a/playbooks.templates/i_21_nginx_sites.yaml b/playbooks.templates/nginx_sites.yaml similarity index 100% rename from playbooks.templates/i_21_nginx_sites.yaml rename to playbooks.templates/nginx_sites.yaml diff --git a/playbooks.templates/pg_databases.yaml b/playbooks.templates/pg_databases.yaml new file mode 100644 index 0000000..e69de29 diff --git a/playbooks.templates/pg_users.yaml b/playbooks.templates/pg_users.yaml new file mode 100644 index 0000000..d8f1185 --- /dev/null +++ b/playbooks.templates/pg_users.yaml @@ -0,0 +1,71 @@ +--- +# Administration playbook for PostgreSQL users and groups +- name: Playbook to prepare the PosgreSQL users and groups + hosts: all + vars_files: + - ../vars/common.yaml + - ../vars/pg_vault.yaml + - ../vars/pg.yaml + tasks: + - name: Create users with password + community.postgresql.postgresql_user: + name: "{{ item.key }}" + password: "{{ item.value }}" + role_attr_flags: LOGIN + login_host: "{{ pg_meta_host }}" + login_db: "{{ pg_meta_name }}" + state: present + when: item.value != '' + with_dict: "{{ pg_users }}" + + - name: Create users without password + community.postgresql.postgresql_user: + name: "{{ item.key }}" + role_attr_flags: LOGIN + login_host: "{{ pg_meta_host }}" + login_db: "{{ pg_meta_name }}" + state: present + when: item.value == '' + loop: "{{ pg_users | dict2items }}" + + - name: Create groups + community.postgresql.postgresql_user: + name: "{{ item.key }}" + role_attr_flags: NOLOGIN + login_host: "{{ pg_meta_host }}" + login_db: "{{ pg_meta_name }}" + state: present + loop: "{{ pg_groups | dict2items }}" + + - name: Create primary groups of the dbs + community.postgresql.postgresql_user: + name: "{{ item }}" + role_attr_flags: NOLOGIN + login_host: "{{ pg_meta_host }}" + login_db: "{{ pg_meta_name }}" + state: present + with_items: "{{ pg_databases }}" + + - name: Grant all privileges on the databases + community.postgresql.postgresql_privs: + db: "{{ item }}" + login_host: "{{ pg_meta_host }}" + login_db: "{{ pg_meta_name }}" + privs: + - ALL + roles: + - "{{ item }}" + state: present + with_items: "{{ pg_databases }}" + + - name: Add users to groups + community.postgresql.postgresql_membership: + db: postgres # or the name of your DB + login_host: "{{ pg_meta_host }}" + login_db: "{{ pg_meta_name }}" + login_user: "{{ dba_name }}" + login_password: "{{ dba_password }}" + target_role: "{{ item.key }}" + groups: "{{ item.value }}" + state: present" + with_dict: "{{ pg_groups }}" \ No newline at end of file diff --git a/playbooks/create_project.yaml b/playbooks/create_project.yaml index 4f0fa98..6195e5c 100644 --- a/playbooks/create_project.yaml +++ b/playbooks/create_project.yaml @@ -38,6 +38,13 @@ force: yes state: link delegate_to: localhost + - name: build link to the docu/ansknife directory + ansible.builtin.file: + src: "../../ansknife/docu/" + dest: "{{ base_ansible }}/{{ project }}/docu/ansknife" + force: yes + state: link + delegate_to: localhost - name: create the templates base directory ansible.builtin.file: path: "{{ base_ansible }}/{{ project }}/templates.local" diff --git a/templates.vars/common.yaml b/templates.vars/common.yaml index 9079a81..1a8c9c1 100644 --- a/templates.vars/common.yaml +++ b/templates.vars/common.yaml @@ -5,8 +5,9 @@ remote_www_directory: "/home/www" # the system log files have maximal that size systemd_journal_system_max_use: 200M systemd_journal_system_max_file_size: 50M -postfix_host: "example.infeos.it" -postfix_domain: "infeos.it" +postfix_host: "mail.example.com" +postfix_domain: "example.com" postfix_mode: send_only postfix_receipient_email: "mail@example.com" webmaster_email: "web@example.com" +seafile_user_id: 261 diff --git a/templates.vars/mysql.yaml b/templates.vars/mysql.yaml index 00573f9..50c2365 100644 --- a/templates.vars/mysql.yaml +++ b/templates.vars/mysql.yaml @@ -1,8 +1,5 @@ --- -# Creation of the central password file: -# echo "top_secret_password" > resources/.vaults -# Creation of the encrypted vault file: -# ansible-vault encrypt_string --vault-password-file resources/.vault --name 'vault_dba_password' --stdin-name 'vault_dba_password' | tee vars/mysql_vault.yaml -# Find the password file: ANSIBLE_VAULT_PASSWORD_FILE=resources/.vault +# MySQL configuration dba_name: dba -dba_password: "{{ vault_dba_password }}" \ No newline at end of file +dba_password: "{{ vault_dba_password }}" + diff --git a/templates.vars/mysql_vault.yaml b/templates.vars/mysql_vault.yaml index 5241a79..d2d27cc 100644 --- a/templates.vars/mysql_vault.yaml +++ b/templates.vars/mysql_vault.yaml @@ -1 +1,4 @@ -vault_dba_password: TopSecret \ No newline at end of file +--- +# Passwords for the mysql users +vault_dba_password: TopSecret + diff --git a/templates.vars/php.yaml b/templates.vars/php.yaml index a9bcf1d..8b29213 100644 --- a/templates.vars/php.yaml +++ b/templates.vars/php.yaml @@ -5,25 +5,25 @@ # needed variables: php_version php_packages: - - php{{php_version}}-common - - php{{php_version}}-curl - - php{{php_version}}-fpm - - php{{php_version}}-gd - - php{{php_version}}-igbinary - - php{{php_version}}-imagick - - php{{php_version}}-imap - - php{{php_version}}-intl - - php{{php_version}}-mbstring - - php{{php_version}}-memcached - - php{{php_version}}-msgpack - - php{{php_version}}-mysql - - php{{php_version}}-opcache - - php{{php_version}}-phpdbg - - php{{php_version}}-readline - - php{{php_version}}-redis - - php{{php_version}}-xdebug - - php{{php_version}}-xml - - php{{php_version}}-zip + - php{{ php_version }}-common + - php{{ php_version }}-curl + - php{{ php_version }}-fpm + - php{{ php_version }}-gd + - php{{ php_version }}-igbinary + - php{{ php_version }}-imagick + - php{{ php_version }}-imap + - php{{ php_version }}-intl + - php{{ php_version }}-mbstring + - php{{ php_version }}-memcached + - php{{ php_version }}-msgpack + - php{{ php_version }}-mysql + - php{{ php_version }}-opcache + - php{{ php_version }}-phpdbg + - php{{ php_version }}-readline + - php{{ php_version }}-redis + - php{{ php_version }}-xdebug + - php{{ php_version }}-xml + - php{{ php_version }}-zip php_additional_packages: - redis-server - imagemagick diff --git a/templates.vars/webapps.yaml b/templates.vars/webapps.yaml index 4825c48..c8656c3 100644 --- a/templates.vars/webapps.yaml +++ b/templates.vars/webapps.yaml @@ -1,6 +1,9 @@ +--- +# Configuration data of the web applications webapps_list: - dummy db_name: dbdummy5 db_user: dummy5 db_password: NeverKnown5 directory: /srv/www/myapp5.example.com + -- 2.39.5