--- /dev/null
+.vscode/
+.stdusr
+++ /dev/null
-# Neue Webapplikation
-
-## Definition
-Eine Webapplikation besteht aus
-- einer Domäne (der Name der Webapplikation)
-- einem Dateibaum (mit den zur Applikation gehörigen Dateien), normalerweise ein Unterverzeichnis unter /srv/www
-- einer Datenbank mit Benutzer
-- einer NGINX-Konfiguration
-- eines Letsencrypt-Zertifikats (optional)
-
-## Einrichten einer Webapp
-Es soll die Webapp mit der Domäne huber.de, der Datenbank wphuber und dem Benutzer wphuber eingerichtet werden:
-
-```
-DOMAIN=huber.de
-DB_NAME=wphuber
-PW=Geheim
-# Erzeugen DB und User:
-ansible-playbook playbooks/webapp_create \
- -e webapp_name=$DOMAIN \
- -e db_name=$DB_NAME \
- -e db_user=$DB_NAME \
- -e "db_password=$PW"
-# Erzeugen des SSL-Zertifikats (Basis für Letsencrypt)
-ansible-playbook playbooks/ssl_create_certificate.yaml -e domain=$DOMAIN
-# Erzeugen der NGINX-Konfiguration (muss noch angepasst werden)
-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:
- ```
- ...
- #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;
- ...
-```
-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
-```
-
-### Fehlersuche
-Wenn das Zertifikat nicht erstellt werden kann: Prüfen, ob der acme-Verzeichnis erreicht werden kann (auf der Workstation):
-```
-curl http://$DOMAIN/.well-known/acme-challenge/hi2.txt
-```
-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
-```
\ No newline at end of file
--- /dev/null
+# 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
## Paketinstallation
```
-apt install ansible openssh
+apt install ansible openssh-server
```
## Installation Entwicklungsumgebung
Es ist sinnvoll, die Entwicklungsumgebung "Microsoft Visual Code" zu verwenden.
'''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.
```
ansadm: ALL=NOPASSWD: ALL
```
-
-
```
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
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"
--- /dev/null
+# Neue Webapplikation
+
+## Definition
+Eine Webapplikation besteht aus
+- einer Domäne (der Name der Webapplikation)
+- einem Dateibaum (mit den zur Applikation gehörigen Dateien), normalerweise ein Unterverzeichnis unter /srv/www
+- einer Datenbank mit Benutzer
+- einer NGINX-Konfiguration
+- eines Letsencrypt-Zertifikats (optional)
+
+## Einrichten einer Webapp
+Es soll die Webapp mit der Domäne huber.de, der Datenbank wphuber und dem Benutzer wphuber eingerichtet werden:
+
+```
+DOMAIN=huber.de
+DB_NAME=wphuber
+PW=Geheim
+# Erzeugen DB und User:
+ansible-playbook playbooks/webapp_create \
+ -e webapp_name=$DOMAIN \
+ -e db_name=$DB_NAME \
+ -e db_user=$DB_NAME \
+ -e "db_password=$PW"
+# Erzeugen des SSL-Zertifikats (Basis für Letsencrypt)
+ansible-playbook playbooks/ssl_create_certificate.yaml -e domain=$DOMAIN
+# Erzeugen der NGINX-Konfiguration (muss noch angepasst werden)
+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 nicht existiert:
+ ```
+ ...
+ #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;
+ ...
+```
+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 auf das Letsencrypt-Zertifikat in templates.local/nginx/sites/huber.de umstellen:
+```
+ ...
+ 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
+Wenn das Zertifikat nicht erstellt werden kann: Prüfen, ob der acme-Verzeichnis erreicht werden kann (auf der Workstation):
+```
+curl http://$DOMAIN/.well-known/acme-challenge/hi2.txt
+```
+Als Antwort muss "Hi 2!" erscheinen.
+
+Auf dem Server:
+```
+certbot certonly --dry -a webroot --webroot-path=/srv/www/letsencrypt -d $DOMAIN
+```
\ No newline at end of file
- 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
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
+++ /dev/null
----
-# This playbook maintains the NGINX configuration files in /etc/nginx//sites_available
-- name: Installs and configures the sites served by
- hosts: all
- vars_files:
- - ../vars/common.yaml
- - ../vars/webapps.yaml
- tasks:
- - name: Set the NGINX configuration files
- copy:
- src: "../templates.local/nginx/sites/{{ item.webapp_name }}"
- dest: "/etc/nginx/sites-available/"
- owner: root
- group: root
- mode: 0644
- with_list: "{{ webapps_list }}"
- notify:
- - reload nginx
- handlers:
- - name: reload nginx
- service:
- name: nginx
- state: reloaded
- enabled: yes
-
\ No newline at end of file
"{{ 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
--- /dev/null
+- 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-*"
+++ /dev/null
----
-- 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
--- /dev/null
+---
+# This playbook maintains the NGINX configuration files in /etc/nginx//sites_available
+- name: Installs and configures the sites served by
+ hosts: all
+ vars_files:
+ - ../vars/common.yaml
+ - ../vars/webapps.yaml
+ tasks:
+ - name: Set the NGINX configuration files
+ copy:
+ src: "../templates.local/nginx/sites/{{ item.webapp_name }}"
+ dest: "/etc/nginx/sites-available/"
+ owner: root
+ group: root
+ mode: 0644
+ with_list: "{{ webapps_list }}"
+ notify:
+ - reload nginx
+ handlers:
+ - name: reload nginx
+ service:
+ name: nginx
+ state: reloaded
+ enabled: yes
+
\ No newline at end of file
--- /dev/null
+---
+# 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
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"
# 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
---
-# 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 }}"
+
-vault_dba_password: TopSecret
\ No newline at end of file
+---
+# Passwords for the mysql users
+vault_dba_password: TopSecret
+
# 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
+---
+# Configuration data of the web applications
webapps_list:
- dummy
db_name: dbdummy5
db_user: dummy5
db_password: NeverKnown5
directory: /srv/www/myapp5.example.com
+