Update to 2022-03-07 14:00

This commit is contained in:
Daniel Berteaud
2022-03-07 14:00:06 +01:00
parent c55f851cbd
commit 8b7e505180
58 changed files with 1119 additions and 89 deletions

View File

@@ -0,0 +1,14 @@
#!/bin/bash -e
cd /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}
# Remove old archives
find archives/ -type f -mtime +2 -exec rm -f "{}" \;
# Create the new daily archive, with a dump of the DB and the web, data and logs dir
TS=$(date +%Y-%m-%d_%Hh%M)
mysqldump --add-drop-table --single-transaction \
--host={{ (wh_default_app | combine(item.1)).database.server | default(mysql_server) }} \
--user={{ item.0.name[0:7] }}_{{ item.1.name[0:7] }} \
--password="{{ (wh_default_app | combine(item.1)).database.pass | default((wh_pass_seed | password_hash('sha256', 65534 | random(seed=item.0.name + item.1.name) | string))[9:27] ) }}" \
{{ item.0.name[0:7] }}_{{ item.1.name[0:7] }} | \
zstd -c > archives/$TS.sql.zst
ZSTD_CLEVEL=15 ZSTD_NBTHREADS=0 nice -n 9 tar cf archives/$TS.tar.zst --use-compress-program=zstd data web logs

View File

@@ -0,0 +1,5 @@
Type: {{ (wh_default_app | combine(item.1)).database.engine | default('mysql') }}
Server: {{ (wh_default_app | combine(item.1)).database.server | default(mysql_server) }}
Database: {{ item.0.name[0:7] }}_{{ item.1.name[0:7] }}
User: {{ item.0.name[0:7] }}_{{ item.1.name[0:7] }}
Password: {{ (wh_default_app | combine(item.1)).database.pass | default((wh_pass_seed | password_hash('sha256', 65534 | random(seed=item.0.name + item.1.name) | string))[9:27] ) }}

View File

@@ -0,0 +1,44 @@
# {{ ansible_managed }}
{% for client in wh_clients %}
{% for app in client.apps | default([]) %}
{% set app = wh_default_app | combine(app, recursive=True) %}
{% if app.backend | default(client.backend) | default(wh_defaults.backend) == inventory_hostname %}
################################################
## vhost for {{ client.name }}-{{ app.name }}
################################################
<VirtualHost *:80>
ServerName {{ app.vhost | default(client.name + '-' + app.name + '.wh.fws.fr') }}
{% if app.aliases | length > 0 %}
ServerAlias {{ app.aliases | join(' ') }}
{% endif %}
ServerAdmin webmaster@fws.fr
DocumentRoot /opt/wh/{{ client.name }}/apps/{{ app.name }}/web
Alias /_deferror/ "/usr/share/httpd/error/"
Include ansible_conf.d/common_env.inc
ProxyTimeout {{ app.php.max_execution_time }}
</VirtualHost>
################################################
## webroot for {{ client.name }}-{{ app.name }}
################################################
<Directory /opt/wh/{{ client.name }}/apps/{{ app.name }}/web>
AllowOverride All
Options FollowSymLinks
Require all granted
{% if app.php.enabled %}
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/php{{ app.php.version}}-{{ client.name }}-{{ app.name }}.sock|fcgi://localhost"
</FilesMatch>
{% endif %}
<FilesMatch "^(\.ansible_version|\.git.*|(README|LICENSE|AUTHORS|CHANGELOG|CONTRIBUTING|LEGALNOTICE|PRIVACY|SECURITY)(\.md)?|.*\.co?nf|\.htaccess|composer\.(json|lock))">
Require all denied
</FilesMatch>
</Directory>
{% endif %}
{% endfor %}
{% endfor %}

View File

@@ -0,0 +1,21 @@
# {{ ansible_managed }}
{% for client in wh_clients %}
{% for app in client.apps %}
{% set app = wh_default_app | combine(app, recursive=True) %}
{% if app.backend | default(client.backend) | default(wh_defaults.backend) == inventory_hostname %}
/opt/wh/{{ client.name }}/apps/{{ app.name }}/logs/*.log {
rotate 52
weekly
copytruncate
missingok
compress
compressoptions -T0
compresscmd /bin/xz
uncompresscmd /bin/unxz
compressext .xz
su {{ app.run_as | default('wh-' + client.name) }} {{ app.run_as | default('wh-' + client.name) }}
}
{% endif %}
{% endfor %}
{% endfor %}

View File

@@ -0,0 +1,35 @@
#!/bin/sh
# Set correct SELinux label
restorecon -R /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}
# Remove all the ACL so we can start from scratch
setfacl -R --remove-all --remove-default /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}
# Set permissions on the top level client dir. Not recursively !
# Here, the corresponding client only has read permissions (pus the tech team)
chown root:root /opt/wh/{{ item.0.name }}/{,apps}
chmod 750 /opt/wh/{{ item.0.name }}/
chmod 755 /opt/wh/{{ item.0.name }}/apps
setfacl -m u:apache:rX,g:Tech:rX,g:Client_{{ item.0.name }}:rX,u:{{ item.1.run_as | default('wh-' + item.0.name) }}:rX /opt/wh/{{ item.0.name }}/
# Set decent permissions, aka rw for files and rwx for directories. With setgid so the group owner is inherited to new files
find /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/{data,tmp,web} -type f -exec chmod 660 "{}" \;
find /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/{data,tmp,web} -type d -exec chmod 2770 "{}" \;
# Now, grant apache read access (needed for serving static assets), and full rw access to the client group. Set mask to full permission, we don't want to limit ACL. And excplicitely set other perms to 0
# Members of the tech team has write access for install/debug
setfacl -R -m u:apache:rX,d:u:apache:rX,g:Tech:rwX,d:g:Tech:rwX,g:Client_{{ item.0.name }}:rwX,d:g:Client_{{ item.0.name }}:rwX,u:{{ item.1.run_as | default('wh-' + item.0.name) }}:rwX,d:u:{{ item.1.run_as | default('wh-' + item.0.name) }}:rwX,m:rwX,o:- /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}
# The bin folder shouldn't be visible to the client, it only contains admin's scripts
setfacl -R --remove-all --remove-default /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/bin
chown -R root:root /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/bin
chmod 700 /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/bin
chmod 750 /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/bin/*
# Info is readonly for the client (and the tech team)
setfacl -R --remove-all --remove-default /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/info
chown -R root:Client_{{ item.0.name }} /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/info
chmod 750 /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/info
chmod 640 /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/info/*
setfacl -R -m g:Tech:rX,d:g:Tech:rX,m:rwX,o:- /opt/wh/{{ item.0.name }}/apps/{{ item.1.name }}/info

View File

@@ -0,0 +1,61 @@
; {{ ansible_managed }}
{% for client in wh_clients | default([]) %}
{% for app in client.apps | default([]) %}
{% set app = wh_default_app | combine(app, recursive=True) %}
{% if app.php.enabled and app.php.version | string == wh_php_version | string and app.backend | default(client.backend) | default(wh_defaults.backend) == inventory_hostname %}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Begin pool {{ client.name }}-{{ app.name }}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[{{ client.name }}-{{ app.name }}]
listen.owner = root
listen.group = {{ httpd_group }}
listen.mode = 0660
listen = /run/php-fpm/php{{ wh_php_version }}-{{ client.name }}-{{ app.name }}.sock
user = {{ client.run_as | default('wh-' + client.name) }}
group = {{ client.run_as | default('wh-' + client.name) }}
catch_workers_output = yes
pm = dynamic
pm.max_children = 15
pm.start_servers = 3
pm.min_spare_servers = 3
pm.max_spare_servers = 6
pm.max_requests = 5000
request_terminate_timeout = 5m
php_flag[display_errors] = {{ app.php.display_error | ternary('on','off') }}
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /opt/wh/{{ client.name }}/apps/{{ app.name }}/logs/php_error.log
php_admin_value[memory_limit] = {{ app.php.memory_limit }}
php_admin_value[session.save_path] = /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp
php_admin_value[upload_tmp_dir] = /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp
php_admin_value[sys_temp_dir] = /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp
php_admin_value[post_max_size] = {{ app.php.upload_max_filesize }}
php_admin_value[upload_max_filesize] = {{ app.php.upload_max_filesize }}
php_admin_value[disable_functions] = {{ app.php.disabled_functions | difference(app.php.enabled_functions) | join(', ') }}
php_admin_value[open_basedir] = /opt/wh/{{ client.name }}/apps
php_admin_value[max_execution_time] = {{ app.php.max_execution_time }}
php_admin_value[max_input_time] = {{ app.php.max_execution_time }}
php_admin_flag[allow_url_include] = off
php_admin_flag[allow_url_fopen] = {{ app.php.allow_url_fopen | ternary('on','off') }}
php_admin_flag[file_uploads] = {{ app.php.file_uploads | ternary('on','off') }}
php_admin_flag[session.cookie_httponly] = on
{% if app.php.custom_conf is defined %}
{{ app.php.custom_conf }}
{% endif %}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; End pool {{ client.name }}-{{ app.name }}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
{% endif %}
{% endfor %}
{% endfor %}

View File

@@ -0,0 +1,3 @@
#!/bin/bash -e
rm -f /opt/wh/*/apps/*/db_dumps/*.sql.zst

View File

@@ -0,0 +1,17 @@
#!/bin/sh
set -eo pipefail
{% for client in wh_clients %}
{% for app in client.apps | default([]) %}
{% set app = wh_default_app | combine(app, recursive=True) %}
{% if app.backend | default(client.backend) | default(wh_defaults.backend) == inventory_hostname %}
mysqldump --add-drop-table --single-transaction \
--host={{ (wh_default_app | combine(app)).database.server | default(mysql_server) }} \
--user={{ client.name[0:7] }}_{{ app.name[0:7] }} \
--password="{{ (wh_default_app | combine(app)).database.pass | default((wh_pass_seed | password_hash('sha256', 65534 | random(seed=client.name + app.name) | string))[9:27] ) }}" \
{{ client.name[0:7] }}_{{ app.name[0:7] }} | \
zstd -c > /opt/wh/{{ client.name }}/apps/{{ app.name }}/db_dumps/{{ client.name[0:7] }}_{{ app.name[0:7] }}.sql.zst
{% endif %}
{% endfor %}
{% endfor %}

View File

@@ -0,0 +1,17 @@
#!/bin/bash -e
while true; do
{% for client in wh_clients %}
{% for app in client.apps %}
{% if app.backend | default(client.backend) | default(wh_defaults.backend) == inventory_hostname %}
if [ -e /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp/reset -o -e /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp/reset.txt ]; then
echo Reseting permissions for {{ client.name }} - {{ app.name }}
sh /opt/wh/{{ client.name }}/apps/{{ app.name }}/bin/perms.sh
echo Permissions for {{ client.name }} - {{ app.name }} have been reseted
rm -f /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp/reset /opt/wh/{{ client.name }}/apps/{{ app.name }}/tmp/reset.txt
fi
{% endif %}
{% endfor %}
{% endfor %}
sleep 5
done

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Web Hosting ACL monitor daemon
[Service]
Type=simple
ExecStart=/usr/local/bin/wh-acld
PrivateTmp=yes
PrivateDevices=yes
MemoryLimit=100M
Restart=on-failure
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,13 @@
#!/bin/bash -e
{% for client in wh_clients %}
{% for app in client.apps %}
{% set app = wh_default_app | combine(app, recursive=True) %}
{% if app.backend | default(client.backend) | default(wh_defaults.backend) == inventory_hostname %}
echo Starting archiving {{ client.name }} - {{ app.name }}
sh /opt/wh/{{ client.name }}/apps/{{ app.name }}/bin/backup.sh
echo Archive for {{ client.name }} - {{ app.name }} created
{% endif %}
{% endfor %}
{% endfor %}